@tenphi/glaze 2.0.1 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["fmt","configure","resetConfig"],"sources":["../src/okhsl-color-math.ts","../src/config.ts","../src/types.ts","../src/serialize.ts","../src/hc-pair.ts","../src/okhst.ts","../src/color-value.ts","../src/format-guard.ts","../src/contrast-solver.ts","../src/roles.ts","../src/shadow.ts","../src/validation.ts","../src/warnings.ts","../src/resolver.ts","../src/channels.ts","../src/formatters.ts","../src/color-token.ts","../src/theme.ts","../src/palette.ts","../src/glaze.ts"],"sourcesContent":["/**\n * OKHSL color math primitives for the glaze theme generator.\n *\n * Provides bidirectional OKHSL ↔ sRGB conversion, luminance computation\n * for both contrast metrics (WCAG 2 relative luminance and APCA screen\n * luminance `Ys`), and multi-format output (okhsl, rgb, hsl, oklch).\n */\n\ntype Vec3 = [number, number, number];\n\n// ============================================================================\n// Matrices (from texel-color / Björn Ottosson's reference)\n// ============================================================================\n\nconst OKLab_to_LMS_M: Vec3[] = [\n [1.0, 0.3963377773761749, 0.2158037573099136],\n [1.0, -0.1055613458156586, -0.0638541728258133],\n [1.0, -0.0894841775298119, -1.2914855480194092],\n];\n\nconst LMS_to_linear_sRGB_M: Vec3[] = [\n [4.076741636075959, -3.307711539258062, 0.2309699031821041],\n [-1.2684379732850313, 2.6097573492876878, -0.3413193760026569],\n [-0.004196076138675526, -0.703418617935936, 1.7076146940746113],\n];\n\nconst linear_sRGB_to_LMS_M: Vec3[] = [\n [0.4122214708, 0.5363325363, 0.0514459929],\n [0.2119034982, 0.6806995451, 0.1073969566],\n [0.0883024619, 0.2817188376, 0.6299787005],\n];\n\nconst LMS_to_OKLab_M: Vec3[] = [\n [0.2104542553, 0.793617785, -0.0040720468],\n [1.9779984951, -2.428592205, 0.4505937099],\n [0.0259040371, 0.7827717662, -0.808675766],\n];\n\nconst OKLab_to_linear_sRGB_coefficients: [\n [[number, number], number[]],\n [[number, number], number[]],\n [[number, number], number[]],\n] = [\n [\n [-1.8817030993265873, -0.8093650129914302],\n [1.19086277, 1.76576728, 0.59662641, 0.75515197, 0.56771245],\n ],\n [\n [1.8144407988010998, -1.194452667805235],\n [0.73956515, -0.45954404, 0.08285427, 0.1254107, 0.14503204],\n ],\n [\n [0.13110757611180954, 1.813339709266608],\n [1.35733652, -0.00915799, -1.1513021, -0.50559606, 0.00692167],\n ],\n];\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst TAU = 2 * Math.PI;\nconst K1 = 0.206;\nconst K2 = 0.03;\nconst K3 = (1.0 + K1) / (1.0 + K2);\nconst EPSILON = 1e-10;\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nconst constrainAngle = (angle: number): number => ((angle % 360) + 360) % 360;\n/**\n * OKHSL toe function: maps OKLab lightness L to perceptual lightness l.\n * Exported for the OKHST tone transfers in `okhst.ts`.\n */\nexport const toe = (x: number): number =>\n 0.5 *\n (K3 * x - K1 + Math.sqrt((K3 * x - K1) * (K3 * x - K1) + 4 * K2 * K3 * x));\n/** Inverse OKHSL toe: maps perceptual lightness l back to OKLab lightness L. */\nexport const toeInv = (x: number): number =>\n (x ** 2 + K1 * x) / (K3 * (x + K2));\nconst dot3 = (a: Vec3, b: Vec3): number =>\n a[0] * b[0] + a[1] * b[1] + a[2] * b[2];\nconst dotXY = (a: [number, number], b: [number, number]): number =>\n a[0] * b[0] + a[1] * b[1];\nconst transform = (input: Vec3, matrix: Vec3[]): Vec3 => [\n dot3(input, matrix[0]),\n dot3(input, matrix[1]),\n dot3(input, matrix[2]),\n];\nconst cubed3 = (lms: Vec3): Vec3 => [lms[0] ** 3, lms[1] ** 3, lms[2] ** 3];\nconst cbrt3 = (lms: Vec3): Vec3 => [\n Math.cbrt(lms[0]),\n Math.cbrt(lms[1]),\n Math.cbrt(lms[2]),\n];\nconst clampVal = (v: number, min: number, max: number): number =>\n Math.max(min, Math.min(max, v));\n\n// ============================================================================\n// Internal OKHSL pipeline\n// ============================================================================\n\nconst OKLabToLinearSRGB = (lab: Vec3): Vec3 => {\n const lms = transform(lab, OKLab_to_LMS_M);\n return transform(cubed3(lms), LMS_to_linear_sRGB_M);\n};\n\nconst computeMaxSaturationOKLC = (a: number, b: number): number => {\n const okCoeff = OKLab_to_linear_sRGB_coefficients;\n const lmsToRgb = LMS_to_linear_sRGB_M;\n const tmp2: [number, number] = [a, b];\n const tmp3: Vec3 = [0, a, b];\n\n let chnlCoeff: number[];\n let chnlLMS: Vec3;\n\n if (dotXY(okCoeff[0][0], tmp2) > 1) {\n chnlCoeff = okCoeff[0][1];\n chnlLMS = lmsToRgb[0];\n } else if (dotXY(okCoeff[1][0], tmp2) > 1) {\n chnlCoeff = okCoeff[1][1];\n chnlLMS = lmsToRgb[1];\n } else {\n chnlCoeff = okCoeff[2][1];\n chnlLMS = lmsToRgb[2];\n }\n\n const [k0, k1, k2, k3, k4] = chnlCoeff;\n const [wl, wm, ws] = chnlLMS;\n\n let sat = k0 + k1 * a + k2 * b + k3 * (a * a) + k4 * a * b;\n\n const dotYZ = (mat: Vec3, vec: Vec3): number =>\n mat[1] * vec[1] + mat[2] * vec[2];\n\n const kl = dotYZ(OKLab_to_LMS_M[0], tmp3);\n const km = dotYZ(OKLab_to_LMS_M[1], tmp3);\n const ks = dotYZ(OKLab_to_LMS_M[2], tmp3);\n\n const l_ = 1.0 + sat * kl;\n const m_ = 1.0 + sat * km;\n const s_ = 1.0 + sat * ks;\n\n const l = l_ ** 3;\n const m = m_ ** 3;\n const s = s_ ** 3;\n\n const lds = 3.0 * kl * l_ * l_;\n const mds = 3.0 * km * m_ * m_;\n const sds = 3.0 * ks * s_ * s_;\n\n const lds2 = 6.0 * kl * kl * l_;\n const mds2 = 6.0 * km * km * m_;\n const sds2 = 6.0 * ks * ks * s_;\n\n const f = wl * l + wm * m + ws * s;\n const f1 = wl * lds + wm * mds + ws * sds;\n const f2 = wl * lds2 + wm * mds2 + ws * sds2;\n\n sat = sat - (f * f1) / (f1 * f1 - 0.5 * f * f2);\n\n return sat;\n};\n\nconst findCuspOKLCH = (a: number, b: number): [number, number] => {\n const S_cusp = computeMaxSaturationOKLC(a, b);\n const lab: Vec3 = [1, S_cusp * a, S_cusp * b];\n const rgb_at_max = OKLabToLinearSRGB(lab);\n const L_cusp = Math.cbrt(\n 1 /\n Math.max(\n Math.max(rgb_at_max[0], rgb_at_max[1]),\n Math.max(rgb_at_max[2], 0.0),\n ),\n );\n return [L_cusp, L_cusp * S_cusp];\n};\n\nconst findGamutIntersectionOKLCH = (\n a: number,\n b: number,\n l1: number,\n c1: number,\n l0: number,\n cusp: [number, number],\n): number => {\n const lmsToRgb = LMS_to_linear_sRGB_M;\n const tmp3: Vec3 = [0, a, b];\n const floatMax = Number.MAX_VALUE;\n\n let t: number;\n\n const dotYZ = (mat: Vec3, vec: Vec3): number =>\n mat[1] * vec[1] + mat[2] * vec[2];\n const dotXYZ = (vec: Vec3, x: number, y: number, z: number): number =>\n vec[0] * x + vec[1] * y + vec[2] * z;\n\n if ((l1 - l0) * cusp[1] - (cusp[0] - l0) * c1 <= 0.0) {\n const denom = c1 * cusp[0] + cusp[1] * (l0 - l1);\n t = denom === 0 ? 0 : (cusp[1] * l0) / denom;\n } else {\n const denom = c1 * (cusp[0] - 1.0) + cusp[1] * (l0 - l1);\n t = denom === 0 ? 0 : (cusp[1] * (l0 - 1.0)) / denom;\n\n const dl = l1 - l0;\n const dc = c1;\n const kl = dotYZ(OKLab_to_LMS_M[0], tmp3);\n const km = dotYZ(OKLab_to_LMS_M[1], tmp3);\n const ks = dotYZ(OKLab_to_LMS_M[2], tmp3);\n\n const L = l0 * (1.0 - t) + t * l1;\n const C = t * c1;\n\n const l_ = L + C * kl;\n const m_ = L + C * km;\n const s_ = L + C * ks;\n\n const l = l_ ** 3;\n const m = m_ ** 3;\n const s = s_ ** 3;\n\n const ldt = 3 * (dl + dc * kl) * l_ * l_;\n const mdt = 3 * (dl + dc * km) * m_ * m_;\n const sdt = 3 * (dl + dc * ks) * s_ * s_;\n\n const ldt2 = 6 * (dl + dc * kl) ** 2 * l_;\n const mdt2 = 6 * (dl + dc * km) ** 2 * m_;\n const sdt2 = 6 * (dl + dc * ks) ** 2 * s_;\n\n const r_ = dotXYZ(lmsToRgb[0], l, m, s) - 1;\n const r1 = dotXYZ(lmsToRgb[0], ldt, mdt, sdt);\n const r2 = dotXYZ(lmsToRgb[0], ldt2, mdt2, sdt2);\n const ur = r1 / (r1 * r1 - 0.5 * r_ * r2);\n let tr = -r_ * ur;\n\n const g_ = dotXYZ(lmsToRgb[1], l, m, s) - 1;\n const g1 = dotXYZ(lmsToRgb[1], ldt, mdt, sdt);\n const g2 = dotXYZ(lmsToRgb[1], ldt2, mdt2, sdt2);\n const ug = g1 / (g1 * g1 - 0.5 * g_ * g2);\n let tg = -g_ * ug;\n\n const b_ = dotXYZ(lmsToRgb[2], l, m, s) - 1;\n const b1 = dotXYZ(lmsToRgb[2], ldt, mdt, sdt);\n const b2 = dotXYZ(lmsToRgb[2], ldt2, mdt2, sdt2);\n const ub = b1 / (b1 * b1 - 0.5 * b_ * b2);\n let tb = -b_ * ub;\n\n tr = ur >= 0.0 ? tr : floatMax;\n tg = ug >= 0.0 ? tg : floatMax;\n tb = ub >= 0.0 ? tb : floatMax;\n\n t += Math.min(tr, Math.min(tg, tb));\n }\n\n return t;\n};\n\nconst computeSt = (cusp: [number, number]): [number, number] => [\n cusp[1] / cusp[0],\n cusp[1] / (1 - cusp[0]),\n];\n\nconst computeStMid = (a: number, b: number): [number, number] => [\n 0.11516993 +\n 1.0 /\n (7.4477897 +\n 4.1590124 * b +\n a *\n (-2.19557347 +\n 1.75198401 * b +\n a *\n (-2.13704948 -\n 10.02301043 * b +\n a * (-4.24894561 + 5.38770819 * b + 4.69891013 * a)))),\n 0.11239642 +\n 1.0 /\n (1.6132032 -\n 0.68124379 * b +\n a *\n (0.40370612 +\n 0.90148123 * b +\n a *\n (-0.27087943 +\n 0.6122399 * b +\n a * (0.00299215 - 0.45399568 * b - 0.14661872 * a)))),\n];\n\nconst getCs = (\n L: number,\n a: number,\n b: number,\n cusp: [number, number],\n): [number, number, number] => {\n const cMax = findGamutIntersectionOKLCH(a, b, L, 1, L, cusp);\n const stMax = computeSt(cusp);\n const k = cMax / Math.min(L * stMax[0], (1 - L) * stMax[1]);\n const stMid = computeStMid(a, b);\n let ca = L * stMid[0];\n let cb = (1.0 - L) * stMid[1];\n const cMid =\n 0.9 * k * Math.sqrt(Math.sqrt(1.0 / (1.0 / ca ** 4 + 1.0 / cb ** 4)));\n ca = L * 0.4;\n cb = (1.0 - L) * 0.8;\n const c0 = Math.sqrt(1.0 / (1.0 / ca ** 2 + 1.0 / cb ** 2));\n return [c0, cMid, cMax];\n};\n\nconst CYAN_A = Math.cos((199.8 * Math.PI) / 180);\nconst CYAN_B = Math.sin((199.8 * Math.PI) / 180);\nconst BLUE_A = Math.cos((267.4 * Math.PI) / 180);\nconst BLUE_B = Math.sin((267.4 * Math.PI) / 180);\n\nlet cyanCusp: [number, number] | undefined;\nlet blueCusp: [number, number] | undefined;\n\n/**\n * Computes the maximum safe OKLCH chroma that fits inside the sRGB gamut\n * for all possible hues at a given OKLab lightness `L`.\n */\nexport function computeSafeChromaOKLCH(L: number): number {\n if (!cyanCusp) cyanCusp = findCuspOKLCH(CYAN_A, CYAN_B);\n if (!blueCusp) blueCusp = findCuspOKLCH(BLUE_A, BLUE_B);\n\n const c1 = findGamutIntersectionOKLCH(CYAN_A, CYAN_B, L, 1, L, cyanCusp);\n const c2 = findGamutIntersectionOKLCH(BLUE_A, BLUE_B, L, 1, L, blueCusp);\n return Math.min(c1, c2);\n}\n\n// ============================================================================\n// Public API\n// ============================================================================\n\n/** Per-hue cusp-lightness cache. The cusp is mode-independent, so keying on\n * a rounded hue is safe and keeps the cache small. */\nconst cuspLightnessCache = new Map<number, number>();\n\n/**\n * OKHSL lightness of the gamut cusp for a hue — the lightness where the\n * realizable chroma peaks. Reuses the same `find_cusp` OKHSL already runs for\n * its `s` normalization (no new color math); the OKLab cusp lightness is run\n * through the OKHSL `toe` and clamped to `[0.001, 0.999]` so divisions that\n * key off it stay safe. Cached per (rounded) hue.\n *\n * @param h Hue, 0–360.\n */\nexport function cuspLightness(h: number): number {\n const key = Math.round(constrainAngle(h) * 100) / 100;\n const cached = cuspLightnessCache.get(key);\n if (cached !== undefined) return cached;\n\n const hNorm = key / 360.0;\n const cusp = findCuspOKLCH(Math.cos(TAU * hNorm), Math.sin(TAU * hNorm));\n const lc = clampVal(toe(cusp[0]), 0.001, 0.999);\n cuspLightnessCache.set(key, lc);\n return lc;\n}\n\n/**\n * Convert OKHSL (h: 0–360, s: 0–1, l: 0–1) to OKLab [L, a, b].\n */\nexport function okhslToOklab(\n h: number,\n s: number,\n l: number,\n pastel = false,\n): [number, number, number] {\n const L = toeInv(l);\n let a = 0;\n let b = 0;\n\n const hNorm = constrainAngle(h) / 360.0;\n\n if (L !== 0.0 && L !== 1.0 && s !== 0) {\n const a_ = Math.cos(TAU * hNorm);\n const b_ = Math.sin(TAU * hNorm);\n\n if (pastel) {\n const c = s * computeSafeChromaOKLCH(L);\n a = c * a_;\n b = c * b_;\n } else {\n const cusp = findCuspOKLCH(a_, b_);\n const Cs = getCs(L, a_, b_, cusp);\n const [c0, cMid, cMax] = Cs;\n\n const mid = 0.8;\n const midInv = 1.25;\n let t: number, k0: number, k1: number, k2: number;\n\n if (s < mid) {\n t = midInv * s;\n k0 = 0.0;\n k1 = mid * c0;\n k2 = 1.0 - k1 / cMid;\n } else {\n t = 5 * (s - 0.8);\n k0 = cMid;\n k1 = (0.2 * cMid ** 2 * 1.25 ** 2) / c0;\n k2 = 1.0 - k1 / (cMax - cMid);\n }\n\n const c = k0 + (t * k1) / (1.0 - k2 * t);\n a = c * a_;\n b = c * b_;\n }\n }\n\n return [L, a, b];\n}\n\n/**\n * Convert OKHSL (h: 0–360, s: 0–1, l: 0–1) to linear sRGB.\n * Channels may exceed [0, 1] near gamut boundaries — caller must clamp if needed.\n */\nexport function okhslToLinearSrgb(\n h: number,\n s: number,\n l: number,\n pastel = false,\n): [number, number, number] {\n return OKLabToLinearSRGB(okhslToOklab(h, s, l, pastel));\n}\n\n/**\n * Compute relative luminance Y from linear sRGB channels.\n * Per WCAG 2: Y = 0.2126·R + 0.7152·G + 0.0722·B\n */\nexport function relativeLuminanceFromLinearRgb(\n rgb: [number, number, number],\n): number {\n return 0.2126 * rgb[0] + 0.7152 * rgb[1] + 0.0722 * rgb[2];\n}\n\n/**\n * WCAG 2 contrast ratio from two luminance values.\n */\nexport function contrastRatioFromLuminance(yA: number, yB: number): number {\n const lighter = Math.max(yA, yB);\n const darker = Math.min(yA, yB);\n return (lighter + 0.05) / (darker + 0.05);\n}\n\nexport const sRGBLinearToGamma = (val: number): number => {\n const sign = val < 0 ? -1 : 1;\n const abs = Math.abs(val);\n return abs > 0.0031308\n ? sign * (1.055 * Math.pow(abs, 1 / 2.4) - 0.055)\n : 12.92 * val;\n};\n\nexport const sRGBGammaToLinear = (val: number): number => {\n const sign = val < 0 ? -1 : 1;\n const abs = Math.abs(val);\n return abs <= 0.04045\n ? val / 12.92\n : sign * Math.pow((abs + 0.055) / 1.055, 2.4);\n};\n\n/**\n * Convert OKHSL to gamma-encoded sRGB (clamped to 0–1).\n * h: 0–360, s: 0–1, l: 0–1. Returns [r, g, b] with each channel 0–1.\n */\nexport function okhslToSrgb(\n h: number,\n s: number,\n l: number,\n pastel = false,\n): [number, number, number] {\n const lin = okhslToLinearSrgb(h, s, l, pastel);\n return [\n Math.max(0, Math.min(1, sRGBLinearToGamma(lin[0]))),\n Math.max(0, Math.min(1, sRGBLinearToGamma(lin[1]))),\n Math.max(0, Math.min(1, sRGBLinearToGamma(lin[2]))),\n ];\n}\n\n/**\n * Compute WCAG 2 relative luminance from linear sRGB, matching the browser\n * rendering pipeline: gamma-encode, clamp to sRGB gamut [0,1], then linearize.\n * This avoids over/under-estimating luminance for out-of-gamut OKHSL colors.\n */\nexport function gamutClampedLuminance(\n linearRgb: [number, number, number],\n): number {\n const r = sRGBGammaToLinear(\n Math.max(0, Math.min(1, sRGBLinearToGamma(linearRgb[0]))),\n );\n const g = sRGBGammaToLinear(\n Math.max(0, Math.min(1, sRGBLinearToGamma(linearRgb[1]))),\n );\n const b = sRGBGammaToLinear(\n Math.max(0, Math.min(1, sRGBLinearToGamma(linearRgb[2]))),\n );\n return 0.2126 * r + 0.7152 * g + 0.0722 * b;\n}\n\n/**\n * Compute APCA screen luminance (`Ys`) from linear sRGB.\n *\n * APCA does not use the WCAG piecewise sRGB EOTF; it defines its own\n * luminance as `0.2126·R^2.4 + 0.7152·G^2.4 + 0.0722·B^2.4` over the\n * gamma-encoded (display) channels with a simple 2.4 exponent. The APCA\n * soft-clamp threshold in `apcaContrast` is calibrated against this basis,\n * so the solver must feed it `Ys`, not WCAG relative luminance. Channels\n * are gamut-clamped to [0, 1] first, matching `gamutClampedLuminance`.\n */\nexport function apcaLuminanceFromLinearRgb(\n linearRgb: [number, number, number],\n): number {\n const r = Math.max(0, Math.min(1, sRGBLinearToGamma(linearRgb[0])));\n const g = Math.max(0, Math.min(1, sRGBLinearToGamma(linearRgb[1])));\n const b = Math.max(0, Math.min(1, sRGBLinearToGamma(linearRgb[2])));\n return (\n 0.2126 * Math.pow(r, 2.4) +\n 0.7152 * Math.pow(g, 2.4) +\n 0.0722 * Math.pow(b, 2.4)\n );\n}\n\n// ============================================================================\n// Reverse pipeline: sRGB → OKHSL\n// ============================================================================\n\nconst linearSrgbToOklab = (rgb: Vec3): Vec3 => {\n const lms = transform(rgb, linear_sRGB_to_LMS_M);\n const lms_ = cbrt3(lms);\n return transform(lms_, LMS_to_OKLab_M);\n};\n\n/**\n * Convert OKLab to OKHSL.\n * Input: [L, a, b] where L: 0–1, a/b: roughly -0.5 to 0.5.\n * Returns [h, s, l] where h: 0–360, s: 0–1, l: 0–1.\n */\nexport const oklabToOkhsl = (lab: Vec3, pastel = false): Vec3 => {\n const L = lab[0];\n const a = lab[1];\n const b = lab[2];\n\n const C = Math.sqrt(a * a + b * b);\n\n if (C < EPSILON) {\n return [0, 0, toe(L)];\n }\n\n // Lightness-extreme achromatic guard.\n //\n // At L → 1 (white) and L → 0 (black) the in-gamut chroma collapses to\n // a single point: cMax, cMid, c0 all approach zero. Pure white is the\n // most visible failure case — `linearSrgbToOklab([1, 1, 1])` leaves\n // tiny floating-point residue in the a / b channels (`a ≈ 8e-11`,\n // `b ≈ 3.7e-8` → `C ≈ 3.7e-8`) that's well above `EPSILON` (`1e-10`),\n // so the chroma early-return above doesn't catch it. The chromatic\n // path then runs, the gamut at L ≈ 1 has nowhere to put any chroma,\n // and the saturation formula in `getCs` divides through ~zero values,\n // producing nonsense h/s for what is physically an achromatic color\n // (`#FFFFFF` → `okhsl(89.88 55.83% 100%)` instead of\n // `okhsl(0 0% 100%)`).\n //\n // The threshold (`1e-6`) is much wider than `EPSILON` because the fp\n // wobble in L for pure white lands at `1 - 6.5e-9` — `EPSILON = 1e-10`\n // misses it. `1e-6` is still well below any human-perceivable\n // difference in lightness (JNDs in OKHSL L are several orders of\n // magnitude larger), so we don't falsely flatten any in-gamut color.\n //\n // Treat both extremes as achromatic. The lightness window itself is\n // preserved through `toe(L)`.\n const L_EXTREME_EPSILON = 1e-6;\n if (L >= 1 - L_EXTREME_EPSILON || L <= L_EXTREME_EPSILON) {\n return [0, 0, toe(L)];\n }\n\n const a_ = a / C;\n const b_ = b / C;\n\n let h = Math.atan2(b, a) * (180 / Math.PI);\n h = constrainAngle(h);\n\n let s: number;\n\n if (pastel) {\n s = C / computeSafeChromaOKLCH(L);\n } else {\n const cusp = findCuspOKLCH(a_, b_);\n const Cs = getCs(L, a_, b_, cusp);\n const [c0, cMid, cMax] = Cs;\n\n const mid = 0.8;\n const midInv = 1.25;\n\n if (C < cMid) {\n const k1 = mid * c0;\n const k2 = 1.0 - k1 / cMid;\n const t = C / (k1 + C * k2);\n s = t / midInv;\n } else {\n const k0 = cMid;\n const k1 = (0.2 * cMid ** 2 * 1.25 ** 2) / c0;\n const k2 = 1.0 - k1 / (cMax - cMid);\n const cDiff = C - k0;\n const t = cDiff / (k1 + cDiff * k2);\n s = mid + t / 5;\n }\n }\n\n const l = toe(L);\n\n return [h, clampVal(s, 0, 1), clampVal(l, 0, 1)];\n};\n\n/**\n * Convert gamma-encoded sRGB (0–1 per channel) to OKHSL.\n * Returns [h, s, l] where h: 0–360, s: 0–1, l: 0–1.\n */\nexport function srgbToOkhsl(\n rgb: [number, number, number],\n pastel = false,\n): [number, number, number] {\n const linear: Vec3 = [\n sRGBGammaToLinear(rgb[0]),\n sRGBGammaToLinear(rgb[1]),\n sRGBGammaToLinear(rgb[2]),\n ];\n const oklab = linearSrgbToOklab(linear);\n return oklabToOkhsl(oklab, pastel) as [number, number, number];\n}\n\n/**\n * Convert CSS HSL (sRGB-based) to gamma-encoded sRGB [r, g, b] in 0–1 range.\n * h: 0–360, s: 0–1, l: 0–1.\n *\n * Note: CSS HSL is not the same as OKHSL — it's HSL in the sRGB color space.\n * Use this when parsing `hsl(...)` strings before passing to `srgbToOkhsl`.\n */\nexport function hslToSrgb(\n h: number,\n s: number,\n l: number,\n): [number, number, number] {\n const hh = (((h % 360) + 360) % 360) / 360;\n const ss = clampVal(s, 0, 1);\n const ll = clampVal(l, 0, 1);\n\n if (ss === 0) {\n return [ll, ll, ll];\n }\n\n const q = ll < 0.5 ? ll * (1 + ss) : ll + ss - ll * ss;\n const p = 2 * ll - q;\n\n const hueToChannel = (t: number): number => {\n let tt = t;\n if (tt < 0) tt += 1;\n if (tt > 1) tt -= 1;\n if (tt < 1 / 6) return p + (q - p) * 6 * tt;\n if (tt < 1 / 2) return q;\n if (tt < 2 / 3) return p + (q - p) * (2 / 3 - tt) * 6;\n return p;\n };\n\n return [hueToChannel(hh + 1 / 3), hueToChannel(hh), hueToChannel(hh - 1 / 3)];\n}\n\n/**\n * Parse a hex color string (#rgb or #rrggbb) to sRGB [r, g, b] in 0–1 range.\n * Returns null if the string is not a valid hex color.\n *\n * For 8-digit hex (`#rrggbbaa`) and 4-digit hex (`#rgba`) with alpha,\n * use {@link parseHexAlpha}.\n */\nexport function parseHex(hex: string): [number, number, number] | null {\n const result = parseHexAlpha(hex);\n if (!result || result.alpha !== undefined) return null;\n return result.rgb;\n}\n\n/**\n * Parse a hex color string (#rgb, #rrggbb, #rgba, or #rrggbbaa) to\n * sRGB [r, g, b] in 0–1 range plus an optional alpha (0–1).\n * Returns null if the string is not a valid hex color.\n */\nexport function parseHexAlpha(\n hex: string,\n): { rgb: [number, number, number]; alpha?: number } | null {\n const h = hex.startsWith('#') ? hex.slice(1) : hex;\n\n if (h.length === 3) {\n const r = parseInt(h[0] + h[0], 16);\n const g = parseInt(h[1] + h[1], 16);\n const b = parseInt(h[2] + h[2], 16);\n if (isNaN(r) || isNaN(g) || isNaN(b)) return null;\n return { rgb: [r / 255, g / 255, b / 255] };\n }\n\n if (h.length === 4) {\n const r = parseInt(h[0] + h[0], 16);\n const g = parseInt(h[1] + h[1], 16);\n const b = parseInt(h[2] + h[2], 16);\n const a = parseInt(h[3] + h[3], 16);\n if (isNaN(r) || isNaN(g) || isNaN(b) || isNaN(a)) return null;\n return { rgb: [r / 255, g / 255, b / 255], alpha: a / 255 };\n }\n\n if (h.length === 6) {\n const r = parseInt(h.slice(0, 2), 16);\n const g = parseInt(h.slice(2, 4), 16);\n const b = parseInt(h.slice(4, 6), 16);\n if (isNaN(r) || isNaN(g) || isNaN(b)) return null;\n return { rgb: [r / 255, g / 255, b / 255] };\n }\n\n if (h.length === 8) {\n const r = parseInt(h.slice(0, 2), 16);\n const g = parseInt(h.slice(2, 4), 16);\n const b = parseInt(h.slice(4, 6), 16);\n const a = parseInt(h.slice(6, 8), 16);\n if (isNaN(r) || isNaN(g) || isNaN(b) || isNaN(a)) return null;\n return { rgb: [r / 255, g / 255, b / 255], alpha: a / 255 };\n }\n\n return null;\n}\n\n// ============================================================================\n// Format functions\n// ============================================================================\n\nfunction fmt(value: number, decimals: number): string {\n return parseFloat(value.toFixed(decimals)).toString();\n}\n\n/**\n * Every `format*` writer takes `s` / `l` / `t` on the **0–1 factor scale** —\n * the same scale every producer in the library hands back (`resolve()`,\n * `variantToOkhsl`, `srgbToOkhsl`, `oklabToOkhsl`, `okhslToOklab`,\n * `okhslToSrgb`). The percentages are an output detail: the writers multiply\n * by 100 themselves when the CSS syntax asks for a percentage.\n *\n * Before 2.0 the writers took 0–100 while everything producing those values\n * returned 0–1, so the obvious composition was off by 100x and failed\n * silently — `0.7` is a legal percentage, so the result was a valid CSS string\n * naming a near-black color. A value above 1 can only be that old\n * percentage-scale input, so warn about it loudly rather than emit a wrong\n * color quietly.\n */\n// Keyed by writer name, so the cache is bounded by the five writers below and\n// needs no cap of its own (unlike the per-color contrast warnings).\nconst scaleWarnCache = new Set<string>();\n\nfunction warnPercentScale(fn: string, ...values: number[]): void {\n if (!values.some((v) => v > 1 + 1e-6)) return;\n\n if (!scaleWarnCache.has(fn)) {\n scaleWarnCache.add(fn);\n console.warn(\n `glaze: ${fn}() got a value above 1 — it takes the 0-1 factors every ` +\n `Glaze producer returns (resolve(), variantToOkhsl, srgbToOkhsl), not ` +\n `0-100 percentages. Divide by 100, or drop the \"* 100\" left over from ` +\n `the pre-2.0 signature.`,\n );\n }\n}\n\n/**\n * Format OKHSL values as a CSS `okhsl(H S% L%)` string.\n * h: 0–360, s: 0–1, l: 0–1 (factor scale, as returned by every converter).\n */\nexport function formatOkhsl(\n h: number,\n s: number,\n l: number,\n pastel = false,\n): string {\n warnPercentScale('formatOkhsl', s, l);\n\n let outS = s;\n if (pastel) {\n // If it's a pastel color, we need to find the equivalent normal OKHSL `s`\n // so it renders identically in external parsers that don't know about `pastel`.\n const oklab = okhslToOklab(h, s, l, true);\n const normalOkhsl = oklabToOkhsl(oklab, false);\n outS = normalOkhsl[1];\n }\n return `okhsl(${fmt(h, 2)} ${fmt(outS * 100, 2)}% ${fmt(l * 100, 2)}%)`;\n}\n\n/**\n * Format OKHST values as a CSS `okhst(H S% T%)` string.\n * h: 0–360, s: 0–1, t: 0–1 (factor scale, matching `ResolvedColorVariant`).\n *\n * Pastel recompute matches `formatOkhsl`: convert via OKLab so external\n * parsers that only understand non-pastel OKHST render identically.\n */\nexport function formatOkhst(\n h: number,\n s: number,\n t: number,\n pastel = false,\n): string {\n warnPercentScale('formatOkhst', s, t);\n\n let outS = s;\n if (pastel) {\n const REF_EPS = 0.05;\n const den = Math.log(1 + REF_EPS) - Math.log(REF_EPS);\n const y = Math.exp(t * den + Math.log(REF_EPS)) - REF_EPS;\n const l = toe(Math.cbrt(Math.max(0, y)));\n const oklab = okhslToOklab(h, s, l, true);\n const normalOkhsl = oklabToOkhsl(oklab, false);\n outS = normalOkhsl[1];\n }\n return `okhst(${fmt(h, 2)} ${fmt(outS * 100, 2)}% ${fmt(t * 100, 2)}%)`;\n}\n\n/**\n * Format OKHSL values as a CSS `rgb(R G B)` string.\n * Uses 2 decimal places to avoid 8-bit quantization contrast loss.\n * h: 0–360, s: 0–1, l: 0–1 (factor scale, as returned by every converter).\n */\nexport function formatRgb(\n h: number,\n s: number,\n l: number,\n pastel = false,\n): string {\n warnPercentScale('formatRgb', s, l);\n\n const [r, g, b] = okhslToSrgb(h, s, l, pastel);\n return `rgb(${parseFloat((r * 255).toFixed(2))} ${parseFloat((g * 255).toFixed(2))} ${parseFloat((b * 255).toFixed(2))})`;\n}\n\n/**\n * Format OKHSL values as a CSS `hsl(H S% L%)` string.\n * h: 0–360, s: 0–1, l: 0–1 (factor scale, as returned by every converter).\n */\nexport function formatHsl(\n h: number,\n s: number,\n l: number,\n pastel = false,\n): string {\n warnPercentScale('formatHsl', s, l);\n\n const [r, g, b] = okhslToSrgb(h, s, l, pastel);\n\n const max = Math.max(r, g, b);\n const min = Math.min(r, g, b);\n const delta = max - min;\n\n let hh = 0;\n let ss = 0;\n const ll = (max + min) / 2;\n\n if (delta > 0) {\n ss = ll > 0.5 ? delta / (2 - max - min) : delta / (max + min);\n\n if (max === r) {\n hh = ((g - b) / delta + (g < b ? 6 : 0)) * 60;\n } else if (max === g) {\n hh = ((b - r) / delta + 2) * 60;\n } else {\n hh = ((r - g) / delta + 4) * 60;\n }\n }\n\n return `hsl(${fmt(hh, 2)} ${fmt(ss * 100, 2)}% ${fmt(ll * 100, 2)}%)`;\n}\n\n/**\n * Format OKHSL values as a CSS `oklch(L C H)` string.\n * h: 0–360, s: 0–1, l: 0–1 (factor scale, as returned by every converter).\n */\nexport function formatOklch(\n h: number,\n s: number,\n l: number,\n pastel = false,\n): string {\n warnPercentScale('formatOklch', s, l);\n\n const [L, C, hh] = okhslToOklch(h, s, l, pastel);\n return `oklch(${fmt(L, 4)} ${fmt(C, 4)} ${fmt(hh, 2)})`;\n}\n\n/**\n * Reset the `format*` percentage-scale warning cache. Test-only seam — the\n * warning is deduped per function for the life of the process, which a test\n * asserting on it has to be able to clear.\n */\nexport function resetScaleWarnings(): void {\n scaleWarnCache.clear();\n}\n\n// ============================================================================\n// Structured (non-string) color accessors — used by the DTCG exporter.\n// ============================================================================\n\n/**\n * Convert gamma-encoded sRGB channels (0–1) to a 6-digit lowercase hex\n * string (`#rrggbb`). Channels are clamped to [0,1] and rounded to 8-bit.\n * Alpha is not encoded here — DTCG carries it as a separate `alpha` field.\n */\nexport function srgbToHex(rgb: [number, number, number]): `#${string}` {\n const toByte = (c: number): number =>\n Math.max(0, Math.min(255, Math.round(c * 255)));\n const r = toByte(rgb[0]);\n const g = toByte(rgb[1]);\n const b = toByte(rgb[2]);\n return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`;\n}\n\n/**\n * Convert OKHSL (h: 0–360, s: 0–1, l: 0–1) to OKLCH components `[L, C, H]`.\n * L: 0–1, C: 0–~0.4 (chroma), H: 0–360 (hue). Shared by `formatOklch` and\n * the DTCG `oklch` colorSpace exporter so the two never drift apart.\n */\nexport function okhslToOklch(\n h: number,\n s: number,\n l: number,\n pastel = false,\n): [number, number, number] {\n const [L, a, b] = okhslToOklab(h, s, l, pastel);\n const C = Math.sqrt(a * a + b * b);\n const hh = constrainAngle(Math.atan2(b, a) * (180 / Math.PI));\n return [L, C, hh];\n}\n","/**\n * Glaze global configuration singleton.\n *\n * `configure()` mutates the singleton; every other module reads it via\n * `getConfig()` at call time so changes take effect for subsequent\n * resolves. Per-instance overrides (themes / color tokens) stay sparse —\n * omitted fields fall through to the live global at resolve time.\n * Authoring exports freeze the effective merge at export call time.\n *\n * `pastel` is instance-only (theme / token override or per-color def),\n * never set via `configure()`.\n */\n\nimport type {\n GlazeConfig,\n GlazeConfigOverride,\n GlazeConfigResolved,\n} from './types';\n\n/**\n * Build a fresh defaults object. Called from module init and from\n * `resetConfig()` so the two paths can't drift.\n *\n * `pastel: false` is a fixed instance default — not globally configurable.\n */\nexport function defaultConfig(): GlazeConfigResolved {\n return {\n lightTone: { lo: 10, hi: 100, eps: 0.05 },\n darkTone: { lo: 15, hi: 95, eps: 0.05 },\n darkDesaturation: 0.1,\n states: {\n dark: '@media(prefers-color-scheme: dark)',\n highContrast: '@media(prefers-contrast: more)',\n },\n modes: {\n dark: true,\n highContrast: false,\n },\n autoFlip: true,\n pastel: false,\n inferRole: true,\n contrastLevel: 'auto',\n };\n}\n\n/**\n * Validate an authored `contrastLevel`. Numbers clamp to 0–100 so a slider\n * can't produce an out-of-range level; a non-finite number throws rather than\n * silently reading as `'auto'`, which would turn a `NaN` slider value into an\n * invisible no-op.\n */\nexport function normalizeContrastLevel(\n value: number | 'auto' | undefined,\n): number | 'auto' {\n if (value === undefined || value === 'auto') return 'auto';\n if (typeof value !== 'number' || !Number.isFinite(value)) {\n throw new Error(\n `glaze: contrastLevel must be a finite number 0–100 or 'auto' (got ${String(value)}).`,\n );\n }\n return Math.max(0, Math.min(100, value));\n}\n\nlet globalConfig: GlazeConfigResolved = defaultConfig();\n\n/**\n * Monotonic counter incremented on every `configure()` / `resetConfig()`\n * call. Theme / palette caches read this to invalidate stale resolve\n * results when the config changes between exports.\n */\nlet configVersion = 0;\n\n/** Live reference to the current config. Mutated by `configure()` / `resetConfig()`. */\nexport function getConfig(): GlazeConfigResolved {\n return globalConfig;\n}\n\nexport function getConfigVersion(): number {\n return configVersion;\n}\n\n/**\n * Public-facing snapshot used by `glaze.getConfig()`. Returns a shallow\n * copy so callers can't mutate the live config.\n */\nexport function snapshotConfig(): GlazeConfigResolved {\n return { ...globalConfig };\n}\n\nexport function configure(config: GlazeConfig): void {\n configVersion++;\n globalConfig = {\n lightTone: config.lightTone ?? globalConfig.lightTone,\n darkTone: config.darkTone ?? globalConfig.darkTone,\n darkDesaturation: config.darkDesaturation ?? globalConfig.darkDesaturation,\n states: {\n dark: config.states?.dark ?? globalConfig.states.dark,\n highContrast:\n config.states?.highContrast ?? globalConfig.states.highContrast,\n },\n modes: {\n dark: config.modes?.dark ?? globalConfig.modes.dark,\n highContrast:\n config.modes?.highContrast ?? globalConfig.modes.highContrast,\n },\n shadowTuning: config.shadowTuning ?? globalConfig.shadowTuning,\n autoFlip: config.autoFlip ?? globalConfig.autoFlip,\n // Instance-only; never configurable globally.\n pastel: false,\n inferRole: config.inferRole ?? globalConfig.inferRole,\n contrastLevel: normalizeContrastLevel(\n config.contrastLevel ?? globalConfig.contrastLevel,\n ),\n };\n}\n\nexport function resetConfig(): void {\n configVersion++;\n globalConfig = defaultConfig();\n}\n\n/**\n * Merge a per-instance config override over a base resolved config.\n * Only fields present in `override` are replaced; others fall through\n * from `base`. `false` for tone windows passes through as-is\n * (treated as the full range by `activeWindow()` in okhst.ts).\n *\n * `pastel` is instance-only: `override.pastel ?? false`, never inherited\n * from the global base.\n */\nexport function mergeConfig(\n base: GlazeConfigResolved,\n override?: GlazeConfigOverride,\n): GlazeConfigResolved {\n if (!override) {\n return base.pastel === false ? base : { ...base, pastel: false };\n }\n return {\n lightTone:\n override.lightTone !== undefined ? override.lightTone : base.lightTone,\n darkTone:\n override.darkTone !== undefined ? override.darkTone : base.darkTone,\n darkDesaturation: override.darkDesaturation ?? base.darkDesaturation,\n states: base.states,\n modes: base.modes,\n shadowTuning: override.shadowTuning ?? base.shadowTuning,\n autoFlip: override.autoFlip ?? base.autoFlip,\n pastel: override.pastel ?? false,\n inferRole: override.inferRole ?? base.inferRole,\n contrastLevel: normalizeContrastLevel(\n override.contrastLevel ?? base.contrastLevel,\n ),\n };\n}\n\n/**\n * Freeze `getConfig() ∪ instanceLocal ∪ exportArg` as a plain, resolve-relevant\n * override for authoring export, so restored snapshots pin these fields. Later\n * wins; nested objects (`shadowTuning`) replace wholesale. The final\n * `structuredClone` detaches tone-window / shadow objects that `mergeConfig`\n * may still share with the live global config.\n */\nexport function freezeConfigForExport(\n instanceLocal?: GlazeConfigOverride,\n exportArg?: GlazeConfigOverride,\n): GlazeConfigOverride {\n const effective = mergeConfig(getConfig(), {\n ...instanceLocal,\n ...exportArg,\n });\n const out: GlazeConfigOverride = {\n lightTone: effective.lightTone,\n darkTone: effective.darkTone,\n darkDesaturation: effective.darkDesaturation,\n autoFlip: effective.autoFlip,\n pastel: effective.pastel,\n inferRole: effective.inferRole,\n };\n if (effective.shadowTuning !== undefined) {\n out.shadowTuning = effective.shadowTuning;\n }\n // `contrastLevel` is deliberately NOT taken from the effective merge. A\n // global level is a live user preference (an accessibility slider), not\n // authored theme data — freezing it would pin a transient slider position\n // into the snapshot and make restored themes ignore the slider forever.\n // Only an instance-local or explicitly-passed level is authored intent.\n // Same reasoning excludes `modes` and `states` from the freeze.\n const authoredLevel =\n exportArg?.contrastLevel ?? instanceLocal?.contrastLevel;\n if (authoredLevel !== undefined) {\n out.contrastLevel = normalizeContrastLevel(authoredLevel);\n }\n return structuredClone(out);\n}\n","/**\n * Glaze type definitions.\n */\n\nimport type { ApcaPreset, ContrastPreset } from './contrast-solver';\n\n// ============================================================================\n// Value types\n// ============================================================================\n\n/** A value or [normal, high-contrast] pair. */\nexport type HCPair<T> = T | [T, T];\n\n/** Bare WCAG contrast target: a ratio number or a named preset. */\nexport type MinContrast = number | ContrastPreset;\n\n/**\n * A contrast floor with a pluggable metric.\n *\n * - `number` / `ContrastPreset`: a WCAG ratio (bare form).\n * - `{ wcag }`: WCAG ratio or preset, optionally an HC pair.\n * - `{ apca }`: APCA Lc target (absolute value or preset), optionally an HC pair.\n *\n * The `[normal, highContrast]` pair may live at the outer level\n * (`[4.5, 7]`, `[{ wcag: 4.5 }, { wcag: 7 }]`) or inside the metric\n * (`{ wcag: [4.5, 7] }`, `{ apca: [45, 60] }`, `{ apca: ['content', 'body'] }`).\n */\nexport type ContrastSpec =\n | number\n | ContrastPreset\n | { wcag: HCPair<number | ContrastPreset> }\n | { apca: HCPair<number | ApcaPreset> };\n\n// ============================================================================\n// Color role\n// ============================================================================\n\n/**\n * The semantic role a color plays against its base, used to fix APCA contrast\n * polarity (which side is the foreground vs the background). WCAG is\n * symmetric, so role never changes WCAG results.\n */\nexport type Role = 'text' | 'surface' | 'border';\n\n/**\n * Any string accepted as a `role`. Canonical values plus aliases normalized by\n * `normalizeRole` (see `roles.ts`): `surface` (bg/background/fill/canvas/\n * paper/layer), `text` (fg/foreground/content/ink/label/stroke), `border`\n * (divider/outline/separator/hairline/rule).\n */\nexport type RoleInput =\n | Role\n | 'bg'\n | 'background'\n | 'fill'\n | 'canvas'\n | 'paper'\n | 'layer'\n | 'fg'\n | 'foreground'\n | 'content'\n | 'ink'\n | 'label'\n | 'stroke'\n | 'divider'\n | 'outline'\n | 'separator'\n | 'hairline'\n | 'rule';\n\nexport type AdaptationMode = 'auto' | 'fixed' | 'static';\n\n/** A signed relative offset string, e.g. '+20' or '-15.5'. */\nexport type RelativeValue = `+${number}` | `-${number}`;\n\n/**\n * Force a color to a tone extreme:\n * - `'max'`: the highest tone in the active scheme range/window.\n * - `'min'`: the lowest tone.\n *\n * Under `mode: 'auto'` the extreme inverts in the dark scheme (so `'max'`\n * tracks the inversion and becomes the darkest tone). No `base` required.\n */\nexport type ExtremeValue = 'max' | 'min';\n\n/**\n * A tone value as authored on a color.\n * - Number: absolute tone (0–100).\n * - `'+N'` / `'-N'`: relative to the base's tone (requires `base`).\n * - `'max'` / `'min'`: forced to the scheme's tone extreme (no base needed).\n */\nexport type ToneValue = number | RelativeValue | ExtremeValue;\n\n/** Color format for output. */\nexport type GlazeColorFormat = 'okhsl' | 'okhst' | 'rgb' | 'hsl' | 'oklch';\n\n/**\n * Controls which scheme variants are generated in the export.\n * Light is always included (it's the default).\n */\nexport interface GlazeOutputModes {\n /** Include dark scheme variants. Default: true. */\n dark?: boolean;\n /**\n * Include high-contrast variants (both light-HC and dark-HC). Default: false.\n *\n * Independent of `contrastLevel` — the level positions the normal variants\n * while these stay the true high-contrast resolution, so the two compose. The\n * exception is a global level of 100, where the normal variants already *are*\n * the high-contrast ones: the tier would duplicate them and is dropped.\n * @see GlazeConfig.contrastLevel\n */\n highContrast?: boolean;\n}\n\n// ============================================================================\n// Color definitions\n// ============================================================================\n\n/** Hex color string for DX hints. Runtime validation in `parseHex()`. */\nexport type HexColor = `#${string}`;\n\n/** Direct OKHSL color input. */\nexport interface OkhslColor {\n h: number;\n s: number;\n l: number;\n}\n\n/**\n * Direct OKHST color input — OKHSL with the lightness axis replaced by the\n * contrast-uniform tone axis. `h`: 0–360, `s`: 0–1, `t`: 0–1 (tone).\n */\nexport interface OkhstColor {\n h: number;\n s: number;\n t: number;\n}\n\n/** sRGB components in 0–255 (value-shorthand object form). */\nexport interface RgbColor {\n r: number;\n g: number;\n b: number;\n}\n\n/** OKLCh components matching CSS `oklch(L C H)` (L/C: 0–1, H: degrees). */\nexport interface OklchColor {\n l: number;\n c: number;\n h: number;\n}\n\nexport interface RegularColorDef {\n /**\n * Seed this color from a literal color instead of from the theme.\n *\n * Accepts the same values as `glaze.color()` — hex, `rgb()`, `hsl()`,\n * `okhsl()`, `okhst()`, `oklch()`, or a value object. It supplies three\n * things at once: `hue`, `tone`, and — unlike every other color in a theme —\n * an **absolute saturation** rather than a factor of the seed. That last\n * part is the point: a color can now be more saturated than its theme, so\n * honoring a brand color no longer means re-seeding the whole theme to reach\n * it.\n *\n * The **light, normal-contrast** variant reproduces the value exactly\n * (a local `lightTone: false`, matching the value-shorthand form of\n * `glaze.color()`). Dark and high-contrast variants adapt as usual — they\n * are where readability outranks fidelity, and a color pinned across every\n * scheme would defeat both. A `contrast` floor still applies everywhere and\n * still only moves the color when the authored value misses it.\n *\n * Sibling fields override what the value supplied, so\n * `{ from: '#2F5BFF', hue: 300 }` keeps its saturation and tone but rotates\n * the hue.\n */\n from?: GlazeColorValue;\n /**\n * Tone value (0–100, contrast-uniform — see `docs/okhst.md`).\n * - Number: absolute tone.\n * - String ('+N' / '-N'): relative to base color's tone (requires `base`).\n * - `'max'` / `'min'`: force to the scheme's tone extreme (no base needed).\n *\n * Defaults to the tone of `from` when that is set.\n */\n tone?: HCPair<ToneValue>;\n /**\n * Saturation factor applied to the seed saturation (0–1, default: 1).\n *\n * With `from`, an explicit value here is still a factor of the seed and\n * overrides the absolute saturation the color carried.\n */\n saturation?: number;\n /**\n * Hue override for this color.\n * - Number: absolute hue (0–360).\n * - String ('+N' / '-N'): relative to the theme seed hue.\n */\n hue?: number | RelativeValue;\n /**\n * Dark-scheme hue override. Applies to the `dark` and `darkContrast`\n * variants; falls back to `hue` when omitted.\n * - Number: absolute hue (0–360).\n * - String ('+N' / '-N'): relative to the theme's **dark** seed hue\n * (`GlazeTheme.darkHue`, itself defaulting to the light seed hue).\n *\n * Ignored under `mode: 'static'`, which pins one value across all schemes.\n */\n darkHue?: number | RelativeValue;\n /**\n * Dark-scheme saturation factor (0–1) applied to the dark seed\n * saturation. Applies to the `dark` and `darkContrast` variants; falls\n * back to `saturation` when omitted.\n *\n * When set, the global `darkDesaturation` reduction is **not** applied on\n * top — the resulting saturation is taken literally. Ignored under\n * `mode: 'static'`.\n */\n darkSaturation?: number;\n\n /** Name of another color in the same theme (dependent color). */\n base?: string;\n /**\n * Contrast floor against the base color. A bare number/preset is WCAG;\n * use `{ wcag }` / `{ apca }` to pick the metric. Accepts an HC pair.\n */\n contrast?: HCPair<ContrastSpec>;\n\n /** Adaptation mode. Default: 'auto'. */\n mode?: AdaptationMode;\n\n /**\n * Whether to flip out-of-bounds results to the opposite side instead of\n * clamping to the extreme. Affects both:\n * - relative `tone`: when `base ± delta` exceeds `[0, 100]`, mirror the\n * delta to the other side of the base. If the mirrored target is also\n * out of range, keep the original delta and clamp on the authored side.\n * - `contrast`: when the requested direction can't meet the floor, try the\n * opposite side (same as the global `autoFlip`).\n *\n * Defaults to the global `autoFlip` config (default `true`). Set `false`\n * to clamp instead.\n */\n autoFlip?: boolean;\n\n /**\n * Fixed opacity (0–1).\n * Output includes alpha in the CSS value.\n * Does not affect contrast resolution — a semi-transparent color\n * has no fixed perceived tone, so `contrast` and `opacity`\n * should not be combined (a console.warn is emitted).\n */\n opacity?: number;\n\n /**\n * Per-color override for the hue-independent \"safe\" chroma limit used in\n * OKHSL↔sRGB conversions (luminance, contrast solving, output formatting).\n * Falls through to the per-theme / per-token `pastel` override when omitted.\n * @see GlazeConfigOverride.pastel\n */\n pastel?: boolean;\n\n /**\n * Semantic role against `base`: how this color is used. Fixes APCA contrast\n * polarity (the argument order in `apcaContrast`). WCAG is symmetric so it\n * never affects WCAG results.\n *\n * Resolution: explicit `role` wins; else inferred from the color name when\n * `inferRole` is enabled (default); else the opposite of the base's role;\n * else defaults to `'text'` (foreground).\n */\n role?: RoleInput;\n\n /**\n * Whether this color is inherited by child themes created via `extend()`.\n * Default: true. Set to false to make this color local to the current theme.\n */\n inherit?: boolean;\n}\n\n/** Shadow tuning knobs. All values use the 0–1 scale (OKHSL). */\nexport interface ShadowTuning {\n /** Fraction of fg saturation kept in pigment (0-1). Default: 0.18. */\n saturationFactor?: number;\n /** Upper clamp on pigment saturation (0-1). Default: 0.25. */\n maxSaturation?: number;\n /** Multiplier for bg lightness → pigment lightness. Default: 0.25. */\n lightnessFactor?: number;\n /** [min, max] clamp for pigment lightness (0-1). Default: [0.05, 0.20]. */\n lightnessBounds?: [number, number];\n /**\n * Target minimum gap between pigment lightness and bg lightness (0-1).\n * Default: 0.05.\n */\n minGapTarget?: number;\n /** Max alpha (0-1). Reached at intensity=100 with max contrast. Default: 1.0. */\n alphaMax?: number;\n /**\n * Blend weight (0-1) pulling pigment hue toward bg hue.\n * 0 = pure fg hue, 1 = pure bg hue. Default: 0.2.\n */\n bgHueBlend?: number;\n}\n\nexport interface ShadowColorDef {\n type: 'shadow';\n /**\n * Background color name — the surface the shadow sits on.\n * Must reference a non-shadow color in the same theme.\n */\n bg: string;\n /**\n * Foreground color name for tinting and intensity modulation.\n * Must reference a non-shadow color in the same theme.\n * Omit for achromatic shadow at full user-specified intensity.\n */\n fg?: string;\n /**\n * Shadow intensity, 0-100.\n * Supports [normal, highContrast] pair.\n */\n intensity: HCPair<number>;\n /** Override default tuning. Merged field-by-field with global `shadowTuning`. */\n tuning?: ShadowTuning;\n\n /**\n * Per-color override for the hue-independent \"safe\" chroma limit used in\n * OKHSL↔sRGB conversions (luminance, contrast solving, output formatting).\n * Falls through to the per-theme / per-token `pastel` override when omitted.\n * @see GlazeConfigOverride.pastel\n */\n pastel?: boolean;\n\n /**\n * Whether this color is inherited by child themes created via `extend()`.\n * Default: true. Set to false to make this color local to the current theme.\n */\n inherit?: boolean;\n}\n\nexport interface MixColorDef {\n type: 'mix';\n /** Background/base color name — the \"from\" color. */\n base: string;\n /** Target color name — the \"to\" color to mix toward. */\n target: string;\n /**\n * Mix ratio 0–100 (0 = pure base, 100 = pure target).\n * In 'transparent' blend mode, this controls the opacity of the target.\n * Supports [normal, highContrast] pair.\n */\n value: HCPair<number>;\n /**\n * Blending mode. Default: 'opaque'.\n * - 'opaque': produces a solid color by interpolating base and target.\n * - 'transparent': produces the target color with alpha = value/100.\n */\n blend?: 'opaque' | 'transparent';\n /**\n * Interpolation color space for opaque blending. Default: 'okhsl'.\n * - 'okhsl': perceptually uniform, consistent with Glaze's internal model.\n * - 'srgb': linear sRGB interpolation, matches browser compositing.\n *\n * Ignored for 'transparent' blend (always composites in linear sRGB).\n */\n space?: 'okhsl' | 'srgb';\n /**\n * Minimum contrast between the base and the resulting color.\n * In 'opaque' mode, adjusts the mix ratio to meet contrast.\n * In 'transparent' mode, adjusts opacity to meet contrast against the composite.\n * A bare number/preset is WCAG; use `{ wcag }` / `{ apca }` to pick the\n * metric. Supports [normal, highContrast] pair.\n */\n contrast?: HCPair<ContrastSpec>;\n\n /**\n * Per-color override for the hue-independent \"safe\" chroma limit used in\n * OKHSL↔sRGB conversions (luminance, contrast solving, output formatting).\n * Falls through to the per-theme / per-token `pastel` override when omitted.\n * @see GlazeConfigOverride.pastel\n */\n pastel?: boolean;\n\n /**\n * Semantic role of the mixed result against `base`. Same semantics as\n * `RegularColorDef.role` (fixes APCA polarity). Resolution and defaults\n * are identical.\n */\n role?: RoleInput;\n\n /**\n * Whether this color is inherited by child themes created via `extend()`.\n * Default: true. Set to false to make this color local to the current theme.\n */\n inherit?: boolean;\n}\n\nexport type ColorDef = RegularColorDef | ShadowColorDef | MixColorDef;\n\nexport type ColorMap = Record<string, ColorDef>;\n\n// ============================================================================\n// Resolved internal types\n// ============================================================================\n\n/**\n * Resolved color for a single scheme variant.\n *\n * Stored in OKHST: `h` / `s` are OKHSL hue/saturation, `t` is the canonical\n * contrast-uniform tone (0–1, reference eps). Convert to OKHSL lightness via\n * `variantToOkhsl` at the rendering / luminance edges.\n */\nexport interface ResolvedColorVariant {\n /** OKHSL hue (0–360). */\n h: number;\n /** OKHSL saturation (0–1). */\n s: number;\n /** Canonical tone (0–1, reference eps). */\n t: number;\n /** Opacity (0–1). Default: 1. */\n alpha: number;\n /**\n * Effective `pastel` flag used while resolving this variant (author def or\n * config fallback). Carried on the variant so output formatting matches the\n * gamut mapping applied during resolution.\n */\n pastel?: boolean;\n}\n\n/** Fully resolved color across all scheme variants. */\nexport interface ResolvedColor {\n name: string;\n light: ResolvedColorVariant;\n dark: ResolvedColorVariant;\n lightContrast: ResolvedColorVariant;\n darkContrast: ResolvedColorVariant;\n /** Adaptation mode. Present only for regular colors, omitted for shadows. */\n mode?: AdaptationMode;\n}\n\n// ============================================================================\n// Configuration\n// ============================================================================\n\n/**\n * A scheme tone window.\n * - `[lo, hi]`: OKHSL-lightness endpoints (0–100) the authored tone is\n * remapped into, using the reference eps `0.05`. The common form.\n * - `{ lo, hi, eps }`: same, with an explicit render curvature `eps`\n * (advanced — most palettes never need this).\n * - `false`: disable clamping (full range `[0, 100]` at the reference eps).\n * This removes the *boundaries*, not the tone curve.\n */\nexport type ToneWindow =\n | false\n | [number, number]\n | { lo: number; hi: number; eps: number };\n\nexport interface GlazeConfig {\n /** Light scheme tone window — `[lo, hi]` (default `[10, 100]`), `{ lo, hi, eps }` for advanced eps tuning, or `false` to disable clamping. */\n lightTone?: ToneWindow;\n /** Dark scheme tone window — `[lo, hi]` (default `[15, 95]`), `{ lo, hi, eps }`, or `false` to disable clamping. */\n darkTone?: ToneWindow;\n /** Saturation reduction factor for dark scheme (0–1). Default: 0.1. */\n darkDesaturation?: number;\n /**\n * State alias names for Tasty token export. Default to media-query states\n * (`'@media(prefers-color-scheme: dark)'` / `'@media(prefers-contrast: more)'`)\n * so tokens react to the OS preference without registering custom states.\n */\n states?: {\n dark?: string;\n highContrast?: string;\n };\n /**\n * Which scheme variants to include in exports. Defaults: `dark: true`,\n * `highContrast: false`.\n */\n modes?: GlazeOutputModes;\n /** Default tuning for all shadow colors. Per-color tuning merges field-by-field. */\n shadowTuning?: ShadowTuning;\n /**\n * Manual contrast level — a 0–100 slider from normal contrast (`0`) to high\n * contrast (`100`), or `'auto'` (the default) to take the authored normal\n * entries as-is.\n *\n * With a number, Glaze resolves the `light` / `dark` variants *at* that level.\n * That is all it does: `lightContrast` / `darkContrast` stay the true\n * high-contrast resolution at every level, and `modes.highContrast` alone\n * decides whether they are emitted. Level `0` therefore reproduces `'auto'`\n * bit for bit. At `100` the normal variants *are* the high-contrast ones, so a\n * separate tier would duplicate them and a global level of 100 drops it.\n *\n * The level interpolates all three things that make high contrast differ:\n * authored `[normal, highContrast]` pairs, the tone-window widening, and\n * the `AA → AAA` / APCA `+15 Lc` escalation. Contrast floors are re-solved\n * at the interpolated target, so every level is a solution rather than an\n * approximation, and a color keeps to one side of its base as the level moves.\n *\n * Pass `'auto'` to leave manual mode; `configure()` never clears a field by\n * omission. See `docs/api.md` for the ramp's edge cases (un-interpolable\n * pairs, side changes) and the export-freeze rule.\n *\n * @default 'auto'\n */\n contrastLevel?: number | 'auto';\n /**\n * Automatically flip tone direction when contrast can't be met.\n *\n * When enabled (default `true`), the solver searches the requested\n * tone direction first. If that direction can't reach the target,\n * it tries the opposite direction and uses it when it passes. If neither\n * side passes, the tone is pinned to the requested-direction\n * extreme and a warning is emitted.\n *\n * Set to `false` for strict \"no flip\" behavior. The opposite\n * direction is never considered: if the requested direction can't\n * meet the target, the tone is pinned to its extreme (never\n * falls back to the originally requested tone).\n */\n autoFlip?: boolean;\n /**\n * If true (default), infer a color's `role` from its name when no explicit\n * `role` is set. Set to `false` to opt out of name-based inference (the\n * base-opposite and default-foreground fallbacks still apply).\n * @default true\n */\n inferRole?: boolean;\n}\n\nexport interface GlazeConfigResolved {\n lightTone: ToneWindow;\n darkTone: ToneWindow;\n darkDesaturation: number;\n states: {\n dark: string;\n highContrast: string;\n };\n modes: Required<GlazeOutputModes>;\n shadowTuning?: ShadowTuning;\n autoFlip: boolean;\n /**\n * Manual contrast level (0–100) for the normal variants, or `'auto'` to take\n * the authored normal entries as-is.\n * @see GlazeConfig.contrastLevel\n */\n contrastLevel: number | 'auto';\n /**\n * Instance-level pastel default (`def.pastel ?? config.pastel`).\n * Not set via `glaze.configure()` — only via per-theme / per-token\n * `GlazeConfigOverride` (default `false`).\n */\n pastel: boolean;\n inferRole: boolean;\n}\n\n/**\n * Per-instance config override for `glaze.color()` and `glaze()` themes.\n * Fields that are set take priority over the live global config. Fields\n * that are omitted fall through to the live global at resolve time\n * (`pastel` is instance-only and defaults to `false` when omitted).\n *\n * `false` for a tone window disables clamping (full range at reference eps).\n */\nexport interface GlazeConfigOverride {\n /** Light scheme tone window, or `false` to disable clamping. */\n lightTone?: ToneWindow;\n /** Dark scheme tone window, or `false` to disable clamping. */\n darkTone?: ToneWindow;\n /** Saturation reduction factor for dark scheme (0–1). */\n darkDesaturation?: number;\n /** Whether to auto-flip tone when contrast can't be met. */\n autoFlip?: boolean;\n /**\n * Manual contrast level (0–100) for this instance, or `'auto'` to opt out of a\n * global level and take the authored normal entries as-is. Either way the\n * instance keeps its high-contrast tier; a per-instance level never changes\n * which modes are emitted.\n *\n * Only an instance-authored level is frozen into `.export()` snapshots — a\n * level inherited from the global config is treated as a live preference and\n * re-read at restore time.\n *\n * @see GlazeConfig.contrastLevel\n */\n contrastLevel?: number | 'auto';\n /**\n * Instance-level pastel default for colors that omit per-color `pastel`.\n * Not available on `glaze.configure()` — set here or per-color.\n * @default false\n */\n pastel?: boolean;\n /**\n * If true, infer a color's `role` from its name when no explicit `role` is\n * set. Falls through to the live global at resolve time when omitted.\n */\n inferRole?: boolean;\n /**\n * Shadow tuning defaults. Only meaningful for themes; harmless on\n * standalone color tokens.\n */\n shadowTuning?: ShadowTuning;\n}\n\n// ============================================================================\n// Serialization\n// ============================================================================\n\n/**\n * Current authoring-export schema version. Bump when the export shape\n * changes in a non-compatible way. Written on every `.export()` snapshot.\n */\nexport const GLAZE_EXPORT_VERSION = 1 as const;\n\n/** Literal type of {@link GLAZE_EXPORT_VERSION}. */\nexport type GlazeExportVersion = typeof GLAZE_EXPORT_VERSION;\n\n/** Discriminator for authoring export snapshots. */\nexport type GlazeExportKind = 'theme' | 'color' | 'palette';\n\n/** Serialized theme configuration (no resolved values). */\nexport interface GlazeThemeExport {\n /** Snapshot kind. Always written by `theme.export()`; optional on legacy hand-written configs. */\n kind?: 'theme';\n /** Schema version. Always written by `theme.export()`; optional on legacy configs. */\n version?: number;\n hue: number;\n saturation: number;\n /** Dark-scheme seed hue (0–360). Omitted when the theme reuses `hue`. */\n darkHue?: number;\n /** Dark-scheme seed saturation (0–100). Omitted when the theme reuses `saturation`. */\n darkSaturation?: number;\n colors: ColorMap;\n /**\n * Effective config freeze from `.export()` —\n * `getConfig() ∪ instance local ∪ exportArg`. May be sparse on legacy\n * snapshots (omitted fields fall through to the live global at restore).\n */\n config?: GlazeConfigOverride;\n}\n\n// ============================================================================\n// Standalone shadow\n// ============================================================================\n\n/** Input for `glaze.shadow()` standalone factory. */\nexport interface GlazeShadowInput {\n /**\n * Background color — accepts any `GlazeColorValue` form: hex\n * (`#rgb` / `#rrggbb` / `#rrggbbaa`), `rgb()` / `hsl()` / `okhsl()`\n * / `oklch()` strings, or literal objects (`{ r, g, b }`, `{ h, s, l }`,\n * `{ l, c, h }`). Alpha components are dropped with a warning.\n */\n bg: GlazeColorValue;\n /**\n * Foreground color for tinting + intensity modulation. Accepts the\n * same forms as `bg`.\n */\n fg?: GlazeColorValue;\n /** Intensity 0-100. */\n intensity: number;\n tuning?: ShadowTuning;\n}\n\n// ============================================================================\n// Standalone color token\n// ============================================================================\n\n/** Input for the structured `glaze.color()` overload. */\nexport interface GlazeColorInput {\n hue: number;\n saturation: number;\n tone: HCPair<number | ExtremeValue>;\n saturationFactor?: number;\n /**\n * Dark-scheme hue. Number is absolute (0–360); `'+N'`/`'-N'` is relative\n * to the dark seed hue, which defaults to `hue`. Falls back to `hue`.\n */\n darkHue?: number | RelativeValue;\n /** Dark-scheme seed saturation (0–100). Defaults to `saturation`. */\n darkSaturation?: number;\n /** Dark-scheme multiplier on the dark seed (0–1). Defaults to `saturationFactor`. */\n darkSaturationFactor?: number;\n mode?: AdaptationMode;\n /** Flip out-of-bounds results instead of clamping. Default: global `autoFlip`. */\n autoFlip?: boolean;\n /**\n * Fixed opacity (0–1). Output includes alpha in the CSS value.\n * Combining with `contrast` is not recommended (perceived tone\n * becomes unpredictable) — a `console.warn` is emitted in that case.\n */\n opacity?: number;\n /**\n * Optional dependency on another color. Same semantics as\n * `GlazeColorOverrides.base` — `contrast` and relative `tone`\n * anchor to the base per scheme.\n */\n base?: GlazeColorToken | GlazeColorValue;\n /**\n * Contrast floor against `base`. Requires `base` to be set. A bare\n * number/preset is WCAG; use `{ wcag }` / `{ apca }` to pick the metric.\n */\n contrast?: HCPair<ContrastSpec>;\n /**\n * Optional human-readable name for the token. Used in error and\n * warning messages (otherwise an internal name like `\"value\"` is\n * used). Does not affect output keys.\n */\n name?: string;\n\n /**\n * Per-color override for the hue-independent \"safe\" chroma limit used in\n * OKHSL↔sRGB conversions (luminance, contrast solving, output formatting).\n * Falls through to the per-theme / per-token `pastel` override when omitted.\n * @see GlazeConfigOverride.pastel\n */\n pastel?: boolean;\n\n /**\n * Semantic role against `base` / the literal seed: how this token is used.\n * Fixes APCA contrast polarity. Same resolution chain as\n * `RegularColorDef.role` (explicit → name inference → opposite of base →\n * `'text'`). For standalone tokens the name is internal, so set `role`\n * explicitly or rely on the base-opposite / foreground default.\n */\n role?: RoleInput;\n}\n\n/**\n * Any single-color input form accepted by the value-shorthand\n * overload of `glaze.color()`.\n *\n * Strings cover hex (`#rgb` / `#rrggbb` / `#rrggbbaa`, alpha dropped\n * with a warning) and the four CSS color functions Glaze itself emits:\n * `rgb()`, `hsl()`, `okhsl()`, `oklch()` (alpha components also dropped\n * with a warning).\n *\n * Literal object forms:\n * - `{ h, s, l }` — OKHSL (h: 0–360, s/l: 0–1). Passing 0–100 for `s`/`l`\n * throws with a hint to use the structured form.\n * - `{ h, s, t }` — OKHST (h: 0–360, s/t: 0–1). Tone in 0–1.\n * - `{ r, g, b }` — sRGB 0–255.\n * - `{ l, c, h }` — OKLCh (L/C: 0–1, H: degrees), same as `oklch()` strings.\n */\nexport type GlazeColorValue =\n | string\n | OkhslColor\n | OkhstColor\n | RgbColor\n | OklchColor;\n\n/** Color overrides for the `from` and value-shorthand inputs. */\nexport interface GlazeColorOverrides {\n /**\n * Override hue. Number is absolute (0–360); `'+N'`/`'-N'` is relative\n * to the extracted (or overridden) seed hue — same semantics as\n * `RegularColorDef.hue`.\n */\n hue?: number | RelativeValue;\n /** Override seed saturation (0–100). Default: extracted from value. */\n saturation?: number;\n /**\n * Dark-scheme hue. Number is absolute (0–360); `'+N'`/`'-N'` is relative\n * to the dark seed hue, which defaults to the (possibly overridden) seed\n * hue. Falls back to `hue` when omitted.\n */\n darkHue?: number | RelativeValue;\n /**\n * Dark-scheme seed saturation (0–100). Defaults to `saturation`. When set,\n * the global `darkDesaturation` reduction is not applied on top.\n */\n darkSaturation?: number;\n /**\n * Dark-scheme multiplier on the dark seed (0–1). Defaults to\n * `saturationFactor`. When set, the global `darkDesaturation` reduction is\n * not applied on top.\n */\n darkSaturationFactor?: number;\n /**\n * Override tone. Number is absolute (0–100, contrast-uniform); `'+N'`/`'-N'`\n * is relative to the literal seed (the value passed to `glaze.color()`);\n * `'max'` / `'min'` force to the scheme's tone extreme.\n * Supports HCPair for high-contrast.\n */\n tone?: HCPair<ToneValue>;\n /** Saturation multiplier on the seed (0–1). Default: 1. */\n saturationFactor?: number;\n /**\n * Adaptation mode. Defaults to `'auto'` for every input form, so\n * colors automatically adapt between light and dark like an ordinary\n * theme color. Value-shorthand inputs (strings and literal objects)\n * preserve light tone via a local `lightTone: false` default; other\n * omitted config fields fall through to the live global at resolve\n * time. Structured `{ hue, saturation, tone }` form also falls\n * through for both tone windows unless overridden.\n *\n * Pass `'fixed'` explicitly to opt back into the linear, non-\n * inverting mapping; pass `'static'` to pin the same tone\n * across every variant.\n */\n mode?: AdaptationMode;\n\n /**\n * Flip out-of-bounds results (relative `tone` overshoot / unmet\n * `contrast`) to the opposite side instead of clamping. Defaults to\n * the global `autoFlip`.\n */\n autoFlip?: boolean;\n\n /**\n * Contrast floor. By default solved against the literal seed\n * (the value itself); when `base` is set, solved against the base's\n * resolved variant per scheme. Same shape as `RegularColorDef.contrast`\n * (bare number/preset = WCAG; `{ wcag }` / `{ apca }` to pick the metric).\n */\n contrast?: HCPair<ContrastSpec>;\n\n /**\n * Optional dependency on another color. Accepts either a\n * `GlazeColorToken` (returned by another `glaze.color()`) or a raw\n * `GlazeColorValue` (hex / CSS strings / `{ r, g, b }` / `{ h, s, l }` / …),\n * which is automatically wrapped in `glaze.color(value)`.\n *\n * When set:\n * - `contrast` is solved against the base's resolved variant\n * per-scheme (light / dark / lightContrast / darkContrast).\n * - Relative `tone: '+N'` / `'-N'` is anchored to the base's\n * tone per-scheme (matches theme behavior for dependent colors).\n * - Relative `hue: '+N'` / `'-N'` still anchors to the seed (the\n * value passed to `glaze.color()`), not the base.\n * - When the base was created via the structured form (with explicit\n * `hue`/`saturation`/`tone`), it is resolved at full range\n * (`lightTone: false`) for the linking math — ensuring the\n * contrast/tone anchor matches the input tone, not the\n * windowed output. The base's own `.resolve()` output is unaffected.\n *\n * The base token's `.resolve()` is called lazily on first resolve and\n * its result is captured by reference; later mutations to the base's\n * defining call don't apply (matches existing token snapshot semantics).\n */\n base?: GlazeColorToken | GlazeColorValue;\n\n /**\n * Fixed opacity (0–1). Output includes alpha in the CSS value.\n * Combining with `contrast` is not recommended (perceived tone\n * becomes unpredictable) — a `console.warn` is emitted in that case.\n */\n opacity?: number;\n\n /**\n * Optional human-readable name for the token. Used in error and\n * warning messages (otherwise an internal name like `\"value\"` is\n * used). Does not affect output keys.\n */\n name?: string;\n\n /**\n * Per-color override for the hue-independent \"safe\" chroma limit used in\n * OKHSL↔sRGB conversions (luminance, contrast solving, output formatting).\n * Falls through to the per-theme / per-token `pastel` override when omitted.\n * @see GlazeConfigOverride.pastel\n */\n pastel?: boolean;\n\n /**\n * Semantic role against `base` / the literal seed: how this token is used.\n * Fixes APCA contrast polarity. Same resolution chain as\n * `RegularColorDef.role`.\n */\n role?: RoleInput;\n}\n\n/**\n * Object input for `glaze.color()` that carries a raw color value plus\n * optional color overrides in the same object.\n *\n * ```ts\n * glaze.color({ from: '#1a1a2e', base: bg, contrast: 'AA' })\n * glaze.color({ from: { r: 38, g: 252, b: 178 }, tone: '+10' })\n * ```\n */\nexport interface GlazeFromInput extends GlazeColorOverrides {\n /** The source color value. Accepts the same forms as a bare `GlazeColorValue`. */\n from: GlazeColorValue;\n}\n\n/** Options for `GlazeColorToken.css()`. */\nexport interface GlazeColorCssOptions {\n /**\n * Custom property base name (without leading `--`). Required.\n * Becomes the variable identifier in the output, e.g.\n * `name: 'brand'` → `--brand-color: …`.\n */\n name: string;\n /** Output color format. Default: 'oklch'. */\n format?: GlazeColorFormat;\n /**\n * Suffix appended to the name. Default: '-color' (matches\n * `theme.css` default).\n */\n suffix?: string;\n /**\n * Emit hue as a separate custom property, referenced via `var()`.\n * Requires `format: 'oklch'` and a pastel token. oklch + all-pastel only.\n */\n splitHue?: boolean;\n}\n\n/** Return type for `glaze.color()`. */\nexport interface GlazeColorToken {\n /** Resolve the color across all scheme variants. */\n resolve(): ResolvedColor;\n /** Export as a flat token map (no color name key). */\n token(options?: GlazeTokenOptions): Record<string, string>;\n /**\n * Export as a tasty style-to-state binding (no color name key).\n * Uses `#name` keys and state aliases (`''`, `'@media(prefers-color-scheme: dark)'`, etc.).\n * @see https://tasty.style/docs\n */\n tasty(options?: GlazeTokenOptions): Record<string, string>;\n /** Export as a flat JSON map (no color name key). */\n json(options?: GlazeJsonOptions): Record<string, string>;\n /** Export as CSS custom property declarations grouped by scheme variant. */\n css(options: GlazeColorCssOptions): GlazeCssResult;\n /**\n * Export as W3C DTCG color tokens (one per scheme variant, no color name\n * key). Each entry is a full `{ $type: 'color', $value }` token.\n * @see https://www.designtokens.org/\n */\n dtcg(options?: GlazeDtcgOptions): GlazeColorDtcgResult;\n /**\n * Export as a single W3C DTCG Resolver-Module document for this color,\n * keyed by `name` across all scheme variants. `name` is required.\n * @see https://www.designtokens.org/\n */\n dtcgResolver(\n options: GlazeColorDtcgResolverOptions,\n ): GlazeDtcgResolverDocument;\n /**\n * Export as a Tailwind CSS v4 `@theme` block (light baseline) plus dark /\n * high-contrast overrides. Returns a single ready-to-paste CSS string.\n * `name` is required (forms `--color-<name>`).\n * @see https://tailwindcss.com/docs/theme\n */\n tailwind(options: GlazeColorTailwindOptions): string;\n /**\n * Serialize the token as a JSON-safe object. Captures the original\n * input value, overrides, and config so it can be rehydrated via\n * `glaze.colorFrom(...)`. `base` is recursively serialized.\n * Optional `override` is merged over the instance local at export time.\n */\n export(override?: GlazeConfigOverride): GlazeColorTokenExport;\n}\n\n/**\n * JSON-safe serialization of a `glaze.color()` token. Pass to\n * `glaze.colorFrom(...)` to rehydrate.\n */\nexport interface GlazeColorTokenExport {\n /** Snapshot kind. Always written by `token.export()`; optional on legacy snapshots. */\n kind?: 'color';\n /** Schema version. Always written by `token.export()`; optional on legacy snapshots. */\n version?: number;\n /**\n * Discriminator for the source overload that created the token.\n * - `'value'`: created via `glaze.color(value)` or `glaze.color({ from, ...overrides })`.\n * - `'structured'`: created via `glaze.color({ hue, saturation, ... })`.\n */\n form: 'value' | 'structured';\n /** Original input. For `form: 'value'` this is the raw `GlazeColorValue`; for `form: 'structured'` this is the structured input. */\n input: GlazeColorValue | GlazeColorInputExport;\n /**\n * Overrides recorded at creation time. `base` is recursively\n * serialized. Only present for `form: 'value'`.\n */\n overrides?: GlazeColorOverridesExport;\n /**\n * Effective config freeze from `.export()` — `getConfig() ∪ local ∪\n * exportArg` at call time. Used by `glaze.colorFrom()` to pin\n * deterministic behavior across later `configure()` calls.\n */\n config?: GlazeConfigOverride;\n}\n\n/**\n * JSON-safe serialization of a `glaze.palette()` composition.\n * Pass to `glaze.paletteFrom(...)` to rehydrate.\n */\nexport interface GlazePaletteExport {\n /** Snapshot kind. Always written by `palette.export()`. */\n kind?: 'palette';\n /** Schema version. Always written by `palette.export()`. */\n version?: number;\n /** Per-theme authoring snapshots keyed by theme name. */\n themes: Record<string, GlazeThemeExport>;\n /** Primary theme name, if set on the palette. */\n primary?: string;\n}\n\n/**\n * Serializable shape of a structured `glaze.color({...})` input.\n * Differs from `GlazeColorInput` only in that `base` is replaced by an\n * `export` instead of a token reference.\n */\nexport interface GlazeColorInputExport {\n hue: number;\n saturation: number;\n tone: HCPair<number | ExtremeValue>;\n saturationFactor?: number;\n darkHue?: number | RelativeValue;\n darkSaturation?: number;\n darkSaturationFactor?: number;\n mode?: AdaptationMode;\n autoFlip?: boolean;\n opacity?: number;\n base?: GlazeColorTokenExport | GlazeColorValue;\n contrast?: HCPair<ContrastSpec>;\n name?: string;\n pastel?: boolean;\n role?: RoleInput;\n}\n\n/**\n * Serializable shape of `GlazeColorOverrides`. `base` is replaced by\n * its export (or left as a `GlazeColorValue` if it was originally a value).\n */\nexport interface GlazeColorOverridesExport {\n hue?: number | RelativeValue;\n saturation?: number;\n darkHue?: number | RelativeValue;\n darkSaturation?: number;\n darkSaturationFactor?: number;\n tone?: HCPair<ToneValue>;\n saturationFactor?: number;\n mode?: AdaptationMode;\n autoFlip?: boolean;\n contrast?: HCPair<ContrastSpec>;\n base?: GlazeColorTokenExport | GlazeColorValue;\n opacity?: number;\n name?: string;\n pastel?: boolean;\n role?: RoleInput;\n}\n\n// ============================================================================\n// Theme API\n// ============================================================================\n\n/**\n * The hue/saturation seed pair a theme resolves against.\n *\n * `darkHue` / `darkSaturation` are a separate seed for the `dark` and\n * `darkContrast` variants; each falls back to its light counterpart. Setting\n * `darkSaturation` opts the theme out of the global `darkDesaturation`\n * reduction — the authored value is used literally.\n */\nexport interface GlazeThemeSeed {\n /** Light-scheme hue seed (0–360). */\n hue: number;\n /** Light-scheme saturation seed (0–100). */\n saturation: number;\n /** Dark-scheme hue seed (0–360). Defaults to `hue`. */\n darkHue?: number;\n /** Dark-scheme saturation seed (0–100). Defaults to `saturation`. */\n darkSaturation?: number;\n}\n\nexport interface GlazeTheme {\n /** The hue seed (0–360). */\n readonly hue: number;\n /** The saturation seed (0–100). */\n readonly saturation: number;\n /** The dark-scheme hue seed (0–360), or `undefined` when `hue` is reused. */\n readonly darkHue: number | undefined;\n /** The dark-scheme saturation seed (0–100), or `undefined` when `saturation` is reused. */\n readonly darkSaturation: number | undefined;\n /** The effective config for this theme. */\n getConfig(): GlazeConfigResolved;\n\n /** Add/replace colors (additive merge with existing definitions). */\n colors(defs: ColorMap): void;\n\n /** Get a color definition by name. */\n color(name: string): ColorDef | undefined;\n /** Set a single color definition. */\n color(name: string, def: ColorDef): void;\n\n /** Remove one or more color definitions. */\n remove(names: string | string[]): void;\n\n /** Check if a color is defined. */\n has(name: string): boolean;\n\n /** List all defined color names. */\n list(): string[];\n\n /** Clear all color definitions. */\n reset(): void;\n\n /** Export the theme configuration as a JSON-safe object. */\n export(override?: GlazeConfigOverride): GlazeThemeExport;\n\n /** Create a child theme inheriting all color definitions. */\n extend(options: GlazeExtendOptions): GlazeTheme;\n\n /** Resolve all colors and return the result map. */\n resolve(): Map<string, ResolvedColor>;\n\n /**\n * Export as a flat token map grouped by scheme variant.\n *\n * ```ts\n * theme.tokens()\n * // → { light: { surface: 'okhsl(...)' }, dark: { surface: 'okhsl(...)' } }\n * ```\n */\n tokens(options?: GlazeJsonOptions): Record<string, Record<string, string>>;\n\n /**\n * Export as tasty style-to-state bindings.\n * Uses `#name` color token keys and state aliases (`''`, `'@media(prefers-color-scheme: dark)'`, etc.).\n * Spread into component styles or register as a recipe via `configure({ recipes })`.\n * @see https://tasty.style/docs\n */\n tasty(options?: GlazeTokenOptions): Record<string, Record<string, string>>;\n\n /** Export as plain JSON. */\n json(options?: GlazeJsonOptions): Record<string, Record<string, string>>;\n\n /** Export as CSS custom property declarations. */\n css(options?: GlazeCssOptions): GlazeCssResult;\n\n /**\n * Export as W3C Design Tokens Format Module (2025.10) documents, one per\n * scheme variant. Consumable by Figma, Tokens Studio, Style Dictionary,\n * Terrazzo, and any DTCG-compatible tool.\n * @see https://www.designtokens.org/\n */\n dtcg(options?: GlazeDtcgOptions): GlazeDtcgResult;\n\n /**\n * Export as a single W3C DTCG Resolver-Module document describing every\n * scheme variant as one `sets` entry plus a single `scheme` modifier with a\n * context per variant. Consumable by resolver tools such as Dispersa.\n * @see https://www.designtokens.org/\n */\n dtcgResolver(options?: GlazeDtcgResolverOptions): GlazeDtcgResolverDocument;\n\n /**\n * Export as a Tailwind CSS v4 `@theme` block (light baseline) plus dark /\n * high-contrast overrides under configurable selectors. Returns a single\n * ready-to-paste CSS string.\n * @see https://tailwindcss.com/docs/theme\n */\n tailwind(options?: GlazeTailwindOptions): string;\n}\n\nexport interface GlazeExtendOptions {\n hue?: number;\n saturation?: number;\n /** Replace the dark-scheme hue seed (0–360). Defaults to the parent's. */\n darkHue?: number;\n /** Replace the dark-scheme saturation seed (0–100). Defaults to the parent's. */\n darkSaturation?: number;\n colors?: ColorMap;\n /** Config override for the child theme. Merged with the parent's override. */\n config?: GlazeConfigOverride;\n}\n\n// ============================================================================\n// Palette API\n// ============================================================================\n\nexport interface GlazeTokenOptions {\n /** Prefix mode. `true` uses \"<themeName>-\", or provide a custom map. */\n prefix?: boolean | Record<string, string>;\n /** Override state aliases for this export. */\n states?: {\n dark?: string;\n highContrast?: string;\n };\n /** Override which scheme variants to include. */\n modes?: GlazeOutputModes;\n /** Output color format. Default: 'oklch'. */\n format?: GlazeColorFormat;\n /**\n * Emit hue as a separate custom property, referenced via `var()`.\n * Requires `format: 'oklch'` and every color to be pastel.\n */\n splitHue?: boolean;\n /**\n * Base name for the theme-level hue var (`--{name}-hue`). Default: `'theme'`.\n * Palette export auto-derives this from the theme name.\n */\n name?: string;\n}\n\nexport interface GlazeJsonOptions {\n /** Override which scheme variants to include. */\n modes?: GlazeOutputModes;\n /** Output color format. Default: 'oklch'. */\n format?: GlazeColorFormat;\n}\n\nexport interface GlazeCssOptions {\n /** Output color format. Default: 'oklch'. */\n format?: GlazeColorFormat;\n /** Suffix appended to each CSS custom property name. Default: '-color'. */\n suffix?: string;\n /**\n * Emit hue as a separate custom property, referenced via `var()`.\n * Requires `format: 'oklch'` and every color to be pastel.\n */\n splitHue?: boolean;\n /**\n * Base name for the theme-level hue var (`--{name}-hue`). Default: `'theme'`.\n * Palette export auto-derives this from the theme name.\n */\n name?: string;\n}\n\n/** CSS custom property declarations grouped by scheme variant. */\nexport interface GlazeCssResult {\n light: string;\n dark: string;\n lightContrast: string;\n darkContrast: string;\n}\n\n// ============================================================================\n// DTCG & Tailwind export types\n// ============================================================================\n\n/**\n * Color space used for DTCG `$value` color objects.\n * @see https://www.designtokens.org/\n */\nexport type DtcgColorSpace = 'srgb' | 'oklch';\n\n/**\n * A DTCG color `$value` in the sRGB color space: gamma sRGB components in\n * 0–1 plus a 6-digit `hex` hint. Universally understood by Figma, Tokens\n * Studio, Style Dictionary, and every DTCG reader.\n */\nexport interface DtcgSrgbColorValue {\n colorSpace: 'srgb';\n components: [number, number, number];\n hex: HexColor;\n /** Opacity 0–1. Omitted when fully opaque (alpha = 1). */\n alpha?: number;\n}\n\n/**\n * A DTCG color `$value` in the OKLCH color space: `[L, C, H]` components\n * (L/C: 0–1, H: degrees). Wide-gamut and Glaze-native; no `hex` is emitted.\n */\nexport interface DtcgOklchColorValue {\n colorSpace: 'oklch';\n components: [number, number, number];\n /** Opacity 0–1. Omitted when fully opaque (alpha = 1). */\n alpha?: number;\n}\n\n/** A DTCG `$value` for a color token, in either supported color space. */\nexport type DtcgColorValue = DtcgSrgbColorValue | DtcgOklchColorValue;\n\n/**\n * A single W3C DTCG color token: `{ $type: 'color', $value }`.\n * `$description` is optional and not populated by Glaze today.\n */\nexport interface DtcgColorToken {\n $type: 'color';\n $value: DtcgColorValue;\n $description?: string;\n}\n\n/**\n * A W3C Design Tokens Format Module (2025.10) token tree for one scheme.\n * Glaze emits one document per scheme variant — the most tool-compatible\n * convention (one file per Style Dictionary theme / Tokens Studio set /\n * Figma variable mode).\n */\nexport type DtcgDocument = Record<string, DtcgColorToken>;\n\n/** DTCG token documents grouped by scheme variant. Light is always present. */\nexport interface GlazeDtcgResult {\n light: DtcgDocument;\n dark?: DtcgDocument;\n lightContrast?: DtcgDocument;\n darkContrast?: DtcgDocument;\n}\n\n/** A single DTCG color token grouped by scheme variant (standalone tokens). */\nexport interface GlazeColorDtcgResult {\n light: DtcgColorToken;\n dark?: DtcgColorToken;\n lightContrast?: DtcgColorToken;\n darkContrast?: DtcgColorToken;\n}\n\n/** Options for `theme.dtcg()` / `palette.dtcg()`. */\nexport interface GlazeDtcgOptions {\n /** Override which scheme variants to include. */\n modes?: GlazeOutputModes;\n /**\n * DTCG color space. `'srgb'` (default) emits sRGB components plus a `hex`\n * hint — universally understood (Figma, Tokens Studio). `'oklch'` emits\n * OKLCH components with no hex — Glaze-native, wide-gamut.\n */\n colorSpace?: DtcgColorSpace;\n}\n\n// ============================================================================\n// DTCG Resolver-Module export types\n// (W3C Design Tokens Resolver Module — one document for all scheme variants)\n// ============================================================================\n\n/**\n * A node in a DTCG Resolver-Module token tree: either a leaf color token or a\n * nested group. A flat `DtcgDocument` (top-level color-name keys) is a valid\n * shallow tree, so Glaze's per-scheme documents slot directly into\n * `sets.<name>.sources` and `modifiers.<name>.contexts.<ctx>` entries.\n */\nexport interface DtcgTokenTree {\n [key: string]: DtcgColorToken | DtcgTokenTree;\n}\n\n/** A named set in a resolver document: a list of token-tree sources. */\nexport interface DtcgResolverSet {\n sources: DtcgTokenTree[];\n}\n\n/**\n * A named modifier (an axis such as `scheme`) in a resolver document.\n * `default` names the context applied when no override is selected; `contexts`\n * maps each context name to the token-tree overrides applied for it.\n */\nexport interface DtcgResolverModifier {\n default: string;\n contexts: Record<string, DtcgTokenTree[]>;\n}\n\n/** A JSON-pointer `$ref` entry in a resolver document's `resolutionOrder`. */\nexport interface DtcgResolverRef {\n $ref: string;\n}\n\n/**\n * A W3C DTCG Resolver-Module document. Describes every scheme variant in a\n * single file as `sets` (base token sources) plus `modifiers` (per-context\n * overrides) composed in `resolutionOrder`. Consumable by resolver tools such\n * as Dispersa.\n * @see https://www.designtokens.org/\n */\nexport interface GlazeDtcgResolverDocument {\n version: string;\n sets: Record<string, DtcgResolverSet>;\n modifiers: Record<string, DtcgResolverModifier>;\n resolutionOrder: DtcgResolverRef[];\n}\n\n/** Renaming of the four scheme variants as resolver-modifier context names. */\nexport interface GlazeDtcgResolverContextNames {\n light?: string;\n dark?: string;\n lightContrast?: string;\n darkContrast?: string;\n}\n\n/**\n * Options for `theme.dtcgResolver()` / `palette.dtcgResolver()`. Extends\n * `GlazeDtcgOptions` so `modes` + `colorSpace` pass through to the underlying\n * per-scheme `dtcg()` build.\n */\nexport interface GlazeDtcgResolverOptions extends GlazeDtcgOptions {\n /** Name of the single set holding the default (light) token tree. Default `'base'`. */\n setName?: string;\n /**\n * Name of the modifier describing the scheme axis. Default `'scheme'`\n * (Glaze's term for the light / dark / high-contrast axis).\n */\n modifierName?: string;\n /**\n * Override the four context names emitted on the modifier. Defaults to the\n * Glaze variant keys: `light` / `dark` / `lightContrast` / `darkContrast`.\n */\n contextNames?: GlazeDtcgResolverContextNames;\n /** Resolver document version. Default `'2025.10'`. */\n version?: string;\n}\n\n/** Options for `glaze.color().dtcgResolver()`. `name` is required. */\nexport interface GlazeColorDtcgResolverOptions extends GlazeDtcgResolverOptions {\n /** Token name keying the color within each token tree. Required. */\n name: string;\n}\n\n/** Options for `theme.tailwind()` / `palette.tailwind()`. */\nexport interface GlazeTailwindOptions {\n /** Override which scheme variants to include. */\n modes?: GlazeOutputModes;\n /** Output color format. Default: 'oklch'. */\n format?: GlazeColorFormat;\n /**\n * CSS custom property namespace, forming `--<namespace><name>`.\n * Default: `'color-'` → `--color-surface`. (Tailwind v4's `--color-*`\n * convention, which auto-generates `bg-*` / `text-*` / `border-*`.)\n *\n * Named `namespace` rather than `prefix` to avoid clashing with the\n * palette theme-prefix option on `palette.tailwind()`.\n */\n namespace?: string;\n /**\n * Selector wrapping the dark-scheme overrides. Default: `'.dark'`.\n * Pass a media query such as `'@media (prefers-color-scheme: dark)'` to\n * drive dark mode from the OS preference instead of a class.\n */\n darkSelector?: string;\n /**\n * Selector wrapping the light high-contrast overrides. Default:\n * `'.high-contrast'`. The combined dark + high-contrast overrides are\n * emitted under `${darkSelector}${highContrastSelector}` (e.g.\n * `.dark.high-contrast`).\n */\n highContrastSelector?: string;\n}\n\n/** Options for `glaze.color().tailwind()`. `name` is required. */\nexport interface GlazeColorTailwindOptions extends GlazeTailwindOptions {\n /** Custom property base name (without leading `--`). Required. */\n name: string;\n}\n\n/** Options for `glaze.palette()` creation. */\nexport interface GlazePaletteOptions {\n /**\n * Name of the primary theme. The primary theme's tokens are duplicated\n * without prefix in all exports, providing convenient short aliases\n * alongside the prefixed versions. Can be overridden per-export.\n *\n * @example\n * ```ts\n * const palette = glaze.palette({ brand, accent }, { primary: 'brand' });\n * palette.tokens()\n * // → { light: { 'brand-surface': '...', 'surface': '...', 'accent-surface': '...' } }\n * ```\n */\n primary?: string;\n}\n\n/** Options shared by palette `tokens()`, `tasty()`, and `css()` exports. */\nexport interface GlazePaletteExportOptions {\n /**\n * Prefix mode. `true` uses `\"<themeName>-\"`, or provide a custom map.\n * Defaults to `true` for palette export methods.\n * Set to `false` explicitly to disable prefixing. Colliding keys\n * produce a console.warn and the first-written value wins.\n */\n prefix?: boolean | Record<string, string>;\n /**\n * Override the palette-level primary theme for this export.\n * Pass a theme name to set/change the primary, or `false` to disable it.\n * When omitted, inherits the palette-level `primary`.\n */\n primary?: string | false;\n /**\n * Emit hue as a separate custom property, referenced via `var()`.\n * Requires `format: 'oklch'` and every color to be pastel.\n */\n splitHue?: boolean;\n}\n\nexport interface GlazePalette {\n /** Theme names in insertion order. */\n list(): string[];\n\n /** Primary theme name, if set at palette creation. */\n readonly primary: string | undefined;\n\n /** Get a theme by name. Returns the live instance held by the palette. */\n theme(name: string): GlazeTheme | undefined;\n\n /**\n * Shallow copy of the theme map (same instances the palette holds).\n * Mutating a returned theme affects subsequent palette exports.\n */\n themes(): Record<string, GlazeTheme>;\n\n /**\n * Export the palette authoring configuration as a JSON-safe object.\n * Restorable via `glaze.paletteFrom(...)`. Distinct from `json()`, which\n * emits resolved color strings. Optional `override` is forwarded to each\n * nested `theme.export(override)`.\n */\n export(override?: GlazeConfigOverride): GlazePaletteExport;\n\n /**\n * Export all themes as a flat token map grouped by scheme variant.\n * Prefix defaults to `true` — all tokens are prefixed with the theme name.\n * Inherits the palette-level `primary`; override per-call or pass `false` to disable.\n *\n * ```ts\n * const palette = glaze.palette({ brand, accent }, { primary: 'brand' });\n * palette.tokens()\n * // → { light: { 'brand-surface': '...', 'surface': '...', 'accent-surface': '...' } }\n * ```\n */\n tokens(\n options?: GlazeJsonOptions & GlazePaletteExportOptions,\n ): Record<string, Record<string, string>>;\n\n /**\n * Export all themes as tasty style-to-state bindings.\n * Uses `#name` color token keys and state aliases (`''`, `'@media(prefers-color-scheme: dark)'`, etc.).\n * Prefix defaults to `true`. Inherits the palette-level `primary`.\n * @see https://tasty.style/docs\n */\n tasty(\n options?: GlazeTokenOptions & GlazePaletteExportOptions,\n ): Record<string, Record<string, string>>;\n\n /** Export all themes as plain JSON grouped by theme name. */\n json(\n options?: GlazeJsonOptions & {\n prefix?: boolean | Record<string, string>;\n },\n ): Record<string, Record<string, Record<string, string>>>;\n\n /** Export all themes as CSS custom property declarations. */\n css(options?: GlazeCssOptions & GlazePaletteExportOptions): GlazeCssResult;\n\n /**\n * Export all themes as W3C DTCG documents, one per scheme variant.\n * Prefix defaults to `true`. Inherits the palette-level `primary`.\n * @see https://www.designtokens.org/\n */\n dtcg(options?: GlazeDtcgOptions & GlazePaletteExportOptions): GlazeDtcgResult;\n\n /**\n * Export all themes as a single W3C DTCG Resolver-Module document. Prefix\n * defaults to `true`. Inherits the palette-level `primary`.\n * @see https://www.designtokens.org/\n */\n dtcgResolver(\n options?: GlazeDtcgResolverOptions & GlazePaletteExportOptions,\n ): GlazeDtcgResolverDocument;\n\n /**\n * Export all themes as a Tailwind CSS v4 `@theme` block plus dark /\n * high-contrast overrides. Returns a single ready-to-paste CSS string.\n * Prefix defaults to `true`.\n * @see https://tailwindcss.com/docs/theme\n */\n tailwind(options?: GlazeTailwindOptions & GlazePaletteExportOptions): string;\n}\n","/**\n * Authoring-export helpers: schema version, type guards, and restore\n * validation shared by `themeFrom` / `colorFrom` / `paletteFrom`.\n */\n\nimport { GLAZE_EXPORT_VERSION } from './types';\nimport type {\n GlazeColorTokenExport,\n GlazeExportKind,\n GlazePaletteExport,\n GlazeThemeExport,\n} from './types';\n\nexport { GLAZE_EXPORT_VERSION };\n\nfunction isPlainObject(data: unknown): data is Record<string, unknown> {\n return typeof data === 'object' && data !== null && !Array.isArray(data);\n}\n\n/**\n * Reject unknown / invalid schema versions. Missing `version` is allowed\n * (legacy snapshots). Present versions must be an integer in\n * `1..=GLAZE_EXPORT_VERSION`.\n */\nexport function assertExportVersion(\n data: { version?: unknown },\n factory: string,\n): void {\n if (data.version === undefined) return;\n if (\n typeof data.version !== 'number' ||\n !Number.isInteger(data.version) ||\n data.version < 1\n ) {\n throw new Error(\n `${factory}: invalid \"version\" field — expected an integer >= 1 (got ${JSON.stringify(data.version)}).`,\n );\n }\n if (data.version > GLAZE_EXPORT_VERSION) {\n throw new Error(\n `${factory}: unsupported export version ${data.version} (this library supports version ${GLAZE_EXPORT_VERSION}). Upgrade @tenphi/glaze to load this snapshot.`,\n );\n }\n}\n\n/**\n * When `kind` is present, it must match the factory. Missing `kind` is\n * allowed for legacy snapshots.\n */\nexport function assertExportKind(\n data: { kind?: unknown },\n expected: GlazeExportKind,\n factory: string,\n): void {\n if (data.kind === undefined) return;\n if (data.kind !== expected) {\n throw new Error(\n `${factory}: expected kind \"${expected}\", got ${JSON.stringify(data.kind)}.`,\n );\n }\n}\n\nfunction hasThemeShape(data: Record<string, unknown>): boolean {\n return (\n typeof data.hue === 'number' &&\n typeof data.saturation === 'number' &&\n !('form' in data) &&\n !('themes' in data)\n );\n}\n\nfunction hasColorTokenShape(data: Record<string, unknown>): boolean {\n return data.form === 'value' || data.form === 'structured';\n}\n\nfunction hasPaletteShape(data: Record<string, unknown>): boolean {\n return (\n isPlainObject(data.themes) &&\n !('form' in data) &&\n typeof data.hue !== 'number'\n );\n}\n\n/** Type guard for theme authoring snapshots (prefers `kind`, falls back to shape). */\nexport function isThemeExport(data: unknown): data is GlazeThemeExport {\n if (!isPlainObject(data)) return false;\n if (data.kind === 'theme') return hasThemeShape(data);\n if (data.kind !== undefined) return false;\n return hasThemeShape(data);\n}\n\n/** Type guard for color-token authoring snapshots. */\nexport function isColorTokenExport(\n data: unknown,\n): data is GlazeColorTokenExport {\n if (!isPlainObject(data)) return false;\n if (data.kind === 'color') return hasColorTokenShape(data);\n if (data.kind !== undefined) return false;\n return hasColorTokenShape(data);\n}\n\n/** Type guard for palette authoring snapshots. */\nexport function isPaletteExport(data: unknown): data is GlazePaletteExport {\n if (!isPlainObject(data)) return false;\n if (data.kind === 'palette') return hasPaletteShape(data);\n if (data.kind !== undefined) return false;\n return hasPaletteShape(data);\n}\n","/**\n * Small shared helpers used across the resolver pipeline:\n * - HC-pair selection (`pairNormal` / `pairHC`)\n * - HC-pair interpolation for the manual contrast level (`contrastFraction`,\n * `hcMirrorsNormal`, `numberAt`, `parseToneValueAt`)\n * - Absolute / relative / extreme tone discrimination\n * - Generic numeric helpers (`clamp`, `lerp`, hue resolution, relative-value\n * parsing)\n */\n\nimport type { ExtremeValue, HCPair, RelativeValue, ToneValue } from './types';\n\nexport function pairNormal<T>(p: HCPair<T>): T {\n return Array.isArray(p) ? p[0] : p;\n}\n\nexport function pairHC<T>(p: HCPair<T>): T {\n return Array.isArray(p) ? p[1] : p;\n}\n\nexport function clamp(v: number, min: number, max: number): number {\n return Math.max(min, Math.min(max, v));\n}\n\nexport function lerp(a: number, b: number, f: number): number {\n return a + (b - a) * f;\n}\n\n// ============================================================================\n// Manual contrast level\n// ============================================================================\n\n/**\n * Blend fraction at/above which an un-interpolable HC pair switches from its\n * normal entry to its high-contrast one (level 50).\n */\nexport const PAIR_SWITCH = 0.5;\n\n/** Blend fraction (0–1) for an authored 0–100 contrast level. */\nexport function levelFraction(level: number): number {\n return clamp(level, 0, 100) / 100;\n}\n\n/**\n * Manual-contrast blend fraction (0–1) for a resolved config, or `undefined`\n * in `'auto'` mode, where the normal variants take the authored normal entries\n * as-is.\n *\n * Note `contrastLevel: 0` yields `0`, not `undefined`. The two select different\n * branches, and an authored `0` is a slider position that `.export()` freezes\n * where an absent level is not — but they are not an *output* distinction: at\n * fraction 0 every interpolation returns its normal entry verbatim, so level 0\n * reproduces `'auto'` bit for bit.\n */\nexport function contrastFraction(config: {\n contrastLevel?: number | 'auto';\n}): number | undefined {\n const level = config.contrastLevel;\n if (typeof level !== 'number' || !Number.isFinite(level)) return undefined;\n return levelFraction(level);\n}\n\n/**\n * Whether the high-contrast variants are exact duplicates of the normal ones —\n * true only at `contrastLevel: 100`, where the normal passes already resolve at\n * full contrast.\n *\n * The level otherwise says nothing about high contrast: it positions the normal\n * variants, while `lightContrast` / `darkContrast` stay the true high-contrast\n * resolution at every level. This predicate marks the one level where that tier\n * carries no new information, so callers can skip the two high-contrast passes,\n * their drift checks, and the redundant output tier.\n */\nexport function hcMirrorsNormal(config: {\n contrastLevel?: number | 'auto';\n}): boolean {\n return contrastFraction(config) === 1;\n}\n\n/**\n * A numeric HC pair at a blend fraction (shadow `intensity`, mix `value`).\n *\n * The endpoints return the authored entry *by identity* rather than through\n * float arithmetic — `a + (b - a) * 1` is not bit-exactly `b` in IEEE 754, and\n * levels 0 / 100 must reproduce the classic output exactly.\n */\nexport function numberAt(p: HCPair<number>, f: number): number {\n if (!Array.isArray(p)) return p;\n if (f <= 0) return p[0];\n if (f >= 1) return p[1];\n return lerp(p[0], p[1], f);\n}\n\n/** Whether a tone value is an extreme keyword (`'max'` / `'min'`). */\nexport function isExtremeTone(value: ToneValue): value is ExtremeValue {\n return value === 'max' || value === 'min';\n}\n\n/**\n * Parse a value that can be absolute (number) or relative (signed string).\n * Returns the numeric value and whether it's relative.\n */\nexport function parseRelativeOrAbsolute(value: number | RelativeValue): {\n value: number;\n relative: boolean;\n} {\n if (typeof value === 'number') {\n return { value, relative: false };\n }\n return { value: parseFloat(value), relative: true };\n}\n\n/**\n * Parse a tone value into a normalized shape.\n * - `'max'` / `'min'` → `{ kind: 'extreme', value: 100 | 0 }` (an absolute\n * author tone before scheme mapping — `'max'` is 100, `'min'` is 0).\n * - `'+N'` / `'-N'` → `{ kind: 'relative', value: ±N }`.\n * - number → `{ kind: 'absolute', value }`.\n */\nexport function parseToneValue(value: ToneValue): {\n kind: 'absolute' | 'relative' | 'extreme';\n value: number;\n} {\n if (value === 'max') return { kind: 'extreme', value: 100 };\n if (value === 'min') return { kind: 'extreme', value: 0 };\n if (typeof value === 'number') return { kind: 'absolute', value };\n return { kind: 'relative', value: parseFloat(value) };\n}\n\n/**\n * Parse an authored tone pair at a manual-contrast blend fraction, returning\n * the same normalized shape as {@link parseToneValue}.\n *\n * Same-kind numeric pairs interpolate their magnitude — absolute tones\n * (`[30, 20]` → 25 at level 50) and relative deltas (`['+10', '+20']` → +15).\n * Everything else is un-interpolable and switches at {@link PAIR_SWITCH}:\n * extremes carry no magnitude, and a mixed-kind pair would change *which*\n * resolver branch runs mid-ramp (absolute remap vs. extreme-against-base vs.\n * base-anchored delta), putting a discontinuity at level 100 — exactly where\n * the output must stay bit-exact.\n *\n * Returns a parsed struct rather than a `ToneValue` so a blended relative\n * delta never round-trips through a `'+15.5'` string, and so `kind` — which\n * selects the resolver branch — cannot drift.\n */\nexport function parseToneValueAt(\n p: HCPair<ToneValue>,\n f: number,\n): { kind: 'absolute' | 'relative' | 'extreme'; value: number } {\n if (!Array.isArray(p)) return parseToneValue(p);\n if (f <= 0) return parseToneValue(p[0]);\n if (f >= 1) return parseToneValue(p[1]);\n const normal = parseToneValue(p[0]);\n const hc = parseToneValue(p[1]);\n if (normal.kind === hc.kind && normal.kind !== 'extreme') {\n return { kind: normal.kind, value: lerp(normal.value, hc.value, f) };\n }\n return f < PAIR_SWITCH ? normal : hc;\n}\n\n/**\n * Compute the effective hue for a color, given the theme seed hue\n * and an optional per-color hue override.\n */\nexport function resolveEffectiveHue(\n seedHue: number,\n defHue: number | RelativeValue | undefined,\n): number {\n if (defHue === undefined) return seedHue;\n const parsed = parseRelativeOrAbsolute(defHue);\n if (parsed.relative) {\n return (((seedHue + parsed.value) % 360) + 360) % 360;\n }\n return ((parsed.value % 360) + 360) % 360;\n}\n\n/**\n * Check whether a tone value represents an absolute root definition\n * (i.e. a number, not a relative string). Extreme keywords (`'max'` /\n * `'min'`) also count — they need no base.\n */\nexport function isAbsoluteTone(tone: HCPair<ToneValue> | undefined): boolean {\n if (tone === undefined) return false;\n const normal = Array.isArray(tone) ? tone[0] : tone;\n return typeof normal === 'number' || isExtremeTone(normal);\n}\n","/**\n * OKHST — the contrast-uniform tone space.\n *\n * OKHST is OKHSL with its lightness axis replaced by a contrast-uniform\n * \"tone\" axis. It shares `h` / `s` with OKHSL verbatim and swaps `l` for\n * `t`. This module owns:\n *\n * - the closed-form tone transfers (`toTone` / `fromTone`) at a fixed\n * reference eps, plus the gray luminance helpers (`lToY` / `yToL`),\n * - the `{ h, s, t }` <-> `{ h, s, l }` color-space converters,\n * - the resolved-variant edge adapter (`variantToOkhsl`),\n * - the per-scheme tone mapping that replaced the Möbius dark curve\n * (`mapToneForScheme`), the dark desaturation reducer, and the solver's scheme\n * tone range,\n * - the scheme tone window, including the high-contrast bypass and its\n * continuous generalization under a manual contrast level.\n *\n * See `docs/okhst.md` for the full specification and the calibrated\n * default constants.\n */\n\nimport { clamp, contrastFraction, lerp } from './hc-pair';\nimport { toe, toeInv } from './okhsl-color-math';\nimport type { AdaptationMode, GlazeConfigResolved, ToneWindow } from './types';\n\n/**\n * Reference eps for the OKHST color space. WCAG 2 contrast is\n * `(Y_hi + 0.05) / (Y_lo + 0.05)`, so an eps of `0.05` makes equal tone\n * steps yield equal WCAG contrast. This is the canonical eps used by\n * `okhst()` input, `{ h, s, t }` input, stored `ResolvedColorVariant.t`,\n * relative `tone` offsets, and the contrast solver.\n */\nexport const REF_EPS = 0.05;\n\n// ============================================================================\n// Gray luminance <-> OKHSL lightness (closed form)\n// ============================================================================\n\n/**\n * Gray luminance from OKHSL lightness. For an achromatic color the OKLab\n * lightness is `toeInv(l)` and luminance is its cube.\n */\nexport function lToY(l: number): number {\n const L = toeInv(l);\n return L * L * L;\n}\n\n/** OKHSL lightness from gray luminance — exact inverse of {@link lToY}. */\nexport function yToL(y: number): number {\n return toe(Math.cbrt(Math.max(0, y)));\n}\n\n// ============================================================================\n// Tone transfers (luminance domain)\n// ============================================================================\n\n/**\n * Map a luminance `Y` (0–1) to tone (0–100) at the given eps.\n * `toneFromY(0) === 0` and `toneFromY(1) === 100` for any eps.\n */\nexport function toneFromY(y: number, eps: number = REF_EPS): number {\n const num = Math.log(y + eps) - Math.log(eps);\n const den = Math.log(1 + eps) - Math.log(eps);\n return (num / den) * 100;\n}\n\n/** Map a tone (0–100) back to luminance (0–1). Inverse of {@link toneFromY}. */\nexport function yFromTone(t: number, eps: number = REF_EPS): number {\n const den = Math.log(1 + eps) - Math.log(eps);\n return Math.exp((t / 100) * den + Math.log(eps)) - eps;\n}\n\n// ============================================================================\n// Tone transfers (OKHSL lightness domain)\n// ============================================================================\n\n/** OKHSL lightness (0–1) -> tone (0–100). */\nexport function toTone(l: number, eps: number = REF_EPS): number {\n return toneFromY(lToY(l), eps);\n}\n\n/** Tone (0–100) -> OKHSL lightness (0–1). Inverse of {@link toTone}. */\nexport function fromTone(t: number, eps: number = REF_EPS): number {\n return yToL(yFromTone(t, eps));\n}\n\n// ============================================================================\n// Color-space converters\n// ============================================================================\n\n/** Convert OKHST `{ h, s, t }` (t in 0–1) to OKHSL `{ h, s, l }`. */\nexport function okhstToOkhsl(c: { h: number; s: number; t: number }): {\n h: number;\n s: number;\n l: number;\n} {\n return { h: c.h, s: c.s, l: clamp(fromTone(c.t * 100), 0, 1) };\n}\n\n/** Convert OKHSL `{ h, s, l }` to OKHST `{ h, s, t }` (t in 0–1). */\nexport function okhslToOkhst(c: { h: number; s: number; l: number }): {\n h: number;\n s: number;\n t: number;\n} {\n return { h: c.h, s: c.s, t: clamp(toTone(c.l) / 100, 0, 1) };\n}\n\n/**\n * Edge adapter: a resolved variant stores canonical tone `t` (0–1). Convert\n * it to the OKHSL `{ h, s, l }` the formatters and luminance pipeline expect —\n * `s` and `l` on the same 0–1 factor scale, so `const { h, s, l } =\n * variantToOkhsl(v)` destructures straight into `formatOkhsl` / `formatRgb` /\n * `okhslToLinearSrgb` with no rescaling. `alpha` stays on the variant; use\n * `glaze.format(v, format)` for a string that carries it.\n */\nexport function variantToOkhsl(v: { h: number; s: number; t: number }): {\n h: number;\n s: number;\n l: number;\n} {\n return { h: v.h, s: v.s, l: clamp(fromTone(v.t * 100), 0, 1) };\n}\n\n// ============================================================================\n// Scheme tone mapping (replaces the Möbius dark curve)\n// ============================================================================\n\n/**\n * Normalize any {@link ToneWindow} form to `{ lo, hi, eps }`.\n * - `false`: full range `[0, 100]` at the reference eps (boundaries removed,\n * curve preserved).\n * - `[lo, hi]`: endpoints at the reference eps (the common form).\n * - `{ lo, hi, eps }`: passed through (advanced eps tuning).\n */\nexport function normalizeToneWindow(win: ToneWindow): {\n lo: number;\n hi: number;\n eps: number;\n} {\n if (win === false) return { lo: 0, hi: 100, eps: REF_EPS };\n if (Array.isArray(win)) return { lo: win[0], hi: win[1], eps: REF_EPS };\n return { lo: win.lo, hi: win.hi, eps: win.eps };\n}\n\n/**\n * Resolve the active tone window for a scheme as OKHSL-lightness endpoints.\n * - HC variants always return the full range `[0, 100]` with the mode eps.\n * - Under a manual `contrastLevel`, each endpoint is interpolated toward that\n * full range: light `10 → 0` / `100 → 100`, dark `15 → 0` / `95 → 100`. The\n * endpoints are exact — level 0 returns the configured window and level 100\n * the same literal the HC branch returns.\n * - `false` (= \"no clamping\") is treated as `[0, 100]` with the reference eps,\n * and is therefore level-invariant.\n */\nfunction activeWindow(\n isHighContrast: boolean,\n kind: 'light' | 'dark',\n config: GlazeConfigResolved,\n): { lo: number; hi: number; eps: number } {\n const win = normalizeToneWindow(\n kind === 'dark' ? config.darkTone : config.lightTone,\n );\n if (isHighContrast) return { lo: 0, hi: 100, eps: win.eps };\n const f = contrastFraction(config);\n if (f === undefined || f <= 0) return win;\n if (f >= 1) return { lo: 0, hi: 100, eps: win.eps };\n // The render eps is not interpolated — HC keeps the configured eps today, so\n // the ramp does too.\n return { lo: lerp(win.lo, 0, f), hi: lerp(win.hi, 100, f), eps: win.eps };\n}\n\n/**\n * Remap an authored tone (0–100) into a scheme window and return the final\n * OKHSL lightness (0–100). The window endpoints are OKHSL lightnesses; the\n * author tone is positioned within the window's tone interval (using the\n * window's render eps), then converted back to lightness.\n */\nfunction remapToneToLightness(\n authorTone: number,\n win: { lo: number; hi: number; eps: number },\n): number {\n const loT = toTone(win.lo / 100, win.eps);\n const hiT = toTone(win.hi / 100, win.eps);\n const winTone = loT + (authorTone / 100) * (hiT - loT);\n return clamp(fromTone(winTone, win.eps) * 100, 0, 100);\n}\n\n/**\n * Map an authored tone for a scheme and return the canonical stored tone\n * (0–100, reference eps).\n *\n * - `static`: identity — the same tone renders in every scheme.\n * - `auto` + dark: invert (`100 - tone`) then remap into the dark window.\n * - `auto`/`fixed` + light, or `fixed` + dark: remap, no inversion.\n *\n * The window remap uses the mode's render eps to land a final OKHSL\n * lightness; that lightness is then re-expressed as canonical tone so\n * relative offsets and contrast stay comparable across schemes.\n *\n * A manual `contrastLevel` widens the window continuously (see\n * `activeWindow`); inversion is unaffected.\n */\nexport function mapToneForScheme(\n authorTone: number,\n mode: AdaptationMode,\n isDark: boolean,\n isHighContrast: boolean,\n config: GlazeConfigResolved,\n): number {\n if (mode === 'static') return clamp(authorTone, 0, 100);\n\n const kind = isDark ? 'dark' : 'light';\n const win = activeWindow(isHighContrast, kind, config);\n\n const inverted = isDark && mode === 'auto' ? 100 - authorTone : authorTone;\n const finalL = remapToneToLightness(clamp(inverted, 0, 100), win);\n return clamp(toTone(finalL / 100), 0, 100);\n}\n\n// ============================================================================\n// Saturation\n// ============================================================================\n\n/** Dark-scheme desaturation reducer (unchanged from the legacy pipeline). */\nexport function mapSaturationDark(\n s: number,\n mode: AdaptationMode,\n config: GlazeConfigResolved,\n): number {\n if (mode === 'static') return s;\n return s * (1 - config.darkDesaturation);\n}\n\n// ============================================================================\n// Solver support\n// ============================================================================\n\n/**\n * Tone search range (0–1) for the contrast solver in a given scheme.\n * `static` searches the full range; otherwise the scheme window's tone\n * endpoints (HC bypasses to full range, a manual `contrastLevel` widens\n * toward it — see `activeWindow`).\n */\nexport function schemeToneRange(\n isDark: boolean,\n mode: AdaptationMode,\n isHighContrast: boolean,\n config: GlazeConfigResolved,\n): [number, number] {\n if (mode === 'static') return [0, 1];\n const win = activeWindow(isHighContrast, isDark ? 'dark' : 'light', config);\n return [\n clamp(toTone(win.lo / 100) / 100, 0, 1),\n clamp(toTone(win.hi / 100) / 100, 0, 1),\n ];\n}\n","/**\n * Parsing and validation for `GlazeColorValue` — the literal color forms.\n *\n * Hex, the CSS color functions Glaze emits, and the four value-object shapes all\n * land here and come out as OKHSL. Split out of `color-token.ts` so both\n * consumers can reach it without an import cycle: standalone `glaze.color()`\n * tokens build on it, and the resolver needs it for a theme color's `from`. It\n * depends on nothing but the color math, which is what keeps that true.\n */\n\nimport {\n hslToSrgb,\n oklabToOkhsl,\n parseHexAlpha,\n srgbToOkhsl,\n} from './okhsl-color-math';\nimport { okhstToOkhsl } from './okhst';\nimport type {\n GlazeColorValue,\n OkhslColor,\n OkhstColor,\n OklchColor,\n RgbColor,\n} from './types';\n\n/**\n * Matches the CSS color functions Glaze itself emits (`rgb()`, `hsl()`,\n * `okhsl()`, `oklch()`) plus their legacy alpha aliases (`rgba()`, `hsla()`).\n *\n * Only bare numeric components are supported. Named colors (`red`),\n * relative-color syntax (`from <color> ...`), and angle units other\n * than bare degrees (`deg` is the only suffix tolerated by `parseFloat`)\n * are out of scope.\n */\nconst COLOR_FN_RE = /^(rgba?|hsla?|okhsl|okhst|oklch)\\(\\s*([^)]*)\\s*\\)$/i;\n\nfunction parseNumberOrPercent(raw: string, percentScale: number): number {\n if (raw.endsWith('%')) {\n return (parseFloat(raw) / 100) * percentScale;\n }\n return parseFloat(raw);\n}\n\n/**\n * Split the body of a CSS color function into its components and detect\n * whether an alpha channel was present.\n *\n * Handles both modern slash syntax (`R G B / A` or `R, G, B / A`) and\n * legacy comma syntax (`R, G, B, A`). The alpha value itself is discarded\n * by the caller — standalone Glaze colors have no opacity field.\n */\nfunction splitColorBody(body: string): {\n components: string[];\n hadAlpha: boolean;\n} {\n const slashIdx = body.indexOf('/');\n if (slashIdx !== -1) {\n const components = body\n .slice(0, slashIdx)\n .trim()\n .split(/[\\s,]+/)\n .filter(Boolean);\n const hadAlpha = body.slice(slashIdx + 1).trim().length > 0;\n return { components, hadAlpha };\n }\n\n const components = body.split(/[\\s,]+/).filter(Boolean);\n if (components.length === 4) {\n components.pop();\n return { components, hadAlpha: true };\n }\n return { components, hadAlpha: false };\n}\n\nfunction warnDroppedAlpha(input: string): void {\n console.warn(\n `glaze: alpha component dropped from \"${input}\" (standalone color has no opacity field).`,\n );\n}\n\nexport function parseColorString(input: string): OkhslColor {\n if (input.startsWith('#')) {\n const parsed = parseHexAlpha(input);\n if (!parsed) throw new Error(`glaze: invalid hex color \"${input}\".`);\n if (parsed.alpha !== undefined) warnDroppedAlpha(input);\n const [h, s, l] = srgbToOkhsl(parsed.rgb);\n return { h, s, l };\n }\n\n const m = input.match(COLOR_FN_RE);\n if (!m) {\n throw new Error(`glaze: unsupported color string \"${input}\".`);\n }\n\n const fn = m[1].toLowerCase();\n const { components, hadAlpha } = splitColorBody(m[2].trim());\n\n if (hadAlpha) warnDroppedAlpha(input);\n if (components.length !== 3) {\n throw new Error(`glaze: expected 3 components in \"${input}\".`);\n }\n\n switch (fn) {\n case 'rgb':\n case 'rgba': {\n const r = parseNumberOrPercent(components[0], 255) / 255;\n const g = parseNumberOrPercent(components[1], 255) / 255;\n const b = parseNumberOrPercent(components[2], 255) / 255;\n const [h, s, l] = srgbToOkhsl([r, g, b]);\n return { h, s, l };\n }\n case 'hsl':\n case 'hsla': {\n const h = parseFloat(components[0]);\n const s = parseNumberOrPercent(components[1], 1);\n const l = parseNumberOrPercent(components[2], 1);\n const [oh, os, ol] = srgbToOkhsl(hslToSrgb(h, s, l));\n return { h: oh, s: os, l: ol };\n }\n case 'okhsl': {\n const h = parseFloat(components[0]);\n const s = parseNumberOrPercent(components[1], 1);\n const l = parseNumberOrPercent(components[2], 1);\n return { h, s, l };\n }\n case 'okhst': {\n const h = parseFloat(components[0]);\n const s = parseNumberOrPercent(components[1], 1);\n const t = parseNumberOrPercent(components[2], 1);\n return okhstToOkhsl({ h, s, t });\n }\n case 'oklch': {\n const L = parseNumberOrPercent(components[0], 1);\n // Per CSS Color 4: chroma percent maps `100% → 0.4`.\n const C = parseNumberOrPercent(components[1], 0.4);\n const hDeg = parseFloat(components[2]);\n const hRad = (hDeg * Math.PI) / 180;\n const a = C * Math.cos(hRad);\n const b = C * Math.sin(hRad);\n const [h, s, l] = oklabToOkhsl([L, a, b]);\n return { h, s, l };\n }\n }\n throw new Error(`glaze: unsupported color function \"${fn}\".`);\n}\n\n// ============================================================================\n// Input validation\n// ============================================================================\n\n/**\n * Validate a user-supplied `OkhslColor`. Catches the common 0-100 vs 0-1\n * confusion (the structured form uses 0-100, OKHSL objects use 0-1).\n */\nexport function validateOkhslColor(value: OkhslColor): void {\n const { h, s, l } = value;\n if (!Number.isFinite(h) || !Number.isFinite(s) || !Number.isFinite(l)) {\n throw new Error('glaze.color: OkhslColor h/s/l must be finite numbers.');\n }\n if (s > 1.5 || l > 1.5) {\n throw new Error(\n 'glaze.color: OkhslColor s/l must be in 0–1 range. Did you mean the structured form { hue, saturation, tone } (which uses 0–100)?',\n );\n }\n}\n\n/** Validate a user-supplied `{ r, g, b }` object in 0–255. */\nexport function validateRgbColor(value: RgbColor): void {\n for (const key of ['r', 'g', 'b'] as const) {\n const n = value[key];\n if (!Number.isFinite(n) || n < 0 || n > 255) {\n throw new Error(\n `glaze.color: RgbColor ${key} must be a finite number in 0–255 (got ${n}).`,\n );\n }\n }\n}\n\n/** Validate a user-supplied `{ l, c, h }` OKLCh object. */\nexport function validateOklchColor(value: OklchColor): void {\n const { l, c, h } = value;\n if (!Number.isFinite(l) || !Number.isFinite(c) || !Number.isFinite(h)) {\n throw new Error('glaze.color: OklchColor l/c/h must be finite numbers.');\n }\n if (l > 1.5 || c > 1.5) {\n throw new Error(\n 'glaze.color: OklchColor l/c must be in 0–1 range (matching oklch() strings).',\n );\n }\n}\n\nexport function oklchComponentsToOkhsl(\n l: number,\n c: number,\n hDeg: number,\n): OkhslColor {\n const hRad = (hDeg * Math.PI) / 180;\n const a = c * Math.cos(hRad);\n const b = c * Math.sin(hRad);\n const [h, s, outL] = oklabToOkhsl([l, a, b]);\n return { h, s, l: outL };\n}\n\nexport function isRgbColorObject(value: object): value is RgbColor {\n return 'r' in value && 'g' in value && 'b' in value;\n}\n\nexport function isOklchColorObject(value: object): value is OklchColor {\n return 'c' in value && 'l' in value && 'h' in value;\n}\n\nexport function isOkhstColorObject(value: object): value is OkhstColor {\n return 't' in value && 'h' in value && 's' in value;\n}\n\n/** Validate a user-supplied `{ h, s, t }` OKHST object (s/t in 0–1). */\nexport function validateOkhstColor(value: OkhstColor): void {\n const { h, s, t } = value;\n if (!Number.isFinite(h) || !Number.isFinite(s) || !Number.isFinite(t)) {\n throw new Error('glaze.color: OkhstColor h/s/t must be finite numbers.');\n }\n if (s > 1.5 || t > 1.5) {\n throw new Error(\n 'glaze.color: OkhstColor s/t must be in 0–1 range. Did you mean the structured form { hue, saturation, tone } (which uses 0–100)?',\n );\n }\n}\n\n/**\n * Extract an OKHSL color from any `GlazeColorValue` form. Also used by\n * `glaze.shadow()` so all shadow inputs (hex, color functions, OKHSL,\n * literal objects) go through one parser.\n */\nexport function extractOkhslFromValue(value: GlazeColorValue): OkhslColor {\n if (typeof value === 'string') return parseColorString(value);\n if (Array.isArray(value)) {\n throw new Error(\n 'glaze.color: RGB tuple [r, g, b] is no longer supported — use { r, g, b } instead.',\n );\n }\n if (isRgbColorObject(value)) {\n validateRgbColor(value);\n const [h, s, l] = srgbToOkhsl([\n value.r / 255,\n value.g / 255,\n value.b / 255,\n ]);\n return { h, s, l };\n }\n if (isOklchColorObject(value)) {\n validateOklchColor(value);\n return oklchComponentsToOkhsl(value.l, value.c, value.h);\n }\n if (isOkhstColorObject(value)) {\n validateOkhstColor(value);\n return okhstToOkhsl(value);\n }\n validateOkhslColor(value);\n return value;\n}\n","/**\n * Export-time guards for color format and channel-splitting prerequisites.\n */\n\nimport type {\n GlazeColorFormat,\n GlazeOutputModes,\n ResolvedColor,\n} from './types';\n\nconst NON_NATIVE_FORMATS = new Set<GlazeColorFormat>(['okhsl', 'okhst']);\n\n/**\n * Throw when a non-native Glaze color space is requested for an export that\n * emits raw CSS or non-Tasty token maps.\n */\nexport function assertNativeFormat(\n format: GlazeColorFormat | undefined,\n method: string,\n): void {\n if (format !== undefined && NON_NATIVE_FORMATS.has(format)) {\n throw new Error(\n `glaze: ${format} output is only supported by tasty() (not a native CSS color space). ` +\n `Use tasty({ format: '${format}' }) or pick a native format (oklch|hsl|rgb) for ${method}().`,\n );\n }\n}\n\ntype SchemeField = 'light' | 'dark' | 'lightContrast' | 'darkContrast';\n\nconst SCHEME_FIELDS: {\n field: SchemeField;\n modes: (modes: Required<GlazeOutputModes>) => boolean;\n}[] = [\n { field: 'light', modes: () => true },\n { field: 'dark', modes: (m) => m.dark },\n { field: 'lightContrast', modes: (m) => m.highContrast },\n {\n field: 'darkContrast',\n modes: (m) => m.dark && m.highContrast,\n },\n];\n\n/**\n * Throw when `splitHue` is enabled but any exported color is not pastel.\n * Hue rotation is only clip-free when chroma is bounded by the hue-independent\n * safe chroma (`computeSafeChromaOKLCH`).\n */\nexport function assertAllPastel(\n resolved: Map<string, ResolvedColor>,\n modes: Required<GlazeOutputModes>,\n): void {\n const nonPastel: string[] = [];\n\n for (const [name, color] of resolved) {\n for (const { field, modes: active } of SCHEME_FIELDS) {\n if (!active(modes)) continue;\n const variant = color[field];\n if (variant.pastel !== true) {\n if (!nonPastel.includes(name)) nonPastel.push(name);\n break;\n }\n }\n }\n\n if (nonPastel.length === 0) return;\n\n throw new Error(\n 'glaze: splitHue requires every color to be pastel (hue rotation is only ' +\n 'clip-free when chroma is bounded by the hue-independent safe chroma). ' +\n `Non-pastel: ${nonPastel.join(', ')}. ` +\n 'Set pastel: true (per-theme, per-token, or per-color) or drop splitHue.',\n );\n}\n","/**\n * Contrast solver — operates in OKHST tone.\n *\n * Finds the tone closest to a preferred tone that satisfies a contrast\n * floor (WCAG 2 ratio or APCA Lc) against a base color. Because tone is\n * contrast-uniform, the WCAG branch gets a closed-form seed and the search\n * converges quickly.\n *\n * Public API: `findToneForContrast`, `findValueForMixContrast`,\n * `resolveMinContrast`, `resolveContrastForMode`, `resolveContrastForLevel`,\n * `apcaContrast`.\n */\n\nimport {\n okhslToLinearSrgb,\n contrastRatioFromLuminance,\n gamutClampedLuminance,\n apcaLuminanceFromLinearRgb,\n} from './okhsl-color-math';\nimport { REF_EPS, fromTone, toneFromY } from './okhst';\nimport { clamp, lerp, levelFraction, pairHC, pairNormal } from './hc-pair';\nimport type { ContrastSpec, HCPair } from './types';\n\nexport type LinearRgb = [number, number, number];\n\nexport type ContrastMetric = 'wcag' | 'apca';\n\n/**\n * Luminance of a linear-sRGB color in the basis the metric expects: WCAG\n * relative luminance for `wcag`, APCA screen luminance (`Ys`) for `apca`.\n */\nexport function metricLuminance(\n metric: ContrastMetric,\n linearRgb: LinearRgb,\n): number {\n return metric === 'apca'\n ? apcaLuminanceFromLinearRgb(linearRgb)\n : gamutClampedLuminance(linearRgb);\n}\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type ContrastPreset = 'AA' | 'AAA' | 'AA-large' | 'AAA-large';\nexport type MinContrast = number | ContrastPreset;\n\n/**\n * Named APCA Lc floor presets (APCA Bronze Simple Mode conformance levels),\n * independent of role. Use them anywhere an APCA target is accepted.\n *\n * | Preset | Lc | Use case |\n * | ------------- | --- | ---------------------------------------------------- |\n * | `'preferred'` | 90 | Preferred body / column text |\n * | `'body'` | 75 | Minimum body / column text |\n * | `'content'` | 60 | Readable non-body content (~WCAG AA 4.5:1) |\n * | `'large'` | 45 | Large/bold headlines; fine icons/outlines (~3:1) |\n * | `'non-text'` | 30 | Solid icons/controls; placeholder/disabled text |\n * | `'min'` | 15 | Dividers/decorative; APCA \"point of invisibility\" |\n */\nexport type ApcaPreset =\n | 'preferred'\n | 'body'\n | 'content'\n | 'large'\n | 'non-text'\n | 'min';\n\nexport const APCA_PRESETS: Record<ApcaPreset, number> = {\n preferred: 90,\n body: 75,\n content: 60,\n large: 45,\n 'non-text': 30,\n min: 15,\n};\n\n/**\n * APCA-W3 \"Enhanced Level\" delta added to a bare APCA target in high-contrast\n * mode when no explicit HC value is provided (analogous to WCAG AAA over AA).\n * Only applied when neither the outer `contrast` pair nor the inner `apca`\n * pair carries an explicit HC entry.\n */\nexport const APCA_HC_ENHANCEMENT = 15;\n\n/** Upper bound for an APCA Lc target after HC enhancement. */\nexport const APCA_MAX_LC = 106;\n\n/**\n * Resolve an APCA target — a raw Lc number (kept as-is) or an `ApcaPreset`\n * keyword mapped to its Lc value. The magnitude is forced non-negative.\n */\nexport function resolveApcaTarget(value: number | ApcaPreset): number {\n if (typeof value === 'number') return Math.abs(value);\n return APCA_PRESETS[value];\n}\n\n/** Metric + numeric target after resolving a `ContrastSpec` for a mode. */\nexport interface ResolvedContrast {\n metric: 'wcag' | 'apca';\n /** WCAG ratio (>= 1) or APCA Lc magnitude (0–106). */\n target: number;\n /**\n * APCA argument order: which side the resolved (candidate) color plays\n * against the base. `'fg'` (default) → `apcaContrast(yCandidate, yBase)`;\n * `'bg'` → `apcaContrast(yBase, yCandidate)`. Always `'fg'` for WCAG\n * (symmetric, ignored).\n */\n polarity?: 'fg' | 'bg';\n}\n\n// ============================================================================\n// Preset mapping + spec resolution\n// ============================================================================\n\nconst CONTRAST_PRESETS: Record<ContrastPreset, number> = {\n AA: 4.5,\n AAA: 7,\n 'AA-large': 3,\n 'AAA-large': 4.5,\n};\n\n/**\n * WCAG high-contrast auto-promotion (analog of APCA's Enhanced Level). A bare\n * AA / AA-large preset is promoted to its spec-defined \"Enhanced\" successor\n * (SC 1.4.3 → SC 1.4.6) in high-contrast mode. AAA / AAA-large are already\n * the top WCAG tier and are left unchanged. Bare numeric targets have no\n * defined successor tier and are also left unchanged. An explicit HC value\n * (outer or inner pair) always overrides.\n */\nconst WCAG_HC_PROMOTION: Partial<Record<ContrastPreset, ContrastPreset>> = {\n AA: 'AAA',\n 'AA-large': 'AAA-large',\n};\n\nexport function resolveMinContrast(value: MinContrast): number {\n if (typeof value === 'number') {\n return Math.max(1, value);\n }\n return CONTRAST_PRESETS[value];\n}\n\n/**\n * Resolve a WCAG target (number or preset) for a mode, applying the\n * high-contrast auto-promotion when `explicitHC` is false and the value is an\n * AA-family preset. Bare numbers and AAA-family presets pass through.\n */\nfunction resolveWcagTarget(\n value: number | ContrastPreset,\n isHighContrast: boolean,\n explicitHC: boolean,\n): number {\n if (typeof value === 'number') {\n return resolveMinContrast(value);\n }\n if (isHighContrast && !explicitHC) {\n const promoted = WCAG_HC_PROMOTION[value];\n if (promoted !== undefined) return resolveMinContrast(promoted);\n }\n return resolveMinContrast(value);\n}\n\nfunction pickPair<T>(p: HCPair<T>, isHighContrast: boolean): T {\n return Array.isArray(p) ? (isHighContrast ? p[1] : p[0]) : p;\n}\n\n/**\n * The metric a single `ContrastSpec` measures in. Bare numbers and WCAG\n * presets are `'wcag'`; only an `{ apca }` object is `'apca'`.\n */\nexport function contrastMetricOf(spec: ContrastSpec): ContrastMetric {\n return typeof spec === 'object' && 'apca' in spec ? 'apca' : 'wcag';\n}\n\n/**\n * Resolve a `ContrastSpec` (already selected from any outer HC pair) for a\n * given mode into `{ metric, target }`. Handles the inner metric HC pair and\n * preset resolution. `polarity` is passed through to the result for the APCA\n * branch (it controls argument order in the solver); WCAG ignores it.\n *\n * `outerExplicitHC` indicates whether the caller selected this `spec` from an\n * explicit high-contrast entry of the outer `contrast` pair. Together with the\n * inner metric pair, it decides whether the HC auto-enhancement fires:\n * - APCA: +15 Lc \"Enhanced Level\" boost when neither level is explicit.\n * - WCAG: AA → AAA / AA-large → AAA-large promotion (SC 1.4.3 → 1.4.6) when\n * neither level is explicit. AAA-family presets and bare numbers are left\n * unchanged (AAA is the top WCAG tier).\n * Defaults to `false` (correct for direct callers, which pass a single\n * selected spec rather than an outer pair).\n */\nexport function resolveContrastForMode(\n spec: ContrastSpec,\n isHighContrast: boolean,\n polarity?: 'fg' | 'bg',\n outerExplicitHC?: boolean,\n): ResolvedContrast {\n if (typeof spec === 'number' || typeof spec === 'string') {\n // A bare string here is a WCAG preset ('AA' / 'AAA' / ...).\n return {\n metric: 'wcag',\n target: resolveWcagTarget(spec, isHighContrast, !!outerExplicitHC),\n };\n }\n if ('apca' in spec) {\n const baseTarget = resolveApcaTarget(pickPair(spec.apca, isHighContrast));\n const innerExplicitHC = Array.isArray(spec.apca);\n const enhanced =\n isHighContrast && !outerExplicitHC && !innerExplicitHC\n ? Math.min(baseTarget + APCA_HC_ENHANCEMENT, APCA_MAX_LC)\n : baseTarget;\n return {\n metric: 'apca',\n target: enhanced,\n polarity: polarity ?? 'fg',\n };\n }\n const innerExplicitHC = Array.isArray(spec.wcag);\n const picked = pickPair(spec.wcag, isHighContrast);\n return {\n metric: 'wcag',\n target: resolveWcagTarget(\n picked,\n isHighContrast,\n !!outerExplicitHC || innerExplicitHC,\n ),\n };\n}\n\n/**\n * Resolve a `contrast` spec — including its outer `[normal, highContrast]`\n * pair — at a manual contrast `level` (0–100), by resolving both ends and\n * interpolating the numeric target.\n *\n * Level 0 / 100 delegate verbatim to {@link resolveContrastForMode}, so the\n * endpoints are bit-identical to classic normal / high-contrast resolution.\n * Resolving each end fully first also means every rule that governs the\n * escalation still applies at both ends for free: preset mapping, the\n * `APCA_MAX_LC` clamp, and the explicit-HC suppression that cancels the\n * `AA → AAA` promotion and the `+15 Lc` enhancement.\n *\n * Throws when the two ends measure in different metrics — a WCAG ratio and an\n * APCA Lc live on different scales, so there is no target between them. Such a\n * pair is rejected at authoring time by `validateColorDefs`; this is the guard\n * for direct callers.\n */\nexport function resolveContrastForLevel(\n spec: HCPair<ContrastSpec>,\n level: number,\n polarity?: 'fg' | 'bg',\n): ResolvedContrast {\n const outerExplicitHC = Array.isArray(spec);\n const f = levelFraction(level);\n const normal = resolveContrastForMode(\n pairNormal(spec),\n false,\n polarity,\n outerExplicitHC,\n );\n if (f <= 0) return normal;\n const hc = resolveContrastForMode(\n pairHC(spec),\n true,\n polarity,\n outerExplicitHC,\n );\n if (f >= 1) return hc;\n if (normal.metric !== hc.metric) {\n throw new Error(\n `glaze: a \"contrast\" pair cannot switch metric between its normal ` +\n `(${normal.metric}) and high-contrast (${hc.metric}) entry — the two ` +\n `targets are on different scales. Use one metric for both entries.`,\n );\n }\n // Spread `normal` so the WCAG branch keeps its absent `polarity` and the\n // APCA branch its resolved one.\n return { ...normal, target: lerp(normal.target, hc.target, f) };\n}\n\n// ============================================================================\n// APCA (SAPC / APCA-W3 0.1.9 simplified)\n// ============================================================================\n\nconst APCA_EXPONENTS = {\n mainTRC: 2.4,\n normBG: 0.56,\n normTXT: 0.57,\n revTXT: 0.62,\n revBG: 0.65,\n};\nconst APCA_BLACK_THRESH = 0.022;\nconst APCA_BLACK_CLIP = 1.414;\nconst APCA_DELTA_Y_MIN = 0.0005;\nconst APCA_SCALE = 1.14;\nconst APCA_LO_OFFSET = 0.027;\n\nfunction apcaSoftClamp(y: number): number {\n const yc = Math.max(0, y);\n if (yc >= APCA_BLACK_THRESH) return yc;\n return yc + Math.pow(APCA_BLACK_THRESH - yc, APCA_BLACK_CLIP);\n}\n\n/**\n * APCA lightness contrast (Lc), signed: positive for dark text on light bg,\n * negative for light text on dark bg. Inputs are screen luminances (0–1).\n */\nexport function apcaContrast(yText: number, yBg: number): number {\n const txt = apcaSoftClamp(yText);\n const bg = apcaSoftClamp(yBg);\n\n if (Math.abs(bg - txt) < APCA_DELTA_Y_MIN) return 0;\n\n let sapc: number;\n if (bg > txt) {\n // Normal polarity: dark text on light bg.\n sapc =\n (Math.pow(bg, APCA_EXPONENTS.normBG) -\n Math.pow(txt, APCA_EXPONENTS.normTXT)) *\n APCA_SCALE;\n return sapc < 0.1 ? 0 : (sapc - APCA_LO_OFFSET) * 100;\n }\n // Reverse polarity: light text on dark bg.\n sapc =\n (Math.pow(bg, APCA_EXPONENTS.revBG) -\n Math.pow(txt, APCA_EXPONENTS.revTXT)) *\n APCA_SCALE;\n return sapc > -0.1 ? 0 : (sapc + APCA_LO_OFFSET) * 100;\n}\n\n// ============================================================================\n// Tone -> luminance (cached)\n// ============================================================================\n\nconst CACHE_SIZE = 512;\nconst luminanceCache = new Map<string, number>();\nconst cacheOrder: string[] = [];\n\n/**\n * Luminance of an OKHST color `(h, s, t)` with t in 0–1 (reference eps), in\n * the metric's luminance basis. The metric is part of the cache key because\n * WCAG and APCA derive different luminances from the same color.\n */\nfunction cachedLuminance(\n metric: ContrastMetric,\n h: number,\n s: number,\n t: number,\n pastel: boolean,\n): number {\n const tRounded = Math.round(t * 10000) / 10000;\n const key = `${metric}|${h}|${s}|${tRounded}|${pastel}`;\n\n const cached = luminanceCache.get(key);\n if (cached !== undefined) return cached;\n\n const l = fromTone(tRounded * 100, REF_EPS);\n const linearRgb = okhslToLinearSrgb(h, s, l, pastel);\n const y = metricLuminance(metric, linearRgb);\n\n if (luminanceCache.size >= CACHE_SIZE) {\n const evict = cacheOrder.shift()!;\n luminanceCache.delete(evict);\n }\n luminanceCache.set(key, y);\n cacheOrder.push(key);\n\n return y;\n}\n\n// ============================================================================\n// Metric evaluation\n// ============================================================================\n\n/**\n * Score a candidate luminance against the base for a metric. Returns a value\n * that is `>= target` exactly when the floor is met (WCAG ratio, or APCA Lc\n * magnitude). For APCA, `polarity` selects the argument order: `'fg'` (the\n * default) treats the candidate as the text against a background base\n * (`apcaContrast(yCandidate, yBase)`); `'bg'` treats the candidate as the\n * background (`apcaContrast(yBase, yCandidate)`). The magnitude is taken\n * either way. WCAG is symmetric, so polarity is ignored there.\n */\nfunction metricScore(\n metric: 'wcag' | 'apca',\n yCandidate: number,\n yBase: number,\n polarity?: 'fg' | 'bg',\n): number {\n if (metric === 'wcag') return contrastRatioFromLuminance(yCandidate, yBase);\n const lc =\n polarity === 'bg'\n ? apcaContrast(yBase, yCandidate)\n : apcaContrast(yCandidate, yBase);\n return Math.abs(lc);\n}\n\n// ============================================================================\n// Solver\n// ============================================================================\n\nexport interface FindToneForContrastOptions {\n /** Hue of the candidate color (0–360). */\n hue: number;\n /** Saturation of the candidate color (0–1). */\n saturation: number;\n /** Preferred tone of the candidate (0–1). */\n preferredTone: number;\n\n /** Base/reference color as linear sRGB. */\n baseLinearRgb: LinearRgb;\n\n /** Resolved contrast floor (metric + target). */\n contrast: ResolvedContrast;\n\n /** Search bounds for tone. Default: [0, 1]. */\n toneRange?: [number, number];\n /** Convergence threshold. Default: 1e-4. */\n epsilon?: number;\n /** Maximum binary-search iterations per branch. Default: 18. */\n maxIterations?: number;\n /** Preferred search direction before auto-flip is considered. */\n initialDirection?: 'lighter' | 'darker';\n /** Auto-flip tone direction when contrast can't be met. Default: false. */\n flip?: boolean;\n /**\n * When `flip` is on and *both* directions meet the target, keep\n * `initialDirection` instead of taking whichever result lands nearer the\n * preferred tone. Default: false (nearest wins).\n *\n * The nearest-wins tie-break is unstable along a ramp of targets: which side\n * is nearer shifts as the target grows, so a color can swap sides between two\n * adjacent targets. Set this when a caller needs the side to be a property of\n * the color rather than of the target — the manual contrast level does. The\n * flip itself is unaffected: an initial direction that cannot reach the\n * target still falls back to the opposite side.\n */\n preferInitial?: boolean;\n /** Use the hue-independent \"safe\" chroma boundary. Default: false. */\n pastel?: boolean;\n}\n\nexport interface FindToneForContrastResult {\n /** Chosen tone in 0–1. */\n tone: number;\n /** Achieved score (WCAG ratio or APCA Lc magnitude). */\n contrast: number;\n /** Whether the target was reached. */\n met: boolean;\n /** Which branch was selected. */\n branch: 'lighter' | 'darker' | 'preferred';\n /** Whether the result auto-flipped to the opposite direction. */\n flipped?: boolean;\n}\n\n/**\n * Result of a single one-dimensional branch search. `pos` is the chosen\n * coordinate (tone or mix value depending on the caller's domain).\n */\ninterface BranchResult {\n pos: number;\n contrast: number;\n met: boolean;\n}\n\n/**\n * Binary search one branch `[lo, hi]` for the position nearest to `anchor`\n * that meets `target`. The domain is whatever `lum` interprets (tone 0–1 or\n * mix parameter 0–1); the search is identical in both cases.\n */\nfunction searchBranch(\n lum: (x: number) => number,\n lo: number,\n hi: number,\n yBase: number,\n metric: 'wcag' | 'apca',\n target: number,\n epsilon: number,\n maxIter: number,\n anchor: number,\n polarity?: 'fg' | 'bg',\n): BranchResult {\n const scoreLo = metricScore(metric, lum(lo), yBase, polarity);\n const scoreHi = metricScore(metric, lum(hi), yBase, polarity);\n\n if (scoreLo < target && scoreHi < target) {\n return scoreLo >= scoreHi\n ? { pos: lo, contrast: scoreLo, met: false }\n : { pos: hi, contrast: scoreHi, met: false };\n }\n\n let low = lo;\n let high = hi;\n\n for (let i = 0; i < maxIter; i++) {\n if (high - low < epsilon) break;\n const mid = (low + high) / 2;\n const scoreMid = metricScore(metric, lum(mid), yBase, polarity);\n\n if (scoreMid >= target) {\n if (mid < anchor) low = mid;\n else high = mid;\n } else {\n if (mid < anchor) high = mid;\n else low = mid;\n }\n }\n\n const scoreLow = metricScore(metric, lum(low), yBase, polarity);\n const scoreHigh = metricScore(metric, lum(high), yBase, polarity);\n const lowPasses = scoreLow >= target;\n const highPasses = scoreHigh >= target;\n\n if (lowPasses && highPasses) {\n return Math.abs(low - anchor) <= Math.abs(high - anchor)\n ? { pos: low, contrast: scoreLow, met: true }\n : { pos: high, contrast: scoreHigh, met: true };\n }\n if (lowPasses) return { pos: low, contrast: scoreLow, met: true };\n if (highPasses) return { pos: high, contrast: scoreHigh, met: true };\n\n return scoreLow >= scoreHigh\n ? { pos: low, contrast: scoreLow, met: false }\n : { pos: high, contrast: scoreHigh, met: false };\n}\n\n/**\n * Closed-form WCAG tone seed: the gray tone whose luminance produces exactly\n * the target ratio against the base, on the requested side. Used to bias the\n * preferred tone before the search so chromatic refinement starts close.\n */\nfunction wcagToneSeed(yBase: number, target: number, darker: boolean): number {\n const yTarget = darker\n ? (yBase + 0.05) / target - 0.05\n : target * (yBase + 0.05) - 0.05;\n const yClamped = Math.max(0, Math.min(1, yTarget));\n return Math.max(0, Math.min(1, toneFromY(yClamped, REF_EPS) / 100));\n}\n\n/**\n * Shared \"find the nearest passing position\" core for both the tone and mix\n * solvers. Both pick an initial direction within `[lo, hi]`, binary-search\n * that branch, optionally flip to the opposite branch, and pin to the\n * initial extreme on failure — they only differ in their domain and how the\n * branch boundary / luminance closure are built.\n *\n * `searchAnchor` biases the branch boundary and the in-branch tiebreak (the\n * WCAG seed for the tone solver; `preferred` otherwise). `distanceAnchor`\n * is the position the flip step measures closeness against (the original\n * preferred position, before any seed bias).\n */\ninterface SolveCoreOptions {\n lum: (x: number) => number;\n yBase: number;\n metric: 'wcag' | 'apca';\n target: number;\n searchTarget: number;\n lo: number;\n hi: number;\n /** Branch-boundary + in-branch tiebreak anchor. */\n searchAnchor: number;\n /** Position the flip step minimizes distance to. */\n distanceAnchor: number;\n epsilon: number;\n maxIterations: number;\n flip: boolean;\n /** Keep the initial branch when both meet, instead of taking the nearest. */\n preferInitial: boolean;\n /** Force the first branch ('lower' searches `[lo, anchor]`). */\n initialIsLower: boolean;\n /** APCA argument order; ignored for WCAG. Default `'fg'`. */\n polarity?: 'fg' | 'bg';\n}\n\ninterface SolveCoreResult {\n pos: number;\n contrast: number;\n met: boolean;\n /** Which branch produced the result. */\n lower: boolean;\n flipped?: boolean;\n}\n\nfunction solveNearestContrast(opts: SolveCoreOptions): SolveCoreResult {\n const {\n lum,\n yBase,\n metric,\n target,\n searchTarget,\n lo,\n hi,\n searchAnchor,\n distanceAnchor,\n epsilon,\n maxIterations,\n flip,\n preferInitial,\n initialIsLower,\n polarity,\n } = opts;\n\n const runBranch = (lower: boolean): BranchResult =>\n lower\n ? searchBranch(\n lum,\n lo,\n searchAnchor,\n yBase,\n metric,\n searchTarget,\n epsilon,\n maxIterations,\n searchAnchor,\n polarity,\n )\n : searchBranch(\n lum,\n searchAnchor,\n hi,\n yBase,\n metric,\n searchTarget,\n epsilon,\n maxIterations,\n searchAnchor,\n polarity,\n );\n\n const initialResult = runBranch(initialIsLower);\n initialResult.met = initialResult.contrast >= target;\n\n if (initialResult.met && !flip) {\n return { ...initialResult, lower: initialIsLower };\n }\n\n if (flip) {\n // The opposite branch exists only when `distanceAnchor` is strictly\n // interior on that side (matches the legacy canDarker/canUpper guards).\n const canOpposite = initialIsLower\n ? distanceAnchor < hi\n : distanceAnchor > lo;\n const oppositeResult = canOpposite ? runBranch(!initialIsLower) : null;\n if (oppositeResult) oppositeResult.met = oppositeResult.contrast >= target;\n\n if (initialResult.met && oppositeResult?.met) {\n if (preferInitial) return { ...initialResult, lower: initialIsLower };\n const initialDist = Math.abs(initialResult.pos - distanceAnchor);\n const oppositeDist = Math.abs(oppositeResult.pos - distanceAnchor);\n return initialDist <= oppositeDist\n ? { ...initialResult, lower: initialIsLower }\n : { ...oppositeResult, lower: !initialIsLower, flipped: true };\n }\n if (initialResult.met) return { ...initialResult, lower: initialIsLower };\n if (oppositeResult?.met) {\n return { ...oppositeResult, lower: !initialIsLower, flipped: true };\n }\n }\n\n // Failure: pin to the initial direction's extreme.\n const extreme = initialIsLower ? lo : hi;\n const scoreExtreme = metricScore(metric, lum(extreme), yBase, polarity);\n return {\n pos: extreme,\n contrast: scoreExtreme,\n met: false,\n lower: initialIsLower,\n };\n}\n\n/**\n * Find the tone that satisfies a contrast floor against a base color,\n * staying as close to `preferredTone` as possible.\n */\nexport function findToneForContrast(\n options: FindToneForContrastOptions,\n): FindToneForContrastResult {\n const {\n hue,\n saturation,\n preferredTone,\n baseLinearRgb,\n contrast,\n toneRange = [0, 1],\n epsilon = 1e-4,\n maxIterations = 18,\n pastel = false,\n } = options;\n\n const { metric, target, polarity } = contrast;\n // Overshoot absorbs rounding in the OKHSL/OKLCH formatting pipeline.\n const searchTarget = metric === 'wcag' ? target * 1.01 : target + 0.5;\n const yBase = metricLuminance(metric, baseLinearRgb);\n\n // Luminance of a candidate at tone `t`.\n const lum = (t: number): number =>\n cachedLuminance(metric, hue, saturation, t, pastel);\n\n const scorePref = metricScore(metric, lum(preferredTone), yBase, polarity);\n\n if (scorePref >= searchTarget) {\n return {\n tone: preferredTone,\n contrast: scorePref,\n met: true,\n branch: 'preferred',\n };\n }\n\n const [minT, maxT] = toneRange;\n const canDarker = preferredTone > minT;\n const canLighter = preferredTone < maxT;\n\n let initialIsDarker: boolean;\n if (options.initialDirection !== undefined) {\n initialIsDarker = options.initialDirection === 'darker';\n } else if (canDarker && !canLighter) {\n initialIsDarker = true;\n } else if (!canDarker && canLighter) {\n initialIsDarker = false;\n } else if (!canDarker && !canLighter) {\n return {\n tone: preferredTone,\n contrast: scorePref,\n met: false,\n branch: 'preferred',\n };\n } else {\n const scoreMin = metricScore(metric, lum(minT), yBase, polarity);\n const scoreMax = metricScore(metric, lum(maxT), yBase, polarity);\n initialIsDarker = scoreMin >= scoreMax;\n }\n\n // For WCAG, bias the search start toward the closed-form seed (darker =\n // the \"lower\" branch). The flip step still measures distance against the\n // original `preferredTone`, not the seed.\n const searchAnchor =\n metric === 'wcag'\n ? clamp(\n initialIsDarker\n ? Math.min(preferredTone, wcagToneSeed(yBase, target, true))\n : Math.max(preferredTone, wcagToneSeed(yBase, target, false)),\n minT,\n maxT,\n )\n : preferredTone;\n\n const solved = solveNearestContrast({\n lum,\n yBase,\n metric,\n target,\n searchTarget,\n lo: minT,\n hi: maxT,\n searchAnchor,\n distanceAnchor: preferredTone,\n epsilon,\n maxIterations,\n flip: options.flip ?? false,\n preferInitial: options.preferInitial ?? false,\n initialIsLower: initialIsDarker,\n polarity,\n });\n\n return {\n tone: solved.pos,\n contrast: solved.contrast,\n met: solved.met,\n branch: solved.lower ? 'darker' : 'lighter',\n ...(solved.flipped ? { flipped: true } : {}),\n };\n}\n\n// ============================================================================\n// Mix contrast solver\n// ============================================================================\n\nexport interface FindValueForMixContrastOptions {\n /** Preferred mix parameter (0–1). */\n preferredValue: number;\n /** Base color as linear sRGB. */\n baseLinearRgb: LinearRgb;\n /** Target color as linear sRGB. */\n targetLinearRgb: LinearRgb;\n /** Resolved contrast floor (metric + target). */\n contrast: ResolvedContrast;\n /** Compute the luminance of the mixed color at parameter t. */\n luminanceAtValue: (t: number) => number;\n /** Convergence threshold. Default: 1e-4. */\n epsilon?: number;\n /** Maximum binary-search iterations per branch. Default: 20. */\n maxIterations?: number;\n /** Auto-flip mix direction when contrast can't be met. Default: false. */\n flip?: boolean;\n}\n\nexport interface FindValueForMixContrastResult {\n value: number;\n contrast: number;\n met: boolean;\n flipped?: boolean;\n}\n\n/**\n * Find the mix parameter (ratio or opacity) that satisfies a contrast floor\n * against a base color, staying as close to `preferredValue` as possible.\n */\nexport function findValueForMixContrast(\n options: FindValueForMixContrastOptions,\n): FindValueForMixContrastResult {\n const {\n preferredValue,\n baseLinearRgb,\n contrast,\n luminanceAtValue,\n epsilon = 1e-4,\n maxIterations = 20,\n } = options;\n\n const { metric, target, polarity } = contrast;\n const searchTarget = metric === 'wcag' ? target * 1.01 : target + 0.5;\n const yBase = metricLuminance(metric, baseLinearRgb);\n\n const scorePref = metricScore(\n metric,\n luminanceAtValue(preferredValue),\n yBase,\n polarity,\n );\n if (scorePref >= searchTarget) {\n return { value: preferredValue, contrast: scorePref, met: true };\n }\n\n const canLower = preferredValue > 0;\n const canUpper = preferredValue < 1;\n let initialIsLower: boolean;\n if (canLower && !canUpper) {\n initialIsLower = true;\n } else if (!canLower && canUpper) {\n initialIsLower = false;\n } else if (!canLower && !canUpper) {\n return { value: preferredValue, contrast: scorePref, met: false };\n } else {\n const scoreLower = metricScore(\n metric,\n luminanceAtValue(0),\n yBase,\n polarity,\n );\n const scoreUpper = metricScore(\n metric,\n luminanceAtValue(1),\n yBase,\n polarity,\n );\n initialIsLower = scoreLower >= scoreUpper;\n }\n\n const solved = solveNearestContrast({\n lum: luminanceAtValue,\n yBase,\n metric,\n target,\n searchTarget,\n lo: 0,\n hi: 1,\n searchAnchor: preferredValue,\n distanceAnchor: preferredValue,\n epsilon,\n maxIterations,\n flip: options.flip ?? false,\n // A mix searches along the base→target segment rather than across a base,\n // so the nearest-wins tie-break has no side to swap; left as-is.\n preferInitial: false,\n initialIsLower,\n polarity,\n });\n\n return {\n value: solved.pos,\n contrast: solved.contrast,\n met: solved.met,\n ...(solved.flipped ? { flipped: true } : {}),\n };\n}\n","/**\n * Semantic color role resolution.\n *\n * A `role` fixes APCA contrast polarity (which side is the foreground vs the\n * background). Roles are resolved per color via a four-step chain (see\n * `resolveRole`): explicit `def.role` → name inference → opposite of the\n * base's role → `'text'` foreground default.\n *\n * This module owns the alias keyword sets, name tokenization, and the\n * role → polarity / opposite-role mappings. It has no dependencies.\n */\n\nimport type { Role, RoleInput } from './types';\n\n// ============================================================================\n// Keyword sets\n// ============================================================================\n\nconst SURFACE_KEYWORDS = new Set([\n 'surface',\n 'bg',\n 'background',\n 'fill',\n 'canvas',\n 'paper',\n 'layer',\n]);\n\nconst TEXT_KEYWORDS = new Set([\n 'text',\n 'fg',\n 'foreground',\n 'content',\n 'ink',\n 'label',\n 'stroke',\n]);\n\nconst BORDER_KEYWORDS = new Set([\n 'border',\n 'divider',\n 'outline',\n 'separator',\n 'hairline',\n 'rule',\n]);\n\nconst ALIAS_TO_ROLE: Record<string, Role> = {\n // surface\n surface: 'surface',\n bg: 'surface',\n background: 'surface',\n fill: 'surface',\n canvas: 'surface',\n paper: 'surface',\n layer: 'surface',\n // text\n text: 'text',\n fg: 'text',\n foreground: 'text',\n content: 'text',\n ink: 'text',\n label: 'text',\n stroke: 'text',\n // border\n border: 'border',\n divider: 'border',\n outline: 'border',\n separator: 'border',\n hairline: 'border',\n rule: 'border',\n};\n\n// ============================================================================\n// Normalization\n// ============================================================================\n\n/**\n * Normalize a `RoleInput` (canonical value or alias) into a canonical `Role`.\n * Returns `undefined` for unrecognized strings so callers can fall through to\n * the next step of the resolution chain.\n */\nexport function normalizeRole(input: RoleInput | undefined): Role | undefined {\n if (input === undefined) return undefined;\n return ALIAS_TO_ROLE[input];\n}\n\n// ============================================================================\n// Name inference\n// ============================================================================\n\n/**\n * Tokenize a color name into lowercase keyword tokens, splitting on\n * non-alphanumeric boundaries and at camelCase boundaries. Examples:\n * - `'button-text'` → `['button', 'text']`\n * - `'inputBg'` → `['input', 'bg']`\n * - `'card_border-outline'` → `['card', 'border', 'outline']`\n */\nfunction tokenizeName(name: string): string[] {\n // Split on non-alphanumeric, then split camelCase within each piece.\n const pieces = name.split(/[^0-9a-zA-Z]+/).filter(Boolean);\n const tokens: string[] = [];\n for (const piece of pieces) {\n // Split at the boundary between a lowercase/digit run and an uppercase\n // letter (camelCase humps), e.g. \"inputBg\" → [\"input\", \"Bg\"].\n const sub = piece\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\n .split(/\\s+/)\n .filter(Boolean);\n for (const s of sub) tokens.push(s.toLowerCase());\n }\n return tokens;\n}\n\n/**\n * Infer a `Role` from a color name by matching its tokens against the role\n * keyword sets. When multiple tokens match, the **last** recognized token\n * wins (so `button-text` → `text`, `input-bg` → `surface`, `card-border` →\n * `border`). Returns `undefined` when no token matches.\n */\nexport function inferRoleFromName(name: string): Role | undefined {\n const tokens = tokenizeName(name);\n let inferred: Role | undefined;\n for (const token of tokens) {\n if (SURFACE_KEYWORDS.has(token)) inferred = 'surface';\n else if (TEXT_KEYWORDS.has(token)) inferred = 'text';\n else if (BORDER_KEYWORDS.has(token)) inferred = 'border';\n }\n return inferred;\n}\n\n// ============================================================================\n// Polarity + opposites\n// ============================================================================\n\n/** APCA argument order: which side the resolved color plays. */\nexport type Polarity = 'fg' | 'bg';\n\n/**\n * Map a role to its APCA polarity. `text` and `border` are foreground spots\n * against their base (the candidate is the text argument); `surface` is the\n * background (the base is the text argument).\n */\nexport function roleToPolarity(role: Role): Polarity {\n return role === 'surface' ? 'bg' : 'fg';\n}\n\n/**\n * The opposite role of `role`, used when a color with no explicit role and no\n * inferable name depends on a base: the dependent color plays the opposite\n * role of its base. `surface` ↔ `text`; `border` is treated as a foreground\n * spot, so its opposite is `surface`.\n */\nexport function oppositeRole(role: Role): Role {\n if (role === 'surface') return 'text';\n return 'surface';\n}\n","/**\n * Shadow color computation.\n *\n * Owns the shadow / mix def predicates, default tuning constants, the\n * tuning merge, and the actual `computeShadow` math (hue blend,\n * saturation cap, lightness clamp, alpha curve). The resolver consumes\n * this module per scheme variant.\n */\n\nimport { clamp } from './hc-pair';\nimport type {\n ColorDef,\n MixColorDef,\n ShadowColorDef,\n ShadowTuning,\n} from './types';\n\n/**\n * OKHSL-lightness variant shape used by the shadow math. The resolver\n * converts the OKHST-stored variants to this shape at the shadow edge.\n */\nexport interface OkhslShadowVariant {\n h: number;\n s: number;\n l: number;\n alpha: number;\n}\n\nexport function isShadowDef(def: ColorDef): def is ShadowColorDef {\n return (def as ShadowColorDef).type === 'shadow';\n}\n\nexport function isMixDef(def: ColorDef): def is MixColorDef {\n return (def as MixColorDef).type === 'mix';\n}\n\nexport const DEFAULT_SHADOW_TUNING: Required<ShadowTuning> = {\n saturationFactor: 0.18,\n maxSaturation: 0.25,\n lightnessFactor: 0.25,\n lightnessBounds: [0.05, 0.2],\n minGapTarget: 0.05,\n alphaMax: 1.0,\n bgHueBlend: 0.2,\n};\n\nexport function resolveShadowTuning(\n perColor?: ShadowTuning,\n globalTuning?: ShadowTuning,\n): Required<ShadowTuning> {\n return {\n ...DEFAULT_SHADOW_TUNING,\n ...globalTuning,\n ...perColor,\n lightnessBounds:\n perColor?.lightnessBounds ??\n globalTuning?.lightnessBounds ??\n DEFAULT_SHADOW_TUNING.lightnessBounds,\n };\n}\n\nexport function circularLerp(a: number, b: number, t: number): number {\n let diff = b - a;\n if (diff > 180) diff -= 360;\n else if (diff < -180) diff += 360;\n return (((a + diff * t) % 360) + 360) % 360;\n}\n\n/**\n * Compute the canonical max-contrast reference t value for normalization.\n * Uses bg.l=1, fg.l=0, intensity=100 — the theoretical maximum.\n * This is a fixed constant per tuning configuration, ensuring uniform\n * scaling across all bg/fg pairs at low intensities.\n */\nfunction computeRefT(tuning: Required<ShadowTuning>): number {\n const EPSILON = 1e-6;\n let lShRef = clamp(\n tuning.lightnessFactor,\n tuning.lightnessBounds[0],\n tuning.lightnessBounds[1],\n );\n lShRef = Math.max(Math.min(lShRef, 1 - tuning.minGapTarget), 0);\n const gapRef = Math.max(1 - lShRef, EPSILON);\n return 1 / gapRef;\n}\n\nexport function computeShadow(\n bg: OkhslShadowVariant,\n fg: OkhslShadowVariant | undefined,\n intensity: number,\n tuning: Required<ShadowTuning>,\n): OkhslShadowVariant {\n const EPSILON = 1e-6;\n const clampedIntensity = clamp(intensity, 0, 100);\n const contrastWeight = fg ? Math.abs(bg.l - fg.l) : 1;\n const deltaL = (clampedIntensity / 100) * contrastWeight;\n\n const h = fg ? circularLerp(fg.h, bg.h, tuning.bgHueBlend) : bg.h;\n const s = fg\n ? Math.min(fg.s * tuning.saturationFactor, tuning.maxSaturation)\n : 0;\n\n let lSh = clamp(\n bg.l * tuning.lightnessFactor,\n tuning.lightnessBounds[0],\n tuning.lightnessBounds[1],\n );\n lSh = Math.max(Math.min(lSh, bg.l - tuning.minGapTarget), 0);\n\n const gap = Math.max(bg.l - lSh, EPSILON);\n const t = deltaL / gap;\n\n const tRef = computeRefT(tuning);\n const norm = Math.tanh(tRef / tuning.alphaMax);\n const alpha = Math.min(\n (tuning.alphaMax * Math.tanh(t / tuning.alphaMax)) / norm,\n tuning.alphaMax,\n );\n\n return { h, s, l: lSh, alpha };\n}\n","/**\n * Color graph validation and topological sort.\n *\n * `validateColorDefs` rejects bad references (missing / shadow-referencing /\n * base/contrast/tone mismatches) and detects cycles before the\n * resolver runs. `topoSort` orders defs so each color is processed after\n * its base / bg / fg / target dependencies.\n */\n\nimport { extractOkhslFromValue } from './color-value';\nimport { contrastMetricOf } from './contrast-solver';\nimport { isAbsoluteTone, pairHC, pairNormal } from './hc-pair';\nimport { isMixDef, isShadowDef } from './shadow';\nimport type {\n ColorMap,\n ContrastSpec,\n HCPair,\n RegularColorDef,\n ResolvedColor,\n} from './types';\n\n/**\n * Does this color sit at an absolute tone — either authored, or carried by a\n * `from` value? That is the test for \"root\" (placed on its own) as opposed to\n * \"dependent\" (placed relative to a base), and it is what lets a bare\n * `{ from: '#2F5BFF' }` stand as a complete color definition.\n */\nexport function hasAbsoluteTone(def: RegularColorDef): boolean {\n if (def.tone === undefined) return def.from !== undefined;\n return isAbsoluteTone(def.tone);\n}\n\n/**\n * Reject a `contrast` pair whose two entries measure in different metrics.\n *\n * A WCAG ratio and an APCA Lc are different scales, so `[4.5, { apca: 75 }]`\n * asks one color to be judged two incompatible ways. There is no target between\n * them for a manual `contrastLevel` to resolve, and even in `'auto'` mode the\n * two variants become incomparable. Pick one metric and pair its values\n * instead: `{ wcag: [4.5, 7] }` or `{ apca: [60, 90] }`.\n */\nfunction assertConsistentContrastMetric(\n name: string,\n contrast: HCPair<ContrastSpec> | undefined,\n): void {\n if (contrast === undefined || !Array.isArray(contrast)) return;\n const normal = contrastMetricOf(pairNormal(contrast));\n const hc = contrastMetricOf(pairHC(contrast));\n if (normal === hc) return;\n throw new Error(\n `glaze: color \"${name}\" has a \"contrast\" pair that switches metric ` +\n `(${normal} → ${hc}). A WCAG ratio and an APCA Lc are different scales; ` +\n `use one metric for both entries, e.g. { ${normal}: [normal, highContrast] }.`,\n );\n}\n\nexport function validateColorDefs(\n defs: ColorMap,\n externalBases?: Map<string, ResolvedColor>,\n): void {\n const localNames = new Set(Object.keys(defs));\n const allNames = new Set([\n ...localNames,\n ...(externalBases ? externalBases.keys() : []),\n ]);\n\n for (const [name, def] of Object.entries(defs)) {\n if (isShadowDef(def)) {\n if (!allNames.has(def.bg)) {\n throw new Error(\n `glaze: shadow \"${name}\" references non-existent bg \"${def.bg}\".`,\n );\n }\n if (localNames.has(def.bg) && isShadowDef(defs[def.bg])) {\n throw new Error(\n `glaze: shadow \"${name}\" bg \"${def.bg}\" references another shadow color.`,\n );\n }\n if (def.fg !== undefined) {\n if (!allNames.has(def.fg)) {\n throw new Error(\n `glaze: shadow \"${name}\" references non-existent fg \"${def.fg}\".`,\n );\n }\n if (localNames.has(def.fg) && isShadowDef(defs[def.fg])) {\n throw new Error(\n `glaze: shadow \"${name}\" fg \"${def.fg}\" references another shadow color.`,\n );\n }\n }\n continue;\n }\n\n if (isMixDef(def)) {\n if (!allNames.has(def.base)) {\n throw new Error(\n `glaze: mix \"${name}\" references non-existent base \"${def.base}\".`,\n );\n }\n if (!allNames.has(def.target)) {\n throw new Error(\n `glaze: mix \"${name}\" references non-existent target \"${def.target}\".`,\n );\n }\n if (localNames.has(def.base) && isShadowDef(defs[def.base])) {\n throw new Error(\n `glaze: mix \"${name}\" base \"${def.base}\" references a shadow color.`,\n );\n }\n if (localNames.has(def.target) && isShadowDef(defs[def.target])) {\n throw new Error(\n `glaze: mix \"${name}\" target \"${def.target}\" references a shadow color.`,\n );\n }\n assertConsistentContrastMetric(name, def.contrast);\n continue;\n }\n\n const regDef = def as RegularColorDef;\n\n assertConsistentContrastMetric(name, regDef.contrast);\n\n // Parse `from` here rather than letting the resolver hit it. The parser's own\n // error names the offending string but not the color it came from, which in a\n // palette of fifty tokens is the half you actually need.\n if (regDef.from !== undefined) {\n try {\n extractOkhslFromValue(regDef.from);\n } catch (error) {\n throw new Error(\n `glaze: color \"${name}\" has an invalid \"from\" value. ${\n error instanceof Error ? error.message : String(error)\n }`,\n { cause: error },\n );\n }\n }\n\n if (regDef.contrast !== undefined && !regDef.base) {\n throw new Error(`glaze: color \"${name}\" has \"contrast\" without \"base\".`);\n }\n\n if (\n regDef.tone !== undefined &&\n !isAbsoluteTone(regDef.tone) &&\n !regDef.base\n ) {\n throw new Error(\n `glaze: color \"${name}\" has relative \"tone\" without \"base\".`,\n );\n }\n\n if (regDef.base && !allNames.has(regDef.base)) {\n throw new Error(\n `glaze: color \"${name}\" references non-existent base \"${regDef.base}\".`,\n );\n }\n\n if (\n regDef.base &&\n localNames.has(regDef.base) &&\n isShadowDef(defs[regDef.base])\n ) {\n throw new Error(\n `glaze: color \"${name}\" base \"${regDef.base}\" references a shadow color.`,\n );\n }\n\n if (!hasAbsoluteTone(regDef) && regDef.base === undefined) {\n throw new Error(\n `glaze: color \"${name}\" must have either absolute \"tone\" (root), \"from\" (a literal color), or \"base\" (dependent).`,\n );\n }\n\n if (regDef.contrast !== undefined && regDef.opacity !== undefined) {\n console.warn(\n `glaze: color \"${name}\" has both \"contrast\" and \"opacity\". Opacity makes perceived tone unpredictable.`,\n );\n }\n }\n\n // Check for circular references (follows base, bg, fg edges).\n // External bases are leaves (no outgoing edges in `defs`), so they can't\n // form a cycle and we short-circuit there.\n const visited = new Set<string>();\n const inStack = new Set<string>();\n\n function dfs(name: string): void {\n if (!localNames.has(name)) return;\n if (inStack.has(name)) {\n throw new Error(\n `glaze: circular base reference detected involving \"${name}\".`,\n );\n }\n if (visited.has(name)) return;\n\n inStack.add(name);\n const def = defs[name];\n if (isShadowDef(def)) {\n dfs(def.bg);\n if (def.fg) dfs(def.fg);\n } else if (isMixDef(def)) {\n dfs(def.base);\n dfs(def.target);\n } else {\n const regDef = def as RegularColorDef;\n if (regDef.base) {\n dfs(regDef.base);\n }\n }\n inStack.delete(name);\n visited.add(name);\n }\n\n for (const name of localNames) {\n dfs(name);\n }\n}\n\nexport function topoSort(defs: ColorMap): string[] {\n const result: string[] = [];\n const visited = new Set<string>();\n\n function visit(name: string): void {\n if (visited.has(name)) return;\n visited.add(name);\n\n const def = defs[name];\n // External base references (not in `defs`) are leaves — they're already\n // pre-seeded into `ctx.resolved` and don't participate in the local sort.\n if (def === undefined) return;\n if (isShadowDef(def)) {\n visit(def.bg);\n if (def.fg) visit(def.fg);\n } else if (isMixDef(def)) {\n visit(def.base);\n visit(def.target);\n } else {\n const regDef = def as RegularColorDef;\n if (regDef.base) {\n visit(regDef.base);\n }\n }\n\n result.push(name);\n }\n\n for (const name of Object.keys(defs)) {\n visit(name);\n }\n\n return result;\n}\n","/**\n * Contrast-warning dispatcher.\n *\n * Tokens memoize their resolution, but a long-lived process (e.g. a dev\n * server with HMR) can re-resolve the same theme many times. The cache\n * here dedupes warnings within a session with a soft cap to keep noise\n * bounded.\n */\n\nimport { apcaContrast } from './contrast-solver';\nimport type { ResolvedContrast } from './contrast-solver';\nimport { contrastRatioFromLuminance } from './okhsl-color-math';\n\nconst CONTRAST_WARN_CACHE_LIMIT = 256;\nconst contrastWarnCache = new Set<string>();\n\n/**\n * Slack factor below the requested target before we emit a warning.\n * The contrast solver overshoots to absorb rounding noise, so an actual\n * value within ~2x that overshoot is effectively a pass.\n */\nconst CONTRAST_WARN_SLACK_WCAG = 0.98;\n/** APCA Lc is on a 0–106 scale; allow a small absolute slack. */\nconst CONTRAST_WARN_SLACK_APCA = 1.5;\n\nfunction schemeLabel(isDark: boolean, isHighContrast: boolean): string {\n if (isDark && isHighContrast) return 'darkContrast';\n if (isDark) return 'dark';\n if (isHighContrast) return 'lightContrast';\n return 'light';\n}\n\nfunction metricLabel(c: ResolvedContrast): string {\n return c.metric === 'apca'\n ? `APCA Lc ${c.target.toFixed(1)}`\n : `WCAG ${c.target.toFixed(2)}`;\n}\n\nfunction dedupe(key: string): boolean {\n if (contrastWarnCache.has(key)) return true;\n if (contrastWarnCache.size >= CONTRAST_WARN_CACHE_LIMIT) {\n contrastWarnCache.clear();\n }\n contrastWarnCache.add(key);\n return false;\n}\n\n/** Warn when the solver could not reach the requested contrast floor. */\nexport function warnContrastUnmet(\n name: string,\n isDark: boolean,\n isHighContrast: boolean,\n contrast: ResolvedContrast,\n actual: number,\n): void {\n const slack =\n contrast.metric === 'apca'\n ? contrast.target - CONTRAST_WARN_SLACK_APCA\n : contrast.target * CONTRAST_WARN_SLACK_WCAG;\n if (actual >= slack) return;\n\n const scheme = schemeLabel(isDark, isHighContrast);\n const key = `unmet|${name}|${scheme}|${contrast.metric}|${contrast.target.toFixed(\n 2,\n )}|${actual.toFixed(2)}`;\n if (dedupe(key)) return;\n\n console.warn(\n `glaze: color \"${name}\" cannot meet ${metricLabel(contrast)} in ` +\n `${scheme} scheme (got ${actual.toFixed(2)}). ` +\n `Try widening the tone window, lowering the contrast target, ` +\n `or picking a base color further from this color's tone.`,\n );\n}\n\n/**\n * Verification (§10): a chromatic swatch inherits the gray tone's\n * lightness but drifts in real luminance, so a contrast-floored color may\n * land slightly under the contrast its tone implies. Emit an advisory\n * warning when the actual measured contrast drifts below the target.\n */\nexport function warnContrastDrift(\n name: string,\n isDark: boolean,\n isHighContrast: boolean,\n contrast: ResolvedContrast,\n yColor: number,\n yBase: number,\n): void {\n const actual =\n contrast.metric === 'apca'\n ? Math.abs(\n contrast.polarity === 'bg'\n ? apcaContrast(yBase, yColor)\n : apcaContrast(yColor, yBase),\n )\n : contrastRatioFromLuminance(yColor, yBase);\n\n const slack =\n contrast.metric === 'apca'\n ? contrast.target - CONTRAST_WARN_SLACK_APCA\n : contrast.target * CONTRAST_WARN_SLACK_WCAG;\n if (actual >= slack) return;\n\n const scheme = schemeLabel(isDark, isHighContrast);\n const key = `drift|${name}|${scheme}|${contrast.metric}|${contrast.target.toFixed(\n 2,\n )}|${actual.toFixed(2)}`;\n if (dedupe(key)) return;\n\n console.warn(\n `glaze: color \"${name}\" drifts below ${metricLabel(contrast)} in ` +\n `${scheme} scheme (measured ${actual.toFixed(2)}). Chromatic luminance ` +\n `differs from the gray tone; nudge the tone or saturation if the floor matters.`,\n );\n}\n","/**\n * Color resolution engine.\n *\n * Runs the four-pass solver (light → light-HC → dark → dark-HC) that\n * turns a `ColorMap` into a fully resolved `ResolvedColor` per name. A manual\n * `contrastLevel` interpolates the authored HC pairs, tone window, and contrast\n * targets at that level for the two *normal* passes only; the high-contrast\n * passes bypass the level entirely, so the high-contrast slots are the same\n * values `'auto'` resolves. At level 100 the normal passes already are the\n * high-contrast ones, so the solver drops to two passes (light → dark) and\n * mirrors the slots. Owns the per-scheme resolve helpers for regular, shadow,\n * and mix color defs.\n *\n * Variants are stored in OKHST: `h` / `s` are OKHSL hue/saturation and\n * `t` is the canonical contrast-uniform tone (0–1, reference eps). The\n * resolver works in tone for regular colors and converts to/from OKHSL\n * lightness only at the mix/shadow and luminance edges.\n *\n * Every function receives a single `GlazeConfigResolved` so the full\n * per-instance config (including overrides) is available without\n * re-reading the global singleton mid-resolve.\n */\n\nimport {\n okhslToLinearSrgb,\n sRGBLinearToGamma,\n srgbToOkhsl,\n} from './okhsl-color-math';\nimport {\n findToneForContrast,\n findValueForMixContrast,\n metricLuminance,\n resolveContrastForLevel,\n resolveContrastForMode,\n} from './contrast-solver';\nimport type { LinearRgb, ResolvedContrast } from './contrast-solver';\nimport {\n PAIR_SWITCH,\n clamp,\n contrastFraction,\n hcMirrorsNormal,\n numberAt,\n pairHC,\n pairNormal,\n parseToneValue,\n parseToneValueAt,\n resolveEffectiveHue,\n} from './hc-pair';\nimport {\n inferRoleFromName,\n normalizeRole,\n oppositeRole,\n roleToPolarity,\n} from './roles';\nimport {\n computeShadow,\n circularLerp,\n isMixDef,\n isShadowDef,\n resolveShadowTuning,\n} from './shadow';\nimport {\n fromTone,\n mapSaturationDark,\n mapToneForScheme,\n okhslToOkhst,\n schemeToneRange,\n toTone,\n variantToOkhsl,\n} from './okhst';\nimport { extractOkhslFromValue } from './color-value';\nimport { hasAbsoluteTone, topoSort, validateColorDefs } from './validation';\nimport { warnContrastUnmet, warnContrastDrift } from './warnings';\nimport type {\n AdaptationMode,\n ColorDef,\n ColorMap,\n ContrastSpec,\n GlazeConfigResolved,\n GlazeThemeSeed,\n HCPair,\n MixColorDef,\n RegularColorDef,\n ResolvedColor,\n ResolvedColorVariant,\n Role,\n ShadowColorDef,\n ToneValue,\n} from './types';\n\nexport interface ResolveContext extends GlazeThemeSeed {\n defs: ColorMap;\n resolved: Map<string, ResolvedColor>;\n /** Fully-merged effective config for this resolve pass. */\n config: GlazeConfigResolved;\n /** Per-name role memo (filled lazily by `resolveRole`). */\n roles: Map<string, Role>;\n}\n\ntype ResolvedField = 'light' | 'dark' | 'lightContrast' | 'darkContrast';\n\n/** An OKHSL-lightness-shaped variant used at the mix/shadow edge. */\ninterface OkhslVariant {\n h: number;\n s: number;\n l: number;\n alpha: number;\n /** Carried from the resolved variant so edge conversions reuse the right gamut. */\n pastel?: boolean;\n}\n\nexport function getSchemeVariant(\n color: ResolvedColor,\n isDark: boolean,\n isHighContrast: boolean,\n): ResolvedColorVariant {\n if (isDark && isHighContrast) return color.darkContrast;\n if (isDark) return color.dark;\n if (isHighContrast) return color.lightContrast;\n return color.light;\n}\n\n/** Edge adapter: resolved variant (`t`) → OKHSL-lightness variant. */\nfunction toOkhslVariant(v: ResolvedColorVariant): OkhslVariant {\n const c = variantToOkhsl(v);\n return { h: c.h, s: c.s, l: c.l, alpha: v.alpha, pastel: v.pastel };\n}\n\n/** Edge adapter: OKHSL-lightness variant → resolved variant (`t`). */\nfunction toToneVariant(v: OkhslVariant): ResolvedColorVariant {\n const c = okhslToOkhst({ h: v.h, s: v.s, l: v.l });\n return { h: c.h, s: c.s, t: c.t, alpha: v.alpha };\n}\n\n// ============================================================================\n// Role resolution\n// ============================================================================\n\n/**\n * Resolve the role of a base color referenced by `baseName`, returning the\n * role the *dependent* color should take (the opposite of the base's role).\n * A base that lives in `defs` recursively resolves and is inverted via\n * `oppositeRole`; an external base (no local def, e.g. an injected standalone\n * token) is treated as a background, so the dependent defaults to foreground\n * (`'text'`).\n */\nfunction resolveBaseRoleInMap(\n baseName: string | undefined,\n defs: ColorMap,\n inferRole: boolean,\n roles: Map<string, Role>,\n): Role | undefined {\n if (!baseName) return undefined;\n const baseDef = defs[baseName];\n if (!baseDef) return 'text';\n return oppositeRole(\n resolveRoleInMap(baseName, baseDef, defs, inferRole, roles),\n );\n}\n\n/**\n * Role-resolution core that does not need a full `ResolveContext`. Shared by\n * the resolver (via `resolveRole`) and `verifyContrastDrift`.\n */\nfunction resolveRoleInMap(\n name: string,\n def: ColorDef,\n defs: ColorMap,\n inferRole: boolean,\n roles: Map<string, Role>,\n): Role {\n const cached = roles.get(name);\n if (cached) return cached;\n\n let role: Role | undefined;\n if (isShadowDef(def)) {\n role = 'surface';\n } else if (isMixDef(def)) {\n role =\n normalizeRole(def.role) ??\n (inferRole ? inferRoleFromName(name) : undefined) ??\n resolveBaseRoleInMap(def.base, defs, inferRole, roles) ??\n 'text';\n } else {\n const regDef = def as RegularColorDef;\n role =\n normalizeRole(regDef.role) ??\n (inferRole ? inferRoleFromName(name) : undefined) ??\n resolveBaseRoleInMap(regDef.base, defs, inferRole, roles) ??\n 'text';\n }\n\n const finalRole = role ?? 'text';\n roles.set(name, finalRole);\n return finalRole;\n}\n\n/**\n * Resolve a color's semantic `role` (text / surface / border) per the chain:\n * 1. explicit `def.role` (normalized)\n * 2. inferred from the color name when `config.inferRole` is on\n * 3. opposite of the base's role\n * 4. `'text'` (foreground) default\n *\n * Memoized on `ctx.roles` so the four scheme passes share one resolution.\n * Shadows have no contrast participation and default to `'surface'`.\n */\nfunction resolveRole(name: string, def: ColorDef, ctx: ResolveContext): Role {\n return resolveRoleInMap(name, def, ctx.defs, ctx.config.inferRole, ctx.roles);\n}\n\nfunction resolveContrastSpec(\n spec: HCPair<ContrastSpec>,\n isHighContrast: boolean,\n config: GlazeConfigResolved,\n polarity?: 'fg' | 'bg',\n): ResolvedContrast {\n if (!isHighContrast && contrastFraction(config) !== undefined) {\n // A defined fraction proves the level is a finite number, not `'auto'`.\n return resolveContrastForLevel(\n spec,\n config.contrastLevel as number,\n polarity,\n );\n }\n const outerExplicitHC = Array.isArray(spec);\n const outer = isHighContrast ? pairHC(spec) : pairNormal(spec);\n return resolveContrastForMode(\n outer,\n isHighContrast,\n polarity,\n outerExplicitHC,\n );\n}\n\n/**\n * The authored tone for this pass: the pair's own entry in `'auto'` mode, or\n * the manual-level interpolation. Returns the parsed struct so the `kind` —\n * which selects the branch in `resolveDependentColor` — is fixed here once.\n */\nfunction passTone(\n tone: HCPair<ToneValue>,\n isHighContrast: boolean,\n config: GlazeConfigResolved,\n): { kind: 'absolute' | 'relative' | 'extreme'; value: number } {\n const f = contrastFraction(config);\n return f === undefined || isHighContrast\n ? parseToneValue(isHighContrast ? pairHC(tone) : pairNormal(tone))\n : parseToneValueAt(tone, f);\n}\n\n/** The authored numeric pair for this pass (shadow `intensity`, mix `value`). */\nfunction passNumber(\n p: HCPair<number>,\n isHighContrast: boolean,\n config: GlazeConfigResolved,\n): number {\n const f = contrastFraction(config);\n if (f === undefined || isHighContrast) {\n return isHighContrast ? pairHC(p) : pairNormal(p);\n }\n return numberAt(p, f);\n}\n\n/**\n * Apply the relative-tone delta against a base, honoring `flip`.\n *\n * When `flip` is on and `base + delta` falls outside `[0, 100]`, try mirroring\n * the delta to the other side of the base. If the mirrored target is also out\n * of range, keep the original delta so the caller clamps on the authored side.\n * When off, the caller clamps as usual.\n */\nfunction applyToneFlip(delta: number, baseTone: number, flip: boolean): number {\n if (!flip) return delta;\n const target = baseTone + delta;\n if (target >= 0 && target <= 100) return delta;\n const mirrored = baseTone - delta;\n if (mirrored >= 0 && mirrored <= 100) return -delta;\n return delta;\n}\n\n/**\n * Dark position for an extreme tone (`'max'` / `'min'`) anchored to a base.\n *\n * A windowed dark remap compresses the base→extreme span, so the pair loses\n * contrast in dark. Instead, measure the tone shift the light scheme applied\n * between the base and the extreme, then replay it against the base's dark\n * tone: `auto` mirrors the sign (both ends invert), `fixed` keeps it. The\n * result is clamped to `[0, 100]` only — crossing the dark tone window is\n * intended, since the author asked for the extreme.\n */\nfunction extremeDarkTone(\n authorTone: number,\n mode: AdaptationMode,\n isHighContrast: boolean,\n baseResolved: ResolvedColor,\n config: GlazeConfigResolved,\n): number {\n const extremeLightTone = mapToneForScheme(\n authorTone,\n mode,\n false,\n isHighContrast,\n config,\n );\n const lightBase = getSchemeVariant(baseResolved, false, isHighContrast);\n const darkBase = getSchemeVariant(baseResolved, true, isHighContrast);\n const shift = extremeLightTone - lightBase.t * 100;\n return clamp(darkBase.t * 100 + (mode === 'auto' ? -shift : shift), 0, 100);\n}\n\n/**\n * Hue, absolute saturation (0–1) and tone (0–100) read off a color def's `from`.\n *\n * Deliberately not memoized. Keying a cache on the def object looks free — a\n * resolve reads this a handful of times per color — but defs are stored by\n * reference, so mutating one in place and re-setting it would invalidate the\n * theme's own cache while a def-keyed cache quietly served the old color. The\n * parse is a few microseconds against a resolve that is already cached; that is\n * not a trade worth a staleness bug.\n */\nfunction fromSeed(\n def: RegularColorDef,\n): { hue: number; saturation: number; tone: number } | undefined {\n if (def.from === undefined) return undefined;\n\n // `toTone` already returns the 0–100 tone; `s` stays the OKHSL 0–1 saturation\n // the resolver emits.\n const { h, s, l } = extractOkhslFromValue(def.from);\n\n return { hue: h, saturation: s, tone: toTone(l) };\n}\n\n/**\n * The config this color resolves against.\n *\n * A `from` color carries a literal value, so its light variant has to survive\n * the light tone window intact — hence a local `lightTone: false`, the same\n * default the value-shorthand form of `glaze.color()` applies. Only the light\n * window is dropped: dark and high contrast keep theirs, because that is where\n * the color is expected to adapt.\n */\nfunction configForColor(\n def: RegularColorDef,\n config: GlazeConfigResolved,\n): GlazeConfigResolved {\n if (def.from === undefined) return config;\n\n return { ...config, lightTone: false };\n}\n\nfunction resolveRootColor(\n def: RegularColorDef,\n isHighContrast: boolean,\n config: GlazeConfigResolved,\n): number {\n // Root tone is absolute or extreme ('max' = 100, 'min' = 0); both flow\n // through mapToneForScheme (and invert in dark under mode 'auto').\n if (def.tone === undefined) return clamp(fromSeed(def)!.tone, 0, 100);\n\n const parsed = passTone(def.tone, isHighContrast, config);\n return clamp(parsed.value, 0, 100);\n}\n\n/**\n * Effective hue and saturation for one color in one scheme.\n *\n * Dark schemes read the dark seed pair and the color's `darkHue` /\n * `darkSaturation`, each falling back to its light counterpart. An explicit\n * dark saturation — on the seed or the def — is taken literally; the global\n * `darkDesaturation` reduction applies only when neither is authored.\n * `mode: 'static'` pins one value across every scheme, so it skips all of it.\n *\n * Shared by `resolveColorForScheme` (the emitted variant) and\n * `resolveDependentColor` (the contrast solver's inputs) so the solver always\n * measures the color it is actually going to produce.\n */\nfunction resolveChannels(\n def: RegularColorDef,\n ctx: ResolveContext,\n isDark: boolean,\n): { hue: number; saturation: number } {\n const mode = def.mode ?? 'auto';\n const satFactor = clamp(def.saturation ?? 1, 0, 1);\n\n // A `from` color carries its own hue and an ABSOLUTE saturation, so it stands\n // outside the seed entirely: the theme seed is a ceiling for every other color\n // (`saturation` is a 0–1 factor of it), and a literal color has to be able to\n // exceed it or the caller would have to re-seed the theme to be honored.\n // An explicit `hue` / `saturation` on the same def still wins — those are the\n // more specific instruction, and `saturation` keeps its factor-of-seed meaning.\n const seed = fromSeed(def);\n const fromHue =\n seed !== undefined && def.hue === undefined ? seed.hue : undefined;\n const fromSaturation =\n seed !== undefined && def.saturation === undefined\n ? seed.saturation\n : undefined;\n\n if (!isDark || mode === 'static') {\n return {\n hue: fromHue ?? resolveEffectiveHue(ctx.hue, def.hue),\n saturation:\n fromSaturation ?? clamp((satFactor * ctx.saturation) / 100, 0, 1),\n };\n }\n\n const darkSeedSaturation = ctx.darkSaturation ?? ctx.saturation;\n const darkFactor = clamp(def.darkSaturation ?? satFactor, 0, 1);\n // Dark keeps the color's own saturation as its starting point too, but unlike\n // light it is still subject to `darkDesaturation` — dark is where the color is\n // allowed to move, so the global haircut applies as it does to any other color.\n const fromDark =\n fromSaturation !== undefined && def.darkSaturation === undefined;\n const raw = fromDark\n ? fromSaturation\n : (darkFactor * darkSeedSaturation) / 100;\n // A theme-level `darkSaturation` only counts as \"authored\" for a color that\n // actually reads the seed. A `from` color does not, so letting the theme's\n // value suppress the haircut here would leave the same color MORE saturated in\n // dark than it is in a theme that never set one.\n const explicitDark = fromDark\n ? false\n : def.darkSaturation !== undefined || ctx.darkSaturation !== undefined;\n\n return {\n hue:\n fromHue !== undefined && def.darkHue === undefined\n ? fromHue\n : resolveEffectiveHue(ctx.darkHue ?? ctx.hue, def.darkHue ?? def.hue),\n saturation: clamp(\n explicitDark ? raw : mapSaturationDark(raw, mode, ctx.config),\n 0,\n 1,\n ),\n };\n}\n\nfunction resolveDependentColor(\n name: string,\n def: RegularColorDef,\n ctx: ResolveContext,\n isHighContrast: boolean,\n isDark: boolean,\n channels: { hue: number; saturation: number },\n polarity: 'fg' | 'bg',\n effectivePastel: boolean,\n): number {\n const baseName = def.base!;\n const baseResolved = ctx.resolved.get(baseName);\n if (!baseResolved) {\n throw new Error(\n `glaze: base \"${baseName}\" not yet resolved for \"${name}\".`,\n );\n }\n\n const mode = def.mode ?? 'auto';\n const flip = def.autoFlip ?? ctx.config.autoFlip;\n const pastel = effectivePastel;\n const config = configForColor(def, ctx.config);\n\n const baseVariant = getSchemeVariant(baseResolved, isDark, isHighContrast);\n const baseTone = baseVariant.t * 100;\n\n let preferredTone: number;\n let isExtreme = false;\n // A `from` color with no authored `tone` is placed at the tone it carries —\n // not at its base's, which is what an ordinary dependent color would inherit.\n const seed = fromSeed(def);\n const rawTone: HCPair<ToneValue> | undefined =\n def.tone ?? (seed !== undefined ? seed.tone : undefined);\n\n if (rawTone === undefined) {\n preferredTone = baseTone;\n } else {\n const parsed = passTone(rawTone, isHighContrast, config);\n\n if (parsed.kind === 'relative') {\n if (isDark && mode === 'auto') {\n const baseLightVariant = getSchemeVariant(\n baseResolved,\n false,\n isHighContrast,\n );\n const baseLightTone = baseLightVariant.t * 100;\n const absoluteLightTone = clamp(\n baseLightTone + applyToneFlip(parsed.value, baseLightTone, flip),\n 0,\n 100,\n );\n // Invert + remap the base-anchored light tone into the dark window,\n // exactly like an absolute author tone under `mode: 'auto'`.\n preferredTone = mapToneForScheme(\n absoluteLightTone,\n 'auto',\n true,\n isHighContrast,\n config,\n );\n } else {\n const delta = applyToneFlip(parsed.value, baseTone, flip);\n preferredTone = clamp(baseTone + delta, 0, 100);\n }\n } else {\n // Absolute or extreme ('max' = 100, 'min' = 0).\n isExtreme = parsed.kind === 'extreme';\n if (isExtreme && isDark && mode !== 'static') {\n // Replay the light-scheme shift so the base/extreme pair keeps its\n // contrast instead of being squeezed by the dark window.\n preferredTone = extremeDarkTone(\n parsed.value,\n mode,\n isHighContrast,\n baseResolved,\n config,\n );\n } else {\n preferredTone = mapToneForScheme(\n parsed.value,\n mode,\n isDark,\n isHighContrast,\n config,\n );\n }\n }\n }\n\n const rawContrast = def.contrast;\n if (rawContrast !== undefined) {\n const resolvedContrast = resolveContrastSpec(\n rawContrast,\n isHighContrast,\n config,\n polarity,\n );\n\n const baseOkhsl = toOkhslVariant(baseVariant);\n const baseLinearRgb = okhslToLinearSrgb(\n baseOkhsl.h,\n baseOkhsl.s,\n baseOkhsl.l,\n baseVariant.pastel ?? ctx.config.pastel,\n );\n\n // An extreme keeps its own position — clamping it back into the scheme\n // window would undo the shift the extreme asked for.\n const preferredRange = isExtreme\n ? ([0, 1] as const)\n : schemeToneRange(isDark, mode, isHighContrast, config);\n\n let initialDirection: 'lighter' | 'darker' | undefined;\n if (preferredTone < baseTone) {\n initialDirection = 'darker';\n } else if (preferredTone > baseTone) {\n initialDirection = 'lighter';\n }\n\n const solve = {\n hue: channels.hue,\n saturation: channels.saturation,\n preferredTone: clamp(\n preferredTone / 100,\n preferredRange[0],\n preferredRange[1],\n ),\n baseLinearRgb,\n toneRange: [0, 1] as [number, number],\n flip,\n pastel,\n };\n\n // Under a manual contrast level, pin which side of the base the color sits\n // on so a slider can't send it leaping across its own base. The normal\n // passes only: a high-contrast pass has no ramp to be stable along, and it\n // must reproduce what `'auto'` resolves, which never probes.\n //\n // `autoFlip`'s tie-break is unstable along a ramp: when both sides meet the\n // floor it takes whichever lands nearer the anchor, and which side that is\n // shifts as the target grows. So the side is decided once — by a probe solve\n // at the *nearer endpoint's* target — and then preferred at every level in\n // that half of the ramp via `preferInitial`.\n //\n // Anchoring to the nearer endpoint is what keeps levels 0 and 100\n // bit-identical to the classic normal / high-contrast output: at an endpoint\n // the probe solves the very problem that pass would solve, so it reproduces\n // that side. `flip` stays on, so a pinned side that physically cannot reach\n // the target still falls back to the opposite one and the floor is met.\n // A color whose two endpoints genuinely disagree therefore changes side at\n // most once, at level 50 — the same place every other un-interpolable\n // decision switches.\n const level = isHighContrast ? undefined : contrastFraction(config);\n let preferInitial = false;\n if (level !== undefined && level > 0 && level < 1) {\n const probe = findToneForContrast({\n ...solve,\n contrast: resolveContrastForLevel(\n rawContrast,\n level < PAIR_SWITCH ? 0 : 100,\n polarity,\n ),\n initialDirection,\n });\n initialDirection = probe.tone * 100 < baseTone ? 'darker' : 'lighter';\n preferInitial = true;\n }\n\n const result = findToneForContrast({\n ...solve,\n contrast: resolvedContrast,\n initialDirection,\n preferInitial,\n });\n\n if (!result.met) {\n warnContrastUnmet(\n name,\n isDark,\n isHighContrast,\n resolvedContrast,\n result.contrast,\n );\n }\n\n return result.tone * 100;\n }\n\n return clamp(preferredTone, 0, 100);\n}\n\nfunction resolveColorForScheme(\n name: string,\n def: ColorDef,\n ctx: ResolveContext,\n isDark: boolean,\n isHighContrast: boolean,\n): ResolvedColorVariant {\n if (isShadowDef(def)) {\n return resolveShadowForScheme(def, ctx, isDark, isHighContrast);\n }\n\n if (isMixDef(def)) {\n return resolveMixForScheme(name, def, ctx, isDark, isHighContrast);\n }\n\n const regDef = def as RegularColorDef;\n const mode = regDef.mode ?? 'auto';\n // `from` supplies an absolute tone, so a color that carries one is a root even\n // with no authored `tone` — same as any other absolutely-placed color.\n const isRoot = hasAbsoluteTone(regDef) && !regDef.base;\n const channels = resolveChannels(regDef, ctx, isDark);\n const role = resolveRole(name, def, ctx);\n const polarity = roleToPolarity(role);\n const pastel = regDef.pastel ?? ctx.config.pastel;\n const config = configForColor(regDef, ctx.config);\n\n const finalTone = isRoot\n ? mapToneForScheme(\n resolveRootColor(regDef, isHighContrast, config),\n mode,\n isDark,\n isHighContrast,\n config,\n )\n : resolveDependentColor(\n name,\n regDef,\n ctx,\n isHighContrast,\n isDark,\n channels,\n polarity,\n pastel,\n );\n\n return {\n h: channels.hue,\n s: channels.saturation,\n t: clamp(finalTone / 100, 0, 1),\n alpha: regDef.opacity ?? 1,\n pastel,\n };\n}\n\nfunction resolveShadowForScheme(\n def: ShadowColorDef,\n ctx: ResolveContext,\n isDark: boolean,\n isHighContrast: boolean,\n): ResolvedColorVariant {\n const bgResolved = ctx.resolved.get(def.bg)!;\n const bgVariant = toOkhslVariant(\n getSchemeVariant(bgResolved, isDark, isHighContrast),\n );\n\n let fgVariant: OkhslVariant | undefined;\n if (def.fg) {\n const fgResolved = ctx.resolved.get(def.fg)!;\n fgVariant = toOkhslVariant(\n getSchemeVariant(fgResolved, isDark, isHighContrast),\n );\n }\n\n const intensity = passNumber(def.intensity, isHighContrast, ctx.config);\n\n const tuning = resolveShadowTuning(def.tuning, ctx.config.shadowTuning);\n return {\n ...toToneVariant(computeShadow(bgVariant, fgVariant, intensity, tuning)),\n pastel: def.pastel ?? ctx.config.pastel,\n };\n}\n\nfunction okhslVariantToLinearRgb(v: OkhslVariant, pastel: boolean): LinearRgb {\n return okhslToLinearSrgb(v.h, v.s, v.l, pastel);\n}\n\n/**\n * Resolve hue for OKHSL mixing, handling achromatic colors.\n * When one color has no saturation, its hue is meaningless —\n * use the hue from the color that has saturation (matches CSS\n * color-mix \"missing component\" behavior).\n */\nfunction mixHue(base: OkhslVariant, target: OkhslVariant, t: number): number {\n const SAT_EPSILON = 1e-6;\n const baseHasSat = base.s > SAT_EPSILON;\n const targetHasSat = target.s > SAT_EPSILON;\n\n if (baseHasSat && targetHasSat) return circularLerp(base.h, target.h, t);\n if (targetHasSat) return target.h;\n return base.h;\n}\n\nfunction linearSrgbLerp(\n base: LinearRgb,\n target: LinearRgb,\n t: number,\n): LinearRgb {\n return [\n base[0] + (target[0] - base[0]) * t,\n base[1] + (target[1] - base[1]) * t,\n base[2] + (target[2] - base[2]) * t,\n ];\n}\n\nfunction linearRgbToToneVariant(\n rgb: LinearRgb,\n pastel: boolean,\n): ResolvedColorVariant {\n const gamma: [number, number, number] = [\n Math.max(0, Math.min(1, sRGBLinearToGamma(rgb[0]))),\n Math.max(0, Math.min(1, sRGBLinearToGamma(rgb[1]))),\n Math.max(0, Math.min(1, sRGBLinearToGamma(rgb[2]))),\n ];\n const [h, s, l] = srgbToOkhsl(gamma, pastel);\n return toToneVariant({ h, s, l, alpha: 1 });\n}\n\nfunction resolveMixForScheme(\n name: string,\n def: MixColorDef,\n ctx: ResolveContext,\n isDark: boolean,\n isHighContrast: boolean,\n): ResolvedColorVariant {\n const baseResolved = ctx.resolved.get(def.base)!;\n const targetResolved = ctx.resolved.get(def.target)!;\n const baseVariant = toOkhslVariant(\n getSchemeVariant(baseResolved, isDark, isHighContrast),\n );\n const targetVariant = toOkhslVariant(\n getSchemeVariant(targetResolved, isDark, isHighContrast),\n );\n\n const rawValue = passNumber(def.value, isHighContrast, ctx.config);\n let t = clamp(rawValue, 0, 100) / 100;\n\n const blend = def.blend ?? 'opaque';\n const space = def.space ?? 'okhsl';\n const role = resolveRole(name, def, ctx);\n const polarity = roleToPolarity(role);\n const pastel = def.pastel ?? ctx.config.pastel;\n const baseLinear = okhslVariantToLinearRgb(\n baseVariant,\n baseVariant.pastel ?? ctx.config.pastel,\n );\n const targetLinear = okhslVariantToLinearRgb(\n targetVariant,\n targetVariant.pastel ?? ctx.config.pastel,\n );\n\n if (def.contrast !== undefined) {\n const resolvedContrast = resolveContrastSpec(\n def.contrast,\n isHighContrast,\n ctx.config,\n polarity,\n );\n const metric = resolvedContrast.metric;\n\n let luminanceAt: (v: number) => number;\n\n if (blend === 'transparent' || space === 'srgb') {\n luminanceAt = (v: number) =>\n metricLuminance(metric, linearSrgbLerp(baseLinear, targetLinear, v));\n } else {\n luminanceAt = (v: number) => {\n const h = mixHue(baseVariant, targetVariant, v);\n const s = baseVariant.s + (targetVariant.s - baseVariant.s) * v;\n const l = baseVariant.l + (targetVariant.l - baseVariant.l) * v;\n return metricLuminance(metric, okhslToLinearSrgb(h, s, l, pastel));\n };\n }\n\n const result = findValueForMixContrast({\n preferredValue: t,\n baseLinearRgb: baseLinear,\n targetLinearRgb: targetLinear,\n contrast: resolvedContrast,\n luminanceAtValue: luminanceAt,\n flip: ctx.config.autoFlip,\n });\n t = result.value;\n }\n\n if (blend === 'transparent') {\n return {\n ...toToneVariant({\n h: targetVariant.h,\n s: targetVariant.s,\n l: targetVariant.l,\n alpha: clamp(t, 0, 1),\n }),\n pastel,\n };\n }\n\n if (space === 'srgb') {\n const mixed = linearSrgbLerp(baseLinear, targetLinear, t);\n return { ...linearRgbToToneVariant(mixed, pastel), pastel };\n }\n\n return {\n ...toToneVariant({\n h: mixHue(baseVariant, targetVariant, t),\n s: clamp(baseVariant.s + (targetVariant.s - baseVariant.s) * t, 0, 1),\n l: clamp(baseVariant.l + (targetVariant.l - baseVariant.l) * t, 0, 1),\n alpha: 1,\n }),\n pastel,\n };\n}\n\nfunction defMode(def: ColorDef): AdaptationMode | undefined {\n if (isShadowDef(def) || isMixDef(def)) return undefined;\n return (def as RegularColorDef).mode ?? 'auto';\n}\n\n/**\n * Run a single resolve pass over all local names. Pass 1 lazily creates\n * each `ResolvedColor` (all four slots seeded with the just-resolved\n * variant) the first time it sees a name; later passes update the\n * `target` slot on the existing record.\n */\nfunction runPass(\n order: string[],\n defs: ColorMap,\n ctx: ResolveContext,\n isDark: boolean,\n isHighContrast: boolean,\n target: ResolvedField,\n): Map<string, ResolvedColorVariant> {\n const out = new Map<string, ResolvedColorVariant>();\n for (const name of order) {\n const variant = resolveColorForScheme(\n name,\n defs[name],\n ctx,\n isDark,\n isHighContrast,\n );\n out.set(name, variant);\n const existing = ctx.resolved.get(name);\n if (existing) {\n ctx.resolved.set(name, { ...existing, [target]: variant });\n } else {\n ctx.resolved.set(name, {\n name,\n light: variant,\n dark: variant,\n lightContrast: variant,\n darkContrast: variant,\n mode: defMode(defs[name]),\n });\n }\n }\n return out;\n}\n\n/**\n * Re-seed a single variant slot with a previously-resolved map so the\n * upcoming pass reads sensible fallbacks via `getSchemeVariant`.\n */\nfunction seedField(\n order: string[],\n ctx: ResolveContext,\n field: ResolvedField,\n source: Map<string, ResolvedColorVariant>,\n): void {\n for (const name of order) {\n const existing = ctx.resolved.get(name)!;\n ctx.resolved.set(name, { ...existing, [field]: source.get(name)! });\n }\n}\n\n/**\n * After the passes, surface chromatic contrast drift (§10): a color\n * resolved with a `base` + `contrast` may land slightly under the contrast\n * its tone implies because chromatic luminance drifts from the gray tone.\n *\n * Under a manual `contrastLevel` the spec is resolved at the level, so the check\n * measures each normal variant against the target it was actually solved for. At\n * level 100 the high-contrast slots are mirrors and are skipped: the normal\n * schemes already carry that check, and repeating it would emit a byte-identical\n * advisory under a different scheme label, which dedupes as a separate key.\n */\nfunction verifyContrastDrift(\n order: string[],\n defs: ColorMap,\n result: Map<string, ResolvedColor>,\n config: GlazeConfigResolved,\n): void {\n const roles = new Map<string, Role>();\n for (const name of order) {\n const def = defs[name];\n if (isShadowDef(def) || isMixDef(def)) continue;\n const regDef = def as RegularColorDef;\n if (regDef.contrast === undefined || !regDef.base) continue;\n const color = result.get(name);\n const base = result.get(regDef.base);\n if (!color || !base) continue;\n\n const role = resolveRoleInMap(name, def, defs, config.inferRole, roles);\n const polarity = roleToPolarity(role);\n\n const schemes: {\n isDark: boolean;\n isHighContrast: boolean;\n field: ResolvedField;\n }[] = [\n { isDark: false, isHighContrast: false, field: 'light' },\n { isDark: false, isHighContrast: true, field: 'lightContrast' },\n { isDark: true, isHighContrast: false, field: 'dark' },\n { isDark: true, isHighContrast: true, field: 'darkContrast' },\n ];\n const mirrored = hcMirrorsNormal(config);\n\n for (const s of schemes) {\n // At level 100 the high-contrast slots are mirrors of the normal ones.\n if (mirrored && s.isHighContrast) continue;\n const spec = resolveContrastSpec(\n regDef.contrast,\n s.isHighContrast,\n config,\n polarity,\n );\n const cVariant = color[s.field];\n const bVariant = base[s.field];\n const cOkhsl = toOkhslVariant(cVariant);\n const bOkhsl = toOkhslVariant(bVariant);\n // Measure in the spec's metric basis so the APCA warning compares APCA\n // luminances, not WCAG ones. Each variant carries its own effective\n // pastel flag so the gamut mapping matches what the resolver applied;\n // fall back to the config default for any variant without one.\n const cPastel = cVariant.pastel ?? config.pastel;\n const bPastel = bVariant.pastel ?? config.pastel;\n const yC = metricLuminance(\n spec.metric,\n okhslToLinearSrgb(cOkhsl.h, cOkhsl.s, cOkhsl.l, cPastel),\n );\n const yB = metricLuminance(\n spec.metric,\n okhslToLinearSrgb(bOkhsl.h, bOkhsl.s, bOkhsl.l, bPastel),\n );\n warnContrastDrift(name, s.isDark, s.isHighContrast, spec, yC, yB);\n }\n }\n}\n\nexport function resolveAllColors(\n seed: GlazeThemeSeed,\n defs: ColorMap,\n config: GlazeConfigResolved,\n externalBases?: Map<string, ResolvedColor>,\n): Map<string, ResolvedColor> {\n validateColorDefs(defs, externalBases);\n const order = topoSort(defs);\n\n const ctx: ResolveContext = {\n ...seed,\n defs,\n resolved: new Map(),\n config,\n roles: new Map(),\n };\n\n // Pre-seed externally-resolved bases. The per-pass loops iterate only\n // `defs` keys (via `order`), so external entries persist across all\n // four passes and are read via `getSchemeVariant` per scheme.\n if (externalBases) {\n for (const [name, color] of externalBases) {\n ctx.resolved.set(name, color);\n }\n }\n\n // A manual contrast level positions the *normal* passes; the high-contrast\n // passes bypass it, so they run as usual and produce the same values `'auto'`\n // does. Level 100 is the one exception: there the normal passes already *are*\n // the high-contrast passes bit for bit, so the two are skipped and their slots\n // mirror the normal ones. That holds because within a pass a dependent reads\n // its base's same slot (topo order), and the only cross-scheme reads — the\n // relative-tone dark branch and `extremeDarkTone` — read `light`, which equals\n // `lightContrast` at 100.\n const mirrored = hcMirrorsNormal(config);\n\n // Pass 1: Light (normal, or at the level).\n const lightMap = runPass(order, defs, ctx, false, false, 'light');\n\n // Pass 2: Light high-contrast.\n let lightHCMap = lightMap;\n if (!mirrored) {\n seedField(order, ctx, 'lightContrast', lightMap);\n lightHCMap = runPass(order, defs, ctx, false, true, 'lightContrast');\n }\n\n // Pass 3: Dark (normal, or at the level).\n seedField(order, ctx, 'dark', lightMap);\n seedField(order, ctx, 'darkContrast', lightHCMap);\n const darkMap = runPass(order, defs, ctx, true, false, 'dark');\n\n // Pass 4: Dark high-contrast.\n let darkHCMap = darkMap;\n if (!mirrored) {\n seedField(order, ctx, 'darkContrast', darkMap);\n darkHCMap = runPass(order, defs, ctx, true, true, 'darkContrast');\n }\n\n const result = new Map<string, ResolvedColor>();\n for (const name of order) {\n result.set(name, {\n name,\n light: lightMap.get(name)!,\n dark: darkMap.get(name)!,\n lightContrast: lightHCMap.get(name)!,\n darkContrast: darkHCMap.get(name)!,\n mode: defMode(defs[name]),\n });\n }\n\n verifyContrastDrift(order, defs, result, config);\n\n return result;\n}\n\n// Re-export for callers that previously imported tone helpers from here.\nexport { fromTone, toTone };\n","/**\n * Hue channel planning for `splitHue` exports.\n *\n * Builds per-color hue var references and the `--*-hue` declarations backing\n * them for oklch CSS / Tasty output when every color is pastel.\n *\n * Hue is scheme-independent unless the theme or a color authors a dark hue,\n * so declarations are collected per scheme (`'light'` / `'dark'`) and the dark\n * set is emitted only when it actually differs — see `buildHueDeclarations`.\n * A color that authors a hue in *either* scheme gets its own var in both, so\n * the shared `var()` reference stays valid.\n */\n\nimport { parseRelativeOrAbsolute } from './hc-pair';\nimport { isMixDef, isShadowDef } from './shadow';\nimport type {\n ColorDef,\n ColorMap,\n RegularColorDef,\n ResolvedColor,\n ResolvedColorVariant,\n} from './types';\n\nconst ACHROMATIC_EPSILON = 1e-6;\n\n/** Which scheme's hue a plan or declaration set describes. */\nexport type HueScheme = 'light' | 'dark';\n\nexport interface HueDeclaration {\n prop: string;\n value: string;\n}\n\nexport interface HuePlan {\n /** CSS `var()` reference spliced into `oklch(L C <hueVar>)`. */\n hueVar: string;\n /** When true, emit a full inline color (shadow/mix/achromatic). */\n inline: boolean;\n /** Scheme-independent `--*-hue` declarations for this color. */\n declarations: HueDeclaration[];\n}\n\nexport interface ChannelCtx {\n seedHue: number;\n /**\n * Dark-scheme seed hue, when the theme authored one. Drives the dark\n * `--{baseName}-hue` value; falls back to `seedHue`.\n */\n darkSeedHue?: number;\n /** Theme-level hue var base name (without `--` / `-hue`). */\n baseName: string;\n /** Token / custom-property name prefix used for hue var naming (`brand-` etc.). */\n prefix: string;\n defs: ColorMap;\n mode: 'theme' | 'standalone';\n /** Standalone: resolved hue from the primary variant (scheme-independent). */\n resolvedHue?: number;\n /**\n * When false, hue declarations are not emitted (the pass only references\n * hue vars already declared by a sibling pass). Used by palette primary\n * unprefixed aliases so they reference the themed `--{themeName}-*-hue`\n * vars without re-declaring (and colliding with) other themes' base vars.\n * Defaults to true.\n */\n emitDeclarations?: boolean;\n}\n\nfunction cssProp(prefix: string, name: string, suffix: string): string {\n return `--${prefix}${name}${suffix}`;\n}\n\nfunction isAchromatic(v: ResolvedColorVariant): boolean {\n return v.s <= ACHROMATIC_EPSILON;\n}\n\n/** Seed hue backing `--{baseName}-hue` in a given scheme. */\nfunction schemeSeedHue(ctx: ChannelCtx, scheme: HueScheme): number {\n return scheme === 'dark' ? (ctx.darkSeedHue ?? ctx.seedHue) : ctx.seedHue;\n}\n\nfunction themeHuePlan(\n name: string,\n def: ColorDef | undefined,\n variant: ResolvedColorVariant,\n ctx: ChannelCtx,\n scheme: HueScheme,\n): HuePlan {\n if (\n def === undefined ||\n isShadowDef(def) ||\n isMixDef(def) ||\n isAchromatic(variant)\n ) {\n return { hueVar: '', inline: true, declarations: [] };\n }\n\n const regDef = def as RegularColorDef;\n const baseHueVar = `var(--${ctx.baseName}-hue)`;\n const prop = cssProp(ctx.prefix, name, '-hue');\n\n // `mode: 'static'` pins one hue across every scheme, but `--{baseName}-hue`\n // is re-declared in dark whenever the theme seeds one. Pin the resolved hue\n // so a static color doesn't drift with it — matching what the resolver does.\n // Both variants carry the same hue under `static`, so either one works.\n if (\n (regDef.mode ?? 'auto') === 'static' &&\n schemeSeedHue(ctx, 'dark') !== ctx.seedHue\n ) {\n return {\n hueVar: `var(${prop})`,\n inline: false,\n declarations: [{ prop, value: String(variant.h) }],\n };\n }\n\n // A color needs its own var as soon as *either* scheme authors a hue: the\n // `var()` reference is shared across schemes, so it can't be the theme var\n // in one and a per-color var in the other.\n //\n // `from` counts as authoring one. It carries a hue that is not the theme's,\n // so pointing the color at the theme hue var would re-skin it to whatever the\n // theme is seeded with — the same failure a `darkHue`-only color used to have.\n if (\n regDef.hue === undefined &&\n regDef.darkHue === undefined &&\n regDef.from === undefined\n ) {\n return { hueVar: baseHueVar, inline: false, declarations: [] };\n }\n\n const authored =\n scheme === 'dark' ? (regDef.darkHue ?? regDef.hue) : regDef.hue;\n\n if (authored === undefined) {\n // `from` supplied the hue for this scheme, so pin the resolved literal —\n // tracking the theme var would re-skin the color to the theme's hue, which\n // is the one thing a literal color must not do.\n if (regDef.from !== undefined) {\n return {\n hueVar: `var(${prop})`,\n inline: false,\n declarations: [{ prop, value: String(variant.h) }],\n };\n }\n\n // Only the other scheme authored a hue; track the theme var in this one.\n return {\n hueVar: `var(${prop})`,\n inline: false,\n declarations: [{ prop, value: baseHueVar }],\n };\n }\n\n const parsed = parseRelativeOrAbsolute(authored);\n\n if (parsed.relative) {\n const sign = parsed.value >= 0 ? '+' : '-';\n const magnitude = Math.abs(parsed.value);\n const value = `calc(var(--${ctx.baseName}-hue) ${sign} ${magnitude})`;\n return {\n hueVar: `var(${prop})`,\n inline: false,\n declarations: [{ prop, value }],\n };\n }\n\n const absHue = ((parsed.value % 360) + 360) % 360;\n return {\n hueVar: `var(${prop})`,\n inline: false,\n declarations: [{ prop, value: String(absHue) }],\n };\n}\n\nfunction standaloneHuePlan(\n name: string,\n variant: ResolvedColorVariant,\n ctx: ChannelCtx,\n scheme: HueScheme,\n): HuePlan {\n if (isAchromatic(variant)) {\n return { hueVar: '', inline: true, declarations: [] };\n }\n\n // `resolvedHue` is the light-variant hue captured by the caller; the dark\n // pass reads the hue off the dark variant it was handed.\n const hue = scheme === 'dark' ? variant.h : (ctx.resolvedHue ?? variant.h);\n const prop = cssProp(ctx.prefix, name, '-hue');\n return {\n hueVar: `var(${prop})`,\n inline: false,\n declarations: [{ prop, value: String(hue) }],\n };\n}\n\nexport function buildHuePlan(\n name: string,\n def: ColorDef | undefined,\n variant: ResolvedColorVariant,\n ctx: ChannelCtx,\n scheme: HueScheme = 'light',\n): HuePlan {\n if (ctx.mode === 'standalone') {\n return standaloneHuePlan(name, variant, ctx, scheme);\n }\n return themeHuePlan(name, def, variant, ctx, scheme);\n}\n\n/** Collect unique hue declarations across all colors (theme + per-color). */\nfunction collectHueDeclarations(\n resolved: Map<string, ResolvedColor>,\n ctx: ChannelCtx,\n scheme: HueScheme,\n): HueDeclaration[] {\n if (ctx.emitDeclarations === false) return [];\n\n const seen = new Set<string>();\n const out: HueDeclaration[] = [];\n\n const push = (decl: HueDeclaration): void => {\n if (seen.has(decl.prop)) return;\n seen.add(decl.prop);\n out.push(decl);\n };\n\n if (ctx.mode === 'theme') {\n push({\n prop: `--${ctx.baseName}-hue`,\n value: String(schemeSeedHue(ctx, scheme)),\n });\n }\n\n for (const [name, color] of resolved) {\n const def = ctx.defs[name];\n const variant = scheme === 'dark' ? color.dark : color.light;\n const plan = buildHuePlan(name, def, variant, ctx, scheme);\n for (const decl of plan.declarations) {\n push(decl);\n }\n }\n\n return out;\n}\n\n/**\n * Hue declarations for both schemes. `dark` is empty when it resolves to the\n * same hues as light — the common case, with no `darkHue` anywhere.\n *\n * When they differ, the **whole** dark set is returned rather than only the\n * entries whose text changed. A relative declaration reads\n * `calc(var(--theme-hue) + N)` in both schemes even though its resolved value\n * moves with the seed, and custom properties substitute `var()` at\n * computed-value time on the declaring element — so re-declaring\n * `--{baseName}-hue` alone would leave inherited per-color vars still holding\n * the light-substituted value.\n */\nexport function buildHueDeclarations(\n resolved: Map<string, ResolvedColor>,\n ctx: ChannelCtx,\n): { light: HueDeclaration[]; dark: HueDeclaration[] } {\n const light = collectHueDeclarations(resolved, ctx, 'light');\n const dark = collectHueDeclarations(resolved, ctx, 'dark');\n\n const same =\n dark.length === light.length &&\n dark.every(\n (decl, i) => decl.prop === light[i].prop && decl.value === light[i].value,\n );\n\n return { light, dark: same ? [] : dark };\n}\n\nexport function buildHuePlans(\n resolved: Map<string, ResolvedColor>,\n ctx: ChannelCtx,\n): Map<string, HuePlan> {\n const plans = new Map<string, HuePlan>();\n for (const [name, color] of resolved) {\n plans.set(name, buildHuePlan(name, ctx.defs[name], color.light, ctx));\n }\n return plans;\n}\n","/**\n * Output formatting for resolved color maps.\n *\n * Owns the CSS-string formatter dispatch table (`okhsl` / `rgb` / `hsl` /\n * `oklch`) and the token-map shapes Glaze emits:\n * - `buildTokenMap` — Tasty style-to-state bindings (`#name` keys, state aliases).\n * - `buildFlatTokenMap` — `{ light, dark, ... }` per-variant maps.\n * - `buildJsonMap` — `{ name: { light, dark, ... } }` per-color JSON.\n * - `buildCssMap` — CSS custom property declaration strings per variant.\n * - `buildDtcgMap` — W3C DTCG (2025.10) token documents, one per scheme.\n * - `buildDtcgResolver` — W3C DTCG Resolver-Module document (one modifier, a context per scheme).\n * - `buildTailwindMap` — Tailwind v4 `@theme` block + dark/HC overrides.\n */\n\nimport {\n buildHueDeclarations,\n buildHuePlans,\n type ChannelCtx,\n type HuePlan,\n} from './channels';\nimport {\n formatHsl,\n formatOkhsl,\n formatOkhst,\n formatOklch,\n formatRgb,\n okhslToOklch,\n okhslToSrgb,\n srgbToHex,\n} from './okhsl-color-math';\nimport { variantToOkhsl } from './okhst';\nimport { getConfig } from './config';\nimport { hcMirrorsNormal } from './hc-pair';\nimport type {\n DtcgColorSpace,\n DtcgColorToken,\n DtcgColorValue,\n DtcgDocument,\n DtcgTokenTree,\n GlazeColorFormat,\n GlazeCssResult,\n GlazeDtcgResolverDocument,\n GlazeDtcgResolverOptions,\n GlazeDtcgResult,\n GlazeOutputModes,\n ResolvedColor,\n ResolvedColorVariant,\n} from './types';\n\nexport type { ChannelCtx } from './channels';\n\nconst formatters: Record<\n Exclude<GlazeColorFormat, 'okhst'>,\n (h: number, s: number, l: number, pastel: boolean) => string\n> = {\n okhsl: formatOkhsl,\n rgb: formatRgb,\n hsl: formatHsl,\n oklch: formatOklch,\n};\n\nfunction fmt(value: number, decimals: number): string {\n return parseFloat(value.toFixed(decimals)).toString();\n}\n\nexport function formatVariant(\n v: ResolvedColorVariant,\n format: GlazeColorFormat = 'oklch',\n pastel = false,\n): string {\n // Variants store canonical tone; convert to OKHSL lightness at the edge.\n // Per-variant `pastel` (set by the resolver from def or config fallback)\n // wins over the format-time fallback, so output matches resolution.\n const effectivePastel = v.pastel ?? pastel;\n\n let base: string;\n if (format === 'okhst') {\n base = formatOkhst(v.h, v.s, v.t, effectivePastel);\n } else {\n const { l } = variantToOkhsl(v);\n base = formatters[format](v.h, v.s, l, effectivePastel);\n }\n\n if (v.alpha >= 1) return base;\n const closing = base.lastIndexOf(')');\n return `${base.slice(0, closing)} / ${fmt(v.alpha, 4)})`;\n}\n\n/**\n * Format a resolved variant as `oklch(L C <hueVar>)`, splicing a CSS hue var\n * for `splitHue` exports. Falls back to inline when the plan is inline.\n */\nexport function formatVariantHue(\n v: ResolvedColorVariant,\n plan: HuePlan,\n pastel = false,\n): string {\n const effectivePastel = v.pastel ?? pastel;\n const { l } = variantToOkhsl(v);\n const [L, C] = okhslToOklch(v.h, v.s, l, effectivePastel);\n\n let base: string;\n if (plan.inline) {\n if (v.s <= 1e-6) {\n base = `oklch(${fmt(L, 4)} 0 0)`;\n } else {\n base = formatOklch(v.h, v.s, l, effectivePastel);\n }\n } else {\n base = `oklch(${fmt(L, 4)} ${fmt(C, 4)} ${plan.hueVar})`;\n }\n\n if (v.alpha >= 1) return base;\n const closing = base.lastIndexOf(')');\n return `${base.slice(0, closing)} / ${fmt(v.alpha, 4)})`;\n}\n\nfunction formatColorValue(\n v: ResolvedColorVariant,\n format: GlazeColorFormat,\n pastel: boolean,\n huePlan?: HuePlan,\n): string {\n if (format === 'oklch' && huePlan !== undefined) {\n return formatVariantHue(v, huePlan, pastel);\n }\n return formatVariant(v, format, pastel);\n}\n\n/**\n * Resolve the effective output modes for an export.\n *\n * `modes.highContrast` and `contrastLevel` are independent: the level positions\n * the normal variants, the high-contrast tier stays the true high-contrast\n * resolution, and the two compose — a slider raises the baseline while a\n * `prefers-contrast: more` block still escalates on top of it.\n *\n * The one exception is a **global** level of 100, where the normal variants\n * already *are* the high-contrast ones. The tier would be an exact duplicate, so\n * it is dropped and a single light/dark set is emitted — including against an\n * explicit `highContrast: true` override, which has nothing different left to\n * ask for.\n *\n * A level set on a single theme or token does not change which modes are\n * emitted: `modes` is global-only, and a palette must not have one sibling\n * collapse the shared token structure. A per-instance level of 100 therefore\n * still reports into the tier, with values equal to its own normal ones.\n */\nexport function resolveModes(\n override?: GlazeOutputModes,\n): Required<GlazeOutputModes> {\n const cfg = getConfig();\n const highContrast = override?.highContrast ?? cfg.modes.highContrast;\n return {\n dark: override?.dark ?? cfg.modes.dark,\n highContrast: highContrast && !hcMirrorsNormal(cfg),\n };\n}\n\nexport function buildTokenMap(\n resolved: Map<string, ResolvedColor>,\n prefix: string,\n states: { dark: string; highContrast: string },\n modes: Required<GlazeOutputModes>,\n format: GlazeColorFormat = 'oklch',\n pastel = false,\n channelCtx?: ChannelCtx,\n): Record<string, Record<string, string>> {\n const tokens: Record<string, Record<string, string>> = {};\n const huePlans =\n channelCtx !== undefined && format === 'oklch'\n ? buildHuePlans(resolved, channelCtx)\n : undefined;\n\n if (huePlans !== undefined && channelCtx !== undefined) {\n const hueDecls = buildHueDeclarations(resolved, channelCtx);\n for (const decl of hueDecls.light) {\n tokens[`$${decl.prop.slice(2)}`] = { '': decl.value };\n }\n // Hue vars must not outlive the modes gate the color values respect.\n if (modes.dark) {\n for (const decl of hueDecls.dark) {\n const key = `$${decl.prop.slice(2)}`;\n tokens[key] = { ...tokens[key], [states.dark]: decl.value };\n }\n }\n for (const [name, color] of resolved) {\n tokens[`#${prefix}${name}`] = buildTokenEntry(\n color,\n states,\n modes,\n format,\n pastel,\n huePlans.get(name),\n );\n }\n return tokens;\n }\n\n for (const [name, color] of resolved) {\n const key = `#${prefix}${name}`;\n tokens[key] = buildTokenEntry(color, states, modes, format, pastel);\n }\n\n return tokens;\n}\n\nfunction buildTokenEntry(\n color: ResolvedColor,\n states: { dark: string; highContrast: string },\n modes: Required<GlazeOutputModes>,\n format: GlazeColorFormat,\n pastel: boolean,\n huePlan?: HuePlan,\n): Record<string, string> {\n const entry: Record<string, string> = {\n '': formatColorValue(color.light, format, pastel, huePlan),\n };\n\n if (modes.dark) {\n entry[states.dark] = formatColorValue(color.dark, format, pastel, huePlan);\n }\n if (modes.highContrast) {\n entry[states.highContrast] = formatColorValue(\n color.lightContrast,\n format,\n pastel,\n huePlan,\n );\n }\n if (modes.dark && modes.highContrast) {\n entry[`${states.dark} & ${states.highContrast}`] = formatColorValue(\n color.darkContrast,\n format,\n pastel,\n huePlan,\n );\n }\n\n return entry;\n}\n\nexport function buildFlatTokenMap(\n resolved: Map<string, ResolvedColor>,\n prefix: string,\n modes: Required<GlazeOutputModes>,\n format: GlazeColorFormat = 'oklch',\n pastel = false,\n): Record<string, Record<string, string>> {\n const result: Record<string, Record<string, string>> = {\n light: {},\n };\n\n if (modes.dark) {\n result.dark = {};\n }\n if (modes.highContrast) {\n result.lightContrast = {};\n }\n if (modes.dark && modes.highContrast) {\n result.darkContrast = {};\n }\n\n for (const [name, color] of resolved) {\n const key = `${prefix}${name}`;\n\n result.light[key] = formatVariant(color.light, format, pastel);\n\n if (modes.dark) {\n result.dark[key] = formatVariant(color.dark, format, pastel);\n }\n if (modes.highContrast) {\n result.lightContrast[key] = formatVariant(\n color.lightContrast,\n format,\n pastel,\n );\n }\n if (modes.dark && modes.highContrast) {\n result.darkContrast[key] = formatVariant(\n color.darkContrast,\n format,\n pastel,\n );\n }\n }\n\n return result;\n}\n\nexport function buildJsonMap(\n resolved: Map<string, ResolvedColor>,\n modes: Required<GlazeOutputModes>,\n format: GlazeColorFormat = 'oklch',\n pastel = false,\n): Record<string, Record<string, string>> {\n const result: Record<string, Record<string, string>> = {};\n\n for (const [name, color] of resolved) {\n const entry: Record<string, string> = {\n light: formatVariant(color.light, format, pastel),\n };\n\n if (modes.dark) {\n entry.dark = formatVariant(color.dark, format, pastel);\n }\n if (modes.highContrast) {\n entry.lightContrast = formatVariant(color.lightContrast, format, pastel);\n }\n if (modes.dark && modes.highContrast) {\n entry.darkContrast = formatVariant(color.darkContrast, format, pastel);\n }\n\n result[name] = entry;\n }\n\n return result;\n}\n\nexport function buildCssMap(\n resolved: Map<string, ResolvedColor>,\n prefix: string,\n suffix: string,\n format: GlazeColorFormat,\n pastel = false,\n channelCtx?: ChannelCtx,\n): GlazeCssResult {\n const lines: Record<keyof GlazeCssResult, string[]> = {\n light: [],\n dark: [],\n lightContrast: [],\n darkContrast: [],\n };\n\n const huePlans =\n channelCtx !== undefined && format === 'oklch'\n ? buildHuePlans(resolved, channelCtx)\n : undefined;\n\n if (huePlans !== undefined && channelCtx !== undefined) {\n const hueDecls = buildHueDeclarations(resolved, channelCtx);\n for (const decl of hueDecls.light) {\n lines.light.push(`${decl.prop}: ${decl.value};`);\n }\n for (const decl of hueDecls.dark) {\n lines.dark.push(`${decl.prop}: ${decl.value};`);\n lines.darkContrast.push(`${decl.prop}: ${decl.value};`);\n }\n }\n\n for (const [name, color] of resolved) {\n const prop = `--${prefix}${name}${suffix}`;\n const plan = huePlans?.get(name);\n lines.light.push(\n `${prop}: ${formatColorValue(color.light, format, pastel, plan)};`,\n );\n lines.dark.push(\n `${prop}: ${formatColorValue(color.dark, format, pastel, plan)};`,\n );\n lines.lightContrast.push(\n `${prop}: ${formatColorValue(color.lightContrast, format, pastel, plan)};`,\n );\n lines.darkContrast.push(\n `${prop}: ${formatColorValue(color.darkContrast, format, pastel, plan)};`,\n );\n }\n\n return {\n light: lines.light.join('\\n'),\n dark: lines.dark.join('\\n'),\n lightContrast: lines.lightContrast.join('\\n'),\n darkContrast: lines.darkContrast.join('\\n'),\n };\n}\n\n// ============================================================================\n// DTCG (W3C Design Tokens Format Module 2025.10)\n// ============================================================================\n\nfunction roundTo(value: number, decimals: number): number {\n return parseFloat(value.toFixed(decimals));\n}\n\n/**\n * Build a DTCG `$value` color object for a resolved variant.\n *\n * `srgb` (default) emits gamma sRGB components in 0–1 plus a 6-digit `hex`\n * hint — the most universally understood form (Figma, Tokens Studio, Style\n * Dictionary). `oklch` emits `[L, C, H]` components with no hex — Glaze-native\n * and wide-gamut. `alpha` is included only when below 1.\n */\nexport function dtcgColorValue(\n v: ResolvedColorVariant,\n colorSpace: DtcgColorSpace = 'srgb',\n pastel = false,\n): DtcgColorValue {\n const effectivePastel = v.pastel ?? pastel;\n const { l } = variantToOkhsl(v);\n const alpha = v.alpha < 1 ? roundTo(v.alpha, 6) : undefined;\n\n if (colorSpace === 'oklch') {\n const [L, C, H] = okhslToOklch(v.h, v.s, l, effectivePastel);\n const value: DtcgColorValue = {\n colorSpace: 'oklch',\n components: [roundTo(L, 6), roundTo(C, 6), roundTo(H, 4)],\n };\n if (alpha !== undefined) value.alpha = alpha;\n return value;\n }\n\n const [r, g, b] = okhslToSrgb(v.h, v.s, l, effectivePastel);\n const value: DtcgColorValue = {\n colorSpace: 'srgb',\n components: [roundTo(r, 6), roundTo(g, 6), roundTo(b, 6)],\n hex: srgbToHex([r, g, b]),\n };\n if (alpha !== undefined) value.alpha = alpha;\n return value;\n}\n\nfunction dtcgToken(\n v: ResolvedColorVariant,\n colorSpace: DtcgColorSpace,\n pastel: boolean,\n): DtcgColorToken {\n return { $type: 'color', $value: dtcgColorValue(v, colorSpace, pastel) };\n}\n\n/**\n * Build a `GlazeDtcgResult`: one spec-conformant DTCG token document per\n * scheme variant, gated by `modes`. Light is always present.\n */\nexport function buildDtcgMap(\n resolved: Map<string, ResolvedColor>,\n prefix: string,\n modes: Required<GlazeOutputModes>,\n colorSpace: DtcgColorSpace = 'srgb',\n pastel = false,\n): GlazeDtcgResult {\n const light: DtcgDocument = {};\n const dark: DtcgDocument | undefined = modes.dark ? {} : undefined;\n const lightContrast: DtcgDocument | undefined = modes.highContrast\n ? {}\n : undefined;\n const darkContrast: DtcgDocument | undefined =\n modes.dark && modes.highContrast ? {} : undefined;\n\n for (const [name, color] of resolved) {\n const key = `${prefix}${name}`;\n light[key] = dtcgToken(color.light, colorSpace, pastel);\n if (dark) dark[key] = dtcgToken(color.dark, colorSpace, pastel);\n if (lightContrast) {\n lightContrast[key] = dtcgToken(color.lightContrast, colorSpace, pastel);\n }\n if (darkContrast) {\n darkContrast[key] = dtcgToken(color.darkContrast, colorSpace, pastel);\n }\n }\n\n return { light, dark, lightContrast, darkContrast };\n}\n\n// ============================================================================\n// DTCG Resolver Module (single document for all scheme variants)\n// ============================================================================\n\n/**\n * Default context names emitted on the `scheme` modifier — the Glaze variant\n * keys, so the resolver document mirrors `GlazeDtcgResult` exactly.\n */\nconst DEFAULT_DTCG_CONTEXT_NAMES = {\n light: 'light',\n dark: 'dark',\n lightContrast: 'lightContrast',\n darkContrast: 'darkContrast',\n} as const;\n\n/**\n * Wrap a per-scheme `GlazeDtcgResult` into a single W3C DTCG Resolver-Module\n * document. The light document becomes `sets[setName].sources[0]` (the default\n * context); each other present variant becomes a `contexts[ctx]` override\n * array on a single `modifiers[modifierName]`. Absent variants (per the\n * `modes` already applied to `result`) are omitted — light is always present\n * and is the modifier `default`. Only the resolver-specific options are read;\n * `modes` / `colorSpace` were already consumed by the `buildDtcgMap` call that\n * produced `result`.\n */\nexport function buildDtcgResolver(\n result: GlazeDtcgResult,\n options?: GlazeDtcgResolverOptions,\n): GlazeDtcgResolverDocument {\n const setName = options?.setName ?? 'base';\n const modifierName = options?.modifierName ?? 'scheme';\n const ctx = {\n ...DEFAULT_DTCG_CONTEXT_NAMES,\n ...options?.contextNames,\n };\n const contexts: Record<string, DtcgTokenTree[]> = {\n [ctx.light]: [],\n };\n if (result.dark) contexts[ctx.dark] = [result.dark];\n if (result.lightContrast) {\n contexts[ctx.lightContrast] = [result.lightContrast];\n }\n if (result.darkContrast) contexts[ctx.darkContrast] = [result.darkContrast];\n\n return {\n version: options?.version ?? '2025.10',\n sets: {\n [setName]: { sources: [result.light] },\n },\n modifiers: {\n [modifierName]: {\n default: ctx.light,\n contexts,\n },\n },\n resolutionOrder: [\n { $ref: `#/sets/${setName}` },\n { $ref: `#/modifiers/${modifierName}` },\n ],\n };\n}\n\n// ============================================================================\n// Tailwind CSS v4 (@theme)\n// ============================================================================\n\n/** Per-scheme declaration lines (`--prop: value;`) accumulated for emission. */\nexport interface GlazeTailwindLines {\n light: string[];\n dark: string[];\n lightContrast: string[];\n darkContrast: string[];\n}\n\nfunction tailwindLinesFor(\n resolved: Map<string, ResolvedColor>,\n themePrefix: string,\n cssPrefix: string,\n format: GlazeColorFormat,\n pastel: boolean,\n): GlazeTailwindLines {\n const lines: GlazeTailwindLines = {\n light: [],\n dark: [],\n lightContrast: [],\n darkContrast: [],\n };\n for (const [name, color] of resolved) {\n const prop = `--${cssPrefix}${themePrefix}${name}`;\n lines.light.push(`${prop}: ${formatVariant(color.light, format, pastel)};`);\n lines.dark.push(`${prop}: ${formatVariant(color.dark, format, pastel)};`);\n lines.lightContrast.push(\n `${prop}: ${formatVariant(color.lightContrast, format, pastel)};`,\n );\n lines.darkContrast.push(\n `${prop}: ${formatVariant(color.darkContrast, format, pastel)};`,\n );\n }\n return lines;\n}\n\nfunction indentBlock(text: string, pad: string): string {\n return text\n .split('\\n')\n .map((line) => (line.length === 0 ? line : pad + line))\n .join('\\n');\n}\n\nfunction emitRule(selector: string, body: string): string {\n return `${selector} {\\n${indentBlock(body, ' ')}\\n}`;\n}\n\n/**\n * Emit a CSS block for a set of declarations scoped by one or more selectors\n * / at-rules. Class-like selectors concatenate (`.dark.high-contrast`);\n * at-rules (`@media …`) nest `:root` (or the chained selector) inside.\n */\nfunction emitScoped(\n scopes: string[],\n declarations: string[],\n): string | undefined {\n if (declarations.length === 0) return undefined;\n\n const atRules: string[] = [];\n let selectorChain = '';\n for (const scope of scopes) {\n if (scope.startsWith('@')) atRules.push(scope);\n else selectorChain += scope;\n }\n const selector = selectorChain || ':root';\n\n let css = emitRule(selector, declarations.join('\\n'));\n for (const rule of atRules) {\n css = emitRule(rule, css);\n }\n return css;\n}\n\n/**\n * Render accumulated per-scheme declaration lines as a Tailwind v4 CSS string:\n * an `@theme` block (light baseline) plus dark / high-contrast overrides under\n * the configured selectors. Empty blocks are skipped.\n */\nexport function emitTailwindCss(\n lines: GlazeTailwindLines,\n modes: Required<GlazeOutputModes>,\n darkSelector: string,\n highContrastSelector: string,\n): string {\n const blocks: string[] = [];\n\n if (lines.light.length > 0) {\n blocks.push(emitRule('@theme', lines.light.join('\\n')));\n }\n\n if (modes.dark) {\n const dark = emitScoped([darkSelector], lines.dark);\n if (dark) blocks.push(dark);\n }\n if (modes.highContrast) {\n const hc = emitScoped([highContrastSelector], lines.lightContrast);\n if (hc) blocks.push(hc);\n }\n if (modes.dark && modes.highContrast) {\n const dhc = emitScoped(\n [darkSelector, highContrastSelector],\n lines.darkContrast,\n );\n if (dhc) blocks.push(dhc);\n }\n\n return blocks.join('\\n\\n');\n}\n\n/**\n * Build per-scheme declaration lines for a single theme (used by\n * `theme.tailwind()` and as the palette `buildOne` step).\n */\nexport function buildTailwindLines(\n resolved: Map<string, ResolvedColor>,\n themePrefix: string,\n cssPrefix: string,\n format: GlazeColorFormat,\n pastel: boolean,\n): GlazeTailwindLines {\n return tailwindLinesFor(resolved, themePrefix, cssPrefix, format, pastel);\n}\n\n/**\n * Build a complete Tailwind v4 CSS string for a single theme.\n */\nexport function buildTailwindMap(\n resolved: Map<string, ResolvedColor>,\n themePrefix: string,\n cssPrefix: string,\n modes: Required<GlazeOutputModes>,\n format: GlazeColorFormat,\n darkSelector: string,\n highContrastSelector: string,\n pastel = false,\n): string {\n const lines = tailwindLinesFor(\n resolved,\n themePrefix,\n cssPrefix,\n format,\n pastel,\n );\n return emitTailwindCss(lines, modes, darkSelector, highContrastSelector);\n}\n","/**\n * Standalone single-color tokens (`glaze.color()` / `glaze.colorFrom()`).\n *\n * Owns the value-shorthand parser (hex, `rgb()` / `hsl()` / `okhsl()` /\n * `okhst()` / `oklch()`, `{ r, g, b }`, `{ h, s, l }`, `{ h, s, t }`,\n * `{ l, c, h }`), the structured-input validator, the two factory paths\n * (value vs structured), and the JSON-safe export / rehydration round-trip.\n *\n * Tokens store a sparse local config override only. Resolve merges the\n * live global config with that local override (invalidated on\n * `configure()`). Authoring `.export(override?)` freezes\n * `getConfig() ∪ local ∪ override` at call time.\n */\n\nimport {\n freezeConfigForExport,\n getConfig,\n getConfigVersion,\n mergeConfig,\n} from './config';\nimport {\n assertExportKind,\n assertExportVersion,\n GLAZE_EXPORT_VERSION,\n isColorTokenExport,\n} from './serialize';\nimport type { ChannelCtx } from './channels';\nimport { extractOkhslFromValue } from './color-value';\nimport { assertAllPastel, assertNativeFormat } from './format-guard';\nimport { toTone } from './okhst';\nimport { isAbsoluteTone, pairNormal } from './hc-pair';\nimport { resolveAllColors } from './resolver';\nimport {\n buildCssMap,\n buildDtcgMap,\n buildDtcgResolver,\n buildJsonMap,\n buildTailwindMap,\n buildTokenMap,\n resolveModes,\n} from './formatters';\nimport type {\n ColorMap,\n GlazeColorCssOptions,\n GlazeColorDtcgResolverOptions,\n GlazeColorDtcgResult,\n GlazeColorInput,\n GlazeColorInputExport,\n GlazeColorOverrides,\n GlazeColorOverridesExport,\n GlazeColorTailwindOptions,\n GlazeColorToken,\n GlazeColorTokenExport,\n GlazeColorValue,\n GlazeCssResult,\n GlazeConfigOverride,\n GlazeConfigResolved,\n GlazeDtcgOptions,\n GlazeDtcgResolverDocument,\n GlazeDtcgResult,\n GlazeJsonOptions,\n GlazeThemeSeed,\n GlazeTokenOptions,\n HCPair,\n OkhslColor,\n RegularColorDef,\n ResolvedColor,\n ToneValue,\n} from './types';\n\n// ============================================================================\n// Standalone color constants\n// ============================================================================\n\n/** Internal name of the user-facing standalone color in the synthesized def map. */\nconst STANDALONE_VALUE = 'value';\n/** Internal name of the hidden static-anchor seed used for relative tone / contrast. */\nconst STANDALONE_SEED = 'seed';\n/** Internal name of an externally-resolved `GlazeColorToken` injected as a base reference. */\nconst STANDALONE_BASE = 'externalBase';\n\n/** Reserved internal names that user-supplied `name` must not collide with. */\nconst RESERVED_STANDALONE_NAMES = new Set([\n STANDALONE_VALUE,\n STANDALONE_SEED,\n STANDALONE_BASE,\n]);\n\n// ============================================================================\n// Sparse local config (no global freeze at create)\n// ============================================================================\n\n/**\n * Value-form local override: `lightTone` defaults to `false` (preserve\n * input tone). User override fields win.\n */\nfunction sparseValueFormLocal(\n userOverride?: GlazeConfigOverride,\n): GlazeConfigOverride {\n return {\n ...userOverride,\n lightTone:\n userOverride?.lightTone !== undefined ? userOverride.lightTone : false,\n };\n}\n\n// ============================================================================\n// Input validation\n// ============================================================================\n\n/**\n * Validate a user-supplied `opacity` override on `glaze.color()`.\n * Must be a finite number in `0..=1`.\n */\nfunction validateStandaloneOpacity(value: number): void {\n if (!Number.isFinite(value) || value < 0 || value > 1) {\n throw new Error(\n `glaze.color: opacity must be a finite number in 0–1 (got ${value}).`,\n );\n }\n}\n\n/**\n * Validate a structured `GlazeColorInput`. Range-checks the `hue` /\n * `saturation` / `tone` numerics (and any HC-pair second value)\n * before the resolver sees them so out-of-range or non-finite inputs\n * fail with a helpful, top-level error rather than producing a\n * NaN-laden token. `opacity` is checked here too so all input\n * validation lives in one place.\n */\nfunction validateStructuredInput(input: GlazeColorInput): void {\n if (!Number.isFinite(input.hue)) {\n throw new Error(\n `glaze.color: structured hue must be a finite number (got ${input.hue}).`,\n );\n }\n if (\n !Number.isFinite(input.saturation) ||\n input.saturation < 0 ||\n input.saturation > 100\n ) {\n throw new Error(\n `glaze.color: structured saturation must be a finite number in 0–100 (got ${input.saturation}).`,\n );\n }\n const checkTone = (value: number | string, label: string): void => {\n // 'max' / 'min' extreme keywords are always valid.\n if (value === 'max' || value === 'min') return;\n if (\n typeof value !== 'number' ||\n !Number.isFinite(value) ||\n value < 0 ||\n value > 100\n ) {\n throw new Error(\n `glaze.color: structured ${label} must be a finite number in 0–100 or 'max'/'min' (got ${String(value)}).`,\n );\n }\n };\n if (Array.isArray(input.tone)) {\n checkTone(input.tone[0], 'tone[normal]');\n checkTone(input.tone[1], 'tone[hc]');\n } else {\n checkTone(input.tone, 'tone');\n }\n if (input.saturationFactor !== undefined) {\n if (\n !Number.isFinite(input.saturationFactor) ||\n input.saturationFactor < 0 ||\n input.saturationFactor > 1\n ) {\n throw new Error(\n `glaze.color: structured saturationFactor must be a finite number in 0–1 (got ${input.saturationFactor}).`,\n );\n }\n }\n if (typeof input.darkHue === 'number' && !Number.isFinite(input.darkHue)) {\n throw new Error(\n `glaze.color: structured darkHue must be a finite number (got ${input.darkHue}).`,\n );\n }\n if (input.darkSaturation !== undefined) {\n if (\n !Number.isFinite(input.darkSaturation) ||\n input.darkSaturation < 0 ||\n input.darkSaturation > 100\n ) {\n throw new Error(\n `glaze.color: structured darkSaturation must be a finite number in 0–100 (got ${input.darkSaturation}).`,\n );\n }\n }\n if (input.darkSaturationFactor !== undefined) {\n if (\n !Number.isFinite(input.darkSaturationFactor) ||\n input.darkSaturationFactor < 0 ||\n input.darkSaturationFactor > 1\n ) {\n throw new Error(\n `glaze.color: structured darkSaturationFactor must be a finite number in 0–1 (got ${input.darkSaturationFactor}).`,\n );\n }\n }\n if (input.opacity !== undefined) validateStandaloneOpacity(input.opacity);\n}\n\n/**\n * Validate a user-supplied `name` override. Rejects empty / whitespace-only\n * strings and names colliding with `glaze`'s reserved internal sentinels.\n */\nfunction validateStandaloneName(name: string): void {\n if (typeof name !== 'string' || name.trim() === '') {\n throw new Error(\n 'glaze.color: name must be a non-empty string. ' +\n 'Omit `name` if you do not want to set a debug label.',\n );\n }\n if (RESERVED_STANDALONE_NAMES.has(name)) {\n const reserved = [...RESERVED_STANDALONE_NAMES]\n .map((n) => `\"${n}\"`)\n .join(', ');\n throw new Error(\n `glaze.color: name \"${name}\" is reserved (used internally). ` +\n `Reserved names are: ${reserved}. Pick a different name.`,\n );\n }\n}\n\n// ============================================================================\n// Factory: shared helpers\n// ============================================================================\n\ninterface ValueDefsResult {\n seed: GlazeThemeSeed;\n defs: ColorMap;\n primary: string;\n}\n\n/**\n * Resolve `'max'` / `'min'` to their literal author tones (100 / 0).\n *\n * The hidden `STANDALONE_SEED` anchor exists only so `contrast` has something\n * to measure against — it is not an authored base. Pinning the extreme keeps\n * the token on the plain scheme mapping instead of the base-anchored dark\n * replay the resolver applies to real `base` references.\n */\nfunction pinExtremeTone(tone: HCPair<ToneValue>): HCPair<ToneValue> {\n const pin = (value: ToneValue): ToneValue =>\n value === 'max' ? 100 : value === 'min' ? 0 : value;\n return Array.isArray(tone) ? [pin(tone[0]), pin(tone[1])] : pin(tone);\n}\n\n/**\n * Build the `ColorMap` for a value-shorthand `glaze.color()` call.\n *\n * The user-facing color (`STANDALONE_VALUE`) defaults to `mode: 'auto'`\n * across every value-shorthand form.\n *\n * An absolute `hue` override becomes the seed while a relative one becomes a\n * def field; `darkHue` always lands on the def in either form, so an absolute\n * `darkHue` wins outright instead of being re-offset by a relative `hue`.\n *\n * When the user requests `contrast` or relative `tone`, a hidden\n * `STANDALONE_SEED` def is synthesized at `mode: 'static'`. That keeps\n * the seed pinned to the literal user-provided color across all four\n * variants, so the contrast solver always anchors against it.\n */\nfunction buildStandaloneValueDefs(\n main: OkhslColor,\n options: GlazeColorOverrides | undefined,\n): ValueDefsResult {\n const seedHue = typeof options?.hue === 'number' ? options.hue : main.h;\n const seedSaturation = options?.saturation ?? main.s * 100;\n const relativeHue =\n typeof options?.hue === 'string' ? options.hue : undefined;\n\n const toneOption = options?.tone;\n const hasExternalBase = options?.base !== undefined;\n // Seed-anchor synthesis only kicks in when the user did NOT supply their\n // own base — in that case `contrast` and relative `tone` anchor to\n // the literal seed via the hidden `STANDALONE_SEED` def.\n const needsSeedAnchor =\n !hasExternalBase &&\n (options?.contrast !== undefined ||\n (toneOption !== undefined && !isAbsoluteTone(toneOption)));\n\n if (options?.opacity !== undefined)\n validateStandaloneOpacity(options.opacity);\n\n const userName = options?.name;\n if (userName !== undefined) validateStandaloneName(userName);\n const primary = userName ?? STANDALONE_VALUE;\n\n // The seed color is given in OKHSL lightness; express it as canonical tone.\n const seedTone = toTone(main.l);\n\n const primaryTone = toneOption ?? seedTone;\n\n const valueDef: RegularColorDef = {\n hue: relativeHue,\n saturation: options?.saturationFactor,\n darkHue: options?.darkHue,\n darkSaturation: options?.darkSaturationFactor,\n tone: needsSeedAnchor ? pinExtremeTone(primaryTone) : primaryTone,\n contrast: options?.contrast,\n mode: options?.mode ?? 'auto',\n autoFlip: options?.autoFlip,\n opacity: options?.opacity,\n pastel: options?.pastel,\n role: options?.role,\n base: hasExternalBase\n ? STANDALONE_BASE\n : needsSeedAnchor\n ? STANDALONE_SEED\n : undefined,\n };\n\n const defs: ColorMap = { [primary]: valueDef };\n\n if (needsSeedAnchor) {\n defs[STANDALONE_SEED] = {\n hue: main.h,\n saturation: 1,\n tone: seedTone,\n mode: 'static',\n };\n }\n\n return {\n seed: {\n hue: seedHue,\n saturation: seedSaturation,\n darkSaturation: options?.darkSaturation,\n },\n defs,\n primary,\n };\n}\n\nfunction createColorTokenFromDefs(\n seed: GlazeThemeSeed,\n defs: ColorMap,\n primary: string,\n configOverride: GlazeConfigOverride | undefined,\n baseToken: GlazeColorToken | undefined,\n buildExport: (override?: GlazeConfigOverride) => GlazeColorTokenExport,\n): GlazeColorToken {\n let cache: {\n map: Map<string, ResolvedColor> | null;\n version: number;\n effectiveConfig: GlazeConfigResolved;\n } | null = null;\n\n function getEffectiveConfig(): GlazeConfigResolved {\n const version = getConfigVersion();\n if (cache && cache.version === version) return cache.effectiveConfig;\n const effectiveConfig = mergeConfig(getConfig(), configOverride);\n cache = { map: null, version, effectiveConfig };\n return effectiveConfig;\n }\n\n const resolveOnce = (): Map<string, ResolvedColor> => {\n const version = getConfigVersion();\n if (cache && cache.version === version && cache.map) return cache.map;\n const effectiveConfig = getEffectiveConfig();\n const externalBases = baseToken\n ? new Map([[STANDALONE_BASE, baseToken.resolve()]])\n : undefined;\n const map = resolveAllColors(seed, defs, effectiveConfig, externalBases);\n cache = { map, version, effectiveConfig };\n return map;\n };\n\n const resolveStates = (options?: GlazeTokenOptions) => {\n const cfg = getConfig();\n return {\n dark: options?.states?.dark ?? cfg.states.dark,\n highContrast: options?.states?.highContrast ?? cfg.states.highContrast,\n };\n };\n\n const tokenLike = (options?: GlazeTokenOptions): Record<string, string> => {\n const tokenMap = buildTokenMap(\n resolveOnce(),\n '',\n resolveStates(options),\n resolveModes(options?.modes),\n options?.format ?? 'oklch',\n getEffectiveConfig().pastel,\n );\n return tokenMap[`#${primary}`];\n };\n\n return {\n resolve(): ResolvedColor {\n return resolveOnce().get(primary)!;\n },\n\n token: tokenLike,\n tasty: tokenLike,\n\n json(options?: GlazeJsonOptions): Record<string, string> {\n const format = options?.format ?? 'oklch';\n assertNativeFormat(format, 'json');\n const jsonMap = buildJsonMap(\n resolveOnce(),\n resolveModes(options?.modes),\n format,\n getEffectiveConfig().pastel,\n );\n return jsonMap[primary];\n },\n\n css(options: GlazeColorCssOptions): GlazeCssResult {\n const format = options.format ?? 'oklch';\n assertNativeFormat(format, 'css');\n const resolved = resolveOnce().get(primary)!;\n const renamed = new Map<string, ResolvedColor>([\n [options.name, resolved],\n ]);\n\n let channelCtx: ChannelCtx | undefined;\n if (options.splitHue && format === 'oklch') {\n const modes = resolveModes();\n assertAllPastel(renamed, modes);\n channelCtx = {\n seedHue: seed.hue,\n baseName: options.name,\n prefix: '',\n defs: { [options.name]: defs[primary] },\n mode: 'standalone',\n resolvedHue: resolved.light.h,\n };\n }\n\n return buildCssMap(\n renamed,\n '',\n options.suffix ?? '-color',\n format,\n getEffectiveConfig().pastel,\n channelCtx,\n );\n },\n\n dtcg(options?: GlazeDtcgOptions): GlazeColorDtcgResult {\n const modes = resolveModes(options?.modes);\n const doc = buildDtcgMap(\n resolveOnce(),\n '',\n modes,\n options?.colorSpace ?? 'srgb',\n getEffectiveConfig().pastel,\n );\n const result: GlazeColorDtcgResult = { light: doc.light[primary] };\n if (doc.dark) result.dark = doc.dark[primary];\n if (doc.lightContrast) {\n result.lightContrast = doc.lightContrast[primary];\n }\n if (doc.darkContrast) result.darkContrast = doc.darkContrast[primary];\n return result;\n },\n\n dtcgResolver(\n options: GlazeColorDtcgResolverOptions,\n ): GlazeDtcgResolverDocument {\n const doc = buildDtcgMap(\n resolveOnce(),\n '',\n resolveModes(options?.modes),\n options?.colorSpace ?? 'srgb',\n getEffectiveConfig().pastel,\n );\n const name = options.name;\n const result: GlazeDtcgResult = {\n light: { [name]: doc.light[primary] },\n };\n if (doc.dark) result.dark = { [name]: doc.dark[primary] };\n if (doc.lightContrast) {\n result.lightContrast = { [name]: doc.lightContrast[primary] };\n }\n if (doc.darkContrast) {\n result.darkContrast = { [name]: doc.darkContrast[primary] };\n }\n return buildDtcgResolver(result, options);\n },\n\n tailwind(options: GlazeColorTailwindOptions): string {\n const format = options.format ?? 'oklch';\n assertNativeFormat(format, 'tailwind');\n const renamed = new Map<string, ResolvedColor>([\n [options.name, resolveOnce().get(primary)!],\n ]);\n return buildTailwindMap(\n renamed,\n '',\n options.namespace ?? 'color-',\n resolveModes(options?.modes),\n format,\n options.darkSelector ?? '.dark',\n options.highContrastSelector ?? '.high-contrast',\n getEffectiveConfig().pastel,\n );\n },\n\n export(override?: GlazeConfigOverride): GlazeColorTokenExport {\n return buildExport(override);\n },\n };\n}\n\n/**\n * When a value/`from` color links to a base that was created via the\n * structured form (with explicit `hue`/`saturation`/`tone`), resolve\n * that base with `lightTone: false` for the linking math so the\n * contrast/tone anchor matches the input tone — not the\n * windowed output. The original base token's `.resolve()` is unaffected.\n */\nfunction toLinkingBase(\n base: GlazeColorToken | undefined,\n): GlazeColorToken | undefined {\n if (!base) return undefined;\n const exp = base.export();\n if (exp.form !== 'structured') return base;\n const linkingConfig: GlazeConfigOverride = {\n ...(exp.config ?? {}),\n lightTone: false,\n };\n return colorFromExport({ ...exp, config: linkingConfig });\n}\n\n/**\n * Resolve `base` (which may be a token reference or a raw color value)\n * into a `GlazeColorToken`. Raw values are auto-wrapped via\n * `createColorTokenFromValue` so they pick up the same auto-invert\n * defaults as an explicit wrap. Returns `undefined` when no base is provided.\n */\nfunction resolveBaseToken(\n base: GlazeColorToken | GlazeColorValue | undefined,\n): GlazeColorToken | undefined {\n if (base === undefined) return undefined;\n if (isGlazeColorToken(base)) return base;\n return createColorTokenFromValue(base, undefined, undefined);\n}\n\n/**\n * Discriminate a `GlazeColorToken` from a raw `GlazeColorValue`.\n */\nexport function isGlazeColorToken(\n candidate: GlazeColorToken | GlazeColorValue,\n): candidate is GlazeColorToken {\n return (\n typeof candidate === 'object' &&\n candidate !== null &&\n !Array.isArray(candidate) &&\n 'resolve' in candidate &&\n typeof (candidate as { resolve?: unknown }).resolve === 'function'\n );\n}\n\n// ============================================================================\n// Factory: structured input\n// ============================================================================\n\nexport function createColorToken(\n input: GlazeColorInput,\n configOverride?: GlazeConfigOverride,\n): GlazeColorToken {\n validateStructuredInput(input);\n\n const userName = input.name;\n if (userName !== undefined) validateStandaloneName(userName);\n const primary = userName ?? STANDALONE_VALUE;\n\n const baseToken = resolveBaseToken(input.base);\n const hasExternalBase = baseToken !== undefined;\n const needsSeedAnchor = !hasExternalBase && input.contrast !== undefined;\n\n const defs: ColorMap = {\n [primary]: {\n tone: needsSeedAnchor ? pinExtremeTone(input.tone) : input.tone,\n saturation: input.saturationFactor,\n darkHue: input.darkHue,\n darkSaturation: input.darkSaturationFactor,\n mode: input.mode ?? 'auto',\n autoFlip: input.autoFlip,\n contrast: input.contrast,\n opacity: input.opacity,\n pastel: input.pastel,\n role: input.role,\n base: hasExternalBase\n ? STANDALONE_BASE\n : needsSeedAnchor\n ? STANDALONE_SEED\n : undefined,\n },\n };\n\n if (needsSeedAnchor) {\n defs[STANDALONE_SEED] = {\n // The seed anchor must be a concrete tone; resolve 'max'/'min' to its\n // extreme so the static anchor is well-defined.\n tone: pinExtremeTone(pairNormal(input.tone)),\n saturation: 1,\n mode: 'static',\n };\n }\n\n const localOverride = configOverride;\n\n return createColorTokenFromDefs(\n {\n hue: input.hue,\n saturation: input.saturation,\n darkSaturation: input.darkSaturation,\n },\n defs,\n primary,\n localOverride,\n baseToken,\n (exportArg) => ({\n kind: 'color',\n version: GLAZE_EXPORT_VERSION,\n form: 'structured',\n input: buildStructuredInputExport(input, exportArg),\n config: freezeConfigForExport(localOverride, exportArg),\n }),\n );\n}\n\n// ============================================================================\n// Factory: value-shorthand input\n// ============================================================================\n\nexport function createColorTokenFromValue(\n value: GlazeColorValue,\n options: GlazeColorOverrides | undefined,\n configOverride: GlazeConfigOverride | undefined,\n): GlazeColorToken {\n const main = extractOkhslFromValue(value);\n const rawBaseToken = resolveBaseToken(options?.base);\n // For linking math, structured bases are re-resolved at full range\n // (lightTone: false) so contrast/tone anchors use the\n // input tone, not the windowed output.\n const linkingBase = toLinkingBase(rawBaseToken);\n const { seed, defs, primary } = buildStandaloneValueDefs(main, options);\n\n const localOverride = sparseValueFormLocal(configOverride);\n\n return createColorTokenFromDefs(\n seed,\n defs,\n primary,\n localOverride,\n linkingBase,\n (exportArg) => ({\n kind: 'color',\n version: GLAZE_EXPORT_VERSION,\n form: 'value',\n input: value,\n ...(options !== undefined\n ? { overrides: buildOverridesExport(options, exportArg) }\n : {}),\n config: freezeConfigForExport(localOverride, exportArg),\n }),\n );\n}\n\n// ============================================================================\n// Export / rehydrate\n// ============================================================================\n\n/**\n * Build a JSON-safe snapshot of `GlazeColorOverrides`. `base` is\n * recursively serialized when it was originally a token; raw values are\n * preserved as-is so `glaze.colorFrom(...)` round-trips them.\n */\nfunction buildOverridesExport(\n options: GlazeColorOverrides,\n exportArg?: GlazeConfigOverride,\n): GlazeColorOverridesExport {\n const out: GlazeColorOverridesExport = {};\n if (options.hue !== undefined) out.hue = options.hue;\n if (options.saturation !== undefined) out.saturation = options.saturation;\n if (options.tone !== undefined) out.tone = options.tone;\n if (options.saturationFactor !== undefined) {\n out.saturationFactor = options.saturationFactor;\n }\n if (options.darkHue !== undefined) out.darkHue = options.darkHue;\n if (options.darkSaturation !== undefined) {\n out.darkSaturation = options.darkSaturation;\n }\n if (options.darkSaturationFactor !== undefined) {\n out.darkSaturationFactor = options.darkSaturationFactor;\n }\n if (options.mode !== undefined) out.mode = options.mode;\n if (options.autoFlip !== undefined) out.autoFlip = options.autoFlip;\n if (options.contrast !== undefined) out.contrast = options.contrast;\n if (options.opacity !== undefined) out.opacity = options.opacity;\n if (options.name !== undefined) out.name = options.name;\n if (options.pastel !== undefined) out.pastel = options.pastel;\n if (options.role !== undefined) out.role = options.role;\n if (options.base !== undefined) {\n out.base = isGlazeColorToken(options.base)\n ? options.base.export(exportArg)\n : options.base;\n }\n return out;\n}\n\nfunction buildStructuredInputExport(\n input: GlazeColorInput,\n exportArg?: GlazeConfigOverride,\n): GlazeColorInputExport {\n const out: GlazeColorInputExport = {\n hue: input.hue,\n saturation: input.saturation,\n tone: input.tone,\n };\n if (input.saturationFactor !== undefined) {\n out.saturationFactor = input.saturationFactor;\n }\n if (input.darkHue !== undefined) out.darkHue = input.darkHue;\n if (input.darkSaturation !== undefined) {\n out.darkSaturation = input.darkSaturation;\n }\n if (input.darkSaturationFactor !== undefined) {\n out.darkSaturationFactor = input.darkSaturationFactor;\n }\n if (input.mode !== undefined) out.mode = input.mode;\n if (input.autoFlip !== undefined) out.autoFlip = input.autoFlip;\n if (input.opacity !== undefined) out.opacity = input.opacity;\n if (input.contrast !== undefined) out.contrast = input.contrast;\n if (input.name !== undefined) out.name = input.name;\n if (input.pastel !== undefined) out.pastel = input.pastel;\n if (input.role !== undefined) out.role = input.role;\n if (input.base !== undefined) {\n out.base = isGlazeColorToken(input.base)\n ? input.base.export(exportArg)\n : input.base;\n }\n return out;\n}\n\n/**\n * Discriminate a `GlazeColorTokenExport` from a raw `GlazeColorValue`.\n */\nfunction isExportedToken(\n candidate: GlazeColorTokenExport | GlazeColorValue,\n): candidate is GlazeColorTokenExport {\n return isColorTokenExport(candidate);\n}\n\nfunction rehydrateOverrides(\n data: GlazeColorOverridesExport,\n): GlazeColorOverrides {\n const out: GlazeColorOverrides = {};\n if (data.hue !== undefined) out.hue = data.hue;\n if (data.saturation !== undefined) out.saturation = data.saturation;\n if (data.tone !== undefined) out.tone = data.tone;\n if (data.saturationFactor !== undefined) {\n out.saturationFactor = data.saturationFactor;\n }\n if (data.darkHue !== undefined) out.darkHue = data.darkHue;\n if (data.darkSaturation !== undefined) {\n out.darkSaturation = data.darkSaturation;\n }\n if (data.darkSaturationFactor !== undefined) {\n out.darkSaturationFactor = data.darkSaturationFactor;\n }\n if (data.mode !== undefined) out.mode = data.mode;\n if (data.autoFlip !== undefined) out.autoFlip = data.autoFlip;\n if (data.contrast !== undefined) out.contrast = data.contrast;\n if (data.opacity !== undefined) out.opacity = data.opacity;\n if (data.name !== undefined) out.name = data.name;\n if (data.pastel !== undefined) out.pastel = data.pastel;\n if (data.role !== undefined) out.role = data.role;\n if (data.base !== undefined) {\n out.base = isExportedToken(data.base)\n ? colorFromExport(data.base)\n : data.base;\n }\n return out;\n}\n\nfunction rehydrateStructuredInput(\n data: GlazeColorInputExport,\n): GlazeColorInput {\n const out: GlazeColorInput = {\n hue: data.hue,\n saturation: data.saturation,\n tone: data.tone,\n };\n if (data.saturationFactor !== undefined) {\n out.saturationFactor = data.saturationFactor;\n }\n if (data.darkHue !== undefined) out.darkHue = data.darkHue;\n if (data.darkSaturation !== undefined) {\n out.darkSaturation = data.darkSaturation;\n }\n if (data.darkSaturationFactor !== undefined) {\n out.darkSaturationFactor = data.darkSaturationFactor;\n }\n if (data.mode !== undefined) out.mode = data.mode;\n if (data.autoFlip !== undefined) out.autoFlip = data.autoFlip;\n if (data.opacity !== undefined) out.opacity = data.opacity;\n if (data.contrast !== undefined) out.contrast = data.contrast;\n if (data.name !== undefined) out.name = data.name;\n if (data.pastel !== undefined) out.pastel = data.pastel;\n if (data.role !== undefined) out.role = data.role;\n if (data.base !== undefined) {\n out.base = isExportedToken(data.base)\n ? colorFromExport(data.base)\n : data.base;\n }\n return out;\n}\n\n/**\n * Rehydrate a token from its `.export()` snapshot. Recursively rebuilds\n * any base dependency. Inverse of `GlazeColorToken.export()`.\n *\n * The stored `config` field is the freeze from export time — passed as\n * the instance local override so the rehydrated token stays pinned\n * against later `glaze.configure()` calls.\n */\nexport function colorFromExport(data: GlazeColorTokenExport): GlazeColorToken {\n if (data === null || typeof data !== 'object') {\n throw new Error(\n `glaze.colorFrom: expected an object from token.export(), got ${data === null ? 'null' : typeof data}.`,\n );\n }\n assertExportKind(data, 'color', 'glaze.colorFrom');\n assertExportVersion(data, 'glaze.colorFrom');\n if (data.form !== 'value' && data.form !== 'structured') {\n throw new Error(\n `glaze.colorFrom: invalid \"form\" field — expected \"value\" or \"structured\" (got ${JSON.stringify((data as { form?: unknown }).form)}).`,\n );\n }\n if (data.input === undefined) {\n throw new Error(\n `glaze.colorFrom: missing \"input\" field — expected the original ${data.form === 'value' ? 'GlazeColorValue' : 'GlazeColorInput'}.`,\n );\n }\n\n if (data.form === 'value') {\n const value = data.input as GlazeColorValue;\n const overrides = data.overrides\n ? rehydrateOverrides(data.overrides)\n : undefined;\n return createColorTokenFromValue(value, overrides, data.config);\n }\n\n const input = rehydrateStructuredInput(data.input as GlazeColorInputExport);\n return createColorToken(input, data.config);\n}\n","/**\n * Theme factory.\n *\n * Wraps a hue/saturation seed, a mutable `ColorMap`, and an optional\n * per-theme `GlazeConfigOverride`. Exposes `tokens()` / `tasty()` /\n * `json()` / `css()` / `dtcg()` / `dtcgResolver()` / `tailwind()` / `resolve()` /\n * `export()` / `extend()`.\n *\n * The per-theme config override is **merged over the live global config at\n * resolve time** so the theme still reacts to later `configure()` calls\n * for fields it didn't override. The merged config is memoized by\n * `configVersion` to avoid rebuilding it on every export call.\n */\n\nimport type { ChannelCtx } from './channels';\nimport {\n freezeConfigForExport,\n getConfig,\n getConfigVersion,\n mergeConfig,\n} from './config';\nimport { assertAllPastel, assertNativeFormat } from './format-guard';\nimport {\n buildCssMap,\n buildDtcgMap,\n buildDtcgResolver,\n buildFlatTokenMap,\n buildJsonMap,\n buildTailwindMap,\n buildTokenMap,\n resolveModes,\n} from './formatters';\nimport { resolveAllColors } from './resolver';\nimport { GLAZE_EXPORT_VERSION } from './serialize';\nimport type {\n ColorDef,\n ColorMap,\n GlazeConfigOverride,\n GlazeConfigResolved,\n GlazeCssOptions,\n GlazeCssResult,\n GlazeDtcgOptions,\n GlazeDtcgResolverDocument,\n GlazeDtcgResolverOptions,\n GlazeDtcgResult,\n GlazeExtendOptions,\n GlazeJsonOptions,\n GlazeTailwindOptions,\n GlazeTheme,\n GlazeThemeExport,\n GlazeThemeSeed,\n GlazeTokenOptions,\n ResolvedColor,\n} from './types';\n\nexport function createTheme(\n seed: GlazeThemeSeed,\n initialColors?: ColorMap,\n configOverride?: GlazeConfigOverride,\n): GlazeTheme {\n const { hue, saturation, darkHue, darkSaturation } = seed;\n let colorDefs: ColorMap = initialColors ? { ...initialColors } : {};\n\n let cache: {\n map: Map<string, ResolvedColor> | null;\n version: number;\n effectiveConfig: GlazeConfigResolved;\n } | null = null;\n\n function getEffectiveConfig(): GlazeConfigResolved {\n const version = getConfigVersion();\n if (cache && cache.version === version) return cache.effectiveConfig;\n const effectiveConfig = mergeConfig(getConfig(), configOverride);\n cache = { map: null, version, effectiveConfig };\n return effectiveConfig;\n }\n\n function resolveCached(): Map<string, ResolvedColor> {\n const version = getConfigVersion();\n if (cache && cache.version === version && cache.map) return cache.map;\n const effectiveConfig = getEffectiveConfig();\n const map = resolveAllColors(seed, colorDefs, effectiveConfig);\n cache = { map, version, effectiveConfig };\n return map;\n }\n\n function invalidate(): void {\n cache = null;\n }\n\n function channelCtxFor(\n options:\n | {\n splitHue?: boolean;\n name?: string;\n format?: GlazeCssOptions['format'];\n modes?: GlazeJsonOptions['modes'];\n }\n | undefined,\n formatDefault: 'rgb' | 'oklch' | 'okhsl',\n prefix: string,\n ): ChannelCtx | undefined {\n const format = options?.format ?? formatDefault;\n if (!options?.splitHue || format !== 'oklch') return undefined;\n const resolved = resolveCached();\n const modes = resolveModes(options?.modes);\n assertAllPastel(resolved, modes);\n return {\n seedHue: hue,\n darkSeedHue: darkHue,\n baseName: options.name ?? 'theme',\n prefix,\n defs: colorDefs,\n mode: 'theme',\n };\n }\n\n const theme: GlazeTheme = {\n get hue() {\n return hue;\n },\n get saturation() {\n return saturation;\n },\n get darkHue() {\n return darkHue;\n },\n get darkSaturation() {\n return darkSaturation;\n },\n getConfig(): GlazeConfigResolved {\n return getEffectiveConfig();\n },\n\n colors(defs: ColorMap): void {\n colorDefs = { ...colorDefs, ...defs };\n invalidate();\n },\n\n color(name: string, def?: ColorDef): ColorDef | undefined | void {\n if (def === undefined) {\n return colorDefs[name];\n }\n colorDefs[name] = def;\n invalidate();\n },\n\n remove(names: string | string[]): void {\n const list = Array.isArray(names) ? names : [names];\n for (const name of list) {\n delete colorDefs[name];\n }\n invalidate();\n },\n\n has(name: string): boolean {\n return name in colorDefs;\n },\n\n list(): string[] {\n return Object.keys(colorDefs);\n },\n\n reset(): void {\n colorDefs = {};\n invalidate();\n },\n\n export(override?: GlazeConfigOverride): GlazeThemeExport {\n return {\n kind: 'theme',\n version: GLAZE_EXPORT_VERSION,\n hue,\n saturation,\n ...(darkHue !== undefined ? { darkHue } : {}),\n ...(darkSaturation !== undefined ? { darkSaturation } : {}),\n colors: structuredClone(colorDefs),\n config: freezeConfigForExport(configOverride, override),\n };\n },\n\n extend(options: GlazeExtendOptions): GlazeTheme {\n const childSeed: GlazeThemeSeed = {\n hue: options.hue ?? hue,\n saturation: options.saturation ?? saturation,\n darkHue: options.darkHue ?? darkHue,\n darkSaturation: options.darkSaturation ?? darkSaturation,\n };\n\n const inheritedColors: ColorMap = {};\n for (const [name, def] of Object.entries(colorDefs)) {\n if (def.inherit !== false) {\n inheritedColors[name] = def;\n }\n }\n\n const mergedColors = options.colors\n ? { ...inheritedColors, ...options.colors }\n : { ...inheritedColors };\n\n // Child inherits the parent override then merges in the per-extend override.\n const mergedConfigOverride: GlazeConfigOverride | undefined =\n configOverride || options.config\n ? { ...(configOverride ?? {}), ...(options.config ?? {}) }\n : undefined;\n\n return createTheme(childSeed, mergedColors, mergedConfigOverride);\n },\n\n resolve(): Map<string, ResolvedColor> {\n // Defensive shallow clone: the cache holds the canonical Map for\n // internal exporters; callers that mutate the returned Map must\n // not corrupt subsequent cached reads.\n return new Map(resolveCached());\n },\n\n tokens(options?: GlazeJsonOptions): Record<string, Record<string, string>> {\n const format = options?.format ?? 'oklch';\n assertNativeFormat(format, 'tokens');\n const modes = resolveModes(options?.modes);\n return buildFlatTokenMap(\n resolveCached(),\n '',\n modes,\n format,\n getEffectiveConfig().pastel,\n );\n },\n\n tasty(options?: GlazeTokenOptions): Record<string, Record<string, string>> {\n const cfg = getEffectiveConfig();\n const states = {\n dark: options?.states?.dark ?? cfg.states.dark,\n highContrast: options?.states?.highContrast ?? cfg.states.highContrast,\n };\n const modes = resolveModes(options?.modes);\n const format = options?.format ?? 'oklch';\n const channelCtx = channelCtxFor(options, 'oklch', '');\n return buildTokenMap(\n resolveCached(),\n '',\n states,\n modes,\n format,\n cfg.pastel,\n channelCtx,\n );\n },\n\n json(options?: GlazeJsonOptions): Record<string, Record<string, string>> {\n const format = options?.format ?? 'oklch';\n assertNativeFormat(format, 'json');\n const modes = resolveModes(options?.modes);\n return buildJsonMap(\n resolveCached(),\n modes,\n format,\n getEffectiveConfig().pastel,\n );\n },\n\n css(options?: GlazeCssOptions): GlazeCssResult {\n const format = options?.format ?? 'oklch';\n assertNativeFormat(format, 'css');\n const channelCtx = channelCtxFor(options, 'oklch', '');\n return buildCssMap(\n resolveCached(),\n '',\n options?.suffix ?? '-color',\n format,\n getEffectiveConfig().pastel,\n channelCtx,\n );\n },\n\n dtcg(options?: GlazeDtcgOptions): GlazeDtcgResult {\n const modes = resolveModes(options?.modes);\n return buildDtcgMap(\n resolveCached(),\n '',\n modes,\n options?.colorSpace ?? 'srgb',\n getEffectiveConfig().pastel,\n );\n },\n\n dtcgResolver(\n options?: GlazeDtcgResolverOptions,\n ): GlazeDtcgResolverDocument {\n const result = buildDtcgMap(\n resolveCached(),\n '',\n resolveModes(options?.modes),\n options?.colorSpace ?? 'srgb',\n getEffectiveConfig().pastel,\n );\n return buildDtcgResolver(result, options);\n },\n\n tailwind(options?: GlazeTailwindOptions): string {\n const format = options?.format ?? 'oklch';\n assertNativeFormat(format, 'tailwind');\n const modes = resolveModes(options?.modes);\n return buildTailwindMap(\n resolveCached(),\n '',\n options?.namespace ?? 'color-',\n modes,\n format,\n options?.darkSelector ?? '.dark',\n options?.highContrastSelector ?? '.high-contrast',\n getEffectiveConfig().pastel,\n );\n },\n } as GlazeTheme;\n\n return theme;\n}\n","/**\n * Palette factory.\n *\n * Composes multiple themes into a single token namespace with optional\n * theme-name prefixes and a \"primary theme\" that also surfaces an\n * unprefixed copy of its tokens. All seven export methods (`tokens` /\n * `tasty` / `json` / `css` / `dtcg` / `dtcgResolver` / `tailwind`) share a\n * `buildPaletteOutput` driver that handles validation, per-theme iteration,\n * prefix resolution, collision filtering, and primary duplication.\n *\n * Authoring round-trip: `palette.export()` / `createPaletteFromExport()`\n * (wired as `glaze.paletteFrom`).\n */\n\nimport type { ChannelCtx } from './channels';\nimport { getConfig } from './config';\nimport { assertAllPastel, assertNativeFormat } from './format-guard';\nimport {\n buildCssMap,\n buildDtcgMap,\n buildDtcgResolver,\n buildFlatTokenMap,\n buildJsonMap,\n buildTailwindLines,\n buildTokenMap,\n emitTailwindCss,\n resolveModes,\n} from './formatters';\nimport {\n assertExportKind,\n assertExportVersion,\n GLAZE_EXPORT_VERSION,\n} from './serialize';\nimport { createTheme } from './theme';\nimport type {\n ColorMap,\n GlazeCssOptions,\n GlazeCssResult,\n GlazeConfigOverride,\n GlazeDtcgOptions,\n GlazeDtcgResolverDocument,\n GlazeDtcgResolverOptions,\n GlazeDtcgResult,\n GlazeJsonOptions,\n GlazePalette,\n GlazePaletteExport,\n GlazePaletteExportOptions,\n GlazePaletteOptions,\n GlazeTailwindOptions,\n GlazeTheme,\n GlazeThemeExport,\n GlazeTokenOptions,\n ResolvedColor,\n} from './types';\nimport type { GlazeTailwindLines } from './formatters';\n\ntype PaletteInput = Record<string, GlazeTheme>;\n\nfunction resolvePrefix(\n options: { prefix?: boolean | Record<string, string> } | undefined,\n themeName: string,\n defaultPrefix = false,\n): string {\n const prefix = options?.prefix ?? defaultPrefix;\n if (prefix === true) {\n return `${themeName}-`;\n }\n if (typeof prefix === 'object' && prefix !== null) {\n return prefix[themeName] ?? `${themeName}-`;\n }\n return '';\n}\n\nfunction validatePrimaryTheme(\n primary: string | undefined,\n themes: PaletteInput,\n): void {\n if (primary !== undefined && !(primary in themes)) {\n const available = Object.keys(themes).join(', ');\n throw new Error(\n `glaze: primary theme \"${primary}\" not found in palette. Available: ${available}.`,\n );\n }\n}\n\n/**\n * Resolve the effective primary for an export call.\n * `false` disables, a string overrides, `undefined` inherits from palette.\n */\nfunction resolveEffectivePrimary(\n exportPrimary: string | false | undefined,\n palettePrimary: string | undefined,\n): string | undefined {\n if (exportPrimary === false) return undefined;\n return exportPrimary ?? palettePrimary;\n}\n\n/**\n * Filter a resolved color map, skipping keys already in `seen`.\n * Warns on collision and keeps the first-written value (first-write-wins).\n * Returns a new map containing only non-colliding entries.\n */\nfunction filterCollisions(\n resolved: Map<string, ResolvedColor>,\n prefix: string,\n seen: Map<string, string>,\n themeName: string,\n isPrimary?: boolean,\n): Map<string, ResolvedColor> {\n const filtered = new Map<string, ResolvedColor>();\n const label = isPrimary ? `${themeName} (primary)` : themeName;\n\n for (const [name, color] of resolved) {\n const key = `${prefix}${name}`;\n if (seen.has(key)) {\n console.warn(\n `glaze: token \"${key}\" from theme \"${label}\" collides with theme \"${seen.get(key)}\" — skipping.`,\n );\n continue;\n }\n seen.set(key, label);\n filtered.set(name, color);\n }\n return filtered;\n}\n\nfunction colorMapFromTheme(theme: GlazeTheme): ColorMap {\n const defs: ColorMap = {};\n for (const name of theme.list()) {\n const def = theme.color(name);\n if (def !== undefined) defs[name] = def;\n }\n return defs;\n}\n\nfunction channelCtxForTheme(\n theme: GlazeTheme,\n themeName: string,\n passPrefix: string,\n themedPrefix: string,\n splitHue: boolean | undefined,\n format: string,\n modes: ReturnType<typeof resolveModes>,\n filtered: Map<string, ResolvedColor>,\n): ChannelCtx | undefined {\n if (!splitHue || format !== 'oklch') return undefined;\n assertAllPastel(filtered, modes);\n return {\n seedHue: theme.hue,\n darkSeedHue: theme.darkHue,\n baseName: themeName,\n // Hue var names always follow the themed prefix so the primary's\n // unprefixed alias references `--{themeName}-*-hue` rather than colliding\n // with other themes' base vars.\n prefix: themedPrefix,\n defs: colorMapFromTheme(theme),\n mode: 'theme',\n // Emit declarations only in the pass whose color-prop prefix matches the\n // themed prefix (the prefixed pass, or the single pass when prefix:false).\n emitDeclarations: passPrefix === themedPrefix,\n };\n}\n\n/**\n * Shared per-theme driver for `tokens` / `tasty` / `css`. `json` skips\n * this because it doesn't do collision filtering or primary duplication.\n */\nfunction buildPaletteOutput<T, R>(\n themes: PaletteInput,\n paletteOptions: GlazePaletteOptions | undefined,\n options:\n | {\n prefix?: boolean | Record<string, string>;\n primary?: string | false;\n }\n | undefined,\n buildOne: (\n resolved: Map<string, ResolvedColor>,\n prefix: string,\n pastel: boolean,\n themeName: string,\n theme: GlazeTheme,\n ) => T,\n merge: (acc: R, part: T) => void,\n empty: () => R,\n): R {\n const effectivePrimary = resolveEffectivePrimary(\n options?.primary,\n paletteOptions?.primary,\n );\n if (options?.primary !== undefined) {\n validatePrimaryTheme(effectivePrimary, themes);\n }\n\n const acc = empty();\n const seen = new Map<string, string>();\n\n for (const [themeName, theme] of Object.entries(themes)) {\n const resolved = theme.resolve();\n const pastel = theme.getConfig().pastel;\n const prefix = resolvePrefix(options, themeName, true);\n const filtered = filterCollisions(resolved, prefix, seen, themeName);\n merge(acc, buildOne(filtered, prefix, pastel, themeName, theme));\n\n if (themeName === effectivePrimary) {\n const primaryFiltered = filterCollisions(\n resolved,\n '',\n seen,\n themeName,\n true,\n );\n merge(acc, buildOne(primaryFiltered, '', pastel, themeName, theme));\n }\n }\n\n return acc;\n}\n\n/** Rebuild a theme from a `theme.export()` snapshot. */\nexport function createThemeFromExport(\n data: GlazeThemeExport,\n factory = 'glaze.themeFrom',\n): GlazeTheme {\n if (data === null || typeof data !== 'object') {\n throw new Error(\n `${factory}: expected an object from theme.export(), got ${data === null ? 'null' : typeof data}.`,\n );\n }\n assertExportKind(data, 'theme', factory);\n assertExportVersion(data, factory);\n if (typeof data.hue !== 'number' || typeof data.saturation !== 'number') {\n throw new Error(\n `${factory}: expected numeric \"hue\" and \"saturation\" fields.`,\n );\n }\n for (const field of ['darkHue', 'darkSaturation'] as const) {\n if (data[field] !== undefined && typeof data[field] !== 'number') {\n throw new Error(\n `${factory}: expected \"${field}\" to be a number when present (got ${JSON.stringify(data[field])}).`,\n );\n }\n }\n return createTheme(\n {\n hue: data.hue,\n saturation: data.saturation,\n darkHue: data.darkHue,\n darkSaturation: data.darkSaturation,\n },\n data.colors,\n data.config,\n );\n}\n\n/**\n * Rebuild a palette from a `palette.export()` snapshot.\n */\nexport function createPaletteFromExport(\n data: GlazePaletteExport,\n): GlazePalette {\n if (data === null || typeof data !== 'object') {\n throw new Error(\n `glaze.paletteFrom: expected an object from palette.export(), got ${data === null ? 'null' : typeof data}.`,\n );\n }\n assertExportKind(data, 'palette', 'glaze.paletteFrom');\n assertExportVersion(data, 'glaze.paletteFrom');\n if (data.themes === null || typeof data.themes !== 'object') {\n throw new Error(\n `glaze.paletteFrom: expected a \"themes\" object map of theme exports.`,\n );\n }\n\n const rebuilt: PaletteInput = {};\n for (const [name, themeExport] of Object.entries(data.themes)) {\n rebuilt[name] = createThemeFromExport(\n themeExport,\n `glaze.paletteFrom (theme \"${name}\")`,\n );\n }\n\n return createPalette(rebuilt, {\n primary: data.primary,\n });\n}\n\nexport function createPalette(\n themes: PaletteInput,\n paletteOptions?: GlazePaletteOptions,\n): GlazePalette {\n validatePrimaryTheme(paletteOptions?.primary, themes);\n\n const buildDtcgResult = (\n options?: GlazeDtcgOptions & GlazePaletteExportOptions,\n ): GlazeDtcgResult => {\n const modes = resolveModes(options?.modes);\n const colorSpace = options?.colorSpace ?? 'srgb';\n return buildPaletteOutput<GlazeDtcgResult, GlazeDtcgResult>(\n themes,\n paletteOptions,\n options,\n (filtered, prefix, pastel, _themeName, _theme) =>\n buildDtcgMap(filtered, prefix, modes, colorSpace, pastel),\n (acc, part) => {\n Object.assign(acc.light, part.light);\n if (part.dark) {\n acc.dark = Object.assign(acc.dark ?? {}, part.dark);\n }\n if (part.lightContrast) {\n acc.lightContrast = Object.assign(\n acc.lightContrast ?? {},\n part.lightContrast,\n );\n }\n if (part.darkContrast) {\n acc.darkContrast = Object.assign(\n acc.darkContrast ?? {},\n part.darkContrast,\n );\n }\n },\n () => ({ light: {} }),\n );\n };\n\n return {\n list(): string[] {\n return Object.keys(themes);\n },\n\n get primary(): string | undefined {\n return paletteOptions?.primary;\n },\n\n theme(name: string): GlazeTheme | undefined {\n return themes[name];\n },\n\n themes(): Record<string, GlazeTheme> {\n return { ...themes };\n },\n\n export(override?: GlazeConfigOverride): GlazePaletteExport {\n const themesExport: Record<string, GlazeThemeExport> = {};\n for (const [name, theme] of Object.entries(themes)) {\n themesExport[name] = theme.export(override);\n }\n const out: GlazePaletteExport = {\n kind: 'palette',\n version: GLAZE_EXPORT_VERSION,\n themes: themesExport,\n };\n if (paletteOptions?.primary !== undefined) {\n out.primary = paletteOptions.primary;\n }\n return out;\n },\n\n tokens(\n options?: GlazeJsonOptions & GlazePaletteExportOptions,\n ): Record<string, Record<string, string>> {\n const format = options?.format ?? 'oklch';\n assertNativeFormat(format, 'tokens');\n const modes = resolveModes(options?.modes);\n return buildPaletteOutput<\n Record<string, Record<string, string>>,\n Record<string, Record<string, string>>\n >(\n themes,\n paletteOptions,\n options,\n (filtered, prefix, pastel) =>\n buildFlatTokenMap(filtered, prefix, modes, format, pastel),\n (acc, part) => {\n for (const variant of Object.keys(part)) {\n if (!acc[variant]) {\n acc[variant] = {};\n }\n Object.assign(acc[variant], part[variant]);\n }\n },\n () => ({}),\n );\n },\n\n tasty(\n options?: GlazeTokenOptions & GlazePaletteExportOptions,\n ): Record<string, Record<string, string>> {\n const cfg = getConfig();\n const states = {\n dark: options?.states?.dark ?? cfg.states.dark,\n highContrast: options?.states?.highContrast ?? cfg.states.highContrast,\n };\n const modes = resolveModes(options?.modes);\n const format = options?.format ?? 'oklch';\n return buildPaletteOutput<\n Record<string, Record<string, string>>,\n Record<string, Record<string, string>>\n >(\n themes,\n paletteOptions,\n options,\n (filtered, prefix, pastel, themeName, theme) => {\n const themedPrefix = resolvePrefix(options, themeName, true);\n const channelCtx = channelCtxForTheme(\n theme,\n themeName,\n prefix,\n themedPrefix,\n options?.splitHue,\n format,\n modes,\n filtered,\n );\n return buildTokenMap(\n filtered,\n prefix,\n states,\n modes,\n format,\n pastel,\n channelCtx,\n );\n },\n (acc, part) => Object.assign(acc, part),\n () => ({}),\n );\n },\n\n json(\n options?: GlazeJsonOptions & {\n prefix?: boolean | Record<string, string>;\n },\n ): Record<string, Record<string, Record<string, string>>> {\n const format = options?.format ?? 'oklch';\n assertNativeFormat(format, 'json');\n const modes = resolveModes(options?.modes);\n const result: Record<string, Record<string, Record<string, string>>> = {};\n\n for (const [themeName, theme] of Object.entries(themes)) {\n const resolved = theme.resolve();\n result[themeName] = buildJsonMap(\n resolved,\n modes,\n format,\n theme.getConfig().pastel,\n );\n }\n\n return result;\n },\n\n css(options?: GlazeCssOptions & GlazePaletteExportOptions): GlazeCssResult {\n const suffix = options?.suffix ?? '-color';\n const format = options?.format ?? 'oklch';\n assertNativeFormat(format, 'css');\n const modes = resolveModes();\n\n const lines = buildPaletteOutput<\n GlazeCssResult,\n Record<keyof GlazeCssResult, string[]>\n >(\n themes,\n paletteOptions,\n options,\n (filtered, prefix, pastel, themeName, theme) => {\n const themedPrefix = resolvePrefix(options, themeName, true);\n const channelCtx = channelCtxForTheme(\n theme,\n themeName,\n prefix,\n themedPrefix,\n options?.splitHue,\n format,\n modes,\n filtered,\n );\n return buildCssMap(\n filtered,\n prefix,\n suffix,\n format,\n pastel,\n channelCtx,\n );\n },\n (acc, part) => {\n for (const key of [\n 'light',\n 'dark',\n 'lightContrast',\n 'darkContrast',\n ] as const) {\n if (part[key]) {\n acc[key].push(part[key]);\n }\n }\n },\n () => ({\n light: [],\n dark: [],\n lightContrast: [],\n darkContrast: [],\n }),\n );\n\n return {\n light: lines.light.join('\\n'),\n dark: lines.dark.join('\\n'),\n lightContrast: lines.lightContrast.join('\\n'),\n darkContrast: lines.darkContrast.join('\\n'),\n };\n },\n\n dtcg(\n options?: GlazeDtcgOptions & GlazePaletteExportOptions,\n ): GlazeDtcgResult {\n return buildDtcgResult(options);\n },\n\n dtcgResolver(\n options?: GlazeDtcgResolverOptions & GlazePaletteExportOptions,\n ): GlazeDtcgResolverDocument {\n return buildDtcgResolver(buildDtcgResult(options), options);\n },\n\n tailwind(\n options?: GlazeTailwindOptions & GlazePaletteExportOptions,\n ): string {\n const modes = resolveModes(options?.modes);\n const cssPrefix = options?.namespace ?? 'color-';\n const format = options?.format ?? 'oklch';\n assertNativeFormat(format, 'tailwind');\n const darkSelector = options?.darkSelector ?? '.dark';\n const highContrastSelector =\n options?.highContrastSelector ?? '.high-contrast';\n\n const lines = buildPaletteOutput<GlazeTailwindLines, GlazeTailwindLines>(\n themes,\n paletteOptions,\n options,\n (filtered, prefix, pastel, _themeName, _theme) =>\n buildTailwindLines(filtered, prefix, cssPrefix, format, pastel),\n (acc, part) => {\n for (const variant of [\n 'light',\n 'dark',\n 'lightContrast',\n 'darkContrast',\n ] as const) {\n acc[variant].push(...part[variant]);\n }\n },\n () => ({\n light: [],\n dark: [],\n lightContrast: [],\n darkContrast: [],\n }),\n );\n\n return emitTailwindCss(lines, modes, darkSelector, highContrastSelector);\n },\n };\n}\n","/**\n * Glaze — OKHST color theme generator.\n *\n * Public API entry. Wires `glaze()` and its attached static methods to\n * the focused modules in this folder:\n * - `theme.ts` — single-theme factory\n * - `palette.ts` — multi-theme composition\n * - `color-token.ts` — standalone single-color tokens (`glaze.color`)\n * - `shadow.ts` — standalone shadow factory (`glaze.shadow`)\n * - `formatters.ts` — variant → string (`glaze.format`)\n * - `config.ts` — global config singleton\n * - `serialize.ts` — authoring export type guards / version checks\n */\n\nimport { parseHex, srgbToOkhsl } from './okhsl-color-math';\nimport {\n configure as configureImpl,\n getConfig,\n resetConfig as resetConfigImpl,\n snapshotConfig,\n} from './config';\nimport {\n colorFromExport,\n createColorToken,\n createColorTokenFromValue,\n} from './color-token';\nimport { extractOkhslFromValue } from './color-value';\nimport { formatVariant } from './formatters';\nimport { computeShadow, resolveShadowTuning } from './shadow';\nimport { okhslToOkhst } from './okhst';\nimport {\n createPalette,\n createPaletteFromExport,\n createThemeFromExport,\n} from './palette';\nimport {\n isColorTokenExport,\n isPaletteExport,\n isThemeExport,\n} from './serialize';\nimport { createTheme } from './theme';\nimport type {\n GlazeColorFormat,\n GlazeColorInput,\n GlazeColorToken,\n GlazeColorTokenExport,\n GlazeColorValue,\n GlazeConfig,\n GlazeConfigOverride,\n GlazeConfigResolved,\n GlazeFromInput,\n GlazePalette,\n GlazePaletteExport,\n GlazePaletteOptions,\n GlazeShadowInput,\n GlazeTheme,\n GlazeThemeExport,\n GlazeThemeSeed,\n ResolvedColorVariant,\n} from './types';\n\ntype PaletteInput = Record<string, GlazeTheme>;\n\n/**\n * Create a single-hue glaze theme.\n *\n * An optional `config` override can be supplied to customize the resolve\n * behavior for this theme (tone windows, etc.). The\n * override is **merged over the live global config at resolve time** —\n * the theme still reacts to later `configure()` calls for fields it\n * didn't override.\n *\n * The object form also accepts `darkHue` / `darkSaturation` — a separate\n * seed pair for the dark and dark-high-contrast schemes. Both default to\n * their light counterparts, and an explicit `darkSaturation` opts the theme\n * out of the global `darkDesaturation` reduction.\n *\n * @example\n * ```ts\n * const primary = glaze(280, 80);\n * // or shorthand:\n * const primary = glaze({ hue: 280, saturation: 80 });\n * // with a retuned dark seed:\n * const primary = glaze({ hue: 280, saturation: 80, darkHue: 268, darkSaturation: 65 });\n * // with config override:\n * const raw = glaze(280, 80, { lightTone: false });\n * ```\n */\nexport function glaze(\n hueOrOptions: number | GlazeThemeSeed,\n saturation?: number,\n config?: GlazeConfigOverride,\n): GlazeTheme {\n if (typeof hueOrOptions === 'number') {\n return createTheme(\n { hue: hueOrOptions, saturation: saturation ?? 100 },\n undefined,\n config,\n );\n }\n return createTheme(hueOrOptions, undefined, config);\n}\n\n/** Configure global glaze settings. */\nglaze.configure = function configure(config: GlazeConfig): void {\n configureImpl(config);\n};\n\n/** Compose multiple themes into a palette. */\nglaze.palette = function palette(\n themes: PaletteInput,\n options?: GlazePaletteOptions,\n): GlazePalette {\n return createPalette(themes, options);\n};\n\n/**\n * Create a theme from a serialized `theme.export()` snapshot.\n * Prefer this over the legacy `glaze.from` alias.\n */\nglaze.themeFrom = function themeFrom(data: GlazeThemeExport): GlazeTheme {\n return createThemeFromExport(data);\n};\n\n/** Compat alias for `glaze.themeFrom`. */\nglaze.from = glaze.themeFrom;\n\n/**\n * Create a standalone single-color token.\n *\n * **arg1 — the color** (four accepted shapes, discriminated by structure):\n *\n * | Shape | Example | Notes |\n * |---|---|---|\n * | Bare string | `'#26fcb2'`, `'rgb(38 252 178)'` | Hex or CSS color function (incl. `okhst()`) |\n * | Value object | `{ h: 152, s: 0.95, l: 0.74 }` | OKHSL, OKHST (`{h,s,t}`), `{r,g,b}`, `{l,c,h}` |\n * | `{ from, ...overrides }` | `{ from: '#fff', base: bg, contrast: 'AA' }` | Value + color overrides |\n * | Structured | `{ hue: 152, saturation: 95, tone: 74 }` | Full theme-style token |\n *\n * **arg2 — config override** (optional, all shapes):\n * Overrides the resolve-relevant global config fields for this token.\n * Fields that are omitted fall through to the live global config at\n * resolve time. Pass `false` for a tone window to disable clamping\n * entirely. `pastel` is instance-only (not set via `configure()`).\n *\n * ```ts\n * // Bare string — no overrides\n * glaze.color('#26fcb2')\n *\n * // From form — value + color overrides\n * glaze.color({ from: '#fff', base: bg, contrast: 'AA' })\n *\n * // Structured form — full theme-style token\n * glaze.color({ hue: 152, saturation: 95, tone: 74 })\n *\n * // Config override on any form\n * glaze.color('#26fcb2', { darkTone: false, autoFlip: false })\n * glaze.color({ from: '#fff', base: bg })\n * ```\n *\n * Defaults: every form defaults to `mode: 'auto'`. Value-shorthand forms\n * (bare strings and value objects) preserve light tone exactly\n * (`lightTone: false` locally). Structured form falls through to the live\n * global tone windows for omitted fields.\n *\n * Relative `tone: '+N'` and `contrast` anchor to the literal seed by\n * default; when `base` is set they anchor to the base's resolved variant\n * per scheme. Relative `hue: '+N'` always anchors to the seed, not the base.\n */\nglaze.color = function color(\n input: GlazeFromInput | GlazeColorInput | GlazeColorValue,\n config?: GlazeConfigOverride,\n): GlazeColorToken {\n if (typeof input === 'string') {\n return createColorTokenFromValue(input, undefined, config);\n }\n\n // Object inputs — discriminate by key presence\n const obj = input as object;\n\n if ('from' in obj) {\n const { from, ...overrides } = input as GlazeFromInput;\n return createColorTokenFromValue(from, overrides, config);\n }\n\n if ('hue' in obj) {\n return createColorToken(input as GlazeColorInput, config);\n }\n\n // Value-object: { h, s, l }, { r, g, b }, or { l, c, h }\n return createColorTokenFromValue(input as GlazeColorValue, undefined, config);\n};\n\n/**\n * Compute a shadow color from a bg/fg pair and intensity.\n *\n * Both `bg` and `fg` accept any `GlazeColorValue` form: hex (`#rgb` /\n * `#rrggbb` / `#rrggbbaa`), `rgb()` / `hsl()` / `okhsl()` / `oklch()`\n * strings, or `{ r, g, b }` / `{ h, s, l }` / `{ l, c, h }` objects.\n */\nglaze.shadow = function shadow(input: GlazeShadowInput): ResolvedColorVariant {\n const bg = extractOkhslFromValue(input.bg as GlazeColorValue);\n const fg = input.fg\n ? extractOkhslFromValue(input.fg as GlazeColorValue)\n : undefined;\n const cfg = getConfig();\n const tuning = resolveShadowTuning(input.tuning, cfg.shadowTuning);\n const result = computeShadow(\n { ...bg, alpha: 1 },\n fg ? { ...fg, alpha: 1 } : undefined,\n input.intensity,\n tuning,\n );\n const { h, s, t } = okhslToOkhst({\n h: result.h,\n s: result.s,\n l: result.l,\n });\n return { h, s, t, alpha: result.alpha };\n};\n\n/** Format a resolved color variant as a CSS string. */\nglaze.format = function format(\n variant: ResolvedColorVariant,\n colorFormat?: GlazeColorFormat,\n pastel?: boolean,\n): string {\n return formatVariant(variant, colorFormat, pastel);\n};\n\n/**\n * Create a theme from a hex color string.\n * Extracts hue and saturation from the color.\n */\nglaze.fromHex = function fromHex(hex: string): GlazeTheme {\n const rgb = parseHex(hex);\n if (!rgb) {\n throw new Error(`glaze: invalid hex color \"${hex}\".`);\n }\n const [h, s] = srgbToOkhsl(rgb);\n return createTheme({ hue: h, saturation: s * 100 });\n};\n\n/**\n * Create a theme from RGB values (0–255).\n * Extracts hue and saturation from the color.\n */\nglaze.fromRgb = function fromRgb(r: number, g: number, b: number): GlazeTheme {\n const [h, s] = srgbToOkhsl([r / 255, g / 255, b / 255]);\n return createTheme({ hue: h, saturation: s * 100 });\n};\n\n/**\n * Rehydrate a `glaze.color()` token from a `.export()` snapshot.\n *\n * The snapshot is a plain JSON-safe object containing the original\n * input value, overrides (with any `base` token recursively serialized),\n * and the effective config freeze from export time. The reconstructed\n * token pins that freeze as its local override.\n *\n * @example\n * ```ts\n * const text = glaze.color({ from: '#1a1a1a', contrast: 'AA' });\n * const data = text.export(); // JSON-safe\n * localStorage.setItem('text', JSON.stringify(data));\n * // ...later...\n * const restored = glaze.colorFrom(JSON.parse(localStorage.getItem('text')!));\n * ```\n */\nglaze.colorFrom = function colorFrom(\n data: GlazeColorTokenExport,\n): GlazeColorToken {\n return colorFromExport(data);\n};\n\n/**\n * Rehydrate a palette from a `palette.export()` snapshot.\n */\nglaze.paletteFrom = function paletteFrom(\n data: GlazePaletteExport,\n): GlazePalette {\n return createPaletteFromExport(data);\n};\n\n/** Type guard for theme authoring snapshots. */\nglaze.isThemeExport = isThemeExport;\n\n/** Type guard for color-token authoring snapshots. */\nglaze.isColorTokenExport = isColorTokenExport;\n\n/** Type guard for palette authoring snapshots. */\nglaze.isPaletteExport = isPaletteExport;\n\n/** Get the current global configuration (for testing/debugging). */\nglaze.getConfig = function getConfig(): GlazeConfigResolved {\n return snapshotConfig();\n};\n\n/** Reset global configuration to defaults. */\nglaze.resetConfig = function resetConfig(): void {\n resetConfigImpl();\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["fmt","ACHROMATIC_EPSILON","SCHEMES","configure","resetConfig"],"sources":["../src/okhsl-color-math.ts","../src/hc-pair.ts","../src/okhst.ts","../src/lighting.ts","../src/contrast-solver.ts","../src/warnings.ts","../src/config.ts","../src/types.ts","../src/serialize.ts","../src/channels.ts","../src/color-value.ts","../src/format-guard.ts","../src/roles.ts","../src/validation.ts","../src/resolver.ts","../src/formatters.ts","../src/color-token.ts","../src/theme.ts","../src/palette.ts","../src/glaze.ts"],"sourcesContent":["/**\n * OKHSL color math primitives for the glaze theme generator.\n *\n * Provides bidirectional OKHSL ↔ sRGB conversion, luminance computation\n * for both contrast metrics (WCAG 2 relative luminance and APCA screen\n * luminance `Ys` — both the exact functions the contrast solver uses, and\n * both public), strict hex parsing (`parseHex` / `parseHexAlpha` check every\n * digit), and multi-format output (okhsl, rgb, hsl, oklch, plus the\n * unclamped `color(srgb …)` / `color(srgb-linear …)` writers for HDR glow\n * values, whose channels may exceed 1).\n */\n\ntype Vec3 = [number, number, number];\n\n// ============================================================================\n// Matrices (from texel-color / Björn Ottosson's reference)\n// ============================================================================\n\nconst OKLab_to_LMS_M: Vec3[] = [\n [1.0, 0.3963377773761749, 0.2158037573099136],\n [1.0, -0.1055613458156586, -0.0638541728258133],\n [1.0, -0.0894841775298119, -1.2914855480194092],\n];\n\nconst LMS_to_linear_sRGB_M: Vec3[] = [\n [4.076741636075959, -3.307711539258062, 0.2309699031821041],\n [-1.2684379732850313, 2.6097573492876878, -0.3413193760026569],\n [-0.004196076138675526, -0.703418617935936, 1.7076146940746113],\n];\n\nconst linear_sRGB_to_LMS_M: Vec3[] = [\n [0.4122214708, 0.5363325363, 0.0514459929],\n [0.2119034982, 0.6806995451, 0.1073969566],\n [0.0883024619, 0.2817188376, 0.6299787005],\n];\n\nconst LMS_to_OKLab_M: Vec3[] = [\n [0.2104542553, 0.793617785, -0.0040720468],\n [1.9779984951, -2.428592205, 0.4505937099],\n [0.0259040371, 0.7827717662, -0.808675766],\n];\n\nconst OKLab_to_linear_sRGB_coefficients: [\n [[number, number], number[]],\n [[number, number], number[]],\n [[number, number], number[]],\n] = [\n [\n [-1.8817030993265873, -0.8093650129914302],\n [1.19086277, 1.76576728, 0.59662641, 0.75515197, 0.56771245],\n ],\n [\n [1.8144407988010998, -1.194452667805235],\n [0.73956515, -0.45954404, 0.08285427, 0.1254107, 0.14503204],\n ],\n [\n [0.13110757611180954, 1.813339709266608],\n [1.35733652, -0.00915799, -1.1513021, -0.50559606, 0.00692167],\n ],\n];\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst TAU = 2 * Math.PI;\nconst K1 = 0.206;\nconst K2 = 0.03;\nconst K3 = (1.0 + K1) / (1.0 + K2);\nconst EPSILON = 1e-10;\n/**\n * OKLab chroma under which an sRGB input counts as gray. An exact sRGB gray\n * leaves float residue in OKLab a / b (at most 3.7e-8, at white); the faintest\n * deliberate tint, one channel 0.01 of 255 off gray, has 1.06e-5.\n */\nconst GRAY_CHROMA = 1e-6;\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nconst constrainAngle = (angle: number): number => ((angle % 360) + 360) % 360;\n/**\n * OKHSL toe function: maps OKLab lightness L to perceptual lightness l.\n * Exported for the OKHST tone transfers in `okhst.ts`.\n */\nexport const toe = (x: number): number =>\n 0.5 *\n (K3 * x - K1 + Math.sqrt((K3 * x - K1) * (K3 * x - K1) + 4 * K2 * K3 * x));\n/** Inverse OKHSL toe: maps perceptual lightness l back to OKLab lightness L. */\nexport const toeInv = (x: number): number =>\n (x ** 2 + K1 * x) / (K3 * (x + K2));\nconst dot3 = (a: Vec3, b: Vec3): number =>\n a[0] * b[0] + a[1] * b[1] + a[2] * b[2];\nconst dotXY = (a: [number, number], b: [number, number]): number =>\n a[0] * b[0] + a[1] * b[1];\nconst transform = (input: Vec3, matrix: Vec3[]): Vec3 => [\n dot3(input, matrix[0]),\n dot3(input, matrix[1]),\n dot3(input, matrix[2]),\n];\nconst cubed3 = (lms: Vec3): Vec3 => [lms[0] ** 3, lms[1] ** 3, lms[2] ** 3];\nconst cbrt3 = (lms: Vec3): Vec3 => [\n Math.cbrt(lms[0]),\n Math.cbrt(lms[1]),\n Math.cbrt(lms[2]),\n];\nconst clampVal = (v: number, min: number, max: number): number =>\n Math.max(min, Math.min(max, v));\n\n// ============================================================================\n// Internal OKHSL pipeline\n// ============================================================================\n\nconst OKLabToLinearSRGB = (lab: Vec3): Vec3 => {\n const lms = transform(lab, OKLab_to_LMS_M);\n return transform(cubed3(lms), LMS_to_linear_sRGB_M);\n};\n\nconst computeMaxSaturationOKLC = (a: number, b: number): number => {\n const okCoeff = OKLab_to_linear_sRGB_coefficients;\n const lmsToRgb = LMS_to_linear_sRGB_M;\n const tmp2: [number, number] = [a, b];\n const tmp3: Vec3 = [0, a, b];\n\n let chnlCoeff: number[];\n let chnlLMS: Vec3;\n\n if (dotXY(okCoeff[0][0], tmp2) > 1) {\n chnlCoeff = okCoeff[0][1];\n chnlLMS = lmsToRgb[0];\n } else if (dotXY(okCoeff[1][0], tmp2) > 1) {\n chnlCoeff = okCoeff[1][1];\n chnlLMS = lmsToRgb[1];\n } else {\n chnlCoeff = okCoeff[2][1];\n chnlLMS = lmsToRgb[2];\n }\n\n const [k0, k1, k2, k3, k4] = chnlCoeff;\n const [wl, wm, ws] = chnlLMS;\n\n let sat = k0 + k1 * a + k2 * b + k3 * (a * a) + k4 * a * b;\n\n const dotYZ = (mat: Vec3, vec: Vec3): number =>\n mat[1] * vec[1] + mat[2] * vec[2];\n\n const kl = dotYZ(OKLab_to_LMS_M[0], tmp3);\n const km = dotYZ(OKLab_to_LMS_M[1], tmp3);\n const ks = dotYZ(OKLab_to_LMS_M[2], tmp3);\n\n const l_ = 1.0 + sat * kl;\n const m_ = 1.0 + sat * km;\n const s_ = 1.0 + sat * ks;\n\n const l = l_ ** 3;\n const m = m_ ** 3;\n const s = s_ ** 3;\n\n const lds = 3.0 * kl * l_ * l_;\n const mds = 3.0 * km * m_ * m_;\n const sds = 3.0 * ks * s_ * s_;\n\n const lds2 = 6.0 * kl * kl * l_;\n const mds2 = 6.0 * km * km * m_;\n const sds2 = 6.0 * ks * ks * s_;\n\n const f = wl * l + wm * m + ws * s;\n const f1 = wl * lds + wm * mds + ws * sds;\n const f2 = wl * lds2 + wm * mds2 + ws * sds2;\n\n sat = sat - (f * f1) / (f1 * f1 - 0.5 * f * f2);\n\n return sat;\n};\n\nconst findCuspOKLCH = (a: number, b: number): [number, number] => {\n const S_cusp = computeMaxSaturationOKLC(a, b);\n const lab: Vec3 = [1, S_cusp * a, S_cusp * b];\n const rgb_at_max = OKLabToLinearSRGB(lab);\n const L_cusp = Math.cbrt(\n 1 /\n Math.max(\n Math.max(rgb_at_max[0], rgb_at_max[1]),\n Math.max(rgb_at_max[2], 0.0),\n ),\n );\n return [L_cusp, L_cusp * S_cusp];\n};\n\nconst findGamutIntersectionOKLCH = (\n a: number,\n b: number,\n l1: number,\n c1: number,\n l0: number,\n cusp: [number, number],\n): number => {\n const lmsToRgb = LMS_to_linear_sRGB_M;\n const tmp3: Vec3 = [0, a, b];\n const floatMax = Number.MAX_VALUE;\n\n let t: number;\n\n const dotYZ = (mat: Vec3, vec: Vec3): number =>\n mat[1] * vec[1] + mat[2] * vec[2];\n const dotXYZ = (vec: Vec3, x: number, y: number, z: number): number =>\n vec[0] * x + vec[1] * y + vec[2] * z;\n\n if ((l1 - l0) * cusp[1] - (cusp[0] - l0) * c1 <= 0.0) {\n const denom = c1 * cusp[0] + cusp[1] * (l0 - l1);\n t = denom === 0 ? 0 : (cusp[1] * l0) / denom;\n } else {\n const denom = c1 * (cusp[0] - 1.0) + cusp[1] * (l0 - l1);\n t = denom === 0 ? 0 : (cusp[1] * (l0 - 1.0)) / denom;\n\n const dl = l1 - l0;\n const dc = c1;\n const kl = dotYZ(OKLab_to_LMS_M[0], tmp3);\n const km = dotYZ(OKLab_to_LMS_M[1], tmp3);\n const ks = dotYZ(OKLab_to_LMS_M[2], tmp3);\n\n const L = l0 * (1.0 - t) + t * l1;\n const C = t * c1;\n\n const l_ = L + C * kl;\n const m_ = L + C * km;\n const s_ = L + C * ks;\n\n const l = l_ ** 3;\n const m = m_ ** 3;\n const s = s_ ** 3;\n\n const ldt = 3 * (dl + dc * kl) * l_ * l_;\n const mdt = 3 * (dl + dc * km) * m_ * m_;\n const sdt = 3 * (dl + dc * ks) * s_ * s_;\n\n const ldt2 = 6 * (dl + dc * kl) ** 2 * l_;\n const mdt2 = 6 * (dl + dc * km) ** 2 * m_;\n const sdt2 = 6 * (dl + dc * ks) ** 2 * s_;\n\n const r_ = dotXYZ(lmsToRgb[0], l, m, s) - 1;\n const r1 = dotXYZ(lmsToRgb[0], ldt, mdt, sdt);\n const r2 = dotXYZ(lmsToRgb[0], ldt2, mdt2, sdt2);\n const ur = r1 / (r1 * r1 - 0.5 * r_ * r2);\n let tr = -r_ * ur;\n\n const g_ = dotXYZ(lmsToRgb[1], l, m, s) - 1;\n const g1 = dotXYZ(lmsToRgb[1], ldt, mdt, sdt);\n const g2 = dotXYZ(lmsToRgb[1], ldt2, mdt2, sdt2);\n const ug = g1 / (g1 * g1 - 0.5 * g_ * g2);\n let tg = -g_ * ug;\n\n const b_ = dotXYZ(lmsToRgb[2], l, m, s) - 1;\n const b1 = dotXYZ(lmsToRgb[2], ldt, mdt, sdt);\n const b2 = dotXYZ(lmsToRgb[2], ldt2, mdt2, sdt2);\n const ub = b1 / (b1 * b1 - 0.5 * b_ * b2);\n let tb = -b_ * ub;\n\n tr = ur >= 0.0 ? tr : floatMax;\n tg = ug >= 0.0 ? tg : floatMax;\n tb = ub >= 0.0 ? tb : floatMax;\n\n t += Math.min(tr, Math.min(tg, tb));\n }\n\n return t;\n};\n\nconst computeSt = (cusp: [number, number]): [number, number] => [\n cusp[1] / cusp[0],\n cusp[1] / (1 - cusp[0]),\n];\n\nconst computeStMid = (a: number, b: number): [number, number] => [\n 0.11516993 +\n 1.0 /\n (7.4477897 +\n 4.1590124 * b +\n a *\n (-2.19557347 +\n 1.75198401 * b +\n a *\n (-2.13704948 -\n 10.02301043 * b +\n a * (-4.24894561 + 5.38770819 * b + 4.69891013 * a)))),\n 0.11239642 +\n 1.0 /\n (1.6132032 -\n 0.68124379 * b +\n a *\n (0.40370612 +\n 0.90148123 * b +\n a *\n (-0.27087943 +\n 0.6122399 * b +\n a * (0.00299215 - 0.45399568 * b - 0.14661872 * a)))),\n];\n\nconst getCs = (\n L: number,\n a: number,\n b: number,\n cusp: [number, number],\n): [number, number, number] => {\n const cMax = findGamutIntersectionOKLCH(a, b, L, 1, L, cusp);\n const stMax = computeSt(cusp);\n const k = cMax / Math.min(L * stMax[0], (1 - L) * stMax[1]);\n const stMid = computeStMid(a, b);\n let ca = L * stMid[0];\n let cb = (1.0 - L) * stMid[1];\n const cMid =\n 0.9 * k * Math.sqrt(Math.sqrt(1.0 / (1.0 / ca ** 4 + 1.0 / cb ** 4)));\n ca = L * 0.4;\n cb = (1.0 - L) * 0.8;\n const c0 = Math.sqrt(1.0 / (1.0 / ca ** 2 + 1.0 / cb ** 2));\n return [c0, cMid, cMax];\n};\n\nconst CYAN_A = Math.cos((199.8 * Math.PI) / 180);\nconst CYAN_B = Math.sin((199.8 * Math.PI) / 180);\nconst BLUE_A = Math.cos((267.4 * Math.PI) / 180);\nconst BLUE_B = Math.sin((267.4 * Math.PI) / 180);\n\nlet cyanCusp: [number, number] | undefined;\nlet blueCusp: [number, number] | undefined;\n\n/**\n * Computes the maximum safe OKLCH chroma that fits inside the sRGB gamut\n * for all possible hues at a given OKLab lightness `L`.\n */\nexport function computeSafeChromaOKLCH(L: number): number {\n if (!cyanCusp) cyanCusp = findCuspOKLCH(CYAN_A, CYAN_B);\n if (!blueCusp) blueCusp = findCuspOKLCH(BLUE_A, BLUE_B);\n\n const c1 = findGamutIntersectionOKLCH(CYAN_A, CYAN_B, L, 1, L, cyanCusp);\n const c2 = findGamutIntersectionOKLCH(BLUE_A, BLUE_B, L, 1, L, blueCusp);\n return Math.min(c1, c2);\n}\n\n// ============================================================================\n// Public API\n// ============================================================================\n\n/** Per-hue cusp-lightness cache. The cusp is mode-independent, so keying on\n * a rounded hue is safe and keeps the cache small. */\nconst cuspLightnessCache = new Map<number, number>();\n\n/**\n * OKHSL lightness of the gamut cusp for a hue — the lightness where the\n * realizable chroma peaks. Reuses the same `find_cusp` OKHSL already runs for\n * its `s` normalization (no new color math); the OKLab cusp lightness is run\n * through the OKHSL `toe` and clamped to `[0.001, 0.999]` so divisions that\n * key off it stay safe. Cached per (rounded) hue.\n *\n * @param h Hue, 0–360.\n */\nexport function cuspLightness(h: number): number {\n const key = Math.round(constrainAngle(h) * 100) / 100;\n const cached = cuspLightnessCache.get(key);\n if (cached !== undefined) return cached;\n\n const hNorm = key / 360.0;\n const cusp = findCuspOKLCH(Math.cos(TAU * hNorm), Math.sin(TAU * hNorm));\n const lc = clampVal(toe(cusp[0]), 0.001, 0.999);\n cuspLightnessCache.set(key, lc);\n return lc;\n}\n\n/**\n * Convert OKHSL (h: 0–360, s: 0–1, l: 0–1) to OKLab [L, a, b].\n */\nexport function okhslToOklab(\n h: number,\n s: number,\n l: number,\n pastel = false,\n): [number, number, number] {\n const L = toeInv(l);\n let a = 0;\n let b = 0;\n\n const hNorm = constrainAngle(h) / 360.0;\n\n if (L !== 0.0 && L !== 1.0 && s !== 0) {\n const a_ = Math.cos(TAU * hNorm);\n const b_ = Math.sin(TAU * hNorm);\n\n if (pastel) {\n const c = s * computeSafeChromaOKLCH(L);\n a = c * a_;\n b = c * b_;\n } else {\n const cusp = findCuspOKLCH(a_, b_);\n const Cs = getCs(L, a_, b_, cusp);\n const [c0, cMid, cMax] = Cs;\n\n const mid = 0.8;\n const midInv = 1.25;\n let t: number, k0: number, k1: number, k2: number;\n\n if (s < mid) {\n t = midInv * s;\n k0 = 0.0;\n k1 = mid * c0;\n k2 = 1.0 - k1 / cMid;\n } else {\n t = 5 * (s - 0.8);\n k0 = cMid;\n k1 = (0.2 * cMid ** 2 * 1.25 ** 2) / c0;\n k2 = 1.0 - k1 / (cMax - cMid);\n }\n\n const c = k0 + (t * k1) / (1.0 - k2 * t);\n a = c * a_;\n b = c * b_;\n }\n }\n\n return [L, a, b];\n}\n\n/**\n * Convert OKHSL (h: 0–360, s: 0–1, l: 0–1) to linear sRGB.\n * Channels may exceed [0, 1] near gamut boundaries — caller must clamp if needed.\n */\nexport function okhslToLinearSrgb(\n h: number,\n s: number,\n l: number,\n pastel = false,\n): [number, number, number] {\n return OKLabToLinearSRGB(okhslToOklab(h, s, l, pastel));\n}\n\n/**\n * Compute relative luminance Y from linear sRGB channels.\n * Per WCAG 2: Y = 0.2126·R + 0.7152·G + 0.0722·B\n */\nexport function relativeLuminanceFromLinearRgb(\n rgb: [number, number, number],\n): number {\n return 0.2126 * rgb[0] + 0.7152 * rgb[1] + 0.0722 * rgb[2];\n}\n\n/**\n * WCAG 2 contrast ratio from two luminance values.\n */\nexport function contrastRatioFromLuminance(yA: number, yB: number): number {\n const lighter = Math.max(yA, yB);\n const darker = Math.min(yA, yB);\n return (lighter + 0.05) / (darker + 0.05);\n}\n\nexport const sRGBLinearToGamma = (val: number): number => {\n const sign = val < 0 ? -1 : 1;\n const abs = Math.abs(val);\n return abs > 0.0031308\n ? sign * (1.055 * Math.pow(abs, 1 / 2.4) - 0.055)\n : 12.92 * val;\n};\n\nexport const sRGBGammaToLinear = (val: number): number => {\n const sign = val < 0 ? -1 : 1;\n const abs = Math.abs(val);\n return abs <= 0.04045\n ? val / 12.92\n : sign * Math.pow((abs + 0.055) / 1.055, 2.4);\n};\n\n/** Gamma-encoded sRGB clamped to the display gamut — what a browser paints. */\nexport function toDisplayGamma(linearRgb: Vec3): Vec3 {\n return [\n Math.max(0, Math.min(1, sRGBLinearToGamma(linearRgb[0]))),\n Math.max(0, Math.min(1, sRGBLinearToGamma(linearRgb[1]))),\n Math.max(0, Math.min(1, sRGBLinearToGamma(linearRgb[2]))),\n ];\n}\n\n/**\n * Browser alpha compositing: `source-over` interpolates the gamma-encoded\n * channels, not linear light (50% black over white paints `#808080`).\n * Takes display-gamma inputs and returns the composite as linear sRGB for\n * the luminance pipeline.\n */\nexport function compositeOverGamma(\n baseGamma: Vec3,\n overlayGamma: Vec3,\n alpha: number,\n): Vec3 {\n return [\n sRGBGammaToLinear(baseGamma[0] + (overlayGamma[0] - baseGamma[0]) * alpha),\n sRGBGammaToLinear(baseGamma[1] + (overlayGamma[1] - baseGamma[1]) * alpha),\n sRGBGammaToLinear(baseGamma[2] + (overlayGamma[2] - baseGamma[2]) * alpha),\n ];\n}\n\n/**\n * Convert OKHSL to gamma-encoded sRGB (clamped to 0–1).\n * h: 0–360, s: 0–1, l: 0–1. Returns [r, g, b] with each channel 0–1.\n */\nexport function okhslToSrgb(\n h: number,\n s: number,\n l: number,\n pastel = false,\n): [number, number, number] {\n const lin = okhslToLinearSrgb(h, s, l, pastel);\n return [\n Math.max(0, Math.min(1, sRGBLinearToGamma(lin[0]))),\n Math.max(0, Math.min(1, sRGBLinearToGamma(lin[1]))),\n Math.max(0, Math.min(1, sRGBLinearToGamma(lin[2]))),\n ];\n}\n\n/**\n * Compute WCAG 2 relative luminance from linear sRGB, matching the browser\n * rendering pipeline: gamma-encode, clamp to sRGB gamut [0,1], then linearize.\n * This avoids over/under-estimating luminance for out-of-gamut OKHSL colors.\n */\nexport function gamutClampedLuminance(\n linearRgb: [number, number, number],\n): number {\n const r = sRGBGammaToLinear(\n Math.max(0, Math.min(1, sRGBLinearToGamma(linearRgb[0]))),\n );\n const g = sRGBGammaToLinear(\n Math.max(0, Math.min(1, sRGBLinearToGamma(linearRgb[1]))),\n );\n const b = sRGBGammaToLinear(\n Math.max(0, Math.min(1, sRGBLinearToGamma(linearRgb[2]))),\n );\n return 0.2126 * r + 0.7152 * g + 0.0722 * b;\n}\n\n/**\n * Compute APCA screen luminance (`Ys`) from linear sRGB.\n *\n * APCA does not use the WCAG piecewise sRGB EOTF; it defines its own\n * luminance as `0.2126·R^2.4 + 0.7152·G^2.4 + 0.0722·B^2.4` over the\n * gamma-encoded (display) channels with a simple 2.4 exponent. The APCA\n * soft-clamp threshold in `apcaContrast` is calibrated against this basis,\n * so the solver must feed it `Ys`, not WCAG relative luminance. Channels\n * are gamut-clamped to [0, 1] first, matching `gamutClampedLuminance`.\n *\n * This is exactly the luminance Glaze's contrast solver (and its drift\n * check) feeds `apcaContrast`, so\n * `apcaContrast(apcaLuminanceFromLinearRgb(text), apcaLuminanceFromLinearRgb(bg))`\n * reproduces the solver's Lc for a resolved pair.\n */\nexport function apcaLuminanceFromLinearRgb(\n linearRgb: [number, number, number],\n): number {\n const r = Math.max(0, Math.min(1, sRGBLinearToGamma(linearRgb[0])));\n const g = Math.max(0, Math.min(1, sRGBLinearToGamma(linearRgb[1])));\n const b = Math.max(0, Math.min(1, sRGBLinearToGamma(linearRgb[2])));\n return (\n 0.2126 * Math.pow(r, 2.4) +\n 0.7152 * Math.pow(g, 2.4) +\n 0.0722 * Math.pow(b, 2.4)\n );\n}\n\n// ============================================================================\n// Reverse pipeline: sRGB → OKHSL\n// ============================================================================\n\nconst linearSrgbToOklab = (rgb: Vec3): Vec3 => {\n const lms = transform(rgb, linear_sRGB_to_LMS_M);\n const lms_ = cbrt3(lms);\n return transform(lms_, LMS_to_OKLab_M);\n};\n\n/**\n * Convert OKLab to OKHSL.\n * Input: [L, a, b] where L: 0–1, a/b: roughly -0.5 to 0.5.\n * Returns [h, s, l] where h: 0–360, s: 0–1, l: 0–1.\n */\nexport const oklabToOkhsl = (lab: Vec3, pastel = false): Vec3 => {\n const L = lab[0];\n const a = lab[1];\n const b = lab[2];\n\n const C = Math.sqrt(a * a + b * b);\n\n if (C < EPSILON) {\n return [0, 0, toe(L)];\n }\n\n // Lightness-extreme achromatic guard.\n //\n // At L → 1 (white) and L → 0 (black) the in-gamut chroma collapses to\n // a single point: cMax, cMid, c0 all approach zero. Pure white is the\n // most visible failure case — `linearSrgbToOklab([1, 1, 1])` leaves\n // tiny floating-point residue in the a / b channels (`a ≈ 8e-11`,\n // `b ≈ 3.7e-8` → `C ≈ 3.7e-8`) that's well above `EPSILON` (`1e-10`),\n // so the chroma early-return above doesn't catch it. The chromatic\n // path then runs, the gamut at L ≈ 1 has nowhere to put any chroma,\n // and the saturation formula in `getCs` divides through ~zero values,\n // producing nonsense h/s for what is physically an achromatic color\n // (`#FFFFFF` → `okhsl(89.88 55.83% 100%)` instead of\n // `okhsl(0 0% 100%)`).\n //\n // The threshold (`1e-6`) is much wider than `EPSILON` because the fp\n // wobble in L for pure white lands at `1 - 6.5e-9` — `EPSILON = 1e-10`\n // misses it. `1e-6` is still well below any human-perceivable\n // difference in lightness (JNDs in OKHSL L are several orders of\n // magnitude larger), so we don't falsely flatten any in-gamut color.\n //\n // Treat both extremes as achromatic. The lightness window itself is\n // preserved through `toe(L)`.\n const L_EXTREME_EPSILON = 1e-6;\n if (L >= 1 - L_EXTREME_EPSILON || L <= L_EXTREME_EPSILON) {\n return [0, 0, toe(L)];\n }\n\n const a_ = a / C;\n const b_ = b / C;\n\n let h = Math.atan2(b, a) * (180 / Math.PI);\n h = constrainAngle(h);\n\n let s: number;\n\n if (pastel) {\n s = C / computeSafeChromaOKLCH(L);\n } else {\n const cusp = findCuspOKLCH(a_, b_);\n const Cs = getCs(L, a_, b_, cusp);\n const [c0, cMid, cMax] = Cs;\n\n const mid = 0.8;\n const midInv = 1.25;\n\n if (C < cMid) {\n const k1 = mid * c0;\n const k2 = 1.0 - k1 / cMid;\n const t = C / (k1 + C * k2);\n s = t / midInv;\n } else {\n const k0 = cMid;\n const k1 = (0.2 * cMid ** 2 * 1.25 ** 2) / c0;\n const k2 = 1.0 - k1 / (cMax - cMid);\n const cDiff = C - k0;\n const t = cDiff / (k1 + cDiff * k2);\n s = mid + t / 5;\n }\n }\n\n const l = toe(L);\n\n return [h, clampVal(s, 0, 1), clampVal(l, 0, 1)];\n};\n\n/**\n * Convert gamma-encoded sRGB (0–1 per channel) to OKHSL.\n * Returns [h, s, l] where h: 0–360, s: 0–1, l: 0–1.\n *\n * A gray reads with saturation 0 (its computed hue is kept). Its OKLab\n * residue would otherwise come out as a saturation that grows toward white\n * (`#fefefe` reads 1.6e-5, `rgb(254.999 254.999 254.999)` 1.6e-2), which a\n * color carries into every scheme and an OKHSL mix reads as a hue.\n */\nexport function srgbToOkhsl(\n rgb: [number, number, number],\n pastel = false,\n): [number, number, number] {\n const linear: Vec3 = [\n sRGBGammaToLinear(rgb[0]),\n sRGBGammaToLinear(rgb[1]),\n sRGBGammaToLinear(rgb[2]),\n ];\n const oklab = linearSrgbToOklab(linear);\n const okhsl = oklabToOkhsl(oklab, pastel) as [number, number, number];\n if (Math.hypot(oklab[1], oklab[2]) < GRAY_CHROMA) okhsl[1] = 0;\n return okhsl;\n}\n\n/**\n * Convert CSS HSL (sRGB-based) to gamma-encoded sRGB [r, g, b] in 0–1 range.\n * h: 0–360, s: 0–1, l: 0–1.\n *\n * Note: CSS HSL is not the same as OKHSL — it's HSL in the sRGB color space.\n * Use this when parsing `hsl(...)` strings before passing to `srgbToOkhsl`.\n */\nexport function hslToSrgb(\n h: number,\n s: number,\n l: number,\n): [number, number, number] {\n const hh = (((h % 360) + 360) % 360) / 360;\n const ss = clampVal(s, 0, 1);\n const ll = clampVal(l, 0, 1);\n\n if (ss === 0) {\n return [ll, ll, ll];\n }\n\n const q = ll < 0.5 ? ll * (1 + ss) : ll + ss - ll * ss;\n const p = 2 * ll - q;\n\n const hueToChannel = (t: number): number => {\n let tt = t;\n if (tt < 0) tt += 1;\n if (tt > 1) tt -= 1;\n if (tt < 1 / 6) return p + (q - p) * 6 * tt;\n if (tt < 1 / 2) return q;\n if (tt < 2 / 3) return p + (q - p) * (2 / 3 - tt) * 6;\n return p;\n };\n\n return [hueToChannel(hh + 1 / 3), hueToChannel(hh), hueToChannel(hh - 1 / 3)];\n}\n\n/**\n * Parse a hex color string (#rgb or #rrggbb) to sRGB [r, g, b] in 0–1 range.\n * The leading `#` is optional. Returns null if the string is not a valid hex\n * color: a wrong length, any character outside `0-9a-f` (case-insensitive),\n * or a form with alpha.\n *\n * For 8-digit hex (`#rrggbbaa`) and 4-digit hex (`#rgba`) with alpha,\n * use {@link parseHexAlpha}.\n */\nexport function parseHex(hex: string): [number, number, number] | null {\n const result = parseHexAlpha(hex);\n if (!result || result.alpha !== undefined) return null;\n return result.rgb;\n}\n\n/** Hex digits only — no sign, whitespace, or `0x` prefix. */\nconst HEX_DIGITS_RE = /^[0-9a-f]+$/i;\n\n/**\n * Parse a hex color string (#rgb, #rrggbb, #rgba, or #rrggbbaa) to\n * sRGB [r, g, b] in 0–1 range plus an optional alpha (0–1).\n * The leading `#` is optional. Returns null if the string is not a valid hex\n * color: a wrong length or any character outside `0-9a-f`\n * (case-insensitive).\n *\n * Every digit is checked up front: `parseInt` alone stops at the first bad\n * character, so `'#1z2z3z'` would otherwise read as `#010203`.\n */\nexport function parseHexAlpha(\n hex: string,\n): { rgb: [number, number, number]; alpha?: number } | null {\n const h = hex.startsWith('#') ? hex.slice(1) : hex;\n if (!HEX_DIGITS_RE.test(h)) return null;\n\n // Expand the short forms (#rgb / #rgba) to their long equivalents.\n const full =\n h.length === 3 || h.length === 4\n ? Array.from(h, (digit) => digit + digit).join('')\n : h;\n if (full.length !== 6 && full.length !== 8) return null;\n\n const channel = (i: number): number =>\n parseInt(full.slice(i, i + 2), 16) / 255;\n const rgb: [number, number, number] = [channel(0), channel(2), channel(4)];\n return full.length === 8 ? { rgb, alpha: channel(6) } : { rgb };\n}\n\n// ============================================================================\n// Format functions\n// ============================================================================\n\nfunction fmt(value: number, decimals: number): string {\n return parseFloat(value.toFixed(decimals)).toString();\n}\n\n/**\n * Every `format*` writer takes `s` / `l` / `t` on the **0–1 factor scale** —\n * the same scale every producer in the library hands back (`resolve()`,\n * `variantToOkhsl`, `srgbToOkhsl`, `oklabToOkhsl`, `okhslToOklab`,\n * `okhslToSrgb`). The percentages are an output detail: the writers multiply\n * by 100 themselves when the CSS syntax asks for a percentage.\n *\n * Before 2.0 the writers took 0–100 while everything producing those values\n * returned 0–1, so the obvious composition was off by 100x and failed\n * silently — `0.7` is a legal percentage, so the result was a valid CSS string\n * naming a near-black color. A value above 1 can only be that old\n * percentage-scale input, so warn about it loudly rather than emit a wrong\n * color quietly.\n */\n// Keyed by writer name, so the cache is bounded by the five writers below and\n// needs no cap of its own (unlike the per-color contrast warnings).\nconst scaleWarnCache = new Set<string>();\n\nfunction warnPercentScale(fn: string, ...values: number[]): void {\n if (!values.some((v) => v > 1 + 1e-6)) return;\n\n if (!scaleWarnCache.has(fn)) {\n scaleWarnCache.add(fn);\n console.warn(\n `glaze: ${fn}() got a value above 1 — it takes the 0-1 factors every ` +\n `Glaze producer returns (resolve(), variantToOkhsl, srgbToOkhsl), not ` +\n `0-100 percentages. Divide by 100, or drop the \"* 100\" left over from ` +\n `the pre-2.0 signature.`,\n );\n }\n}\n\n/**\n * Format OKHSL values as a CSS `okhsl(H S% L%)` string.\n * h: 0–360, s: 0–1, l: 0–1 (factor scale, as returned by every converter).\n */\nexport function formatOkhsl(\n h: number,\n s: number,\n l: number,\n pastel = false,\n): string {\n warnPercentScale('formatOkhsl', s, l);\n\n let outS = s;\n if (pastel) {\n // If it's a pastel color, we need to find the equivalent normal OKHSL `s`\n // so it renders identically in external parsers that don't know about `pastel`.\n const oklab = okhslToOklab(h, s, l, true);\n const normalOkhsl = oklabToOkhsl(oklab, false);\n outS = normalOkhsl[1];\n }\n return `okhsl(${fmt(h, 2)} ${fmt(outS * 100, 2)}% ${fmt(l * 100, 2)}%)`;\n}\n\n/**\n * Format OKHST values as a CSS `okhst(H S% T%)` string.\n * h: 0–360, s: 0–1, t: 0–1 (factor scale, matching `ResolvedColorVariant`).\n *\n * Pastel recompute matches `formatOkhsl`: convert via OKLab so external\n * parsers that only understand non-pastel OKHST render identically.\n */\nexport function formatOkhst(\n h: number,\n s: number,\n t: number,\n pastel = false,\n): string {\n warnPercentScale('formatOkhst', s, t);\n\n let outS = s;\n if (pastel) {\n const REF_EPS = 0.05;\n const den = Math.log(1 + REF_EPS) - Math.log(REF_EPS);\n const y = Math.exp(t * den + Math.log(REF_EPS)) - REF_EPS;\n const l = toe(Math.cbrt(Math.max(0, y)));\n const oklab = okhslToOklab(h, s, l, true);\n const normalOkhsl = oklabToOkhsl(oklab, false);\n outS = normalOkhsl[1];\n }\n return `okhst(${fmt(h, 2)} ${fmt(outS * 100, 2)}% ${fmt(t * 100, 2)}%)`;\n}\n\n/**\n * Format OKHSL values as a CSS `rgb(R G B)` string.\n * Uses 2 decimal places to avoid 8-bit quantization contrast loss.\n * h: 0–360, s: 0–1, l: 0–1 (factor scale, as returned by every converter).\n */\nexport function formatRgb(\n h: number,\n s: number,\n l: number,\n pastel = false,\n): string {\n warnPercentScale('formatRgb', s, l);\n\n const [r, g, b] = okhslToSrgb(h, s, l, pastel);\n return `rgb(${parseFloat((r * 255).toFixed(2))} ${parseFloat((g * 255).toFixed(2))} ${parseFloat((b * 255).toFixed(2))})`;\n}\n\n/**\n * Format OKHSL values as a CSS `hsl(H S% L%)` string.\n * h: 0–360, s: 0–1, l: 0–1 (factor scale, as returned by every converter).\n */\nexport function formatHsl(\n h: number,\n s: number,\n l: number,\n pastel = false,\n): string {\n warnPercentScale('formatHsl', s, l);\n\n const [r, g, b] = okhslToSrgb(h, s, l, pastel);\n\n const max = Math.max(r, g, b);\n const min = Math.min(r, g, b);\n const delta = max - min;\n\n let hh = 0;\n let ss = 0;\n const ll = (max + min) / 2;\n\n if (delta > 0) {\n ss = ll > 0.5 ? delta / (2 - max - min) : delta / (max + min);\n\n if (max === r) {\n hh = ((g - b) / delta + (g < b ? 6 : 0)) * 60;\n } else if (max === g) {\n hh = ((b - r) / delta + 2) * 60;\n } else {\n hh = ((r - g) / delta + 4) * 60;\n }\n }\n\n return `hsl(${fmt(hh, 2)} ${fmt(ss * 100, 2)}% ${fmt(ll * 100, 2)}%)`;\n}\n\n/**\n * Format OKHSL values as a CSS `oklch(L C H)` string.\n * h: 0–360, s: 0–1, l: 0–1 (factor scale, as returned by every converter).\n */\nexport function formatOklch(\n h: number,\n s: number,\n l: number,\n pastel = false,\n): string {\n warnPercentScale('formatOklch', s, l);\n\n const [L, C, hh] = okhslToOklch(h, s, l, pastel);\n return `oklch(${fmt(L, 4)} ${fmt(C, 4)} ${fmt(hh, 2)})`;\n}\n\n/**\n * Format linear sRGB channels as a CSS `color(srgb-linear R G B)` string with\n * 4 decimals. Unlike the other writers it takes linear light, not OKHSL, and\n * does not clamp: a channel may exceed 1, which is how an HDR glow value\n * written with `glaze.formatHdr(v, 'srgb-linear')` goes past SDR white — `1`\n * is SDR white, `2` one stop above it (the default extended form is\n * `formatSrgb`). Opaque only; HDR values carry no alpha.\n */\nexport function formatSrgbLinear(rgb: [number, number, number]): string {\n return `color(srgb-linear ${fmt(rgb[0], 4)} ${fmt(rgb[1], 4)} ${fmt(rgb[2], 4)})`;\n}\n\n/**\n * Format extended sRGB channels — gamma-encoded, with the transfer function\n * continued past 1 (`sRGBLinearToGamma` does) — as a CSS `color(srgb R G B)`\n * string with 4 decimals. Like `formatSrgbLinear` it takes the channels of\n * its own space and does not clamp, so an HDR glow value\n * (`glaze.formatHdr()`) can pass SDR white: `1` is SDR white, about `1.3533`\n * one stop above it. CSS reads it as the same color as the matching\n * `color(srgb-linear …)`. Opaque only; HDR values carry no alpha.\n */\nexport function formatSrgb(rgb: [number, number, number]): string {\n return `color(srgb ${fmt(rgb[0], 4)} ${fmt(rgb[1], 4)} ${fmt(rgb[2], 4)})`;\n}\n\n/**\n * Reset the `format*` percentage-scale warning cache. Test-only seam — the\n * warning is deduped per function for the life of the process, which a test\n * asserting on it has to be able to clear.\n */\nexport function resetScaleWarnings(): void {\n scaleWarnCache.clear();\n}\n\n// ============================================================================\n// Structured (non-string) color accessors — used by the DTCG exporter.\n// ============================================================================\n\n/**\n * Convert gamma-encoded sRGB channels (0–1) to a 6-digit lowercase hex\n * string (`#rrggbb`). Channels are clamped to [0,1] and rounded to 8-bit.\n * Alpha is not encoded here — DTCG carries it as a separate `alpha` field.\n */\nexport function srgbToHex(rgb: [number, number, number]): `#${string}` {\n const toByte = (c: number): number =>\n Math.max(0, Math.min(255, Math.round(c * 255)));\n const r = toByte(rgb[0]);\n const g = toByte(rgb[1]);\n const b = toByte(rgb[2]);\n return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`;\n}\n\n/**\n * Convert OKHSL (h: 0–360, s: 0–1, l: 0–1) to OKLCH components `[L, C, H]`.\n * L: 0–1, C: 0–~0.4 (chroma), H: 0–360 (hue). Shared by `formatOklch` and\n * the DTCG `oklch` colorSpace exporter so the two never drift apart.\n */\nexport function okhslToOklch(\n h: number,\n s: number,\n l: number,\n pastel = false,\n): [number, number, number] {\n const [L, a, b] = okhslToOklab(h, s, l, pastel);\n const C = Math.sqrt(a * a + b * b);\n const hh = constrainAngle(Math.atan2(b, a) * (180 / Math.PI));\n return [L, C, hh];\n}\n","/**\n * Small shared helpers used across the resolver pipeline:\n * - HC-pair selection (`pairNormal` / `pairHC`)\n * - HC-pair interpolation for the manual contrast level (`contrastFraction`,\n * `hcMirrorsNormal`, `numberAt`, `parseToneValueAt`)\n * - Absolute / relative / extreme tone discrimination\n * - Generic numeric helpers (`clamp`, `lerp`, hue resolution, relative-value\n * parsing)\n * - `showValue`, which writes a rejected input into a validation error\n */\n\nimport type { ExtremeValue, HCPair, RelativeValue, ToneValue } from './types';\n\nexport function pairNormal<T>(p: HCPair<T>): T {\n return Array.isArray(p) ? p[0] : p;\n}\n\nexport function pairHC<T>(p: HCPair<T>): T {\n return Array.isArray(p) ? p[1] : p;\n}\n\nexport function clamp(v: number, min: number, max: number): number {\n return Math.max(min, Math.min(max, v));\n}\n\nexport function lerp(a: number, b: number, f: number): number {\n return a + (b - a) * f;\n}\n\n/** Brackets `undefined` or a non-finite number while JSON writes it. */\nconst UNWRITABLE_MARK = '\\uE000';\nconst UNWRITABLE_RE = /\"\\uE000([^\"]*)\\uE000\"/g;\n\n/**\n * A rejected input as a validation error shows it. Numbers and `undefined`\n * via `String` (`JSON.stringify(NaN)` is \"null\"), a bigint with its `n`\n * (JSON can't write one), anything else via JSON so a string shows its quotes\n * and an array its shape, with `undefined` or a non-finite number inside\n * written as it prints (`[10,NaN]`, `{\"wcag\":undefined}`; JSON would write\n * `null` or drop the key) — falling back to `String` for what JSON can't\n * write (a symbol, a function, a cycle).\n */\nexport function showValue(value: unknown): string {\n if (typeof value === 'number' || value === undefined) return String(value);\n if (typeof value === 'bigint') return `${value}n`;\n try {\n // A value that holds the marker itself is written as plain JSON, so a\n // string of the caller's never loses its quotes.\n const plain = JSON.stringify(value);\n if (plain === undefined) return String(value);\n if (plain.includes(UNWRITABLE_MARK)) return plain;\n const json = JSON.stringify(value, (_key, v: unknown) =>\n v === undefined || (typeof v === 'number' && !Number.isFinite(v))\n ? `${UNWRITABLE_MARK}${v}${UNWRITABLE_MARK}`\n : v,\n );\n return json?.replace(UNWRITABLE_RE, '$1') ?? String(value);\n } catch {\n return String(value);\n }\n}\n\n// ============================================================================\n// Manual contrast level\n// ============================================================================\n\n/**\n * Blend fraction at/above which an un-interpolable HC pair switches from its\n * normal entry to its high-contrast one (level 50).\n */\nexport const PAIR_SWITCH = 0.5;\n\n/** Blend fraction (0–1) for an authored 0–100 contrast level. */\nexport function levelFraction(level: number): number {\n return clamp(level, 0, 100) / 100;\n}\n\n/**\n * Manual-contrast blend fraction (0–1) for a resolved config, or `undefined`\n * in `'auto'` mode, where the normal variants take the authored normal entries\n * as-is.\n *\n * Note `contrastLevel: 0` yields `0`, not `undefined`. The two select different\n * branches, and an authored `0` is a slider position that `.export()` freezes\n * where an absent level is not — but they are not an *output* distinction: at\n * fraction 0 every interpolation returns its normal entry verbatim, so level 0\n * reproduces `'auto'` bit for bit.\n */\nexport function contrastFraction(config: {\n contrastLevel?: number | 'auto';\n}): number | undefined {\n const level = config.contrastLevel;\n if (typeof level !== 'number' || !Number.isFinite(level)) return undefined;\n return levelFraction(level);\n}\n\n/**\n * Whether the high-contrast variants are exact duplicates of the normal ones —\n * true only at `contrastLevel: 100`, where the normal passes already resolve at\n * full contrast.\n *\n * The level otherwise says nothing about high contrast: it positions the normal\n * variants, while `lightContrast` / `darkContrast` stay the true high-contrast\n * resolution at every level. This predicate marks the one level where that tier\n * carries no new information, so callers can skip the two high-contrast passes,\n * their drift checks, and the redundant output tier.\n */\nexport function hcMirrorsNormal(config: {\n contrastLevel?: number | 'auto';\n}): boolean {\n return contrastFraction(config) === 1;\n}\n\n/**\n * A numeric HC pair at a blend fraction (shadow / glow `intensity`, mix `value`).\n *\n * The endpoints return the authored entry *by identity* rather than through\n * float arithmetic — `a + (b - a) * 1` is not bit-exactly `b` in IEEE 754, and\n * levels 0 / 100 must reproduce the classic output exactly.\n */\nexport function numberAt(p: HCPair<number>, f: number): number {\n if (!Array.isArray(p)) return p;\n if (f <= 0) return p[0];\n if (f >= 1) return p[1];\n return lerp(p[0], p[1], f);\n}\n\n/** Whether a tone value is an extreme keyword (`'max'` / `'min'`). */\nexport function isExtremeTone(value: ToneValue): value is ExtremeValue {\n return value === 'max' || value === 'min';\n}\n\n/**\n * Parse a value that can be absolute (number) or relative (signed string).\n * Returns the numeric value and whether it's relative.\n */\nexport function parseRelativeOrAbsolute(value: number | RelativeValue): {\n value: number;\n relative: boolean;\n} {\n if (typeof value === 'number') {\n return { value, relative: false };\n }\n return { value: parseFloat(value), relative: true };\n}\n\n/**\n * Parse a tone value into a normalized shape.\n * - `'max'` / `'min'` → `{ kind: 'extreme', value: 100 | 0 }` (an absolute\n * author tone before scheme mapping — `'max'` is 100, `'min'` is 0).\n * - `'+N'` / `'-N'` → `{ kind: 'relative', value: ±N }`.\n * - number → `{ kind: 'absolute', value }`.\n */\nexport function parseToneValue(value: ToneValue): {\n kind: 'absolute' | 'relative' | 'extreme';\n value: number;\n} {\n if (value === 'max') return { kind: 'extreme', value: 100 };\n if (value === 'min') return { kind: 'extreme', value: 0 };\n if (typeof value === 'number') return { kind: 'absolute', value };\n return { kind: 'relative', value: parseFloat(value) };\n}\n\n/**\n * Parse an authored tone pair at a manual-contrast blend fraction, returning\n * the same normalized shape as {@link parseToneValue}.\n *\n * Same-kind numeric pairs interpolate their magnitude — absolute tones\n * (`[30, 20]` → 25 at level 50) and relative deltas (`['+10', '+20']` → +15).\n * Everything else is un-interpolable and switches at {@link PAIR_SWITCH}:\n * extremes carry no magnitude, and a mixed-kind pair would change *which*\n * resolver branch runs mid-ramp (absolute remap vs. extreme-against-base vs.\n * base-anchored delta), putting a discontinuity at level 100 — exactly where\n * the output must stay bit-exact.\n *\n * Returns a parsed struct rather than a `ToneValue` so a blended relative\n * delta never round-trips through a `'+15.5'` string, and so `kind` — which\n * selects the resolver branch — cannot drift.\n */\nexport function parseToneValueAt(\n p: HCPair<ToneValue>,\n f: number,\n): { kind: 'absolute' | 'relative' | 'extreme'; value: number } {\n if (!Array.isArray(p)) return parseToneValue(p);\n if (f <= 0) return parseToneValue(p[0]);\n if (f >= 1) return parseToneValue(p[1]);\n const normal = parseToneValue(p[0]);\n const hc = parseToneValue(p[1]);\n if (normal.kind === hc.kind && normal.kind !== 'extreme') {\n return { kind: normal.kind, value: lerp(normal.value, hc.value, f) };\n }\n return f < PAIR_SWITCH ? normal : hc;\n}\n\n/**\n * Compute the effective hue for a color, given the theme seed hue\n * and an optional per-color hue override.\n */\nexport function resolveEffectiveHue(\n seedHue: number,\n defHue: number | RelativeValue | undefined,\n): number {\n if (defHue === undefined) return seedHue;\n const parsed = parseRelativeOrAbsolute(defHue);\n if (parsed.relative) {\n return (((seedHue + parsed.value) % 360) + 360) % 360;\n }\n return ((parsed.value % 360) + 360) % 360;\n}\n\n/**\n * Check whether a tone value represents an absolute root definition\n * (i.e. a number, not a relative string). Extreme keywords (`'max'` /\n * `'min'`) also count — they need no base.\n */\nexport function isAbsoluteTone(tone: HCPair<ToneValue> | undefined): boolean {\n if (tone === undefined) return false;\n const normal = Array.isArray(tone) ? tone[0] : tone;\n return typeof normal === 'number' || isExtremeTone(normal);\n}\n","/**\n * OKHST — the contrast-uniform tone space.\n *\n * OKHST is OKHSL with its lightness axis replaced by a contrast-uniform\n * \"tone\" axis. It shares `h` / `s` with OKHSL verbatim and swaps `l` for\n * `t`. This module owns:\n *\n * - the closed-form tone transfers (`toTone` / `fromTone`) at a fixed\n * reference eps, plus the gray luminance helpers (`lToY` / `yToL`),\n * - the `{ h, s, t }` <-> `{ h, s, l }` color-space converters,\n * - the resolved-variant edge adapter (`variantToOkhsl`),\n * - the per-scheme tone mapping that replaced the Möbius dark curve\n * (`mapToneForScheme`) and its dark inverse (`unmapDarkTone`, which the\n * resolver uses to find where a base sits on the authored scale), the dark\n * map off that scale (`mapDarkToneUnclamped`, for a\n * step from a base pushed past the dark window) and the dark-window\n * comparison across configs (`sameDarkWindow`), the dark desaturation\n * reducer, and the scheme tone range that clamps a contrast-solved color's\n * preferred tone,\n * - the scheme tone window — validated and clamped by `normalizeToneWindow` —\n * including the high-contrast bypass and its continuous generalization under\n * a manual contrast level.\n *\n * See `docs/okhst.mdx` for the full specification and the calibrated\n * default constants.\n */\n\nimport { clamp, contrastFraction, lerp, showValue } from './hc-pair';\nimport { toe, toeInv } from './okhsl-color-math';\nimport type { AdaptationMode, GlazeConfigResolved, ToneWindow } from './types';\n\n/**\n * Reference eps for the OKHST color space. WCAG 2 contrast is\n * `(Y_hi + 0.05) / (Y_lo + 0.05)`, so an eps of `0.05` makes equal tone\n * steps yield equal WCAG contrast. This is the canonical eps used by\n * `okhst()` input, `{ h, s, t }` input, stored `ResolvedColorVariant.t`,\n * relative `tone` offsets, and the contrast solver.\n */\nexport const REF_EPS = 0.05;\n\n// ============================================================================\n// Gray luminance <-> OKHSL lightness (closed form)\n// ============================================================================\n\n/**\n * Gray luminance from OKHSL lightness. For an achromatic color the OKLab\n * lightness is `toeInv(l)` and luminance is its cube.\n */\nexport function lToY(l: number): number {\n const L = toeInv(l);\n return L * L * L;\n}\n\n/** OKHSL lightness from gray luminance — exact inverse of {@link lToY}. */\nexport function yToL(y: number): number {\n return toe(Math.cbrt(Math.max(0, y)));\n}\n\n// ============================================================================\n// Tone transfers (luminance domain)\n// ============================================================================\n\n/**\n * Map a luminance `Y` (0–1) to tone (0–100) at the given eps.\n * `toneFromY(0) === 0` and `toneFromY(1) === 100` for any eps.\n */\nexport function toneFromY(y: number, eps: number = REF_EPS): number {\n const num = Math.log(y + eps) - Math.log(eps);\n const den = Math.log(1 + eps) - Math.log(eps);\n return (num / den) * 100;\n}\n\n/** Map a tone (0–100) back to luminance (0–1). Inverse of {@link toneFromY}. */\nexport function yFromTone(t: number, eps: number = REF_EPS): number {\n const den = Math.log(1 + eps) - Math.log(eps);\n return Math.exp((t / 100) * den + Math.log(eps)) - eps;\n}\n\n// ============================================================================\n// Tone transfers (OKHSL lightness domain)\n// ============================================================================\n\n/** OKHSL lightness (0–1) -> tone (0–100). */\nexport function toTone(l: number, eps: number = REF_EPS): number {\n return toneFromY(lToY(l), eps);\n}\n\n/** Tone (0–100) -> OKHSL lightness (0–1). Inverse of {@link toTone}. */\nexport function fromTone(t: number, eps: number = REF_EPS): number {\n return yToL(yFromTone(t, eps));\n}\n\n// ============================================================================\n// Color-space converters\n// ============================================================================\n\n/** Convert OKHST `{ h, s, t }` (t in 0–1) to OKHSL `{ h, s, l }`. */\nexport function okhstToOkhsl(c: { h: number; s: number; t: number }): {\n h: number;\n s: number;\n l: number;\n} {\n return { h: c.h, s: c.s, l: clamp(fromTone(c.t * 100), 0, 1) };\n}\n\n/** Convert OKHSL `{ h, s, l }` to OKHST `{ h, s, t }` (t in 0–1). */\nexport function okhslToOkhst(c: { h: number; s: number; l: number }): {\n h: number;\n s: number;\n t: number;\n} {\n return { h: c.h, s: c.s, t: clamp(toTone(c.l) / 100, 0, 1) };\n}\n\n/**\n * Edge adapter: a resolved variant stores canonical tone `t` (0–1). Convert\n * it to the OKHSL `{ h, s, l }` the formatters and luminance pipeline expect —\n * `s` and `l` on the same 0–1 factor scale, so `const { h, s, l } =\n * variantToOkhsl(v)` destructures straight into `formatOkhsl` / `formatRgb` /\n * `okhslToLinearSrgb` with no rescaling. `alpha` stays on the variant; use\n * `glaze.format(v, format)` for a string that carries it.\n */\nexport function variantToOkhsl(v: { h: number; s: number; t: number }): {\n h: number;\n s: number;\n l: number;\n} {\n return { h: v.h, s: v.s, l: clamp(fromTone(v.t * 100), 0, 1) };\n}\n\n// ============================================================================\n// Scheme tone mapping (replaces the Möbius dark curve)\n// ============================================================================\n\n/**\n * Largest render eps a tone window accepts. The transfers divide by\n * `log(1 + eps) - log(eps)`, which loses precision as eps grows (colors are\n * visibly wrong by ~1e14) and cancels to 0 — `NaN` tones — from ~1e15. At 1e6\n * the tone ↔ luminance round trip still holds to ~1e-9, and past ~1e3 the\n * curve is already linear in luminance, so the cap costs nothing usable.\n */\nconst MAX_WINDOW_EPS = 1e6;\n\n/**\n * Normalize any {@link ToneWindow} form to `{ lo, hi, eps }`, validated.\n * - `false`: full range `[0, 100]` at the reference eps (boundaries removed,\n * curve preserved).\n * - `[lo, hi]`: endpoints at the reference eps (the common form).\n * - `{ lo, hi, eps }`: an explicit render eps (advanced eps tuning).\n *\n * A bad window never fails on its own — `[90, 20]` silently inverts the scale\n * and an `eps` of 0 turns every tone into `NaN` — so this throws a `glaze:`\n * error when the value is none of the three forms, an endpoint is not a finite\n * number, `lo > hi`, or `eps` is not a finite number in `(0, MAX_WINDOW_EPS]`.\n * Endpoints then clamp into `[0, 100]`, the OKHSL lightness range. `lo === hi`\n * is allowed: a zero-width window renders every tone at that one lightness.\n *\n * `field` names the window in the error message (`lightTone` / `darkTone`).\n */\nexport function normalizeToneWindow(\n win: ToneWindow,\n field = 'tone window',\n): { lo: number; hi: number; eps: number } {\n if (win === false) return { lo: 0, hi: 100, eps: REF_EPS };\n const raw: unknown = win;\n let lo: unknown;\n let hi: unknown;\n let eps: unknown = REF_EPS;\n if (Array.isArray(raw) && raw.length === 2) {\n [lo, hi] = raw;\n } else if (typeof raw === 'object' && raw !== null && !Array.isArray(raw)) {\n ({ lo, hi, eps } = raw as Record<string, unknown>);\n } else {\n throw new Error(\n `glaze: ${field} must be [lo, hi], { lo, hi, eps }, or false (got ${showValue(raw)}).`,\n );\n }\n for (const [name, value] of [\n ['lo', lo],\n ['hi', hi],\n ] as const) {\n if (typeof value !== 'number' || !Number.isFinite(value)) {\n throw new Error(\n `glaze: ${field} ${name} must be a finite number (got ${showValue(value)}).`,\n );\n }\n }\n if (\n typeof eps !== 'number' ||\n !Number.isFinite(eps) ||\n eps <= 0 ||\n eps > MAX_WINDOW_EPS\n ) {\n throw new Error(\n `glaze: ${field} eps must be a finite number above 0 and at most 1e6 (got ${showValue(eps)}).`,\n );\n }\n const from = lo as number;\n const to = hi as number;\n if (from > to) {\n throw new Error(\n `glaze: ${field} lo (${from}) is above hi (${to}). A window runs from ` +\n `its dark end to its light end: [lo, hi] with lo ≤ hi, e.g. [${to}, ${from}].`,\n );\n }\n return { lo: clamp(from, 0, 100), hi: clamp(to, 0, 100), eps };\n}\n\n/**\n * Resolve the active tone window for a scheme as OKHSL-lightness endpoints.\n * - HC variants always return the full range `[0, 100]` with the mode eps.\n * - Under a manual `contrastLevel`, each endpoint is interpolated toward that\n * full range: light `10 → 0` / `100 → 100`, dark `15 → 0` / `95 → 100`. The\n * endpoints are exact — level 0 returns the configured window and level 100\n * the same literal the HC branch returns.\n * - `false` (= \"no clamping\") is treated as `[0, 100]` with the reference eps,\n * and is therefore level-invariant.\n */\nfunction activeWindow(\n isHighContrast: boolean,\n kind: 'light' | 'dark',\n config: GlazeConfigResolved,\n): { lo: number; hi: number; eps: number } {\n const win = normalizeToneWindow(\n kind === 'dark' ? config.darkTone : config.lightTone,\n );\n if (isHighContrast) return { lo: 0, hi: 100, eps: win.eps };\n const f = contrastFraction(config);\n if (f === undefined || f <= 0) return win;\n if (f >= 1) return { lo: 0, hi: 100, eps: win.eps };\n // The render eps is not interpolated — HC keeps the configured eps today, so\n // the ramp does too.\n return { lo: lerp(win.lo, 0, f), hi: lerp(win.hi, 100, f), eps: win.eps };\n}\n\n/**\n * Remap an authored tone (0–100) into a scheme window and return the final\n * OKHSL lightness (0–100). The window endpoints are OKHSL lightnesses; the\n * author tone is positioned within the window's tone interval (using the\n * window's render eps), then converted back to lightness.\n */\nfunction remapToneToLightness(\n authorTone: number,\n win: { lo: number; hi: number; eps: number },\n): number {\n const loT = toTone(win.lo / 100, win.eps);\n const hiT = toTone(win.hi / 100, win.eps);\n const winTone = loT + (authorTone / 100) * (hiT - loT);\n return clamp(fromTone(winTone, win.eps) * 100, 0, 100);\n}\n\n/**\n * Map an authored tone for a scheme and return the canonical stored tone\n * (0–100, reference eps).\n *\n * - `static`: identity — the same tone renders in every scheme.\n * - `auto` + dark: invert (`100 - tone`) then remap into the dark window.\n * - `auto`/`fixed` + light, or `fixed` + dark: remap, no inversion.\n *\n * The window remap uses the mode's render eps to land a final OKHSL\n * lightness; that lightness is then re-expressed as canonical tone so\n * relative offsets and contrast stay comparable across schemes.\n *\n * A manual `contrastLevel` widens the window continuously (see\n * `activeWindow`); inversion is unaffected.\n */\nexport function mapToneForScheme(\n authorTone: number,\n mode: AdaptationMode,\n isDark: boolean,\n isHighContrast: boolean,\n config: GlazeConfigResolved,\n): number {\n if (mode === 'static') return clamp(authorTone, 0, 100);\n\n const kind = isDark ? 'dark' : 'light';\n const win = activeWindow(isHighContrast, kind, config);\n\n const inverted = isDark && mode === 'auto' ? 100 - authorTone : authorTone;\n const finalL = remapToneToLightness(clamp(inverted, 0, 100), win);\n return clamp(toTone(finalL / 100), 0, 100);\n}\n\n/**\n * The dark `auto` branch of {@link mapToneForScheme} without its clamp to the\n * authored `0–100` scale: a tone below 0 lands past the dark window's top, one\n * above 100 past its bottom, and only the stored tone is clamped (to the full\n * range). That makes it the inverse of `unmapDarkTone(…, 'auto', …)` off the\n * scale too, so a step can start from a base a contrast floor pushed past the\n * window. Inside `0–100` it is `mapToneForScheme` bit for bit.\n */\nexport function mapDarkToneUnclamped(\n authorTone: number,\n isHighContrast: boolean,\n config: GlazeConfigResolved,\n): number {\n const win = activeWindow(isHighContrast, 'dark', config);\n const finalL = remapToneToLightness(100 - authorTone, win);\n return clamp(toTone(finalL / 100), 0, 100);\n}\n\n/**\n * Whether two configs give one pass the same active dark window — endpoints and\n * render eps, after the high-contrast bypass and a manual level's widening. An\n * authored tone only means the same dark tone under both when they do.\n */\nexport function sameDarkWindow(\n isHighContrast: boolean,\n a: GlazeConfigResolved,\n b: GlazeConfigResolved,\n): boolean {\n const wa = activeWindow(isHighContrast, 'dark', a);\n const wb = activeWindow(isHighContrast, 'dark', b);\n return wa.lo === wb.lo && wa.hi === wb.hi && wa.eps === wb.eps;\n}\n\n/**\n * Inverse of {@link remapToneToLightness} on canonical tone: the position\n * (0–100) in the window that renders at a stored canonical tone. A tone outside\n * the window comes back outside `0–100`; a zero-width window has no inverse, so\n * the tone is returned unchanged.\n */\nfunction unmapWindow(\n tone: number,\n win: { lo: number; hi: number; eps: number },\n): number {\n const loT = toTone(win.lo / 100, win.eps);\n const hiT = toTone(win.hi / 100, win.eps);\n if (hiT === loT) return tone;\n\n const winTone = toTone(fromTone(tone), win.eps);\n return ((winTone - loT) / (hiT - loT)) * 100;\n}\n\n/**\n * Inverse of the dark branch of {@link mapToneForScheme}: the authored tone\n * (0–100) that the active dark window places at a stored canonical tone —\n * inverted back (`100 - position`) under `auto`, as is under `fixed`, and the\n * identity under `static`. A tone outside the window comes back outside\n * `0–100` (a contrast floor can push a color past the window; callers clamp);\n * a zero-width window has no inverse, so only the inversion is undone.\n */\nexport function unmapDarkTone(\n tone: number,\n mode: AdaptationMode,\n isHighContrast: boolean,\n config: GlazeConfigResolved,\n): number {\n if (mode === 'static') return tone;\n const position = unmapWindow(\n tone,\n activeWindow(isHighContrast, 'dark', config),\n );\n return mode === 'auto' ? 100 - position : position;\n}\n\n// ============================================================================\n// Saturation\n// ============================================================================\n\n/** Dark-scheme desaturation reducer (unchanged from the legacy pipeline). */\nexport function mapSaturationDark(\n s: number,\n mode: AdaptationMode,\n config: GlazeConfigResolved,\n): number {\n if (mode === 'static') return s;\n return s * (1 - config.darkDesaturation);\n}\n\n// ============================================================================\n// Solver support\n// ============================================================================\n\n/**\n * A scheme's window as canonical tone endpoints (0–1): `[0, 1]` for `static`,\n * otherwise the active window's `lo` / `hi` (HC bypasses to the full range, a\n * manual `contrastLevel` widens toward it — see `activeWindow`).\n *\n * The resolver uses it only to clamp a contrast-solved color's *preferred*\n * tone into the window before the solve. It is not the solver's search range:\n * the solver always searches the full `[0, 1]`, so a contrast floor can push a\n * color outside the window when the window can't meet it.\n */\nexport function schemeToneRange(\n isDark: boolean,\n mode: AdaptationMode,\n isHighContrast: boolean,\n config: GlazeConfigResolved,\n): [number, number] {\n if (mode === 'static') return [0, 1];\n const win = activeWindow(isHighContrast, isDark ? 'dark' : 'light', config);\n return [\n clamp(toTone(win.lo / 100) / 100, 0, 1),\n clamp(toTone(win.hi / 100) / 100, 0, 1),\n ];\n}\n","/**\n * Shadow and glow color computation.\n *\n * Owns the shadow / glow / mix def predicates, the default lighting tuning\n * and its merge, and the exact lighting solver (`computeLighting`). Both\n * types emit a translucent pigment over a known surface (`bg`) whose opacity\n * is solved so the composite lands an exact tone step away from it: darker\n * for `shadow`, lighter for `glow`, in every scheme. Compositing is modeled\n * the way browsers paint it — `source-over` on gamma-encoded sRGB — and the\n * step is measured in the WCAG-shaped tone of the composite's luminance, so\n * it holds on chromatic surfaces too. An optional object (`fg`) scales the\n * step the way bounce light does. The resolver consumes this module per\n * scheme variant; `glaze.shadow()` / `glaze.glow()` call it directly.\n *\n * HDR glows: with `glowTuning.headroom` above 0, a glow whose target tone\n * (surface tone + step) passes 100 also gets an HDR value, computed in closed\n * form after the untouched SDR solve. SDR is pinned at its brightest there —\n * the pigment at opacity 1, or a white surface at opacity 0 — and the HDR\n * value is an opaque exposure of that color: the base times `2^exposure`, the\n * gain that lands the exact step, capped per channel at `2^headroom`\n * (`MAX_HEADROOM` stops at most). A pigment that cannot lift a non-white\n * surface at all gets none and keeps the SDR shortfall warning. Since the\n * value lands the whole step, only a full-reach glow meets SDR at the boundary\n * (`exposure` → 0); one with `reach` below 1 jumps from its pigment to the\n * exact step. `hdrToLinearSrgb` / `hdrToSrgb` turn a resolved HDR value back\n * into linear or extended sRGB channels for the writers (both public).\n */\n\nimport {\n compositeOverGamma,\n okhslToLinearSrgb,\n okhslToOklab,\n oklabToOkhsl,\n relativeLuminanceFromLinearRgb,\n sRGBLinearToGamma,\n toDisplayGamma,\n} from './okhsl-color-math';\nimport { clamp } from './hc-pair';\nimport {\n fromTone,\n okhslToOkhst,\n okhstToOkhsl,\n toTone,\n toneFromY,\n yFromTone,\n} from './okhst';\nimport type {\n ColorDef,\n GlowColorDef,\n GlowTuning,\n LightingTuning,\n MixColorDef,\n ResolvedHdr,\n ShadowColorDef,\n} from './types';\n\nexport type LightingKind = 'shadow' | 'glow';\n\n/** OKHSL color fed to the lighting solver (`h` 0–360, `s` / `l` 0–1). */\nexport interface LightingColor {\n h: number;\n s: number;\n l: number;\n /** Gamut flag for this color's own sRGB conversion. */\n pastel?: boolean;\n}\n\n/** Output of {@link computeLighting}. */\nexport interface LightingResult {\n /** Pigment hue (0–360). */\n h: number;\n /** Pigment OKHSL saturation (0–1). */\n s: number;\n /** Pigment OKHSL lightness (0–1). */\n l: number;\n /** Solved pigment opacity (0–1). */\n alpha: number;\n /** Requested tone step: `intensity × k`. */\n step: number;\n /** Tone step the composite actually lands. Below `step` only when unreachable. */\n reached: number;\n /**\n * HDR value of a glow whose target tone passes 100 with `headroom` above 0,\n * when SDR is pinned at its brightest (see `pinnedBase`); absent otherwise.\n * The SDR fields above are unchanged by it.\n */\n hdr?: LightingHdr;\n}\n\n/** The HDR value in a {@link LightingResult}. */\nexport interface LightingHdr {\n /**\n * Base hue (0–360). The base is what SDR paints at its brightest, opaque:\n * the pigment, or the white surface it cannot lift.\n */\n h: number;\n /** Base OKHSL saturation (0–1, always non-pastel). */\n s: number;\n /** Base OKHSL lightness (0–1). */\n l: number;\n /** Gain over the base in stops, above 0. */\n exposure: number;\n /**\n * Tone step the exposed base lands above the surface: `step`, or less when\n * the `headroom` cap binds.\n */\n reached: number;\n}\n\n/** Most stops of HDR headroom a glow may use; larger values clamp to it. */\nexport const MAX_HEADROOM = 2;\n\n/**\n * A merged tuning: every {@link LightingTuning} field, plus the glow-only\n * `headroom` in stops (0 for a shadow, which never carries one).\n */\nexport type ResolvedLightingTuning = Required<LightingTuning> & {\n headroom: number;\n};\n\nexport function isShadowDef(def: ColorDef): def is ShadowColorDef {\n return (def as ShadowColorDef).type === 'shadow';\n}\n\nexport function isGlowDef(def: ColorDef): def is GlowColorDef {\n return (def as GlowColorDef).type === 'glow';\n}\n\n/** A `shadow` or `glow` def — the translucent overlay types. */\nexport function isLightingDef(\n def: ColorDef,\n): def is ShadowColorDef | GlowColorDef {\n return isShadowDef(def) || isGlowDef(def);\n}\n\nexport function isMixDef(def: ColorDef): def is MixColorDef {\n return (def as MixColorDef).type === 'mix';\n}\n\nexport const DEFAULT_LIGHTING_TUNING: Required<LightingTuning> = {\n objectInfluence: 0.5,\n tint: 0,\n reach: 1,\n hueBleed: 0,\n};\n\n/**\n * Defaults ← global (`shadowTuning` / `glowTuning`) ← per-color, field by\n * field. `headroom` defaults to 0 and clamps to `0–MAX_HEADROOM`; the config\n * and def validators have already rejected a non-finite or negative value and\n * warned about one above the maximum.\n */\nexport function resolveLightingTuning(\n perColor?: GlowTuning,\n globalTuning?: GlowTuning,\n): ResolvedLightingTuning {\n // `??`, not a spread: a field set to `undefined` is unset, not a value.\n const field = <K extends keyof LightingTuning>(key: K) =>\n perColor?.[key] ?? globalTuning?.[key] ?? DEFAULT_LIGHTING_TUNING[key];\n const headroom = perColor?.headroom ?? globalTuning?.headroom ?? 0;\n return {\n objectInfluence: field('objectInfluence'),\n tint: field('tint'),\n reach: field('reach'),\n hueBleed: field('hueBleed'),\n headroom: clamp(headroom, 0, MAX_HEADROOM),\n };\n}\n\nexport function circularLerp(a: number, b: number, t: number): number {\n let diff = b - a;\n if (diff > 180) diff -= 360;\n else if (diff < -180) diff += 360;\n return (((a + diff * t) % 360) + 360) % 360;\n}\n\n/**\n * Saturation at or below which a color has no hue of its own. A gray given as\n * a value parses with saturation 0; a near-gray under this has a hue too\n * faint to give a tint.\n */\nconst HUE_EPSILON = 1e-4;\nconst BISECT_ITERATIONS = 40;\nconst GOLDEN = (Math.sqrt(5) - 1) / 2;\n/** Float noise a target tone may sit above 100 without counting as HDR. */\nconst HDR_TRIGGER_EPS = 1e-9;\n/** Float noise a pigment may move the surface by and still count as not. */\nconst NO_LIFT_EPS = 1e-9;\n/** Float noise a surface tone may sit below 100 and still count as white. */\nconst WHITE_SURFACE_EPS = 1e-6;\n\n/**\n * Object factor `k = max(0, 1 + β · d · (t_bg − t_fg) / 100)`, with `d = +1`\n * for a shadow and `−1` for a glow. Calibrated so an object at the surface's\n * own tone — or no object at all — gives exactly the authored step: a darker\n * object deepens its shadow, a lighter one strengthens its glow.\n */\nexport function objectFactor(\n kind: LightingKind,\n bgTone: number,\n fgTone: number | undefined,\n objectInfluence: number,\n): number {\n if (fgTone === undefined) return 1;\n const d = kind === 'shadow' ? 1 : -1;\n return Math.max(0, 1 + (objectInfluence * d * (bgTone - fgTone)) / 100);\n}\n\n/**\n * The pigment: pure black (shadow) / pure white (glow) by default. `reach`\n * below 1 parks it part of the way from the surface's tone to that extreme so\n * a `tint` — saturation in the surface's hue, optionally pulled toward the\n * object's hue by `hueBleed` — can show. A neutral surface has no hue to give:\n * the tint takes the object's hue when `hueBleed` is above 0, and the pigment\n * stays neutral otherwise.\n */\nfunction pigmentFor(\n kind: LightingKind,\n bg: LightingColor,\n fg: LightingColor | undefined,\n bgTone: number,\n tuning: Required<LightingTuning>,\n): { h: number; s: number; l: number } {\n const reach = clamp(tuning.reach, 0, 1);\n const tone =\n kind === 'shadow' ? bgTone * (1 - reach) : bgTone + (100 - bgTone) * reach;\n const bleed = clamp(tuning.hueBleed, 0, 1);\n const l = clamp(fromTone(tone), 0, 1);\n const tint = clamp(tuning.tint, 0, 1);\n const objectHue =\n fg !== undefined && fg.s > HUE_EPSILON && bleed > 0 ? fg.h : undefined;\n if (bg.s <= HUE_EPSILON) {\n return objectHue === undefined\n ? { h: bg.h, s: 0, l }\n : { h: objectHue, s: tint, l };\n }\n const h =\n objectHue === undefined ? bg.h : circularLerp(bg.h, objectHue, bleed);\n return { h, s: tint, l };\n}\n\n/**\n * Solve the pigment opacity that moves `bg` exactly `intensity × k` tones\n * darker (shadow) or lighter (glow) once the browser composites it.\n *\n * The composite's luminance is convex in alpha (each gamma channel moves\n * linearly and the sRGB decode is convex), so the \"has reached the step\"\n * predicate is monotone whenever full opacity reaches it and a bisection\n * lands it exactly. When it doesn't, the step is out of reach — a glow on\n * white, a deep shadow on near-black — and the result pins to the pigment's\n * strongest composite, reporting what it reached in `reached`.\n *\n * A glow with `headroom` above 0 whose target tone passes 100 also gets\n * `hdr` (see `exposeGlow`) when SDR is pinned at its brightest\n * (`pinnedBase`); the SDR fields are the same with or without it.\n */\nexport function computeLighting(\n kind: LightingKind,\n bg: LightingColor,\n fg: LightingColor | undefined,\n intensity: number,\n tuning: Required<LightingTuning> & GlowTuning,\n pastel: boolean,\n): LightingResult {\n const bgTone = toTone(bg.l);\n const k = objectFactor(\n kind,\n bgTone,\n fg === undefined ? undefined : toTone(fg.l),\n tuning.objectInfluence,\n );\n const step = clamp(intensity, 0, 100) * k;\n const pigment = pigmentFor(kind, bg, fg, bgTone, tuning);\n\n const bgGamma = toDisplayGamma(\n okhslToLinearSrgb(bg.h, bg.s, bg.l, bg.pastel ?? pastel),\n );\n const pigmentGamma = toDisplayGamma(\n okhslToLinearSrgb(pigment.h, pigment.s, pigment.l, pastel),\n );\n const toneAt = (alpha: number): number =>\n toneFromY(\n relativeLuminanceFromLinearRgb(\n compositeOverGamma(bgGamma, pigmentGamma, alpha),\n ),\n );\n const surfaceTone = toneAt(0);\n const d = kind === 'shadow' ? 1 : -1;\n const gain = (alpha: number): number => d * (surfaceTone - toneAt(alpha));\n\n const { alpha, reached } = solveOpacity(kind, gain, step);\n const result: LightingResult = { ...pigment, alpha, step, reached };\n\n const headroom = tuning.headroom ?? 0;\n if (kind === 'glow' && headroom > 0 && step > 0) {\n const base = pinnedBase(alpha, surfaceTone, pigment, bg, pastel);\n const hdr =\n base === undefined\n ? undefined\n : exposeGlow(base, surfaceTone, step, headroom);\n if (hdr !== undefined) result.hdr = hdr;\n }\n return result;\n}\n\n/**\n * The SDR opacity solve: the smallest opacity whose composite reaches `step`,\n * or — out of reach — the pigment's strongest composite.\n */\nfunction solveOpacity(\n kind: LightingKind,\n gain: (alpha: number) => number,\n step: number,\n): { alpha: number; reached: number } {\n if (step <= 0) return { alpha: 0, reached: 0 };\n\n // The predicate is monotone on [0, hi] once `gain(hi)` reaches the step.\n let hi = 1;\n if (gain(1) < step) {\n hi = kind === 'shadow' ? strongestShadowAlpha(gain) : 1;\n const reached = gain(hi);\n if (reached < step) {\n // A pigment that cannot move the surface at all — or only by float\n // noise, as a neutral one at the surface's own tone — stays transparent.\n return reached > NO_LIFT_EPS\n ? { alpha: hi, reached }\n : { alpha: 0, reached: 0 };\n }\n }\n\n let lo = 0;\n for (let i = 0; i < BISECT_ITERATIONS; i++) {\n const mid = (lo + hi) / 2;\n if (gain(mid) < step) lo = mid;\n else hi = mid;\n }\n return { alpha: hi, reached: gain(hi) };\n}\n\n/** An OKHSL color in the standard (non-pastel) space the HDR base uses. */\nfunction standardOkhsl(\n c: { h: number; s: number; l: number },\n pastel: boolean,\n): { h: number; s: number; l: number } {\n if (!pastel) return { h: c.h, s: c.s, l: c.l };\n const [h, s, l] = oklabToOkhsl(okhslToOklab(c.h, c.s, c.l, true));\n return { h, s, l };\n}\n\n/**\n * What SDR paints once it is pinned at its brightest, as standard OKHSL — the\n * only color an HDR glow exposes. Past white SDR cannot land the step, so the\n * solved opacity is 0 or 1 there: at 1 that is the pigment itself; at 0 it is\n * the surface, which counts only when it is white (no pigment can lift white,\n * and SDR shows white). A pigment that cannot lift a non-white surface at all\n * — `reach: 0` on a gray surface, say, or a `tint` that only darkens — paints\n * nothing in SDR, so there is nothing to expose. (On a chromatic surface a\n * `reach: 0` pigment, a gray at the surface's tone, can measure slightly\n * brighter; it then pins at 1 like any pigment.) An exposure of the bare\n * surface would be an opaque, brighter copy of it where SDR leaves the surface\n * showing, and a neutral one clips to opaque white wherever HDR is clamped.\n * `undefined` then (and for any opacity between, which only float noise at the\n * trigger reaches).\n */\nfunction pinnedBase(\n alpha: number,\n surfaceTone: number,\n pigment: { h: number; s: number; l: number },\n bg: LightingColor,\n pastel: boolean,\n): { h: number; s: number; l: number } | undefined {\n if (alpha === 1) return standardOkhsl(pigment, pastel);\n if (alpha === 0 && surfaceTone >= 100 - WHITE_SURFACE_EPS) {\n return standardOkhsl(bg, bg.pastel ?? pastel);\n }\n return undefined;\n}\n\n/**\n * HDR value of a glow past white: an opaque exposure of `base` — what SDR\n * paints at its brightest (`pinnedBase`), as standard OKHSL — by the gain that\n * lands the target tone `surfaceTone + step`, capped so no channel passes\n * `2^headroom` (displays clip per channel; for a neutral base that is a cap on\n * luminance). `undefined` when the target stays at or below 100 — the trigger\n * depends on the target alone — or when the base is black and has nothing to\n * expose.\n *\n * Tone runs past 100 unchanged (`toneFromY` / `yFromTone` are unclamped), so\n * equal tone steps above white are still equal `Y + 0.05` ratios. The gain is\n * measured on the base as stored, so base × `2^exposure` lands the step to\n * float precision. It lands the whole step, not just the part past white: a\n * base at white (full `reach`) meets SDR with `exposure` → 0 as the target\n * goes to 100⁺, while a base below white (`reach` under 1) starts at\n * `log2(Y(100) / Y(base))` — just under white SDR stays short at the pigment\n * and warns; just past it HDR lands the exact step.\n */\nfunction exposeGlow(\n base: { h: number; s: number; l: number },\n surfaceTone: number,\n step: number,\n headroom: number,\n): LightingHdr | undefined {\n const target = surfaceTone + step;\n if (!(target > 100 + HDR_TRIGGER_EPS)) return undefined;\n\n const linear = okhslToLinearSrgb(base.h, base.s, base.l);\n const yBase = relativeLuminanceFromLinearRgb(linear);\n const peak = Math.max(linear[0], linear[1], linear[2]);\n if (!(yBase > 0) || !(peak > 0)) return undefined;\n\n const m = Math.min(yFromTone(target) / yBase, 2 ** headroom / peak);\n if (!(m > 1)) return undefined;\n return {\n ...base,\n exposure: Math.log2(m),\n reached: toneFromY(yBase * m) - surfaceTone,\n };\n}\n\n/** The solver's HDR value (OKHSL base) as a `ResolvedHdr` (OKHST base). */\nexport function toResolvedHdr(hdr: LightingHdr): ResolvedHdr {\n const { h, s, t } = okhslToOkhst(hdr);\n return { h, s, t, exposure: hdr.exposure };\n}\n\n/**\n * Linear sRGB of a resolved HDR value: the base's channels times\n * `2^exposure`, unclamped (the brightest channel can reach `2^headroom`).\n * The base is non-pastel OKHSL, so no `pastel` flag applies.\n */\nexport function hdrToLinearSrgb(hdr: ResolvedHdr): [number, number, number] {\n const { h, s, l } = okhstToOkhsl(hdr);\n const [r, g, b] = okhslToLinearSrgb(h, s, l);\n const m = 2 ** hdr.exposure;\n return [r * m, g * m, b * m];\n}\n\n/**\n * Extended sRGB of a resolved HDR value: `hdrToLinearSrgb` through the sRGB\n * transfer function, continued past 1 the way CSS and the platform\n * extended-sRGB spaces continue it, unclamped. These are the channels of\n * `color(srgb R G B)` (`glaze.formatHdr()`), and what a WebGPU `'srgb'`\n * canvas, `CGColorSpace.extendedSRGB`, and Android's `EXTENDED_SRGB` take.\n */\nexport function hdrToSrgb(hdr: ResolvedHdr): [number, number, number] {\n const [r, g, b] = hdrToLinearSrgb(hdr);\n return [sRGBLinearToGamma(r), sRGBLinearToGamma(g), sRGBLinearToGamma(b)];\n}\n\n/**\n * Opacity of a shadow pigment's darkest composite. Full opacity for pure\n * black; a tinted pigment whose channels pull in different directions can\n * bottom out earlier, so a golden-section search over the unimodal gain finds\n * it and the better of that and full opacity wins. (A glow needs no search:\n * convex luminance peaks at an endpoint, and full opacity is the one that\n * lightens.)\n */\nfunction strongestShadowAlpha(gain: (alpha: number) => number): number {\n let a = 0;\n let b = 1;\n for (let i = 0; i < BISECT_ITERATIONS; i++) {\n const c = b - GOLDEN * (b - a);\n const e = a + GOLDEN * (b - a);\n if (gain(c) < gain(e)) a = c;\n else b = e;\n }\n const peak = (a + b) / 2;\n return gain(peak) > gain(1) ? peak : 1;\n}\n","/**\n * Contrast solver — operates in OKHST tone.\n *\n * Finds the tone closest to a preferred tone that satisfies a contrast\n * floor (WCAG 2 ratio or APCA Lc) against a base color. Because tone is\n * contrast-uniform, the WCAG branch gets a closed-form seed and the search\n * converges quickly.\n *\n * Both solvers search two branches that meet at the preferred position, which\n * has already missed the overshooting search target and so sits between the\n * passing regions. Each branch therefore reaches only its own side: a result\n * sits where its `branch` / `flipped` say, and keeps the overshoot that absorbs\n * formatting rounding. The WCAG gray seed is only the initial branch's first\n * probe, never a bound, so a chromatic color still lands on its own crossing\n * nearest the preferred tone. When no searched side meets the floor but the\n * preferred position itself clears the bare target (it sits on a bound, or its\n * side was never searched), the preferred position is the answer, met; the\n * tone solver labels it `'preferred'`, as it does a met result from a starting\n * side whose only position is the preferred tone. With no direction given, a\n * solver starts toward the end that scores higher, and a float-noise gap\n * between the two ends is a tie that starts darker / lower.\n *\n * Public API: `findToneForContrast`, `findValueForMixContrast`,\n * `resolveMinContrast`, `resolveApcaTarget`, `resolveContrastForMode`,\n * `resolveContrastForLevel`, `apcaContrast`, plus the `APCA_PRESETS`,\n * `APCA_HC_ENHANCEMENT` and `APCA_MAX_LC` constants.\n */\n\nimport {\n okhslToLinearSrgb,\n contrastRatioFromLuminance,\n gamutClampedLuminance,\n apcaLuminanceFromLinearRgb,\n} from './okhsl-color-math';\nimport { REF_EPS, fromTone, toneFromY } from './okhst';\nimport { clamp, lerp, levelFraction, pairHC, pairNormal } from './hc-pair';\nimport type { ContrastSpec, HCPair } from './types';\n\nexport type LinearRgb = [number, number, number];\n\nexport type ContrastMetric = 'wcag' | 'apca';\n\n/**\n * Luminance of a linear-sRGB color in the basis the metric expects: WCAG\n * relative luminance for `wcag`, APCA screen luminance (`Ys`) for `apca`.\n */\nexport function metricLuminance(\n metric: ContrastMetric,\n linearRgb: LinearRgb,\n): number {\n return metric === 'apca'\n ? apcaLuminanceFromLinearRgb(linearRgb)\n : gamutClampedLuminance(linearRgb);\n}\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type ContrastPreset = 'AA' | 'AAA' | 'AA-large' | 'AAA-large';\nexport type MinContrast = number | ContrastPreset;\n\n/**\n * Named APCA Lc floor presets (APCA Bronze Simple Mode conformance levels),\n * independent of role. Use them anywhere an APCA target is accepted.\n *\n * | Preset | Lc | Use case |\n * | ------------- | --- | ---------------------------------------------------- |\n * | `'preferred'` | 90 | Preferred body / column text |\n * | `'body'` | 75 | Minimum body / column text |\n * | `'content'` | 60 | Readable non-body content (~WCAG AA 4.5:1) |\n * | `'large'` | 45 | Large/bold headlines; fine icons/outlines (~3:1) |\n * | `'non-text'` | 30 | Solid icons/controls; placeholder/disabled text |\n * | `'min'` | 15 | Dividers/decorative; APCA \"point of invisibility\" |\n */\nexport type ApcaPreset =\n | 'preferred'\n | 'body'\n | 'content'\n | 'large'\n | 'non-text'\n | 'min';\n\nexport const APCA_PRESETS: Record<ApcaPreset, number> = {\n preferred: 90,\n body: 75,\n content: 60,\n large: 45,\n 'non-text': 30,\n min: 15,\n};\n\n/**\n * APCA-W3 \"Enhanced Level\" delta added to a bare APCA target in high-contrast\n * mode when no explicit HC value is provided (analogous to WCAG AAA over AA).\n * Only applied when neither the outer `contrast` pair nor the inner `apca`\n * pair carries an explicit HC entry.\n */\nexport const APCA_HC_ENHANCEMENT = 15;\n\n/** Upper bound for an APCA Lc target after HC enhancement. */\nexport const APCA_MAX_LC = 106;\n\n/**\n * Resolve an APCA target — a raw Lc number (kept as-is) or an `ApcaPreset`\n * keyword mapped to its Lc value. The magnitude is forced non-negative.\n */\nexport function resolveApcaTarget(value: number | ApcaPreset): number {\n if (typeof value === 'number') return Math.abs(value);\n return APCA_PRESETS[value];\n}\n\n/** Metric + numeric target after resolving a `ContrastSpec` for a mode. */\nexport interface ResolvedContrast {\n metric: 'wcag' | 'apca';\n /** WCAG ratio (>= 1) or APCA Lc magnitude (0–106). */\n target: number;\n /**\n * APCA argument order: which side the resolved (candidate) color plays\n * against the base. `'fg'` (default) → `apcaContrast(yCandidate, yBase)`;\n * `'bg'` → `apcaContrast(yBase, yCandidate)`. Always `'fg'` for WCAG\n * (symmetric, ignored).\n */\n polarity?: 'fg' | 'bg';\n}\n\n// ============================================================================\n// Preset mapping + spec resolution\n// ============================================================================\n\nconst CONTRAST_PRESETS: Record<ContrastPreset, number> = {\n AA: 4.5,\n AAA: 7,\n 'AA-large': 3,\n 'AAA-large': 4.5,\n};\n\n/**\n * WCAG high-contrast auto-promotion (analog of APCA's Enhanced Level). A bare\n * AA / AA-large preset is promoted to its spec-defined \"Enhanced\" successor\n * (SC 1.4.3 → SC 1.4.6) in high-contrast mode. AAA / AAA-large are already\n * the top WCAG tier and are left unchanged. Bare numeric targets have no\n * defined successor tier and are also left unchanged. An explicit HC value\n * (outer or inner pair) always overrides.\n */\nconst WCAG_HC_PROMOTION: Partial<Record<ContrastPreset, ContrastPreset>> = {\n AA: 'AAA',\n 'AA-large': 'AAA-large',\n};\n\n/** An `{ apca }` spec: its `apca` is set (a key holding `undefined` is not). */\nfunction isApcaSpec(\n spec: object,\n): spec is Extract<ContrastSpec, { apca: unknown }> {\n return (spec as { apca?: unknown }).apca !== undefined;\n}\n\n/** Whether `value` names a WCAG preset (internal; see validation.ts). */\nexport function isContrastPreset(value: unknown): value is ContrastPreset {\n return typeof value === 'string' && Object.hasOwn(CONTRAST_PRESETS, value);\n}\n\n/** Whether `value` names an APCA preset (internal; see validation.ts). */\nexport function isApcaPreset(value: unknown): value is ApcaPreset {\n return typeof value === 'string' && Object.hasOwn(APCA_PRESETS, value);\n}\n\nexport function resolveMinContrast(value: MinContrast): number {\n if (typeof value === 'number') {\n return Math.max(1, value);\n }\n return CONTRAST_PRESETS[value];\n}\n\n/**\n * Resolve a WCAG target (number or preset) for a mode, applying the\n * high-contrast auto-promotion when `explicitHC` is false and the value is an\n * AA-family preset. Bare numbers and AAA-family presets pass through.\n */\nfunction resolveWcagTarget(\n value: number | ContrastPreset,\n isHighContrast: boolean,\n explicitHC: boolean,\n): number {\n if (typeof value === 'number') {\n return resolveMinContrast(value);\n }\n if (isHighContrast && !explicitHC) {\n const promoted = WCAG_HC_PROMOTION[value];\n if (promoted !== undefined) return resolveMinContrast(promoted);\n }\n return resolveMinContrast(value);\n}\n\nfunction pickPair<T>(p: HCPair<T>, isHighContrast: boolean): T {\n return Array.isArray(p) ? (isHighContrast ? p[1] : p[0]) : p;\n}\n\n/**\n * The metric a single `ContrastSpec` measures in. Bare numbers and WCAG\n * presets are `'wcag'`; only an `{ apca }` object is `'apca'`.\n */\nexport function contrastMetricOf(spec: ContrastSpec): ContrastMetric {\n return typeof spec === 'object' && isApcaSpec(spec) ? 'apca' : 'wcag';\n}\n\n/**\n * Resolve a `ContrastSpec` (already selected from any outer HC pair) for a\n * given mode into `{ metric, target }`. Handles the inner metric HC pair and\n * preset resolution. `polarity` is passed through to the result for the APCA\n * branch (it controls argument order in the solver); WCAG ignores it.\n *\n * `outerExplicitHC` indicates whether the caller selected this `spec` from an\n * explicit high-contrast entry of the outer `contrast` pair. Together with the\n * inner metric pair, it decides whether the HC auto-enhancement fires:\n * - APCA: +15 Lc \"Enhanced Level\" boost when neither level is explicit.\n * - WCAG: AA → AAA / AA-large → AAA-large promotion (SC 1.4.3 → 1.4.6) when\n * neither level is explicit. AAA-family presets and bare numbers are left\n * unchanged (AAA is the top WCAG tier).\n * Defaults to `false` (correct for direct callers, which pass a single\n * selected spec rather than an outer pair).\n */\nexport function resolveContrastForMode(\n spec: ContrastSpec,\n isHighContrast: boolean,\n polarity?: 'fg' | 'bg',\n outerExplicitHC?: boolean,\n): ResolvedContrast {\n if (typeof spec === 'number' || typeof spec === 'string') {\n // A bare string here is a WCAG preset ('AA' / 'AAA' / ...).\n return {\n metric: 'wcag',\n target: resolveWcagTarget(spec, isHighContrast, !!outerExplicitHC),\n };\n }\n if (isApcaSpec(spec)) {\n const baseTarget = resolveApcaTarget(pickPair(spec.apca, isHighContrast));\n const innerExplicitHC = Array.isArray(spec.apca);\n // The cap only limits the boost: a normal target already past it is kept.\n const enhanced =\n isHighContrast && !outerExplicitHC && !innerExplicitHC\n ? Math.max(\n baseTarget,\n Math.min(baseTarget + APCA_HC_ENHANCEMENT, APCA_MAX_LC),\n )\n : baseTarget;\n return {\n metric: 'apca',\n target: enhanced,\n polarity: polarity ?? 'fg',\n };\n }\n const innerExplicitHC = Array.isArray(spec.wcag);\n const picked = pickPair(spec.wcag, isHighContrast);\n return {\n metric: 'wcag',\n target: resolveWcagTarget(\n picked,\n isHighContrast,\n !!outerExplicitHC || innerExplicitHC,\n ),\n };\n}\n\n/**\n * Resolve a `contrast` spec — including its outer `[normal, highContrast]`\n * pair — at a manual contrast `level` (0–100), by resolving both ends and\n * interpolating the numeric target.\n *\n * Level 0 / 100 delegate verbatim to {@link resolveContrastForMode}, so the\n * endpoints are bit-identical to classic normal / high-contrast resolution.\n * Resolving each end fully first also means every rule that governs the\n * escalation still applies at both ends for free: preset mapping, the\n * `APCA_MAX_LC` clamp, and the explicit-HC suppression that cancels the\n * `AA → AAA` promotion and the `+15 Lc` enhancement.\n *\n * Throws when the two ends measure in different metrics — a WCAG ratio and an\n * APCA Lc live on different scales, so there is no target between them. Such a\n * pair is rejected at authoring time by `validateColorDefs`; this is the guard\n * for direct callers.\n */\nexport function resolveContrastForLevel(\n spec: HCPair<ContrastSpec>,\n level: number,\n polarity?: 'fg' | 'bg',\n): ResolvedContrast {\n if (!Number.isFinite(level)) {\n throw new Error(\n `glaze: resolveContrastForLevel needs a finite level (got ${level}).`,\n );\n }\n const outerExplicitHC = Array.isArray(spec);\n const f = levelFraction(level);\n const normal = resolveContrastForMode(\n pairNormal(spec),\n false,\n polarity,\n outerExplicitHC,\n );\n if (f <= 0) return normal;\n const hc = resolveContrastForMode(\n pairHC(spec),\n true,\n polarity,\n outerExplicitHC,\n );\n if (f >= 1) return hc;\n if (normal.metric !== hc.metric) {\n throw new Error(\n `glaze: a \"contrast\" pair cannot switch metric between its normal ` +\n `(${normal.metric}) and high-contrast (${hc.metric}) entry — the two ` +\n `targets are on different scales. Use one metric for both entries.`,\n );\n }\n // Spread `normal` so the WCAG branch keeps its absent `polarity` and the\n // APCA branch its resolved one.\n return { ...normal, target: lerp(normal.target, hc.target, f) };\n}\n\n// ============================================================================\n// APCA (SAPC / APCA-W3 0.1.9 simplified)\n// ============================================================================\n\nconst APCA_EXPONENTS = {\n mainTRC: 2.4,\n normBG: 0.56,\n normTXT: 0.57,\n revTXT: 0.62,\n revBG: 0.65,\n};\nconst APCA_BLACK_THRESH = 0.022;\nconst APCA_BLACK_CLIP = 1.414;\nconst APCA_DELTA_Y_MIN = 0.0005;\nconst APCA_SCALE = 1.14;\nconst APCA_LO_OFFSET = 0.027;\n\nfunction apcaSoftClamp(y: number): number {\n const yc = Math.max(0, y);\n if (yc >= APCA_BLACK_THRESH) return yc;\n return yc + Math.pow(APCA_BLACK_THRESH - yc, APCA_BLACK_CLIP);\n}\n\n/**\n * APCA lightness contrast (Lc), signed: positive for dark text on light bg,\n * negative for light text on dark bg. Inputs are screen luminances (0–1).\n */\nexport function apcaContrast(yText: number, yBg: number): number {\n const txt = apcaSoftClamp(yText);\n const bg = apcaSoftClamp(yBg);\n\n if (Math.abs(bg - txt) < APCA_DELTA_Y_MIN) return 0;\n\n let sapc: number;\n if (bg > txt) {\n // Normal polarity: dark text on light bg.\n sapc =\n (Math.pow(bg, APCA_EXPONENTS.normBG) -\n Math.pow(txt, APCA_EXPONENTS.normTXT)) *\n APCA_SCALE;\n return sapc < 0.1 ? 0 : (sapc - APCA_LO_OFFSET) * 100;\n }\n // Reverse polarity: light text on dark bg.\n sapc =\n (Math.pow(bg, APCA_EXPONENTS.revBG) -\n Math.pow(txt, APCA_EXPONENTS.revTXT)) *\n APCA_SCALE;\n return sapc > -0.1 ? 0 : (sapc + APCA_LO_OFFSET) * 100;\n}\n\n// ============================================================================\n// Tone -> luminance (cached)\n// ============================================================================\n\nconst CACHE_SIZE = 512;\nconst luminanceCache = new Map<string, number>();\nconst cacheOrder: string[] = [];\n\n/**\n * Tones are rounded to `1 / TONE_STEPS` (0.0001) before measuring, so the tone\n * solver can't resolve a crossing more finely than that, whatever `epsilon`.\n */\nconst TONE_STEPS = 10000;\n\n/**\n * Luminance of an OKHST color `(h, s, t)` with t in 0–1 (reference eps), in\n * the metric's luminance basis. The metric is part of the cache key because\n * WCAG and APCA derive different luminances from the same color.\n */\nfunction cachedLuminance(\n metric: ContrastMetric,\n h: number,\n s: number,\n t: number,\n pastel: boolean,\n): number {\n const tRounded = Math.round(t * TONE_STEPS) / TONE_STEPS;\n const key = `${metric}|${h}|${s}|${tRounded}|${pastel}`;\n\n const cached = luminanceCache.get(key);\n if (cached !== undefined) return cached;\n\n const l = fromTone(tRounded * 100, REF_EPS);\n const linearRgb = okhslToLinearSrgb(h, s, l, pastel);\n const y = metricLuminance(metric, linearRgb);\n\n if (luminanceCache.size >= CACHE_SIZE) {\n const evict = cacheOrder.shift()!;\n luminanceCache.delete(evict);\n }\n luminanceCache.set(key, y);\n cacheOrder.push(key);\n\n return y;\n}\n\n// ============================================================================\n// Metric evaluation\n// ============================================================================\n\n/**\n * Score a candidate luminance against the base for a metric. Returns a value\n * that is `>= target` exactly when the floor is met (WCAG ratio, or APCA Lc\n * magnitude). For APCA, `polarity` selects the argument order: `'fg'` (the\n * default) treats the candidate as the text against a background base\n * (`apcaContrast(yCandidate, yBase)`); `'bg'` treats the candidate as the\n * background (`apcaContrast(yBase, yCandidate)`). The magnitude is taken\n * either way. WCAG is symmetric, so polarity is ignored there.\n */\nexport function metricScore(\n metric: 'wcag' | 'apca',\n yCandidate: number,\n yBase: number,\n polarity?: 'fg' | 'bg',\n): number {\n if (metric === 'wcag') return contrastRatioFromLuminance(yCandidate, yBase);\n const lc =\n polarity === 'bg'\n ? apcaContrast(yBase, yCandidate)\n : apcaContrast(yCandidate, yBase);\n return Math.abs(lc);\n}\n\n/**\n * Relative gap under which two scores count as equal when a solver picks its\n * starting side from the two ends of its range. Tone is WCAG-uniform, so a\n * gray base at tone 50 sits exactly as far from black as from white: without\n * a tolerance, float noise in the base (1e-16 is enough) decides which end\n * scores higher, and with it the side a color lands on.\n */\nconst SCORE_TIE_TOLERANCE = 1e-9;\n\n/** `a >= b`, with a gap inside {@link SCORE_TIE_TOLERANCE} counted as a tie. */\nfunction scoreAtLeast(a: number, b: number): boolean {\n return a >= b - SCORE_TIE_TOLERANCE * Math.max(1, Math.abs(b));\n}\n\n// ============================================================================\n// Solver\n// ============================================================================\n\nexport interface FindToneForContrastOptions {\n /** Hue of the candidate color (0–360). */\n hue: number;\n /** Saturation of the candidate color (0–1). */\n saturation: number;\n /** Preferred tone of the candidate (0–1). */\n preferredTone: number;\n\n /** Base/reference color as linear sRGB. */\n baseLinearRgb: LinearRgb;\n\n /** Resolved contrast floor (metric + target). */\n contrast: ResolvedContrast;\n\n /** Search bounds for tone. Default: [0, 1]. */\n toneRange?: [number, number];\n /** Convergence threshold. Default: 1e-4. */\n epsilon?: number;\n /** Maximum binary-search iterations per branch. Default: 18. */\n maxIterations?: number;\n /**\n * Preferred search direction before auto-flip is considered. Default: the\n * side whose bound scores higher (the only open side when `preferredTone`\n * sits on a bound); a tie within float noise starts `'darker'`.\n */\n initialDirection?: 'lighter' | 'darker';\n /**\n * Also search the opposite direction. Default: false. When both directions\n * meet the target, the result nearer `preferredTone` wins; a gap within\n * twice the search resolution is a tie and keeps `initialDirection`.\n */\n flip?: boolean;\n /**\n * When `flip` is on and *both* directions meet the target, keep\n * `initialDirection` instead of taking whichever result lands nearer the\n * preferred tone. Default: false (nearest wins).\n *\n * The nearest-wins tie-break is unstable along a ramp of targets: which side\n * is nearer shifts as the target grows, so a color can swap sides between two\n * adjacent targets. Set this when a caller needs the side to be a property of\n * the color rather than of the target — the manual contrast level does. The\n * flip itself is unaffected: an initial direction that cannot reach the\n * target still falls back to the opposite side.\n */\n preferInitial?: boolean;\n /** Use the hue-independent \"safe\" chroma boundary. Default: false. */\n pastel?: boolean;\n}\n\nexport interface FindToneForContrastResult {\n /** Chosen tone in 0–1. */\n tone: number;\n /** Achieved score (WCAG ratio or APCA Lc magnitude). */\n contrast: number;\n /** Whether the target was reached. */\n met: boolean;\n /**\n * The side the result was found on. The two sides meet at `preferredTone`,\n * so a met result sits on that side of the base too. `'preferred'` whenever\n * a met result is `preferredTone` itself: it already cleared the\n * overshooting search target, or it clears the bare target and no search\n * could improve on it — no searched side met the floor, or the starting\n * side's only position was `preferredTone` (it sits on that side's bound).\n * Also `'preferred'` when `toneRange` leaves no room to search, met or not.\n * An unmet result otherwise reports the side whose extreme it pinned to.\n */\n branch: 'lighter' | 'darker' | 'preferred';\n /** Whether the result auto-flipped to the opposite direction. */\n flipped?: boolean;\n}\n\n/**\n * Result of a single one-dimensional branch search. `pos` is the chosen\n * coordinate (tone or mix value depending on the caller's domain).\n */\ninterface BranchResult {\n pos: number;\n contrast: number;\n}\n\n/**\n * Binary search one branch, from its `inner` bound out to its `outer` extreme,\n * for the position nearest `inner` that meets `target`. The domain is whatever\n * `lum` interprets (tone 0–1 or mix parameter 0–1); the search is identical in\n * both cases, and either end may be the numerically lower one.\n *\n * The score falls toward the base, so a branch's passing positions form one run\n * that reaches out to `outer`: the outer extreme is the most the branch can\n * reach. When even it falls short, the branch reports that extreme — never\n * `inner`, which borders the opposite branch: a near-miss there may sit on the\n * other side of the base, and returning it as this branch's answer would\n * mislabel its side and drop the overshoot.\n *\n * `probe`, when it lies strictly between `inner` and `outer`, is measured\n * before the bisection and only narrows the bracket — to its passing side or\n * its failing side — so the result is still the crossing nearest `inner`.\n */\nfunction searchBranch(\n lum: (x: number) => number,\n inner: number,\n outer: number,\n yBase: number,\n metric: 'wcag' | 'apca',\n target: number,\n epsilon: number,\n maxIter: number,\n polarity?: 'fg' | 'bg',\n probe?: number,\n): BranchResult {\n const scoreOuter = metricScore(metric, lum(outer), yBase, polarity);\n if (scoreOuter < target) return { pos: outer, contrast: scoreOuter };\n\n const scoreInner = metricScore(metric, lum(inner), yBase, polarity);\n if (scoreInner >= target) return { pos: inner, contrast: scoreInner };\n\n // Invariant: `pass` meets the target, `fail` does not.\n let fail = inner;\n let pass = outer;\n if (probe !== undefined && (probe - inner) * (outer - probe) > 0) {\n if (metricScore(metric, lum(probe), yBase, polarity) >= target) {\n pass = probe;\n } else {\n fail = probe;\n }\n }\n for (let i = 0; i < maxIter; i++) {\n if (Math.abs(pass - fail) < epsilon) break;\n const mid = (fail + pass) / 2;\n if (metricScore(metric, lum(mid), yBase, polarity) >= target) pass = mid;\n else fail = mid;\n }\n\n return {\n pos: pass,\n contrast: metricScore(metric, lum(pass), yBase, polarity),\n };\n}\n\n/**\n * Closed-form WCAG tone seed: the gray tone whose luminance produces exactly\n * the target ratio against the base, on the requested side. The initial\n * branch measures it first so chromatic refinement starts from a tight\n * bracket; it is a probe, never a bound.\n */\nfunction wcagToneSeed(yBase: number, target: number, darker: boolean): number {\n const yTarget = darker\n ? (yBase + 0.05) / target - 0.05\n : target * (yBase + 0.05) - 0.05;\n const yClamped = Math.max(0, Math.min(1, yTarget));\n return Math.max(0, Math.min(1, toneFromY(yClamped, REF_EPS) / 100));\n}\n\n/**\n * Shared \"find the nearest passing position\" core for both the tone and mix\n * solvers. Both pick an initial direction within `[lo, hi]`, binary-search\n * that branch, optionally flip to the opposite branch, and pin to the\n * initial extreme on failure — they only differ in their domain and how the\n * search anchor / luminance closure are built. On failure each caller still\n * keeps `preferred` itself when it clears the bare target.\n *\n * The two branches meet at `preferred`. The core only runs once `preferred`\n * has missed `searchTarget`, so it sits strictly between the passing region on\n * each side of the base: the lower branch `[lo, preferred]` can only reach the\n * lower side's passing positions and the upper branch `[preferred, hi]` only\n * the upper side's. That is what keeps a result on the side its branch reports\n * and, away from the bounds, its contrast at `searchTarget` (overshoot\n * included).\n *\n * Both branches start at `preferred`, which is also the position the flip step\n * measures closeness against. `searchAnchor` (the WCAG seed for the tone\n * solver) is only the *initial* branch's first probe: measured before the\n * bisection, it narrows the bracket to whichever side of it the crossing lies\n * on, and never bounds the branch — so a chromatic color whose crossing sits\n * between `preferred` and the gray seed still reaches it.\n */\ninterface SolveCoreOptions {\n lum: (x: number) => number;\n yBase: number;\n metric: 'wcag' | 'apca';\n target: number;\n searchTarget: number;\n lo: number;\n hi: number;\n /**\n * First probe of the initial branch, never a bound (the tone solver's WCAG\n * seed). Ignored unless it lies strictly inside the initial branch.\n */\n searchAnchor?: number;\n /** Boundary between the branches; the flip step minimizes distance to it. */\n preferred: number;\n epsilon: number;\n /**\n * How finely a branch result is known: `epsilon`, or coarser when `lum` is\n * quantized. Nearest-wins treats distances within twice this as a tie.\n */\n resolution: number;\n maxIterations: number;\n flip: boolean;\n /** Keep the initial branch when both meet, instead of taking the nearest. */\n preferInitial: boolean;\n /** Force the first branch ('lower' searches `[lo, preferred]`). */\n initialIsLower: boolean;\n /** APCA argument order; ignored for WCAG. Default `'fg'`. */\n polarity?: 'fg' | 'bg';\n}\n\ninterface SolveCoreResult {\n pos: number;\n contrast: number;\n met: boolean;\n /** Which branch produced the result. */\n lower: boolean;\n flipped?: boolean;\n}\n\nfunction solveNearestContrast(opts: SolveCoreOptions): SolveCoreResult {\n const {\n lum,\n yBase,\n metric,\n target,\n searchTarget,\n lo,\n hi,\n searchAnchor,\n preferred,\n epsilon,\n resolution,\n maxIterations,\n flip,\n preferInitial,\n initialIsLower,\n polarity,\n } = opts;\n\n const boundary = clamp(preferred, lo, hi);\n\n const runBranch = (lower: boolean, probe?: number) => {\n const result = searchBranch(\n lum,\n boundary,\n lower ? lo : hi,\n yBase,\n metric,\n searchTarget,\n epsilon,\n maxIterations,\n polarity,\n probe,\n );\n return { ...result, met: result.contrast >= target, lower };\n };\n\n // The seed is probed first, so it can narrow the bracket from either side;\n // `searchBranch` skips it unless it lies inside the initial branch.\n const initial = runBranch(initialIsLower, searchAnchor);\n\n // A branch that misses the target reports its outer extreme, so an unmet\n // `initial` is already pinned to the initial direction's extreme — the\n // failure result whether or not the flip is tried.\n if (!flip) return initial;\n\n // The opposite branch exists only when `preferred` is strictly interior on\n // that side (matches the legacy canDarker/canUpper guards).\n const canOpposite = initialIsLower ? preferred < hi : preferred > lo;\n if (!canOpposite) return initial;\n const opposite = { ...runBranch(!initialIsLower), flipped: true };\n\n if (initial.met && opposite.met) {\n if (preferInitial) return initial;\n const initialDist = Math.abs(initial.pos - preferred);\n const oppositeDist = Math.abs(opposite.pos - preferred);\n // Each distance is only known to within `resolution`, so a gap inside\n // twice that is a tie — and a tie keeps the initial side. Without the\n // margin, an exact tie (a neutral color with no tone of its own sits the\n // same tone distance from either side's crossing) is decided by search\n // noise.\n return initialDist <= oppositeDist + 2 * resolution ? initial : opposite;\n }\n return opposite.met && !initial.met ? opposite : initial;\n}\n\n/**\n * Find the tone that satisfies a contrast floor against a base color,\n * staying as close to `preferredTone` as possible. A searched result keeps the\n * overshoot (1% for WCAG, 0.5 Lc for APCA). When no searched side reaches the\n * floor, the result pins to the initial direction's extreme, unmet — unless\n * `preferredTone` itself clears the bare target, which is then kept as met\n * (`branch: 'preferred'`, the same label a met result gets when the starting\n * side's only position is `preferredTone`).\n */\nexport function findToneForContrast(\n options: FindToneForContrastOptions,\n): FindToneForContrastResult {\n const {\n hue,\n saturation,\n preferredTone,\n baseLinearRgb,\n contrast,\n toneRange = [0, 1],\n epsilon = 1e-4,\n maxIterations = 18,\n pastel = false,\n } = options;\n\n const { metric, target, polarity } = contrast;\n // Overshoot absorbs rounding in the OKHSL/OKLCH formatting pipeline.\n const searchTarget = metric === 'wcag' ? target * 1.01 : target + 0.5;\n const yBase = metricLuminance(metric, baseLinearRgb);\n\n // Luminance of a candidate at tone `t`.\n const lum = (t: number): number =>\n cachedLuminance(metric, hue, saturation, t, pastel);\n\n const scorePref = metricScore(metric, lum(preferredTone), yBase, polarity);\n\n if (scorePref >= searchTarget) {\n return {\n tone: preferredTone,\n contrast: scorePref,\n met: true,\n branch: 'preferred',\n };\n }\n\n const [minT, maxT] = toneRange;\n const canDarker = preferredTone > minT;\n const canLighter = preferredTone < maxT;\n\n let initialIsDarker: boolean;\n if (options.initialDirection !== undefined) {\n initialIsDarker = options.initialDirection === 'darker';\n } else if (canDarker && !canLighter) {\n initialIsDarker = true;\n } else if (!canDarker && canLighter) {\n initialIsDarker = false;\n } else if (!canDarker && !canLighter) {\n return {\n tone: preferredTone,\n contrast: scorePref,\n met: scorePref >= target,\n branch: 'preferred',\n };\n } else {\n const scoreMin = metricScore(metric, lum(minT), yBase, polarity);\n const scoreMax = metricScore(metric, lum(maxT), yBase, polarity);\n // A tie (gray base at tone 50) starts darker, whatever the float noise.\n initialIsDarker = scoreAtLeast(scoreMin, scoreMax);\n }\n\n // For WCAG, the initial branch probes the closed-form gray seed first\n // (darker = the \"lower\" branch). It only narrows that branch's bracket: both\n // branches and the flip step's distance stay anchored to `preferredTone`.\n const searchAnchor =\n metric === 'wcag'\n ? wcagToneSeed(yBase, target, initialIsDarker)\n : undefined;\n\n const solved = solveNearestContrast({\n lum,\n yBase,\n metric,\n target,\n searchTarget,\n lo: minT,\n hi: maxT,\n searchAnchor,\n preferred: preferredTone,\n epsilon,\n resolution: Math.max(epsilon, 1 / TONE_STEPS),\n maxIterations,\n flip: options.flip ?? false,\n preferInitial: options.preferInitial ?? false,\n initialIsLower: initialIsDarker,\n polarity,\n });\n\n // `preferredTone` is the answer, met, with no search reaching past it:\n // - No searched side met the floor, yet it clears the bare target (it missed\n // only the overshoot). Its own side was never searched — it sits on a\n // bound, or a forced direction pointed away with no flip — or that side\n // would have met: a met side's extreme scores higher still. So it beats\n // the unmet extreme.\n // - The starting side's only position was `preferredTone` itself (it sits on\n // that side's bound), which met. That side found nothing, and its name\n // need not match where `preferredTone` sits relative to the base, so the\n // result is labelled like any other kept preferred tone.\n // A searched branch never returns its inner end, so `solved.pos` equals\n // `preferredTone` only for that degenerate side.\n if (solved.met ? solved.pos === preferredTone : scorePref >= target) {\n return {\n tone: preferredTone,\n contrast: scorePref,\n met: true,\n branch: 'preferred',\n };\n }\n\n return {\n tone: solved.pos,\n contrast: solved.contrast,\n met: solved.met,\n branch: solved.lower ? 'darker' : 'lighter',\n ...(solved.flipped ? { flipped: true } : {}),\n };\n}\n\n// ============================================================================\n// Mix contrast solver\n// ============================================================================\n\nexport interface FindValueForMixContrastOptions {\n /** Preferred mix parameter (0–1). */\n preferredValue: number;\n /** Base color as linear sRGB — the color the mix is measured against. */\n baseLinearRgb: LinearRgb;\n /** Resolved contrast floor (metric + target). */\n contrast: ResolvedContrast;\n /**\n * Luminance of the mixed color at parameter t, in the metric's basis\n * ({@link metricLuminance}). This closure is the only view the solver has of\n * the mix's target color, blend, and color space.\n */\n luminanceAtValue: (t: number) => number;\n /** Convergence threshold. Default: 1e-4. */\n epsilon?: number;\n /** Maximum binary-search iterations per branch. Default: 20. */\n maxIterations?: number;\n /** Auto-flip mix direction when contrast can't be met. Default: false. */\n flip?: boolean;\n}\n\nexport interface FindValueForMixContrastResult {\n value: number;\n contrast: number;\n met: boolean;\n flipped?: boolean;\n}\n\n/**\n * Find the mix parameter (ratio or opacity) that satisfies a contrast floor\n * against a base color, staying as close to `preferredValue` as possible.\n * Misses pin to the initial direction's end like the tone solver, and a\n * `preferredValue` that clears the bare target is kept as met when no searched\n * side reaches the floor (a value of 1 has no room toward the target).\n */\nexport function findValueForMixContrast(\n options: FindValueForMixContrastOptions,\n): FindValueForMixContrastResult {\n const {\n preferredValue,\n baseLinearRgb,\n contrast,\n luminanceAtValue,\n epsilon = 1e-4,\n maxIterations = 20,\n } = options;\n\n const { metric, target, polarity } = contrast;\n const searchTarget = metric === 'wcag' ? target * 1.01 : target + 0.5;\n const yBase = metricLuminance(metric, baseLinearRgb);\n\n const scorePref = metricScore(\n metric,\n luminanceAtValue(preferredValue),\n yBase,\n polarity,\n );\n if (scorePref >= searchTarget) {\n return { value: preferredValue, contrast: scorePref, met: true };\n }\n\n const canLower = preferredValue > 0;\n const canUpper = preferredValue < 1;\n let initialIsLower: boolean;\n if (canLower && !canUpper) {\n initialIsLower = true;\n } else if (!canLower && canUpper) {\n initialIsLower = false;\n } else if (!canLower && !canUpper) {\n return {\n value: preferredValue,\n contrast: scorePref,\n met: scorePref >= target,\n };\n } else {\n const scoreLower = metricScore(\n metric,\n luminanceAtValue(0),\n yBase,\n polarity,\n );\n const scoreUpper = metricScore(\n metric,\n luminanceAtValue(1),\n yBase,\n polarity,\n );\n initialIsLower = scoreAtLeast(scoreLower, scoreUpper);\n }\n\n const solved = solveNearestContrast({\n lum: luminanceAtValue,\n yBase,\n metric,\n target,\n searchTarget,\n lo: 0,\n hi: 1,\n preferred: preferredValue,\n epsilon,\n resolution: epsilon,\n maxIterations,\n flip: options.flip ?? false,\n // A mix searches along the base→target segment rather than across a base,\n // so the nearest-wins tie-break has no side to swap; left as-is.\n preferInitial: false,\n initialIsLower,\n polarity,\n });\n\n // `preferredValue` missed only the overshoot and no searched side met the\n // floor: keep it, met. At a value of 1 the only open side runs back to the\n // base, so without this a pure target that clears the floor would collapse\n // to the base itself (or to alpha 0 for a transparent mix).\n if (!solved.met && scorePref >= target) {\n return { value: preferredValue, contrast: scorePref, met: true };\n }\n\n return {\n value: solved.pos,\n contrast: solved.contrast,\n met: solved.met,\n ...(solved.flipped ? { flipped: true } : {}),\n };\n}\n","/**\n * Resolve-time warning dispatcher: unmet contrast floors (regular colors and\n * mixes), chromatic contrast drift, out-of-reach shadow / glow steps (SDR, and\n * HDR glows whose headroom cap falls short), and a glow `headroom` clamped to\n * its 2-stop maximum. A validator that checks more fields after a clamp queues\n * that warning (`DeferredWarnings`) and sends it with `flushWarnings` only once\n * the whole input has passed.\n *\n * Tokens memoize their resolution, but a long-lived process (e.g. a dev\n * server with HMR) can re-resolve the same theme many times. The cache\n * here dedupes warnings within a session with a soft cap to keep noise\n * bounded.\n */\n\nimport { apcaContrast } from './contrast-solver';\nimport type { ResolvedContrast } from './contrast-solver';\nimport { MAX_HEADROOM } from './lighting';\nimport type { LightingKind, LightingResult } from './lighting';\nimport { contrastRatioFromLuminance } from './okhsl-color-math';\n\nconst CONTRAST_WARN_CACHE_LIMIT = 256;\nconst contrastWarnCache = new Set<string>();\n\n/**\n * Slack factor below the requested target before we emit a warning.\n * The contrast solver overshoots to absorb rounding noise, so an actual\n * value within ~2x that overshoot is effectively a pass.\n */\nconst CONTRAST_WARN_SLACK_WCAG = 0.98;\n/** APCA Lc is on a 0–106 scale; allow a small absolute slack. */\nconst CONTRAST_WARN_SLACK_APCA = 1.5;\n\nfunction schemeLabel(isDark: boolean, isHighContrast: boolean): string {\n if (isDark && isHighContrast) return 'darkContrast';\n if (isDark) return 'dark';\n if (isHighContrast) return 'lightContrast';\n return 'light';\n}\n\nfunction metricLabel(c: ResolvedContrast): string {\n return c.metric === 'apca'\n ? `APCA Lc ${c.target.toFixed(1)}`\n : `WCAG ${c.target.toFixed(2)}`;\n}\n\nfunction dedupe(key: string): boolean {\n if (contrastWarnCache.has(key)) return true;\n if (contrastWarnCache.size >= CONTRAST_WARN_CACHE_LIMIT) {\n contrastWarnCache.clear();\n }\n contrastWarnCache.add(key);\n return false;\n}\n\n/**\n * Whether `actual` is short of the floor by more than the slack. The solver\n * aims slightly past the target, so a smaller shortfall is rounding noise. A\n * non-finite target or measurement counts as a miss, so it is reported.\n */\nfunction missesFloor(contrast: ResolvedContrast, actual: number): boolean {\n const slack =\n contrast.metric === 'apca'\n ? contrast.target - CONTRAST_WARN_SLACK_APCA\n : contrast.target * CONTRAST_WARN_SLACK_WCAG;\n return !(actual >= slack);\n}\n\nfunction contrastKey(\n kind: string,\n name: string,\n scheme: string,\n contrast: ResolvedContrast,\n actual: number,\n): string {\n return `${kind}|${name}|${scheme}|${contrast.metric}|${contrast.target.toFixed(\n 2,\n )}|${actual.toFixed(2)}`;\n}\n\n/** Warn when the solver could not reach the requested contrast floor. */\nexport function warnContrastUnmet(\n name: string,\n isDark: boolean,\n isHighContrast: boolean,\n contrast: ResolvedContrast,\n actual: number,\n): void {\n if (!missesFloor(contrast, actual)) return;\n\n const scheme = schemeLabel(isDark, isHighContrast);\n if (dedupe(contrastKey('unmet', name, scheme, contrast, actual))) return;\n\n console.warn(\n `glaze: color \"${name}\" cannot meet ${metricLabel(contrast)} in ` +\n `${scheme} scheme (got ${actual.toFixed(2)}). ` +\n `Try widening the tone window, lowering the contrast target, ` +\n `or picking a base color further from this color's tone.`,\n );\n}\n\n/**\n * Warn when a mix's ratio / opacity search could not reach its contrast floor\n * against the mix's `base`. An unmet mix means even the pure target falls\n * short, so the fix is the target color or the floor, not a tone window.\n * `actual` is the contrast of the value the mix settled at. `pastelCapped`\n * says the pastel cap is why: the mix's pastel gamut paints the target with\n * less saturation, and the target painted in full would meet the floor, so\n * the hint offers `pastel: false`.\n */\nexport function warnMixContrastUnmet(\n name: string,\n isDark: boolean,\n isHighContrast: boolean,\n contrast: ResolvedContrast,\n actual: number,\n pastelCapped = false,\n): void {\n if (!missesFloor(contrast, actual)) return;\n\n const scheme = schemeLabel(isDark, isHighContrast);\n if (dedupe(contrastKey('unmet-mix', name, scheme, contrast, actual))) return;\n\n console.warn(\n `glaze: mix \"${name}\" cannot meet ${metricLabel(contrast)} against its ` +\n `base in ${scheme} scheme (got ${actual.toFixed(2)}). ` +\n (pastelCapped\n ? `Even the pure target falls short once the mix's pastel gamut caps ` +\n `its saturation; try \\`pastel: false\\` on the mix, lowering the ` +\n `contrast target, or mixing toward a color further from the base.`\n : `Even the pure target falls short; try lowering the contrast ` +\n `target or mixing toward a color further from the base.`),\n );\n}\n\n/**\n * Verification (the drift check in docs/okhst.mdx): a chromatic swatch\n * inherits the gray tone's lightness but drifts in real luminance, so a\n * contrast-floored color may land slightly under the contrast its tone\n * implies. Emit an advisory warning when the actual measured contrast\n * drifts below the target. The caller skips achromatic variants and ones the\n * solver already reported through `warnContrastUnmet`.\n */\nexport function warnContrastDrift(\n name: string,\n isDark: boolean,\n isHighContrast: boolean,\n contrast: ResolvedContrast,\n yColor: number,\n yBase: number,\n): void {\n const actual =\n contrast.metric === 'apca'\n ? Math.abs(\n contrast.polarity === 'bg'\n ? apcaContrast(yBase, yColor)\n : apcaContrast(yColor, yBase),\n )\n : contrastRatioFromLuminance(yColor, yBase);\n\n if (!missesFloor(contrast, actual)) return;\n\n const scheme = schemeLabel(isDark, isHighContrast);\n if (dedupe(contrastKey('drift', name, scheme, contrast, actual))) return;\n\n console.warn(\n `glaze: color \"${name}\" drifts below ${metricLabel(contrast)} in ` +\n `${scheme} scheme (measured ${actual.toFixed(2)}). Chromatic luminance ` +\n `differs from the gray tone; nudge the tone or saturation if the floor matters.`,\n );\n}\n\n/** Tone slack before an out-of-reach shadow / glow step is worth a warning. */\nconst LIGHTING_WARN_SLACK = 0.05;\n\n/**\n * Warn when a `shadow` / `glow` step is out of reach of its pigment — a glow\n * on white, a deep shadow on near-black — so the composite pins to the\n * pigment's strongest and lands short. `name` is omitted for the standalone\n * `glaze.shadow()` / `glaze.glow()` factories, which have no scheme either.\n */\nexport function warnLightingUnreachable(\n kind: 'shadow' | 'glow',\n name: string | undefined,\n scheme: { isDark: boolean; isHighContrast: boolean } | undefined,\n step: number,\n reached: number,\n): void {\n if (reached >= step - LIGHTING_WARN_SLACK) return;\n\n const label = scheme\n ? schemeLabel(scheme.isDark, scheme.isHighContrast)\n : undefined;\n const key = `lighting|${kind}|${name ?? ''}|${label ?? ''}|${step.toFixed(\n 2,\n )}|${reached.toFixed(2)}`;\n if (dedupe(key)) return;\n\n const subject = name === undefined ? `glaze.${kind}()` : `${kind} \"${name}\"`;\n const where = label === undefined ? '' : ` in ${label} scheme`;\n const extreme = kind === 'shadow' ? 'black' : 'white';\n console.warn(\n `glaze: ${subject} cannot reach a ${step.toFixed(1)}-tone step${where} ` +\n `(reached ${reached.toFixed(1)} at full strength). Lower the intensity, ` +\n `move the surface away from ${extreme}, or raise a tuned-down \\`reach\\`.`,\n );\n}\n\n/**\n * `1 stop`, `2 stops`, `1.5 stops`, `0.004 stops`: three significant digits,\n * so a small headroom never reads as `0 stops`.\n */\nfunction stopsLabel(stops: number): string {\n const n = Number(stops.toPrecision(3));\n return `${n} stop${n === 1 ? '' : 's'}`;\n}\n\n/**\n * Warn when an HDR glow's gain is capped by its `headroom` short of the step:\n * the brightest channel sits at `2^headroom` and the composite lands\n * `reached` tones above the surface instead of `step`. Replaces the SDR\n * shortfall warning for that variant — when the cap does not bind, HDR covers\n * the step and neither warning fires. `name` / `scheme` are omitted for the\n * standalone `glaze.glow()`.\n */\nexport function warnHdrUnreachable(\n name: string | undefined,\n scheme: { isDark: boolean; isHighContrast: boolean } | undefined,\n step: number,\n reached: number,\n headroom: number,\n): void {\n if (reached >= step - LIGHTING_WARN_SLACK) return;\n\n const label = scheme\n ? schemeLabel(scheme.isDark, scheme.isHighContrast)\n : undefined;\n const key = `hdr|${name ?? ''}|${label ?? ''}|${step.toFixed(\n 2,\n )}|${reached.toFixed(2)}|${headroom}`;\n if (dedupe(key)) return;\n\n const subject = name === undefined ? 'glaze.glow()' : `glow \"${name}\"`;\n const where = label === undefined ? '' : ` in ${label} scheme`;\n const advice =\n headroom >= MAX_HEADROOM\n ? `Lower the intensity; \\`headroom\\` is already at its ${MAX_HEADROOM}-stop maximum.`\n : 'Lower the intensity or raise `headroom`.';\n console.warn(\n `glaze: ${subject} cannot reach a ${step.toFixed(1)}-tone step${where} ` +\n `even with ${stopsLabel(headroom)} of headroom ` +\n `(reached ${reached.toFixed(1)}). ${advice}`,\n );\n}\n\n/**\n * Report a shadow / glow solve that lands short. A glow with an HDR value\n * (the author opted into headroom) warns only when the headroom cap leaves\n * the step short (`warnHdrUnreachable`); everything else gets the SDR\n * shortfall warning (`warnLightingUnreachable`), unchanged at headroom 0.\n */\nexport function warnLightingShortfall(\n kind: LightingKind,\n name: string | undefined,\n scheme: { isDark: boolean; isHighContrast: boolean } | undefined,\n result: LightingResult,\n headroom: number,\n): void {\n if (result.hdr) {\n warnHdrUnreachable(name, scheme, result.step, result.hdr.reached, headroom);\n } else {\n warnLightingUnreachable(kind, name, scheme, result.step, result.reached);\n }\n}\n\n/**\n * Warnings a validator found, queued until the whole input has passed. Every\n * warning here is deduped for the session, so one sent by a call that then\n * throws on a later field would leave the corrected retry — the call that\n * actually applies the value — silent.\n */\nexport type DeferredWarnings = (() => void)[];\n\n/** Send the queued warnings, in the order they were found. */\nexport function flushWarnings(deferred: DeferredWarnings): void {\n for (const warn of deferred) warn();\n}\n\n/**\n * Warn, once per field and value, that a glow `headroom` above the maximum was\n * clamped. The likely cause is a ratio typed where stops were meant (`4` for\n * \"4× white\", which is 2 stops), so the message spells out the unit.\n */\nexport function warnHeadroomClamped(where: string, value: number): void {\n if (dedupe(`headroom|${where}|${value}`)) return;\n console.warn(\n `glaze: ${where}.headroom ${value} is above the ${MAX_HEADROOM}-stop ` +\n `maximum; using ${MAX_HEADROOM}. Headroom counts stops (doublings of SDR white's ` +\n `luminance), not a ratio: 1 stop is 2× white, 2 stops 4×.`,\n );\n}\n","/**\n * Glaze global configuration singleton.\n *\n * `configure()` mutates the singleton; every other module reads it via\n * `getConfig()` at call time so changes take effect for subsequent\n * resolves. Per-instance overrides (themes / color tokens) stay sparse —\n * omitted fields fall through to the live global at resolve time.\n * Authoring exports freeze the effective merge at export call time.\n *\n * `pastel` is instance-only (theme / token override or per-color def),\n * never set via `configure()`.\n *\n * Numeric fields are validated where they enter — `configure()` for the\n * global, `mergeConfig()` (i.e. at resolve) for per-instance overrides:\n * `contrastLevel` clamps to 0–100, `darkDesaturation` to 0–1, and tone windows\n * are checked and clamped by `normalizeToneWindow`; a non-finite value throws.\n * Both entry points treat only `undefined` as \"keep\" for a tone window, so a\n * `null` throws in either. A glow's HDR `headroom` (`normalizeLightingTuning`,\n * shared with the per-color and standalone validators) must be a finite number\n * ≥ 0 and clamps to `MAX_HEADROOM` stops with a one-time warning; a `headroom`\n * on shadow tuning throws. Both entry points hold that warning back\n * (`DeferredWarnings`) until every field has passed, so a call that throws on\n * a later field doesn't spend it before the corrected retry applies the clamp.\n *\n * No config object is shared with a caller, in either direction. Going in,\n * `configure()` copies what it keeps and a theme or token copies its override\n * once where it stores it (`copyConfigOverride`, which reads each known field\n * by property access, so getters and proxies work). Coming out,\n * `snapshotConfig()` (`glaze.getConfig()`) and `theme.getConfig()`\n * (`copyResolvedConfig`) hand out deep copies, and `mergeConfig()` /\n * `freezeConfigForExport()` build fresh objects. So mutating a value passed in\n * or handed out can't change a resolve or an export.\n */\n\nimport { showValue } from './hc-pair';\nimport { MAX_HEADROOM } from './lighting';\nimport type { LightingKind } from './lighting';\nimport { normalizeToneWindow } from './okhst';\nimport { flushWarnings, warnHeadroomClamped } from './warnings';\nimport type { DeferredWarnings } from './warnings';\nimport type {\n GlazeConfig,\n GlazeConfigOverride,\n GlazeConfigResolved,\n GlowTuning,\n ToneWindow,\n} from './types';\n\n/**\n * Build a fresh defaults object. Called from module init and from\n * `resetConfig()` so the two paths can't drift.\n *\n * `pastel: false` is a fixed instance default — not globally configurable.\n */\nexport function defaultConfig(): GlazeConfigResolved {\n return {\n lightTone: { lo: 10, hi: 100, eps: 0.05 },\n darkTone: { lo: 15, hi: 95, eps: 0.05 },\n darkDesaturation: 0.1,\n states: {\n dark: '@media(prefers-color-scheme: dark)',\n highContrast: '@media(prefers-contrast: more)',\n hdr: '@media(dynamic-range: high)',\n },\n modes: {\n dark: true,\n highContrast: false,\n hdr: false,\n },\n autoFlip: true,\n pastel: false,\n inferRole: true,\n contrastLevel: 'auto',\n };\n}\n\n/**\n * `value`, or `fallback` when it is `undefined`. Only `undefined` means\n * \"keep\": a `null` is passed on so the field's validator rejects it.\n */\nfunction keepIfUndefined<T>(value: T | undefined, fallback: T): T {\n return value !== undefined ? value : fallback;\n}\n\n/**\n * Validate an authored `contrastLevel`. Numbers clamp to 0–100 so a slider\n * can't produce an out-of-range level; a non-finite number throws rather than\n * silently reading as `'auto'`, which would turn a `NaN` slider value into an\n * invisible no-op.\n */\nexport function normalizeContrastLevel(\n value: number | 'auto' | undefined,\n): number | 'auto' {\n if (value === undefined || value === 'auto') return 'auto';\n if (typeof value !== 'number' || !Number.isFinite(value)) {\n throw new Error(\n `glaze: contrastLevel must be a finite number 0–100 or 'auto' (got ${showValue(value)}).`,\n );\n }\n return Math.max(0, Math.min(100, value));\n}\n\n/**\n * Validate an authored `darkDesaturation`, the way `normalizeContrastLevel`\n * treats a level. Numbers clamp to 0–1 — above 1 would zero every dark\n * saturation and a negative value would raise it — and a non-finite or\n * non-number value throws instead of producing `NaN` saturations.\n */\nexport function normalizeDarkDesaturation(value: number): number {\n if (typeof value !== 'number' || !Number.isFinite(value)) {\n throw new Error(\n `glaze: darkDesaturation must be a finite number 0–1 (got ${showValue(value)}).`,\n );\n }\n return Math.max(0, Math.min(1, value));\n}\n\n/**\n * Validate an authored tone window (see `normalizeToneWindow`) and return it in\n * the form it was written — `false`, `[lo, hi]`, or `{ lo, hi, eps }` — with\n * the endpoints clamped to 0–100. Always a fresh value, so mutating the\n * caller's array or object later can't reach the config.\n */\nexport function normalizeToneWindowInput(\n win: ToneWindow,\n field: 'lightTone' | 'darkTone',\n): ToneWindow {\n if (win === false) return false;\n const { lo, hi, eps } = normalizeToneWindow(win, field);\n return Array.isArray(win) ? [lo, hi] : { lo, hi, eps };\n}\n\n/**\n * Validate a glow's HDR `headroom` (stops above SDR white). A non-number,\n * non-finite, or negative value throws; one above `MAX_HEADROOM` clamps to it\n * with a one-time warning, since a ratio typed where stops were meant (`4` for\n * \"4× white\") is the likely cause. `where` names the tuning in messages\n * (`glowTuning`, `glow \"x\" tuning`, `glaze.glow() tuning`).\n *\n * With `deferred`, the clamp warning is queued there instead of sent, for a\n * caller that validates more fields after this one: it sends the queue only\n * once the whole input has passed (`flushWarnings`).\n */\nexport function normalizeHeadroom(\n value: unknown,\n where: string,\n deferred?: DeferredWarnings,\n): number {\n if (typeof value !== 'number' || !Number.isFinite(value) || value < 0) {\n throw new Error(\n `glaze: ${where}.headroom must be a finite number ≥ 0 — stops above ` +\n `SDR white (got ${showValue(value)}).`,\n );\n }\n if (value > MAX_HEADROOM) {\n const warn = (): void => warnHeadroomClamped(where, value);\n if (deferred) deferred.push(warn);\n else warn();\n return MAX_HEADROOM;\n }\n return value;\n}\n\n/**\n * Validate and copy a lighting tuning: a detached copy (or `undefined`) with\n * `objectInfluence` / `tint` / `reach` / `hueBleed` checked to be finite\n * numbers (the 0–1 fields clamp at use) and a glow's `headroom` checked and\n * clamped by `normalizeHeadroom`. A shadow has no headroom — it darkens toward\n * black, and nothing goes below black — so a `headroom` on shadow tuning\n * throws. Only `undefined` counts as unset. `deferred` queues the clamp\n * warning (see `normalizeHeadroom`).\n */\nexport function normalizeLightingTuning(\n kind: LightingKind,\n tuning: GlowTuning | undefined,\n where: string,\n deferred?: DeferredWarnings,\n): GlowTuning | undefined {\n if (tuning === undefined) return undefined;\n const out: GlowTuning = { ...tuning };\n for (const field of [\n 'objectInfluence',\n 'tint',\n 'reach',\n 'hueBleed',\n ] as const) {\n const value: unknown = out[field];\n if (\n value !== undefined &&\n (typeof value !== 'number' || !Number.isFinite(value))\n ) {\n throw new Error(\n `glaze: ${where}.${field} must be a finite number (got ${showValue(value)}).`,\n );\n }\n }\n const headroom = (tuning as { headroom?: unknown } | null)?.headroom;\n if (headroom === undefined) return out;\n if (kind === 'shadow') {\n throw new Error(\n `glaze: ${where}.headroom is not supported — a shadow darkens toward ` +\n `black, and nothing goes below black. Headroom is for glows ` +\n `(glowTuning or a glow's tuning).`,\n );\n }\n out.headroom = normalizeHeadroom(headroom, where, deferred);\n return out;\n}\n\n/**\n * Detached copy of a resolved config: windows, `states`, `modes` and tunings\n * included, with the same keys present. Hand-written rather than\n * `structuredClone` because `theme.getConfig()` uses it, and palettes call\n * that once per theme on every output; this is ~30× cheaper.\n */\nexport function copyResolvedConfig(\n config: GlazeConfigResolved,\n): GlazeConfigResolved {\n const copyWindow = (win: ToneWindow): ToneWindow =>\n win === false ? false : Array.isArray(win) ? [win[0], win[1]] : { ...win };\n const out: GlazeConfigResolved = {\n ...config,\n lightTone: copyWindow(config.lightTone),\n darkTone: copyWindow(config.darkTone),\n states: { ...config.states },\n modes: { ...config.modes },\n };\n if (config.shadowTuning) out.shadowTuning = { ...config.shadowTuning };\n if (config.glowTuning) out.glowTuning = { ...config.glowTuning };\n return out;\n}\n\n/**\n * Override window copy, unvalidated: an array is spread, an object is rebuilt\n * from `lo` / `hi` / `eps` read by property access (as `normalizeToneWindow`\n * reads it, so a getter-backed window still works), and anything else\n * (`false`, `null`, a bad scalar) passes through for `mergeConfig()` to judge.\n */\nfunction copyWindowField(win: unknown): unknown {\n if (Array.isArray(win)) return [...(win as unknown[])];\n if (typeof win === 'object' && win !== null) {\n const { lo, hi, eps } = win as Record<string, unknown>;\n return { lo, hi, eps };\n }\n return win;\n}\n\n/**\n * Override tuning copy, unvalidated: an object is spread (as `mergeConfig()`\n * copies it); anything else passes through.\n */\nfunction copyTuningField(tuning: unknown): unknown {\n return typeof tuning === 'object' && tuning !== null ? { ...tuning } : tuning;\n}\n\nconst keepField = (value: unknown): unknown => value;\n\n/**\n * How `copyConfigOverride` copies each field. A record over every\n * `GlazeConfigOverride` key, so a field added to the type doesn't compile\n * until it's listed here.\n */\nconst OVERRIDE_FIELD_COPY: Record<\n keyof GlazeConfigOverride,\n (value: unknown) => unknown\n> = {\n lightTone: copyWindowField,\n darkTone: copyWindowField,\n darkDesaturation: keepField,\n autoFlip: keepField,\n contrastLevel: keepField,\n pastel: keepField,\n inferRole: keepField,\n shadowTuning: copyTuningField,\n glowTuning: copyTuningField,\n};\n\n/**\n * Detached copy of a per-instance override, taken once where a theme or token\n * stores it so that resolve, `getConfig()`, `export()` and `extend()` all read\n * one object the caller can no longer reach. Every nested field\n * (`lightTone` / `darkTone` / `shadowTuning` / `glowTuning`) is copied one\n * level deep, which is all the nesting the type has. Nothing is validated\n * here — that still happens in `mergeConfig()` at resolve, as documented.\n *\n * Each known field is read by property access (`key in override`, then\n * `override[key]`) rather than spread, so a field `mergeConfig()` would see —\n * a class getter, an inherited field, a reactive proxy's trap — is copied too,\n * and a non-cloneable wrapper still works as an override. A non-object passes\n * through unchanged.\n */\nexport function copyConfigOverride(\n override: GlazeConfigOverride | undefined,\n): GlazeConfigOverride | undefined {\n // `null` is no override, as `undefined` is.\n if (override === null) return undefined;\n if (typeof override !== 'object') return override;\n const source = override as Record<string, unknown>;\n const out: Record<string, unknown> = {};\n for (const [key, copy] of Object.entries(OVERRIDE_FIELD_COPY)) {\n if (key in source) out[key] = copy(source[key]);\n }\n return out as GlazeConfigOverride;\n}\n\nlet globalConfig: GlazeConfigResolved = defaultConfig();\n\n/**\n * Monotonic counter incremented on every `configure()` / `resetConfig()`\n * call. Theme / palette caches read this to invalidate stale resolve\n * results when the config changes between exports.\n */\nlet configVersion = 0;\n\n/** Live reference to the current config. Mutated by `configure()` / `resetConfig()`. */\nexport function getConfig(): GlazeConfigResolved {\n return globalConfig;\n}\n\nexport function getConfigVersion(): number {\n return configVersion;\n}\n\n/**\n * Public-facing snapshot used by `glaze.getConfig()`. A deep copy — nested\n * `states`, `modes`, object windows, and tunings included — so mutating it\n * can't change the live config behind `configure()`'s back (which would skip\n * the version bump and leave every cache stale).\n */\nexport function snapshotConfig(): GlazeConfigResolved {\n return structuredClone(globalConfig);\n}\n\n/**\n * Merge a `GlazeConfig` into the global config. Fields are validated before\n * anything changes, so a call that throws leaves the config (and its version)\n * untouched — and sends no warning: a headroom clamp found on the way is sent\n * only once every field has passed, so the corrected retry still reports it.\n * A tone window is kept only when it's `undefined`, as in `mergeConfig()`: a\n * `null` (say, from a JSON config) throws the same error an instance override\n * with it does.\n */\nexport function configure(config: GlazeConfig): void {\n const deferred: DeferredWarnings = [];\n const next: GlazeConfigResolved = {\n lightTone: normalizeToneWindowInput(\n config.lightTone !== undefined\n ? config.lightTone\n : globalConfig.lightTone,\n 'lightTone',\n ),\n darkTone: normalizeToneWindowInput(\n config.darkTone !== undefined ? config.darkTone : globalConfig.darkTone,\n 'darkTone',\n ),\n darkDesaturation: normalizeDarkDesaturation(\n keepIfUndefined(config.darkDesaturation, globalConfig.darkDesaturation),\n ),\n states: {\n dark: config.states?.dark ?? globalConfig.states.dark,\n highContrast:\n config.states?.highContrast ?? globalConfig.states.highContrast,\n hdr: config.states?.hdr ?? globalConfig.states.hdr,\n },\n modes: {\n dark: config.modes?.dark ?? globalConfig.modes.dark,\n highContrast:\n config.modes?.highContrast ?? globalConfig.modes.highContrast,\n hdr: config.modes?.hdr ?? globalConfig.modes.hdr,\n },\n shadowTuning: normalizeLightingTuning(\n 'shadow',\n config.shadowTuning ?? globalConfig.shadowTuning,\n 'shadowTuning',\n ),\n glowTuning: normalizeLightingTuning(\n 'glow',\n config.glowTuning ?? globalConfig.glowTuning,\n 'glowTuning',\n deferred,\n ),\n autoFlip: config.autoFlip ?? globalConfig.autoFlip,\n // Instance-only; never configurable globally.\n pastel: false,\n inferRole: config.inferRole ?? globalConfig.inferRole,\n contrastLevel: normalizeContrastLevel(\n keepIfUndefined(config.contrastLevel, globalConfig.contrastLevel),\n ),\n };\n flushWarnings(deferred);\n configVersion++;\n globalConfig = next;\n}\n\nexport function resetConfig(): void {\n configVersion++;\n globalConfig = defaultConfig();\n}\n\n/**\n * Merge a per-instance config override over a base resolved config.\n * Only fields present in `override` are replaced; others fall through\n * from `base`. `false` for tone windows passes through as-is\n * (treated as the full range by `activeWindow()` in okhst.ts).\n *\n * This is where an instance's override is validated (at resolve), with the\n * same rules `configure()` applies to the global. The result is always a fresh\n * object that shares nothing with `base` or `override`, so an instance's\n * cached config can't alias the live global.\n *\n * `pastel` is instance-only: `override.pastel ?? false`, never inherited\n * from the global base. As in `configure()`, a headroom clamp warning is sent\n * only once every field has passed.\n */\nexport function mergeConfig(\n base: GlazeConfigResolved,\n override: GlazeConfigOverride = {},\n): GlazeConfigResolved {\n const deferred: DeferredWarnings = [];\n const merged: GlazeConfigResolved = {\n lightTone: normalizeToneWindowInput(\n override.lightTone !== undefined ? override.lightTone : base.lightTone,\n 'lightTone',\n ),\n darkTone: normalizeToneWindowInput(\n override.darkTone !== undefined ? override.darkTone : base.darkTone,\n 'darkTone',\n ),\n darkDesaturation: normalizeDarkDesaturation(\n keepIfUndefined(override.darkDesaturation, base.darkDesaturation),\n ),\n states: { ...base.states },\n modes: { ...base.modes },\n shadowTuning: normalizeLightingTuning(\n 'shadow',\n override.shadowTuning ?? base.shadowTuning,\n 'shadowTuning',\n ),\n glowTuning: normalizeLightingTuning(\n 'glow',\n override.glowTuning ?? base.glowTuning,\n 'glowTuning',\n deferred,\n ),\n autoFlip: override.autoFlip ?? base.autoFlip,\n pastel: override.pastel ?? false,\n inferRole: override.inferRole ?? base.inferRole,\n contrastLevel: normalizeContrastLevel(\n keepIfUndefined(override.contrastLevel, base.contrastLevel),\n ),\n };\n flushWarnings(deferred);\n return merged;\n}\n\n/**\n * Freeze `getConfig() ∪ instanceLocal ∪ exportArg` as a plain, resolve-relevant\n * override for authoring export, so restored snapshots pin these fields. Later\n * wins; nested objects (`shadowTuning` / `glowTuning`) replace wholesale.\n * `exportArg` is read through `copyConfigOverride`, like a stored override, so\n * its getters count too. `mergeConfig` already validates and copies every\n * field; the final `structuredClone` keeps the snapshot detached even if that\n * ever changes.\n */\nexport function freezeConfigForExport(\n instanceLocal?: GlazeConfigOverride,\n exportArg?: GlazeConfigOverride,\n): GlazeConfigOverride {\n const effective = mergeConfig(getConfig(), {\n ...instanceLocal,\n ...copyConfigOverride(exportArg),\n });\n const out: GlazeConfigOverride = {\n lightTone: effective.lightTone,\n darkTone: effective.darkTone,\n darkDesaturation: effective.darkDesaturation,\n autoFlip: effective.autoFlip,\n pastel: effective.pastel,\n inferRole: effective.inferRole,\n };\n if (effective.shadowTuning !== undefined) {\n out.shadowTuning = effective.shadowTuning;\n }\n if (effective.glowTuning !== undefined) {\n out.glowTuning = effective.glowTuning;\n }\n // `contrastLevel` is deliberately NOT taken from the effective merge. A\n // global level is a live user preference (an accessibility slider), not\n // authored theme data — freezing it would pin a transient slider position\n // into the snapshot and make restored themes ignore the slider forever.\n // Only an instance-local or explicitly-passed level is authored intent.\n // Same reasoning excludes `modes` and `states` from the freeze.\n const authoredLevel =\n exportArg?.contrastLevel ?? instanceLocal?.contrastLevel;\n if (authoredLevel !== undefined) {\n out.contrastLevel = normalizeContrastLevel(authoredLevel);\n }\n return structuredClone(out);\n}\n","/**\n * Glaze type definitions.\n */\n\nimport type { ApcaPreset, ContrastPreset } from './contrast-solver';\n\n// ============================================================================\n// Value types\n// ============================================================================\n\n/** A value or [normal, high-contrast] pair. */\nexport type HCPair<T> = T | [T, T];\n\n/** Bare WCAG contrast target: a ratio number or a named preset. */\nexport type MinContrast = number | ContrastPreset;\n\n/**\n * A contrast floor with a pluggable metric.\n *\n * - `number` / `ContrastPreset`: a WCAG ratio (bare form).\n * - `{ wcag }`: WCAG ratio or preset, optionally an HC pair.\n * - `{ apca }`: APCA Lc target (absolute value or preset), optionally an HC pair.\n *\n * The `[normal, highContrast]` pair may live at the outer level\n * (`[4.5, 7]`, `[{ wcag: 4.5 }, { wcag: 7 }]`) or inside the metric\n * (`{ wcag: [4.5, 7] }`, `{ apca: [45, 60] }`, `{ apca: ['content', 'body'] }`).\n */\nexport type ContrastSpec =\n | number\n | ContrastPreset\n | { wcag: HCPair<number | ContrastPreset> }\n | { apca: HCPair<number | ApcaPreset> };\n\n// ============================================================================\n// Color role\n// ============================================================================\n\n/**\n * The semantic role a color plays against its base, used to fix APCA contrast\n * polarity (which side is the foreground vs the background). WCAG is\n * symmetric, so role never changes WCAG results.\n */\nexport type Role = 'text' | 'surface' | 'border';\n\n/**\n * Any string accepted as a `role`. Canonical values plus aliases normalized by\n * `normalizeRole` (see `roles.ts`): `surface` (bg/background/fill/canvas/\n * paper/layer), `text` (fg/foreground/content/ink/label/stroke), `border`\n * (divider/outline/separator/hairline/rule).\n */\nexport type RoleInput =\n | Role\n | 'bg'\n | 'background'\n | 'fill'\n | 'canvas'\n | 'paper'\n | 'layer'\n | 'fg'\n | 'foreground'\n | 'content'\n | 'ink'\n | 'label'\n | 'stroke'\n | 'divider'\n | 'outline'\n | 'separator'\n | 'hairline'\n | 'rule';\n\nexport type AdaptationMode = 'auto' | 'fixed' | 'static';\n\n/** A signed relative offset string, e.g. '+20' or '-15.5'. */\nexport type RelativeValue = `+${number}` | `-${number}`;\n\n/**\n * Force a color to a tone extreme:\n * - `'max'`: the highest tone in the active scheme range/window.\n * - `'min'`: the lowest tone.\n *\n * Under `mode: 'auto'` the extreme inverts in the dark scheme (so `'max'`\n * tracks the inversion and becomes the darkest tone). No `base` required.\n */\nexport type ExtremeValue = 'max' | 'min';\n\n/**\n * A tone value as authored on a color.\n * - Number: absolute tone (0–100).\n * - `'+N'` / `'-N'`: relative to the base's tone (requires `base`).\n * - `'max'` / `'min'`: forced to the scheme's tone extreme (no base needed).\n */\nexport type ToneValue = number | RelativeValue | ExtremeValue;\n\n/** Color format for output. */\nexport type GlazeColorFormat = 'okhsl' | 'okhst' | 'rgb' | 'hsl' | 'oklch';\n\n/**\n * Output format for an HDR glow value (`glaze.formatHdr()`), its brightest\n * channel past 1 (SDR white):\n * - `'srgb'` (default, and what every exporter writes) — extended\n * `color(srgb R G B)`: the sRGB transfer function continued past 1, the\n * channels a WebGPU `'srgb'` canvas and the platform extended-sRGB color\n * spaces take as they are.\n * - `'srgb-linear'` — `color(srgb-linear R G B)`: the same color in linear\n * light, for consumers that take linear channels.\n *\n * No other form: OKLCH lightness clamps at parse time, `rgb()` / `hsl()`\n * cannot go past white, and the `rec2100-*` spaces would tie the value to an\n * absolute reference white it doesn't need.\n */\nexport type GlazeHdrFormat = 'srgb' | 'srgb-linear';\n\n/**\n * Controls which scheme variants are generated in the export.\n * Light is always included (it's the default).\n */\nexport interface GlazeOutputModes {\n /** Include dark scheme variants. Default: true. */\n dark?: boolean;\n /**\n * Include high-contrast variants (both light-HC and dark-HC). Default: false.\n *\n * Independent of `contrastLevel` — the level positions the normal variants\n * while these stay the true high-contrast resolution, so the two compose. The\n * exception is a global level of 100, where the normal variants already *are*\n * the high-contrast ones: the tier would duplicate them and is dropped.\n * @see GlazeConfig.contrastLevel\n */\n highContrast?: boolean;\n /**\n * Include the HDR tier of glows past SDR white (`variant.hdr`, set by\n * `GlowTuning.headroom`). Default: false — every exporter's output stays\n * byte-identical to SDR even when a headroom is set.\n *\n * When on, each exporter adds the HDR values next to the SDR ones it\n * already emits (only for the scheme variants the other modes include),\n * always written as extended `color(srgb R G B)`: Tasty `hdr` state keys,\n * `json()` `lightHdr` / `darkHdr` / … keys, `tokens()` `lightHdr` / … maps,\n * Tailwind blocks under `hdrSelector`, DTCG `$extensions`. `css()` reads\n * its own `hdr` option, which falls back to this.\n *\n * The data tiers (DTCG, `json()`, `tokens()`) are what native apps and\n * WebGPU canvases read. The CSS-family tiers (Tasty, `css()`, Tailwind) are\n * experimental: no browser paints a CSS color past SDR white yet. Prefer\n * turning this on per call (`theme.dtcg({ modes: { hdr: true } })`) over\n * globally.\n */\n hdr?: boolean;\n}\n\n// ============================================================================\n// Color definitions\n// ============================================================================\n\n/** Hex color string for DX hints. Runtime validation in `parseHex()`. */\nexport type HexColor = `#${string}`;\n\n/** Direct OKHSL color input. */\nexport interface OkhslColor {\n h: number;\n s: number;\n l: number;\n}\n\n/**\n * Direct OKHST color input — OKHSL with the lightness axis replaced by the\n * contrast-uniform tone axis. `h`: 0–360, `s`: 0–1, `t`: 0–1 (tone).\n */\nexport interface OkhstColor {\n h: number;\n s: number;\n t: number;\n}\n\n/** sRGB components in 0–255 (value-shorthand object form). */\nexport interface RgbColor {\n r: number;\n g: number;\n b: number;\n}\n\n/** OKLCh components matching CSS `oklch(L C H)` (L/C: 0–1, H: degrees). */\nexport interface OklchColor {\n l: number;\n c: number;\n h: number;\n}\n\nexport interface RegularColorDef {\n /**\n * Seed this color from a literal color instead of from the theme.\n *\n * Accepts the same values as `glaze.color()` — hex, `rgb()`, `hsl()`,\n * `okhsl()`, `okhst()`, `oklch()`, or a value object. It supplies three\n * things at once: `hue`, `tone`, and — unlike every other color in a theme —\n * an **absolute saturation** rather than a factor of the seed. That last\n * part is the point: a color can now be more saturated than its theme, so\n * honoring a brand color no longer means re-seeding the whole theme to reach\n * it.\n *\n * The **light, normal-contrast** variant reproduces the value exactly\n * (a local `lightTone: false`, matching the value-shorthand form of\n * `glaze.color()`). Dark and high-contrast variants adapt as usual — they\n * are where readability outranks fidelity, and a color pinned across every\n * scheme would defeat both. A `contrast` floor still applies everywhere and\n * still only moves the color when the authored value misses it.\n *\n * Sibling fields override what the value supplied, so\n * `{ from: '#2F5BFF', hue: 300 }` keeps its saturation and tone but rotates\n * the hue.\n */\n from?: GlazeColorValue;\n /**\n * Tone value (0–100, contrast-uniform — see `docs/okhst.mdx`).\n * - Number: absolute tone.\n * - String ('+N' / '-N'): relative to base color's tone (requires `base`).\n * - `'max'` / `'min'`: force to the scheme's tone extreme (no base needed).\n *\n * Defaults to the tone of `from` when that is set.\n */\n tone?: HCPair<ToneValue>;\n /**\n * Saturation factor applied to the seed saturation (0–1, default: 1).\n *\n * With `from`, an explicit value here is still a factor of the seed and\n * overrides the absolute saturation the color carried.\n */\n saturation?: number;\n /**\n * Hue override for this color.\n * - Number: absolute hue (0–360).\n * - String ('+N' / '-N'): relative to the theme seed hue.\n */\n hue?: number | RelativeValue;\n /**\n * Dark-scheme hue override. Applies to the `dark` and `darkContrast`\n * variants; falls back to `hue` when omitted.\n * - Number: absolute hue (0–360).\n * - String ('+N' / '-N'): relative to the theme's **dark** seed hue\n * (`GlazeTheme.darkHue`, itself defaulting to the light seed hue).\n *\n * Ignored under `mode: 'static'`, which pins one value across all schemes.\n */\n darkHue?: number | RelativeValue;\n /**\n * Dark-scheme saturation factor (0–1) applied to the dark seed\n * saturation. Applies to the `dark` and `darkContrast` variants; falls\n * back to `saturation` when omitted.\n *\n * When set, the global `darkDesaturation` reduction is **not** applied on\n * top — the resulting saturation is taken literally. Ignored under\n * `mode: 'static'`.\n */\n darkSaturation?: number;\n\n /** Name of another color in the same theme (dependent color). */\n base?: string;\n /**\n * Contrast floor against the base color. A bare number/preset is WCAG;\n * use `{ wcag }` / `{ apca }` to pick the metric. Accepts an HC pair.\n */\n contrast?: HCPair<ContrastSpec>;\n\n /** Adaptation mode. Default: 'auto'. */\n mode?: AdaptationMode;\n\n /**\n * Whether to flip out-of-bounds results to the opposite side instead of\n * clamping to the extreme. Affects both:\n * - relative `tone`: when `base ± delta` exceeds `[0, 100]`, mirror the\n * delta to the other side of the base. If the mirrored target is also\n * out of range, keep the original delta and clamp on the authored side.\n * - `contrast`: when the requested direction can't meet the floor, try the\n * opposite side (same as the global `autoFlip`).\n *\n * Defaults to the global `autoFlip` config (default `true`). Set `false`\n * to clamp instead.\n */\n autoFlip?: boolean;\n\n /**\n * Fixed opacity (0–1).\n * Output includes alpha in the CSS value.\n * Does not affect contrast resolution — a semi-transparent color\n * has no fixed perceived tone, so `contrast` and `opacity`\n * should not be combined (a console.warn is emitted).\n */\n opacity?: number;\n\n /**\n * Per-color override for the hue-independent \"safe\" chroma limit used in\n * OKHSL↔sRGB conversions (luminance, contrast solving, output formatting).\n * Falls through to the per-theme / per-token `pastel` override when omitted.\n * @see GlazeConfigOverride.pastel\n */\n pastel?: boolean;\n\n /**\n * Semantic role against `base`: how this color is used. Fixes APCA contrast\n * polarity (the argument order in `apcaContrast`). WCAG is symmetric so it\n * never affects WCAG results.\n *\n * Resolution: explicit `role` wins; else inferred from the color name when\n * `inferRole` is enabled (default); else the opposite of the base's role;\n * else defaults to `'text'` (foreground).\n */\n role?: RoleInput;\n\n /**\n * Whether this color is inherited by child themes created via `extend()`.\n * Default: true. Set to false to make this color local to the current theme.\n */\n inherit?: boolean;\n}\n\n/**\n * Tuning shared by `shadow` and `glow`. Global defaults come from\n * `shadowTuning` / `glowTuning`; a per-color `tuning` merges over them field\n * by field.\n */\nexport interface LightingTuning {\n /**\n * β — how strongly the object (`fg`) scales the step. The step is\n * `intensity × k` with `k = max(0, 1 + β · d · (t_bg − t_fg) / 100)`,\n * `d = +1` for a shadow and `−1` for a glow: a darker object deepens its\n * shadow, a lighter one strengthens its glow. An object at the surface's\n * own tone (or no `fg`) gives exactly `intensity`. `0` ignores the object.\n * Default: 0.5.\n */\n objectInfluence?: number;\n /**\n * Pigment saturation (0–1) in the surface's hue. Default: 0 (neutral black /\n * white). Shows only with `reach` below 1 — pure black and white have no hue.\n * A neutral surface has no hue either: there the tint takes the object's\n * hue with `hueBleed` above 0, and the pigment stays neutral otherwise.\n */\n tint?: number;\n /**\n * Where the pigment sits (0–1): the fraction of the way from the surface's\n * tone to black (shadow) / white (glow). Default: 1 (pure black / white),\n * the most reach. Lower values let a `tint` show at the cost of reach.\n */\n reach?: number;\n /**\n * Pull (0–1) of the pigment hue from the surface's hue toward the object's\n * (`fg`) hue. Default: 0. Needs `fg`, a `tint`, and `reach` below 1 to show.\n */\n hueBleed?: number;\n}\n\n/**\n * Tuning for `shadow` colors: the shared {@link LightingTuning}. It has no\n * `headroom` — a shadow darkens toward black, and nothing goes below black —\n * so a `headroom` set on a shadow's tuning throws.\n */\nexport type ShadowTuning = LightingTuning;\n\n/** Tuning for `glow` colors: the shared {@link LightingTuning} plus HDR `headroom`. */\nexport interface GlowTuning extends LightingTuning {\n /**\n * Stops above SDR white a glow may use when its step crosses white. Default:\n * 0 (SDR only). Counted in stops — doublings of SDR white's luminance — not\n * as a ratio: `1` allows up to 2× white, `2` up to 4×. Must be a finite\n * number ≥ 0; values above 2 clamp to 2 with a one-time warning.\n *\n * Only a glow whose target tone (surface tone + `intensity × k`) passes 100\n * gets an HDR value: the variant's `hdr`, an opaque exposure of what SDR\n * paints at its brightest — the pigment at full opacity, or a white surface\n * no pigment can lift — plus a gain in stops. A pigment that cannot lift a\n * non-white surface at all (`reach: 0` on a gray surface, say) paints\n * nothing in SDR, so it gets no HDR value either and keeps the SDR \"cannot\n * reach\" warning. On a chromatic surface a `reach: 0` gray can measure\n * slightly brighter than the surface and pins at full opacity instead.\n * Nothing about the SDR variant changes. The gain lands the exact step when\n * the headroom allows it; the brightest linear channel caps at `2^headroom`.\n * High-contrast schemes use the same headroom.\n *\n * The HDR value lands the whole step, not just the part past white. A\n * full-reach glow (the default `reach: 1`) is pinned at white, so its HDR\n * value starts at white (`exposure` → 0) as the target passes 100. A glow\n * with `reach` below 1 is pinned at its pigment, below white: just under 100\n * it stays short there (and warns), and just past 100 its HDR value jumps to\n * the exact step.\n */\n headroom?: number;\n}\n\n/**\n * A translucent dark overlay that lands the surface (`bg`) exactly\n * `intensity` tones darker in every scheme — a shade for state layers and\n * scrims, or, with `fg`, an object-aware drop shadow.\n */\nexport interface ShadowColorDef {\n type: 'shadow';\n /**\n * The surface the shadow falls on. Must reference a color that is not a\n * shadow or glow.\n */\n bg: string;\n /**\n * The object casting the shadow (e.g. the card). A darker object casts a\n * deeper shadow, a lighter one a softer shadow — see\n * `LightingTuning.objectInfluence`. Omit for an exact shade of `intensity`\n * tones. Must reference a color that is not a shadow or glow.\n */\n fg?: string;\n /**\n * Tone step, 0–100: how many tones darker than `bg` the composite lands.\n * Supports [normal, highContrast] pair.\n */\n intensity: HCPair<number>;\n /** Override default tuning. Merged field-by-field with global `shadowTuning`. */\n tuning?: ShadowTuning;\n\n /**\n * Per-color override for the hue-independent \"safe\" chroma limit used in\n * OKHSL↔sRGB conversions (luminance, contrast solving, output formatting).\n * Falls through to the per-theme / per-token `pastel` override when omitted.\n * @see GlazeConfigOverride.pastel\n */\n pastel?: boolean;\n\n /**\n * Whether this color is inherited by child themes created via `extend()`.\n * Default: true. Set to false to make this color local to the current theme.\n */\n inherit?: boolean;\n}\n\n/**\n * The mirror of {@link ShadowColorDef}: a translucent light overlay that lands\n * the surface (`bg`) exactly `intensity` tones lighter in every scheme — for\n * dark-mode elevation, edge highlights, and lightening state layers.\n */\nexport interface GlowColorDef {\n type: 'glow';\n /**\n * The surface the glow falls on. Must reference a color that is not a\n * shadow or glow.\n */\n bg: string;\n /**\n * The object emitting the glow. A lighter object glows stronger, a darker\n * one weaker — see `LightingTuning.objectInfluence`. Omit for an exact tint\n * of `intensity` tones. Must reference a color that is not a shadow or glow.\n */\n fg?: string;\n /**\n * Tone step, 0–100: how many tones lighter than `bg` the composite lands.\n * Supports [normal, highContrast] pair.\n */\n intensity: HCPair<number>;\n /** Override default tuning. Merged field-by-field with global `glowTuning`. */\n tuning?: GlowTuning;\n\n /**\n * Per-color override for the hue-independent \"safe\" chroma limit used in\n * OKHSL↔sRGB conversions (luminance, contrast solving, output formatting).\n * Falls through to the per-theme / per-token `pastel` override when omitted.\n * @see GlazeConfigOverride.pastel\n */\n pastel?: boolean;\n\n /**\n * Whether this color is inherited by child themes created via `extend()`.\n * Default: true. Set to false to make this color local to the current theme.\n */\n inherit?: boolean;\n}\n\nexport interface MixColorDef {\n type: 'mix';\n /** Background/base color name — the \"from\" color. */\n base: string;\n /** Target color name — the \"to\" color to mix toward. */\n target: string;\n /**\n * Mix ratio 0–100 (0 = pure base, 100 = pure target).\n * In 'transparent' blend mode, this controls the opacity of the target.\n * Supports [normal, highContrast] pair.\n */\n value: HCPair<number>;\n /**\n * Blending mode. Default: 'opaque'.\n * - 'opaque': produces a solid color by interpolating base and target.\n * - 'transparent': produces the target color with alpha = value/100.\n */\n blend?: 'opaque' | 'transparent';\n /**\n * Interpolation color space for opaque blending. Default: 'okhsl'.\n * - 'okhsl': perceptually uniform, consistent with Glaze's internal model.\n * - 'srgb': linear-light sRGB interpolation (like CSS\n * `color-mix(in srgb-linear, …)`).\n *\n * Ignored for 'transparent' blend: the browser composites that one, and\n * its contrast solve models the browser (`source-over` on gamma-encoded\n * sRGB).\n */\n space?: 'okhsl' | 'srgb';\n /**\n * Minimum contrast between the base and the resulting color.\n * In 'opaque' mode, adjusts the mix ratio to meet contrast.\n * In 'transparent' mode, adjusts opacity to meet contrast against the composite.\n * A bare number/preset is WCAG; use `{ wcag }` / `{ apca }` to pick the\n * metric. Supports [normal, highContrast] pair.\n */\n contrast?: HCPair<ContrastSpec>;\n\n /**\n * Per-color override for the hue-independent \"safe\" chroma limit used in\n * OKHSL↔sRGB conversions (luminance, contrast solving, output formatting).\n * Falls through to the per-theme / per-token `pastel` override when omitted.\n * @see GlazeConfigOverride.pastel\n */\n pastel?: boolean;\n\n /**\n * Semantic role of the mixed result against `base`. Same semantics as\n * `RegularColorDef.role` (fixes APCA polarity). Resolution and defaults\n * are identical.\n */\n role?: RoleInput;\n\n /**\n * Whether this color is inherited by child themes created via `extend()`.\n * Default: true. Set to false to make this color local to the current theme.\n */\n inherit?: boolean;\n}\n\nexport type ColorDef =\n | RegularColorDef\n | ShadowColorDef\n | GlowColorDef\n | MixColorDef;\n\nexport type ColorMap = Record<string, ColorDef>;\n\n// ============================================================================\n// Resolved internal types\n// ============================================================================\n\n/**\n * Resolved color for a single scheme variant.\n *\n * Stored in OKHST: `h` / `s` are OKHSL hue/saturation, `t` is the canonical\n * contrast-uniform tone (0–1, reference eps). Convert to OKHSL lightness via\n * `variantToOkhsl` at the rendering / luminance edges.\n */\nexport interface ResolvedColorVariant {\n /** OKHSL hue (0–360). */\n h: number;\n /** OKHSL saturation (0–1). */\n s: number;\n /** Canonical tone (0–1, reference eps). */\n t: number;\n /** Opacity (0–1). Default: 1. */\n alpha: number;\n /**\n * Effective `pastel` flag used while resolving this variant (author def or\n * config fallback). Carried on the variant so output formatting matches the\n * gamut mapping applied during resolution.\n */\n pastel?: boolean;\n /**\n * HDR tier of a glow whose step crosses SDR white, present only when the\n * glow's `headroom` is above 0, its target tone passes 100, and SDR is\n * pinned at its brightest — the pigment at full opacity, or a white surface\n * (see `GlowTuning.headroom`). Absent everywhere else — shadows, mixes,\n * regular colors, a glow whose pigment cannot lift a non-white surface, and\n * every glow at the default headroom of 0.\n */\n hdr?: ResolvedHdr;\n}\n\n/**\n * The HDR value of a glow past SDR white: an opaque base plus a gain. The base\n * is what SDR paints at its brightest — the glow's pigment at full opacity, or\n * the white surface it cannot lift — and the HDR color is that base's linear\n * sRGB times `2^exposure`. Format it with `glaze.formatHdr()`, or read its\n * channels with `hdrToSrgb()` / `hdrToLinearSrgb()`.\n *\n * Stored in OKHST like the variant. `s` is always standard (non-pastel)\n * OKHSL saturation, whatever the variant's `pastel`, since the base is an\n * arbitrary in-gamut composite.\n */\nexport interface ResolvedHdr {\n /** Base OKHSL hue (0–360). */\n h: number;\n /** Base OKHSL saturation (0–1, non-pastel). */\n s: number;\n /** Base canonical tone (0–1, reference eps). */\n t: number;\n /** Gain over the base in stops (`log2` of the linear factor), above 0. */\n exposure: number;\n}\n\n/** Fully resolved color across all scheme variants. */\nexport interface ResolvedColor {\n name: string;\n light: ResolvedColorVariant;\n dark: ResolvedColorVariant;\n lightContrast: ResolvedColorVariant;\n darkContrast: ResolvedColorVariant;\n /** Adaptation mode of a regular color; `undefined` for shadow / glow / mix. */\n mode?: AdaptationMode;\n}\n\n// ============================================================================\n// Configuration\n// ============================================================================\n\n/**\n * A scheme tone window.\n * - `[lo, hi]`: OKHSL-lightness endpoints (0–100) the authored tone is\n * remapped into, using the reference eps `0.05`. The common form.\n * - `{ lo, hi, eps }`: same, with an explicit render curvature `eps`\n * (advanced — most palettes never need this).\n * - `false`: disable clamping (full range `[0, 100]` at the reference eps).\n * This removes the *boundaries*, not the tone curve.\n */\nexport type ToneWindow =\n | false\n | [number, number]\n | { lo: number; hi: number; eps: number };\n\nexport interface GlazeConfig {\n /** Light scheme tone window — `[lo, hi]` (default `[10, 100]`), `{ lo, hi, eps }` for advanced eps tuning, or `false` to disable clamping. */\n lightTone?: ToneWindow;\n /** Dark scheme tone window — `[lo, hi]` (default `[15, 95]`), `{ lo, hi, eps }`, or `false` to disable clamping. */\n darkTone?: ToneWindow;\n /** Saturation reduction factor for dark scheme (0–1). Default: 0.1. */\n darkDesaturation?: number;\n /**\n * State alias names for Tasty token export. Default to media-query states\n * (`'@media(prefers-color-scheme: dark)'` / `'@media(prefers-contrast: more)'`\n * / `'@media(dynamic-range: high)'`) so tokens react to the OS preference\n * and the display without registering custom states. `hdr` keys an HDR\n * glow value and is used only with `modes.hdr` (experimental, see\n * `GlazeOutputModes.hdr`).\n */\n states?: {\n dark?: string;\n highContrast?: string;\n hdr?: string;\n };\n /**\n * Which scheme variants to include in exports. Defaults: `dark: true`,\n * `highContrast: false`, `hdr: false`.\n */\n modes?: GlazeOutputModes;\n /**\n * Default tuning for all shadow colors. Per-color tuning merges field-by-field.\n * A `headroom` here throws: it is a glow-only field.\n */\n shadowTuning?: ShadowTuning;\n /**\n * Default tuning for all glow colors, including HDR `headroom`. Per-color\n * tuning merges field-by-field.\n */\n glowTuning?: GlowTuning;\n /**\n * Manual contrast level — a 0–100 slider from normal contrast (`0`) to high\n * contrast (`100`), or `'auto'` (the default) to take the authored normal\n * entries as-is.\n *\n * With a number, Glaze resolves the `light` / `dark` variants *at* that level.\n * That is all it does: `lightContrast` / `darkContrast` stay the true\n * high-contrast resolution at every level, and `modes.highContrast` alone\n * decides whether they are emitted. Level `0` therefore reproduces `'auto'`\n * bit for bit. At `100` the normal variants *are* the high-contrast ones, so a\n * separate tier would duplicate them and a global level of 100 drops it.\n *\n * The level interpolates all three things that make high contrast differ:\n * authored `[normal, highContrast]` pairs, the tone-window widening, and\n * the `AA → AAA` / APCA `+15 Lc` escalation. Contrast floors are re-solved\n * at the interpolated target, so every level is a solution rather than an\n * approximation, and a color keeps to one side of its base as the level moves.\n *\n * Pass `'auto'` to leave manual mode; `configure()` never clears a field by\n * omission. See `docs/reference/contrast.md` for the ramp's edge cases (un-interpolable\n * pairs, side changes) and the export-freeze rule.\n *\n * @default 'auto'\n */\n contrastLevel?: number | 'auto';\n /**\n * Automatically flip tone direction when contrast can't be met.\n *\n * When enabled (default `true`), the solver searches the requested\n * tone direction first. If that direction can't reach the target,\n * it tries the opposite direction and uses it when it passes. If neither\n * side passes, the tone is pinned to the requested-direction\n * extreme and a warning is emitted.\n *\n * Set to `false` for strict \"no flip\" behavior. The opposite\n * direction is never considered: if the requested direction can't\n * meet the target, the tone is pinned to its extreme (never\n * falls back to the originally requested tone).\n */\n autoFlip?: boolean;\n /**\n * If true (default), infer a color's `role` from its name when no explicit\n * `role` is set. Set to `false` to opt out of name-based inference (the\n * base-opposite and default-foreground fallbacks still apply).\n * @default true\n */\n inferRole?: boolean;\n}\n\nexport interface GlazeConfigResolved {\n lightTone: ToneWindow;\n darkTone: ToneWindow;\n darkDesaturation: number;\n states: {\n dark: string;\n highContrast: string;\n hdr: string;\n };\n modes: Required<GlazeOutputModes>;\n shadowTuning?: ShadowTuning;\n glowTuning?: GlowTuning;\n autoFlip: boolean;\n /**\n * Manual contrast level (0–100) for the normal variants, or `'auto'` to take\n * the authored normal entries as-is.\n * @see GlazeConfig.contrastLevel\n */\n contrastLevel: number | 'auto';\n /**\n * Instance-level pastel default (`def.pastel ?? config.pastel`).\n * Not set via `glaze.configure()` — only via per-theme / per-token\n * `GlazeConfigOverride` (default `false`).\n */\n pastel: boolean;\n inferRole: boolean;\n}\n\n/**\n * Per-instance config override for `glaze.color()` and `glaze()` themes.\n * Fields that are set take priority over the live global config. Fields\n * that are omitted fall through to the live global at resolve time\n * (`pastel` is instance-only and defaults to `false` when omitted).\n *\n * `false` for a tone window disables clamping (full range at reference eps).\n */\nexport interface GlazeConfigOverride {\n /** Light scheme tone window, or `false` to disable clamping. */\n lightTone?: ToneWindow;\n /** Dark scheme tone window, or `false` to disable clamping. */\n darkTone?: ToneWindow;\n /** Saturation reduction factor for dark scheme (0–1). */\n darkDesaturation?: number;\n /** Whether to auto-flip tone when contrast can't be met. */\n autoFlip?: boolean;\n /**\n * Manual contrast level (0–100) for this instance, or `'auto'` to opt out of a\n * global level and take the authored normal entries as-is. Either way the\n * instance keeps its high-contrast tier; a per-instance level never changes\n * which modes are emitted.\n *\n * Only an instance-authored level is frozen into `.export()` snapshots — a\n * level inherited from the global config is treated as a live preference and\n * re-read at restore time.\n *\n * @see GlazeConfig.contrastLevel\n */\n contrastLevel?: number | 'auto';\n /**\n * Instance-level pastel default for colors that omit per-color `pastel`.\n * Not available on `glaze.configure()` — set here or per-color.\n * @default false\n */\n pastel?: boolean;\n /**\n * If true, infer a color's `role` from its name when no explicit `role` is\n * set. Falls through to the live global at resolve time when omitted.\n */\n inferRole?: boolean;\n /**\n * Shadow tuning defaults. Only meaningful for themes; harmless on\n * standalone color tokens.\n */\n shadowTuning?: ShadowTuning;\n /**\n * Glow tuning defaults. Only meaningful for themes; harmless on\n * standalone color tokens.\n */\n glowTuning?: GlowTuning;\n}\n\n// ============================================================================\n// Serialization\n// ============================================================================\n\n/**\n * Current authoring-export schema version. Bump when the export shape\n * changes in a non-compatible way. Written on every `.export()` snapshot.\n *\n * - `1` — Glaze 2.x.\n * - `2` — Glaze 3: `shadow` `intensity` / `fg` / `tuning` changed meaning and\n * `glow` was added. Version-1 theme snapshots that carry shadow defs or a\n * `shadowTuning` are rejected on restore.\n */\nexport const GLAZE_EXPORT_VERSION = 2 as const;\n\n/** Literal type of {@link GLAZE_EXPORT_VERSION}. */\nexport type GlazeExportVersion = typeof GLAZE_EXPORT_VERSION;\n\n/** Discriminator for authoring export snapshots. */\nexport type GlazeExportKind = 'theme' | 'color' | 'palette';\n\n/** Serialized theme configuration (no resolved values). */\nexport interface GlazeThemeExport {\n /** Snapshot kind. Always written by `theme.export()`; optional on legacy hand-written configs. */\n kind?: 'theme';\n /** Schema version. Always written by `theme.export()`; optional on legacy configs. */\n version?: number;\n hue: number;\n saturation: number;\n /** Dark-scheme seed hue (0–360). Omitted when the theme reuses `hue`. */\n darkHue?: number;\n /** Dark-scheme seed saturation (0–100). Omitted when the theme reuses `saturation`. */\n darkSaturation?: number;\n colors: ColorMap;\n /**\n * Effective config freeze from `.export()` —\n * `getConfig() ∪ instance local ∪ exportArg`. May be sparse on legacy\n * snapshots (omitted fields fall through to the live global at restore).\n */\n config?: GlazeConfigOverride;\n}\n\n// ============================================================================\n// Standalone shadow / glow\n// ============================================================================\n\n/** Input for the `glaze.shadow()` and `glaze.glow()` standalone factories. */\nexport interface GlazeLightingInput {\n /**\n * The surface — accepts any `GlazeColorValue` form: hex\n * (`#rgb` / `#rgba` / `#rrggbb` / `#rrggbbaa`), `rgb()` / `hsl()` /\n * `okhsl()` / `okhst()` / `oklch()` strings, or literal objects\n * (`{ r, g, b }`, `{ h, s, l }`, `{ h, s, t }`, `{ l, c, h }`). Alpha\n * components are dropped with a warning.\n */\n bg: GlazeColorValue;\n /** The object casting the shadow / emitting the glow. Same forms as `bg`. */\n fg?: GlazeColorValue;\n /** Tone step, 0–100. */\n intensity: number;\n tuning?: LightingTuning;\n}\n\n/** Input for `glaze.shadow()`. */\nexport type GlazeShadowInput = GlazeLightingInput;\n\n/** Input for `glaze.glow()`: the shared input, with glow tuning (`headroom`). */\nexport interface GlazeGlowInput extends GlazeLightingInput {\n tuning?: GlowTuning;\n}\n\n// ============================================================================\n// Standalone color token\n// ============================================================================\n\n/** Input for the structured `glaze.color()` overload. */\nexport interface GlazeColorInput {\n hue: number;\n saturation: number;\n tone: HCPair<number | ExtremeValue>;\n saturationFactor?: number;\n /**\n * Dark-scheme hue. Number is absolute (0–360); `'+N'`/`'-N'` is relative\n * to the dark seed hue, which defaults to `hue`. Falls back to `hue`.\n */\n darkHue?: number | RelativeValue;\n /** Dark-scheme seed saturation (0–100). Defaults to `saturation`. */\n darkSaturation?: number;\n /** Dark-scheme multiplier on the dark seed (0–1). Defaults to `saturationFactor`. */\n darkSaturationFactor?: number;\n mode?: AdaptationMode;\n /** Flip out-of-bounds results instead of clamping. Default: global `autoFlip`. */\n autoFlip?: boolean;\n /**\n * Fixed opacity (0–1). Output includes alpha in the CSS value.\n * Combining with `contrast` is not recommended (perceived tone\n * becomes unpredictable) — a `console.warn` is emitted in that case.\n */\n opacity?: number;\n /**\n * Optional dependency on another color. Same semantics as\n * `GlazeColorOverrides.base` — `contrast` and relative `tone`\n * anchor to the base per scheme.\n */\n base?: GlazeColorToken | GlazeColorValue;\n /**\n * Contrast floor. Without `base`, solved against the token's own input\n * color (`hue`, `saturation`, normal `tone`), held fixed in every scheme;\n * with `base`, against the base's resolved variant per scheme. A bare\n * number/preset is WCAG; use `{ wcag }` / `{ apca }` to pick the metric.\n */\n contrast?: HCPair<ContrastSpec>;\n /**\n * Optional human-readable name for the token. Used in error and\n * warning messages (otherwise an internal name like `\"value\"` is\n * used) and as `resolve().name`. A debug label only: it does not\n * affect output keys or the token's `role`.\n */\n name?: string;\n\n /**\n * Per-color override for the hue-independent \"safe\" chroma limit used in\n * OKHSL↔sRGB conversions (luminance, contrast solving, output formatting).\n * Falls through to the per-theme / per-token `pastel` override when omitted.\n * @see GlazeConfigOverride.pastel\n */\n pastel?: boolean;\n\n /**\n * Semantic role against the token's anchor (`base`, or its own input\n * color when `contrast` is set without one): how this token is used.\n * Fixes APCA contrast polarity; WCAG ignores it. Defaults to `'text'` —\n * the token is the foreground and the anchor the background, with or\n * without `base`. Unlike a theme color, a token never infers its role\n * from `name`, so `inferRole` has no effect on it.\n */\n role?: RoleInput;\n}\n\n/**\n * Any single-color input form accepted by the value-shorthand\n * overload of `glaze.color()`.\n *\n * Strings cover hex with a leading `#` (`#rgb` / `#rgba` / `#rrggbb` /\n * `#rrggbbaa`) and the five color functions Glaze itself emits: `rgb()`,\n * `hsl()`, `okhsl()`, `okhst()`, `oklch()`, plus the `rgba()` / `hsla()`\n * aliases. Function names are case-insensitive; components are numbers or\n * percentages, separated by spaces or commas. Their scales:\n * - `rgb()` — channels 0–255, or percentages (`100%` is 255).\n * - `hsl()` / `okhsl()` / `okhst()` — saturation, lightness and tone are\n * percentages or bare 0–1 fractions: `hsl(120 50% 50%)` or\n * `hsl(120 0.5 0.5)`. Unlike CSS, a bare `hsl(120 50 50)` does not mean\n * 50%; it is out of range and resolves to white without a warning.\n * - `oklch()` — L 0–1 or a percentage; C bare, or a percentage where\n * `100%` is 0.4.\n * - Hue is in degrees, bare or with `deg`. Other angle units (`turn`,\n * `rad`, `grad`) are misread as degrees rather than rejected.\n *\n * An alpha component (hex alpha, `/ A`, or any fourth component) is\n * dropped with a warning. Named colors, other color functions, and\n * relative color syntax throw.\n *\n * Literal object forms, told apart by their keys:\n * - `{ r, g, b }` — sRGB 0–255.\n * - `{ l, c, h }` — OKLCh (L/C: 0–1, H: degrees), same as `oklch()` strings.\n * - `{ h, s, t }` — OKHST (h: 0–360, s/t: 0–1). Tone in 0–1, so `t: 0.7` is\n * tone 70.\n * - `{ h, s, l }` — OKHSL (h: 0–360, s/l: 0–1).\n *\n * An object `s`, `l`, `t` or `c` above 1.5 throws, which catches 0–100\n * input; the OKHSL / OKHST errors point to the structured form. String\n * components have no such check.\n */\nexport type GlazeColorValue =\n | string\n | OkhslColor\n | OkhstColor\n | RgbColor\n | OklchColor;\n\n/** Color overrides for the `from` and value-shorthand inputs. */\nexport interface GlazeColorOverrides {\n /**\n * Override hue. Number is absolute (0–360); `'+N'`/`'-N'` is relative\n * to the extracted (or overridden) seed hue — same semantics as\n * `RegularColorDef.hue`.\n */\n hue?: number | RelativeValue;\n /** Override seed saturation (0–100). Default: extracted from value. */\n saturation?: number;\n /**\n * Dark-scheme hue. Number is absolute (0–360); `'+N'`/`'-N'` is relative\n * to the dark seed hue, which defaults to the (possibly overridden) seed\n * hue. Falls back to `hue` when omitted.\n */\n darkHue?: number | RelativeValue;\n /**\n * Dark-scheme seed saturation (0–100). Defaults to `saturation`. When set,\n * the global `darkDesaturation` reduction is not applied on top.\n */\n darkSaturation?: number;\n /**\n * Dark-scheme multiplier on the dark seed (0–1). Defaults to\n * `saturationFactor`. When set, the global `darkDesaturation` reduction is\n * not applied on top.\n */\n darkSaturationFactor?: number;\n /**\n * Override tone. Number is absolute (0–100, contrast-uniform); `'+N'`/`'-N'`\n * is relative to the literal seed (the value passed to `glaze.color()`);\n * `'max'` / `'min'` force to the scheme's tone extreme.\n * Supports HCPair for high-contrast.\n */\n tone?: HCPair<ToneValue>;\n /** Saturation multiplier on the seed (0–1). Default: 1. */\n saturationFactor?: number;\n /**\n * Adaptation mode. Defaults to `'auto'` for every input form, so\n * colors automatically adapt between light and dark like an ordinary\n * theme color. Value-shorthand inputs (strings and literal objects)\n * preserve light tone via a local `lightTone: false` default; other\n * omitted config fields fall through to the live global at resolve\n * time. Structured `{ hue, saturation, tone }` form also falls\n * through for both tone windows unless overridden.\n *\n * Pass `'fixed'` explicitly to opt back into the linear, non-\n * inverting mapping; pass `'static'` to pin the same tone\n * across every variant.\n */\n mode?: AdaptationMode;\n\n /**\n * Flip out-of-bounds results (relative `tone` overshoot / unmet\n * `contrast`) to the opposite side instead of clamping. Defaults to\n * the global `autoFlip`.\n */\n autoFlip?: boolean;\n\n /**\n * Contrast floor. By default solved against the literal seed\n * (the value itself); when `base` is set, solved against the base's\n * resolved variant per scheme. Same shape as `RegularColorDef.contrast`\n * (bare number/preset = WCAG; `{ wcag }` / `{ apca }` to pick the metric).\n */\n contrast?: HCPair<ContrastSpec>;\n\n /**\n * Optional dependency on another color. Accepts either a\n * `GlazeColorToken` (returned by another `glaze.color()`) or a raw\n * `GlazeColorValue` (hex / CSS strings / `{ r, g, b }` / `{ h, s, l }` / …),\n * which is automatically wrapped in `glaze.color(value)`.\n *\n * When set:\n * - `contrast` is solved against the base's resolved variant\n * per-scheme (light / dark / lightContrast / darkContrast).\n * - Relative `tone: '+N'` / `'-N'` is anchored to the base's\n * tone per-scheme (matches theme behavior for dependent colors).\n * - Relative `hue: '+N'` / `'-N'` still anchors to the seed (the\n * value passed to `glaze.color()`), not the base.\n * - The link resolves against the base token's own variants in every\n * scheme: what the base paints, under its own config, whatever form\n * the base was made in. A light `'+0'` lands on the base and a light\n * `contrast` floor is measured against it.\n *\n * The base token's `.resolve()` is called lazily on first resolve and\n * its result is captured by reference; later mutations to the base's\n * defining call don't apply (matches existing token snapshot semantics).\n */\n base?: GlazeColorToken | GlazeColorValue;\n\n /**\n * Fixed opacity (0–1). Output includes alpha in the CSS value.\n * Combining with `contrast` is not recommended (perceived tone\n * becomes unpredictable) — a `console.warn` is emitted in that case.\n */\n opacity?: number;\n\n /**\n * Optional human-readable name for the token. Used in error and\n * warning messages (otherwise an internal name like `\"value\"` is\n * used) and as `resolve().name`. A debug label only: it does not\n * affect output keys or the token's `role`.\n */\n name?: string;\n\n /**\n * Per-color override for the hue-independent \"safe\" chroma limit used in\n * OKHSL↔sRGB conversions (luminance, contrast solving, output formatting).\n * Falls through to the per-theme / per-token `pastel` override when omitted.\n * @see GlazeConfigOverride.pastel\n */\n pastel?: boolean;\n\n /**\n * Semantic role against the token's anchor (`base`, or the literal seed\n * when `contrast` / a relative `tone` is set without one): how this token\n * is used. Fixes APCA contrast polarity; WCAG ignores it. Defaults to\n * `'text'` — the token is the foreground and the anchor the background,\n * with or without `base`. Unlike a theme color, a token never infers its\n * role from `name`, so `inferRole` has no effect on it.\n */\n role?: RoleInput;\n}\n\n/**\n * Object input for `glaze.color()` that carries a raw color value plus\n * optional color overrides in the same object.\n *\n * ```ts\n * glaze.color({ from: '#1a1a2e', base: bg, contrast: 'AA' })\n * glaze.color({ from: { r: 38, g: 252, b: 178 }, tone: '+10' })\n * ```\n */\nexport interface GlazeFromInput extends GlazeColorOverrides {\n /** The source color value. Accepts the same forms as a bare `GlazeColorValue`. */\n from: GlazeColorValue;\n}\n\n/** Options for `GlazeColorToken.css()`. */\nexport interface GlazeColorCssOptions {\n /**\n * Custom property base name (without leading `--`). Required.\n * Becomes the variable identifier in the output, e.g.\n * `name: 'brand'` → `--brand-color: …`.\n */\n name: string;\n /** Output color format. Default: 'oklch'. */\n format?: GlazeColorFormat;\n /**\n * Suffix appended to the name. Default: '-color' (matches\n * `theme.css` default).\n */\n suffix?: string;\n /**\n * Emit hue as a separate `--{name}-hue` custom property, referenced via\n * `var()`. Requires `format: 'oklch'` (any other format throws) and a\n * pastel token.\n */\n splitHue?: boolean;\n}\n\n/** Return type for `glaze.color()`. */\nexport interface GlazeColorToken {\n /** Resolve the color across all scheme variants. */\n resolve(): ResolvedColor;\n /** Export as a flat token map (no color name key). */\n token(options?: GlazeTokenOptions): Record<string, string>;\n /**\n * Export as a tasty style-to-state binding (no color name key).\n * Uses `#name` keys and state aliases (`''`, `'@media(prefers-color-scheme: dark)'`, etc.).\n * @see https://tasty.style/docs\n */\n tasty(options?: GlazeTokenOptions): Record<string, string>;\n /** Export as a flat JSON map (no color name key). */\n json(options?: GlazeJsonOptions): Record<string, string>;\n /** Export as CSS custom property declarations grouped by scheme variant. */\n css(options: GlazeColorCssOptions): GlazeCssResult;\n /**\n * Export as W3C DTCG color tokens (one per scheme variant, no color name\n * key). Each entry is a full `{ $type: 'color', $value }` token.\n * @see https://www.designtokens.org/\n */\n dtcg(options?: GlazeDtcgOptions): GlazeColorDtcgResult;\n /**\n * Export as a single W3C DTCG Resolver-Module document for this color,\n * keyed by `name` across all scheme variants. `name` is required.\n * @see https://www.designtokens.org/\n */\n dtcgResolver(\n options: GlazeColorDtcgResolverOptions,\n ): GlazeDtcgResolverDocument;\n /**\n * Export as a Tailwind CSS v4 `@theme` block (light baseline) plus dark /\n * high-contrast overrides. Returns a single ready-to-paste CSS string.\n * `name` is required (forms `--color-<name>`).\n * @see https://tailwindcss.com/docs/theme\n */\n tailwind(options: GlazeColorTailwindOptions): string;\n /**\n * Serialize the token as a JSON-safe object. Captures the original\n * input value, overrides, and config so it can be rehydrated via\n * `glaze.colorFrom(...)`. `base` is recursively serialized.\n * Optional `override` is merged over the instance local at export time.\n */\n export(override?: GlazeConfigOverride): GlazeColorTokenExport;\n}\n\n/**\n * JSON-safe serialization of a `glaze.color()` token. Pass to\n * `glaze.colorFrom(...)` to rehydrate.\n */\nexport interface GlazeColorTokenExport {\n /** Snapshot kind. Always written by `token.export()`; optional on legacy snapshots. */\n kind?: 'color';\n /** Schema version. Always written by `token.export()`; optional on legacy snapshots. */\n version?: number;\n /**\n * Discriminator for the source overload that created the token.\n * - `'value'`: created via `glaze.color(value)` or `glaze.color({ from, ...overrides })`.\n * - `'structured'`: created via `glaze.color({ hue, saturation, ... })`.\n */\n form: 'value' | 'structured';\n /** Original input. For `form: 'value'` this is the raw `GlazeColorValue`; for `form: 'structured'` this is the structured input. */\n input: GlazeColorValue | GlazeColorInputExport;\n /**\n * Overrides recorded at creation time. `base` is recursively\n * serialized. Only present for `form: 'value'`.\n */\n overrides?: GlazeColorOverridesExport;\n /**\n * Effective config freeze from `.export()` — `getConfig() ∪ local ∪\n * exportArg` at call time. Used by `glaze.colorFrom()` to pin\n * deterministic behavior across later `configure()` calls.\n */\n config?: GlazeConfigOverride;\n}\n\n/**\n * JSON-safe serialization of a `glaze.palette()` composition.\n * Pass to `glaze.paletteFrom(...)` to rehydrate.\n */\nexport interface GlazePaletteExport {\n /** Snapshot kind. Always written by `palette.export()`. */\n kind?: 'palette';\n /** Schema version. Always written by `palette.export()`. */\n version?: number;\n /** Per-theme authoring snapshots keyed by theme name. */\n themes: Record<string, GlazeThemeExport>;\n /** Primary theme name, if set on the palette. */\n primary?: string;\n}\n\n/**\n * Serializable shape of a structured `glaze.color({...})` input.\n * Differs from `GlazeColorInput` only in that `base` is replaced by an\n * `export` instead of a token reference.\n */\nexport interface GlazeColorInputExport {\n hue: number;\n saturation: number;\n tone: HCPair<number | ExtremeValue>;\n saturationFactor?: number;\n darkHue?: number | RelativeValue;\n darkSaturation?: number;\n darkSaturationFactor?: number;\n mode?: AdaptationMode;\n autoFlip?: boolean;\n opacity?: number;\n base?: GlazeColorTokenExport | GlazeColorValue;\n contrast?: HCPair<ContrastSpec>;\n name?: string;\n pastel?: boolean;\n role?: RoleInput;\n}\n\n/**\n * Serializable shape of `GlazeColorOverrides`. `base` is replaced by\n * its export (or left as a `GlazeColorValue` if it was originally a value).\n */\nexport interface GlazeColorOverridesExport {\n hue?: number | RelativeValue;\n saturation?: number;\n darkHue?: number | RelativeValue;\n darkSaturation?: number;\n darkSaturationFactor?: number;\n tone?: HCPair<ToneValue>;\n saturationFactor?: number;\n mode?: AdaptationMode;\n autoFlip?: boolean;\n contrast?: HCPair<ContrastSpec>;\n base?: GlazeColorTokenExport | GlazeColorValue;\n opacity?: number;\n name?: string;\n pastel?: boolean;\n role?: RoleInput;\n}\n\n// ============================================================================\n// Theme API\n// ============================================================================\n\n/**\n * The hue/saturation seed pair a theme resolves against.\n *\n * `darkHue` / `darkSaturation` are a separate seed for the `dark` and\n * `darkContrast` variants; each falls back to its light counterpart. Setting\n * `darkSaturation` opts the theme out of the global `darkDesaturation`\n * reduction — the authored value is used literally.\n */\nexport interface GlazeThemeSeed {\n /** Light-scheme hue seed (0–360). */\n hue: number;\n /** Light-scheme saturation seed (0–100). */\n saturation: number;\n /** Dark-scheme hue seed (0–360). Defaults to `hue`. */\n darkHue?: number;\n /** Dark-scheme saturation seed (0–100). Defaults to `saturation`. */\n darkSaturation?: number;\n}\n\nexport interface GlazeTheme {\n /** The hue seed (0–360). */\n readonly hue: number;\n /** The saturation seed (0–100). */\n readonly saturation: number;\n /** The dark-scheme hue seed (0–360), or `undefined` when `hue` is reused. */\n readonly darkHue: number | undefined;\n /** The dark-scheme saturation seed (0–100), or `undefined` when `saturation` is reused. */\n readonly darkSaturation: number | undefined;\n /** The effective config for this theme. */\n getConfig(): GlazeConfigResolved;\n\n /** Add/replace colors (additive merge with existing definitions). */\n colors(defs: ColorMap): void;\n\n /** Get a color definition by name. */\n color(name: string): ColorDef | undefined;\n /** Set a single color definition. */\n color(name: string, def: ColorDef): void;\n\n /** Remove one or more color definitions. */\n remove(names: string | string[]): void;\n\n /** Check if a color is defined. */\n has(name: string): boolean;\n\n /** List all defined color names. */\n list(): string[];\n\n /** Clear all color definitions. */\n reset(): void;\n\n /** Export the theme configuration as a JSON-safe object. */\n export(override?: GlazeConfigOverride): GlazeThemeExport;\n\n /** Create a child theme inheriting all color definitions. */\n extend(options: GlazeExtendOptions): GlazeTheme;\n\n /** Resolve all colors and return the result map. */\n resolve(): Map<string, ResolvedColor>;\n\n /**\n * Export as a flat token map grouped by scheme variant.\n *\n * ```ts\n * theme.tokens()\n * // → { light: { surface: 'okhsl(...)' }, dark: { surface: 'okhsl(...)' } }\n * ```\n *\n * With `modes.hdr`, each scheme map is followed by a dense `<scheme>Hdr`\n * map (`lightHdr`, `darkHdr`, …): every glow with an HDR value in any\n * emitted scheme, as extended `color(srgb …)`, or its SDR value where\n * that scheme has none.\n */\n tokens(options?: GlazeJsonOptions): Record<string, Record<string, string>>;\n\n /**\n * Export as tasty style-to-state bindings.\n * Uses `#name` color token keys and state aliases (`''`, `'@media(prefers-color-scheme: dark)'`, etc.).\n * Spread into component styles or register as a recipe via `configure({ recipes })`.\n * With `modes.hdr`, a glow's HDR value follows each SDR key that has one,\n * under `states.hdr` (`'@media(dynamic-range: high)'`) combined with it.\n * @see https://tasty.style/docs\n */\n tasty(options?: GlazeTastyOptions): Record<string, Record<string, string>>;\n\n /**\n * Export as plain JSON. With `modes.hdr`, a glow variant with an HDR value\n * adds a `<scheme>Hdr` key (`lightHdr`, …) right after its SDR key.\n */\n json(options?: GlazeJsonOptions): Record<string, Record<string, string>>;\n\n /** Export as CSS custom property declarations. */\n css(options?: GlazeCssOptions): GlazeCssResult;\n\n /**\n * Export as W3C Design Tokens Format Module (2025.10) documents, one per\n * scheme variant. Consumable by Figma, Tokens Studio, Style Dictionary,\n * Terrazzo, and any DTCG-compatible tool.\n * @see https://www.designtokens.org/\n */\n dtcg(options?: GlazeDtcgOptions): GlazeDtcgResult;\n\n /**\n * Export as a single W3C DTCG Resolver-Module document describing every\n * scheme variant as one `sets` entry plus a single `scheme` modifier with a\n * context per variant. Consumable by resolver tools such as Dispersa.\n * @see https://www.designtokens.org/\n */\n dtcgResolver(options?: GlazeDtcgResolverOptions): GlazeDtcgResolverDocument;\n\n /**\n * Export as a Tailwind CSS v4 `@theme` block (light baseline) plus dark /\n * high-contrast overrides under configurable selectors. Returns a single\n * ready-to-paste CSS string.\n * @see https://tailwindcss.com/docs/theme\n */\n tailwind(options?: GlazeTailwindOptions): string;\n}\n\nexport interface GlazeExtendOptions {\n hue?: number;\n saturation?: number;\n /** Replace the dark-scheme hue seed (0–360). Defaults to the parent's. */\n darkHue?: number;\n /** Replace the dark-scheme saturation seed (0–100). Defaults to the parent's. */\n darkSaturation?: number;\n colors?: ColorMap;\n /** Config override for the child theme. Merged with the parent's override. */\n config?: GlazeConfigOverride;\n}\n\n// ============================================================================\n// Palette API\n// ============================================================================\n\n/**\n * Options for `token.token()` / `token.tasty()`, and the base of the theme and\n * palette `tasty()` options: output format, scheme variants, state aliases.\n */\nexport interface GlazeTokenOptions {\n /**\n * Override state aliases for this export. `hdr` keys an HDR glow value\n * (with `modes.hdr`); a `glaze.color()` token is never a glow, so it never\n * uses it.\n */\n states?: {\n dark?: string;\n highContrast?: string;\n hdr?: string;\n };\n /** Override which scheme variants to include. */\n modes?: GlazeOutputModes;\n /** Output color format. Default: 'oklch'. */\n format?: GlazeColorFormat;\n}\n\n/** Options for `theme.tasty()`. */\nexport interface GlazeTastyOptions extends GlazeTokenOptions {\n /**\n * Emit hue as a separate custom property, referenced via `var()`.\n * Requires `format: 'oklch'` (any other format throws) and every color to\n * be pastel.\n */\n splitHue?: boolean;\n /**\n * Base name for the theme-level hue var (`--{name}-hue`). Default: `'theme'`.\n * Must not equal the name of a color that sets its own hue (throws).\n */\n name?: string;\n}\n\n/** Options for `theme.tokens()` / `theme.json()` and their palette and token counterparts. */\nexport interface GlazeJsonOptions {\n /** Override which scheme variants to include. */\n modes?: GlazeOutputModes;\n /** Output color format. Default: 'oklch'. */\n format?: GlazeColorFormat;\n}\n\n/** Options for `theme.css()`. */\nexport interface GlazeCssOptions {\n /** Output color format. Default: 'oklch'. */\n format?: GlazeColorFormat;\n /** Suffix appended to each CSS custom property name. Default: '-color'. */\n suffix?: string;\n /**\n * Emit hue as a separate custom property, referenced via `var()`.\n * Requires `format: 'oklch'` (any other format throws) and every color to\n * be pastel.\n */\n splitHue?: boolean;\n /**\n * Base name for the theme-level hue var (`--{name}-hue`). Default: `'theme'`.\n * Must not equal the name of a color that sets its own hue (throws).\n */\n name?: string;\n /**\n * Add the HDR tier as `result.hdr` (see {@link GlazeCssResult.hdr}).\n * Default: the global `modes.hdr` (false). `css()` has no `modes` — it\n * always emits all four schemes — so this is its HDR switch.\n * @experimental No browser paints a CSS color past SDR white yet, so this\n * tier looks like SDR at best today, and its shape may change (for example\n * to CSS `hdr-color()`) once one does.\n */\n hdr?: boolean;\n}\n\n/** CSS custom property declarations for each scheme variant. */\nexport interface GlazeCssSchemeBlocks {\n light: string;\n dark: string;\n lightContrast: string;\n darkContrast: string;\n}\n\n/** CSS custom property declarations grouped by scheme variant. */\nexport interface GlazeCssResult extends GlazeCssSchemeBlocks {\n /**\n * The HDR tier, present when HDR output is on — the `hdr` option, which\n * defaults to the global `modes.hdr`: one block per scheme,\n * each re-declaring every color that has an HDR value in any scheme — its\n * HDR value (extended `color(srgb R G B)`) where that scheme has one, and\n * the scheme's SDR declaration where it has none. The blocks are dense so\n * a light HDR value can never leak into dark: wire each one after the SDR\n * blocks, under the same selector plus `(dynamic-range: high)`. Every block\n * is an empty string when no color has an HDR value.\n */\n hdr?: GlazeCssSchemeBlocks;\n}\n\n// ============================================================================\n// DTCG & Tailwind export types\n// ============================================================================\n\n/**\n * Color space used for DTCG `$value` color objects.\n * @see https://www.designtokens.org/\n */\nexport type DtcgColorSpace = 'srgb' | 'oklch';\n\n/**\n * A DTCG color `$value` in the sRGB color space: gamma sRGB components in\n * 0–1 plus a 6-digit `hex` hint. Universally understood by Figma, Tokens\n * Studio, Style Dictionary, and every DTCG reader.\n */\nexport interface DtcgSrgbColorValue {\n colorSpace: 'srgb';\n components: [number, number, number];\n hex: HexColor;\n /** Opacity 0–1. Omitted when fully opaque (alpha = 1). */\n alpha?: number;\n}\n\n/**\n * A DTCG color `$value` in the OKLCH color space: `[L, C, H]` components\n * (L/C: 0–1, H: degrees). Wide-gamut and Glaze-native; no `hex` is emitted.\n */\nexport interface DtcgOklchColorValue {\n colorSpace: 'oklch';\n components: [number, number, number];\n /** Opacity 0–1. Omitted when fully opaque (alpha = 1). */\n alpha?: number;\n}\n\n/** A DTCG `$value` for a color token, in either supported color space. */\nexport type DtcgColorValue = DtcgSrgbColorValue | DtcgOklchColorValue;\n\n/**\n * The HDR value of a glow past SDR white, carried in a DTCG token's\n * `$extensions['me.tenphi.glaze'].hdr` (`$value` stays the SDR color, since\n * DTCG color components stop at 1). Maps onto native APIs: UIKit\n * `UIColor(red:green:blue:alpha:exposure:)` (AppKit: its `NSColor` twin) from\n * `base` and `exposure`, or Android\n * `Color.pack(r, g, b, 1f, ColorSpace.get(ColorSpace.Named.EXTENDED_SRGB))`\n * from `value`.\n */\nexport interface GlazeDtcgHdr {\n /** Gain over `base` in stops (`log2` of the linear factor), above 0. */\n exposure: number;\n /**\n * Luminance tone of the HDR value (e.g. `112`) — past 100 when the headroom\n * covers the step; a saturated base capped by `headroom` can land below 100,\n * though its brightest channel still exceeds 1.\n */\n tone: number;\n /** The opaque base (what SDR paints), as a DTCG sRGB color. */\n base: DtcgSrgbColorValue;\n /**\n * The HDR color, `base × 2^exposure` in linear light, as extended sRGB\n * components (the numbers of `glaze.formatHdr()`): its brightest channel\n * above 1 (the others may stay below).\n */\n value: {\n colorSpace: 'srgb';\n components: [number, number, number];\n };\n}\n\n/** The Glaze namespace of a DTCG token's `$extensions`. */\nexport interface GlazeDtcgExtensions {\n 'me.tenphi.glaze': {\n /** Present only with `modes.hdr`, on a glow variant that has an HDR value. */\n hdr: GlazeDtcgHdr;\n };\n}\n\n/**\n * A single W3C DTCG color token: `{ $type: 'color', $value }`.\n * `$description` is optional and not populated by Glaze today. `$extensions`\n * is set only with `modes.hdr`, on a glow variant with an HDR value.\n */\nexport interface DtcgColorToken {\n $type: 'color';\n $value: DtcgColorValue;\n $description?: string;\n $extensions?: GlazeDtcgExtensions;\n}\n\n/**\n * A W3C Design Tokens Format Module (2025.10) token tree for one scheme.\n * Glaze emits one document per scheme variant — the most tool-compatible\n * convention (one file per Style Dictionary theme / Tokens Studio set /\n * Figma variable mode).\n */\nexport type DtcgDocument = Record<string, DtcgColorToken>;\n\n/** DTCG token documents grouped by scheme variant. Light is always present. */\nexport interface GlazeDtcgResult {\n light: DtcgDocument;\n dark?: DtcgDocument;\n lightContrast?: DtcgDocument;\n darkContrast?: DtcgDocument;\n}\n\n/** A single DTCG color token grouped by scheme variant (standalone tokens). */\nexport interface GlazeColorDtcgResult {\n light: DtcgColorToken;\n dark?: DtcgColorToken;\n lightContrast?: DtcgColorToken;\n darkContrast?: DtcgColorToken;\n}\n\n/** Options for `theme.dtcg()` / `palette.dtcg()`. */\nexport interface GlazeDtcgOptions {\n /** Override which scheme variants to include. */\n modes?: GlazeOutputModes;\n /**\n * DTCG color space. `'srgb'` (default) emits sRGB components plus a `hex`\n * hint — universally understood (Figma, Tokens Studio). `'oklch'` emits\n * OKLCH components with no hex — Glaze-native, wide-gamut.\n */\n colorSpace?: DtcgColorSpace;\n}\n\n// ============================================================================\n// DTCG Resolver-Module export types\n// (W3C Design Tokens Resolver Module — one document for all scheme variants)\n// ============================================================================\n\n/**\n * A node in a DTCG Resolver-Module token tree: either a leaf color token or a\n * nested group. A flat `DtcgDocument` (top-level color-name keys) is a valid\n * shallow tree, so Glaze's per-scheme documents slot directly into\n * `sets.<name>.sources` and `modifiers.<name>.contexts.<ctx>` entries.\n */\nexport interface DtcgTokenTree {\n [key: string]: DtcgColorToken | DtcgTokenTree;\n}\n\n/** A named set in a resolver document: a list of token-tree sources. */\nexport interface DtcgResolverSet {\n sources: DtcgTokenTree[];\n}\n\n/**\n * A named modifier (an axis such as `scheme`) in a resolver document.\n * `default` names the context applied when no override is selected; `contexts`\n * maps each context name to the token-tree overrides applied for it.\n */\nexport interface DtcgResolverModifier {\n default: string;\n contexts: Record<string, DtcgTokenTree[]>;\n}\n\n/** A JSON-pointer `$ref` entry in a resolver document's `resolutionOrder`. */\nexport interface DtcgResolverRef {\n $ref: string;\n}\n\n/**\n * A W3C DTCG Resolver-Module document. Describes every scheme variant in a\n * single file as `sets` (base token sources) plus `modifiers` (per-context\n * overrides) composed in `resolutionOrder`. Consumable by resolver tools such\n * as Dispersa.\n * @see https://www.designtokens.org/\n */\nexport interface GlazeDtcgResolverDocument {\n version: string;\n sets: Record<string, DtcgResolverSet>;\n modifiers: Record<string, DtcgResolverModifier>;\n resolutionOrder: DtcgResolverRef[];\n}\n\n/** Renaming of the four scheme variants as resolver-modifier context names. */\nexport interface GlazeDtcgResolverContextNames {\n light?: string;\n dark?: string;\n lightContrast?: string;\n darkContrast?: string;\n}\n\n/**\n * Options for `theme.dtcgResolver()` / `palette.dtcgResolver()`. Extends\n * `GlazeDtcgOptions` so `modes` + `colorSpace` pass through to the underlying\n * per-scheme `dtcg()` build.\n */\nexport interface GlazeDtcgResolverOptions extends GlazeDtcgOptions {\n /** Name of the single set holding the default (light) token tree. Default `'base'`. */\n setName?: string;\n /**\n * Name of the modifier describing the scheme axis. Default `'scheme'`\n * (Glaze's term for the light / dark / high-contrast axis).\n */\n modifierName?: string;\n /**\n * Override the four context names emitted on the modifier. Defaults to the\n * Glaze variant keys: `light` / `dark` / `lightContrast` / `darkContrast`.\n */\n contextNames?: GlazeDtcgResolverContextNames;\n /** Resolver document version. Default `'2025.10'`. */\n version?: string;\n}\n\n/** Options for `glaze.color().dtcgResolver()`. `name` is required. */\nexport interface GlazeColorDtcgResolverOptions extends GlazeDtcgResolverOptions {\n /** Token name keying the color within each token tree. Required. */\n name: string;\n}\n\n/** Options for `theme.tailwind()` / `palette.tailwind()`. */\nexport interface GlazeTailwindOptions {\n /** Override which scheme variants to include. */\n modes?: GlazeOutputModes;\n /** Output color format. Default: 'oklch'. */\n format?: GlazeColorFormat;\n /**\n * CSS custom property namespace, forming `--<namespace><name>`.\n * Default: `'color-'` → `--color-surface`. (Tailwind v4's `--color-*`\n * convention, which auto-generates `bg-*` / `text-*` / `border-*`.)\n *\n * Named `namespace` rather than `prefix` to avoid clashing with the\n * palette theme-prefix option on `palette.tailwind()`.\n */\n namespace?: string;\n /**\n * Selector wrapping the dark-scheme overrides. Default: `'.dark'`.\n * Pass a media query such as `'@media (prefers-color-scheme: dark)'` to\n * drive dark mode from the OS preference instead of a class.\n */\n darkSelector?: string;\n /**\n * Selector wrapping the light high-contrast overrides. Default:\n * `'.high-contrast'`. The combined dark + high-contrast overrides are\n * emitted under `${darkSelector}${highContrastSelector}` (e.g.\n * `.dark.high-contrast`).\n */\n highContrastSelector?: string;\n /**\n * Selector wrapping the HDR overrides, emitted with `modes.hdr` after every\n * SDR block. Default: `'@media (dynamic-range: high)'`. Each HDR block is\n * dense (every color with an HDR value in any emitted scheme, SDR value\n * where the scheme has none) and is scoped by this selector alone (light),\n * combined with `darkSelector` (dark), with `highContrastSelector` (light\n * high contrast), or with both.\n * @experimental No browser paints a CSS color past SDR white yet, so this\n * tier looks like SDR at best today, and its shape may change (for example\n * to CSS `hdr-color()`) once one does.\n */\n hdrSelector?: string;\n}\n\n/** Options for `glaze.color().tailwind()`. `name` is required. */\nexport interface GlazeColorTailwindOptions extends GlazeTailwindOptions {\n /** Custom property base name (without leading `--`). Required. */\n name: string;\n}\n\n/** Options for `glaze.palette()` creation. */\nexport interface GlazePaletteOptions {\n /**\n * Name of the primary theme. The primary theme's tokens are duplicated\n * without prefix in all exports, providing convenient short aliases\n * alongside the prefixed versions. Can be overridden per-export.\n *\n * @example\n * ```ts\n * const palette = glaze.palette({ brand, accent }, { primary: 'brand' });\n * palette.tokens()\n * // → { light: { 'brand-surface': '...', 'surface': '...', 'accent-surface': '...' } }\n * ```\n */\n primary?: string;\n}\n\n/**\n * Options shared by every palette export except `json()`: `tokens()`,\n * `tasty()`, `css()`, `dtcg()`, `dtcgResolver()`, and `tailwind()`.\n */\nexport interface GlazePaletteExportOptions {\n /**\n * Prefix mode. `true` uses `\"<themeName>-\"`, or provide a custom map.\n * Defaults to `true` for palette export methods.\n * Set to `false` explicitly to disable prefixing. Colliding keys\n * produce a console.warn and the first-written value wins.\n */\n prefix?: boolean | Record<string, string>;\n /**\n * Override the palette-level primary theme for this export.\n * Pass a theme name to set/change the primary, or `false` to disable it.\n * When omitted, inherits the palette-level `primary`.\n */\n primary?: string | false;\n}\n\n/**\n * Options for `palette.tasty()`. There is no `name`: each theme's hue var is\n * named after the theme.\n */\nexport interface GlazePaletteTastyOptions\n extends GlazeTokenOptions, GlazePaletteExportOptions {\n /**\n * Emit hue as a separate custom property, referenced via `var()`.\n * Requires `format: 'oklch'` (any other format throws) and every color to\n * be pastel. The theme-level hue var is `--{themeName}-hue`.\n */\n splitHue?: boolean;\n}\n\n/**\n * Options for `palette.css()`. There is no `name`: each theme's hue var is\n * named after the theme.\n */\nexport interface GlazePaletteCssOptions extends GlazePaletteExportOptions {\n /** Output color format. Default: 'oklch'. */\n format?: GlazeColorFormat;\n /** Suffix appended to each CSS custom property name. Default: '-color'. */\n suffix?: string;\n /**\n * Emit hue as a separate custom property, referenced via `var()`.\n * Requires `format: 'oklch'` (any other format throws) and every color to\n * be pastel. The theme-level hue var is `--{themeName}-hue`.\n */\n splitHue?: boolean;\n /**\n * Add the HDR tier as `result.hdr` (see {@link GlazeCssResult.hdr}).\n * Default: the global `modes.hdr` (false).\n * @experimental No browser paints a CSS color past SDR white yet, so this\n * tier looks like SDR at best today, and its shape may change (for example\n * to CSS `hdr-color()`) once one does.\n */\n hdr?: boolean;\n}\n\nexport interface GlazePalette {\n /** Theme names in insertion order. */\n list(): string[];\n\n /** Primary theme name, if set at palette creation. */\n readonly primary: string | undefined;\n\n /** Get a theme by name. Returns the live instance held by the palette. */\n theme(name: string): GlazeTheme | undefined;\n\n /**\n * Shallow copy of the theme map (same instances the palette holds).\n * Mutating a returned theme affects subsequent palette exports.\n */\n themes(): Record<string, GlazeTheme>;\n\n /**\n * Export the palette authoring configuration as a JSON-safe object.\n * Restorable via `glaze.paletteFrom(...)`. Distinct from `json()`, which\n * emits resolved color strings. Optional `override` is forwarded to each\n * nested `theme.export(override)`.\n */\n export(override?: GlazeConfigOverride): GlazePaletteExport;\n\n /**\n * Export all themes as a flat token map grouped by scheme variant.\n * Prefix defaults to `true` — all tokens are prefixed with the theme name.\n * Inherits the palette-level `primary`; override per-call or pass `false` to disable.\n *\n * ```ts\n * const palette = glaze.palette({ brand, accent }, { primary: 'brand' });\n * palette.tokens()\n * // → { light: { 'brand-surface': '...', 'surface': '...', 'accent-surface': '...' } }\n * ```\n */\n tokens(\n options?: GlazeJsonOptions & GlazePaletteExportOptions,\n ): Record<string, Record<string, string>>;\n\n /**\n * Export all themes as tasty style-to-state bindings.\n * Uses `#name` color token keys and state aliases (`''`, `'@media(prefers-color-scheme: dark)'`, etc.).\n * Prefix defaults to `true`. Inherits the palette-level `primary`.\n * @see https://tasty.style/docs\n */\n tasty(\n options?: GlazePaletteTastyOptions,\n ): Record<string, Record<string, string>>;\n\n /**\n * Export all themes as plain JSON grouped by theme name. No prefix, primary\n * alias, or collision handling: each theme keeps its own key.\n */\n json(\n options?: GlazeJsonOptions,\n ): Record<string, Record<string, Record<string, string>>>;\n\n /** Export all themes as CSS custom property declarations. */\n css(options?: GlazePaletteCssOptions): GlazeCssResult;\n\n /**\n * Export all themes as W3C DTCG documents, one per scheme variant.\n * Prefix defaults to `true`. Inherits the palette-level `primary`.\n * @see https://www.designtokens.org/\n */\n dtcg(options?: GlazeDtcgOptions & GlazePaletteExportOptions): GlazeDtcgResult;\n\n /**\n * Export all themes as a single W3C DTCG Resolver-Module document. Prefix\n * defaults to `true`. Inherits the palette-level `primary`.\n * @see https://www.designtokens.org/\n */\n dtcgResolver(\n options?: GlazeDtcgResolverOptions & GlazePaletteExportOptions,\n ): GlazeDtcgResolverDocument;\n\n /**\n * Export all themes as a Tailwind CSS v4 `@theme` block plus dark /\n * high-contrast overrides. Returns a single ready-to-paste CSS string.\n * Prefix defaults to `true`.\n * @see https://tailwindcss.com/docs/theme\n */\n tailwind(options?: GlazeTailwindOptions & GlazePaletteExportOptions): string;\n}\n","/**\n * Authoring-export helpers: schema version, type guards, and restore\n * validation shared by `themeFrom` / `colorFrom` / `paletteFrom`.\n */\n\nimport { GLAZE_EXPORT_VERSION } from './types';\nimport type {\n GlazeColorTokenExport,\n GlazeExportKind,\n GlazePaletteExport,\n GlazeThemeExport,\n} from './types';\n\nexport { GLAZE_EXPORT_VERSION };\n\nfunction isPlainObject(data: unknown): data is Record<string, unknown> {\n return typeof data === 'object' && data !== null && !Array.isArray(data);\n}\n\n/**\n * Reject unknown / invalid schema versions. Missing `version` is allowed\n * (legacy snapshots). Present versions must be an integer in\n * `1..=GLAZE_EXPORT_VERSION`.\n */\nexport function assertExportVersion(\n data: { version?: unknown },\n factory: string,\n): void {\n if (data.version === undefined) return;\n if (\n typeof data.version !== 'number' ||\n !Number.isInteger(data.version) ||\n data.version < 1\n ) {\n throw new Error(\n `${factory}: invalid \"version\" field — expected an integer >= 1 (got ${JSON.stringify(data.version)}).`,\n );\n }\n if (data.version > GLAZE_EXPORT_VERSION) {\n throw new Error(\n `${factory}: unsupported export version ${data.version} (this library supports version ${GLAZE_EXPORT_VERSION}). Upgrade @tenphi/glaze to load this snapshot.`,\n );\n }\n}\n\n/**\n * Reject a version-1 (Glaze 1.1–2) theme snapshot that carries shadow colors or a\n * `shadowTuning`. Glaze 3 changed what shadow `intensity`, `fg` and tuning\n * mean, so restoring one would silently re-render every shadow differently.\n * Version-1 snapshots without shadows load as before. `fallbackVersion` is the\n * enclosing palette's version, for a theme entry that carries none of its own.\n */\nexport function assertNoLegacyShadows(\n data: GlazeThemeExport,\n factory: string,\n fallbackVersion?: unknown,\n): void {\n if ((data.version ?? fallbackVersion) !== 1) return;\n const colors = isPlainObject(data.colors) ? data.colors : {};\n const shadows = Object.keys(colors).filter(\n (name) =>\n isPlainObject(colors[name]) &&\n (colors[name] as { type?: unknown }).type === 'shadow',\n );\n const hasTuning =\n isPlainObject(data.config) && data.config.shadowTuning !== undefined;\n if (shadows.length === 0 && !hasTuning) return;\n\n const what =\n shadows.length > 0\n ? `shadow colors (${shadows.map((n) => JSON.stringify(n)).join(', ')})`\n : 'a \"shadowTuning\" config';\n throw new Error(\n `${factory}: this snapshot is export version 1 (Glaze 1.1–2) and contains ${what}. ` +\n `Glaze 3 changed what shadow \"intensity\", \"fg\" and tuning mean, so it ` +\n `would restore with different shadows. Re-author them as described in ` +\n `docs/migration.md (\"3.0 — shadows and glows\") and export again.`,\n );\n}\n\n/**\n * When `kind` is present, it must match the factory. Missing `kind` is\n * allowed for legacy snapshots.\n */\nexport function assertExportKind(\n data: { kind?: unknown },\n expected: GlazeExportKind,\n factory: string,\n): void {\n if (data.kind === undefined) return;\n if (data.kind !== expected) {\n throw new Error(\n `${factory}: expected kind \"${expected}\", got ${JSON.stringify(data.kind)}.`,\n );\n }\n}\n\nfunction hasThemeShape(data: Record<string, unknown>): boolean {\n return (\n typeof data.hue === 'number' &&\n typeof data.saturation === 'number' &&\n !('form' in data) &&\n !('themes' in data)\n );\n}\n\nfunction hasColorTokenShape(data: Record<string, unknown>): boolean {\n return data.form === 'value' || data.form === 'structured';\n}\n\nfunction hasPaletteShape(data: Record<string, unknown>): boolean {\n return (\n isPlainObject(data.themes) &&\n !('form' in data) &&\n typeof data.hue !== 'number'\n );\n}\n\n/** Type guard for theme authoring snapshots (prefers `kind`, falls back to shape). */\nexport function isThemeExport(data: unknown): data is GlazeThemeExport {\n if (!isPlainObject(data)) return false;\n if (data.kind === 'theme') return hasThemeShape(data);\n if (data.kind !== undefined) return false;\n return hasThemeShape(data);\n}\n\n/** Type guard for color-token authoring snapshots. */\nexport function isColorTokenExport(\n data: unknown,\n): data is GlazeColorTokenExport {\n if (!isPlainObject(data)) return false;\n if (data.kind === 'color') return hasColorTokenShape(data);\n if (data.kind !== undefined) return false;\n return hasColorTokenShape(data);\n}\n\n/** Type guard for palette authoring snapshots. */\nexport function isPaletteExport(data: unknown): data is GlazePaletteExport {\n if (!isPlainObject(data)) return false;\n if (data.kind === 'palette') return hasPaletteShape(data);\n if (data.kind !== undefined) return false;\n return hasPaletteShape(data);\n}\n","/**\n * Hue channel planning for `splitHue` exports.\n *\n * Builds per-color hue var references and the `--*-hue` declarations backing\n * them for oklch CSS / Tasty output when every color is pastel.\n *\n * Hue is scheme-independent unless the theme or a color authors a dark hue,\n * so declarations are collected per scheme (`'light'` / `'dark'`) and the dark\n * set is emitted only when it actually differs — see `buildHueDeclarations`.\n * A color that authors a hue in *either* scheme gets its own var in both, so\n * the shared `var()` reference stays valid. Every scheme renders with the\n * light plan (`buildHuePlans`), so a color inline in light (achromatic there)\n * is inline everywhere and declares no var in any scheme. Numeric hue values\n * are rounded to 2 decimals, the precision of the hue in `oklch()` output.\n *\n * Also owns the `splitHue` guards the output methods run before planning:\n * `assertSplitHueFormat` (only `oklch()` takes a `var()` hue), and\n * `claimHueVars` / `claimValueProps`, which keep every custom property an\n * export declares to one owner — the theme var, a color's own hue var, and\n * (`css()` only) each color's value property share one namespace.\n */\n\nimport { parseRelativeOrAbsolute } from './hc-pair';\nimport { isLightingDef, isMixDef } from './lighting';\nimport type {\n ColorDef,\n ColorMap,\n GlazeColorFormat,\n RegularColorDef,\n ResolvedColor,\n ResolvedColorVariant,\n} from './types';\n\nconst ACHROMATIC_EPSILON = 1e-6;\nconst SCHEMES: readonly HueScheme[] = ['light', 'dark'];\n\n/**\n * A numeric hue as emitted in a declaration: 2 decimals, matching the hue of\n * `formatOklch`, so a `from` color doesn't leak `266.15797905637027`.\n */\nfunction hueValue(h: number): string {\n return parseFloat(h.toFixed(2)).toString();\n}\n\n/**\n * Throw when `splitHue` is on and the format can't carry a `var()` hue. Only\n * `oklch()` has a hue slot a custom property can stand in for; silently\n * emitting inline colors instead would leave the hue vars the caller asked\n * for missing.\n */\nexport function assertSplitHueFormat(\n splitHue: boolean | undefined,\n format: GlazeColorFormat,\n): void {\n if (splitHue && format !== 'oklch') {\n throw new Error(\n `glaze: splitHue requires format 'oklch' (got '${format}'). ` +\n `Use format: 'oklch' or drop splitHue.`,\n );\n }\n}\n\n/** Which scheme's hue a plan or declaration set describes. */\nexport type HueScheme = 'light' | 'dark';\n\nexport interface HueDeclaration {\n prop: string;\n value: string;\n}\n\nexport interface HuePlan {\n /** CSS `var()` reference spliced into `oklch(L C <hueVar>)`. */\n hueVar: string;\n /** When true, emit a full inline color (shadow/glow/mix/achromatic). */\n inline: boolean;\n /** Scheme-independent `--*-hue` declarations for this color. */\n declarations: HueDeclaration[];\n}\n\nexport interface ChannelCtx {\n seedHue: number;\n /**\n * Dark-scheme seed hue, when the theme authored one. Drives the dark\n * `--{baseName}-hue` value; falls back to `seedHue`.\n */\n darkSeedHue?: number;\n /** Theme-level hue var base name (without `--` / `-hue`). */\n baseName: string;\n /** Token / custom-property name prefix used for hue var naming (`brand-` etc.). */\n prefix: string;\n defs: ColorMap;\n mode: 'theme' | 'standalone';\n /** Standalone: resolved hue from the primary variant (scheme-independent). */\n resolvedHue?: number;\n /**\n * When false, hue declarations are not emitted (the pass only references\n * hue vars already declared by a sibling pass). Used by palette primary\n * unprefixed aliases so they reference the themed `--{themeName}-*-hue`\n * vars without re-declaring (and colliding with) other themes' base vars.\n * Defaults to true.\n */\n emitDeclarations?: boolean;\n}\n\nfunction cssProp(prefix: string, name: string, suffix: string): string {\n return `--${prefix}${name}${suffix}`;\n}\n\nfunction isAchromatic(v: ResolvedColorVariant): boolean {\n return v.s <= ACHROMATIC_EPSILON;\n}\n\n/** Seed hue backing `--{baseName}-hue` in a given scheme. */\nfunction schemeSeedHue(ctx: ChannelCtx, scheme: HueScheme): number {\n return scheme === 'dark' ? (ctx.darkSeedHue ?? ctx.seedHue) : ctx.seedHue;\n}\n\nfunction themeHuePlan(\n name: string,\n def: ColorDef | undefined,\n variant: ResolvedColorVariant,\n ctx: ChannelCtx,\n scheme: HueScheme,\n): HuePlan {\n if (\n def === undefined ||\n isLightingDef(def) ||\n isMixDef(def) ||\n isAchromatic(variant)\n ) {\n return { hueVar: '', inline: true, declarations: [] };\n }\n\n const regDef = def as RegularColorDef;\n const baseHueVar = `var(--${ctx.baseName}-hue)`;\n const prop = cssProp(ctx.prefix, name, '-hue');\n\n // `mode: 'static'` pins one hue across every scheme, but `--{baseName}-hue`\n // is re-declared in dark whenever the theme seeds one. Pin the resolved hue\n // so a static color doesn't drift with it — matching what the resolver does.\n // Both variants carry the same hue under `static`, so either one works.\n const isStatic = (regDef.mode ?? 'auto') === 'static';\n if (isStatic && schemeSeedHue(ctx, 'dark') !== ctx.seedHue) {\n return {\n hueVar: `var(${prop})`,\n inline: false,\n declarations: [{ prop, value: hueValue(variant.h) }],\n };\n }\n // The resolver ignores a static color's `darkHue`, so its light authoring\n // holds in both schemes and it keeps following `--{baseName}-hue`.\n const darkHue = isStatic ? undefined : regDef.darkHue;\n\n // A color needs its own var as soon as *either* scheme authors a hue: the\n // `var()` reference is shared across schemes, so it can't be the theme var\n // in one and a per-color var in the other.\n //\n // `from` counts as authoring one. It carries a hue that is not the theme's,\n // so pointing the color at the theme hue var would re-skin it to whatever the\n // theme is seeded with — the same failure a `darkHue`-only color used to have.\n if (\n regDef.hue === undefined &&\n darkHue === undefined &&\n regDef.from === undefined\n ) {\n return { hueVar: baseHueVar, inline: false, declarations: [] };\n }\n\n const authored = scheme === 'dark' ? (darkHue ?? regDef.hue) : regDef.hue;\n\n if (authored === undefined) {\n // `from` supplied the hue for this scheme, so pin the resolved literal —\n // tracking the theme var would re-skin the color to the theme's hue, which\n // is the one thing a literal color must not do.\n if (regDef.from !== undefined) {\n return {\n hueVar: `var(${prop})`,\n inline: false,\n declarations: [{ prop, value: hueValue(variant.h) }],\n };\n }\n\n // Only the other scheme authored a hue; track the theme var in this one.\n return {\n hueVar: `var(${prop})`,\n inline: false,\n declarations: [{ prop, value: baseHueVar }],\n };\n }\n\n const parsed = parseRelativeOrAbsolute(authored);\n\n if (parsed.relative) {\n const sign = parsed.value >= 0 ? '+' : '-';\n const magnitude = hueValue(Math.abs(parsed.value));\n const value = `calc(var(--${ctx.baseName}-hue) ${sign} ${magnitude})`;\n return {\n hueVar: `var(${prop})`,\n inline: false,\n declarations: [{ prop, value }],\n };\n }\n\n const absHue = ((parsed.value % 360) + 360) % 360;\n return {\n hueVar: `var(${prop})`,\n inline: false,\n declarations: [{ prop, value: hueValue(absHue) }],\n };\n}\n\nfunction standaloneHuePlan(\n name: string,\n variant: ResolvedColorVariant,\n ctx: ChannelCtx,\n scheme: HueScheme,\n): HuePlan {\n if (isAchromatic(variant)) {\n return { hueVar: '', inline: true, declarations: [] };\n }\n\n // `resolvedHue` is the light-variant hue captured by the caller; the dark\n // pass reads the hue off the dark variant it was handed.\n const hue = scheme === 'dark' ? variant.h : (ctx.resolvedHue ?? variant.h);\n const prop = cssProp(ctx.prefix, name, '-hue');\n return {\n hueVar: `var(${prop})`,\n inline: false,\n declarations: [{ prop, value: hueValue(hue) }],\n };\n}\n\nexport function buildHuePlan(\n name: string,\n def: ColorDef | undefined,\n variant: ResolvedColorVariant,\n ctx: ChannelCtx,\n scheme: HueScheme = 'light',\n): HuePlan {\n if (ctx.mode === 'standalone') {\n return standaloneHuePlan(name, variant, ctx, scheme);\n }\n return themeHuePlan(name, def, variant, ctx, scheme);\n}\n\n/**\n * The plan whose declarations `name` contributes in `scheme`, or `undefined`\n * when the color declares nothing.\n *\n * Rendering uses the light plan in every scheme (`buildHuePlans`), so a color\n * whose light plan is inline — achromatic in light, say — is a literal\n * `oklch()` everywhere. Its dark plan may still name a var (it has chroma\n * there), but nothing would read it: a dead declaration that, in an unprefixed\n * palette, could override another theme's live hue var.\n */\nfunction declaringPlan(\n name: string,\n color: ResolvedColor,\n ctx: ChannelCtx,\n scheme: HueScheme,\n): HuePlan | undefined {\n const def = ctx.defs[name];\n const light = buildHuePlan(name, def, color.light, ctx);\n if (light.inline) return undefined;\n if (scheme === 'light') return light;\n return buildHuePlan(name, def, color.dark, ctx, scheme);\n}\n\n/** Collect unique hue declarations across all colors (theme + per-color). */\nfunction collectHueDeclarations(\n resolved: Map<string, ResolvedColor>,\n ctx: ChannelCtx,\n scheme: HueScheme,\n): HueDeclaration[] {\n if (ctx.emitDeclarations === false) return [];\n\n const seen = new Set<string>();\n const out: HueDeclaration[] = [];\n\n const push = (decl: HueDeclaration): void => {\n if (seen.has(decl.prop)) return;\n seen.add(decl.prop);\n out.push(decl);\n };\n\n if (ctx.mode === 'theme') {\n push({\n prop: `--${ctx.baseName}-hue`,\n value: hueValue(schemeSeedHue(ctx, scheme)),\n });\n }\n\n for (const [name, color] of resolved) {\n const plan = declaringPlan(name, color, ctx, scheme);\n for (const decl of plan?.declarations ?? []) {\n push(decl);\n }\n }\n\n return out;\n}\n\n/**\n * Hue declarations for both schemes. `dark` is empty when it resolves to the\n * same hues as light — the common case, with no `darkHue` anywhere.\n *\n * When they differ, the **whole** dark set is returned rather than only the\n * entries whose text changed. A relative declaration reads\n * `calc(var(--theme-hue) + N)` in both schemes even though its resolved value\n * moves with the seed, and custom properties substitute `var()` at\n * computed-value time on the declaring element — so re-declaring\n * `--{baseName}-hue` alone would leave inherited per-color vars still holding\n * the light-substituted value.\n */\nexport function buildHueDeclarations(\n resolved: Map<string, ResolvedColor>,\n ctx: ChannelCtx,\n): { light: HueDeclaration[]; dark: HueDeclaration[] } {\n const light = collectHueDeclarations(resolved, ctx, 'light');\n const dark = collectHueDeclarations(resolved, ctx, 'dark');\n\n const same =\n dark.length === light.length &&\n dark.every(\n (decl, i) => decl.prop === light[i].prop && decl.value === light[i].value,\n );\n\n return { light, dark: same ? [] : dark };\n}\n\nexport function buildHuePlans(\n resolved: Map<string, ResolvedColor>,\n ctx: ChannelCtx,\n): Map<string, HuePlan> {\n const plans = new Map<string, HuePlan>();\n for (const [name, color] of resolved) {\n plans.set(name, buildHuePlan(name, ctx.defs[name], color.light, ctx));\n }\n return plans;\n}\n\n/** Who declares a custom property in a `splitHue` export. */\nexport interface SplitHueOwner {\n /** The owner as the collision error names it. */\n label: string;\n /** True for a color's `css()` value property, false for a hue var. */\n value: boolean;\n}\n\n/**\n * Every custom property a `splitHue` export declares, by name. Pass one map\n * across all the passes of an export call (a palette runs one per theme, plus\n * the primary's aliases) to catch collisions between them.\n */\nexport type SplitHueOwners = Map<string, SplitHueOwner>;\n\n/** How a caller words who declares a property, and the fix. */\nexport interface HueVarLabels {\n /** The theme-level var's owner, e.g. `the theme hue (name: 'brand')`. */\n theme: string;\n /** A color's own var's owner, e.g. `color \"brand\"'s own hue`. */\n color: (name: string) => string;\n /** A color's `css()` value property's owner, e.g. `color \"brand\"'s value`. */\n value: (name: string) => string;\n /** The remedy appended when two hue vars clash. */\n fix: string;\n /** The remedy appended when a value property is one side of the clash. */\n valueFix: string;\n}\n\n/**\n * Record `prop` as `owner`'s, or throw when someone else already holds it. A\n * repeat claim by the same owner is fine: that is the same declaration seen\n * again (a theme pass re-run with the same prefix).\n */\nfunction claim(\n owners: SplitHueOwners,\n prop: string,\n owner: SplitHueOwner,\n labels: HueVarLabels,\n): void {\n const held = owners.get(prop);\n if (held === undefined) {\n owners.set(prop, owner);\n return;\n }\n if (held.label === owner.label) return;\n const fix = held.value || owner.value ? labels.valueFix : labels.fix;\n throw new Error(\n `glaze: splitHue would declare \"${prop}\" twice: for ${held.label} and ` +\n `for ${owner.label}. One would silently override the other. ${fix}`,\n );\n}\n\n/**\n * Claim every hue var this pass declares in `owners` and throw when a name is\n * already held by someone else.\n *\n * Theme and per-color vars share one namespace: `--{baseName}-hue` and\n * `--{prefix}{color}-hue`. A color named after the theme var (`brand` with\n * `name: 'brand'`), or a palette color named after another theme under an\n * empty prefix, would declare the same property as the theme. Only one value\n * survives — the theme's, after `collectHueDeclarations` dedupes — so the\n * color would silently render at the wrong hue.\n *\n * Every declaration a rendered plan references is claimed, in both schemes: a\n * color's own var only when its light plan references it. That includes a\n * declaration `collectHueDeclarations` would drop as a duplicate (a chromatic\n * `brand` color under `name: 'brand'`), since the color would still read the\n * survivor's hue. A color achromatic in light is inline in every scheme and\n * declares nothing, so it can share a name with the theme var.\n */\nexport function claimHueVars(\n resolved: Map<string, ResolvedColor>,\n ctx: ChannelCtx,\n owners: SplitHueOwners,\n labels: HueVarLabels,\n): void {\n if (ctx.emitDeclarations === false) return;\n\n if (ctx.mode === 'theme') {\n const owner = { label: labels.theme, value: false };\n claim(owners, `--${ctx.baseName}-hue`, owner, labels);\n }\n\n for (const [name, color] of resolved) {\n const owner = { label: labels.color(name), value: false };\n for (const scheme of SCHEMES) {\n const plan = declaringPlan(name, color, ctx, scheme);\n for (const decl of plan?.declarations ?? []) {\n claim(owners, decl.prop, owner, labels);\n }\n }\n }\n}\n\n/**\n * Claim each color's `css()` value property, `--{prefix}{color}{suffix}`, in\n * the same `owners` map as the hue vars.\n *\n * Value properties share the custom-property namespace with the hue vars, so\n * `suffix: '-hue'` — or `suffix: ''` with a color named `*-hue` — can land a\n * color's value on a hue var: its own, which makes a `var()` cycle, or one\n * another color or theme declares (in a palette, another theme's), which\n * hands every color reading it a color string where a hue belongs. Either way\n * the CSS is invalid at computed-value time.\n *\n * Unlike `claimHueVars` this runs on every pass, including one that declares\n * no hue vars (a palette's primary aliases): its value properties are emitted\n * all the same. Not for `tasty()`, whose `#name` colors compile to\n * `--name-color` and can't land on a `$…-hue` var.\n */\nexport function claimValueProps(\n resolved: Map<string, ResolvedColor>,\n prefix: string,\n suffix: string,\n owners: SplitHueOwners,\n labels: HueVarLabels,\n): void {\n for (const name of resolved.keys()) {\n const owner = { label: labels.value(name), value: true };\n claim(owners, cssProp(prefix, name, suffix), owner, labels);\n }\n}\n","/**\n * Parsing and validation for `GlazeColorValue` — the literal color forms.\n *\n * Hex, the CSS color functions Glaze emits, and the four value-object shapes all\n * land here and come out as OKHSL. Split out of `color-token.ts` so both\n * consumers can reach it without an import cycle: standalone `glaze.color()`\n * tokens build on it, and the resolver needs it for a theme color's `from`. It\n * depends on nothing but the color math, which is what keeps that true.\n */\n\nimport {\n hslToSrgb,\n oklabToOkhsl,\n parseHexAlpha,\n srgbToOkhsl,\n} from './okhsl-color-math';\nimport { okhstToOkhsl } from './okhst';\nimport type {\n GlazeColorValue,\n OkhslColor,\n OkhstColor,\n OklchColor,\n RgbColor,\n} from './types';\n\n/**\n * Matches the color functions Glaze itself emits (`rgb()`, `hsl()`, `okhsl()`,\n * `okhst()`, `oklch()`) plus their legacy alpha aliases (`rgba()`, `hsla()`).\n *\n * Only numeric components are supported, plus the CSS keyword `none` (a missing\n * component, read as 0 as CSS renders it); named colors (`red`) and\n * relative-color syntax (`from <color> ...`) are out of scope. A hue takes a\n * bare number (degrees) or `deg` / `turn` / `rad` / `grad`.\n */\nconst COLOR_FN_RE = /^(rgba?|hsla?|okhsl|okhst|oklch)\\(\\s*([^)]*)\\s*\\)$/i;\n\n/** One numeric component: a CSS number with an optional unit. */\nconst COMPONENT_RE = /^([+-]?(?:\\d+\\.?\\d*|\\.\\d+)(?:e[+-]?\\d+)?)([a-z%]*)$/i;\n\n/** Degrees per unit of each CSS angle unit. */\nconst ANGLE_UNITS: Record<string, number> = {\n '': 1,\n deg: 1,\n turn: 360,\n rad: 180 / Math.PI,\n grad: 0.9,\n};\n\nfunction readComponent(\n raw: string,\n input: string,\n units: Record<string, number>,\n): number {\n if (raw.toLowerCase() === 'none') return 0;\n const m = COMPONENT_RE.exec(raw);\n const scale = m ? units[m[2].toLowerCase()] : undefined;\n const value = m ? parseFloat(m[1]) * (scale ?? NaN) : NaN;\n if (!Number.isFinite(value)) {\n throw new Error(`glaze: invalid component \"${raw}\" in \"${input}\".`);\n }\n return value;\n}\n\n/** A number, or a percentage of `percentScale`. */\nfunction parseNumberOrPercent(\n raw: string,\n percentScale: number,\n input: string,\n): number {\n return readComponent(raw, input, { '': 1, '%': percentScale / 100 });\n}\n\n/** A hue in degrees. */\nfunction parseHue(raw: string, input: string): number {\n return readComponent(raw, input, ANGLE_UNITS);\n}\n\nconst clamp01 = (value: number): number => Math.min(1, Math.max(0, value));\n\n/**\n * Split the body of a CSS color function into its components and detect\n * whether an alpha channel was present.\n *\n * Handles both modern slash syntax (`R G B / A` or `R, G, B / A`) and\n * legacy comma syntax (`R, G, B, A`). The alpha value itself is discarded\n * by the caller, with a warning: translucency is a color's `opacity` field.\n */\nfunction splitColorBody(body: string): {\n components: string[];\n hadAlpha: boolean;\n} {\n const slashIdx = body.indexOf('/');\n if (slashIdx !== -1) {\n const components = body\n .slice(0, slashIdx)\n .trim()\n .split(/[\\s,]+/)\n .filter(Boolean);\n const hadAlpha = body.slice(slashIdx + 1).trim().length > 0;\n return { components, hadAlpha };\n }\n\n const components = body.split(/[\\s,]+/).filter(Boolean);\n if (components.length === 4) {\n components.pop();\n return { components, hadAlpha: true };\n }\n return { components, hadAlpha: false };\n}\n\n/** Inputs already warned about, so a re-parsed `from` warns once. */\nconst warnedAlpha = new Set<string>();\n\nfunction warnDroppedAlpha(input: string): void {\n if (warnedAlpha.has(input)) return;\n if (warnedAlpha.size >= 256) warnedAlpha.clear();\n warnedAlpha.add(input);\n console.warn(\n `glaze: alpha component dropped from \"${input}\"; use the color's \\`opacity\\` (or a transparent mix) for translucency.`,\n );\n}\n\nexport function parseColorString(input: string): OkhslColor {\n if (input.startsWith('#')) {\n const parsed = parseHexAlpha(input);\n if (!parsed) throw new Error(`glaze: invalid hex color \"${input}\".`);\n if (parsed.alpha !== undefined) warnDroppedAlpha(input);\n const [h, s, l] = srgbToOkhsl(parsed.rgb);\n return { h, s, l };\n }\n\n const m = input.match(COLOR_FN_RE);\n if (!m) {\n throw new Error(`glaze: unsupported color string \"${input}\".`);\n }\n\n const fn = m[1].toLowerCase();\n const { components, hadAlpha } = splitColorBody(m[2].trim());\n\n if (hadAlpha) warnDroppedAlpha(input);\n if (components.length !== 3) {\n throw new Error(`glaze: expected 3 components in \"${input}\".`);\n }\n\n // Out-of-range values clamp, as CSS clamps them at parse time: a channel\n // past 255, a lightness past 100%, a negative chroma.\n const [c0, c1, c2] = components;\n switch (fn) {\n case 'rgb':\n case 'rgba': {\n const r = clamp01(parseNumberOrPercent(c0, 255, input) / 255);\n const g = clamp01(parseNumberOrPercent(c1, 255, input) / 255);\n const b = clamp01(parseNumberOrPercent(c2, 255, input) / 255);\n const [h, s, l] = srgbToOkhsl([r, g, b]);\n return { h, s, l };\n }\n case 'hsl':\n case 'hsla': {\n const h = parseHue(c0, input);\n const s = clamp01(parseNumberOrPercent(c1, 1, input));\n const l = clamp01(parseNumberOrPercent(c2, 1, input));\n const [oh, os, ol] = srgbToOkhsl(hslToSrgb(h, s, l));\n return { h: oh, s: os, l: ol };\n }\n case 'okhsl': {\n const h = parseHue(c0, input);\n const s = clamp01(parseNumberOrPercent(c1, 1, input));\n const l = clamp01(parseNumberOrPercent(c2, 1, input));\n return { h, s, l };\n }\n case 'okhst': {\n const h = parseHue(c0, input);\n const s = clamp01(parseNumberOrPercent(c1, 1, input));\n const t = clamp01(parseNumberOrPercent(c2, 1, input));\n return okhstToOkhsl({ h, s, t });\n }\n case 'oklch': {\n const L = clamp01(parseNumberOrPercent(c0, 1, input));\n // Per CSS Color 4: chroma percent maps `100% → 0.4`.\n const C = Math.max(0, parseNumberOrPercent(c1, 0.4, input));\n const hDeg = parseHue(c2, input);\n const hRad = (hDeg * Math.PI) / 180;\n const a = C * Math.cos(hRad);\n const b = C * Math.sin(hRad);\n const [h, s, l] = oklabToOkhsl([L, a, b]);\n return { h, s, l };\n }\n }\n throw new Error(`glaze: unsupported color function \"${fn}\".`);\n}\n\n// ============================================================================\n// Input validation\n// ============================================================================\n\n/**\n * Validate a user-supplied `OkhslColor`. Catches the common 0-100 vs 0-1\n * confusion (the structured form uses 0-100, OKHSL objects use 0-1).\n */\nexport function validateOkhslColor(value: OkhslColor): void {\n const { h, s, l } = value;\n if (!Number.isFinite(h) || !Number.isFinite(s) || !Number.isFinite(l)) {\n throw new Error('glaze.color: OkhslColor h/s/l must be finite numbers.');\n }\n assertNonNegative('OkhslColor', { s, l });\n if (s > 1.5 || l > 1.5) {\n throw new Error(\n 'glaze.color: OkhslColor s/l must be in 0–1 range. Did you mean the structured form { hue, saturation, tone } (which uses 0–100)?',\n );\n }\n}\n\n/** Reject a negative 0–1 component, naming it: no color has one. */\nfunction assertNonNegative(kind: string, fields: Record<string, number>): void {\n for (const [key, n] of Object.entries(fields)) {\n if (n < 0) {\n throw new Error(\n `glaze.color: ${kind} ${key} must be 0 or more (got ${n}).`,\n );\n }\n }\n}\n\n/** Validate a user-supplied `{ r, g, b }` object in 0–255. */\nexport function validateRgbColor(value: RgbColor): void {\n for (const key of ['r', 'g', 'b'] as const) {\n const n = value[key];\n if (!Number.isFinite(n) || n < 0 || n > 255) {\n throw new Error(\n `glaze.color: RgbColor ${key} must be a finite number in 0–255 (got ${n}).`,\n );\n }\n }\n}\n\n/** Validate a user-supplied `{ l, c, h }` OKLCh object. */\nexport function validateOklchColor(value: OklchColor): void {\n const { l, c, h } = value;\n if (!Number.isFinite(l) || !Number.isFinite(c) || !Number.isFinite(h)) {\n throw new Error('glaze.color: OklchColor l/c/h must be finite numbers.');\n }\n assertNonNegative('OklchColor', { l, c });\n if (l > 1.5 || c > 1.5) {\n throw new Error(\n 'glaze.color: OklchColor l/c must be in 0–1 range (matching oklch() strings).',\n );\n }\n}\n\nexport function oklchComponentsToOkhsl(\n l: number,\n c: number,\n hDeg: number,\n): OkhslColor {\n const hRad = (hDeg * Math.PI) / 180;\n const a = c * Math.cos(hRad);\n const b = c * Math.sin(hRad);\n const [h, s, outL] = oklabToOkhsl([l, a, b]);\n return { h, s, l: outL };\n}\n\n/**\n * A detached copy of a color value. A value object is read by property access\n * once its shape is known, so a getter, an inherited field or a proxy copies\n * like a plain field (a spread would drop the first two). Strings, and shapes\n * the parser rejects anyway, pass through.\n */\nexport function copyColorValue<T extends GlazeColorValue>(value: T): T {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n return value;\n }\n const v = value as unknown as Record<string, unknown>;\n if (isRgbColorObject(value)) return { r: v.r, g: v.g, b: v.b } as T;\n if (isOklchColorObject(value)) return { l: v.l, c: v.c, h: v.h } as T;\n if (isOkhstColorObject(value)) return { h: v.h, s: v.s, t: v.t } as T;\n return { h: v.h, s: v.s, l: v.l } as T;\n}\n\nexport function isRgbColorObject(value: object): value is RgbColor {\n return 'r' in value && 'g' in value && 'b' in value;\n}\n\nexport function isOklchColorObject(value: object): value is OklchColor {\n return 'c' in value && 'l' in value && 'h' in value;\n}\n\nexport function isOkhstColorObject(value: object): value is OkhstColor {\n return 't' in value && 'h' in value && 's' in value;\n}\n\n/** Validate a user-supplied `{ h, s, t }` OKHST object (s/t in 0–1). */\nexport function validateOkhstColor(value: OkhstColor): void {\n const { h, s, t } = value;\n if (!Number.isFinite(h) || !Number.isFinite(s) || !Number.isFinite(t)) {\n throw new Error('glaze.color: OkhstColor h/s/t must be finite numbers.');\n }\n assertNonNegative('OkhstColor', { s, t });\n if (s > 1.5 || t > 1.5) {\n throw new Error(\n 'glaze.color: OkhstColor s/t must be in 0–1 range. Did you mean the structured form { hue, saturation, tone } (which uses 0–100)?',\n );\n }\n}\n\n/**\n * Extract an OKHSL color from any `GlazeColorValue` form. Also used by\n * `glaze.shadow()` / `glaze.glow()` so all their inputs (hex, color\n * functions, OKHSL, literal objects) go through one parser. A value object's\n * 0–1 field that passed its check above 1 (up to 1.5) clamps to 1, as the\n * same value in a color function does.\n */\nexport function extractOkhslFromValue(value: GlazeColorValue): OkhslColor {\n if (typeof value === 'string') return parseColorString(value);\n if (Array.isArray(value)) {\n throw new Error(\n 'glaze.color: RGB tuple [r, g, b] is no longer supported — use { r, g, b } instead.',\n );\n }\n if (isRgbColorObject(value)) {\n validateRgbColor(value);\n const [h, s, l] = srgbToOkhsl([\n value.r / 255,\n value.g / 255,\n value.b / 255,\n ]);\n return { h, s, l };\n }\n if (isOklchColorObject(value)) {\n validateOklchColor(value);\n return oklchComponentsToOkhsl(clamp01(value.l), value.c, value.h);\n }\n if (isOkhstColorObject(value)) {\n validateOkhstColor(value);\n return okhstToOkhsl({\n h: value.h,\n s: clamp01(value.s),\n t: clamp01(value.t),\n });\n }\n validateOkhslColor(value);\n return { h: value.h, s: clamp01(value.s), l: clamp01(value.l) };\n}\n","/**\n * Export-time guards for color format and channel-splitting prerequisites.\n */\n\nimport type {\n GlazeColorFormat,\n GlazeOutputModes,\n ResolvedColor,\n} from './types';\n\nconst NON_NATIVE_FORMATS = new Set<GlazeColorFormat>(['okhsl', 'okhst']);\n\n/**\n * Throw when a non-native Glaze color space is requested for an export that\n * emits raw CSS or non-Tasty token maps.\n */\nexport function assertNativeFormat(\n format: GlazeColorFormat | undefined,\n method: string,\n): void {\n if (format !== undefined && NON_NATIVE_FORMATS.has(format)) {\n throw new Error(\n `glaze: ${format} output is only supported by tasty() (not a native CSS color space). ` +\n `Use tasty({ format: '${format}' }) or pick a native format (oklch|hsl|rgb) for ${method}().`,\n );\n }\n}\n\ntype SchemeField = 'light' | 'dark' | 'lightContrast' | 'darkContrast';\n\n/** The modes `assertAllPastel` reads: which schemes are emitted. */\ntype SchemeModes = Required<Pick<GlazeOutputModes, 'dark' | 'highContrast'>>;\n\nconst SCHEME_FIELDS: {\n field: SchemeField;\n modes: (modes: SchemeModes) => boolean;\n}[] = [\n { field: 'light', modes: () => true },\n { field: 'dark', modes: (m) => m.dark },\n { field: 'lightContrast', modes: (m) => m.highContrast },\n {\n field: 'darkContrast',\n modes: (m) => m.dark && m.highContrast,\n },\n];\n\n/**\n * Throw when `splitHue` is enabled but any exported color is not pastel.\n * Hue rotation is only clip-free when chroma is bounded by the hue-independent\n * safe chroma (`computeSafeChromaOKLCH`).\n */\nexport function assertAllPastel(\n resolved: Map<string, ResolvedColor>,\n modes: SchemeModes,\n): void {\n const nonPastel: string[] = [];\n\n for (const [name, color] of resolved) {\n for (const { field, modes: active } of SCHEME_FIELDS) {\n if (!active(modes)) continue;\n const variant = color[field];\n if (variant.pastel !== true) {\n if (!nonPastel.includes(name)) nonPastel.push(name);\n break;\n }\n }\n }\n\n if (nonPastel.length === 0) return;\n\n throw new Error(\n 'glaze: splitHue requires every color to be pastel (hue rotation is only ' +\n 'clip-free when chroma is bounded by the hue-independent safe chroma). ' +\n `Non-pastel: ${nonPastel.join(', ')}. ` +\n 'Set pastel: true (per-theme, per-token, or per-color) or drop splitHue.',\n );\n}\n","/**\n * Semantic color role resolution.\n *\n * A `role` fixes APCA contrast polarity (which side is the foreground vs the\n * background). Roles are resolved per color via a four-step chain (see\n * `resolveRole`): explicit `def.role` → name inference → opposite of the\n * base's role → `'text'` foreground default.\n *\n * This module owns the alias keyword sets, name tokenization, and the\n * role → polarity / opposite-role mappings. It has no dependencies.\n */\n\nimport type { Role, RoleInput } from './types';\n\n// ============================================================================\n// Keyword sets\n// ============================================================================\n\nconst SURFACE_KEYWORDS = new Set([\n 'surface',\n 'bg',\n 'background',\n 'fill',\n 'canvas',\n 'paper',\n 'layer',\n]);\n\nconst TEXT_KEYWORDS = new Set([\n 'text',\n 'fg',\n 'foreground',\n 'content',\n 'ink',\n 'label',\n 'stroke',\n]);\n\nconst BORDER_KEYWORDS = new Set([\n 'border',\n 'divider',\n 'outline',\n 'separator',\n 'hairline',\n 'rule',\n]);\n\nconst ALIAS_TO_ROLE: Record<string, Role> = {\n // surface\n surface: 'surface',\n bg: 'surface',\n background: 'surface',\n fill: 'surface',\n canvas: 'surface',\n paper: 'surface',\n layer: 'surface',\n // text\n text: 'text',\n fg: 'text',\n foreground: 'text',\n content: 'text',\n ink: 'text',\n label: 'text',\n stroke: 'text',\n // border\n border: 'border',\n divider: 'border',\n outline: 'border',\n separator: 'border',\n hairline: 'border',\n rule: 'border',\n};\n\n// ============================================================================\n// Normalization\n// ============================================================================\n\n/**\n * Normalize a `RoleInput` (canonical value or alias) into a canonical `Role`.\n * Returns `undefined` for unrecognized strings so callers can fall through to\n * the next step of the resolution chain.\n */\nexport function normalizeRole(input: RoleInput | undefined): Role | undefined {\n if (input === undefined) return undefined;\n return ALIAS_TO_ROLE[input];\n}\n\n// ============================================================================\n// Name inference\n// ============================================================================\n\n/**\n * Tokenize a color name into lowercase keyword tokens, splitting on\n * non-alphanumeric boundaries and at camelCase boundaries. Examples:\n * - `'button-text'` → `['button', 'text']`\n * - `'inputBg'` → `['input', 'bg']`\n * - `'card_border-outline'` → `['card', 'border', 'outline']`\n */\nfunction tokenizeName(name: string): string[] {\n // Split on non-alphanumeric, then split camelCase within each piece.\n const pieces = name.split(/[^0-9a-zA-Z]+/).filter(Boolean);\n const tokens: string[] = [];\n for (const piece of pieces) {\n // Split at the boundary between a lowercase/digit run and an uppercase\n // letter (camelCase humps), e.g. \"inputBg\" → [\"input\", \"Bg\"].\n const sub = piece\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\n .split(/\\s+/)\n .filter(Boolean);\n for (const s of sub) tokens.push(s.toLowerCase());\n }\n return tokens;\n}\n\n/**\n * Infer a `Role` from a color name by matching its tokens against the role\n * keyword sets. When multiple tokens match, the **last** recognized token\n * wins (so `button-text` → `text`, `input-bg` → `surface`, `card-border` →\n * `border`). Returns `undefined` when no token matches.\n */\nexport function inferRoleFromName(name: string): Role | undefined {\n const tokens = tokenizeName(name);\n let inferred: Role | undefined;\n for (const token of tokens) {\n if (SURFACE_KEYWORDS.has(token)) inferred = 'surface';\n else if (TEXT_KEYWORDS.has(token)) inferred = 'text';\n else if (BORDER_KEYWORDS.has(token)) inferred = 'border';\n }\n return inferred;\n}\n\n// ============================================================================\n// Polarity + opposites\n// ============================================================================\n\n/** APCA argument order: which side the resolved color plays. */\nexport type Polarity = 'fg' | 'bg';\n\n/**\n * Map a role to its APCA polarity. `text` and `border` are foreground spots\n * against their base (the candidate is the text argument); `surface` is the\n * background (the base is the text argument).\n */\nexport function roleToPolarity(role: Role): Polarity {\n return role === 'surface' ? 'bg' : 'fg';\n}\n\n/**\n * The opposite role of `role`, used when a color with no explicit role and no\n * inferable name depends on a base: the dependent color plays the opposite\n * role of its base. `surface` ↔ `text`; `border` is treated as a foreground\n * spot, so its opposite is `surface`.\n */\nexport function oppositeRole(role: Role): Role {\n if (role === 'surface') return 'text';\n return 'surface';\n}\n","/**\n * Color graph validation and topological sort.\n *\n * `validateColorDefs` rejects bad references (missing / shadow- or\n * glow-referencing / base/contrast/tone mismatches — a relative tone in either\n * entry of an HC pair needs a base), a malformed `contrast` spec (a misspelled\n * preset, a non-finite number, a bad shape), a numeric field the resolver can't\n * place (non-finite, a malformed `'+N'`, an opacity outside 0–1), and bad\n * per-color lighting tuning (a\n * `headroom` on a shadow; a glow `headroom` that is not a finite number ≥ 0,\n * with one above the maximum warned about — once every def has passed — and\n * clamped at resolve), and detects cycles before the resolver runs. `topoSort` orders defs so each color is\n * processed after its base / bg / fg / target dependencies.\n */\n\nimport { extractOkhslFromValue } from './color-value';\nimport { normalizeLightingTuning } from './config';\nimport {\n contrastMetricOf,\n isApcaPreset,\n isContrastPreset,\n} from './contrast-solver';\nimport { isAbsoluteTone, pairHC, pairNormal, showValue } from './hc-pair';\nimport { isLightingDef, isMixDef } from './lighting';\nimport { flushWarnings } from './warnings';\nimport type { DeferredWarnings } from './warnings';\nimport type {\n ColorMap,\n ContrastSpec,\n HCPair,\n RegularColorDef,\n ResolvedColor,\n ToneValue,\n} from './types';\n\n/**\n * Does this color sit at an absolute tone — either authored, or carried by a\n * `from` value? That is the test for \"root\" (placed on its own) as opposed to\n * \"dependent\" (placed relative to a base), and it is what lets a bare\n * `{ from: '#2F5BFF' }` stand as a complete color definition.\n */\nexport function hasAbsoluteTone(def: RegularColorDef): boolean {\n if (def.tone === undefined) return def.from !== undefined;\n return isAbsoluteTone(def.tone);\n}\n\n/**\n * Does either entry of a `tone` measure from a base? `isAbsoluteTone` reads\n * only the normal entry — that is the root / dependent test — so the\n * high-contrast entry of a pair is checked on its own here: `[50, '+20']`\n * needs a base just as much as `'+20'` does.\n */\nexport function hasRelativeTone(tone: HCPair<ToneValue> | undefined): boolean {\n if (tone === undefined) return false;\n return !isAbsoluteTone(pairNormal(tone)) || !isAbsoluteTone(pairHC(tone));\n}\n\nconst isWcagValue = (value: unknown): boolean =>\n (typeof value === 'number' && Number.isFinite(value)) ||\n isContrastPreset(value);\n\nconst isApcaValue = (value: unknown): boolean =>\n (typeof value === 'number' && Number.isFinite(value)) || isApcaPreset(value);\n\n/**\n * A value, or a `[normal, highContrast]` pair of two, that passes `isValue`.\n * Both entries are read by index: `every` would skip a hole (`[, 7]`).\n */\nfunction isPairOf(value: unknown, isValue: (v: unknown) => boolean): boolean {\n return Array.isArray(value)\n ? value.length === 2 && isValue(value[0]) && isValue(value[1])\n : isValue(value);\n}\n\n/**\n * A WCAG value, or an object with exactly one of `wcag` / `apca` set. A key\n * holding `undefined` is unset, as everywhere else; other keys are ignored.\n */\nfunction isContrastSpec(spec: unknown): boolean {\n if (isWcagValue(spec)) return true;\n if (typeof spec !== 'object' || spec === null || Array.isArray(spec)) {\n return false;\n }\n const { wcag, apca } = spec as { wcag?: unknown; apca?: unknown };\n if ((wcag === undefined) === (apca === undefined)) return false;\n return wcag !== undefined\n ? isPairOf(wcag, isWcagValue)\n : isPairOf(apca, isApcaValue);\n}\n\nconst SIGNED_NUMBER_RE = /^[+-](?:\\d+\\.?\\d*|\\.\\d+)(?:e[+-]?\\d+)?$/i;\n\nconst isFiniteNumber = (value: unknown): value is number =>\n typeof value === 'number' && Number.isFinite(value);\n\n/**\n * A relative `'+N'` / `'-N'` string with a finite `N`. Whitespace around it\n * is allowed, as the resolver's `parseFloat` reads past it. Also checks a\n * token's structured `darkHue`.\n */\nexport const isRelativeValue = (value: unknown): boolean =>\n typeof value === 'string' &&\n SIGNED_NUMBER_RE.test(value.trim()) &&\n Number.isFinite(parseFloat(value));\n\nconst isToneValue = (value: unknown): boolean =>\n isFiniteNumber(value) ||\n value === 'max' ||\n value === 'min' ||\n isRelativeValue(value);\n\nconst isHueValue = (value: unknown): boolean =>\n isFiniteNumber(value) || isRelativeValue(value);\n\nconst isOpacity = (value: unknown): boolean =>\n isFiniteNumber(value) && value >= 0 && value <= 1;\n\n/**\n * Reject a numeric field the resolver can't place: `NaN`, `Infinity`, a\n * relative string that isn't `'+N'` / `'-N'` (`'+-5'`, `'+abc'`), an opacity\n * outside 0–1. Each would otherwise reach the output as `NaN`.\n */\nfunction assertField(\n name: string,\n field: string,\n value: unknown,\n isValid: (value: unknown) => boolean,\n): void {\n if (value === undefined || isValid(value)) return;\n throw new Error(\n `glaze: color \"${name}\" has an invalid \"${field}\" ${showValue(value)}.`,\n );\n}\n\n/**\n * Reject a malformed `contrast`: a misspelled preset, a non-finite number, an\n * object without exactly one of `wcag` / `apca`, or a pair without exactly two\n * entries. The solver would read each as no target at all and pin the color\n * to the scheme's extreme without a word.\n */\nfunction assertValidContrast(name: string, contrast: unknown): void {\n if (contrast === undefined || isPairOf(contrast, isContrastSpec)) return;\n throw new Error(\n `glaze: color \"${name}\" has an invalid \"contrast\" ${showValue(contrast)}. ` +\n `Use a WCAG ratio or 'AA' / 'AAA' / 'AA-large' / 'AAA-large', ` +\n `{ wcag: … }, { apca: … }, or a [normal, highContrast] pair of these.`,\n );\n}\n\n/**\n * Reject a `contrast` pair whose two entries measure in different metrics.\n *\n * A WCAG ratio and an APCA Lc are different scales, so `[4.5, { apca: 75 }]`\n * asks one color to be judged two incompatible ways. There is no target between\n * them for a manual `contrastLevel` to resolve, and even in `'auto'` mode the\n * two variants become incomparable. Pick one metric and pair its values\n * instead: `{ wcag: [4.5, 7] }` or `{ apca: [60, 90] }`.\n */\nfunction assertConsistentContrastMetric(\n name: string,\n contrast: HCPair<ContrastSpec> | undefined,\n): void {\n if (contrast === undefined || !Array.isArray(contrast)) return;\n const normal = contrastMetricOf(pairNormal(contrast));\n const hc = contrastMetricOf(pairHC(contrast));\n if (normal === hc) return;\n throw new Error(\n `glaze: color \"${name}\" has a \"contrast\" pair that switches metric ` +\n `(${normal} → ${hc}). A WCAG ratio and an APCA Lc are different scales; ` +\n `use one metric for both entries, e.g. { ${normal}: [normal, highContrast] }.`,\n );\n}\n\n/**\n * `'shadow'` / `'glow'` when `ref` names a local translucent overlay — which\n * nothing may build on — else `undefined`.\n */\nfunction overlayKindOf(\n defs: ColorMap,\n ref: string,\n): 'shadow' | 'glow' | undefined {\n const def = Object.hasOwn(defs, ref) ? defs[ref] : undefined;\n return def !== undefined && isLightingDef(def) ? def.type : undefined;\n}\n\nexport function validateColorDefs(\n defs: ColorMap,\n externalBases?: Map<string, ResolvedColor>,\n): void {\n const localNames = new Set(Object.keys(defs));\n const allNames = new Set([\n ...localNames,\n ...(externalBases ? externalBases.keys() : []),\n ]);\n // Headroom clamp warnings, sent only once every def has passed, so a map\n // that throws on a later def doesn't spend them before its fixed retry.\n const deferred: DeferredWarnings = [];\n\n for (const [name, def] of Object.entries(defs)) {\n if (isLightingDef(def)) {\n // Translucent overlays are leaves: they composite over an opaque color,\n // so neither end may itself be a shadow or glow.\n const kind = def.type;\n for (const field of ['bg', 'fg'] as const) {\n const ref = def[field];\n if (ref === undefined) {\n if (field === 'fg') continue;\n throw new Error(`glaze: ${kind} \"${name}\" is missing \"bg\".`);\n }\n if (!allNames.has(ref)) {\n throw new Error(\n `glaze: ${kind} \"${name}\" references non-existent ${field} \"${ref}\".`,\n );\n }\n const refKind = overlayKindOf(defs, ref);\n if (refKind !== undefined) {\n throw new Error(\n `glaze: ${kind} \"${name}\" ${field} \"${ref}\" references a ${refKind} color.`,\n );\n }\n }\n assertField(name, 'intensity', def.intensity, (v) =>\n isPairOf(v, isFiniteNumber),\n );\n // Throws for a shadow `headroom` or a bad glow one; the resolver's\n // tuning merge applies the clamp this warns about.\n normalizeLightingTuning(\n kind,\n def.tuning,\n `${kind} \"${name}\" tuning`,\n deferred,\n );\n continue;\n }\n\n if (isMixDef(def)) {\n if (!allNames.has(def.base)) {\n throw new Error(\n `glaze: mix \"${name}\" references non-existent base \"${def.base}\".`,\n );\n }\n if (!allNames.has(def.target)) {\n throw new Error(\n `glaze: mix \"${name}\" references non-existent target \"${def.target}\".`,\n );\n }\n for (const field of ['base', 'target'] as const) {\n const ref = def[field];\n const refKind = overlayKindOf(defs, ref);\n if (refKind !== undefined) {\n throw new Error(\n `glaze: mix \"${name}\" ${field} \"${ref}\" references a ${refKind} color.`,\n );\n }\n }\n assertField(name, 'value', def.value, (v) => isPairOf(v, isFiniteNumber));\n assertValidContrast(name, def.contrast);\n assertConsistentContrastMetric(name, def.contrast);\n continue;\n }\n\n const regDef = def as RegularColorDef;\n\n assertField(name, 'tone', regDef.tone, (v) => isPairOf(v, isToneValue));\n assertField(name, 'hue', regDef.hue, isHueValue);\n assertField(name, 'darkHue', regDef.darkHue, isHueValue);\n assertField(name, 'saturation', regDef.saturation, isFiniteNumber);\n assertField(name, 'darkSaturation', regDef.darkSaturation, isFiniteNumber);\n assertField(name, 'opacity', regDef.opacity, isOpacity);\n assertValidContrast(name, regDef.contrast);\n assertConsistentContrastMetric(name, regDef.contrast);\n\n // Parse `from` here rather than letting the resolver hit it. The parser's own\n // error names the offending string but not the color it came from, which in a\n // palette of fifty tokens is the half you actually need.\n if (regDef.from !== undefined) {\n try {\n extractOkhslFromValue(regDef.from);\n } catch (error) {\n throw new Error(\n `glaze: color \"${name}\" has an invalid \"from\" value. ${\n error instanceof Error ? error.message : String(error)\n }`,\n { cause: error },\n );\n }\n }\n\n if (regDef.contrast !== undefined && !regDef.base) {\n throw new Error(`glaze: color \"${name}\" has \"contrast\" without \"base\".`);\n }\n\n // Either entry of a pair: a relative high-contrast entry on a root would\n // otherwise be read as an absolute tone (`'+20'` as tone 20).\n if (hasRelativeTone(regDef.tone) && !regDef.base) {\n throw new Error(\n `glaze: color \"${name}\" has relative \"tone\" without \"base\".`,\n );\n }\n\n if (regDef.base && !allNames.has(regDef.base)) {\n throw new Error(\n `glaze: color \"${name}\" references non-existent base \"${regDef.base}\".`,\n );\n }\n\n const baseKind = regDef.base && overlayKindOf(defs, regDef.base);\n if (baseKind) {\n throw new Error(\n `glaze: color \"${name}\" base \"${regDef.base}\" references a ${baseKind} color.`,\n );\n }\n\n if (!hasAbsoluteTone(regDef) && regDef.base === undefined) {\n throw new Error(\n `glaze: color \"${name}\" must have either absolute \"tone\" (root), \"from\" (a literal color), or \"base\" (dependent).`,\n );\n }\n\n if (regDef.contrast !== undefined && regDef.opacity !== undefined) {\n console.warn(\n `glaze: color \"${name}\" has both \"contrast\" and \"opacity\". Opacity makes perceived tone unpredictable.`,\n );\n }\n }\n\n // Check for circular references (follows base, bg, fg edges).\n // External bases are leaves (no outgoing edges in `defs`), so they can't\n // form a cycle and we short-circuit there.\n const visited = new Set<string>();\n const inStack = new Set<string>();\n\n function dfs(name: string): void {\n if (!localNames.has(name)) return;\n if (inStack.has(name)) {\n throw new Error(\n `glaze: circular base reference detected involving \"${name}\".`,\n );\n }\n if (visited.has(name)) return;\n\n inStack.add(name);\n const def = defs[name];\n if (isLightingDef(def)) {\n dfs(def.bg);\n if (def.fg) dfs(def.fg);\n } else if (isMixDef(def)) {\n dfs(def.base);\n dfs(def.target);\n } else {\n const regDef = def as RegularColorDef;\n if (regDef.base) {\n dfs(regDef.base);\n }\n }\n inStack.delete(name);\n visited.add(name);\n }\n\n for (const name of localNames) {\n dfs(name);\n }\n\n flushWarnings(deferred);\n}\n\nexport function topoSort(defs: ColorMap): string[] {\n const result: string[] = [];\n const visited = new Set<string>();\n\n function visit(name: string): void {\n if (visited.has(name)) return;\n visited.add(name);\n\n const def = defs[name];\n // External base references (not in `defs`) are leaves — they're already\n // pre-seeded into `ctx.resolved` and don't participate in the local sort.\n if (def === undefined) return;\n if (isLightingDef(def)) {\n visit(def.bg);\n if (def.fg) visit(def.fg);\n } else if (isMixDef(def)) {\n visit(def.base);\n visit(def.target);\n } else {\n const regDef = def as RegularColorDef;\n if (regDef.base) {\n visit(regDef.base);\n }\n }\n\n result.push(name);\n }\n\n for (const name of Object.keys(defs)) {\n visit(name);\n }\n\n return result;\n}\n","/**\n * Color resolution engine.\n *\n * Runs the four-pass solver (light → light-HC → dark → dark-HC) that\n * turns a `ColorMap` into a fully resolved `ResolvedColor` per name. A manual\n * `contrastLevel` interpolates the authored HC pairs, tone window, and contrast\n * targets at that level for the two *normal* passes only; the high-contrast\n * passes bypass the level entirely, so the high-contrast slots are the same\n * values `'auto'` resolves. At level 100 the normal passes already are the\n * high-contrast ones, so the solver drops to two passes (light → dark) and\n * mirrors the slots. Owns the per-scheme resolve helpers for regular, shadow /\n * glow, and mix color defs.\n *\n * In dark, an `auto` tone delta (`'+N'` / `'-N'`) steps from where its base\n * sits on the authored scale in that pass (`darkAnchor`, memoized per pass):\n * the authored tone for an `auto` base placed by a tone or a chain of `auto`\n * deltas, or — for a base whose dark tone is not an inverted authored one: a\n * `fixed` / `static` color, or one solved, mixed, or replayed (an `auto`\n * extreme) — its own dark tone taken back through the dark window. So a dark\n * delta lands where the same authored tone would, on every base: the dark\n * window's scale times the delta at the reference dark eps (exact in high\n * contrast), along the dark window's own curve under a custom one, mirrored\n * around wherever the base sits even when the base itself doesn't invert. The\n * flip is still decided on the base's light tone, so\n * dark mirrors the side light took, and a step that runs off the authored\n * scale from its anchor (past 0 or 100) stops at the dark window's edge — at\n * either end, for a base anchored at its own dark tone. A base sitting past the\n * window (pushed by a contrast floor or an extreme, or placed there as a fixed\n * / static color) is stepped from where it sits, and a step pointing further\n * out stops at the base (`stepFromAnchor`). External\n * `glaze.color()` bases supply their own anchor (`darkAnchorOf`).\n *\n * Variants are stored in OKHST: `h` / `s` are OKHSL hue/saturation and\n * `t` is the canonical contrast-uniform tone (0–1, reference eps). The\n * resolver works in tone for regular colors and converts to/from OKHSL\n * lightness only at the mix / shadow / glow and luminance edges. A mix reads\n * a base or target under another `pastel` flag in its own gamut, through the\n * color that endpoint paints, and measures its contrast floor on the color it\n * emits. A glow whose step crosses white with `headroom` above 0 also carries\n * `hdr` — its opaque base in OKHST plus an exposure in stops — and swaps the\n * SDR shortfall warning for one that fires only when the headroom cap falls\n * short. HDR values never feed another color: nothing may build on a glow.\n *\n * Every function receives a single `GlazeConfigResolved` so the full\n * per-instance config (including overrides) is available without\n * re-reading the global singleton mid-resolve.\n */\n\nimport {\n compositeOverGamma,\n okhslToLinearSrgb,\n okhslToOklab,\n oklabToOkhsl,\n srgbToOkhsl,\n toDisplayGamma,\n} from './okhsl-color-math';\nimport {\n findToneForContrast,\n findValueForMixContrast,\n metricLuminance,\n metricScore,\n resolveContrastForLevel,\n resolveContrastForMode,\n} from './contrast-solver';\nimport type { LinearRgb, ResolvedContrast } from './contrast-solver';\nimport {\n PAIR_SWITCH,\n clamp,\n contrastFraction,\n hcMirrorsNormal,\n numberAt,\n pairHC,\n pairNormal,\n parseToneValue,\n parseToneValueAt,\n resolveEffectiveHue,\n} from './hc-pair';\nimport {\n inferRoleFromName,\n normalizeRole,\n oppositeRole,\n roleToPolarity,\n} from './roles';\nimport {\n circularLerp,\n computeLighting,\n isLightingDef,\n isMixDef,\n resolveLightingTuning,\n toResolvedHdr,\n} from './lighting';\nimport {\n REF_EPS,\n fromTone,\n mapDarkToneUnclamped,\n mapSaturationDark,\n mapToneForScheme,\n normalizeToneWindow,\n okhslToOkhst,\n sameDarkWindow,\n schemeToneRange,\n toTone,\n unmapDarkTone,\n variantToOkhsl,\n} from './okhst';\nimport { extractOkhslFromValue } from './color-value';\nimport { hasAbsoluteTone, topoSort, validateColorDefs } from './validation';\nimport {\n warnContrastUnmet,\n warnContrastDrift,\n warnLightingShortfall,\n warnMixContrastUnmet,\n} from './warnings';\nimport type {\n AdaptationMode,\n ColorDef,\n ColorMap,\n ContrastSpec,\n GlazeConfigResolved,\n GlazeThemeSeed,\n GlowColorDef,\n HCPair,\n MixColorDef,\n RegularColorDef,\n ResolvedColor,\n ResolvedColorVariant,\n Role,\n ShadowColorDef,\n ToneValue,\n} from './types';\n\n/** Where a color sits on the authored scale in one pass (see `darkAnchor`). */\ninterface DarkAnchor {\n /**\n * The anchor tone (0–100; a color sitting past the dark window — solved,\n * replayed, or a fixed / static color — leaves it).\n */\n tone: number;\n /**\n * The tone comes from the light side alone — an `auto` tone or a chain of\n * `auto` deltas on one — so it equals the light tone wherever the light\n * window is the identity.\n */\n lightSide: boolean;\n}\n\n/**\n * Defs anchored at their authored tone whatever their mode (see `darkAnchor`).\n * A `glaze.color()` token's hidden seed is `static` only so that its token's\n * `contrast` floor measures against the literal input; a delta on it still\n * steps in dark like one on an `auto` color authored at that tone.\n */\nconst authoredToneAnchors = new WeakSet<ColorDef>();\n\n/**\n * Anchor `def` at its authored tone in dark, whatever its mode (internal, for\n * a token's hidden seed; see `authoredToneAnchors`).\n */\nexport function anchorAtAuthoredTone<T extends ColorDef>(def: T): T {\n authoredToneAnchors.add(def);\n return def;\n}\n\n/**\n * The base of a tone-less, contrast-less `auto` color, which takes its base's\n * dark anchor as is; `undefined` for any other def.\n */\nfunction aliasBaseOf(def: ColorDef | undefined): string | undefined {\n if (def === undefined || isMixDef(def) || isLightingDef(def)) {\n return undefined;\n }\n const regDef = def as RegularColorDef;\n if (\n (regDef.mode ?? 'auto') !== 'auto' ||\n regDef.contrast !== undefined ||\n regDef.tone !== undefined ||\n regDef.from !== undefined\n ) {\n return undefined;\n }\n return regDef.base;\n}\n\n/**\n * An external base's dark-delta anchor for one pass, read in the base's own\n * resolve context (see `darkAnchorOf`), with the config it was read under.\n */\nexport interface ExternalDarkAnchor {\n tone: number;\n /** The base's effective config, whose dark window placed the base. */\n config: GlazeConfigResolved;\n}\n\n/**\n * An external base's dark-delta anchor for one pass, supplied by the base's\n * own `glaze.color()` token (internal).\n */\nexport type DarkAnchorHook = (isHighContrast: boolean) => ExternalDarkAnchor;\n\nexport interface ResolveContext extends GlazeThemeSeed {\n defs: ColorMap;\n resolved: Map<string, ResolvedColor>;\n /** Fully-merged effective config for this resolve pass. */\n config: GlazeConfigResolved;\n /** Per-name role memo (filled lazily by `resolveRole`). */\n roles: Map<string, Role>;\n /**\n * `unmetKey` of every regular-color variant whose contrast solve came back\n * unmet, so `verifyContrastDrift` doesn't repeat the solver's warning.\n */\n unmet: Set<string>;\n /** Per-name `darkAnchor` memo for the normal and high-contrast passes. */\n anchors: [Map<string, DarkAnchor>, Map<string, DarkAnchor>];\n /** Dark-delta anchors of external bases, supplied by their own tokens. */\n externalAnchors?: Map<string, DarkAnchorHook>;\n}\n\n/** The part of a `ResolveContext` that `darkAnchor` reads. */\ntype AnchorContext = Pick<\n ResolveContext,\n 'defs' | 'resolved' | 'config' | 'anchors' | 'externalAnchors'\n>;\n\ntype ResolvedField = 'light' | 'dark' | 'lightContrast' | 'darkContrast';\n\n/** An OKHSL-lightness-shaped variant used at the mix / shadow / glow edge. */\ninterface OkhslVariant {\n h: number;\n s: number;\n l: number;\n alpha: number;\n /** Carried from the resolved variant so edge conversions reuse the right gamut. */\n pastel?: boolean;\n}\n\nexport function getSchemeVariant(\n color: ResolvedColor,\n isDark: boolean,\n isHighContrast: boolean,\n): ResolvedColorVariant {\n if (isDark && isHighContrast) return color.darkContrast;\n if (isDark) return color.dark;\n if (isHighContrast) return color.lightContrast;\n return color.light;\n}\n\n/** Edge adapter: resolved variant (`t`) → OKHSL-lightness variant. */\nfunction toOkhslVariant(v: ResolvedColorVariant): OkhslVariant {\n const c = variantToOkhsl(v);\n return { h: c.h, s: c.s, l: c.l, alpha: v.alpha, pastel: v.pastel };\n}\n\n/** Edge adapter: OKHSL-lightness variant → resolved variant (`t`). */\nfunction toToneVariant(v: OkhslVariant): ResolvedColorVariant {\n const c = okhslToOkhst({ h: v.h, s: v.s, l: v.l });\n return { h: c.h, s: c.s, t: c.t, alpha: v.alpha };\n}\n\n// ============================================================================\n// Role resolution\n// ============================================================================\n\n/**\n * Resolve the role of a base color referenced by `baseName`, returning the\n * role the *dependent* color should take (the opposite of the base's role).\n * A base that lives in `defs` recursively resolves and is inverted via\n * `oppositeRole`; an external base (no local def, e.g. an injected standalone\n * token) is treated as a background, so the dependent defaults to foreground\n * (`'text'`).\n */\nfunction resolveBaseRoleInMap(\n baseName: string | undefined,\n defs: ColorMap,\n inferRole: boolean,\n roles: Map<string, Role>,\n): Role | undefined {\n if (!baseName) return undefined;\n const baseDef = defs[baseName];\n if (!baseDef) return 'text';\n return oppositeRole(\n resolveRoleInMap(baseName, baseDef, defs, inferRole, roles),\n );\n}\n\n/**\n * Role-resolution core that does not need a full `ResolveContext`. Shared by\n * the resolver (via `resolveRole`) and `verifyContrastDrift`.\n */\nfunction resolveRoleInMap(\n name: string,\n def: ColorDef,\n defs: ColorMap,\n inferRole: boolean,\n roles: Map<string, Role>,\n): Role {\n const cached = roles.get(name);\n if (cached) return cached;\n\n let role: Role | undefined;\n if (isLightingDef(def)) {\n role = 'surface';\n } else if (isMixDef(def)) {\n role =\n normalizeRole(def.role) ??\n (inferRole ? inferRoleFromName(name) : undefined) ??\n resolveBaseRoleInMap(def.base, defs, inferRole, roles) ??\n 'text';\n } else {\n const regDef = def as RegularColorDef;\n role =\n normalizeRole(regDef.role) ??\n (inferRole ? inferRoleFromName(name) : undefined) ??\n resolveBaseRoleInMap(regDef.base, defs, inferRole, roles) ??\n 'text';\n }\n\n const finalRole = role ?? 'text';\n roles.set(name, finalRole);\n return finalRole;\n}\n\n/**\n * Resolve a color's semantic `role` (text / surface / border) per the chain:\n * 1. explicit `def.role` (normalized)\n * 2. inferred from the color name when `config.inferRole` is on\n * 3. opposite of the base's role\n * 4. `'text'` (foreground) default\n *\n * Memoized on `ctx.roles` so the four scheme passes share one resolution.\n * Shadows and glows have no contrast participation and default to `'surface'`.\n */\nfunction resolveRole(name: string, def: ColorDef, ctx: ResolveContext): Role {\n return resolveRoleInMap(name, def, ctx.defs, ctx.config.inferRole, ctx.roles);\n}\n\nfunction resolveContrastSpec(\n spec: HCPair<ContrastSpec>,\n isHighContrast: boolean,\n config: GlazeConfigResolved,\n polarity?: 'fg' | 'bg',\n): ResolvedContrast {\n if (!isHighContrast && contrastFraction(config) !== undefined) {\n // A defined fraction proves the level is a finite number, not `'auto'`.\n return resolveContrastForLevel(\n spec,\n config.contrastLevel as number,\n polarity,\n );\n }\n const outerExplicitHC = Array.isArray(spec);\n const outer = isHighContrast ? pairHC(spec) : pairNormal(spec);\n return resolveContrastForMode(\n outer,\n isHighContrast,\n polarity,\n outerExplicitHC,\n );\n}\n\n/**\n * The authored tone for this pass: the pair's own entry in `'auto'` mode, or\n * the manual-level interpolation. Returns the parsed struct so the `kind` —\n * which selects the branch in `resolveDependentColor` — is fixed here once.\n */\nfunction passTone(\n tone: HCPair<ToneValue>,\n isHighContrast: boolean,\n config: GlazeConfigResolved,\n): { kind: 'absolute' | 'relative' | 'extreme'; value: number } {\n const f = contrastFraction(config);\n return f === undefined || isHighContrast\n ? parseToneValue(isHighContrast ? pairHC(tone) : pairNormal(tone))\n : parseToneValueAt(tone, f);\n}\n\n/** The authored numeric pair for this pass (shadow / glow `intensity`, mix `value`). */\nfunction passNumber(\n p: HCPair<number>,\n isHighContrast: boolean,\n config: GlazeConfigResolved,\n): number {\n const f = contrastFraction(config);\n if (f === undefined || isHighContrast) {\n return isHighContrast ? pairHC(p) : pairNormal(p);\n }\n return numberAt(p, f);\n}\n\n/**\n * Apply the relative-tone delta against a base, honoring `flip`.\n *\n * When `flip` is on and `base + delta` falls outside `[0, 100]`, try mirroring\n * the delta to the other side of the base. If the mirrored target is also out\n * of range, keep the original delta so the caller clamps on the authored side.\n * When off, the caller clamps as usual.\n */\nfunction applyToneFlip(delta: number, baseTone: number, flip: boolean): number {\n if (!flip) return delta;\n const target = baseTone + delta;\n if (target >= 0 && target <= 100) return delta;\n const mirrored = baseTone - delta;\n if (mirrored >= 0 && mirrored <= 100) return -delta;\n return delta;\n}\n\n/**\n * Dark position for an extreme tone (`'max'` / `'min'`) anchored to a base.\n *\n * A windowed dark remap compresses the base→extreme span, so the pair loses\n * contrast in dark. Instead, measure the tone shift the light scheme applied\n * between the base and the extreme, then replay it against the base's dark\n * tone: `auto` mirrors the sign (both ends invert), `fixed` keeps it. The\n * result is clamped to `[0, 100]` only — crossing the dark tone window is\n * intended, since the author asked for the extreme.\n */\nfunction extremeDarkTone(\n authorTone: number,\n mode: AdaptationMode,\n isHighContrast: boolean,\n baseResolved: ResolvedColor,\n config: GlazeConfigResolved,\n): number {\n const extremeLightTone = mapToneForScheme(\n authorTone,\n mode,\n false,\n isHighContrast,\n config,\n );\n const lightBase = getSchemeVariant(baseResolved, false, isHighContrast);\n const darkBase = getSchemeVariant(baseResolved, true, isHighContrast);\n const shift = extremeLightTone - lightBase.t * 100;\n return clamp(darkBase.t * 100 + (mode === 'auto' ? -shift : shift), 0, 100);\n}\n\n/**\n * Hue, absolute saturation (0–1) and tone (0–100) read off a color def's `from`.\n *\n * Deliberately not memoized. Keying a cache on the def object looks free — a\n * resolve reads this a handful of times per color — but defs are stored by\n * reference, so mutating one in place and re-setting it would invalidate the\n * theme's own cache while a def-keyed cache quietly served the old color. The\n * parse is a few microseconds against a resolve that is already cached; that is\n * not a trade worth a staleness bug.\n */\nfunction fromSeed(\n def: RegularColorDef,\n): { hue: number; saturation: number; tone: number } | undefined {\n if (def.from === undefined) return undefined;\n\n // `toTone` already returns the 0–100 tone; `s` stays the OKHSL 0–1 saturation\n // the resolver emits.\n const { h, s, l } = extractOkhslFromValue(def.from);\n\n return { hue: h, saturation: s, tone: toTone(l) };\n}\n\n/**\n * The config this color resolves against.\n *\n * A `from` color carries a literal value, so its light variant has to survive\n * the light tone window intact — hence a local `lightTone: false`, the same\n * default the value-shorthand form of `glaze.color()` applies. Only the light\n * window is dropped: dark and high contrast keep theirs, because that is where\n * the color is expected to adapt.\n */\nfunction configForColor(\n def: RegularColorDef,\n config: GlazeConfigResolved,\n): GlazeConfigResolved {\n if (def.from === undefined) return config;\n\n return { ...config, lightTone: false };\n}\n\nfunction resolveRootColor(\n def: RegularColorDef,\n isHighContrast: boolean,\n config: GlazeConfigResolved,\n): number {\n // Root tone is absolute or extreme ('max' = 100, 'min' = 0); both flow\n // through mapToneForScheme (and invert in dark under mode 'auto').\n if (def.tone === undefined) return clamp(fromSeed(def)!.tone, 0, 100);\n\n const parsed = passTone(def.tone, isHighContrast, config);\n return clamp(parsed.value, 0, 100);\n}\n\n/**\n * Effective hue and saturation for one color in one scheme.\n *\n * Dark schemes read the dark seed pair and the color's `darkHue` /\n * `darkSaturation`, each falling back to its light counterpart. An explicit\n * dark saturation — on the seed or the def — is taken literally; the global\n * `darkDesaturation` reduction applies only when neither is authored.\n * `mode: 'static'` pins one value across every scheme, so it skips all of it.\n *\n * Shared by `resolveColorForScheme` (the emitted variant) and\n * `resolveDependentColor` (the contrast solver's inputs) so the solver always\n * measures the color it is actually going to produce.\n */\nfunction resolveChannels(\n def: RegularColorDef,\n ctx: ResolveContext,\n isDark: boolean,\n): { hue: number; saturation: number } {\n const mode = def.mode ?? 'auto';\n const satFactor = clamp(def.saturation ?? 1, 0, 1);\n\n // A `from` color carries its own hue and an ABSOLUTE saturation, so it stands\n // outside the seed entirely: the theme seed is a ceiling for every other color\n // (`saturation` is a 0–1 factor of it), and a literal color has to be able to\n // exceed it or the caller would have to re-seed the theme to be honored.\n // An explicit `hue` / `saturation` on the same def still wins — those are the\n // more specific instruction, and `saturation` keeps its factor-of-seed meaning.\n const seed = fromSeed(def);\n const fromHue =\n seed !== undefined && def.hue === undefined ? seed.hue : undefined;\n const fromSaturation =\n seed !== undefined && def.saturation === undefined\n ? seed.saturation\n : undefined;\n\n if (!isDark || mode === 'static') {\n return {\n hue: fromHue ?? resolveEffectiveHue(ctx.hue, def.hue),\n saturation:\n fromSaturation ?? clamp((satFactor * ctx.saturation) / 100, 0, 1),\n };\n }\n\n const darkSeedSaturation = ctx.darkSaturation ?? ctx.saturation;\n const darkFactor = clamp(def.darkSaturation ?? satFactor, 0, 1);\n // Dark keeps the color's own saturation as its starting point too, but unlike\n // light it is still subject to `darkDesaturation` — dark is where the color is\n // allowed to move, so the global haircut applies as it does to any other color.\n const fromDark =\n fromSaturation !== undefined && def.darkSaturation === undefined;\n const raw = fromDark\n ? fromSaturation\n : (darkFactor * darkSeedSaturation) / 100;\n // A theme-level `darkSaturation` only counts as \"authored\" for a color that\n // actually reads the seed. A `from` color does not, so letting the theme's\n // value suppress the haircut here would leave the same color MORE saturated in\n // dark than it is in a theme that never set one.\n const explicitDark = fromDark\n ? false\n : def.darkSaturation !== undefined || ctx.darkSaturation !== undefined;\n\n return {\n hue:\n fromHue !== undefined && def.darkHue === undefined\n ? fromHue\n : resolveEffectiveHue(ctx.darkHue ?? ctx.hue, def.darkHue ?? def.hue),\n saturation: clamp(\n explicitDark ? raw : mapSaturationDark(raw, mode, ctx.config),\n 0,\n 1,\n ),\n };\n}\n\n/**\n * Whether a light-side anchor reads the stored light tone in this pass: high\n * contrast or a level at 100 at the reference light eps, where the light window\n * bypasses to the full range and is the identity. Those passes have always\n * stepped dark deltas from the light tone, so reading it as stored keeps them\n * bit-identical (recomputing the authored tone differs by float noise, which\n * can flip a tie-broken contrast solve). A normal pass has always read the\n * authored tone as is, so it keeps doing so even where its window is the\n * identity too (`lightTone: false` / `[0, 100]`). Read off the theme's config,\n * not a color's: a `from` color drops its own light window.\n */\nfunction readsStoredLightTone(\n isHighContrast: boolean,\n config: GlazeConfigResolved,\n): boolean {\n if (normalizeToneWindow(config.lightTone).eps !== REF_EPS) return false;\n return isHighContrast || hcMirrorsNormal(config);\n}\n\n/**\n * Where a step of `delta` from `anchor` lands on the authored scale: clamped to\n * `0–100`, widened to reach an anchor past the dark window (a base a contrast\n * floor, an extreme's replay, or its own fixed / static placement put there).\n * A step back toward the scale then moves by the full delta, and one that\n * points further out stops at the anchor — the base itself — instead of\n * snapping back to the window's edge. Either way a step stops at the window's\n * edge or at its base, whichever is further out, so the result moves\n * continuously as the base crosses the edge.\n */\nfunction stepFromAnchor(anchor: number, delta: number): number {\n return clamp(anchor + delta, Math.min(0, anchor), Math.max(100, anchor));\n}\n\n/**\n * Where a color sits on the authored `0–100` tone scale in one pass: the tone\n * an `auto` color would be authored at to land where this one sits in dark. In\n * dark, an `auto` tone delta steps from its base's anchor, so the dark step is\n * the dark window's scale times the delta on every base.\n *\n * - An `auto` color placed by a tone (a root, an absolute tone, a `from` value,\n * an extreme with no base) returns that tone as authored for the pass.\n * - An `auto` tone delta returns its base's anchor plus the delta\n * (`stepFromAnchor`), flipped exactly as the light pass flipped it on the\n * base's light tone, so a chain of deltas steps evenly. An `auto` color with\n * no tone of its own returns its base's.\n * - Any other color — one whose dark tone is not the inversion of an authored\n * tone: a `fixed` / `static` color (which keeps its side, or rides its base\n * with its delta's sign kept), an `auto` contrast-solved color, an `auto`\n * extreme on a base (which replays its light shift), a mix — returns its own\n * dark tone taken back through the dark window (`unmapDarkTone`). So an\n * `auto` dependent mirrors around wherever its base sits in dark, inverting\n * per its own mode. That falls outside `0–100` when the color sits past the\n * window; a step from it stays off the scale until it comes back\n * (`stepFromAnchor`, `mapDarkToneUnclamped`), so it does not snap to the\n * window's edge.\n * - An external base (a `glaze.color()` link) supplies its own anchor, read in\n * its own resolve context (`ctx.externalAnchors`), when its active dark window\n * is this pass's. A base under another dark window — or one with no hook — is\n * read back through this pass's dark window, so a `'+0'` lands on it and the\n * step is this window's scale times the delta.\n * - A token's hidden seed (`anchorAtAuthoredTone`) is `static`, but returns its\n * tone as authored, like an `auto` color placed by a tone, so a delta on it\n * inverts in dark as it would from the same color in a theme.\n *\n * In high contrast and at `contrastLevel: 100` at the reference light eps\n * (`readsStoredLightTone`), a light-side color's light tone *is* its authored\n * tone, so it is read as stored. That keeps those passes bit-identical to the\n * light-tone anchor they have always used, as a normal pass stays on the\n * authored tone it has always used.\n *\n * Memoized per resolve and pass on `ctx.anchors`, so a long chain of deltas\n * resolves in linear time without deep recursion: the dark passes run in topo\n * order, so a base's anchor is cached before its dependents ask for it. A\n * tone-less alias never asks for its own, so a chain of aliases is walked in a\n * loop instead.\n */\nfunction darkAnchor(\n name: string,\n ctx: AnchorContext,\n isHighContrast: boolean,\n): DarkAnchor {\n const memo = ctx.anchors[isHighContrast ? 1 : 0];\n const cached = memo.get(name);\n if (cached) return cached;\n\n if (aliasBaseOf(ctx.defs[name]) !== undefined) {\n const chain: string[] = [];\n let target = name;\n for (\n let base = aliasBaseOf(ctx.defs[target]);\n base !== undefined && !memo.has(target);\n base = aliasBaseOf(ctx.defs[target])\n ) {\n chain.push(target);\n target = base;\n }\n let anchor = darkAnchor(target, ctx, isHighContrast);\n for (let i = chain.length - 1; i >= 0; i--) {\n anchor = withStoredLightTone(chain[i], anchor, ctx, isHighContrast);\n memo.set(chain[i], anchor);\n }\n return anchor;\n }\n\n const color = ctx.resolved.get(name)!;\n const fromDark = (config: GlazeConfigResolved): DarkAnchor => ({\n tone: unmapDarkTone(\n getSchemeVariant(color, true, isHighContrast).t * 100,\n 'auto',\n isHighContrast,\n config,\n ),\n lightSide: false,\n });\n\n let anchor: DarkAnchor;\n const def: ColorDef | undefined = ctx.defs[name];\n if (def === undefined) {\n const external = ctx.externalAnchors?.get(name)?.(isHighContrast);\n anchor =\n external === undefined ||\n !sameDarkWindow(isHighContrast, external.config, ctx.config)\n ? fromDark(ctx.config)\n : { tone: external.tone, lightSide: false };\n } else if (isMixDef(def) || isLightingDef(def)) {\n anchor = fromDark(ctx.config);\n } else {\n const regDef = def as RegularColorDef;\n const mode = regDef.mode ?? 'auto';\n const config = configForColor(regDef, ctx.config);\n const rawTone = regDef.tone ?? fromSeed(regDef)?.tone;\n const parsed =\n rawTone === undefined\n ? undefined\n : passTone(rawTone, isHighContrast, config);\n\n if (\n (mode !== 'auto' && !authoredToneAnchors.has(regDef)) ||\n regDef.contrast !== undefined\n ) {\n anchor = fromDark(config);\n } else if (parsed === undefined) {\n anchor = darkAnchor(regDef.base!, ctx, isHighContrast);\n } else if (parsed.kind === 'relative') {\n const base = darkAnchor(regDef.base!, ctx, isHighContrast);\n const baseLightTone =\n getSchemeVariant(ctx.resolved.get(regDef.base!)!, false, isHighContrast)\n .t * 100;\n const flip = regDef.autoFlip ?? ctx.config.autoFlip;\n anchor = {\n tone: stepFromAnchor(\n base.tone,\n applyToneFlip(parsed.value, baseLightTone, flip),\n ),\n lightSide: base.lightSide,\n };\n } else if (parsed.kind === 'extreme' && regDef.base !== undefined) {\n anchor = fromDark(config);\n } else {\n anchor = { tone: clamp(parsed.value, 0, 100), lightSide: true };\n }\n }\n\n anchor = withStoredLightTone(name, anchor, ctx, isHighContrast);\n memo.set(name, anchor);\n return anchor;\n}\n\n/**\n * A light-side anchor read as the color's stored light tone where that is its\n * authored tone (`readsStoredLightTone`; see `darkAnchor`).\n */\nfunction withStoredLightTone(\n name: string,\n anchor: DarkAnchor,\n ctx: AnchorContext,\n isHighContrast: boolean,\n): DarkAnchor {\n if (!anchor.lightSide || !readsStoredLightTone(isHighContrast, ctx.config)) {\n return anchor;\n }\n const color = ctx.resolved.get(name)!;\n return {\n tone: getSchemeVariant(color, false, isHighContrast).t * 100,\n lightSide: true,\n };\n}\n\n/**\n * A resolved color's dark-delta anchor for one pass (see `darkAnchor`), read\n * after its resolve. This is what a `glaze.color()` token hands the resolver\n * (with its config, and cached per pass) when another token links to it as a\n * `base`, so the link steps from where the base sits under the base's own\n * windows and defs. Internal, not public API.\n */\nexport function darkAnchorOf(\n name: string,\n isHighContrast: boolean,\n source: {\n defs: ColorMap;\n config: GlazeConfigResolved;\n resolved: Map<string, ResolvedColor>;\n externalBases?: Map<string, ResolvedColor>;\n externalAnchors?: Map<string, DarkAnchorHook>;\n },\n): number {\n const resolved = new Map(source.externalBases);\n for (const [key, color] of source.resolved) resolved.set(key, color);\n return darkAnchor(\n name,\n {\n defs: source.defs,\n config: source.config,\n resolved,\n anchors: [new Map(), new Map()],\n externalAnchors: source.externalAnchors,\n },\n isHighContrast,\n ).tone;\n}\n\n/**\n * Which side of its base a tone sits on (both 0–100), or `undefined` when they\n * coincide. A gap within float noise counts as coinciding: a `'+0'` on a base\n * whose dark tone was read back through the dark window lands a few ulps off\n * it, and a strict comparison would let that noise pick the color's side.\n */\nfunction sideOfBase(\n tone: number,\n baseTone: number,\n): 'lighter' | 'darker' | undefined {\n if (Math.abs(tone - baseTone) < 1e-9) return undefined;\n return tone < baseTone ? 'darker' : 'lighter';\n}\n\nfunction resolveDependentColor(\n name: string,\n def: RegularColorDef,\n ctx: ResolveContext,\n isHighContrast: boolean,\n isDark: boolean,\n channels: { hue: number; saturation: number },\n polarity: 'fg' | 'bg',\n effectivePastel: boolean,\n): number {\n const baseName = def.base!;\n const baseResolved = ctx.resolved.get(baseName);\n if (!baseResolved) {\n throw new Error(\n `glaze: base \"${baseName}\" not yet resolved for \"${name}\".`,\n );\n }\n\n const mode = def.mode ?? 'auto';\n const flip = def.autoFlip ?? ctx.config.autoFlip;\n const pastel = effectivePastel;\n const config = configForColor(def, ctx.config);\n\n const baseVariant = getSchemeVariant(baseResolved, isDark, isHighContrast);\n const baseTone = baseVariant.t * 100;\n\n let preferredTone: number;\n let isExtreme = false;\n // A `from` color with no authored `tone` is placed at the tone it carries —\n // not at its base's, which is what an ordinary dependent color would inherit.\n const seed = fromSeed(def);\n const rawTone: HCPair<ToneValue> | undefined =\n def.tone ?? (seed !== undefined ? seed.tone : undefined);\n\n if (rawTone === undefined) {\n preferredTone = baseTone;\n } else {\n const parsed = passTone(rawTone, isHighContrast, config);\n\n if (parsed.kind === 'relative') {\n if (isDark && mode === 'auto') {\n const baseLightTone =\n getSchemeVariant(baseResolved, false, isHighContrast).t * 100;\n // Flip on the light scale, as the light pass did, so the dark step\n // mirrors the light one instead of picking a side of its own.\n const delta = applyToneFlip(parsed.value, baseLightTone, flip);\n // Step from where the base sits on the authored scale — the tone its\n // own dark variant is the inversion of — not from its light tone,\n // which carries the light window's lift (or, for a solved color or a\n // mix, sits wherever light put it). Either would land in the dark step\n // and make it uneven across bases.\n const anchor = darkAnchor(baseName, ctx, isHighContrast).tone;\n // Invert + remap the stepped tone into the dark window, exactly like\n // an absolute author tone under `mode: 'auto'` — past the window's\n // edge where the base itself sits past it.\n preferredTone = mapDarkToneUnclamped(\n stepFromAnchor(anchor, delta),\n isHighContrast,\n config,\n );\n } else {\n const delta = applyToneFlip(parsed.value, baseTone, flip);\n preferredTone = clamp(baseTone + delta, 0, 100);\n }\n } else {\n // Absolute or extreme ('max' = 100, 'min' = 0).\n isExtreme = parsed.kind === 'extreme';\n if (isExtreme && isDark && mode !== 'static') {\n // Replay the light-scheme shift so the base/extreme pair keeps its\n // contrast instead of being squeezed by the dark window.\n preferredTone = extremeDarkTone(\n parsed.value,\n mode,\n isHighContrast,\n baseResolved,\n config,\n );\n } else {\n preferredTone = mapToneForScheme(\n parsed.value,\n mode,\n isDark,\n isHighContrast,\n config,\n );\n }\n }\n }\n\n const rawContrast = def.contrast;\n if (rawContrast !== undefined) {\n const resolvedContrast = resolveContrastSpec(\n rawContrast,\n isHighContrast,\n config,\n polarity,\n );\n\n const baseOkhsl = toOkhslVariant(baseVariant);\n const baseLinearRgb = okhslToLinearSrgb(\n baseOkhsl.h,\n baseOkhsl.s,\n baseOkhsl.l,\n baseVariant.pastel ?? ctx.config.pastel,\n );\n\n // An extreme keeps its own position — clamping it back into the scheme\n // window would undo the shift the extreme asked for.\n const preferredRange = isExtreme\n ? ([0, 1] as const)\n : schemeToneRange(isDark, mode, isHighContrast, config);\n\n let initialDirection = sideOfBase(preferredTone, baseTone);\n\n const solve = {\n hue: channels.hue,\n saturation: channels.saturation,\n preferredTone: clamp(\n preferredTone / 100,\n preferredRange[0],\n preferredRange[1],\n ),\n baseLinearRgb,\n toneRange: [0, 1] as [number, number],\n flip,\n pastel,\n };\n\n // Under a manual contrast level, pin which side of the base the color sits\n // on so a slider can't send it leaping across its own base. The normal\n // passes only: a high-contrast pass has no ramp to be stable along, and it\n // must reproduce what `'auto'` resolves, which never probes.\n //\n // `autoFlip`'s tie-break is unstable along a ramp: when both sides meet the\n // floor it takes whichever lands nearer the anchor, and which side that is\n // shifts as the target grows. So the side is decided once — by a probe solve\n // at the *nearer endpoint's* target — and then preferred at every level in\n // that half of the ramp via `preferInitial`.\n //\n // Anchoring to the nearer endpoint is what keeps levels 0 and 100\n // bit-identical to the classic normal / high-contrast output: at an endpoint\n // the probe solves the very problem that pass would solve, so it reproduces\n // that side. `flip` stays on, so a pinned side that physically cannot reach\n // the target still falls back to the opposite one and the floor is met.\n // A color whose two endpoints genuinely disagree switches its preferred\n // side at level 50, where every other un-interpolable decision switches;\n // that fallback can still move it across earlier, or back and forth.\n const level = isHighContrast ? undefined : contrastFraction(config);\n let preferInitial = false;\n if (level !== undefined && level > 0 && level < 1) {\n const probe = findToneForContrast({\n ...solve,\n contrast: resolveContrastForLevel(\n rawContrast,\n level < PAIR_SWITCH ? 0 : 100,\n polarity,\n ),\n initialDirection,\n });\n initialDirection =\n sideOfBase(probe.tone * 100, baseTone) ?? initialDirection;\n preferInitial = true;\n }\n\n const result = findToneForContrast({\n ...solve,\n contrast: resolvedContrast,\n initialDirection,\n preferInitial,\n });\n\n if (!result.met) {\n ctx.unmet.add(unmetKey(name, isDark, isHighContrast));\n warnContrastUnmet(\n name,\n isDark,\n isHighContrast,\n resolvedContrast,\n result.contrast,\n );\n }\n\n return result.tone * 100;\n }\n\n return clamp(preferredTone, 0, 100);\n}\n\nfunction resolveColorForScheme(\n name: string,\n def: ColorDef,\n ctx: ResolveContext,\n isDark: boolean,\n isHighContrast: boolean,\n): ResolvedColorVariant {\n if (isLightingDef(def)) {\n return resolveLightingForScheme(name, def, ctx, isDark, isHighContrast);\n }\n\n if (isMixDef(def)) {\n return resolveMixForScheme(name, def, ctx, isDark, isHighContrast);\n }\n\n const regDef = def as RegularColorDef;\n const mode = regDef.mode ?? 'auto';\n // `from` supplies an absolute tone, so a color that carries one is a root even\n // with no authored `tone` — same as any other absolutely-placed color.\n const isRoot = hasAbsoluteTone(regDef) && !regDef.base;\n const channels = resolveChannels(regDef, ctx, isDark);\n const role = resolveRole(name, def, ctx);\n const polarity = roleToPolarity(role);\n const pastel = regDef.pastel ?? ctx.config.pastel;\n const config = configForColor(regDef, ctx.config);\n\n const finalTone = isRoot\n ? mapToneForScheme(\n resolveRootColor(regDef, isHighContrast, config),\n mode,\n isDark,\n isHighContrast,\n config,\n )\n : resolveDependentColor(\n name,\n regDef,\n ctx,\n isHighContrast,\n isDark,\n channels,\n polarity,\n pastel,\n );\n\n return {\n h: channels.hue,\n s: channels.saturation,\n t: clamp(finalTone / 100, 0, 1),\n alpha: regDef.opacity ?? 1,\n pastel,\n };\n}\n\n/**\n * Shadow / glow: solve the pigment opacity that lands this scheme's `bg`\n * exactly `intensity × k` tones darker / lighter. `bg` and `fg` are read per\n * scheme, so the object factor `k` adapts on its own in dark and high contrast.\n * A glow past white with `headroom` gets `hdr` (base in OKHST + exposure); the\n * same headroom applies in every scheme, high contrast included.\n */\nfunction resolveLightingForScheme(\n name: string,\n def: ShadowColorDef | GlowColorDef,\n ctx: ResolveContext,\n isDark: boolean,\n isHighContrast: boolean,\n): ResolvedColorVariant {\n const bgVariant = toOkhslVariant(\n getSchemeVariant(ctx.resolved.get(def.bg)!, isDark, isHighContrast),\n );\n const fgVariant = def.fg\n ? toOkhslVariant(\n getSchemeVariant(ctx.resolved.get(def.fg)!, isDark, isHighContrast),\n )\n : undefined;\n\n const intensity = passNumber(def.intensity, isHighContrast, ctx.config);\n const tuning = resolveLightingTuning(\n def.tuning,\n def.type === 'shadow' ? ctx.config.shadowTuning : ctx.config.glowTuning,\n );\n const pastel = def.pastel ?? ctx.config.pastel;\n const result = computeLighting(\n def.type,\n { ...bgVariant, pastel: bgVariant.pastel ?? ctx.config.pastel },\n fgVariant,\n intensity,\n tuning,\n pastel,\n );\n warnLightingShortfall(\n def.type,\n name,\n { isDark, isHighContrast },\n result,\n tuning.headroom,\n );\n\n const variant: ResolvedColorVariant = {\n ...toToneVariant({\n h: result.h,\n s: result.s,\n l: result.l,\n alpha: result.alpha,\n }),\n pastel,\n };\n if (result.hdr) variant.hdr = toResolvedHdr(result.hdr);\n return variant;\n}\n\nfunction okhslVariantToLinearRgb(v: OkhslVariant, pastel: boolean): LinearRgb {\n return okhslToLinearSrgb(v.h, v.s, v.l, pastel);\n}\n\n/** Saturation at or below which a mix endpoint counts as gray (no hue). */\nconst MIX_SAT_EPSILON = 1e-6;\n/** Lightness margin from 0 and 1 for re-reading a mix endpoint's saturation. */\nconst MIX_EXTREME_L = 1e-4;\n\n/**\n * Resolve hue for OKHSL mixing, handling achromatic colors.\n * When one color has no saturation, its hue is meaningless —\n * use the hue from the color that has saturation (matches CSS\n * color-mix \"missing component\" behavior).\n */\nfunction mixHue(base: OkhslVariant, target: OkhslVariant, t: number): number {\n const baseHasSat = base.s > MIX_SAT_EPSILON;\n const targetHasSat = target.s > MIX_SAT_EPSILON;\n\n if (baseHasSat && targetHasSat) return circularLerp(base.h, target.h, t);\n if (targetHasSat) return target.h;\n return base.h;\n}\n\nfunction linearSrgbLerp(\n base: LinearRgb,\n target: LinearRgb,\n t: number,\n): LinearRgb {\n return [\n base[0] + (target[0] - base[0]) * t,\n base[1] + (target[1] - base[1]) * t,\n base[2] + (target[2] - base[2]) * t,\n ];\n}\n\n/**\n * Linear sRGB → OKHSL in one saturation space. Channels are clamped to sRGB\n * first, and a pastel read caps saturation at the pastel limit (same hue and\n * lightness), so the result is a color that space can paint.\n */\nfunction linearRgbToOkhsl(rgb: LinearRgb, pastel: boolean): OkhslVariant {\n const [h, s, l] = srgbToOkhsl(toDisplayGamma(rgb), pastel);\n return { h, s, l, alpha: 1, pastel };\n}\n\nfunction resolveMixForScheme(\n name: string,\n def: MixColorDef,\n ctx: ResolveContext,\n isDark: boolean,\n isHighContrast: boolean,\n): ResolvedColorVariant {\n const baseResolved = ctx.resolved.get(def.base)!;\n const targetResolved = ctx.resolved.get(def.target)!;\n const baseVariant = toOkhslVariant(\n getSchemeVariant(baseResolved, isDark, isHighContrast),\n );\n const targetVariant = toOkhslVariant(\n getSchemeVariant(targetResolved, isDark, isHighContrast),\n );\n\n const rawValue = passNumber(def.value, isHighContrast, ctx.config);\n let t = clamp(rawValue, 0, 100) / 100;\n\n const blend = def.blend ?? 'opaque';\n const space = def.space ?? 'okhsl';\n const role = resolveRole(name, def, ctx);\n const polarity = roleToPolarity(role);\n const pastel = def.pastel ?? ctx.config.pastel;\n const basePastel = baseVariant.pastel ?? ctx.config.pastel;\n const targetPastel = targetVariant.pastel ?? ctx.config.pastel;\n // What each endpoint paints, under its own flag.\n const baseLinear = okhslVariantToLinearRgb(baseVariant, basePastel);\n const targetLinear = okhslVariantToLinearRgb(targetVariant, targetPastel);\n\n // `pastel` sets the gamut of the mixed result, so an endpoint under the\n // other flag has its saturation re-read in the mix's space from the same\n // OKLab color; hue and lightness carry over. A standard mix holds a pastel\n // endpoint exactly, and a pastel mix caps a vivid one at the pastel limit.\n const inMixSpace = (v: OkhslVariant, own: boolean): OkhslVariant => {\n // A gray (as `mixHue` counts one) has no saturation to re-read.\n if (own === pastel || v.s <= MIX_SAT_EPSILON) return v;\n // White and black have no chroma to measure in either space, so the\n // re-read runs just inside the lightness range, where it has converged:\n // their saturation still carries their hue, and the mix stays continuous\n // as an endpoint reaches tone 0 or 100.\n const l = clamp(v.l, MIX_EXTREME_L, 1 - MIX_EXTREME_L);\n const s = oklabToOkhsl(okhslToOklab(v.h, v.s, l, own), pastel)[1];\n return { ...v, s, pastel };\n };\n\n // `mixAt(v)` is the color the mix emits at value `v` and `paintAt(v)` what\n // it paints. The contrast search measures `paintAt`, so the floor holds on\n // the emitted color.\n let mixAt: (v: number) => OkhslVariant;\n let paintAt: (v: number) => LinearRgb;\n\n if (blend === 'transparent') {\n // The overlay is the target in the mix's gamut, composited by the browser\n // over the base as painted.\n const overlay = inMixSpace(targetVariant, targetPastel);\n const baseGamma = toDisplayGamma(baseLinear);\n const overlayGamma = toDisplayGamma(\n okhslVariantToLinearRgb(overlay, pastel),\n );\n mixAt = (v) => ({ ...overlay, alpha: clamp(v, 0, 1) });\n paintAt = (v) => compositeOverGamma(baseGamma, overlayGamma, v);\n } else if (space === 'srgb') {\n // The lerp runs between the painted endpoints and is emitted in the mix's\n // space. The standard gamut holds every lerp (sRGB is convex), so only a\n // pastel mix can clamp one, at the pastel limit (saturation 1), and only\n // a clamped lerp is measured as emitted.\n const lerpAt = (v: number) => linearSrgbLerp(baseLinear, targetLinear, v);\n mixAt = (v) => linearRgbToOkhsl(lerpAt(v), pastel);\n paintAt = pastel\n ? (v) => {\n const mixed = mixAt(v);\n return mixed.s < 1 ? lerpAt(v) : okhslVariantToLinearRgb(mixed, true);\n }\n : lerpAt;\n } else {\n const from = inMixSpace(baseVariant, basePastel);\n const to = inMixSpace(targetVariant, targetPastel);\n mixAt = (v) => ({\n h: mixHue(from, to, v),\n s: clamp(from.s + (to.s - from.s) * v, 0, 1),\n l: clamp(from.l + (to.l - from.l) * v, 0, 1),\n alpha: 1,\n });\n paintAt = (v) => okhslVariantToLinearRgb(mixAt(v), pastel);\n }\n\n if (def.contrast !== undefined) {\n const resolvedContrast = resolveContrastSpec(\n def.contrast,\n isHighContrast,\n ctx.config,\n polarity,\n );\n const metric = resolvedContrast.metric;\n\n const result = findValueForMixContrast({\n preferredValue: t,\n baseLinearRgb: baseLinear,\n contrast: resolvedContrast,\n luminanceAtValue: (v) => metricLuminance(metric, paintAt(v)),\n flip: ctx.config.autoFlip,\n });\n t = result.value;\n\n // Unmet means even the pure target falls short of the floor. The mix\n // settles at the end of the range it searched; say so like a regular\n // color does (deduped, with the same slack, so a rounding miss stays quiet).\n if (!result.met) {\n warnMixContrastUnmet(\n name,\n isDark,\n isHighContrast,\n resolvedContrast,\n result.contrast,\n // Blame the pastel cap only when the target painted in full would\n // meet the floor.\n pastel &&\n !targetPastel &&\n metricScore(\n metric,\n metricLuminance(metric, targetLinear),\n metricLuminance(metric, baseLinear),\n resolvedContrast.polarity,\n ) >= resolvedContrast.target,\n );\n }\n }\n\n return { ...toToneVariant(mixAt(t)), pastel };\n}\n\nfunction defMode(def: ColorDef): AdaptationMode | undefined {\n if (isLightingDef(def) || isMixDef(def)) return undefined;\n return (def as RegularColorDef).mode ?? 'auto';\n}\n\n/**\n * Run a single resolve pass over all local names. Pass 1 lazily creates\n * each `ResolvedColor` (all four slots seeded with the just-resolved\n * variant) the first time it sees a name; later passes update the\n * `target` slot on the existing record.\n */\nfunction runPass(\n order: string[],\n defs: ColorMap,\n ctx: ResolveContext,\n isDark: boolean,\n isHighContrast: boolean,\n target: ResolvedField,\n): Map<string, ResolvedColorVariant> {\n const out = new Map<string, ResolvedColorVariant>();\n for (const name of order) {\n const variant = resolveColorForScheme(\n name,\n defs[name],\n ctx,\n isDark,\n isHighContrast,\n );\n out.set(name, variant);\n const existing = ctx.resolved.get(name);\n if (existing) {\n ctx.resolved.set(name, { ...existing, [target]: variant });\n } else {\n ctx.resolved.set(name, {\n name,\n light: variant,\n dark: variant,\n lightContrast: variant,\n darkContrast: variant,\n mode: defMode(defs[name]),\n });\n }\n }\n return out;\n}\n\n/**\n * Re-seed a single variant slot with a previously-resolved map so the\n * upcoming pass reads sensible fallbacks via `getSchemeVariant`.\n */\nfunction seedField(\n order: string[],\n ctx: ResolveContext,\n field: ResolvedField,\n source: Map<string, ResolvedColorVariant>,\n): void {\n for (const name of order) {\n const existing = ctx.resolved.get(name)!;\n ctx.resolved.set(name, { ...existing, [field]: source.get(name)! });\n }\n}\n\n/** Key for `ResolveContext.unmet`: one color in one scheme. */\nfunction unmetKey(\n name: string,\n isDark: boolean,\n isHighContrast: boolean,\n): string {\n return `${name}|${isDark ? 'dark' : 'light'}|${isHighContrast ? 'hc' : ''}`;\n}\n\n/** Below this OKHSL saturation a variant is a gray: its tone is exact. */\nconst ACHROMATIC_EPSILON = 1e-6;\n\n/**\n * After the passes, surface chromatic contrast drift (the drift check in\n * docs/okhst.mdx): a color resolved with a `base` + `contrast` may land\n * slightly under the contrast its tone implies because chromatic luminance\n * drifts from the gray tone.\n *\n * Two kinds of variant are skipped. One the solver reported as unmet (`unmet`)\n * already got a \"cannot meet\" warning with the same measured value, and the\n * shortfall is an unreachable floor, not drift. An achromatic one (saturation\n * 0) has no chromatic luminance to drift, so the advisory's cause can't apply.\n *\n * Under a manual `contrastLevel` the spec is resolved at the level, so the check\n * measures each normal variant against the target it was actually solved for. At\n * level 100 the high-contrast slots are mirrors and are skipped: the normal\n * schemes already carry that check, and repeating it would emit a byte-identical\n * advisory under a different scheme label, which dedupes as a separate key.\n */\nfunction verifyContrastDrift(\n order: string[],\n defs: ColorMap,\n result: Map<string, ResolvedColor>,\n config: GlazeConfigResolved,\n unmet: ReadonlySet<string>,\n): void {\n const roles = new Map<string, Role>();\n for (const name of order) {\n const def = defs[name];\n if (isLightingDef(def) || isMixDef(def)) continue;\n const regDef = def as RegularColorDef;\n if (regDef.contrast === undefined || !regDef.base) continue;\n const color = result.get(name);\n const base = result.get(regDef.base);\n if (!color || !base) continue;\n\n const role = resolveRoleInMap(name, def, defs, config.inferRole, roles);\n const polarity = roleToPolarity(role);\n\n const schemes: {\n isDark: boolean;\n isHighContrast: boolean;\n field: ResolvedField;\n }[] = [\n { isDark: false, isHighContrast: false, field: 'light' },\n { isDark: false, isHighContrast: true, field: 'lightContrast' },\n { isDark: true, isHighContrast: false, field: 'dark' },\n { isDark: true, isHighContrast: true, field: 'darkContrast' },\n ];\n const mirrored = hcMirrorsNormal(config);\n\n for (const s of schemes) {\n // At level 100 the high-contrast slots are mirrors of the normal ones.\n if (mirrored && s.isHighContrast) continue;\n if (unmet.has(unmetKey(name, s.isDark, s.isHighContrast))) continue;\n const cVariant = color[s.field];\n if (cVariant.s <= ACHROMATIC_EPSILON) continue;\n const spec = resolveContrastSpec(\n regDef.contrast,\n s.isHighContrast,\n config,\n polarity,\n );\n const bVariant = base[s.field];\n const cOkhsl = toOkhslVariant(cVariant);\n const bOkhsl = toOkhslVariant(bVariant);\n // Measure in the spec's metric basis so the APCA warning compares APCA\n // luminances, not WCAG ones. Each variant carries its own effective\n // pastel flag so the gamut mapping matches what the resolver applied;\n // fall back to the config default for any variant without one.\n const cPastel = cVariant.pastel ?? config.pastel;\n const bPastel = bVariant.pastel ?? config.pastel;\n const yC = metricLuminance(\n spec.metric,\n okhslToLinearSrgb(cOkhsl.h, cOkhsl.s, cOkhsl.l, cPastel),\n );\n const yB = metricLuminance(\n spec.metric,\n okhslToLinearSrgb(bOkhsl.h, bOkhsl.s, bOkhsl.l, bPastel),\n );\n warnContrastDrift(name, s.isDark, s.isHighContrast, spec, yC, yB);\n }\n }\n}\n\nexport function resolveAllColors(\n seed: GlazeThemeSeed,\n defs: ColorMap,\n config: GlazeConfigResolved,\n externalBases?: Map<string, ResolvedColor>,\n externalAnchors?: Map<string, DarkAnchorHook>,\n): Map<string, ResolvedColor> {\n validateColorDefs(defs, externalBases);\n const order = topoSort(defs);\n\n const ctx: ResolveContext = {\n ...seed,\n defs,\n resolved: new Map(),\n config,\n roles: new Map(),\n unmet: new Set(),\n anchors: [new Map(), new Map()],\n externalAnchors,\n };\n\n // Pre-seed externally-resolved bases. The per-pass loops iterate only\n // `defs` keys (via `order`), so external entries persist across all\n // four passes and are read via `getSchemeVariant` per scheme.\n if (externalBases) {\n for (const [name, color] of externalBases) {\n ctx.resolved.set(name, color);\n }\n }\n\n // A manual contrast level positions the *normal* passes; the high-contrast\n // passes bypass it, so they run as usual and produce the same values `'auto'`\n // does. Level 100 is the one exception: there the normal passes already *are*\n // the high-contrast passes bit for bit, so the two are skipped and their slots\n // mirror the normal ones. That holds because within a pass a dependent reads\n // its base's same slot (topo order), and the only cross-scheme reads — the\n // relative-tone dark branch (`darkAnchor`) and `extremeDarkTone` — read\n // `light`, which equals `lightContrast` at 100, and every window they map or\n // unmap through is the same full-range literal in both.\n const mirrored = hcMirrorsNormal(config);\n\n // Pass 1: Light (normal, or at the level).\n const lightMap = runPass(order, defs, ctx, false, false, 'light');\n\n // Pass 2: Light high-contrast.\n let lightHCMap = lightMap;\n if (!mirrored) {\n seedField(order, ctx, 'lightContrast', lightMap);\n lightHCMap = runPass(order, defs, ctx, false, true, 'lightContrast');\n }\n\n // Pass 3: Dark (normal, or at the level).\n seedField(order, ctx, 'dark', lightMap);\n seedField(order, ctx, 'darkContrast', lightHCMap);\n const darkMap = runPass(order, defs, ctx, true, false, 'dark');\n\n // Pass 4: Dark high-contrast.\n let darkHCMap = darkMap;\n if (!mirrored) {\n seedField(order, ctx, 'darkContrast', darkMap);\n darkHCMap = runPass(order, defs, ctx, true, true, 'darkContrast');\n }\n\n const result = new Map<string, ResolvedColor>();\n for (const name of order) {\n result.set(name, {\n name,\n light: lightMap.get(name)!,\n dark: darkMap.get(name)!,\n lightContrast: lightHCMap.get(name)!,\n darkContrast: darkHCMap.get(name)!,\n mode: defMode(defs[name]),\n });\n }\n\n verifyContrastDrift(order, defs, result, config, ctx.unmet);\n\n return result;\n}\n\n// Re-export for callers that previously imported tone helpers from here.\nexport { fromTone, toTone };\n","/**\n * Output formatting for resolved color maps.\n *\n * Owns the CSS-string formatter dispatch table (`okhsl` / `rgb` / `hsl` /\n * `oklch`), the HDR glow writer (`formatHdrVariant`: extended `color(srgb …)`,\n * or `color(srgb-linear …)` on request), and the token-map shapes Glaze emits:\n * - `buildTokenMap` — Tasty style-to-state bindings (`#name` keys, state aliases).\n * - `buildFlatTokenMap` — `{ light, dark, ... }` per-variant maps.\n * - `buildJsonMap` — `{ name: { light, dark, ... } }` per-color JSON.\n * - `buildCssMap` — CSS custom property declaration strings per variant.\n * - `buildDtcgMap` — W3C DTCG (2025.10) token documents, one per scheme.\n * - `buildDtcgResolver` — W3C DTCG Resolver-Module document (one modifier, a context per scheme).\n * - `buildTailwindMap` — Tailwind v4 `@theme` block + dark/HC overrides.\n *\n * The HDR tier (`variant.hdr`, a glow past SDR white) is emitted only with\n * `modes.hdr` (`css()`: its `hdr` option), and always as a literal\n * `color(srgb R G B)` with channels past 1 — whatever `format`, even under\n * `splitHue`.\n * Without it every shape is byte-identical to SDR. Each shape carries it the\n * way its consumer composes values:\n * - Tasty: a sparse `hdr` state key after each SDR key that has one (`''`,\n * hdr, dark, dark & hdr, hc, hc & hdr, dark & hc, dark & hc & hdr). Tasty\n * gives later keys priority, so a dark key still beats the light HDR one.\n * - `json()`: sparse `lightHdr` / `darkHdr` / … keys per color.\n * - `tokens()` / `css()` / Tailwind: dense per-scheme HDR blocks — every\n * color with an HDR value in any (emitted) scheme, re-declared with its SDR\n * value where a scheme has none — so a cascade layering one HDR block over\n * the SDR ones can't leak a light HDR value into dark.\n * - DTCG: `$value` stays SDR; the HDR value rides in\n * `$extensions['me.tenphi.glaze'].hdr` of the scheme documents that have it.\n */\n\nimport {\n buildHueDeclarations,\n buildHuePlans,\n type ChannelCtx,\n type HuePlan,\n} from './channels';\nimport {\n formatHsl,\n formatOkhsl,\n formatOkhst,\n formatOklch,\n formatRgb,\n formatSrgb,\n formatSrgbLinear,\n okhslToOklch,\n okhslToSrgb,\n relativeLuminanceFromLinearRgb,\n sRGBLinearToGamma,\n srgbToHex,\n} from './okhsl-color-math';\nimport { okhstToOkhsl, toneFromY, variantToOkhsl } from './okhst';\nimport { hdrToLinearSrgb, hdrToSrgb } from './lighting';\nimport { getConfig } from './config';\nimport { hcMirrorsNormal } from './hc-pair';\nimport type {\n DtcgColorSpace,\n DtcgColorToken,\n DtcgColorValue,\n DtcgDocument,\n DtcgSrgbColorValue,\n DtcgTokenTree,\n GlazeColorFormat,\n GlazeCssResult,\n GlazeCssSchemeBlocks,\n GlazeDtcgHdr,\n GlazeDtcgResolverDocument,\n GlazeDtcgResolverOptions,\n GlazeDtcgResult,\n GlazeHdrFormat,\n GlazeOutputModes,\n ResolvedColor,\n ResolvedColorVariant,\n ResolvedHdr,\n} from './types';\n\nexport type { ChannelCtx } from './channels';\n\n/** The four scheme variants, in emission order. */\nexport const SCHEMES = [\n 'light',\n 'dark',\n 'lightContrast',\n 'darkContrast',\n] as const;\n\ntype Scheme = (typeof SCHEMES)[number];\n\n/** Key of a scheme's HDR counterpart (`lightHdr`, `darkHdr`, …). */\ntype HdrScheme = `${Scheme}Hdr`;\n\nfunction hdrKey(scheme: Scheme): HdrScheme {\n return `${scheme}Hdr`;\n}\n\n/** The scheme variants `modes` emits, in order. Light always. */\nfunction emittedSchemes(modes: Required<GlazeOutputModes>): Scheme[] {\n const schemes: Scheme[] = ['light'];\n if (modes.dark) schemes.push('dark');\n if (modes.highContrast) schemes.push('lightContrast');\n if (modes.dark && modes.highContrast) schemes.push('darkContrast');\n return schemes;\n}\n\n/**\n * Whether a color belongs in the dense HDR blocks: it has an HDR value in at\n * least one of `schemes`.\n */\nfunction hasHdrIn(color: ResolvedColor, schemes: readonly Scheme[]): boolean {\n return schemes.some((scheme) => color[scheme].hdr !== undefined);\n}\n\n/** Join per-scheme declaration lines into `css()` blocks. */\nexport function joinSchemeLines(\n lines: Record<Scheme, string[]>,\n): GlazeCssSchemeBlocks {\n return {\n light: lines.light.join('\\n'),\n dark: lines.dark.join('\\n'),\n lightContrast: lines.lightContrast.join('\\n'),\n darkContrast: lines.darkContrast.join('\\n'),\n };\n}\n\n/** Fresh, empty per-scheme declaration line buckets. */\nexport function emptySchemeLines(): Record<Scheme, string[]> {\n return { light: [], dark: [], lightContrast: [], darkContrast: [] };\n}\n\nconst formatters: Record<\n Exclude<GlazeColorFormat, 'okhst'>,\n (h: number, s: number, l: number, pastel: boolean) => string\n> = {\n okhsl: formatOkhsl,\n rgb: formatRgb,\n hsl: formatHsl,\n oklch: formatOklch,\n};\n\nfunction fmt(value: number, decimals: number): string {\n return parseFloat(value.toFixed(decimals)).toString();\n}\n\nexport function formatVariant(\n v: ResolvedColorVariant,\n format: GlazeColorFormat = 'oklch',\n pastel = false,\n): string {\n // Variants store canonical tone; convert to OKHSL lightness at the edge.\n // Per-variant `pastel` (set by the resolver from def or config fallback)\n // wins over the format-time fallback, so output matches resolution.\n const effectivePastel = v.pastel ?? pastel;\n\n let base: string;\n if (format === 'okhst') {\n base = formatOkhst(v.h, v.s, v.t, effectivePastel);\n } else {\n const { l } = variantToOkhsl(v);\n base = formatters[format](v.h, v.s, l, effectivePastel);\n }\n\n if (v.alpha >= 1) return base;\n const closing = base.lastIndexOf(')');\n return `${base.slice(0, closing)} / ${fmt(v.alpha, 4)})`;\n}\n\n/**\n * Format a variant's HDR value (`variant.hdr`, set on a glow past white with\n * `headroom`) as extended `color(srgb R G B)` (default) or\n * `color(srgb-linear R G B)` — the same color, with the brightest channel\n * past 1 — or `undefined` when it has none. One of these whatever the SDR\n * format: OKLCH lightness clamps at parse time and `rgb()` / `hsl()` cannot\n * pass white. Emitted as a literal, never with a split hue.\n */\nexport function formatHdrVariant(\n v: ResolvedColorVariant,\n format: GlazeHdrFormat = 'srgb',\n): string | undefined {\n if (format !== 'srgb' && format !== 'srgb-linear') {\n throw new Error(\n `glaze: unknown HDR format ${JSON.stringify(format)}. ` +\n `Use 'srgb' or 'srgb-linear'.`,\n );\n }\n if (v.hdr === undefined) return undefined;\n return format === 'srgb'\n ? formatSrgb(hdrToSrgb(v.hdr))\n : formatSrgbLinear(hdrToLinearSrgb(v.hdr));\n}\n\n/**\n * Format a resolved variant as `oklch(L C <hueVar>)`, splicing a CSS hue var\n * for `splitHue` exports. Falls back to inline when the plan is inline.\n */\nexport function formatVariantHue(\n v: ResolvedColorVariant,\n plan: HuePlan,\n pastel = false,\n): string {\n const effectivePastel = v.pastel ?? pastel;\n const { l } = variantToOkhsl(v);\n const [L, C] = okhslToOklch(v.h, v.s, l, effectivePastel);\n\n let base: string;\n if (plan.inline) {\n if (v.s <= 1e-6) {\n base = `oklch(${fmt(L, 4)} 0 0)`;\n } else {\n base = formatOklch(v.h, v.s, l, effectivePastel);\n }\n } else {\n base = `oklch(${fmt(L, 4)} ${fmt(C, 4)} ${plan.hueVar})`;\n }\n\n if (v.alpha >= 1) return base;\n const closing = base.lastIndexOf(')');\n return `${base.slice(0, closing)} / ${fmt(v.alpha, 4)})`;\n}\n\nfunction formatColorValue(\n v: ResolvedColorVariant,\n format: GlazeColorFormat,\n pastel: boolean,\n huePlan?: HuePlan,\n): string {\n if (format === 'oklch' && huePlan !== undefined) {\n return formatVariantHue(v, huePlan, pastel);\n }\n return formatVariant(v, format, pastel);\n}\n\n/**\n * Resolve the effective output modes for an export.\n *\n * `modes.highContrast` and `contrastLevel` are independent: the level positions\n * the normal variants, the high-contrast tier stays the true high-contrast\n * resolution, and the two compose — a slider raises the baseline while a\n * `prefers-contrast: more` block still escalates on top of it.\n *\n * The one exception is a **global** level of 100, where the normal variants\n * already *are* the high-contrast ones. The tier would be an exact duplicate, so\n * it is dropped and a single light/dark set is emitted — including against an\n * explicit `highContrast: true` override, which has nothing different left to\n * ask for.\n *\n * A level set on a single theme or token does not change which modes are\n * emitted: `modes` is global-only, and a palette must not have one sibling\n * collapse the shared token structure. A per-instance level of 100 therefore\n * still reports into the tier, with values equal to its own normal ones.\n */\nexport function resolveModes(\n override?: GlazeOutputModes,\n): Required<GlazeOutputModes> {\n const cfg = getConfig();\n const highContrast = override?.highContrast ?? cfg.modes.highContrast;\n return {\n dark: override?.dark ?? cfg.modes.dark,\n highContrast: highContrast && !hcMirrorsNormal(cfg),\n hdr: override?.hdr ?? cfg.modes.hdr,\n };\n}\n\n/**\n * Tasty state aliases. `hdr` falls back to the global `states.hdr` — a\n * `glaze.color()` token, which is never a glow, doesn't pass it.\n */\nexport interface TastyStates {\n dark: string;\n highContrast: string;\n hdr?: string;\n}\n\nexport function buildTokenMap(\n resolved: Map<string, ResolvedColor>,\n prefix: string,\n states: TastyStates,\n modes: Required<GlazeOutputModes>,\n format: GlazeColorFormat = 'oklch',\n pastel = false,\n channelCtx?: ChannelCtx,\n): Record<string, Record<string, string>> {\n const tokens: Record<string, Record<string, string>> = {};\n const huePlans =\n channelCtx !== undefined && format === 'oklch'\n ? buildHuePlans(resolved, channelCtx)\n : undefined;\n\n if (huePlans !== undefined && channelCtx !== undefined) {\n const hueDecls = buildHueDeclarations(resolved, channelCtx);\n for (const decl of hueDecls.light) {\n tokens[`$${decl.prop.slice(2)}`] = { '': decl.value };\n }\n // Hue vars must not outlive the modes gate the color values respect.\n if (modes.dark) {\n for (const decl of hueDecls.dark) {\n const key = `$${decl.prop.slice(2)}`;\n tokens[key] = { ...tokens[key], [states.dark]: decl.value };\n }\n }\n for (const [name, color] of resolved) {\n tokens[`#${prefix}${name}`] = buildTokenEntry(\n color,\n states,\n modes,\n format,\n pastel,\n huePlans.get(name),\n );\n }\n return tokens;\n }\n\n for (const [name, color] of resolved) {\n const key = `#${prefix}${name}`;\n tokens[key] = buildTokenEntry(color, states, modes, format, pastel);\n }\n\n return tokens;\n}\n\n/**\n * One color's Tasty state map. With `modes.hdr`, each SDR key whose variant\n * has an HDR value is followed by its `hdr` key (`states.hdr` alone after\n * `''`, `<key> & <hdr>` after the others), so the order is `''`, hdr, dark,\n * dark & hdr, hc, hc & hdr, dark & hc, dark & hc & hdr — only the HDR keys\n * that exist. Tasty gives later keys priority, so in a dark HDR context the\n * dark key (or its own HDR key) still beats the light HDR one.\n */\nfunction buildTokenEntry(\n color: ResolvedColor,\n states: TastyStates,\n modes: Required<GlazeOutputModes>,\n format: GlazeColorFormat,\n pastel: boolean,\n huePlan?: HuePlan,\n): Record<string, string> {\n const entry: Record<string, string> = {};\n const add = (key: string, v: ResolvedColorVariant): void => {\n entry[key] = formatColorValue(v, format, pastel, huePlan);\n if (modes.hdr && v.hdr !== undefined) {\n const hdrState = states.hdr ?? getConfig().states.hdr;\n entry[key === '' ? hdrState : `${key} & ${hdrState}`] =\n formatHdrVariant(v)!;\n }\n };\n\n add('', color.light);\n if (modes.dark) {\n add(states.dark, color.dark);\n }\n if (modes.highContrast) {\n add(states.highContrast, color.lightContrast);\n }\n if (modes.dark && modes.highContrast) {\n add(`${states.dark} & ${states.highContrast}`, color.darkContrast);\n }\n\n return entry;\n}\n\n/**\n * Per-scheme flat maps (`{ light, dark, … }`), gated by `modes`. With\n * `modes.hdr` each emitted scheme gains a dense `<scheme>Hdr` map right after\n * it (`light`, `lightHdr`, `dark`, `darkHdr`, …): every color with an HDR\n * value in any emitted scheme, its SDR value where that scheme has none.\n */\nexport function buildFlatTokenMap(\n resolved: Map<string, ResolvedColor>,\n prefix: string,\n modes: Required<GlazeOutputModes>,\n format: GlazeColorFormat = 'oklch',\n pastel = false,\n): Record<string, Record<string, string>> {\n const schemes = emittedSchemes(modes);\n const result: Record<string, Record<string, string>> = {};\n for (const scheme of schemes) {\n result[scheme] = {};\n if (modes.hdr) result[hdrKey(scheme)] = {};\n }\n\n for (const [name, color] of resolved) {\n const key = `${prefix}${name}`;\n const dense = modes.hdr && hasHdrIn(color, schemes);\n for (const scheme of schemes) {\n const v = color[scheme];\n const sdr = formatVariant(v, format, pastel);\n result[scheme][key] = sdr;\n if (dense) result[hdrKey(scheme)][key] = formatHdrVariant(v) ?? sdr;\n }\n }\n\n return result;\n}\n\n/**\n * Per-color JSON (`{ name: { light, dark, … } }`), gated by `modes`. With\n * `modes.hdr`, a variant with an HDR value adds a sparse `<scheme>Hdr` key\n * right after its SDR one (`light`, `lightHdr`, `dark`, …).\n */\nexport function buildJsonMap(\n resolved: Map<string, ResolvedColor>,\n modes: Required<GlazeOutputModes>,\n format: GlazeColorFormat = 'oklch',\n pastel = false,\n): Record<string, Record<string, string>> {\n const schemes = emittedSchemes(modes);\n const result: Record<string, Record<string, string>> = {};\n\n for (const [name, color] of resolved) {\n const entry: Record<string, string> = {};\n for (const scheme of schemes) {\n const v = color[scheme];\n entry[scheme] = formatVariant(v, format, pastel);\n if (modes.hdr && v.hdr !== undefined) {\n entry[hdrKey(scheme)] = formatHdrVariant(v)!;\n }\n }\n result[name] = entry;\n }\n\n return result;\n}\n\n/**\n * CSS custom-property declarations for all four schemes. With `hdr`, the\n * result gains dense `hdr` blocks: every color with an HDR value in any\n * scheme, re-declared in each block with that scheme's HDR value, or its\n * exact SDR declaration where the scheme has none.\n */\nexport function buildCssMap(\n resolved: Map<string, ResolvedColor>,\n prefix: string,\n suffix: string,\n format: GlazeColorFormat,\n pastel = false,\n channelCtx?: ChannelCtx,\n hdr = false,\n): GlazeCssResult {\n const lines = emptySchemeLines();\n const hdrLines = hdr ? emptySchemeLines() : undefined;\n\n const huePlans =\n channelCtx !== undefined && format === 'oklch'\n ? buildHuePlans(resolved, channelCtx)\n : undefined;\n\n if (huePlans !== undefined && channelCtx !== undefined) {\n const hueDecls = buildHueDeclarations(resolved, channelCtx);\n for (const decl of hueDecls.light) {\n lines.light.push(`${decl.prop}: ${decl.value};`);\n }\n for (const decl of hueDecls.dark) {\n lines.dark.push(`${decl.prop}: ${decl.value};`);\n lines.darkContrast.push(`${decl.prop}: ${decl.value};`);\n }\n }\n\n for (const [name, color] of resolved) {\n const prop = `--${prefix}${name}${suffix}`;\n const plan = huePlans?.get(name);\n const dense = hdrLines !== undefined && hasHdrIn(color, SCHEMES);\n for (const scheme of SCHEMES) {\n const v = color[scheme];\n const decl = `${prop}: ${formatColorValue(v, format, pastel, plan)};`;\n lines[scheme].push(decl);\n if (dense) {\n hdrLines[scheme].push(\n v.hdr !== undefined ? `${prop}: ${formatHdrVariant(v)};` : decl,\n );\n }\n }\n }\n\n const result: GlazeCssResult = joinSchemeLines(lines);\n if (hdrLines !== undefined) result.hdr = joinSchemeLines(hdrLines);\n return result;\n}\n\n// ============================================================================\n// DTCG (W3C Design Tokens Format Module 2025.10)\n// ============================================================================\n\nfunction roundTo(value: number, decimals: number): number {\n return parseFloat(value.toFixed(decimals));\n}\n\n/**\n * Build a DTCG `$value` color object for a resolved variant.\n *\n * `srgb` (default) emits gamma sRGB components in 0–1 plus a 6-digit `hex`\n * hint — the most universally understood form (Figma, Tokens Studio, Style\n * Dictionary). `oklch` emits `[L, C, H]` components with no hex — Glaze-native\n * and wide-gamut. `alpha` is included only when below 1.\n */\nexport function dtcgColorValue(\n v: ResolvedColorVariant,\n colorSpace: DtcgColorSpace = 'srgb',\n pastel = false,\n): DtcgColorValue {\n const effectivePastel = v.pastel ?? pastel;\n const { l } = variantToOkhsl(v);\n const alpha = v.alpha < 1 ? roundTo(v.alpha, 6) : undefined;\n\n if (colorSpace === 'oklch') {\n const [L, C, H] = okhslToOklch(v.h, v.s, l, effectivePastel);\n const value: DtcgColorValue = {\n colorSpace: 'oklch',\n components: [roundTo(L, 6), roundTo(C, 6), roundTo(H, 4)],\n };\n if (alpha !== undefined) value.alpha = alpha;\n return value;\n }\n\n const value = dtcgSrgbValue(v.h, v.s, l, effectivePastel);\n if (alpha !== undefined) value.alpha = alpha;\n return value;\n}\n\n/** A DTCG sRGB color value (gamma components, 6 decimals, plus `hex`). */\nfunction dtcgSrgbValue(\n h: number,\n s: number,\n l: number,\n pastel: boolean,\n): DtcgSrgbColorValue {\n const [r, g, b] = okhslToSrgb(h, s, l, pastel);\n return {\n colorSpace: 'srgb',\n components: [roundTo(r, 6), roundTo(g, 6), roundTo(b, 6)],\n hex: srgbToHex([r, g, b]),\n };\n}\n\n/** The `$extensions` namespace Glaze writes into DTCG tokens. */\nconst DTCG_EXTENSION_NAMESPACE = 'me.tenphi.glaze';\n\n/**\n * The DTCG form of an HDR value: `exposure` in stops, the luminance `tone`\n * it lands (past 100 unless `headroom` caps a saturated base short of it), the\n * opaque `base` as a DTCG sRGB color (always sRGB, whatever `colorSpace`, and\n * never pastel — the base is standard OKHSL), and the HDR color as extended\n * sRGB components (the numbers of `glaze.formatHdr()`), the brightest above 1.\n */\nfunction dtcgHdrValue(hdr: ResolvedHdr): GlazeDtcgHdr {\n const linear = hdrToLinearSrgb(hdr);\n const { h, s, l } = okhstToOkhsl(hdr);\n return {\n exposure: roundTo(hdr.exposure, 6),\n tone: roundTo(toneFromY(relativeLuminanceFromLinearRgb(linear)), 4),\n base: dtcgSrgbValue(h, s, l, false),\n value: {\n colorSpace: 'srgb',\n components: [\n roundTo(sRGBLinearToGamma(linear[0]), 6),\n roundTo(sRGBLinearToGamma(linear[1]), 6),\n roundTo(sRGBLinearToGamma(linear[2]), 6),\n ],\n },\n };\n}\n\nfunction dtcgToken(\n v: ResolvedColorVariant,\n colorSpace: DtcgColorSpace,\n pastel: boolean,\n hdr: boolean,\n): DtcgColorToken {\n const token: DtcgColorToken = {\n $type: 'color',\n $value: dtcgColorValue(v, colorSpace, pastel),\n };\n if (hdr && v.hdr !== undefined) {\n token.$extensions = {\n [DTCG_EXTENSION_NAMESPACE]: { hdr: dtcgHdrValue(v.hdr) },\n };\n }\n return token;\n}\n\n/**\n * Build a `GlazeDtcgResult`: one spec-conformant DTCG token document per\n * scheme variant, gated by `modes`. Light is always present. With\n * `modes.hdr`, a token whose variant has an HDR value carries it in\n * `$extensions['me.tenphi.glaze'].hdr` — only in that scheme's document;\n * `$value` stays SDR.\n */\nexport function buildDtcgMap(\n resolved: Map<string, ResolvedColor>,\n prefix: string,\n modes: Required<GlazeOutputModes>,\n colorSpace: DtcgColorSpace = 'srgb',\n pastel = false,\n): GlazeDtcgResult {\n const light: DtcgDocument = {};\n const dark: DtcgDocument | undefined = modes.dark ? {} : undefined;\n const lightContrast: DtcgDocument | undefined = modes.highContrast\n ? {}\n : undefined;\n const darkContrast: DtcgDocument | undefined =\n modes.dark && modes.highContrast ? {} : undefined;\n const token = (v: ResolvedColorVariant): DtcgColorToken =>\n dtcgToken(v, colorSpace, pastel, modes.hdr);\n\n for (const [name, color] of resolved) {\n const key = `${prefix}${name}`;\n light[key] = token(color.light);\n if (dark) dark[key] = token(color.dark);\n if (lightContrast) lightContrast[key] = token(color.lightContrast);\n if (darkContrast) darkContrast[key] = token(color.darkContrast);\n }\n\n return { light, dark, lightContrast, darkContrast };\n}\n\n// ============================================================================\n// DTCG Resolver Module (single document for all scheme variants)\n// ============================================================================\n\n/**\n * Default context names emitted on the `scheme` modifier — the Glaze variant\n * keys, so the resolver document mirrors `GlazeDtcgResult` exactly.\n */\nconst DEFAULT_DTCG_CONTEXT_NAMES = {\n light: 'light',\n dark: 'dark',\n lightContrast: 'lightContrast',\n darkContrast: 'darkContrast',\n} as const;\n\n/**\n * Wrap a per-scheme `GlazeDtcgResult` into a single W3C DTCG Resolver-Module\n * document. The light document becomes `sets[setName].sources[0]` (the default\n * context); each other present variant becomes a `contexts[ctx]` override\n * array on a single `modifiers[modifierName]`. Absent variants (per the\n * `modes` already applied to `result`) are omitted — light is always present\n * and is the modifier `default`. Only the resolver-specific options are read;\n * `modes` / `colorSpace` were already consumed by the `buildDtcgMap` call that\n * produced `result`.\n */\nexport function buildDtcgResolver(\n result: GlazeDtcgResult,\n options?: GlazeDtcgResolverOptions,\n): GlazeDtcgResolverDocument {\n const setName = options?.setName ?? 'base';\n const modifierName = options?.modifierName ?? 'scheme';\n const ctx = {\n ...DEFAULT_DTCG_CONTEXT_NAMES,\n ...options?.contextNames,\n };\n const contexts: Record<string, DtcgTokenTree[]> = {\n [ctx.light]: [],\n };\n if (result.dark) contexts[ctx.dark] = [result.dark];\n if (result.lightContrast) {\n contexts[ctx.lightContrast] = [result.lightContrast];\n }\n if (result.darkContrast) contexts[ctx.darkContrast] = [result.darkContrast];\n\n return {\n version: options?.version ?? '2025.10',\n sets: {\n [setName]: { sources: [result.light] },\n },\n modifiers: {\n [modifierName]: {\n default: ctx.light,\n contexts,\n },\n },\n resolutionOrder: [\n { $ref: `#/sets/${setName}` },\n { $ref: `#/modifiers/${modifierName}` },\n ],\n };\n}\n\n// ============================================================================\n// Tailwind CSS v4 (@theme)\n// ============================================================================\n\n/** Default `hdrSelector` for `tailwind()`. */\nexport const DEFAULT_TAILWIND_HDR_SELECTOR = '@media (dynamic-range: high)';\n\n/**\n * Per-scheme declaration lines (`--prop: value;`) accumulated for emission,\n * plus the dense HDR lines (`lightHdr`, …), filled only with `modes.hdr`.\n */\nexport type GlazeTailwindLines = Record<Scheme | HdrScheme, string[]>;\n\n/** Fresh, empty Tailwind line buckets. */\nexport function emptyTailwindLines(): GlazeTailwindLines {\n return {\n light: [],\n dark: [],\n lightContrast: [],\n darkContrast: [],\n lightHdr: [],\n darkHdr: [],\n lightContrastHdr: [],\n darkContrastHdr: [],\n };\n}\n\n/** Append every bucket of `part` to `acc` (palette accumulation). */\nexport function mergeTailwindLines(\n acc: GlazeTailwindLines,\n part: GlazeTailwindLines,\n): void {\n for (const key of Object.keys(acc) as (keyof GlazeTailwindLines)[]) {\n acc[key].push(...part[key]);\n }\n}\n\nfunction tailwindLinesFor(\n resolved: Map<string, ResolvedColor>,\n themePrefix: string,\n cssPrefix: string,\n format: GlazeColorFormat,\n pastel: boolean,\n modes: Required<GlazeOutputModes>,\n): GlazeTailwindLines {\n const lines = emptyTailwindLines();\n const schemes = emittedSchemes(modes);\n for (const [name, color] of resolved) {\n const prop = `--${cssPrefix}${themePrefix}${name}`;\n const dense = modes.hdr && hasHdrIn(color, schemes);\n for (const scheme of SCHEMES) {\n const v = color[scheme];\n const decl = `${prop}: ${formatVariant(v, format, pastel)};`;\n lines[scheme].push(decl);\n if (dense) {\n lines[hdrKey(scheme)].push(\n v.hdr !== undefined ? `${prop}: ${formatHdrVariant(v)};` : decl,\n );\n }\n }\n }\n return lines;\n}\n\nfunction indentBlock(text: string, pad: string): string {\n return text\n .split('\\n')\n .map((line) => (line.length === 0 ? line : pad + line))\n .join('\\n');\n}\n\nfunction emitRule(selector: string, body: string): string {\n return `${selector} {\\n${indentBlock(body, ' ')}\\n}`;\n}\n\n/**\n * Emit a CSS block for a set of declarations scoped by one or more selectors\n * / at-rules. Class-like selectors concatenate (`.dark.high-contrast`);\n * at-rules (`@media …`) nest `:root` (or the chained selector) inside.\n */\nfunction emitScoped(\n scopes: string[],\n declarations: string[],\n): string | undefined {\n if (declarations.length === 0) return undefined;\n\n const atRules: string[] = [];\n let selectorChain = '';\n for (const scope of scopes) {\n if (scope.startsWith('@')) atRules.push(scope);\n else selectorChain += scope;\n }\n const selector = selectorChain || ':root';\n\n let css = emitRule(selector, declarations.join('\\n'));\n for (const rule of atRules) {\n css = emitRule(rule, css);\n }\n return css;\n}\n\n/**\n * Render accumulated per-scheme declaration lines as a Tailwind v4 CSS string:\n * an `@theme` block (light baseline) plus dark / high-contrast overrides under\n * the configured selectors. Empty blocks are skipped.\n *\n * With `modes.hdr`, the dense HDR blocks follow every SDR block, in scheme\n * order: light under `hdrSelector`, dark under `darkSelector` + `hdrSelector`,\n * and so on. Each re-declares the same set of colors, so whichever scheme\n * block wins the cascade in an HDR context carries that scheme's values.\n */\nexport function emitTailwindCss(\n lines: GlazeTailwindLines,\n modes: Required<GlazeOutputModes>,\n darkSelector: string,\n highContrastSelector: string,\n hdrSelector: string = DEFAULT_TAILWIND_HDR_SELECTOR,\n): string {\n const blocks: string[] = [];\n const push = (block: string | undefined): void => {\n if (block) blocks.push(block);\n };\n\n if (lines.light.length > 0) {\n blocks.push(emitRule('@theme', lines.light.join('\\n')));\n }\n\n if (modes.dark) {\n push(emitScoped([darkSelector], lines.dark));\n }\n if (modes.highContrast) {\n push(emitScoped([highContrastSelector], lines.lightContrast));\n }\n if (modes.dark && modes.highContrast) {\n push(emitScoped([darkSelector, highContrastSelector], lines.darkContrast));\n }\n\n if (modes.hdr) {\n push(emitScoped([hdrSelector], lines.lightHdr));\n if (modes.dark) {\n push(emitScoped([darkSelector, hdrSelector], lines.darkHdr));\n }\n if (modes.highContrast) {\n push(\n emitScoped([highContrastSelector, hdrSelector], lines.lightContrastHdr),\n );\n }\n if (modes.dark && modes.highContrast) {\n push(\n emitScoped(\n [darkSelector, highContrastSelector, hdrSelector],\n lines.darkContrastHdr,\n ),\n );\n }\n }\n\n return blocks.join('\\n\\n');\n}\n\n/**\n * Build per-scheme declaration lines for a single theme (used by\n * `theme.tailwind()` and as the palette `buildOne` step). `modes` decides\n * whether the HDR lines are filled and which schemes count toward the dense\n * set.\n */\nexport function buildTailwindLines(\n resolved: Map<string, ResolvedColor>,\n themePrefix: string,\n cssPrefix: string,\n format: GlazeColorFormat,\n pastel: boolean,\n modes: Required<GlazeOutputModes>,\n): GlazeTailwindLines {\n return tailwindLinesFor(\n resolved,\n themePrefix,\n cssPrefix,\n format,\n pastel,\n modes,\n );\n}\n\n/**\n * Build a complete Tailwind v4 CSS string for a single theme.\n */\nexport function buildTailwindMap(\n resolved: Map<string, ResolvedColor>,\n themePrefix: string,\n cssPrefix: string,\n modes: Required<GlazeOutputModes>,\n format: GlazeColorFormat,\n darkSelector: string,\n highContrastSelector: string,\n pastel = false,\n hdrSelector: string = DEFAULT_TAILWIND_HDR_SELECTOR,\n): string {\n const lines = tailwindLinesFor(\n resolved,\n themePrefix,\n cssPrefix,\n format,\n pastel,\n modes,\n );\n return emitTailwindCss(\n lines,\n modes,\n darkSelector,\n highContrastSelector,\n hdrSelector,\n );\n}\n","/**\n * Standalone single-color tokens (`glaze.color()` / `glaze.colorFrom()`).\n *\n * Owns the value-shorthand parser (hex, `rgb()` / `hsl()` / `okhsl()` /\n * `okhst()` / `oklch()`, `{ r, g, b }`, `{ h, s, l }`, `{ h, s, t }`,\n * `{ l, c, h }`), the structured-input validator, the two factory paths\n * (value vs structured), and the JSON-safe export / rehydration round-trip.\n *\n * A token that links to another as `base` resolves against the base token's\n * own variants — what the base actually paints, under its own config — in\n * every scheme, so a light `'+0'` lands on it and a light `contrast` floor is\n * measured against it. Every token also registers an internal dark-delta\n * anchor hook: a linking token passes it to the resolver, so a `'+N'` link\n * steps in dark from where the base sits under the base's own windows (the\n * resolver reads a base under another dark window back through the link's\n * own). The hook's result is cached per pass with the token's resolve.\n *\n * A token's role is pinned here rather than left to the resolver's chain: an\n * explicit `role`, else `'text'`. The token is the foreground against its\n * anchor — its `base`, or the hidden seed holding its own input color — and\n * the user-supplied `name` is a debug label that never drives role inference.\n *\n * Tokens store a sparse local config override only, copied once at creation so\n * the caller's object can't reach it later. Resolve merges the live global\n * config with that local override (invalidated on `configure()`). Authoring\n * `.export(override?)` freezes `getConfig() ∪ local ∪ override` at call time.\n *\n * `css()` with `splitHue` claims the token's `--{name}-hue` and its value\n * property in one namespace, so `suffix: '-hue'` throws whenever the token\n * declares a hue var (it is chromatic in light), instead of emitting a value\n * that reads itself through `var()`.\n */\n\nimport {\n copyConfigOverride,\n freezeConfigForExport,\n getConfig,\n getConfigVersion,\n mergeConfig,\n} from './config';\nimport {\n assertExportKind,\n assertExportVersion,\n GLAZE_EXPORT_VERSION,\n isColorTokenExport,\n} from './serialize';\nimport {\n assertSplitHueFormat,\n claimHueVars,\n claimValueProps,\n type ChannelCtx,\n type HueVarLabels,\n type SplitHueOwners,\n} from './channels';\nimport { copyColorValue, extractOkhslFromValue } from './color-value';\nimport { assertAllPastel, assertNativeFormat } from './format-guard';\nimport { toTone } from './okhst';\nimport { pairNormal, showValue } from './hc-pair';\nimport {\n anchorAtAuthoredTone,\n darkAnchorOf,\n resolveAllColors,\n} from './resolver';\nimport type { DarkAnchorHook, ExternalDarkAnchor } from './resolver';\nimport { normalizeRole } from './roles';\nimport { hasRelativeTone, isRelativeValue } from './validation';\nimport {\n buildCssMap,\n buildDtcgMap,\n buildDtcgResolver,\n buildJsonMap,\n buildTailwindMap,\n buildTokenMap,\n resolveModes,\n} from './formatters';\nimport type {\n ColorMap,\n GlazeColorCssOptions,\n GlazeColorDtcgResolverOptions,\n GlazeColorDtcgResult,\n GlazeColorInput,\n GlazeColorInputExport,\n GlazeColorOverrides,\n GlazeColorOverridesExport,\n GlazeColorTailwindOptions,\n GlazeColorToken,\n GlazeColorTokenExport,\n GlazeColorValue,\n GlazeCssResult,\n GlazeConfigOverride,\n GlazeConfigResolved,\n GlazeDtcgOptions,\n GlazeDtcgResolverDocument,\n GlazeDtcgResult,\n GlazeJsonOptions,\n GlazeThemeSeed,\n GlazeTokenOptions,\n HCPair,\n ContrastSpec,\n OkhslColor,\n RegularColorDef,\n ResolvedColor,\n Role,\n RoleInput,\n ToneValue,\n} from './types';\n\n// ============================================================================\n// Standalone color constants\n// ============================================================================\n\n/** Internal name of the user-facing standalone color in the synthesized def map. */\nconst STANDALONE_VALUE = 'value';\n/** Internal name of the hidden static-anchor seed used for relative tone / contrast. */\nconst STANDALONE_SEED = 'seed';\n/** Internal name of an externally-resolved `GlazeColorToken` injected as a base reference. */\nconst STANDALONE_BASE = 'externalBase';\n\n/** Reserved internal names that user-supplied `name` must not collide with. */\nconst RESERVED_STANDALONE_NAMES = new Set([\n STANDALONE_VALUE,\n STANDALONE_SEED,\n STANDALONE_BASE,\n]);\n\n// ============================================================================\n// Sparse local config (no global freeze at create)\n// ============================================================================\n\n/**\n * Value-form local override: `lightTone` defaults to `false` (preserve\n * input tone). User override fields win. Returns a detached copy.\n */\nfunction sparseValueFormLocal(\n userOverride?: GlazeConfigOverride,\n): GlazeConfigOverride {\n const own = copyConfigOverride(userOverride);\n return {\n ...own,\n lightTone: own?.lightTone !== undefined ? own.lightTone : false,\n };\n}\n\n// ============================================================================\n// Input validation\n// ============================================================================\n\n/**\n * Validate a user-supplied `opacity` override on `glaze.color()`.\n * Must be a finite number in `0..=1`.\n */\nfunction validateStandaloneOpacity(value: number): void {\n if (!Number.isFinite(value) || value < 0 || value > 1) {\n throw new Error(\n `glaze.color: opacity must be a finite number in 0–1 (got ${value}).`,\n );\n }\n}\n\n/**\n * Validate a structured `GlazeColorInput`. Range-checks the `hue` /\n * `saturation` / `tone` numerics (and any HC-pair second value)\n * before the resolver sees them so out-of-range or non-finite inputs\n * fail with a helpful, top-level error rather than producing a\n * NaN-laden token. `opacity` is checked here too so all input\n * validation lives in one place.\n */\nfunction validateStructuredInput(input: GlazeColorInput): void {\n if (!Number.isFinite(input.hue)) {\n throw new Error(\n `glaze.color: structured hue must be a finite number (got ${input.hue}).`,\n );\n }\n if (\n !Number.isFinite(input.saturation) ||\n input.saturation < 0 ||\n input.saturation > 100\n ) {\n throw new Error(\n `glaze.color: structured saturation must be a finite number in 0–100 (got ${input.saturation}).`,\n );\n }\n const checkTone = (value: number | string, label: string): void => {\n // 'max' / 'min' extreme keywords are always valid.\n if (value === 'max' || value === 'min') return;\n if (\n typeof value !== 'number' ||\n !Number.isFinite(value) ||\n value < 0 ||\n value > 100\n ) {\n throw new Error(\n `glaze.color: structured ${label} must be a finite number in 0–100 or 'max'/'min' (got ${String(value)}).`,\n );\n }\n };\n if (Array.isArray(input.tone)) {\n checkTone(input.tone[0], 'tone[normal]');\n checkTone(input.tone[1], 'tone[hc]');\n } else {\n checkTone(input.tone, 'tone');\n }\n if (input.saturationFactor !== undefined) {\n if (\n !Number.isFinite(input.saturationFactor) ||\n input.saturationFactor < 0 ||\n input.saturationFactor > 1\n ) {\n throw new Error(\n `glaze.color: structured saturationFactor must be a finite number in 0–1 (got ${input.saturationFactor}).`,\n );\n }\n }\n if (\n input.darkHue !== undefined &&\n !(typeof input.darkHue === 'number'\n ? Number.isFinite(input.darkHue)\n : isRelativeValue(input.darkHue))\n ) {\n throw new Error(\n `glaze.color: structured darkHue must be a finite number or a '+N' / '-N' offset (got ${showValue(input.darkHue)}).`,\n );\n }\n if (input.darkSaturation !== undefined) {\n if (\n !Number.isFinite(input.darkSaturation) ||\n input.darkSaturation < 0 ||\n input.darkSaturation > 100\n ) {\n throw new Error(\n `glaze.color: structured darkSaturation must be a finite number in 0–100 (got ${input.darkSaturation}).`,\n );\n }\n }\n if (input.darkSaturationFactor !== undefined) {\n if (\n !Number.isFinite(input.darkSaturationFactor) ||\n input.darkSaturationFactor < 0 ||\n input.darkSaturationFactor > 1\n ) {\n throw new Error(\n `glaze.color: structured darkSaturationFactor must be a finite number in 0–1 (got ${input.darkSaturationFactor}).`,\n );\n }\n }\n if (input.opacity !== undefined) validateStandaloneOpacity(input.opacity);\n}\n\n/**\n * Validate a user-supplied `name` override. Rejects empty / whitespace-only\n * strings and names colliding with `glaze`'s reserved internal sentinels.\n */\nfunction validateStandaloneName(name: string): void {\n if (typeof name !== 'string' || name.trim() === '') {\n throw new Error(\n 'glaze.color: name must be a non-empty string. ' +\n 'Omit `name` if you do not want to set a debug label.',\n );\n }\n if (RESERVED_STANDALONE_NAMES.has(name)) {\n const reserved = [...RESERVED_STANDALONE_NAMES]\n .map((n) => `\"${n}\"`)\n .join(', ');\n throw new Error(\n `glaze.color: name \"${name}\" is reserved (used internally). ` +\n `Reserved names are: ${reserved}. Pick a different name.`,\n );\n }\n}\n\n// ============================================================================\n// Factory: shared helpers\n// ============================================================================\n\ninterface ValueDefsResult {\n seed: GlazeThemeSeed;\n defs: ColorMap;\n primary: string;\n}\n\n/**\n * Resolve `'max'` / `'min'` to their literal author tones (100 / 0).\n *\n * The hidden `STANDALONE_SEED` anchor exists only so `contrast` has something\n * to measure against — it is not an authored base. Pinning the extreme keeps\n * the token on the plain scheme mapping instead of the base-anchored dark\n * replay the resolver applies to real `base` references.\n */\nfunction pinExtremeTone(tone: HCPair<ToneValue>): HCPair<ToneValue> {\n const pin = (value: ToneValue): ToneValue =>\n value === 'max' ? 100 : value === 'min' ? 0 : value;\n return Array.isArray(tone) ? [pin(tone[0]), pin(tone[1])] : pin(tone);\n}\n\n/**\n * The role the user-facing def resolves with: an explicit `role`, else\n * `'text'`.\n *\n * A token is the foreground against its anchor in both pairings — an\n * external `base` (which the resolver treats as a background) and the hidden\n * `STANDALONE_SEED` holding the token's own input color (marked `'surface'`\n * below). Pinning the role here, instead of leaving it to the resolver's\n * chain, also keeps the user-supplied `name` a pure debug label: it becomes\n * the def's key, so the resolver would otherwise infer a role from it.\n */\nfunction standaloneRole(role: RoleInput | undefined): Role {\n return normalizeRole(role) ?? 'text';\n}\n\n/**\n * Build the `ColorMap` for a value-shorthand `glaze.color()` call.\n *\n * The user-facing color (`STANDALONE_VALUE`) defaults to `mode: 'auto'`\n * across every value-shorthand form.\n *\n * An absolute `hue` override becomes the seed while a relative one becomes a\n * def field; `darkHue` always lands on the def in either form, so an absolute\n * `darkHue` wins outright instead of being re-offset by a relative `hue`.\n *\n * When the user requests `contrast` or relative `tone`, a hidden\n * `STANDALONE_SEED` def is synthesized at `mode: 'static'`. That keeps\n * the seed pinned to the literal user-provided color across all four\n * variants, so the contrast solver always anchors against it. Its dark-delta\n * anchor is still its authored tone (`anchorAtAuthoredTone`), so a delta on it\n * inverts in dark like one on the same color in a theme.\n */\nfunction buildStandaloneValueDefs(\n main: OkhslColor,\n options: GlazeColorOverrides | undefined,\n): ValueDefsResult {\n const seedHue = typeof options?.hue === 'number' ? options.hue : main.h;\n const seedSaturation = options?.saturation ?? main.s * 100;\n const relativeHue =\n typeof options?.hue === 'string' ? options.hue : undefined;\n\n const toneOption = options?.tone;\n const hasExternalBase = options?.base !== undefined;\n // Seed-anchor synthesis only kicks in when the user did NOT supply their\n // own base — in that case `contrast` and relative `tone` anchor to\n // the literal seed via the hidden `STANDALONE_SEED` def.\n const needsSeedAnchor =\n !hasExternalBase &&\n (options?.contrast !== undefined || hasRelativeTone(toneOption));\n\n if (options?.opacity !== undefined)\n validateStandaloneOpacity(options.opacity);\n\n const userName = options?.name;\n if (userName !== undefined) validateStandaloneName(userName);\n const primary = userName ?? STANDALONE_VALUE;\n\n // The seed color is given in OKHSL lightness; express it as canonical tone.\n const seedTone = toTone(main.l);\n\n const primaryTone = toneOption ?? seedTone;\n\n const valueDef: RegularColorDef = {\n hue: relativeHue,\n saturation: options?.saturationFactor,\n darkHue: options?.darkHue,\n darkSaturation: options?.darkSaturationFactor,\n tone: needsSeedAnchor ? pinExtremeTone(primaryTone) : primaryTone,\n contrast: options?.contrast,\n mode: options?.mode ?? 'auto',\n autoFlip: options?.autoFlip,\n opacity: options?.opacity,\n pastel: options?.pastel,\n role: standaloneRole(options?.role),\n base: hasExternalBase\n ? STANDALONE_BASE\n : needsSeedAnchor\n ? STANDALONE_SEED\n : undefined,\n };\n\n const defs: ColorMap = { [primary]: valueDef };\n\n if (needsSeedAnchor) {\n defs[STANDALONE_SEED] = anchorAtAuthoredTone({\n hue: main.h,\n saturation: 1,\n tone: seedTone,\n mode: 'static',\n // The anchor is the background the token is measured on.\n role: 'surface',\n });\n }\n\n return {\n seed: {\n hue: seedHue,\n saturation: seedSaturation,\n darkSaturation: options?.darkSaturation,\n },\n defs,\n primary,\n };\n}\n\n/**\n * Each token's dark-delta anchor (internal, not public API). A token linking to\n * another as its `base` hands the resolver the base's hook, so a `'+N'` link\n * steps in dark from where the base sits on its own authored scale — read in the\n * base's own resolve context, under its windows and defs, and returned with the\n * base's config so the resolver can tell whether the link's dark window is the\n * same one.\n */\nconst darkAnchorHooks = new WeakMap<GlazeColorToken, DarkAnchorHook>();\n\nfunction withDarkAnchor(\n hook: DarkAnchorHook,\n token: GlazeColorToken,\n): GlazeColorToken {\n darkAnchorHooks.set(token, hook);\n return token;\n}\n\nfunction createColorTokenFromDefs(\n seed: GlazeThemeSeed,\n defs: ColorMap,\n primary: string,\n configOverride: GlazeConfigOverride | undefined,\n baseToken: GlazeColorToken | undefined,\n buildExport: (override?: GlazeConfigOverride) => GlazeColorTokenExport,\n): GlazeColorToken {\n const baseHook = baseToken && darkAnchorHooks.get(baseToken);\n const externalAnchors = baseHook\n ? new Map([[STANDALONE_BASE, baseHook]])\n : undefined;\n\n let cache: {\n map: Map<string, ResolvedColor> | null;\n version: number;\n effectiveConfig: GlazeConfigResolved;\n /** The resolved `base` token the map was resolved against. */\n externalBases?: Map<string, ResolvedColor>;\n /**\n * This token's dark-delta anchor per pass (normal, high contrast). Cached\n * with the resolve, so a token linking to it reads it in O(1): a chain of\n * links walks itself once, not once per link, and adds no stack depth.\n */\n anchors: [ExternalDarkAnchor?, ExternalDarkAnchor?];\n } | null = null;\n\n function getEffectiveConfig(): GlazeConfigResolved {\n const version = getConfigVersion();\n if (cache && cache.version === version) return cache.effectiveConfig;\n const effectiveConfig = mergeConfig(getConfig(), configOverride);\n cache = { map: null, version, effectiveConfig, anchors: [] };\n return effectiveConfig;\n }\n\n const resolveOnce = (): Map<string, ResolvedColor> => {\n const version = getConfigVersion();\n if (cache && cache.version === version && cache.map) return cache.map;\n const effectiveConfig = getEffectiveConfig();\n // Resolved here, not through a helper: a chain of linked tokens recurses\n // through this line once per link, so an extra frame shortens the chain\n // that fits on the stack.\n const externalBases = baseToken\n ? new Map([[STANDALONE_BASE, baseToken.resolve()]])\n : undefined;\n const map = resolveAllColors(\n seed,\n defs,\n effectiveConfig,\n externalBases,\n externalAnchors,\n );\n cache = { map, version, effectiveConfig, externalBases, anchors: [] };\n return map;\n };\n\n const darkAnchor: DarkAnchorHook = (isHighContrast) => {\n const resolved = resolveOnce();\n const { anchors, effectiveConfig, externalBases } = cache!;\n const pass = isHighContrast ? 1 : 0;\n return (anchors[pass] ??= {\n tone: darkAnchorOf(primary, isHighContrast, {\n defs,\n config: effectiveConfig,\n resolved,\n externalBases,\n externalAnchors,\n }),\n config: effectiveConfig,\n });\n };\n\n const resolveStates = (options?: GlazeTokenOptions) => {\n const cfg = getConfig();\n return {\n dark: options?.states?.dark ?? cfg.states.dark,\n highContrast: options?.states?.highContrast ?? cfg.states.highContrast,\n };\n };\n\n const tokenLike = (options?: GlazeTokenOptions): Record<string, string> => {\n const tokenMap = buildTokenMap(\n resolveOnce(),\n '',\n resolveStates(options),\n resolveModes(options?.modes),\n options?.format ?? 'oklch',\n getEffectiveConfig().pastel,\n );\n return tokenMap[`#${primary}`];\n };\n\n return withDarkAnchor(darkAnchor, {\n resolve(): ResolvedColor {\n return resolveOnce().get(primary)!;\n },\n\n token: tokenLike,\n tasty: tokenLike,\n\n json(options?: GlazeJsonOptions): Record<string, string> {\n const format = options?.format ?? 'oklch';\n assertNativeFormat(format, 'json');\n const jsonMap = buildJsonMap(\n resolveOnce(),\n resolveModes(options?.modes),\n format,\n getEffectiveConfig().pastel,\n );\n return jsonMap[primary];\n },\n\n css(options: GlazeColorCssOptions): GlazeCssResult {\n const format = options.format ?? 'oklch';\n assertNativeFormat(format, 'css');\n assertSplitHueFormat(options.splitHue, format);\n const suffix = options.suffix ?? '-color';\n const resolved = resolveOnce().get(primary)!;\n const renamed = new Map<string, ResolvedColor>([\n [options.name, resolved],\n ]);\n\n let channelCtx: ChannelCtx | undefined;\n if (options.splitHue) {\n const modes = resolveModes();\n assertAllPastel(renamed, modes);\n channelCtx = {\n seedHue: seed.hue,\n baseName: options.name,\n prefix: '',\n defs: { [options.name]: defs[primary] },\n mode: 'standalone',\n resolvedHue: resolved.light.h,\n };\n // `--{name}-hue` and the value `--{name}{suffix}` share a namespace:\n // `suffix: '-hue'` would make the value a `var()` cycle on itself.\n const owners: SplitHueOwners = new Map();\n const fix = \"Pass a `suffix` other than '-hue'.\";\n const labels: HueVarLabels = {\n theme: `the hue of token \"${options.name}\"`,\n color: (name) => `the hue of token \"${name}\"`,\n value: (name) => `the value of token \"${name}\"`,\n fix,\n valueFix: fix,\n };\n claimHueVars(renamed, channelCtx, owners, labels);\n claimValueProps(renamed, '', suffix, owners, labels);\n }\n\n return buildCssMap(\n renamed,\n '',\n suffix,\n format,\n getEffectiveConfig().pastel,\n channelCtx,\n );\n },\n\n dtcg(options?: GlazeDtcgOptions): GlazeColorDtcgResult {\n const modes = resolveModes(options?.modes);\n const doc = buildDtcgMap(\n resolveOnce(),\n '',\n modes,\n options?.colorSpace ?? 'srgb',\n getEffectiveConfig().pastel,\n );\n const result: GlazeColorDtcgResult = { light: doc.light[primary] };\n if (doc.dark) result.dark = doc.dark[primary];\n if (doc.lightContrast) {\n result.lightContrast = doc.lightContrast[primary];\n }\n if (doc.darkContrast) result.darkContrast = doc.darkContrast[primary];\n return result;\n },\n\n dtcgResolver(\n options: GlazeColorDtcgResolverOptions,\n ): GlazeDtcgResolverDocument {\n const doc = buildDtcgMap(\n resolveOnce(),\n '',\n resolveModes(options?.modes),\n options?.colorSpace ?? 'srgb',\n getEffectiveConfig().pastel,\n );\n const name = options.name;\n const result: GlazeDtcgResult = {\n light: { [name]: doc.light[primary] },\n };\n if (doc.dark) result.dark = { [name]: doc.dark[primary] };\n if (doc.lightContrast) {\n result.lightContrast = { [name]: doc.lightContrast[primary] };\n }\n if (doc.darkContrast) {\n result.darkContrast = { [name]: doc.darkContrast[primary] };\n }\n return buildDtcgResolver(result, options);\n },\n\n tailwind(options: GlazeColorTailwindOptions): string {\n const format = options.format ?? 'oklch';\n assertNativeFormat(format, 'tailwind');\n const renamed = new Map<string, ResolvedColor>([\n [options.name, resolveOnce().get(primary)!],\n ]);\n return buildTailwindMap(\n renamed,\n '',\n options.namespace ?? 'color-',\n resolveModes(options?.modes),\n format,\n options.darkSelector ?? '.dark',\n options.highContrastSelector ?? '.high-contrast',\n getEffectiveConfig().pastel,\n );\n },\n\n export(override?: GlazeConfigOverride): GlazeColorTokenExport {\n return buildExport(override);\n },\n });\n}\n\n/**\n * Resolve `base` (which may be a token reference or a raw color value)\n * into a `GlazeColorToken`. Raw values are auto-wrapped via\n * `createColorTokenFromValue` so they pick up the same auto-invert\n * defaults as an explicit wrap. Returns `undefined` when no base is provided.\n */\nfunction resolveBaseToken(\n base: GlazeColorToken | GlazeColorValue | undefined,\n): GlazeColorToken | undefined {\n if (base === undefined) return undefined;\n if (isGlazeColorToken(base)) return base;\n return createColorTokenFromValue(base, undefined, undefined);\n}\n\n/**\n * Discriminate a `GlazeColorToken` from a raw `GlazeColorValue`.\n */\nexport function isGlazeColorToken(\n candidate: GlazeColorToken | GlazeColorValue,\n): candidate is GlazeColorToken {\n return (\n typeof candidate === 'object' &&\n candidate !== null &&\n !Array.isArray(candidate) &&\n 'resolve' in candidate &&\n typeof (candidate as { resolve?: unknown }).resolve === 'function'\n );\n}\n\n// ============================================================================\n// Factory: structured input\n// ============================================================================\n\nexport function createColorToken(\n rawInput: GlazeColorInput,\n configOverride?: GlazeConfigOverride,\n): GlazeColorToken {\n // Validate the copy, so the token is built from exactly what passed.\n const input = copyTokenOptions(rawInput);\n validateStructuredInput(input);\n\n const userName = input.name;\n if (userName !== undefined) validateStandaloneName(userName);\n const primary = userName ?? STANDALONE_VALUE;\n\n const baseToken = resolveBaseToken(input.base);\n const hasExternalBase = baseToken !== undefined;\n const needsSeedAnchor = !hasExternalBase && input.contrast !== undefined;\n\n const defs: ColorMap = {\n [primary]: {\n tone: needsSeedAnchor ? pinExtremeTone(input.tone) : input.tone,\n saturation: input.saturationFactor,\n darkHue: input.darkHue,\n darkSaturation: input.darkSaturationFactor,\n mode: input.mode ?? 'auto',\n autoFlip: input.autoFlip,\n contrast: input.contrast,\n opacity: input.opacity,\n pastel: input.pastel,\n role: standaloneRole(input.role),\n base: hasExternalBase\n ? STANDALONE_BASE\n : needsSeedAnchor\n ? STANDALONE_SEED\n : undefined,\n },\n };\n\n if (needsSeedAnchor) {\n defs[STANDALONE_SEED] = anchorAtAuthoredTone({\n // The seed anchor must be a concrete tone; resolve 'max'/'min' to its\n // extreme so the static anchor is well-defined.\n tone: pinExtremeTone(pairNormal(input.tone)),\n saturation: 1,\n mode: 'static',\n // The anchor is the background the token is measured on.\n role: 'surface',\n });\n }\n\n // Copied once, so resolve and `export()` read the same detached object.\n const localOverride = copyConfigOverride(configOverride);\n\n return createColorTokenFromDefs(\n {\n hue: input.hue,\n saturation: input.saturation,\n darkSaturation: input.darkSaturation,\n },\n defs,\n primary,\n localOverride,\n baseToken,\n (exportArg) => ({\n kind: 'color',\n version: GLAZE_EXPORT_VERSION,\n form: 'structured',\n input: buildStructuredInputExport(input, baseToken, exportArg),\n config: freezeConfigForExport(localOverride, exportArg),\n }),\n );\n}\n\n// ============================================================================\n// Factory: value-shorthand input\n// ============================================================================\n\nexport function createColorTokenFromValue(\n input: GlazeColorValue,\n inputOptions: GlazeColorOverrides | undefined,\n configOverride: GlazeConfigOverride | undefined,\n): GlazeColorToken {\n const value = copyColorValue(input);\n const options = inputOptions && copyTokenOptions(inputOptions);\n const main = extractOkhslFromValue(value);\n const baseToken = resolveBaseToken(options?.base);\n const { seed, defs, primary } = buildStandaloneValueDefs(main, options);\n\n const localOverride = sparseValueFormLocal(configOverride);\n\n return createColorTokenFromDefs(\n seed,\n defs,\n primary,\n localOverride,\n baseToken,\n (exportArg) => ({\n kind: 'color',\n version: GLAZE_EXPORT_VERSION,\n form: 'value',\n input: copyColorValue(value),\n ...(options !== undefined\n ? { overrides: buildOverridesExport(options, baseToken, exportArg) }\n : {}),\n config: freezeConfigForExport(localOverride, exportArg),\n }),\n );\n}\n\n// ============================================================================\n// Export / rehydrate\n// ============================================================================\n\n/**\n * Build a JSON-safe snapshot of `GlazeColorOverrides`. `base` is serialized\n * as its token's own snapshot: a raw value as the token it is wrapped in, so\n * its config is frozen with the rest and a restored token doesn't follow later\n * `glaze.configure()` calls through its base. Every object in it is a fresh\n * copy, so editing a snapshot never reaches the live token.\n */\nfunction buildOverridesExport(\n options: GlazeColorOverrides,\n baseToken: GlazeColorToken | undefined,\n exportArg?: GlazeConfigOverride,\n): GlazeColorOverridesExport {\n const out: GlazeColorOverridesExport = {};\n if (options.hue !== undefined) out.hue = options.hue;\n if (options.saturation !== undefined) out.saturation = options.saturation;\n if (options.tone !== undefined) out.tone = copyPair(options.tone);\n if (options.saturationFactor !== undefined) {\n out.saturationFactor = options.saturationFactor;\n }\n if (options.darkHue !== undefined) out.darkHue = options.darkHue;\n if (options.darkSaturation !== undefined) {\n out.darkSaturation = options.darkSaturation;\n }\n if (options.darkSaturationFactor !== undefined) {\n out.darkSaturationFactor = options.darkSaturationFactor;\n }\n if (options.mode !== undefined) out.mode = options.mode;\n if (options.autoFlip !== undefined) out.autoFlip = options.autoFlip;\n if (options.contrast !== undefined) {\n out.contrast = copyContrast(options.contrast);\n }\n if (options.opacity !== undefined) out.opacity = options.opacity;\n if (options.name !== undefined) out.name = options.name;\n if (options.pastel !== undefined) out.pastel = options.pastel;\n if (options.role !== undefined) out.role = options.role;\n if (baseToken !== undefined) out.base = baseToken.export(exportArg);\n return out;\n}\n\n/** The structured-input counterpart of `buildOverridesExport`. */\nfunction buildStructuredInputExport(\n input: GlazeColorInput,\n baseToken: GlazeColorToken | undefined,\n exportArg?: GlazeConfigOverride,\n): GlazeColorInputExport {\n const out: GlazeColorInputExport = {\n hue: input.hue,\n saturation: input.saturation,\n tone: copyPair(input.tone),\n };\n if (input.saturationFactor !== undefined) {\n out.saturationFactor = input.saturationFactor;\n }\n if (input.darkHue !== undefined) out.darkHue = input.darkHue;\n if (input.darkSaturation !== undefined) {\n out.darkSaturation = input.darkSaturation;\n }\n if (input.darkSaturationFactor !== undefined) {\n out.darkSaturationFactor = input.darkSaturationFactor;\n }\n if (input.mode !== undefined) out.mode = input.mode;\n if (input.autoFlip !== undefined) out.autoFlip = input.autoFlip;\n if (input.opacity !== undefined) out.opacity = input.opacity;\n if (input.contrast !== undefined) out.contrast = copyContrast(input.contrast);\n if (input.name !== undefined) out.name = input.name;\n if (input.pastel !== undefined) out.pastel = input.pastel;\n if (input.role !== undefined) out.role = input.role;\n if (baseToken !== undefined) out.base = baseToken.export(exportArg);\n return out;\n}\n\n/** A copy of a `[normal, highContrast]` pair, or the value itself. */\nfunction copyPair<T>(value: HCPair<T>): HCPair<T> {\n return Array.isArray(value) ? ([...value] as HCPair<T>) : value;\n}\n\n/**\n * A copy of a `contrast` value, read by property access so a proxy (reactive\n * state) copies too. Other keys of a spec object are kept for the validator.\n */\nfunction copyContrast(contrast: HCPair<ContrastSpec>): HCPair<ContrastSpec> {\n const copySpec = (spec: ContrastSpec): ContrastSpec => {\n if (typeof spec !== 'object' || spec === null) return spec;\n const out: Record<string, unknown> = { ...spec };\n for (const key of ['wcag', 'apca'] as const) {\n const value = (spec as Record<string, unknown>)[key];\n if (value !== undefined) out[key] = copyPair(value);\n }\n return out as ContrastSpec;\n };\n return Array.isArray(contrast)\n ? (contrast.map(copySpec) as HCPair<ContrastSpec>)\n : copySpec(contrast);\n}\n\n/** Every field of `GlazeColorInput` / `GlazeColorOverrides`. */\nconst TOKEN_OPTION_KEYS = [\n 'hue',\n 'saturation',\n 'tone',\n 'saturationFactor',\n 'darkHue',\n 'darkSaturation',\n 'darkSaturationFactor',\n 'mode',\n 'autoFlip',\n 'opacity',\n 'contrast',\n 'base',\n 'name',\n 'pastel',\n 'role',\n] as const;\n\n/**\n * A detached copy of a token's input or overrides, each field read by property\n * access so a getter, an inherited field or a proxy copies like a plain one.\n * The pairs, `contrast` and a raw value `base` are copied too, so a caller\n * editing them later doesn't change the token (a token `base` is kept, as\n * tokens are immutable). Other keys (a value form's `from`) are left out.\n */\nfunction copyTokenOptions<T extends GlazeColorOverrides | GlazeColorInput>(\n options: T,\n): T {\n const source = options as Record<string, unknown>;\n const out: Record<string, unknown> = {};\n for (const key of TOKEN_OPTION_KEYS) {\n if (source[key] !== undefined) out[key] = source[key];\n }\n const copy = out as T;\n if (copy.tone !== undefined) copy.tone = copyPair(copy.tone) as T['tone'];\n if (copy.contrast !== undefined) copy.contrast = copyContrast(copy.contrast);\n if (copy.base !== undefined && !isGlazeColorToken(copy.base)) {\n copy.base = copyColorValue(copy.base);\n }\n return copy;\n}\n\n/**\n * Discriminate a `GlazeColorTokenExport` from a raw `GlazeColorValue`.\n */\nfunction isExportedToken(\n candidate: GlazeColorTokenExport | GlazeColorValue,\n): candidate is GlazeColorTokenExport {\n return isColorTokenExport(candidate);\n}\n\nfunction rehydrateOverrides(\n data: GlazeColorOverridesExport,\n): GlazeColorOverrides {\n const out: GlazeColorOverrides = {};\n if (data.hue !== undefined) out.hue = data.hue;\n if (data.saturation !== undefined) out.saturation = data.saturation;\n if (data.tone !== undefined) out.tone = data.tone;\n if (data.saturationFactor !== undefined) {\n out.saturationFactor = data.saturationFactor;\n }\n if (data.darkHue !== undefined) out.darkHue = data.darkHue;\n if (data.darkSaturation !== undefined) {\n out.darkSaturation = data.darkSaturation;\n }\n if (data.darkSaturationFactor !== undefined) {\n out.darkSaturationFactor = data.darkSaturationFactor;\n }\n if (data.mode !== undefined) out.mode = data.mode;\n if (data.autoFlip !== undefined) out.autoFlip = data.autoFlip;\n if (data.contrast !== undefined) out.contrast = data.contrast;\n if (data.opacity !== undefined) out.opacity = data.opacity;\n if (data.name !== undefined) out.name = data.name;\n if (data.pastel !== undefined) out.pastel = data.pastel;\n if (data.role !== undefined) out.role = data.role;\n if (data.base !== undefined) {\n out.base = isExportedToken(data.base)\n ? colorFromExport(data.base)\n : data.base;\n }\n return out;\n}\n\nfunction rehydrateStructuredInput(\n data: GlazeColorInputExport,\n): GlazeColorInput {\n const out: GlazeColorInput = {\n hue: data.hue,\n saturation: data.saturation,\n tone: data.tone,\n };\n if (data.saturationFactor !== undefined) {\n out.saturationFactor = data.saturationFactor;\n }\n if (data.darkHue !== undefined) out.darkHue = data.darkHue;\n if (data.darkSaturation !== undefined) {\n out.darkSaturation = data.darkSaturation;\n }\n if (data.darkSaturationFactor !== undefined) {\n out.darkSaturationFactor = data.darkSaturationFactor;\n }\n if (data.mode !== undefined) out.mode = data.mode;\n if (data.autoFlip !== undefined) out.autoFlip = data.autoFlip;\n if (data.opacity !== undefined) out.opacity = data.opacity;\n if (data.contrast !== undefined) out.contrast = data.contrast;\n if (data.name !== undefined) out.name = data.name;\n if (data.pastel !== undefined) out.pastel = data.pastel;\n if (data.role !== undefined) out.role = data.role;\n if (data.base !== undefined) {\n out.base = isExportedToken(data.base)\n ? colorFromExport(data.base)\n : data.base;\n }\n return out;\n}\n\n/**\n * Rehydrate a token from its `.export()` snapshot. Recursively rebuilds\n * any base dependency. Inverse of `GlazeColorToken.export()`.\n *\n * The stored `config` field is the freeze from export time — passed as\n * the instance local override so the rehydrated token stays pinned\n * against later `glaze.configure()` calls.\n */\nexport function colorFromExport(data: GlazeColorTokenExport): GlazeColorToken {\n if (data === null || typeof data !== 'object') {\n throw new Error(\n `glaze.colorFrom: expected an object from token.export(), got ${data === null ? 'null' : typeof data}.`,\n );\n }\n assertExportKind(data, 'color', 'glaze.colorFrom');\n assertExportVersion(data, 'glaze.colorFrom');\n if (data.form !== 'value' && data.form !== 'structured') {\n throw new Error(\n `glaze.colorFrom: invalid \"form\" field — expected \"value\" or \"structured\" (got ${JSON.stringify((data as { form?: unknown }).form)}).`,\n );\n }\n if (data.input === undefined) {\n throw new Error(\n `glaze.colorFrom: missing \"input\" field — expected the original ${data.form === 'value' ? 'GlazeColorValue' : 'GlazeColorInput'}.`,\n );\n }\n\n if (data.form === 'value') {\n const value = data.input as GlazeColorValue;\n const overrides = data.overrides\n ? rehydrateOverrides(data.overrides)\n : undefined;\n return createColorTokenFromValue(value, overrides, data.config);\n }\n\n const input = rehydrateStructuredInput(data.input as GlazeColorInputExport);\n return createColorToken(input, data.config);\n}\n","/**\n * Theme factory.\n *\n * Wraps a hue/saturation seed, a mutable `ColorMap`, and an optional\n * per-theme `GlazeConfigOverride`. Exposes `tokens()` / `tasty()` /\n * `json()` / `css()` / `dtcg()` / `dtcgResolver()` / `tailwind()` / `resolve()` /\n * `export()` / `extend()`.\n *\n * The per-theme config override is **merged over the live global config at\n * resolve time** so the theme still reacts to later `configure()` calls\n * for fields it didn't override. The merged config is memoized by\n * `configVersion` to avoid rebuilding it on every export call. The override is\n * copied once when the theme is created and `getConfig()` hands out a deep copy\n * of the merged config, so mutating either object can't reach a resolve.\n *\n * Exports carry the HDR tier of glows (`variant.hdr`) only with `modes.hdr`\n * — `css()` reads its own `hdr` option, defaulting to the global mode — and\n * `tasty()` keys it with `states.hdr`; the shapes live in `formatters.ts`.\n *\n * `tasty()` / `css()` with `splitHue` run its guards before emitting: format\n * `'oklch'`, every color pastel, and no color whose own hue var would take the\n * theme var's name (`--{name}-hue`). `css()` also claims each color's value\n * property, so a `suffix` that lands one on a hue var (`'-hue'`, or `''` with a\n * color named `*-hue`) throws too.\n */\n\nimport {\n assertSplitHueFormat,\n claimHueVars,\n claimValueProps,\n type ChannelCtx,\n type HueVarLabels,\n type SplitHueOwners,\n} from './channels';\nimport {\n copyConfigOverride,\n copyResolvedConfig,\n freezeConfigForExport,\n getConfig,\n getConfigVersion,\n mergeConfig,\n} from './config';\nimport { assertAllPastel, assertNativeFormat } from './format-guard';\nimport {\n buildCssMap,\n buildDtcgMap,\n buildDtcgResolver,\n buildFlatTokenMap,\n buildJsonMap,\n buildTailwindMap,\n buildTokenMap,\n DEFAULT_TAILWIND_HDR_SELECTOR,\n resolveModes,\n} from './formatters';\nimport { showValue } from './hc-pair';\nimport { resolveAllColors } from './resolver';\nimport { GLAZE_EXPORT_VERSION } from './serialize';\nimport type {\n ColorDef,\n ColorMap,\n GlazeConfigOverride,\n GlazeConfigResolved,\n GlazeCssOptions,\n GlazeColorFormat,\n GlazeCssResult,\n GlazeDtcgOptions,\n GlazeDtcgResolverDocument,\n GlazeDtcgResolverOptions,\n GlazeDtcgResult,\n GlazeExtendOptions,\n GlazeJsonOptions,\n GlazeOutputModes,\n GlazeTailwindOptions,\n GlazeTastyOptions,\n GlazeTheme,\n GlazeThemeExport,\n GlazeThemeSeed,\n ResolvedColor,\n} from './types';\n\n/**\n * Reject a seed the resolver can't use: every color multiplies its hue and\n * saturation, so a non-finite one paints the whole theme `NaN`.\n */\nfunction assertValidSeed(seed: GlazeThemeSeed): void {\n for (const field of [\n 'hue',\n 'saturation',\n 'darkHue',\n 'darkSaturation',\n ] as const) {\n const value: unknown = seed?.[field];\n const optional = field === 'darkHue' || field === 'darkSaturation';\n if (optional && value === undefined) continue;\n if (typeof value !== 'number' || !Number.isFinite(value)) {\n throw new Error(\n `glaze: theme seed ${field} must be a finite number (got ${showValue(value)}).`,\n );\n }\n }\n}\n\nexport function createTheme(\n seed: GlazeThemeSeed,\n initialColors?: ColorMap,\n callerOverride?: GlazeConfigOverride,\n): GlazeTheme {\n // Copied once here, so resolve, `getConfig()`, `export()` and `extend()`\n // read one object the caller can no longer mutate.\n const configOverride = copyConfigOverride(callerOverride);\n assertValidSeed(seed);\n const { hue, saturation, darkHue, darkSaturation } = seed;\n let colorDefs: ColorMap = initialColors ? { ...initialColors } : {};\n\n let cache: {\n map: Map<string, ResolvedColor> | null;\n version: number;\n effectiveConfig: GlazeConfigResolved;\n } | null = null;\n\n function getEffectiveConfig(): GlazeConfigResolved {\n const version = getConfigVersion();\n if (cache && cache.version === version) return cache.effectiveConfig;\n const effectiveConfig = mergeConfig(getConfig(), configOverride);\n cache = { map: null, version, effectiveConfig };\n return effectiveConfig;\n }\n\n function resolveCached(): Map<string, ResolvedColor> {\n const version = getConfigVersion();\n if (cache && cache.version === version && cache.map) return cache.map;\n const effectiveConfig = getEffectiveConfig();\n const map = resolveAllColors(seed, colorDefs, effectiveConfig);\n cache = { map, version, effectiveConfig };\n return map;\n }\n\n function invalidate(): void {\n cache = null;\n }\n\n /**\n * `splitHue` context for `tasty()` / `css()`, or `undefined` without it.\n * Throws on a non-oklch format, a non-pastel color, or a color whose own\n * hue var would take the theme var's name. `css()` passes its `suffix` so\n * each color's value property is claimed too: `--{color}{suffix}` must not\n * land on a hue var.\n */\n function channelCtxFor(\n options: GlazeTastyOptions | GlazeCssOptions | undefined,\n format: GlazeColorFormat,\n modes: Required<GlazeOutputModes>,\n valueSuffix?: string,\n ): ChannelCtx | undefined {\n if (!options?.splitHue) return undefined;\n assertSplitHueFormat(options.splitHue, format);\n const resolved = resolveCached();\n assertAllPastel(resolved, modes);\n const baseName = options.name ?? 'theme';\n const ctx: ChannelCtx = {\n seedHue: hue,\n darkSeedHue: darkHue,\n baseName,\n prefix: '',\n defs: colorDefs,\n mode: 'theme',\n };\n const owners: SplitHueOwners = new Map();\n const labels: HueVarLabels = {\n theme: `the theme hue (name: '${baseName}')`,\n color: (name) => `color \"${name}\"'s own hue`,\n value: (name) => `color \"${name}\"'s value`,\n fix: 'Rename the color or pass a different `name`.',\n valueFix: 'Rename the color, or pass a different `suffix` or `name`.',\n };\n claimHueVars(resolved, ctx, owners, labels);\n if (valueSuffix !== undefined) {\n claimValueProps(resolved, '', valueSuffix, owners, labels);\n }\n return ctx;\n }\n\n const theme: GlazeTheme = {\n get hue() {\n return hue;\n },\n get saturation() {\n return saturation;\n },\n get darkHue() {\n return darkHue;\n },\n get darkSaturation() {\n return darkSaturation;\n },\n getConfig(): GlazeConfigResolved {\n // A deep copy: the cached config feeds every resolve, so a caller's\n // mutation must not reach it (or skip `mergeConfig()`'s validation).\n return copyResolvedConfig(getEffectiveConfig());\n },\n\n colors(defs: ColorMap): void {\n colorDefs = { ...colorDefs, ...defs };\n invalidate();\n },\n\n color(name: string, def?: ColorDef): ColorDef | undefined | void {\n if (def === undefined) {\n return colorDefs[name];\n }\n colorDefs[name] = def;\n invalidate();\n },\n\n remove(names: string | string[]): void {\n const list = Array.isArray(names) ? names : [names];\n for (const name of list) {\n delete colorDefs[name];\n }\n invalidate();\n },\n\n has(name: string): boolean {\n return name in colorDefs;\n },\n\n list(): string[] {\n return Object.keys(colorDefs);\n },\n\n reset(): void {\n colorDefs = {};\n invalidate();\n },\n\n export(override?: GlazeConfigOverride): GlazeThemeExport {\n return {\n kind: 'theme',\n version: GLAZE_EXPORT_VERSION,\n hue,\n saturation,\n ...(darkHue !== undefined ? { darkHue } : {}),\n ...(darkSaturation !== undefined ? { darkSaturation } : {}),\n colors: structuredClone(colorDefs),\n config: freezeConfigForExport(configOverride, override),\n };\n },\n\n extend(options: GlazeExtendOptions): GlazeTheme {\n const childSeed: GlazeThemeSeed = {\n hue: options.hue ?? hue,\n saturation: options.saturation ?? saturation,\n darkHue: options.darkHue ?? darkHue,\n darkSaturation: options.darkSaturation ?? darkSaturation,\n };\n\n const inheritedColors: ColorMap = {};\n for (const [name, def] of Object.entries(colorDefs)) {\n if (def.inherit !== false) {\n inheritedColors[name] = def;\n }\n }\n\n const mergedColors = options.colors\n ? { ...inheritedColors, ...options.colors }\n : { ...inheritedColors };\n\n // Child inherits the parent override then merges in the per-extend\n // override, read like a stored one so its getters count too.\n const mergedConfigOverride: GlazeConfigOverride | undefined =\n configOverride || options.config\n ? {\n ...(configOverride ?? {}),\n ...(copyConfigOverride(options.config) ?? {}),\n }\n : undefined;\n\n return createTheme(childSeed, mergedColors, mergedConfigOverride);\n },\n\n resolve(): Map<string, ResolvedColor> {\n // Defensive shallow clone: the cache holds the canonical Map for\n // internal exporters; callers that mutate the returned Map must\n // not corrupt subsequent cached reads.\n return new Map(resolveCached());\n },\n\n tokens(options?: GlazeJsonOptions): Record<string, Record<string, string>> {\n const format = options?.format ?? 'oklch';\n assertNativeFormat(format, 'tokens');\n const modes = resolveModes(options?.modes);\n return buildFlatTokenMap(\n resolveCached(),\n '',\n modes,\n format,\n getEffectiveConfig().pastel,\n );\n },\n\n tasty(options?: GlazeTastyOptions): Record<string, Record<string, string>> {\n const cfg = getEffectiveConfig();\n const states = {\n dark: options?.states?.dark ?? cfg.states.dark,\n highContrast: options?.states?.highContrast ?? cfg.states.highContrast,\n hdr: options?.states?.hdr ?? cfg.states.hdr,\n };\n const modes = resolveModes(options?.modes);\n const format = options?.format ?? 'oklch';\n const channelCtx = channelCtxFor(options, format, modes);\n return buildTokenMap(\n resolveCached(),\n '',\n states,\n modes,\n format,\n cfg.pastel,\n channelCtx,\n );\n },\n\n json(options?: GlazeJsonOptions): Record<string, Record<string, string>> {\n const format = options?.format ?? 'oklch';\n assertNativeFormat(format, 'json');\n const modes = resolveModes(options?.modes);\n return buildJsonMap(\n resolveCached(),\n modes,\n format,\n getEffectiveConfig().pastel,\n );\n },\n\n css(options?: GlazeCssOptions): GlazeCssResult {\n const format = options?.format ?? 'oklch';\n assertNativeFormat(format, 'css');\n const suffix = options?.suffix ?? '-color';\n const modes = resolveModes();\n const channelCtx = channelCtxFor(options, format, modes, suffix);\n return buildCssMap(\n resolveCached(),\n '',\n suffix,\n format,\n getEffectiveConfig().pastel,\n channelCtx,\n options?.hdr ?? modes.hdr,\n );\n },\n\n dtcg(options?: GlazeDtcgOptions): GlazeDtcgResult {\n const modes = resolveModes(options?.modes);\n return buildDtcgMap(\n resolveCached(),\n '',\n modes,\n options?.colorSpace ?? 'srgb',\n getEffectiveConfig().pastel,\n );\n },\n\n dtcgResolver(\n options?: GlazeDtcgResolverOptions,\n ): GlazeDtcgResolverDocument {\n const result = buildDtcgMap(\n resolveCached(),\n '',\n resolveModes(options?.modes),\n options?.colorSpace ?? 'srgb',\n getEffectiveConfig().pastel,\n );\n return buildDtcgResolver(result, options);\n },\n\n tailwind(options?: GlazeTailwindOptions): string {\n const format = options?.format ?? 'oklch';\n assertNativeFormat(format, 'tailwind');\n const modes = resolveModes(options?.modes);\n return buildTailwindMap(\n resolveCached(),\n '',\n options?.namespace ?? 'color-',\n modes,\n format,\n options?.darkSelector ?? '.dark',\n options?.highContrastSelector ?? '.high-contrast',\n getEffectiveConfig().pastel,\n options?.hdrSelector ?? DEFAULT_TAILWIND_HDR_SELECTOR,\n );\n },\n } as GlazeTheme;\n\n return theme;\n}\n","/**\n * Palette factory.\n *\n * Composes multiple themes into a single token namespace with optional\n * theme-name prefixes and a \"primary theme\" that also surfaces an\n * unprefixed copy of its tokens. Six export methods (`tokens` / `tasty` /\n * `css` / `dtcg` / `dtcgResolver` / `tailwind`) share a `buildPaletteOutput`\n * driver that handles validation, per-theme iteration, prefix resolution,\n * collision filtering, and primary duplication; `json()` keys its output by\n * theme name instead, with no prefixes or collisions to resolve. The HDR\n * tier of glows (with `modes.hdr`, or `css({ hdr })`) is built from the same\n * filtered maps, so prefixes, the primary alias and collisions apply to it the\n * same way.\n * `tasty()` / `css()` with `splitHue` share one custom-property registry across\n * the passes of a call, so two themes declaring the same `--*-hue` throws — as\n * does a `css()` value property (primary aliases included) landing on a hue\n * var.\n *\n * Authoring round-trip: `palette.export()` / `createPaletteFromExport()`\n * (wired as `glaze.paletteFrom`).\n */\n\nimport {\n assertSplitHueFormat,\n claimHueVars,\n claimValueProps,\n type ChannelCtx,\n type HueVarLabels,\n type SplitHueOwners,\n} from './channels';\nimport { getConfig } from './config';\nimport { assertAllPastel, assertNativeFormat } from './format-guard';\nimport {\n buildCssMap,\n buildDtcgMap,\n buildDtcgResolver,\n buildFlatTokenMap,\n buildJsonMap,\n buildTailwindLines,\n buildTokenMap,\n DEFAULT_TAILWIND_HDR_SELECTOR,\n emitTailwindCss,\n emptySchemeLines,\n emptyTailwindLines,\n joinSchemeLines,\n mergeTailwindLines,\n resolveModes,\n SCHEMES,\n} from './formatters';\nimport {\n assertExportKind,\n assertExportVersion,\n assertNoLegacyShadows,\n GLAZE_EXPORT_VERSION,\n} from './serialize';\nimport { createTheme } from './theme';\nimport type {\n ColorMap,\n GlazeCssResult,\n GlazeCssSchemeBlocks,\n GlazeConfigOverride,\n GlazeDtcgOptions,\n GlazeDtcgResolverDocument,\n GlazeDtcgResolverOptions,\n GlazeDtcgResult,\n GlazeJsonOptions,\n GlazePalette,\n GlazePaletteExport,\n GlazePaletteCssOptions,\n GlazePaletteExportOptions,\n GlazePaletteOptions,\n GlazePaletteTastyOptions,\n GlazeTailwindOptions,\n GlazeTheme,\n GlazeThemeExport,\n ResolvedColor,\n} from './types';\nimport type { GlazeTailwindLines } from './formatters';\n\ntype PaletteInput = Record<string, GlazeTheme>;\n\nfunction resolvePrefix(\n options: { prefix?: boolean | Record<string, string> } | undefined,\n themeName: string,\n defaultPrefix = false,\n): string {\n const prefix = options?.prefix ?? defaultPrefix;\n if (prefix === true) {\n return `${themeName}-`;\n }\n if (typeof prefix === 'object' && prefix !== null) {\n return prefix[themeName] ?? `${themeName}-`;\n }\n return '';\n}\n\nfunction validatePrimaryTheme(\n primary: string | undefined,\n themes: PaletteInput,\n): void {\n if (primary !== undefined && !(primary in themes)) {\n const available = Object.keys(themes).join(', ');\n throw new Error(\n `glaze: primary theme \"${primary}\" not found in palette. Available: ${available}.`,\n );\n }\n}\n\n/**\n * Resolve the effective primary for an export call.\n * `false` disables, a string overrides, `undefined` inherits from palette.\n */\nfunction resolveEffectivePrimary(\n exportPrimary: string | false | undefined,\n palettePrimary: string | undefined,\n): string | undefined {\n if (exportPrimary === false) return undefined;\n return exportPrimary ?? palettePrimary;\n}\n\n/**\n * Filter a resolved color map, skipping keys already in `seen`.\n * Warns on collision and keeps the first-written value (first-write-wins).\n * Returns a new map containing only non-colliding entries.\n */\nfunction filterCollisions(\n resolved: Map<string, ResolvedColor>,\n prefix: string,\n seen: Map<string, string>,\n themeName: string,\n isPrimary?: boolean,\n): Map<string, ResolvedColor> {\n const filtered = new Map<string, ResolvedColor>();\n const label = isPrimary ? `${themeName} (primary)` : themeName;\n\n for (const [name, color] of resolved) {\n const key = `${prefix}${name}`;\n if (seen.has(key)) {\n console.warn(\n `glaze: token \"${key}\" from theme \"${label}\" collides with theme \"${seen.get(key)}\" — skipping.`,\n );\n continue;\n }\n seen.set(key, label);\n filtered.set(name, color);\n }\n return filtered;\n}\n\nfunction colorMapFromTheme(theme: GlazeTheme): ColorMap {\n const defs: ColorMap = {};\n for (const name of theme.list()) {\n const def = theme.color(name);\n if (def !== undefined) defs[name] = def;\n }\n return defs;\n}\n\n/**\n * `splitHue` context for one theme pass of `palette.tasty()` / `css()`, or\n * `undefined` without `splitHue` (the caller has already checked the format).\n * `hueOwners` is shared by every pass of one export call, so a property two\n * declarations would share — a color named after another theme under an empty\n * prefix, or (`css()`, which passes its `suffix`) a color's value property\n * landing on a hue var — throws instead of one silently overriding the other.\n * Value properties are claimed on the primary's alias pass too: it declares no\n * hue vars, but its unprefixed values are emitted all the same.\n */\nfunction channelCtxForTheme(\n theme: GlazeTheme,\n themeName: string,\n passPrefix: string,\n themedPrefix: string,\n splitHue: boolean | undefined,\n modes: ReturnType<typeof resolveModes>,\n filtered: Map<string, ResolvedColor>,\n hueOwners: SplitHueOwners,\n valueSuffix?: string,\n): ChannelCtx | undefined {\n if (!splitHue) return undefined;\n assertAllPastel(filtered, modes);\n // The primary's unprefixed alias pass, which only references the hue vars\n // its prefixed pass declares.\n const aliasPass = passPrefix !== themedPrefix;\n const ctx: ChannelCtx = {\n seedHue: theme.hue,\n darkSeedHue: theme.darkHue,\n baseName: themeName,\n // Hue var names always follow the themed prefix so the primary's\n // unprefixed alias references `--{themeName}-*-hue` rather than colliding\n // with other themes' base vars.\n prefix: themedPrefix,\n defs: colorMapFromTheme(theme),\n mode: 'theme',\n // Emit declarations only in the pass whose color-prop prefix matches the\n // themed prefix (the prefixed pass, or the single pass when prefix:false).\n emitDeclarations: !aliasPass,\n };\n const labels: HueVarLabels = {\n theme: `the hue of theme \"${themeName}\"`,\n color: (name) => `color \"${name}\"'s own hue (theme \"${themeName}\")`,\n value: (name) =>\n aliasPass\n ? `the primary alias of color \"${name}\" (theme \"${themeName}\")`\n : `color \"${name}\"'s value (theme \"${themeName}\")`,\n fix:\n 'Rename the color or the theme, or give the theme a prefix that ' +\n 'keeps its hue vars apart.',\n valueFix:\n 'Rename the color or the theme, or pass a different `suffix` or ' +\n 'theme prefix.',\n };\n claimHueVars(filtered, ctx, hueOwners, labels);\n if (valueSuffix !== undefined) {\n claimValueProps(filtered, passPrefix, valueSuffix, hueOwners, labels);\n }\n return ctx;\n}\n\n/**\n * Shared per-theme driver for `tokens` / `tasty` / `css`. `json` skips\n * this because it doesn't do collision filtering or primary duplication.\n */\nfunction buildPaletteOutput<T, R>(\n themes: PaletteInput,\n paletteOptions: GlazePaletteOptions | undefined,\n options:\n | {\n prefix?: boolean | Record<string, string>;\n primary?: string | false;\n }\n | undefined,\n buildOne: (\n resolved: Map<string, ResolvedColor>,\n prefix: string,\n pastel: boolean,\n themeName: string,\n theme: GlazeTheme,\n ) => T,\n merge: (acc: R, part: T) => void,\n empty: () => R,\n): R {\n const effectivePrimary = resolveEffectivePrimary(\n options?.primary,\n paletteOptions?.primary,\n );\n if (options?.primary !== undefined) {\n validatePrimaryTheme(effectivePrimary, themes);\n }\n\n const acc = empty();\n const seen = new Map<string, string>();\n\n for (const [themeName, theme] of Object.entries(themes)) {\n const resolved = theme.resolve();\n const pastel = theme.getConfig().pastel;\n const prefix = resolvePrefix(options, themeName, true);\n const filtered = filterCollisions(resolved, prefix, seen, themeName);\n merge(acc, buildOne(filtered, prefix, pastel, themeName, theme));\n\n if (themeName === effectivePrimary) {\n const primaryFiltered = filterCollisions(\n resolved,\n '',\n seen,\n themeName,\n true,\n );\n merge(acc, buildOne(primaryFiltered, '', pastel, themeName, theme));\n }\n }\n\n return acc;\n}\n\n/** Rebuild a theme from a `theme.export()` snapshot. */\nexport function createThemeFromExport(\n data: GlazeThemeExport,\n factory = 'glaze.themeFrom',\n fallbackVersion?: unknown,\n): GlazeTheme {\n if (data === null || typeof data !== 'object') {\n throw new Error(\n `${factory}: expected an object from theme.export(), got ${data === null ? 'null' : typeof data}.`,\n );\n }\n assertExportKind(data, 'theme', factory);\n assertExportVersion(data, factory);\n assertNoLegacyShadows(data, factory, fallbackVersion);\n if (typeof data.hue !== 'number' || typeof data.saturation !== 'number') {\n throw new Error(\n `${factory}: expected numeric \"hue\" and \"saturation\" fields.`,\n );\n }\n for (const field of ['darkHue', 'darkSaturation'] as const) {\n if (data[field] !== undefined && typeof data[field] !== 'number') {\n throw new Error(\n `${factory}: expected \"${field}\" to be a number when present (got ${JSON.stringify(data[field])}).`,\n );\n }\n }\n return createTheme(\n {\n hue: data.hue,\n saturation: data.saturation,\n darkHue: data.darkHue,\n darkSaturation: data.darkSaturation,\n },\n data.colors,\n data.config,\n );\n}\n\n/**\n * Rebuild a palette from a `palette.export()` snapshot.\n */\nexport function createPaletteFromExport(\n data: GlazePaletteExport,\n): GlazePalette {\n if (data === null || typeof data !== 'object') {\n throw new Error(\n `glaze.paletteFrom: expected an object from palette.export(), got ${data === null ? 'null' : typeof data}.`,\n );\n }\n assertExportKind(data, 'palette', 'glaze.paletteFrom');\n assertExportVersion(data, 'glaze.paletteFrom');\n if (data.themes === null || typeof data.themes !== 'object') {\n throw new Error(\n `glaze.paletteFrom: expected a \"themes\" object map of theme exports.`,\n );\n }\n\n const rebuilt: PaletteInput = {};\n for (const [name, themeExport] of Object.entries(data.themes)) {\n rebuilt[name] = createThemeFromExport(\n themeExport,\n `glaze.paletteFrom (theme \"${name}\")`,\n data.version,\n );\n }\n\n return createPalette(rebuilt, {\n primary: data.primary,\n });\n}\n\nexport function createPalette(\n themes: PaletteInput,\n paletteOptions?: GlazePaletteOptions,\n): GlazePalette {\n validatePrimaryTheme(paletteOptions?.primary, themes);\n\n const buildDtcgResult = (\n options?: GlazeDtcgOptions & GlazePaletteExportOptions,\n ): GlazeDtcgResult => {\n const modes = resolveModes(options?.modes);\n const colorSpace = options?.colorSpace ?? 'srgb';\n return buildPaletteOutput<GlazeDtcgResult, GlazeDtcgResult>(\n themes,\n paletteOptions,\n options,\n (filtered, prefix, pastel, _themeName, _theme) =>\n buildDtcgMap(filtered, prefix, modes, colorSpace, pastel),\n (acc, part) => {\n Object.assign(acc.light, part.light);\n if (part.dark) {\n acc.dark = Object.assign(acc.dark ?? {}, part.dark);\n }\n if (part.lightContrast) {\n acc.lightContrast = Object.assign(\n acc.lightContrast ?? {},\n part.lightContrast,\n );\n }\n if (part.darkContrast) {\n acc.darkContrast = Object.assign(\n acc.darkContrast ?? {},\n part.darkContrast,\n );\n }\n },\n () => ({ light: {} }),\n );\n };\n\n return {\n list(): string[] {\n return Object.keys(themes);\n },\n\n get primary(): string | undefined {\n return paletteOptions?.primary;\n },\n\n theme(name: string): GlazeTheme | undefined {\n return themes[name];\n },\n\n themes(): Record<string, GlazeTheme> {\n return { ...themes };\n },\n\n export(override?: GlazeConfigOverride): GlazePaletteExport {\n const themesExport: Record<string, GlazeThemeExport> = {};\n for (const [name, theme] of Object.entries(themes)) {\n themesExport[name] = theme.export(override);\n }\n const out: GlazePaletteExport = {\n kind: 'palette',\n version: GLAZE_EXPORT_VERSION,\n themes: themesExport,\n };\n if (paletteOptions?.primary !== undefined) {\n out.primary = paletteOptions.primary;\n }\n return out;\n },\n\n tokens(\n options?: GlazeJsonOptions & GlazePaletteExportOptions,\n ): Record<string, Record<string, string>> {\n const format = options?.format ?? 'oklch';\n assertNativeFormat(format, 'tokens');\n const modes = resolveModes(options?.modes);\n return buildPaletteOutput<\n Record<string, Record<string, string>>,\n Record<string, Record<string, string>>\n >(\n themes,\n paletteOptions,\n options,\n (filtered, prefix, pastel) =>\n buildFlatTokenMap(filtered, prefix, modes, format, pastel),\n (acc, part) => {\n for (const variant of Object.keys(part)) {\n if (!acc[variant]) {\n acc[variant] = {};\n }\n Object.assign(acc[variant], part[variant]);\n }\n },\n () => ({}),\n );\n },\n\n tasty(\n options?: GlazePaletteTastyOptions,\n ): Record<string, Record<string, string>> {\n const cfg = getConfig();\n const states = {\n dark: options?.states?.dark ?? cfg.states.dark,\n highContrast: options?.states?.highContrast ?? cfg.states.highContrast,\n hdr: options?.states?.hdr ?? cfg.states.hdr,\n };\n const modes = resolveModes(options?.modes);\n const format = options?.format ?? 'oklch';\n assertSplitHueFormat(options?.splitHue, format);\n const hueOwners: SplitHueOwners = new Map();\n return buildPaletteOutput<\n Record<string, Record<string, string>>,\n Record<string, Record<string, string>>\n >(\n themes,\n paletteOptions,\n options,\n (filtered, prefix, pastel, themeName, theme) => {\n const themedPrefix = resolvePrefix(options, themeName, true);\n const channelCtx = channelCtxForTheme(\n theme,\n themeName,\n prefix,\n themedPrefix,\n options?.splitHue,\n modes,\n filtered,\n hueOwners,\n );\n return buildTokenMap(\n filtered,\n prefix,\n states,\n modes,\n format,\n pastel,\n channelCtx,\n );\n },\n (acc, part) => Object.assign(acc, part),\n () => ({}),\n );\n },\n\n json(\n options?: GlazeJsonOptions,\n ): Record<string, Record<string, Record<string, string>>> {\n const format = options?.format ?? 'oklch';\n assertNativeFormat(format, 'json');\n const modes = resolveModes(options?.modes);\n const result: Record<string, Record<string, Record<string, string>>> = {};\n\n for (const [themeName, theme] of Object.entries(themes)) {\n const resolved = theme.resolve();\n result[themeName] = buildJsonMap(\n resolved,\n modes,\n format,\n theme.getConfig().pastel,\n );\n }\n\n return result;\n },\n\n css(options?: GlazePaletteCssOptions): GlazeCssResult {\n const suffix = options?.suffix ?? '-color';\n const format = options?.format ?? 'oklch';\n assertNativeFormat(format, 'css');\n assertSplitHueFormat(options?.splitHue, format);\n const modes = resolveModes();\n const hdr = options?.hdr ?? modes.hdr;\n const hueOwners: SplitHueOwners = new Map();\n type SchemeLines = Record<keyof GlazeCssSchemeBlocks, string[]>;\n\n const lines = buildPaletteOutput<\n GlazeCssResult,\n { sdr: SchemeLines; hdr: SchemeLines }\n >(\n themes,\n paletteOptions,\n options,\n (filtered, prefix, pastel, themeName, theme) => {\n const themedPrefix = resolvePrefix(options, themeName, true);\n const channelCtx = channelCtxForTheme(\n theme,\n themeName,\n prefix,\n themedPrefix,\n options?.splitHue,\n modes,\n filtered,\n hueOwners,\n suffix,\n );\n return buildCssMap(\n filtered,\n prefix,\n suffix,\n format,\n pastel,\n channelCtx,\n hdr,\n );\n },\n (acc, part) => {\n for (const key of SCHEMES) {\n if (part[key]) acc.sdr[key].push(part[key]);\n if (part.hdr?.[key]) acc.hdr[key].push(part.hdr[key]);\n }\n },\n () => ({ sdr: emptySchemeLines(), hdr: emptySchemeLines() }),\n );\n\n const result: GlazeCssResult = joinSchemeLines(lines.sdr);\n if (hdr) result.hdr = joinSchemeLines(lines.hdr);\n return result;\n },\n\n dtcg(\n options?: GlazeDtcgOptions & GlazePaletteExportOptions,\n ): GlazeDtcgResult {\n return buildDtcgResult(options);\n },\n\n dtcgResolver(\n options?: GlazeDtcgResolverOptions & GlazePaletteExportOptions,\n ): GlazeDtcgResolverDocument {\n return buildDtcgResolver(buildDtcgResult(options), options);\n },\n\n tailwind(\n options?: GlazeTailwindOptions & GlazePaletteExportOptions,\n ): string {\n const modes = resolveModes(options?.modes);\n const cssPrefix = options?.namespace ?? 'color-';\n const format = options?.format ?? 'oklch';\n assertNativeFormat(format, 'tailwind');\n const darkSelector = options?.darkSelector ?? '.dark';\n const highContrastSelector =\n options?.highContrastSelector ?? '.high-contrast';\n const hdrSelector = options?.hdrSelector ?? DEFAULT_TAILWIND_HDR_SELECTOR;\n\n const lines = buildPaletteOutput<GlazeTailwindLines, GlazeTailwindLines>(\n themes,\n paletteOptions,\n options,\n (filtered, prefix, pastel, _themeName, _theme) =>\n buildTailwindLines(\n filtered,\n prefix,\n cssPrefix,\n format,\n pastel,\n modes,\n ),\n mergeTailwindLines,\n emptyTailwindLines,\n );\n\n return emitTailwindCss(\n lines,\n modes,\n darkSelector,\n highContrastSelector,\n hdrSelector,\n );\n },\n };\n}\n","/**\n * Glaze — OKHST color theme generator.\n *\n * Public API entry. Wires `glaze()` and its attached static methods to\n * the focused modules in this folder:\n * - `theme.ts` — single-theme factory\n * - `palette.ts` — multi-theme composition\n * - `color-token.ts` — standalone single-color tokens (`glaze.color`)\n * - `lighting.ts` — shadow / glow solver (`glaze.shadow`, `glaze.glow`,\n * including a glow's HDR value)\n * - `formatters.ts` — variant → string (`glaze.format`, `glaze.formatHdr`)\n * - `config.ts` — global config singleton\n * - `serialize.ts` — authoring export type guards / version checks\n */\n\nimport { parseHex, srgbToOkhsl } from './okhsl-color-math';\nimport {\n configure as configureImpl,\n getConfig,\n normalizeLightingTuning,\n resetConfig as resetConfigImpl,\n snapshotConfig,\n} from './config';\nimport {\n colorFromExport,\n createColorToken,\n createColorTokenFromValue,\n} from './color-token';\nimport { extractOkhslFromValue } from './color-value';\nimport { formatHdrVariant, formatVariant } from './formatters';\nimport {\n computeLighting,\n resolveLightingTuning,\n toResolvedHdr,\n} from './lighting';\nimport type { LightingKind } from './lighting';\nimport { showValue } from './hc-pair';\nimport { okhslToOkhst } from './okhst';\nimport { warnLightingShortfall } from './warnings';\nimport {\n createPalette,\n createPaletteFromExport,\n createThemeFromExport,\n} from './palette';\nimport {\n isColorTokenExport,\n isPaletteExport,\n isThemeExport,\n} from './serialize';\nimport { createTheme } from './theme';\nimport type {\n GlazeColorFormat,\n GlazeColorInput,\n GlazeColorToken,\n GlazeColorTokenExport,\n GlazeColorValue,\n GlazeConfig,\n GlazeConfigOverride,\n GlazeConfigResolved,\n GlazeFromInput,\n GlazeGlowInput,\n GlazeHdrFormat,\n GlazeLightingInput,\n GlazePalette,\n GlazePaletteExport,\n GlazePaletteOptions,\n GlazeShadowInput,\n GlazeTheme,\n GlazeThemeExport,\n GlazeThemeSeed,\n ResolvedColorVariant,\n} from './types';\n\ntype PaletteInput = Record<string, GlazeTheme>;\n\n/**\n * Create a single-hue glaze theme.\n *\n * An optional `config` override can be supplied to customize the resolve\n * behavior for this theme (tone windows, etc.). The\n * override is **merged over the live global config at resolve time** —\n * the theme still reacts to later `configure()` calls for fields it\n * didn't override.\n *\n * The object form also accepts `darkHue` / `darkSaturation` — a separate\n * seed pair for the dark and dark-high-contrast schemes. Both default to\n * their light counterparts, and an explicit `darkSaturation` opts the theme\n * out of the global `darkDesaturation` reduction.\n *\n * @example\n * ```ts\n * const primary = glaze(280, 80);\n * // or shorthand:\n * const primary = glaze({ hue: 280, saturation: 80 });\n * // with a retuned dark seed:\n * const primary = glaze({ hue: 280, saturation: 80, darkHue: 268, darkSaturation: 65 });\n * // with config override:\n * const raw = glaze(280, 80, { lightTone: false });\n * const rawSeed = glaze({ hue: 280, saturation: 80 }, { lightTone: false });\n * ```\n */\nexport function glaze(\n hue: number,\n saturation?: number,\n config?: GlazeConfigOverride,\n): GlazeTheme;\nexport function glaze(\n seed: GlazeThemeSeed,\n config?: GlazeConfigOverride,\n): GlazeTheme;\n/** @deprecated Pass the config second: `glaze(seed, config)`. */\nexport function glaze(\n seed: GlazeThemeSeed,\n saturation: undefined,\n config?: GlazeConfigOverride,\n): GlazeTheme;\nexport function glaze(\n hueOrOptions: number | GlazeThemeSeed,\n saturationOrConfig?: number | GlazeConfigOverride,\n config?: GlazeConfigOverride,\n): GlazeTheme {\n if (typeof hueOrOptions === 'number') {\n const saturation =\n typeof saturationOrConfig === 'number' ? saturationOrConfig : undefined;\n // `glaze(hue, config)` is not a typed form, but dropping the config\n // without a word would be worse than taking it. A third argument still\n // wins, as it always did.\n const override =\n (config === undefined || config === null) &&\n typeof saturationOrConfig === 'object' &&\n saturationOrConfig !== null\n ? saturationOrConfig\n : config;\n return createTheme(\n { hue: hueOrOptions, saturation: saturation ?? 100 },\n undefined,\n override,\n );\n }\n // The object form takes its override second; the older\n // `glaze(seed, undefined, config)` spelling still works.\n const override =\n typeof saturationOrConfig === 'object' && saturationOrConfig !== null\n ? saturationOrConfig\n : config;\n return createTheme(hueOrOptions, undefined, override);\n}\n\n/** Configure global glaze settings. */\nglaze.configure = function configure(config: GlazeConfig): void {\n configureImpl(config);\n};\n\n/** Compose multiple themes into a palette. */\nglaze.palette = function palette(\n themes: PaletteInput,\n options?: GlazePaletteOptions,\n): GlazePalette {\n return createPalette(themes, options);\n};\n\n/**\n * Create a theme from a serialized `theme.export()` snapshot.\n * Prefer this over the legacy `glaze.from` alias.\n */\nglaze.themeFrom = function themeFrom(data: GlazeThemeExport): GlazeTheme {\n return createThemeFromExport(data);\n};\n\n/** Compat alias for `glaze.themeFrom`. */\nglaze.from = glaze.themeFrom;\n\n/**\n * Create a standalone single-color token.\n *\n * **arg1 — the color** (four accepted shapes, discriminated by structure):\n *\n * | Shape | Example | Notes |\n * |---|---|---|\n * | Bare string | `'#26fcb2'`, `'rgb(38 252 178)'` | Hex or CSS color function (incl. `okhst()`) |\n * | Value object | `{ h: 152, s: 0.95, l: 0.74 }` | OKHSL, OKHST (`{h,s,t}`), `{r,g,b}`, `{l,c,h}` |\n * | `{ from, ...overrides }` | `{ from: '#fff', base: bg, contrast: 'AA' }` | Value + color overrides |\n * | Structured | `{ hue: 152, saturation: 95, tone: 74 }` | Full theme-style token |\n *\n * **arg2 — config override** (optional, all shapes):\n * Overrides the resolve-relevant global config fields for this token.\n * Fields that are omitted fall through to the live global config at\n * resolve time. Pass `false` for a tone window to disable clamping\n * entirely. `pastel` is instance-only (not set via `configure()`).\n *\n * ```ts\n * // Bare string — no overrides\n * glaze.color('#26fcb2')\n *\n * // From form — value + color overrides\n * glaze.color({ from: '#fff', base: bg, contrast: 'AA' })\n *\n * // Structured form — full theme-style token\n * glaze.color({ hue: 152, saturation: 95, tone: 74 })\n *\n * // Config override on any form\n * glaze.color('#26fcb2', { darkTone: false, autoFlip: false })\n * glaze.color({ from: '#fff', base: bg })\n * ```\n *\n * Defaults: every form defaults to `mode: 'auto'`. Value-shorthand forms\n * (bare strings and value objects) preserve light tone exactly\n * (`lightTone: false` locally). Structured form falls through to the live\n * global tone windows for omitted fields.\n *\n * Relative `tone: '+N'` and `contrast` anchor to the literal seed by\n * default; when `base` is set they anchor to the base's resolved variant\n * per scheme. Relative `hue: '+N'` always anchors to the seed, not the base.\n */\nglaze.color = function color(\n input: GlazeFromInput | GlazeColorInput | GlazeColorValue,\n config?: GlazeConfigOverride,\n): GlazeColorToken {\n if (typeof input === 'string') {\n return createColorTokenFromValue(input, undefined, config);\n }\n\n // Object inputs — discriminate by key presence\n const obj = input as object;\n\n if ('from' in obj) {\n // The token reads its override fields off the input itself (`from` aside),\n // so a getter or a proxy field counts.\n const fromInput = input as GlazeFromInput;\n return createColorTokenFromValue(fromInput.from, fromInput, config);\n }\n\n if ('hue' in obj) {\n return createColorToken(input as GlazeColorInput, config);\n }\n\n // Value-object: { h, s, l }, { h, s, t }, { r, g, b }, or { l, c, h }\n return createColorTokenFromValue(input as GlazeColorValue, undefined, config);\n};\n\n/** Shared body of `glaze.shadow()` / `glaze.glow()`. */\nfunction standaloneLighting(\n kind: LightingKind,\n input: GlazeLightingInput | GlazeGlowInput,\n): ResolvedColorVariant {\n if (input?.bg === undefined) {\n throw new Error(`glaze.${kind}(): \"bg\" is required.`);\n }\n if (\n typeof input.intensity !== 'number' ||\n !Number.isFinite(input.intensity)\n ) {\n throw new Error(\n `glaze.${kind}(): \"intensity\" must be a finite number (got ${showValue(input.intensity)}).`,\n );\n }\n // The parser clamps a value past white or black (an `rgb()` channel over\n // 255, `l` over 1) to white or black, as the browser composites it.\n const bg = extractOkhslFromValue(input.bg as GlazeColorValue);\n const fg = input.fg\n ? extractOkhslFromValue(input.fg as GlazeColorValue)\n : undefined;\n const cfg = getConfig();\n const tuning = resolveLightingTuning(\n normalizeLightingTuning(kind, input.tuning, `glaze.${kind}() tuning`),\n kind === 'shadow' ? cfg.shadowTuning : cfg.glowTuning,\n );\n const result = computeLighting(kind, bg, fg, input.intensity, tuning, false);\n warnLightingShortfall(kind, undefined, undefined, result, tuning.headroom);\n const { h, s, t } = okhslToOkhst({\n h: result.h,\n s: result.s,\n l: result.l,\n });\n const variant: ResolvedColorVariant = { h, s, t, alpha: result.alpha };\n if (result.hdr) variant.hdr = toResolvedHdr(result.hdr);\n return variant;\n}\n\n/**\n * Compute a shadow over a surface: a translucent pigment whose opacity lands\n * `bg` exactly `intensity` tones darker once the browser composites it. The\n * optional object `fg` scales the step (a darker object casts a deeper\n * shadow).\n *\n * Both `bg` and `fg` accept any `GlazeColorValue` form: hex (`#rgb` /\n * `#rgba` / `#rrggbb` / `#rrggbbaa`), `rgb()` / `hsl()` / `okhsl()` /\n * `okhst()` / `oklch()` strings, or `{ r, g, b }` / `{ h, s, l }` /\n * `{ h, s, t }` / `{ l, c, h }` objects. Alpha components are dropped with\n * a warning. `GlazeColorValue` gives each form's component scales.\n */\nglaze.shadow = function shadow(input: GlazeShadowInput): ResolvedColorVariant {\n return standaloneLighting('shadow', input);\n};\n\n/**\n * Compute a glow over a surface — the mirror of `glaze.shadow()`: the\n * composite lands `bg` exactly `intensity` tones lighter, and a lighter\n * object `fg` glows stronger. Accepts the same inputs, plus `tuning.headroom`\n * (merged over the global `glowTuning`): when the step would pass SDR white,\n * the result carries `hdr` — an opaque exposure of the SDR result, formatted\n * by `glaze.formatHdr()` — unless the pigment cannot lift a non-white `bg` at\n * all (see `GlowTuning.headroom`).\n */\nglaze.glow = function glow(input: GlazeGlowInput): ResolvedColorVariant {\n return standaloneLighting('glow', input);\n};\n\n/** Format a resolved color variant as a CSS string. */\nglaze.format = function format(\n variant: ResolvedColorVariant,\n colorFormat?: GlazeColorFormat,\n pastel?: boolean,\n): string {\n return formatVariant(variant, colorFormat, pastel);\n};\n\n/**\n * Format a variant's HDR value — set on a glow whose step crosses SDR white\n * with `headroom` above 0 — as extended `color(srgb R G B)`, with channels\n * that may exceed 1 (`1` is SDR white), or as the same color in linear light\n * with `'srgb-linear'`. Returns `undefined` for a variant without one.\n *\n * @example\n * ```ts\n * const v = glaze.glow({ bg: '#ffffff', intensity: 12, tuning: { headroom: 1 } });\n * glaze.format(v); // SDR: 'oklch(1 0 0)'\n * glaze.formatHdr(v); // 'color(srgb 1.1813 1.1813 1.1813)'\n * glaze.formatHdr(v, 'srgb-linear'); // 'color(srgb-linear 1.4631 1.4631 1.4631)'\n * ```\n */\nglaze.formatHdr = function formatHdr(\n variant: ResolvedColorVariant,\n hdrFormat: GlazeHdrFormat = 'srgb',\n): string | undefined {\n return formatHdrVariant(variant, hdrFormat);\n};\n\n/**\n * Create a theme from a hex color string.\n * Extracts hue and saturation from the color.\n */\nglaze.fromHex = function fromHex(hex: string): GlazeTheme {\n const rgb = parseHex(hex);\n if (!rgb) {\n throw new Error(`glaze: invalid hex color \"${hex}\".`);\n }\n const [h, s] = srgbToOkhsl(rgb);\n return createTheme({ hue: h, saturation: s * 100 });\n};\n\n/**\n * Create a theme from RGB values (0–255).\n * Extracts hue and saturation from the color.\n */\nglaze.fromRgb = function fromRgb(r: number, g: number, b: number): GlazeTheme {\n const [h, s] = srgbToOkhsl([r / 255, g / 255, b / 255]);\n return createTheme({ hue: h, saturation: s * 100 });\n};\n\n/**\n * Rehydrate a `glaze.color()` token from a `.export()` snapshot.\n *\n * The snapshot is a plain JSON-safe object containing the original\n * input value, overrides (with any `base` token recursively serialized),\n * and the effective config freeze from export time. The reconstructed\n * token pins that freeze as its local override.\n *\n * @example\n * ```ts\n * const text = glaze.color({ from: '#1a1a1a', contrast: 'AA' });\n * const data = text.export(); // JSON-safe\n * localStorage.setItem('text', JSON.stringify(data));\n * // ...later...\n * const restored = glaze.colorFrom(JSON.parse(localStorage.getItem('text')!));\n * ```\n */\nglaze.colorFrom = function colorFrom(\n data: GlazeColorTokenExport,\n): GlazeColorToken {\n return colorFromExport(data);\n};\n\n/**\n * Rehydrate a palette from a `palette.export()` snapshot.\n */\nglaze.paletteFrom = function paletteFrom(\n data: GlazePaletteExport,\n): GlazePalette {\n return createPaletteFromExport(data);\n};\n\n// Typed explicitly: the declaration bundler would write `typeof isThemeExport`\n// inside `namespace glaze`, where the name means the static itself, and the\n// published guard would come out as `any`.\n\n/** Type guard for theme authoring snapshots. */\nglaze.isThemeExport = isThemeExport as (\n value: unknown,\n) => value is GlazeThemeExport;\n\n/** Type guard for color-token authoring snapshots. */\nglaze.isColorTokenExport = isColorTokenExport as (\n value: unknown,\n) => value is GlazeColorTokenExport;\n\n/** Type guard for palette authoring snapshots. */\nglaze.isPaletteExport = isPaletteExport as (\n value: unknown,\n) => value is GlazePaletteExport;\n\n/** Get the current global configuration (for testing/debugging). */\nglaze.getConfig = function getConfig(): GlazeConfigResolved {\n return snapshotConfig();\n};\n\n/** Reset global configuration to defaults. */\nglaze.resetConfig = function resetConfig(): void {\n resetConfigImpl();\n};\n"],"mappings":"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"}