From 4b1607118db445d6f697cbf0ca4c7756ded0fb8e Mon Sep 17 00:00:00 2001 From: Gjore Milevski Date: Thu, 23 Jul 2026 16:41:35 +0200 Subject: [PATCH 1/8] chore: add radix token generator --- package.json | 2 + scripts/generate_radix_tokens.mjs | 342 ++++++++++++++++++++++++++++++ 2 files changed, 344 insertions(+) create mode 100644 scripts/generate_radix_tokens.mjs diff --git a/package.json b/package.json index 6914087..32b7ac1 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,8 @@ "typecheck": "tsc --noEmit -p tsconfig.json", "test": "vitest run", "test:watch": "vitest", + "tokens:gen": "node scripts/generate_radix_tokens.mjs", + "tokens:check": "node scripts/generate_radix_tokens.mjs --check", "docs:gen": "python scripts/build_widget_docs.py", "skill:gen": "python scripts/build_skill_reference.py", "serve": "python -m http.server -d docs/_build/html 3030", diff --git a/scripts/generate_radix_tokens.mjs b/scripts/generate_radix_tokens.mjs new file mode 100644 index 0000000..e0db52a --- /dev/null +++ b/scripts/generate_radix_tokens.mjs @@ -0,0 +1,342 @@ +#!/usr/bin/env node +// Generate src/manywidgets/themes/_radix_tokens.py from the latest Radix Themes +// package. This is intentionally build-time only; manywidgets does not import +// @radix-ui/themes or React at runtime. +// +// Usage: +// npm run tokens:gen +// node scripts/generate_radix_tokens.mjs --check +// node scripts/generate_radix_tokens.mjs --source /path/to/unpacked/radix-ui-themes + +import { existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs"; +import os from "node:os"; +import path from "node:path"; +import { spawnSync } from "node:child_process"; +import { fileURLToPath } from "node:url"; + +const DEFAULT_RADIX_THEMES_SPEC = "latest"; + +const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); +const defaultOutput = path.join(root, "src", "manywidgets", "themes", "_radix_tokens.py"); + +const colorOrder = [ + "gray", "mauve", "slate", "sage", "olive", "sand", + "amber", "blue", "bronze", "brown", "crimson", "cyan", "gold", "grass", + "green", "indigo", "iris", "jade", "lime", "mint", "orange", "pink", + "plum", "purple", "red", "ruby", "sky", "teal", "tomato", "violet", "yellow", +]; + +const accentColors = [ + "gray", "gold", "bronze", "brown", "yellow", "amber", "orange", "tomato", + "red", "ruby", "crimson", "pink", "plum", "purple", "violet", "iris", + "indigo", "blue", "cyan", "teal", "jade", "green", "grass", "lime", "mint", "sky", +]; + +const grayColors = ["auto", "gray", "mauve", "slate", "sage", "olive", "sand"]; + +const matchingGrayColors = { + tomato: "mauve", + red: "mauve", + ruby: "mauve", + crimson: "mauve", + pink: "mauve", + plum: "mauve", + purple: "mauve", + violet: "mauve", + iris: "slate", + indigo: "slate", + blue: "slate", + sky: "slate", + cyan: "slate", + teal: "sage", + jade: "sage", + mint: "sage", + green: "sage", + grass: "olive", + lime: "olive", + yellow: "sand", + amber: "sand", + orange: "sand", + brown: "sand", + gold: "sand", + bronze: "sand", + gray: "gray", +}; + +const args = parseArgs(process.argv.slice(2)); +let tempDir = null; + +try { + const packageRoot = args.source + ? findPackageRoot(path.resolve(args.source)) + : downloadRadixThemesPackage(args.version); + + const tokensRoot = path.join(packageRoot, "tokens"); + const packageVersion = readPackageVersion(packageRoot) ?? args.version; + const output = generatePythonTokens(tokensRoot, packageVersion); + + if (args.check) { + const current = readFileSync(args.output, "utf8"); + if (current !== output) { + console.error(`[manywidgets] ${path.relative(root, args.output)} is out of date.`); + console.error("[manywidgets] run npm run tokens:gen"); + process.exit(1); + } + console.log(`[manywidgets] ${path.relative(root, args.output)} is up to date.`); + } else { + writeFileSync(args.output, output); + console.log(`[manywidgets] wrote ${path.relative(root, args.output)}`); + } +} finally { + if (tempDir) rmSync(tempDir, { recursive: true, force: true }); +} + +function parseArgs(argv) { + const parsed = { + check: false, + output: defaultOutput, + source: null, + version: DEFAULT_RADIX_THEMES_SPEC, + }; + + for (let i = 0; i < argv.length; i += 1) { + const arg = argv[i]; + if (arg === "--check") { + parsed.check = true; + } else if (arg === "--output") { + parsed.output = path.resolve(requiredValue(argv, ++i, "--output")); + } else if (arg === "--source") { + parsed.source = requiredValue(argv, ++i, "--source"); + } else if (arg === "--version") { + parsed.version = requiredValue(argv, ++i, "--version"); + } else if (arg === "-h" || arg === "--help") { + printHelp(); + process.exit(0); + } else { + throw new Error(`Unknown argument: ${arg}`); + } + } + + return parsed; +} + +function requiredValue(argv, index, flag) { + const value = argv[index]; + if (!value || value.startsWith("--")) { + throw new Error(`${flag} requires a value`); + } + return value; +} + +function printHelp() { + console.log(`Usage: node scripts/generate_radix_tokens.mjs [options] + +Options: + --check Fail when _radix_tokens.py is out of date + --output Output Python file + --source Unpacked @radix-ui/themes package root + --version Radix Themes npm version/range/tag for npm pack, default ${DEFAULT_RADIX_THEMES_SPEC} +`); +} + +function findPackageRoot(source) { + const candidates = [ + source, + path.join(source, "package"), + ]; + for (const candidate of candidates) { + if (existsSync(path.join(candidate, "tokens", "colors"))) { + return candidate; + } + } + + throw new Error( + `Could not find packaged Radix tokens under ${source}. ` + + "Use an unpacked @radix-ui/themes npm package with tokens/colors/*.css.", + ); +} + +function downloadRadixThemesPackage(version) { + tempDir = mkdtempSync(path.join(os.tmpdir(), "manywidgets-radix-themes-")); + const pack = spawnSync( + "npm", + ["pack", `@radix-ui/themes@${version}`, "--pack-destination", tempDir, "--silent"], + { encoding: "utf8" }, + ); + + if (pack.status !== 0) { + throw new Error( + [ + `Failed to download @radix-ui/themes@${version}.`, + pack.stderr.trim(), + pack.stdout.trim(), + ].filter(Boolean).join("\n"), + ); + } + + const tarballName = pack.stdout.trim().split(/\s+/).at(-1); + if (!tarballName) { + throw new Error("npm pack did not report a tarball name"); + } + + const tarball = path.isAbsolute(tarballName) + ? tarballName + : path.join(tempDir, tarballName); + const extract = spawnSync("tar", ["-xzf", tarball, "-C", tempDir], { encoding: "utf8" }); + if (extract.status !== 0) { + throw new Error( + [ + `Failed to extract ${tarball}.`, + extract.stderr.trim(), + extract.stdout.trim(), + ].filter(Boolean).join("\n"), + ); + } + + return findPackageRoot(path.join(tempDir, "package")); +} + +function readPackageVersion(packageRoot) { + const packageJsonPath = path.join(packageRoot, "package.json"); + if (!existsSync(packageJsonPath)) return null; + + const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8")); + return typeof packageJson.version === "string" && packageJson.version + ? packageJson.version + : null; +} + +function generatePythonTokens(tokensRoot, version) { + const colorsRoot = path.join(tokensRoot, "colors"); + const light = []; + const dark = []; + + for (const family of colorOrder) { + const css = stripAtRules(readFileSync(path.join(colorsRoot, `${family}.css`), "utf8")); + const common = []; + const blocks = css.matchAll(/([^{}]+)\{([^{}]*)\}/g); + for (const block of blocks) { + const selector = block[1].trim(); + const declarations = parseColorDeclarations(block[2], family); + if (declarations.length === 0) continue; + + if (selector.includes(".dark") || selector.includes(".dark-theme")) { + dark.push(...declarations); + } else if (selector.includes(".light") || selector.includes(":root")) { + if (selector === ":root") common.push(...declarations); + else light.push(...declarations); + } + } + light.push(...common); + dark.push(...common); + } + + const rootColorTokens = parseRootAlphaTokens( + stripAtRules(readFileSync(path.join(tokensRoot, "base.css"), "utf8")), + ); + + return `# Generated by scripts/generate_radix_tokens.mjs from @radix-ui/themes@${version}. +# Values are adapted to the manywidgets --mw-* namespace. +# The generator uses the sRGB declarations and skips display-p3 @supports overrides. + +from __future__ import annotations + +RADIX_COLOR_FAMILIES = ${pyTuple(colorOrder)} + +RADIX_ACCENT_COLORS = ${pyTuple(accentColors)} + +RADIX_GRAY_COLORS = ${pyTuple(grayColors)} + +RADIX_MATCHING_GRAY_COLORS = ${pySimpleDict(matchingGrayColors)} + +RADIX_ROOT_COLOR_TOKENS = ${pyDict(rootColorTokens)} + +RADIX_LIGHT_COLOR_TOKENS = ${pyDict(light)} + +RADIX_DARK_COLOR_TOKENS = ${pyDict(dark)} +`; +} + +function stripAtRules(css) { + let out = ""; + for (let i = 0; i < css.length;) { + if (css.startsWith("@supports", i)) { + const open = css.indexOf("{", i); + if (open === -1) break; + let depth = 0; + let j = open; + for (; j < css.length; j += 1) { + if (css[j] === "{") depth += 1; + else if (css[j] === "}") { + depth -= 1; + if (depth === 0) { + j += 1; + break; + } + } + } + i = j; + } else { + out += css[i]; + i += 1; + } + } + return out; +} + +function parseColorDeclarations(body, family) { + const out = []; + const re = /--([a-z-]+)-(a?\d+|contrast|surface|indicator|track):\s*([^;]+);/g; + let match; + while ((match = re.exec(body))) { + const name = match[1]; + const suffix = match[2]; + if (name !== family) continue; + out.push([`--mw-${family}-${suffix}`, normalizeValue(match[3])]); + if (family === "gray") { + out.push([`--mw-radix-gray-${suffix}`, normalizeValue(match[3])]); + } + } + return out; +} + +function parseRootAlphaTokens(css) { + const out = []; + const rootBlocks = css.matchAll(/:root\s*\{([^{}]*)\}/g); + for (const block of rootBlocks) { + const re = /--(black|white)-a(\d+):\s*([^;]+);/g; + let match; + while ((match = re.exec(block[1]))) { + out.push([`--mw-${match[1]}-a${match[2]}`, normalizeValue(match[3])]); + } + } + return out; +} + +function normalizeValue(value) { + return value.trim().replace(/var\(--([a-z-]+)(-[a-z0-9]+)?\)/g, (_match, name, suffix = "") => { + return `var(--mw-${name}${suffix})`; + }); +} + +function pyTuple(values) { + if (values.length === 0) return "()"; + return `(\n${values.map((value) => ` ${JSON.stringify(value)},`).join("\n")}\n)`; +} + +function pySimpleDict(obj) { + const lines = Object.entries(obj).map(([key, value]) => { + return ` ${JSON.stringify(key)}: ${JSON.stringify(value)},`; + }); + return `{\n${lines.join("\n")}\n}`; +} + +function pyDict(entries) { + const seen = new Map(); + for (const [key, value] of entries) seen.set(key, value); + const lines = []; + for (const [key, value] of seen.entries()) { + lines.push(` ${JSON.stringify(key)}: ${JSON.stringify(value)},`); + } + return `{\n${lines.join("\n")}\n}`; +} From 76d61ddb6ff6d22451eb633eef37f5e8749b9d73 Mon Sep 17 00:00:00 2001 From: Gjore Milevski Date: Thu, 23 Jul 2026 16:41:48 +0200 Subject: [PATCH 2/8] chore: add generated radix tokens --- .gitattributes | 1 + src/manywidgets/themes/_radix_tokens.py | 1932 +++++++++++++++++++++++ 2 files changed, 1933 insertions(+) create mode 100644 .gitattributes create mode 100644 src/manywidgets/themes/_radix_tokens.py diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..0378ea0 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +src/manywidgets/themes/_radix_tokens.py linguist-generated=true diff --git a/src/manywidgets/themes/_radix_tokens.py b/src/manywidgets/themes/_radix_tokens.py new file mode 100644 index 0000000..7cb5755 --- /dev/null +++ b/src/manywidgets/themes/_radix_tokens.py @@ -0,0 +1,1932 @@ +# Generated by scripts/generate_radix_tokens.mjs from @radix-ui/themes@3.3.0. +# Values are adapted to the manywidgets --mw-* namespace. +# The generator uses the sRGB declarations and skips display-p3 @supports overrides. + +from __future__ import annotations + +RADIX_COLOR_FAMILIES = ( + "gray", + "mauve", + "slate", + "sage", + "olive", + "sand", + "amber", + "blue", + "bronze", + "brown", + "crimson", + "cyan", + "gold", + "grass", + "green", + "indigo", + "iris", + "jade", + "lime", + "mint", + "orange", + "pink", + "plum", + "purple", + "red", + "ruby", + "sky", + "teal", + "tomato", + "violet", + "yellow", +) + +RADIX_ACCENT_COLORS = ( + "gray", + "gold", + "bronze", + "brown", + "yellow", + "amber", + "orange", + "tomato", + "red", + "ruby", + "crimson", + "pink", + "plum", + "purple", + "violet", + "iris", + "indigo", + "blue", + "cyan", + "teal", + "jade", + "green", + "grass", + "lime", + "mint", + "sky", +) + +RADIX_GRAY_COLORS = ( + "auto", + "gray", + "mauve", + "slate", + "sage", + "olive", + "sand", +) + +RADIX_MATCHING_GRAY_COLORS = { + "tomato": "mauve", + "red": "mauve", + "ruby": "mauve", + "crimson": "mauve", + "pink": "mauve", + "plum": "mauve", + "purple": "mauve", + "violet": "mauve", + "iris": "slate", + "indigo": "slate", + "blue": "slate", + "sky": "slate", + "cyan": "slate", + "teal": "sage", + "jade": "sage", + "mint": "sage", + "green": "sage", + "grass": "olive", + "lime": "olive", + "yellow": "sand", + "amber": "sand", + "orange": "sand", + "brown": "sand", + "gold": "sand", + "bronze": "sand", + "gray": "gray", +} + +RADIX_ROOT_COLOR_TOKENS = { + "--mw-black-a1": "rgba(0, 0, 0, 0.05)", + "--mw-black-a2": "rgba(0, 0, 0, 0.1)", + "--mw-black-a3": "rgba(0, 0, 0, 0.15)", + "--mw-black-a4": "rgba(0, 0, 0, 0.2)", + "--mw-black-a5": "rgba(0, 0, 0, 0.3)", + "--mw-black-a6": "rgba(0, 0, 0, 0.4)", + "--mw-black-a7": "rgba(0, 0, 0, 0.5)", + "--mw-black-a8": "rgba(0, 0, 0, 0.6)", + "--mw-black-a9": "rgba(0, 0, 0, 0.7)", + "--mw-black-a10": "rgba(0, 0, 0, 0.8)", + "--mw-black-a11": "rgba(0, 0, 0, 0.9)", + "--mw-black-a12": "rgba(0, 0, 0, 0.95)", + "--mw-white-a1": "rgba(255, 255, 255, 0.05)", + "--mw-white-a2": "rgba(255, 255, 255, 0.1)", + "--mw-white-a3": "rgba(255, 255, 255, 0.15)", + "--mw-white-a4": "rgba(255, 255, 255, 0.2)", + "--mw-white-a5": "rgba(255, 255, 255, 0.3)", + "--mw-white-a6": "rgba(255, 255, 255, 0.4)", + "--mw-white-a7": "rgba(255, 255, 255, 0.5)", + "--mw-white-a8": "rgba(255, 255, 255, 0.6)", + "--mw-white-a9": "rgba(255, 255, 255, 0.7)", + "--mw-white-a10": "rgba(255, 255, 255, 0.8)", + "--mw-white-a11": "rgba(255, 255, 255, 0.9)", + "--mw-white-a12": "rgba(255, 255, 255, 0.95)", +} + +RADIX_LIGHT_COLOR_TOKENS = { + "--mw-gray-1": "#fcfcfc", + "--mw-radix-gray-1": "#fcfcfc", + "--mw-gray-2": "#f9f9f9", + "--mw-radix-gray-2": "#f9f9f9", + "--mw-gray-3": "#f0f0f0", + "--mw-radix-gray-3": "#f0f0f0", + "--mw-gray-4": "#e8e8e8", + "--mw-radix-gray-4": "#e8e8e8", + "--mw-gray-5": "#e0e0e0", + "--mw-radix-gray-5": "#e0e0e0", + "--mw-gray-6": "#d9d9d9", + "--mw-radix-gray-6": "#d9d9d9", + "--mw-gray-7": "#cecece", + "--mw-radix-gray-7": "#cecece", + "--mw-gray-8": "#bbbbbb", + "--mw-radix-gray-8": "#bbbbbb", + "--mw-gray-9": "#8d8d8d", + "--mw-radix-gray-9": "#8d8d8d", + "--mw-gray-10": "#838383", + "--mw-radix-gray-10": "#838383", + "--mw-gray-11": "#646464", + "--mw-radix-gray-11": "#646464", + "--mw-gray-12": "#202020", + "--mw-radix-gray-12": "#202020", + "--mw-gray-a1": "#00000003", + "--mw-radix-gray-a1": "#00000003", + "--mw-gray-a2": "#00000006", + "--mw-radix-gray-a2": "#00000006", + "--mw-gray-a3": "#0000000f", + "--mw-radix-gray-a3": "#0000000f", + "--mw-gray-a4": "#00000017", + "--mw-radix-gray-a4": "#00000017", + "--mw-gray-a5": "#0000001f", + "--mw-radix-gray-a5": "#0000001f", + "--mw-gray-a6": "#00000026", + "--mw-radix-gray-a6": "#00000026", + "--mw-gray-a7": "#00000031", + "--mw-radix-gray-a7": "#00000031", + "--mw-gray-a8": "#00000044", + "--mw-radix-gray-a8": "#00000044", + "--mw-gray-a9": "#00000072", + "--mw-radix-gray-a9": "#00000072", + "--mw-gray-a10": "#0000007c", + "--mw-radix-gray-a10": "#0000007c", + "--mw-gray-a11": "#0000009b", + "--mw-radix-gray-a11": "#0000009b", + "--mw-gray-a12": "#000000df", + "--mw-radix-gray-a12": "#000000df", + "--mw-gray-surface": "#ffffffcc", + "--mw-radix-gray-surface": "#ffffffcc", + "--mw-gray-indicator": "var(--mw-gray-9)", + "--mw-radix-gray-indicator": "var(--mw-gray-9)", + "--mw-gray-track": "var(--mw-gray-9)", + "--mw-radix-gray-track": "var(--mw-gray-9)", + "--mw-gray-contrast": "white", + "--mw-radix-gray-contrast": "white", + "--mw-mauve-1": "#fdfcfd", + "--mw-mauve-2": "#faf9fb", + "--mw-mauve-3": "#f2eff3", + "--mw-mauve-4": "#eae7ec", + "--mw-mauve-5": "#e3dfe6", + "--mw-mauve-6": "#dbd8e0", + "--mw-mauve-7": "#d0cdd7", + "--mw-mauve-8": "#bcbac7", + "--mw-mauve-9": "#8e8c99", + "--mw-mauve-10": "#84828e", + "--mw-mauve-11": "#65636d", + "--mw-mauve-12": "#211f26", + "--mw-mauve-a1": "#55005503", + "--mw-mauve-a2": "#2b005506", + "--mw-mauve-a3": "#30004010", + "--mw-mauve-a4": "#20003618", + "--mw-mauve-a5": "#20003820", + "--mw-mauve-a6": "#14003527", + "--mw-mauve-a7": "#10003332", + "--mw-mauve-a8": "#08003145", + "--mw-mauve-a9": "#05001d73", + "--mw-mauve-a10": "#0500197d", + "--mw-mauve-a11": "#0400119c", + "--mw-mauve-a12": "#020008e0", + "--mw-mauve-surface": "#ffffffcc", + "--mw-mauve-indicator": "var(--mw-mauve-9)", + "--mw-mauve-track": "var(--mw-mauve-9)", + "--mw-mauve-contrast": "white", + "--mw-slate-1": "#fcfcfd", + "--mw-slate-2": "#f9f9fb", + "--mw-slate-3": "#f0f0f3", + "--mw-slate-4": "#e8e8ec", + "--mw-slate-5": "#e0e1e6", + "--mw-slate-6": "#d9d9e0", + "--mw-slate-7": "#cdced6", + "--mw-slate-8": "#b9bbc6", + "--mw-slate-9": "#8b8d98", + "--mw-slate-10": "#80838d", + "--mw-slate-11": "#60646c", + "--mw-slate-12": "#1c2024", + "--mw-slate-a1": "#00005503", + "--mw-slate-a2": "#00005506", + "--mw-slate-a3": "#0000330f", + "--mw-slate-a4": "#00002d17", + "--mw-slate-a5": "#0009321f", + "--mw-slate-a6": "#00002f26", + "--mw-slate-a7": "#00062e32", + "--mw-slate-a8": "#00083046", + "--mw-slate-a9": "#00051d74", + "--mw-slate-a10": "#00071b7f", + "--mw-slate-a11": "#0007149f", + "--mw-slate-a12": "#000509e3", + "--mw-slate-surface": "#ffffffcc", + "--mw-slate-indicator": "var(--mw-slate-9)", + "--mw-slate-track": "var(--mw-slate-9)", + "--mw-slate-contrast": "white", + "--mw-sage-1": "#fbfdfc", + "--mw-sage-2": "#f7f9f8", + "--mw-sage-3": "#eef1f0", + "--mw-sage-4": "#e6e9e8", + "--mw-sage-5": "#dfe2e0", + "--mw-sage-6": "#d7dad9", + "--mw-sage-7": "#cbcfcd", + "--mw-sage-8": "#b8bcba", + "--mw-sage-9": "#868e8b", + "--mw-sage-10": "#7c8481", + "--mw-sage-11": "#5f6563", + "--mw-sage-12": "#1a211e", + "--mw-sage-a1": "#00804004", + "--mw-sage-a2": "#00402008", + "--mw-sage-a3": "#002d1e11", + "--mw-sage-a4": "#001f1519", + "--mw-sage-a5": "#00180820", + "--mw-sage-a6": "#00140d28", + "--mw-sage-a7": "#00140a34", + "--mw-sage-a8": "#000f0847", + "--mw-sage-a9": "#00110b79", + "--mw-sage-a10": "#00100a83", + "--mw-sage-a11": "#000a07a0", + "--mw-sage-a12": "#000805e5", + "--mw-sage-surface": "#ffffffcc", + "--mw-sage-indicator": "var(--mw-sage-9)", + "--mw-sage-track": "var(--mw-sage-9)", + "--mw-sage-contrast": "white", + "--mw-olive-1": "#fcfdfc", + "--mw-olive-2": "#f8faf8", + "--mw-olive-3": "#eff1ef", + "--mw-olive-4": "#e7e9e7", + "--mw-olive-5": "#dfe2df", + "--mw-olive-6": "#d7dad7", + "--mw-olive-7": "#cccfcc", + "--mw-olive-8": "#b9bcb8", + "--mw-olive-9": "#898e87", + "--mw-olive-10": "#7f847d", + "--mw-olive-11": "#60655f", + "--mw-olive-12": "#1d211c", + "--mw-olive-a1": "#00550003", + "--mw-olive-a2": "#00490007", + "--mw-olive-a3": "#00200010", + "--mw-olive-a4": "#00160018", + "--mw-olive-a5": "#00180020", + "--mw-olive-a6": "#00140028", + "--mw-olive-a7": "#000f0033", + "--mw-olive-a8": "#040f0047", + "--mw-olive-a9": "#050f0078", + "--mw-olive-a10": "#040e0082", + "--mw-olive-a11": "#020a00a0", + "--mw-olive-a12": "#010600e3", + "--mw-olive-surface": "#ffffffcc", + "--mw-olive-indicator": "var(--mw-olive-9)", + "--mw-olive-track": "var(--mw-olive-9)", + "--mw-olive-contrast": "white", + "--mw-sand-1": "#fdfdfc", + "--mw-sand-2": "#f9f9f8", + "--mw-sand-3": "#f1f0ef", + "--mw-sand-4": "#e9e8e6", + "--mw-sand-5": "#e2e1de", + "--mw-sand-6": "#dad9d6", + "--mw-sand-7": "#cfceca", + "--mw-sand-8": "#bcbbb5", + "--mw-sand-9": "#8d8d86", + "--mw-sand-10": "#82827c", + "--mw-sand-11": "#63635e", + "--mw-sand-12": "#21201c", + "--mw-sand-a1": "#55550003", + "--mw-sand-a2": "#25250007", + "--mw-sand-a3": "#20100010", + "--mw-sand-a4": "#1f150019", + "--mw-sand-a5": "#1f180021", + "--mw-sand-a6": "#19130029", + "--mw-sand-a7": "#19140035", + "--mw-sand-a8": "#1915014a", + "--mw-sand-a9": "#0f0f0079", + "--mw-sand-a10": "#0c0c0083", + "--mw-sand-a11": "#080800a1", + "--mw-sand-a12": "#060500e3", + "--mw-sand-surface": "#ffffffcc", + "--mw-sand-indicator": "var(--mw-sand-9)", + "--mw-sand-track": "var(--mw-sand-9)", + "--mw-sand-contrast": "white", + "--mw-amber-1": "#fefdfb", + "--mw-amber-2": "#fefbe9", + "--mw-amber-3": "#fff7c2", + "--mw-amber-4": "#ffee9c", + "--mw-amber-5": "#fbe577", + "--mw-amber-6": "#f3d673", + "--mw-amber-7": "#e9c162", + "--mw-amber-8": "#e2a336", + "--mw-amber-9": "#ffc53d", + "--mw-amber-10": "#ffba18", + "--mw-amber-11": "#ab6400", + "--mw-amber-12": "#4f3422", + "--mw-amber-a1": "#c0800004", + "--mw-amber-a2": "#f4d10016", + "--mw-amber-a3": "#ffde003d", + "--mw-amber-a4": "#ffd40063", + "--mw-amber-a5": "#f8cf0088", + "--mw-amber-a6": "#eab5008c", + "--mw-amber-a7": "#dc9b009d", + "--mw-amber-a8": "#da8a00c9", + "--mw-amber-a9": "#ffb300c2", + "--mw-amber-a10": "#ffb300e7", + "--mw-amber-a11": "#ab6400", + "--mw-amber-a12": "#341500dd", + "--mw-amber-surface": "#fefae4cc", + "--mw-amber-indicator": "var(--mw-amber-9)", + "--mw-amber-track": "var(--mw-amber-9)", + "--mw-amber-contrast": "#21201c", + "--mw-blue-1": "#fbfdff", + "--mw-blue-2": "#f4faff", + "--mw-blue-3": "#e6f4fe", + "--mw-blue-4": "#d5efff", + "--mw-blue-5": "#c2e5ff", + "--mw-blue-6": "#acd8fc", + "--mw-blue-7": "#8ec8f6", + "--mw-blue-8": "#5eb1ef", + "--mw-blue-9": "#0090ff", + "--mw-blue-10": "#0588f0", + "--mw-blue-11": "#0d74ce", + "--mw-blue-12": "#113264", + "--mw-blue-a1": "#0080ff04", + "--mw-blue-a2": "#008cff0b", + "--mw-blue-a3": "#008ff519", + "--mw-blue-a4": "#009eff2a", + "--mw-blue-a5": "#0093ff3d", + "--mw-blue-a6": "#0088f653", + "--mw-blue-a7": "#0083eb71", + "--mw-blue-a8": "#0084e6a1", + "--mw-blue-a9": "#0090ff", + "--mw-blue-a10": "#0086f0fa", + "--mw-blue-a11": "#006dcbf2", + "--mw-blue-a12": "#002359ee", + "--mw-blue-surface": "#f1f9ffcc", + "--mw-blue-indicator": "var(--mw-blue-9)", + "--mw-blue-track": "var(--mw-blue-9)", + "--mw-blue-contrast": "white", + "--mw-bronze-1": "#fdfcfc", + "--mw-bronze-2": "#fdf7f5", + "--mw-bronze-3": "#f6edea", + "--mw-bronze-4": "#efe4df", + "--mw-bronze-5": "#e7d9d3", + "--mw-bronze-6": "#dfcdc5", + "--mw-bronze-7": "#d3bcb3", + "--mw-bronze-8": "#c2a499", + "--mw-bronze-9": "#a18072", + "--mw-bronze-10": "#957468", + "--mw-bronze-11": "#7d5e54", + "--mw-bronze-12": "#43302b", + "--mw-bronze-a1": "#55000003", + "--mw-bronze-a2": "#cc33000a", + "--mw-bronze-a3": "#92250015", + "--mw-bronze-a4": "#80280020", + "--mw-bronze-a5": "#7423002c", + "--mw-bronze-a6": "#7324003a", + "--mw-bronze-a7": "#6c1f004c", + "--mw-bronze-a8": "#671c0066", + "--mw-bronze-a9": "#551a008d", + "--mw-bronze-a10": "#4c150097", + "--mw-bronze-a11": "#3d0f00ab", + "--mw-bronze-a12": "#1d0600d4", + "--mw-bronze-surface": "#fdf5f3cc", + "--mw-bronze-indicator": "var(--mw-bronze-9)", + "--mw-bronze-track": "var(--mw-bronze-9)", + "--mw-bronze-contrast": "white", + "--mw-brown-1": "#fefdfc", + "--mw-brown-2": "#fcf9f6", + "--mw-brown-3": "#f6eee7", + "--mw-brown-4": "#f0e4d9", + "--mw-brown-5": "#ebdaca", + "--mw-brown-6": "#e4cdb7", + "--mw-brown-7": "#dcbc9f", + "--mw-brown-8": "#cea37e", + "--mw-brown-9": "#ad7f58", + "--mw-brown-10": "#a07553", + "--mw-brown-11": "#815e46", + "--mw-brown-12": "#3e332e", + "--mw-brown-a1": "#aa550003", + "--mw-brown-a2": "#aa550009", + "--mw-brown-a3": "#a04b0018", + "--mw-brown-a4": "#9b4a0026", + "--mw-brown-a5": "#9f4d0035", + "--mw-brown-a6": "#a04e0048", + "--mw-brown-a7": "#a34e0060", + "--mw-brown-a8": "#9f4a0081", + "--mw-brown-a9": "#823c00a7", + "--mw-brown-a10": "#723300ac", + "--mw-brown-a11": "#522100b9", + "--mw-brown-a12": "#140600d1", + "--mw-brown-surface": "#fbf8f4cc", + "--mw-brown-indicator": "var(--mw-brown-9)", + "--mw-brown-track": "var(--mw-brown-9)", + "--mw-brown-contrast": "white", + "--mw-crimson-1": "#fffcfd", + "--mw-crimson-2": "#fef7f9", + "--mw-crimson-3": "#ffe9f0", + "--mw-crimson-4": "#fedce7", + "--mw-crimson-5": "#facedd", + "--mw-crimson-6": "#f3bed1", + "--mw-crimson-7": "#eaacc3", + "--mw-crimson-8": "#e093b2", + "--mw-crimson-9": "#e93d82", + "--mw-crimson-10": "#df3478", + "--mw-crimson-11": "#cb1d63", + "--mw-crimson-12": "#621639", + "--mw-crimson-a1": "#ff005503", + "--mw-crimson-a2": "#e0004008", + "--mw-crimson-a3": "#ff005216", + "--mw-crimson-a4": "#f8005123", + "--mw-crimson-a5": "#e5004f31", + "--mw-crimson-a6": "#d0004b41", + "--mw-crimson-a7": "#bf004753", + "--mw-crimson-a8": "#b6004a6c", + "--mw-crimson-a9": "#e2005bc2", + "--mw-crimson-a10": "#d70056cb", + "--mw-crimson-a11": "#c4004fe2", + "--mw-crimson-a12": "#530026e9", + "--mw-crimson-surface": "#fef5f8cc", + "--mw-crimson-indicator": "var(--mw-crimson-9)", + "--mw-crimson-track": "var(--mw-crimson-9)", + "--mw-crimson-contrast": "white", + "--mw-cyan-1": "#fafdfe", + "--mw-cyan-2": "#f2fafb", + "--mw-cyan-3": "#def7f9", + "--mw-cyan-4": "#caf1f6", + "--mw-cyan-5": "#b5e9f0", + "--mw-cyan-6": "#9ddde7", + "--mw-cyan-7": "#7dcedc", + "--mw-cyan-8": "#3db9cf", + "--mw-cyan-9": "#00a2c7", + "--mw-cyan-10": "#0797b9", + "--mw-cyan-11": "#107d98", + "--mw-cyan-12": "#0d3c48", + "--mw-cyan-a1": "#0099cc05", + "--mw-cyan-a2": "#009db10d", + "--mw-cyan-a3": "#00c2d121", + "--mw-cyan-a4": "#00bcd435", + "--mw-cyan-a5": "#01b4cc4a", + "--mw-cyan-a6": "#00a7c162", + "--mw-cyan-a7": "#009fbb82", + "--mw-cyan-a8": "#00a3c0c2", + "--mw-cyan-a9": "#00a2c7", + "--mw-cyan-a10": "#0094b7f8", + "--mw-cyan-a11": "#007491ef", + "--mw-cyan-a12": "#00323ef2", + "--mw-cyan-surface": "#eff9facc", + "--mw-cyan-indicator": "var(--mw-cyan-9)", + "--mw-cyan-track": "var(--mw-cyan-9)", + "--mw-cyan-contrast": "white", + "--mw-gold-1": "#fdfdfc", + "--mw-gold-2": "#faf9f2", + "--mw-gold-3": "#f2f0e7", + "--mw-gold-4": "#eae6db", + "--mw-gold-5": "#e1dccf", + "--mw-gold-6": "#d8d0bf", + "--mw-gold-7": "#cbc0aa", + "--mw-gold-8": "#b9a88d", + "--mw-gold-9": "#978365", + "--mw-gold-10": "#8c7a5e", + "--mw-gold-11": "#71624b", + "--mw-gold-12": "#3b352b", + "--mw-gold-a1": "#55550003", + "--mw-gold-a2": "#9d8a000d", + "--mw-gold-a3": "#75600018", + "--mw-gold-a4": "#6b4e0024", + "--mw-gold-a5": "#60460030", + "--mw-gold-a6": "#64440040", + "--mw-gold-a7": "#63420055", + "--mw-gold-a8": "#633d0072", + "--mw-gold-a9": "#5332009a", + "--mw-gold-a10": "#492d00a1", + "--mw-gold-a11": "#362100b4", + "--mw-gold-a12": "#130c00d4", + "--mw-gold-surface": "#f9f8efcc", + "--mw-gold-indicator": "var(--mw-gold-9)", + "--mw-gold-track": "var(--mw-gold-9)", + "--mw-gold-contrast": "white", + "--mw-grass-1": "#fbfefb", + "--mw-grass-2": "#f5fbf5", + "--mw-grass-3": "#e9f6e9", + "--mw-grass-4": "#daf1db", + "--mw-grass-5": "#c9e8ca", + "--mw-grass-6": "#b2ddb5", + "--mw-grass-7": "#94ce9a", + "--mw-grass-8": "#65ba74", + "--mw-grass-9": "#46a758", + "--mw-grass-10": "#3e9b4f", + "--mw-grass-11": "#2a7e3b", + "--mw-grass-12": "#203c25", + "--mw-grass-a1": "#00c00004", + "--mw-grass-a2": "#0099000a", + "--mw-grass-a3": "#00970016", + "--mw-grass-a4": "#009f0725", + "--mw-grass-a5": "#00930536", + "--mw-grass-a6": "#008f0a4d", + "--mw-grass-a7": "#018b0f6b", + "--mw-grass-a8": "#008d199a", + "--mw-grass-a9": "#008619b9", + "--mw-grass-a10": "#007b17c1", + "--mw-grass-a11": "#006514d5", + "--mw-grass-a12": "#002006df", + "--mw-grass-surface": "#f3faf3cc", + "--mw-grass-indicator": "var(--mw-grass-9)", + "--mw-grass-track": "var(--mw-grass-9)", + "--mw-grass-contrast": "white", + "--mw-green-1": "#fbfefc", + "--mw-green-2": "#f4fbf6", + "--mw-green-3": "#e6f6eb", + "--mw-green-4": "#d6f1df", + "--mw-green-5": "#c4e8d1", + "--mw-green-6": "#adddc0", + "--mw-green-7": "#8eceaa", + "--mw-green-8": "#5bb98b", + "--mw-green-9": "#30a46c", + "--mw-green-10": "#2b9a66", + "--mw-green-11": "#218358", + "--mw-green-12": "#193b2d", + "--mw-green-a1": "#00c04004", + "--mw-green-a2": "#00a32f0b", + "--mw-green-a3": "#00a43319", + "--mw-green-a4": "#00a83829", + "--mw-green-a5": "#019c393b", + "--mw-green-a6": "#00963c52", + "--mw-green-a7": "#00914071", + "--mw-green-a8": "#00924ba4", + "--mw-green-a9": "#008f4acf", + "--mw-green-a10": "#008647d4", + "--mw-green-a11": "#00713fde", + "--mw-green-a12": "#002616e6", + "--mw-green-surface": "#f1faf4cc", + "--mw-green-indicator": "var(--mw-green-9)", + "--mw-green-track": "var(--mw-green-9)", + "--mw-green-contrast": "white", + "--mw-indigo-1": "#fdfdfe", + "--mw-indigo-2": "#f7f9ff", + "--mw-indigo-3": "#edf2fe", + "--mw-indigo-4": "#e1e9ff", + "--mw-indigo-5": "#d2deff", + "--mw-indigo-6": "#c1d0ff", + "--mw-indigo-7": "#abbdf9", + "--mw-indigo-8": "#8da4ef", + "--mw-indigo-9": "#3e63dd", + "--mw-indigo-10": "#3358d4", + "--mw-indigo-11": "#3a5bc7", + "--mw-indigo-12": "#1f2d5c", + "--mw-indigo-a1": "#00008002", + "--mw-indigo-a2": "#0040ff08", + "--mw-indigo-a3": "#0047f112", + "--mw-indigo-a4": "#0044ff1e", + "--mw-indigo-a5": "#0044ff2d", + "--mw-indigo-a6": "#003eff3e", + "--mw-indigo-a7": "#0037ed54", + "--mw-indigo-a8": "#0034dc72", + "--mw-indigo-a9": "#0031d2c1", + "--mw-indigo-a10": "#002ec9cc", + "--mw-indigo-a11": "#002bb7c5", + "--mw-indigo-a12": "#001046e0", + "--mw-indigo-surface": "#f5f8ffcc", + "--mw-indigo-indicator": "var(--mw-indigo-9)", + "--mw-indigo-track": "var(--mw-indigo-9)", + "--mw-indigo-contrast": "white", + "--mw-iris-1": "#fdfdff", + "--mw-iris-2": "#f8f8ff", + "--mw-iris-3": "#f0f1fe", + "--mw-iris-4": "#e6e7ff", + "--mw-iris-5": "#dadcff", + "--mw-iris-6": "#cbcdff", + "--mw-iris-7": "#b8baf8", + "--mw-iris-8": "#9b9ef0", + "--mw-iris-9": "#5b5bd6", + "--mw-iris-10": "#5151cd", + "--mw-iris-11": "#5753c6", + "--mw-iris-12": "#272962", + "--mw-iris-a1": "#0000ff02", + "--mw-iris-a2": "#0000ff07", + "--mw-iris-a3": "#0011ee0f", + "--mw-iris-a4": "#000bff19", + "--mw-iris-a5": "#000eff25", + "--mw-iris-a6": "#000aff34", + "--mw-iris-a7": "#0008e647", + "--mw-iris-a8": "#0008d964", + "--mw-iris-a9": "#0000c0a4", + "--mw-iris-a10": "#0000b6ae", + "--mw-iris-a11": "#0600abac", + "--mw-iris-a12": "#000246d8", + "--mw-iris-surface": "#f6f6ffcc", + "--mw-iris-indicator": "var(--mw-iris-9)", + "--mw-iris-track": "var(--mw-iris-9)", + "--mw-iris-contrast": "white", + "--mw-jade-1": "#fbfefd", + "--mw-jade-2": "#f4fbf7", + "--mw-jade-3": "#e6f7ed", + "--mw-jade-4": "#d6f1e3", + "--mw-jade-5": "#c3e9d7", + "--mw-jade-6": "#acdec8", + "--mw-jade-7": "#8bceb6", + "--mw-jade-8": "#56ba9f", + "--mw-jade-9": "#29a383", + "--mw-jade-10": "#26997b", + "--mw-jade-11": "#208368", + "--mw-jade-12": "#1d3b31", + "--mw-jade-a1": "#00c08004", + "--mw-jade-a2": "#00a3460b", + "--mw-jade-a3": "#00ae4819", + "--mw-jade-a4": "#00a85129", + "--mw-jade-a5": "#00a2553c", + "--mw-jade-a6": "#009a5753", + "--mw-jade-a7": "#00945f74", + "--mw-jade-a8": "#00976ea9", + "--mw-jade-a9": "#00916bd6", + "--mw-jade-a10": "#008764d9", + "--mw-jade-a11": "#007152df", + "--mw-jade-a12": "#002217e2", + "--mw-jade-surface": "#f1faf5cc", + "--mw-jade-indicator": "var(--mw-jade-9)", + "--mw-jade-track": "var(--mw-jade-9)", + "--mw-jade-contrast": "white", + "--mw-lime-1": "#fcfdfa", + "--mw-lime-2": "#f8faf3", + "--mw-lime-3": "#eef6d6", + "--mw-lime-4": "#e2f0bd", + "--mw-lime-5": "#d3e7a6", + "--mw-lime-6": "#c2da91", + "--mw-lime-7": "#abc978", + "--mw-lime-8": "#8db654", + "--mw-lime-9": "#bdee63", + "--mw-lime-10": "#b0e64c", + "--mw-lime-11": "#5c7c2f", + "--mw-lime-12": "#37401c", + "--mw-lime-a1": "#66990005", + "--mw-lime-a2": "#6b95000c", + "--mw-lime-a3": "#96c80029", + "--mw-lime-a4": "#8fc60042", + "--mw-lime-a5": "#81bb0059", + "--mw-lime-a6": "#72aa006e", + "--mw-lime-a7": "#61990087", + "--mw-lime-a8": "#559200ab", + "--mw-lime-a9": "#93e4009c", + "--mw-lime-a10": "#8fdc00b3", + "--mw-lime-a11": "#375f00d0", + "--mw-lime-a12": "#1e2900e3", + "--mw-lime-surface": "#f6f9f0cc", + "--mw-lime-indicator": "var(--mw-lime-9)", + "--mw-lime-track": "var(--mw-lime-9)", + "--mw-lime-contrast": "#1d211c", + "--mw-mint-1": "#f9fefd", + "--mw-mint-2": "#f2fbf9", + "--mw-mint-3": "#ddf9f2", + "--mw-mint-4": "#c8f4e9", + "--mw-mint-5": "#b3ecde", + "--mw-mint-6": "#9ce0d0", + "--mw-mint-7": "#7ecfbd", + "--mw-mint-8": "#4cbba5", + "--mw-mint-9": "#86ead4", + "--mw-mint-10": "#7de0cb", + "--mw-mint-11": "#027864", + "--mw-mint-12": "#16433c", + "--mw-mint-a1": "#00d5aa06", + "--mw-mint-a2": "#00b18a0d", + "--mw-mint-a3": "#00d29e22", + "--mw-mint-a4": "#00cc9937", + "--mw-mint-a5": "#00c0914c", + "--mw-mint-a6": "#00b08663", + "--mw-mint-a7": "#00a17d81", + "--mw-mint-a8": "#009e7fb3", + "--mw-mint-a9": "#00d3a579", + "--mw-mint-a10": "#00c39982", + "--mw-mint-a11": "#007763fd", + "--mw-mint-a12": "#00312ae9", + "--mw-mint-surface": "#effaf8cc", + "--mw-mint-indicator": "var(--mw-mint-9)", + "--mw-mint-track": "var(--mw-mint-9)", + "--mw-mint-contrast": "#1a211e", + "--mw-orange-1": "#fefcfb", + "--mw-orange-2": "#fff7ed", + "--mw-orange-3": "#ffefd6", + "--mw-orange-4": "#ffdfb5", + "--mw-orange-5": "#ffd19a", + "--mw-orange-6": "#ffc182", + "--mw-orange-7": "#f5ae73", + "--mw-orange-8": "#ec9455", + "--mw-orange-9": "#f76b15", + "--mw-orange-10": "#ef5f00", + "--mw-orange-11": "#cc4e00", + "--mw-orange-12": "#582d1d", + "--mw-orange-a1": "#c0400004", + "--mw-orange-a2": "#ff8e0012", + "--mw-orange-a3": "#ff9c0029", + "--mw-orange-a4": "#ff91014a", + "--mw-orange-a5": "#ff8b0065", + "--mw-orange-a6": "#ff81007d", + "--mw-orange-a7": "#ed6c008c", + "--mw-orange-a8": "#e35f00aa", + "--mw-orange-a9": "#f65e00ea", + "--mw-orange-a10": "#ef5f00", + "--mw-orange-a11": "#cc4e00", + "--mw-orange-a12": "#431200e2", + "--mw-orange-surface": "#fff5e9cc", + "--mw-orange-indicator": "var(--mw-orange-9)", + "--mw-orange-track": "var(--mw-orange-9)", + "--mw-orange-contrast": "white", + "--mw-pink-1": "#fffcfe", + "--mw-pink-2": "#fef7fb", + "--mw-pink-3": "#fee9f5", + "--mw-pink-4": "#fbdcef", + "--mw-pink-5": "#f6cee7", + "--mw-pink-6": "#efbfdd", + "--mw-pink-7": "#e7acd0", + "--mw-pink-8": "#dd93c2", + "--mw-pink-9": "#d6409f", + "--mw-pink-10": "#cf3897", + "--mw-pink-11": "#c2298a", + "--mw-pink-12": "#651249", + "--mw-pink-a1": "#ff00aa03", + "--mw-pink-a2": "#e0008008", + "--mw-pink-a3": "#f4008c16", + "--mw-pink-a4": "#e2008b23", + "--mw-pink-a5": "#d1008331", + "--mw-pink-a6": "#c0007840", + "--mw-pink-a7": "#b6006f53", + "--mw-pink-a8": "#af006f6c", + "--mw-pink-a9": "#c8007fbf", + "--mw-pink-a10": "#c2007ac7", + "--mw-pink-a11": "#b60074d6", + "--mw-pink-a12": "#59003bed", + "--mw-pink-surface": "#fef5facc", + "--mw-pink-indicator": "var(--mw-pink-9)", + "--mw-pink-track": "var(--mw-pink-9)", + "--mw-pink-contrast": "white", + "--mw-plum-1": "#fefcff", + "--mw-plum-2": "#fdf7fd", + "--mw-plum-3": "#fbebfb", + "--mw-plum-4": "#f7def8", + "--mw-plum-5": "#f2d1f3", + "--mw-plum-6": "#e9c2ec", + "--mw-plum-7": "#deade3", + "--mw-plum-8": "#cf91d8", + "--mw-plum-9": "#ab4aba", + "--mw-plum-10": "#a144af", + "--mw-plum-11": "#953ea3", + "--mw-plum-12": "#53195d", + "--mw-plum-a1": "#aa00ff03", + "--mw-plum-a2": "#c000c008", + "--mw-plum-a3": "#cc00cc14", + "--mw-plum-a4": "#c200c921", + "--mw-plum-a5": "#b700bd2e", + "--mw-plum-a6": "#a400b03d", + "--mw-plum-a7": "#9900a852", + "--mw-plum-a8": "#9000a56e", + "--mw-plum-a9": "#89009eb5", + "--mw-plum-a10": "#7f0092bb", + "--mw-plum-a11": "#730086c1", + "--mw-plum-a12": "#40004be6", + "--mw-plum-surface": "#fdf5fdcc", + "--mw-plum-indicator": "var(--mw-plum-9)", + "--mw-plum-track": "var(--mw-plum-9)", + "--mw-plum-contrast": "white", + "--mw-purple-1": "#fefcfe", + "--mw-purple-2": "#fbf7fe", + "--mw-purple-3": "#f7edfe", + "--mw-purple-4": "#f2e2fc", + "--mw-purple-5": "#ead5f9", + "--mw-purple-6": "#e0c4f4", + "--mw-purple-7": "#d1afec", + "--mw-purple-8": "#be93e4", + "--mw-purple-9": "#8e4ec6", + "--mw-purple-10": "#8347b9", + "--mw-purple-11": "#8145b5", + "--mw-purple-12": "#402060", + "--mw-purple-a1": "#aa00aa03", + "--mw-purple-a2": "#8000e008", + "--mw-purple-a3": "#8e00f112", + "--mw-purple-a4": "#8d00e51d", + "--mw-purple-a5": "#8000db2a", + "--mw-purple-a6": "#7a01d03b", + "--mw-purple-a7": "#6d00c350", + "--mw-purple-a8": "#6600c06c", + "--mw-purple-a9": "#5c00adb1", + "--mw-purple-a10": "#53009eb8", + "--mw-purple-a11": "#52009aba", + "--mw-purple-a12": "#250049df", + "--mw-purple-surface": "#faf5fecc", + "--mw-purple-indicator": "var(--mw-purple-9)", + "--mw-purple-track": "var(--mw-purple-9)", + "--mw-purple-contrast": "white", + "--mw-red-1": "#fffcfc", + "--mw-red-2": "#fff7f7", + "--mw-red-3": "#feebec", + "--mw-red-4": "#ffdbdc", + "--mw-red-5": "#ffcdce", + "--mw-red-6": "#fdbdbe", + "--mw-red-7": "#f4a9aa", + "--mw-red-8": "#eb8e90", + "--mw-red-9": "#e5484d", + "--mw-red-10": "#dc3e42", + "--mw-red-11": "#ce2c31", + "--mw-red-12": "#641723", + "--mw-red-a1": "#ff000003", + "--mw-red-a2": "#ff000008", + "--mw-red-a3": "#f3000d14", + "--mw-red-a4": "#ff000824", + "--mw-red-a5": "#ff000632", + "--mw-red-a6": "#f8000442", + "--mw-red-a7": "#df000356", + "--mw-red-a8": "#d2000571", + "--mw-red-a9": "#db0007b7", + "--mw-red-a10": "#d10005c1", + "--mw-red-a11": "#c40006d3", + "--mw-red-a12": "#55000de8", + "--mw-red-surface": "#fff5f5cc", + "--mw-red-indicator": "var(--mw-red-9)", + "--mw-red-track": "var(--mw-red-9)", + "--mw-red-contrast": "white", + "--mw-ruby-1": "#fffcfd", + "--mw-ruby-2": "#fff7f8", + "--mw-ruby-3": "#feeaed", + "--mw-ruby-4": "#ffdce1", + "--mw-ruby-5": "#ffced6", + "--mw-ruby-6": "#f8bfc8", + "--mw-ruby-7": "#efacb8", + "--mw-ruby-8": "#e592a3", + "--mw-ruby-9": "#e54666", + "--mw-ruby-10": "#dc3b5d", + "--mw-ruby-11": "#ca244d", + "--mw-ruby-12": "#64172b", + "--mw-ruby-a1": "#ff005503", + "--mw-ruby-a2": "#ff002008", + "--mw-ruby-a3": "#f3002515", + "--mw-ruby-a4": "#ff002523", + "--mw-ruby-a5": "#ff002a31", + "--mw-ruby-a6": "#e4002440", + "--mw-ruby-a7": "#ce002553", + "--mw-ruby-a8": "#c300286d", + "--mw-ruby-a9": "#db002cb9", + "--mw-ruby-a10": "#d2002cc4", + "--mw-ruby-a11": "#c10030db", + "--mw-ruby-a12": "#550016e8", + "--mw-ruby-surface": "#fff5f6cc", + "--mw-ruby-indicator": "var(--mw-ruby-9)", + "--mw-ruby-track": "var(--mw-ruby-9)", + "--mw-ruby-contrast": "white", + "--mw-sky-1": "#f9feff", + "--mw-sky-2": "#f1fafd", + "--mw-sky-3": "#e1f6fd", + "--mw-sky-4": "#d1f0fa", + "--mw-sky-5": "#bee7f5", + "--mw-sky-6": "#a9daed", + "--mw-sky-7": "#8dcae3", + "--mw-sky-8": "#60b3d7", + "--mw-sky-9": "#7ce2fe", + "--mw-sky-10": "#74daf8", + "--mw-sky-11": "#00749e", + "--mw-sky-12": "#1d3e56", + "--mw-sky-a1": "#00d5ff06", + "--mw-sky-a2": "#00a4db0e", + "--mw-sky-a3": "#00b3ee1e", + "--mw-sky-a4": "#00ace42e", + "--mw-sky-a5": "#00a1d841", + "--mw-sky-a6": "#0092ca56", + "--mw-sky-a7": "#0089c172", + "--mw-sky-a8": "#0085bf9f", + "--mw-sky-a9": "#00c7fe83", + "--mw-sky-a10": "#00bcf38b", + "--mw-sky-a11": "#00749e", + "--mw-sky-a12": "#002540e2", + "--mw-sky-surface": "#eef9fdcc", + "--mw-sky-indicator": "var(--mw-sky-9)", + "--mw-sky-track": "var(--mw-sky-9)", + "--mw-sky-contrast": "#1c2024", + "--mw-teal-1": "#fafefd", + "--mw-teal-2": "#f3fbf9", + "--mw-teal-3": "#e0f8f3", + "--mw-teal-4": "#ccf3ea", + "--mw-teal-5": "#b8eae0", + "--mw-teal-6": "#a1ded2", + "--mw-teal-7": "#83cdc1", + "--mw-teal-8": "#53b9ab", + "--mw-teal-9": "#12a594", + "--mw-teal-10": "#0d9b8a", + "--mw-teal-11": "#008573", + "--mw-teal-12": "#0d3d38", + "--mw-teal-a1": "#00cc9905", + "--mw-teal-a2": "#00aa800c", + "--mw-teal-a3": "#00c69d1f", + "--mw-teal-a4": "#00c39633", + "--mw-teal-a5": "#00b49047", + "--mw-teal-a6": "#00a6855e", + "--mw-teal-a7": "#0099807c", + "--mw-teal-a8": "#009783ac", + "--mw-teal-a9": "#009e8ced", + "--mw-teal-a10": "#009684f2", + "--mw-teal-a11": "#008573", + "--mw-teal-a12": "#00332df2", + "--mw-teal-surface": "#f0faf8cc", + "--mw-teal-indicator": "var(--mw-teal-9)", + "--mw-teal-track": "var(--mw-teal-9)", + "--mw-teal-contrast": "white", + "--mw-tomato-1": "#fffcfc", + "--mw-tomato-2": "#fff8f7", + "--mw-tomato-3": "#feebe7", + "--mw-tomato-4": "#ffdcd3", + "--mw-tomato-5": "#ffcdc2", + "--mw-tomato-6": "#fdbdaf", + "--mw-tomato-7": "#f5a898", + "--mw-tomato-8": "#ec8e7b", + "--mw-tomato-9": "#e54d2e", + "--mw-tomato-10": "#dd4425", + "--mw-tomato-11": "#d13415", + "--mw-tomato-12": "#5c271f", + "--mw-tomato-a1": "#ff000003", + "--mw-tomato-a2": "#ff200008", + "--mw-tomato-a3": "#f52b0018", + "--mw-tomato-a4": "#ff35002c", + "--mw-tomato-a5": "#ff2e003d", + "--mw-tomato-a6": "#f92d0050", + "--mw-tomato-a7": "#e7280067", + "--mw-tomato-a8": "#db250084", + "--mw-tomato-a9": "#df2600d1", + "--mw-tomato-a10": "#d72400da", + "--mw-tomato-a11": "#cd2200ea", + "--mw-tomato-a12": "#460900e0", + "--mw-tomato-surface": "#fff6f5cc", + "--mw-tomato-indicator": "var(--mw-tomato-9)", + "--mw-tomato-track": "var(--mw-tomato-9)", + "--mw-tomato-contrast": "white", + "--mw-violet-1": "#fdfcfe", + "--mw-violet-2": "#faf8ff", + "--mw-violet-3": "#f4f0fe", + "--mw-violet-4": "#ebe4ff", + "--mw-violet-5": "#e1d9ff", + "--mw-violet-6": "#d4cafe", + "--mw-violet-7": "#c2b5f5", + "--mw-violet-8": "#aa99ec", + "--mw-violet-9": "#6e56cf", + "--mw-violet-10": "#654dc4", + "--mw-violet-11": "#6550b9", + "--mw-violet-12": "#2f265f", + "--mw-violet-a1": "#5500aa03", + "--mw-violet-a2": "#4900ff07", + "--mw-violet-a3": "#4400ee0f", + "--mw-violet-a4": "#4300ff1b", + "--mw-violet-a5": "#3600ff26", + "--mw-violet-a6": "#3100fb35", + "--mw-violet-a7": "#2d01dd4a", + "--mw-violet-a8": "#2b00d066", + "--mw-violet-a9": "#2400b7a9", + "--mw-violet-a10": "#2300abb2", + "--mw-violet-a11": "#1f0099af", + "--mw-violet-a12": "#0b0043d9", + "--mw-violet-surface": "#f9f6ffcc", + "--mw-violet-indicator": "var(--mw-violet-9)", + "--mw-violet-track": "var(--mw-violet-9)", + "--mw-violet-contrast": "white", + "--mw-yellow-1": "#fdfdf9", + "--mw-yellow-2": "#fefce9", + "--mw-yellow-3": "#fffab8", + "--mw-yellow-4": "#fff394", + "--mw-yellow-5": "#ffe770", + "--mw-yellow-6": "#f3d768", + "--mw-yellow-7": "#e4c767", + "--mw-yellow-8": "#d5ae39", + "--mw-yellow-9": "#ffe629", + "--mw-yellow-10": "#ffdc00", + "--mw-yellow-11": "#9e6c00", + "--mw-yellow-12": "#473b1f", + "--mw-yellow-a1": "#aaaa0006", + "--mw-yellow-a2": "#f4dd0016", + "--mw-yellow-a3": "#ffee0047", + "--mw-yellow-a4": "#ffe3016b", + "--mw-yellow-a5": "#ffd5008f", + "--mw-yellow-a6": "#ebbc0097", + "--mw-yellow-a7": "#d2a10098", + "--mw-yellow-a8": "#c99700c6", + "--mw-yellow-a9": "#ffe100d6", + "--mw-yellow-a10": "#ffdc00", + "--mw-yellow-a11": "#9e6c00", + "--mw-yellow-a12": "#2e2000e0", + "--mw-yellow-surface": "#fefbe4cc", + "--mw-yellow-indicator": "var(--mw-yellow-10)", + "--mw-yellow-track": "var(--mw-yellow-10)", + "--mw-yellow-contrast": "#21201c", +} + +RADIX_DARK_COLOR_TOKENS = { + "--mw-gray-1": "#111111", + "--mw-radix-gray-1": "#111111", + "--mw-gray-2": "#191919", + "--mw-radix-gray-2": "#191919", + "--mw-gray-3": "#222222", + "--mw-radix-gray-3": "#222222", + "--mw-gray-4": "#2a2a2a", + "--mw-radix-gray-4": "#2a2a2a", + "--mw-gray-5": "#313131", + "--mw-radix-gray-5": "#313131", + "--mw-gray-6": "#3a3a3a", + "--mw-radix-gray-6": "#3a3a3a", + "--mw-gray-7": "#484848", + "--mw-radix-gray-7": "#484848", + "--mw-gray-8": "#606060", + "--mw-radix-gray-8": "#606060", + "--mw-gray-9": "#6e6e6e", + "--mw-radix-gray-9": "#6e6e6e", + "--mw-gray-10": "#7b7b7b", + "--mw-radix-gray-10": "#7b7b7b", + "--mw-gray-11": "#b4b4b4", + "--mw-radix-gray-11": "#b4b4b4", + "--mw-gray-12": "#eeeeee", + "--mw-radix-gray-12": "#eeeeee", + "--mw-gray-a1": "#00000000", + "--mw-radix-gray-a1": "#00000000", + "--mw-gray-a2": "#ffffff09", + "--mw-radix-gray-a2": "#ffffff09", + "--mw-gray-a3": "#ffffff12", + "--mw-radix-gray-a3": "#ffffff12", + "--mw-gray-a4": "#ffffff1b", + "--mw-radix-gray-a4": "#ffffff1b", + "--mw-gray-a5": "#ffffff22", + "--mw-radix-gray-a5": "#ffffff22", + "--mw-gray-a6": "#ffffff2c", + "--mw-radix-gray-a6": "#ffffff2c", + "--mw-gray-a7": "#ffffff3b", + "--mw-radix-gray-a7": "#ffffff3b", + "--mw-gray-a8": "#ffffff55", + "--mw-radix-gray-a8": "#ffffff55", + "--mw-gray-a9": "#ffffff64", + "--mw-radix-gray-a9": "#ffffff64", + "--mw-gray-a10": "#ffffff72", + "--mw-radix-gray-a10": "#ffffff72", + "--mw-gray-a11": "#ffffffaf", + "--mw-radix-gray-a11": "#ffffffaf", + "--mw-gray-a12": "#ffffffed", + "--mw-radix-gray-a12": "#ffffffed", + "--mw-gray-surface": "#21212180", + "--mw-radix-gray-surface": "#21212180", + "--mw-gray-indicator": "var(--mw-gray-9)", + "--mw-radix-gray-indicator": "var(--mw-gray-9)", + "--mw-gray-track": "var(--mw-gray-9)", + "--mw-radix-gray-track": "var(--mw-gray-9)", + "--mw-gray-contrast": "white", + "--mw-radix-gray-contrast": "white", + "--mw-mauve-1": "#121113", + "--mw-mauve-2": "#1a191b", + "--mw-mauve-3": "#232225", + "--mw-mauve-4": "#2b292d", + "--mw-mauve-5": "#323035", + "--mw-mauve-6": "#3c393f", + "--mw-mauve-7": "#49474e", + "--mw-mauve-8": "#625f69", + "--mw-mauve-9": "#6f6d78", + "--mw-mauve-10": "#7c7a85", + "--mw-mauve-11": "#b5b2bc", + "--mw-mauve-12": "#eeeef0", + "--mw-mauve-a1": "#00000000", + "--mw-mauve-a2": "#f5f4f609", + "--mw-mauve-a3": "#ebeaf814", + "--mw-mauve-a4": "#eee5f81d", + "--mw-mauve-a5": "#efe6fe25", + "--mw-mauve-a6": "#f1e6fd30", + "--mw-mauve-a7": "#eee9ff40", + "--mw-mauve-a8": "#eee7ff5d", + "--mw-mauve-a9": "#eae6fd6e", + "--mw-mauve-a10": "#ece9fd7c", + "--mw-mauve-a11": "#f5f1ffb7", + "--mw-mauve-a12": "#fdfdffef", + "--mw-mauve-surface": "#22212380", + "--mw-mauve-indicator": "var(--mw-mauve-9)", + "--mw-mauve-track": "var(--mw-mauve-9)", + "--mw-mauve-contrast": "white", + "--mw-slate-1": "#111113", + "--mw-slate-2": "#18191b", + "--mw-slate-3": "#212225", + "--mw-slate-4": "#272a2d", + "--mw-slate-5": "#2e3135", + "--mw-slate-6": "#363a3f", + "--mw-slate-7": "#43484e", + "--mw-slate-8": "#5a6169", + "--mw-slate-9": "#696e77", + "--mw-slate-10": "#777b84", + "--mw-slate-11": "#b0b4ba", + "--mw-slate-12": "#edeef0", + "--mw-slate-a1": "#00000000", + "--mw-slate-a2": "#d8f4f609", + "--mw-slate-a3": "#ddeaf814", + "--mw-slate-a4": "#d3edf81d", + "--mw-slate-a5": "#d9edfe25", + "--mw-slate-a6": "#d6ebfd30", + "--mw-slate-a7": "#d9edff40", + "--mw-slate-a8": "#d9edff5d", + "--mw-slate-a9": "#dfebfd6d", + "--mw-slate-a10": "#e5edfd7b", + "--mw-slate-a11": "#f1f7feb5", + "--mw-slate-a12": "#fcfdffef", + "--mw-slate-surface": "#1f212380", + "--mw-slate-indicator": "var(--mw-slate-9)", + "--mw-slate-track": "var(--mw-slate-9)", + "--mw-slate-contrast": "white", + "--mw-sage-1": "#101211", + "--mw-sage-2": "#171918", + "--mw-sage-3": "#202221", + "--mw-sage-4": "#272a29", + "--mw-sage-5": "#2e3130", + "--mw-sage-6": "#373b39", + "--mw-sage-7": "#444947", + "--mw-sage-8": "#5b625f", + "--mw-sage-9": "#63706b", + "--mw-sage-10": "#717d79", + "--mw-sage-11": "#adb5b2", + "--mw-sage-12": "#eceeed", + "--mw-sage-a1": "#00000000", + "--mw-sage-a2": "#f0f2f108", + "--mw-sage-a3": "#f3f5f412", + "--mw-sage-a4": "#f2fefd1a", + "--mw-sage-a5": "#f1fbfa22", + "--mw-sage-a6": "#edfbf42d", + "--mw-sage-a7": "#edfcf73c", + "--mw-sage-a8": "#ebfdf657", + "--mw-sage-a9": "#dffdf266", + "--mw-sage-a10": "#e5fdf674", + "--mw-sage-a11": "#f4fefbb0", + "--mw-sage-a12": "#fdfffeed", + "--mw-sage-surface": "#1e201f80", + "--mw-sage-indicator": "var(--mw-sage-9)", + "--mw-sage-track": "var(--mw-sage-9)", + "--mw-sage-contrast": "white", + "--mw-olive-1": "#111210", + "--mw-olive-2": "#181917", + "--mw-olive-3": "#212220", + "--mw-olive-4": "#282a27", + "--mw-olive-5": "#2f312e", + "--mw-olive-6": "#383a36", + "--mw-olive-7": "#454843", + "--mw-olive-8": "#5c625b", + "--mw-olive-9": "#687066", + "--mw-olive-10": "#767d74", + "--mw-olive-11": "#afb5ad", + "--mw-olive-12": "#eceeec", + "--mw-olive-a1": "#00000000", + "--mw-olive-a2": "#f1f2f008", + "--mw-olive-a3": "#f4f5f312", + "--mw-olive-a4": "#f3fef21a", + "--mw-olive-a5": "#f2fbf122", + "--mw-olive-a6": "#f4faed2c", + "--mw-olive-a7": "#f2fced3b", + "--mw-olive-a8": "#edfdeb57", + "--mw-olive-a9": "#ebfde766", + "--mw-olive-a10": "#f0fdec74", + "--mw-olive-a11": "#f6fef4b0", + "--mw-olive-a12": "#fdfffded", + "--mw-olive-surface": "#1f201e80", + "--mw-olive-indicator": "var(--mw-olive-9)", + "--mw-olive-track": "var(--mw-olive-9)", + "--mw-olive-contrast": "white", + "--mw-sand-1": "#111110", + "--mw-sand-2": "#191918", + "--mw-sand-3": "#222221", + "--mw-sand-4": "#2a2a28", + "--mw-sand-5": "#31312e", + "--mw-sand-6": "#3b3a37", + "--mw-sand-7": "#494844", + "--mw-sand-8": "#62605b", + "--mw-sand-9": "#6f6d66", + "--mw-sand-10": "#7c7b74", + "--mw-sand-11": "#b5b3ad", + "--mw-sand-12": "#eeeeec", + "--mw-sand-a1": "#00000000", + "--mw-sand-a2": "#f4f4f309", + "--mw-sand-a3": "#f6f6f513", + "--mw-sand-a4": "#fefef31b", + "--mw-sand-a5": "#fbfbeb23", + "--mw-sand-a6": "#fffaed2d", + "--mw-sand-a7": "#fffbed3c", + "--mw-sand-a8": "#fff9eb57", + "--mw-sand-a9": "#fffae965", + "--mw-sand-a10": "#fffdee73", + "--mw-sand-a11": "#fffcf4b0", + "--mw-sand-a12": "#fffffded", + "--mw-sand-surface": "#21212080", + "--mw-sand-indicator": "var(--mw-sand-9)", + "--mw-sand-track": "var(--mw-sand-9)", + "--mw-sand-contrast": "white", + "--mw-amber-1": "#16120c", + "--mw-amber-2": "#1d180f", + "--mw-amber-3": "#302008", + "--mw-amber-4": "#3f2700", + "--mw-amber-5": "#4d3000", + "--mw-amber-6": "#5c3d05", + "--mw-amber-7": "#714f19", + "--mw-amber-8": "#8f6424", + "--mw-amber-9": "#ffc53d", + "--mw-amber-10": "#ffd60a", + "--mw-amber-11": "#ffca16", + "--mw-amber-12": "#ffe7b3", + "--mw-amber-a1": "#e63c0006", + "--mw-amber-a2": "#fd9b000d", + "--mw-amber-a3": "#fa820022", + "--mw-amber-a4": "#fc820032", + "--mw-amber-a5": "#fd8b0041", + "--mw-amber-a6": "#fd9b0051", + "--mw-amber-a7": "#ffab2567", + "--mw-amber-a8": "#ffae3587", + "--mw-amber-a9": "#ffc53d", + "--mw-amber-a10": "#ffd60a", + "--mw-amber-a11": "#ffca16", + "--mw-amber-a12": "#ffe7b3", + "--mw-amber-surface": "#271f1380", + "--mw-amber-indicator": "var(--mw-amber-9)", + "--mw-amber-track": "var(--mw-amber-9)", + "--mw-amber-contrast": "#21201c", + "--mw-blue-1": "#0d1520", + "--mw-blue-2": "#111927", + "--mw-blue-3": "#0d2847", + "--mw-blue-4": "#003362", + "--mw-blue-5": "#004074", + "--mw-blue-6": "#104d87", + "--mw-blue-7": "#205d9e", + "--mw-blue-8": "#2870bd", + "--mw-blue-9": "#0090ff", + "--mw-blue-10": "#3b9eff", + "--mw-blue-11": "#70b8ff", + "--mw-blue-12": "#c2e6ff", + "--mw-blue-a1": "#004df211", + "--mw-blue-a2": "#1166fb18", + "--mw-blue-a3": "#0077ff3a", + "--mw-blue-a4": "#0075ff57", + "--mw-blue-a5": "#0081fd6b", + "--mw-blue-a6": "#0f89fd7f", + "--mw-blue-a7": "#2a91fe98", + "--mw-blue-a8": "#3094feb9", + "--mw-blue-a9": "#0090ff", + "--mw-blue-a10": "#3b9eff", + "--mw-blue-a11": "#70b8ff", + "--mw-blue-a12": "#c2e6ff", + "--mw-blue-surface": "#11213d80", + "--mw-blue-indicator": "var(--mw-blue-9)", + "--mw-blue-track": "var(--mw-blue-9)", + "--mw-blue-contrast": "white", + "--mw-bronze-1": "#141110", + "--mw-bronze-2": "#1c1917", + "--mw-bronze-3": "#262220", + "--mw-bronze-4": "#302a27", + "--mw-bronze-5": "#3b3330", + "--mw-bronze-6": "#493e3a", + "--mw-bronze-7": "#5a4c47", + "--mw-bronze-8": "#6f5f58", + "--mw-bronze-9": "#a18072", + "--mw-bronze-10": "#ae8c7e", + "--mw-bronze-11": "#d4b3a5", + "--mw-bronze-12": "#ede0d9", + "--mw-bronze-a1": "#d1110004", + "--mw-bronze-a2": "#fbbc910c", + "--mw-bronze-a3": "#faceb817", + "--mw-bronze-a4": "#facdb622", + "--mw-bronze-a5": "#ffd2c12d", + "--mw-bronze-a6": "#ffd1c03c", + "--mw-bronze-a7": "#fdd0c04f", + "--mw-bronze-a8": "#ffd6c565", + "--mw-bronze-a9": "#fec7b09b", + "--mw-bronze-a10": "#fecab5a9", + "--mw-bronze-a11": "#ffd7c6d1", + "--mw-bronze-a12": "#fff1e9ec", + "--mw-bronze-surface": "#27211d80", + "--mw-bronze-indicator": "var(--mw-bronze-9)", + "--mw-bronze-track": "var(--mw-bronze-9)", + "--mw-bronze-contrast": "white", + "--mw-brown-1": "#12110f", + "--mw-brown-2": "#1c1816", + "--mw-brown-3": "#28211d", + "--mw-brown-4": "#322922", + "--mw-brown-5": "#3e3128", + "--mw-brown-6": "#4d3c2f", + "--mw-brown-7": "#614a39", + "--mw-brown-8": "#7c5f46", + "--mw-brown-9": "#ad7f58", + "--mw-brown-10": "#b88c67", + "--mw-brown-11": "#dbb594", + "--mw-brown-12": "#f2e1ca", + "--mw-brown-a1": "#91110002", + "--mw-brown-a2": "#fba67c0c", + "--mw-brown-a3": "#fcb58c19", + "--mw-brown-a4": "#fbbb8a24", + "--mw-brown-a5": "#fcb88931", + "--mw-brown-a6": "#fdba8741", + "--mw-brown-a7": "#ffbb8856", + "--mw-brown-a8": "#ffbe8773", + "--mw-brown-a9": "#feb87da8", + "--mw-brown-a10": "#ffc18cb3", + "--mw-brown-a11": "#fed1aad9", + "--mw-brown-a12": "#feecd4f2", + "--mw-brown-surface": "#271f1b80", + "--mw-brown-indicator": "var(--mw-brown-9)", + "--mw-brown-track": "var(--mw-brown-9)", + "--mw-brown-contrast": "white", + "--mw-crimson-1": "#191114", + "--mw-crimson-2": "#201318", + "--mw-crimson-3": "#381525", + "--mw-crimson-4": "#4d122f", + "--mw-crimson-5": "#5c1839", + "--mw-crimson-6": "#6d2545", + "--mw-crimson-7": "#873356", + "--mw-crimson-8": "#b0436e", + "--mw-crimson-9": "#e93d82", + "--mw-crimson-10": "#ee518a", + "--mw-crimson-11": "#ff92ad", + "--mw-crimson-12": "#fdd3e8", + "--mw-crimson-a1": "#f4126709", + "--mw-crimson-a2": "#f22f7a11", + "--mw-crimson-a3": "#fe2a8b2a", + "--mw-crimson-a4": "#fd158741", + "--mw-crimson-a5": "#fd278f51", + "--mw-crimson-a6": "#fe459763", + "--mw-crimson-a7": "#fd559b7f", + "--mw-crimson-a8": "#fe5b9bab", + "--mw-crimson-a9": "#fe418de8", + "--mw-crimson-a10": "#ff5693ed", + "--mw-crimson-a11": "#ff92ad", + "--mw-crimson-a12": "#ffd5eafd", + "--mw-crimson-surface": "#2f151f80", + "--mw-crimson-indicator": "var(--mw-crimson-9)", + "--mw-crimson-track": "var(--mw-crimson-9)", + "--mw-crimson-contrast": "white", + "--mw-cyan-1": "#0b161a", + "--mw-cyan-2": "#101b20", + "--mw-cyan-3": "#082c36", + "--mw-cyan-4": "#003848", + "--mw-cyan-5": "#004558", + "--mw-cyan-6": "#045468", + "--mw-cyan-7": "#12677e", + "--mw-cyan-8": "#11809c", + "--mw-cyan-9": "#00a2c7", + "--mw-cyan-10": "#23afd0", + "--mw-cyan-11": "#4ccce6", + "--mw-cyan-12": "#b6ecf7", + "--mw-cyan-a1": "#0091f70a", + "--mw-cyan-a2": "#02a7f211", + "--mw-cyan-a3": "#00befd28", + "--mw-cyan-a4": "#00baff3b", + "--mw-cyan-a5": "#00befd4d", + "--mw-cyan-a6": "#00c7fd5e", + "--mw-cyan-a7": "#14cdff75", + "--mw-cyan-a8": "#11cfff95", + "--mw-cyan-a9": "#00cfffc3", + "--mw-cyan-a10": "#28d6ffcd", + "--mw-cyan-a11": "#52e1fee5", + "--mw-cyan-a12": "#bbf3fef7", + "--mw-cyan-surface": "#11252d80", + "--mw-cyan-indicator": "var(--mw-cyan-9)", + "--mw-cyan-track": "var(--mw-cyan-9)", + "--mw-cyan-contrast": "white", + "--mw-gold-1": "#121211", + "--mw-gold-2": "#1b1a17", + "--mw-gold-3": "#24231f", + "--mw-gold-4": "#2d2b26", + "--mw-gold-5": "#38352e", + "--mw-gold-6": "#444039", + "--mw-gold-7": "#544f46", + "--mw-gold-8": "#696256", + "--mw-gold-9": "#978365", + "--mw-gold-10": "#a39073", + "--mw-gold-11": "#cbb99f", + "--mw-gold-12": "#e8e2d9", + "--mw-gold-a1": "#91911102", + "--mw-gold-a2": "#f9e29d0b", + "--mw-gold-a3": "#f8ecbb15", + "--mw-gold-a4": "#ffeec41e", + "--mw-gold-a5": "#feecc22a", + "--mw-gold-a6": "#feebcb37", + "--mw-gold-a7": "#ffedcd48", + "--mw-gold-a8": "#fdeaca5f", + "--mw-gold-a9": "#ffdba690", + "--mw-gold-a10": "#fedfb09d", + "--mw-gold-a11": "#fee7c6c8", + "--mw-gold-a12": "#fef7ede7", + "--mw-gold-surface": "#25231d80", + "--mw-gold-indicator": "var(--mw-gold-9)", + "--mw-gold-track": "var(--mw-gold-9)", + "--mw-gold-contrast": "white", + "--mw-grass-1": "#0e1511", + "--mw-grass-2": "#141a15", + "--mw-grass-3": "#1b2a1e", + "--mw-grass-4": "#1d3a24", + "--mw-grass-5": "#25482d", + "--mw-grass-6": "#2d5736", + "--mw-grass-7": "#366740", + "--mw-grass-8": "#3e7949", + "--mw-grass-9": "#46a758", + "--mw-grass-10": "#53b365", + "--mw-grass-11": "#71d083", + "--mw-grass-12": "#c2f0c2", + "--mw-grass-a1": "#00de1205", + "--mw-grass-a2": "#5ef7780a", + "--mw-grass-a3": "#70fe8c1b", + "--mw-grass-a4": "#57ff802c", + "--mw-grass-a5": "#68ff8b3b", + "--mw-grass-a6": "#71ff8f4b", + "--mw-grass-a7": "#77fd925d", + "--mw-grass-a8": "#77fd9070", + "--mw-grass-a9": "#65ff82a1", + "--mw-grass-a10": "#72ff8dae", + "--mw-grass-a11": "#89ff9fcd", + "--mw-grass-a12": "#ceffceef", + "--mw-grass-surface": "#19231b80", + "--mw-grass-indicator": "var(--mw-grass-9)", + "--mw-grass-track": "var(--mw-grass-9)", + "--mw-grass-contrast": "white", + "--mw-green-1": "#0e1512", + "--mw-green-2": "#121b17", + "--mw-green-3": "#132d21", + "--mw-green-4": "#113b29", + "--mw-green-5": "#174933", + "--mw-green-6": "#20573e", + "--mw-green-7": "#28684a", + "--mw-green-8": "#2f7c57", + "--mw-green-9": "#30a46c", + "--mw-green-10": "#33b074", + "--mw-green-11": "#3dd68c", + "--mw-green-12": "#b1f1cb", + "--mw-green-a1": "#00de4505", + "--mw-green-a2": "#29f99d0b", + "--mw-green-a3": "#22ff991e", + "--mw-green-a4": "#11ff992d", + "--mw-green-a5": "#2bffa23c", + "--mw-green-a6": "#44ffaa4b", + "--mw-green-a7": "#50fdac5e", + "--mw-green-a8": "#54ffad73", + "--mw-green-a9": "#44ffa49e", + "--mw-green-a10": "#43fea4ab", + "--mw-green-a11": "#46fea5d4", + "--mw-green-a12": "#bbffd7f0", + "--mw-green-surface": "#15251d80", + "--mw-green-indicator": "var(--mw-green-9)", + "--mw-green-track": "var(--mw-green-9)", + "--mw-green-contrast": "white", + "--mw-indigo-1": "#11131f", + "--mw-indigo-2": "#141726", + "--mw-indigo-3": "#182449", + "--mw-indigo-4": "#1d2e62", + "--mw-indigo-5": "#253974", + "--mw-indigo-6": "#304384", + "--mw-indigo-7": "#3a4f97", + "--mw-indigo-8": "#435db1", + "--mw-indigo-9": "#3e63dd", + "--mw-indigo-10": "#5472e4", + "--mw-indigo-11": "#9eb1ff", + "--mw-indigo-12": "#d6e1ff", + "--mw-indigo-a1": "#1133ff0f", + "--mw-indigo-a2": "#3354fa17", + "--mw-indigo-a3": "#2f62ff3c", + "--mw-indigo-a4": "#3566ff57", + "--mw-indigo-a5": "#4171fd6b", + "--mw-indigo-a6": "#5178fd7c", + "--mw-indigo-a7": "#5a7fff90", + "--mw-indigo-a8": "#5b81feac", + "--mw-indigo-a9": "#4671ffdb", + "--mw-indigo-a10": "#5c7efee3", + "--mw-indigo-a11": "#9eb1ff", + "--mw-indigo-a12": "#d6e1ff", + "--mw-indigo-surface": "#171d3b80", + "--mw-indigo-indicator": "var(--mw-indigo-9)", + "--mw-indigo-track": "var(--mw-indigo-9)", + "--mw-indigo-contrast": "white", + "--mw-iris-1": "#13131e", + "--mw-iris-2": "#171625", + "--mw-iris-3": "#202248", + "--mw-iris-4": "#262a65", + "--mw-iris-5": "#303374", + "--mw-iris-6": "#3d3e82", + "--mw-iris-7": "#4a4a95", + "--mw-iris-8": "#5958b1", + "--mw-iris-9": "#5b5bd6", + "--mw-iris-10": "#6e6ade", + "--mw-iris-11": "#b1a9ff", + "--mw-iris-12": "#e0dffe", + "--mw-iris-a1": "#3636fe0e", + "--mw-iris-a2": "#564bf916", + "--mw-iris-a3": "#525bff3b", + "--mw-iris-a4": "#4d58ff5a", + "--mw-iris-a5": "#5b62fd6b", + "--mw-iris-a6": "#6d6ffd7a", + "--mw-iris-a7": "#7777fe8e", + "--mw-iris-a8": "#7b7afeac", + "--mw-iris-a9": "#6a6afed4", + "--mw-iris-a10": "#7d79ffdc", + "--mw-iris-a11": "#b1a9ff", + "--mw-iris-a12": "#e1e0fffe", + "--mw-iris-surface": "#1d1b3980", + "--mw-iris-indicator": "var(--mw-iris-9)", + "--mw-iris-track": "var(--mw-iris-9)", + "--mw-iris-contrast": "white", + "--mw-jade-1": "#0d1512", + "--mw-jade-2": "#121c18", + "--mw-jade-3": "#0f2e22", + "--mw-jade-4": "#0b3b2c", + "--mw-jade-5": "#114837", + "--mw-jade-6": "#1b5745", + "--mw-jade-7": "#246854", + "--mw-jade-8": "#2a7e68", + "--mw-jade-9": "#29a383", + "--mw-jade-10": "#27b08b", + "--mw-jade-11": "#1fd8a4", + "--mw-jade-12": "#adf0d4", + "--mw-jade-a1": "#00de4505", + "--mw-jade-a2": "#27fba60c", + "--mw-jade-a3": "#02f99920", + "--mw-jade-a4": "#00ffaa2d", + "--mw-jade-a5": "#11ffb63b", + "--mw-jade-a6": "#34ffc24b", + "--mw-jade-a7": "#45fdc75e", + "--mw-jade-a8": "#48ffcf75", + "--mw-jade-a9": "#38feca9d", + "--mw-jade-a10": "#31fec7ab", + "--mw-jade-a11": "#21fec0d6", + "--mw-jade-a12": "#b8ffe1ef", + "--mw-jade-surface": "#13271f80", + "--mw-jade-indicator": "var(--mw-jade-9)", + "--mw-jade-track": "var(--mw-jade-9)", + "--mw-jade-contrast": "white", + "--mw-lime-1": "#11130c", + "--mw-lime-2": "#151a10", + "--mw-lime-3": "#1f2917", + "--mw-lime-4": "#29371d", + "--mw-lime-5": "#334423", + "--mw-lime-6": "#3d522a", + "--mw-lime-7": "#496231", + "--mw-lime-8": "#577538", + "--mw-lime-9": "#bdee63", + "--mw-lime-10": "#d4ff70", + "--mw-lime-11": "#bde56c", + "--mw-lime-12": "#e3f7ba", + "--mw-lime-a1": "#11bb0003", + "--mw-lime-a2": "#78f7000a", + "--mw-lime-a3": "#9bfd4c1a", + "--mw-lime-a4": "#a7fe5c29", + "--mw-lime-a5": "#affe6537", + "--mw-lime-a6": "#b2fe6d46", + "--mw-lime-a7": "#b6ff6f57", + "--mw-lime-a8": "#b6fd6d6c", + "--mw-lime-a9": "#caff69ed", + "--mw-lime-a10": "#d4ff70", + "--mw-lime-a11": "#d1fe77e4", + "--mw-lime-a12": "#e9febff7", + "--mw-lime-surface": "#1b211580", + "--mw-lime-indicator": "var(--mw-lime-9)", + "--mw-lime-track": "var(--mw-lime-9)", + "--mw-lime-contrast": "#1d211c", + "--mw-mint-1": "#0e1515", + "--mw-mint-2": "#0f1b1b", + "--mw-mint-3": "#092c2b", + "--mw-mint-4": "#003a38", + "--mw-mint-5": "#004744", + "--mw-mint-6": "#105650", + "--mw-mint-7": "#1e685f", + "--mw-mint-8": "#277f70", + "--mw-mint-9": "#86ead4", + "--mw-mint-10": "#a8f5e5", + "--mw-mint-11": "#58d5ba", + "--mw-mint-12": "#c4f5e1", + "--mw-mint-a1": "#00dede05", + "--mw-mint-a2": "#00f9f90b", + "--mw-mint-a3": "#00fff61d", + "--mw-mint-a4": "#00fff42c", + "--mw-mint-a5": "#00fff23a", + "--mw-mint-a6": "#0effeb4a", + "--mw-mint-a7": "#34fde55e", + "--mw-mint-a8": "#41ffdf76", + "--mw-mint-a9": "#92ffe7e9", + "--mw-mint-a10": "#aefeedf5", + "--mw-mint-a11": "#67ffded2", + "--mw-mint-a12": "#cbfee9f5", + "--mw-mint-surface": "#15272780", + "--mw-mint-indicator": "var(--mw-mint-9)", + "--mw-mint-track": "var(--mw-mint-9)", + "--mw-mint-contrast": "#1a211e", + "--mw-orange-1": "#17120e", + "--mw-orange-2": "#1e160f", + "--mw-orange-3": "#331e0b", + "--mw-orange-4": "#462100", + "--mw-orange-5": "#562800", + "--mw-orange-6": "#66350c", + "--mw-orange-7": "#7e451d", + "--mw-orange-8": "#a35829", + "--mw-orange-9": "#f76b15", + "--mw-orange-10": "#ff801f", + "--mw-orange-11": "#ffa057", + "--mw-orange-12": "#ffe0c2", + "--mw-orange-a1": "#ec360007", + "--mw-orange-a2": "#fe6d000e", + "--mw-orange-a3": "#fb6a0025", + "--mw-orange-a4": "#ff590039", + "--mw-orange-a5": "#ff61004a", + "--mw-orange-a6": "#fd75045c", + "--mw-orange-a7": "#ff832c75", + "--mw-orange-a8": "#fe84389d", + "--mw-orange-a9": "#fe6d15f7", + "--mw-orange-a10": "#ff801f", + "--mw-orange-a11": "#ffa057", + "--mw-orange-a12": "#ffe0c2", + "--mw-orange-surface": "#271d1380", + "--mw-orange-indicator": "var(--mw-orange-9)", + "--mw-orange-track": "var(--mw-orange-9)", + "--mw-orange-contrast": "white", + "--mw-pink-1": "#191117", + "--mw-pink-2": "#21121d", + "--mw-pink-3": "#37172f", + "--mw-pink-4": "#4b143d", + "--mw-pink-5": "#591c47", + "--mw-pink-6": "#692955", + "--mw-pink-7": "#833869", + "--mw-pink-8": "#a84885", + "--mw-pink-9": "#d6409f", + "--mw-pink-10": "#de51a8", + "--mw-pink-11": "#ff8dcc", + "--mw-pink-12": "#fdd1ea", + "--mw-pink-a1": "#f412bc09", + "--mw-pink-a2": "#f420bb12", + "--mw-pink-a3": "#fe37cc29", + "--mw-pink-a4": "#fc1ec43f", + "--mw-pink-a5": "#fd35c24e", + "--mw-pink-a6": "#fd51c75f", + "--mw-pink-a7": "#fd62c87b", + "--mw-pink-a8": "#ff68c8a2", + "--mw-pink-a9": "#fe49bcd4", + "--mw-pink-a10": "#ff5cc0dc", + "--mw-pink-a11": "#ff8dcc", + "--mw-pink-a12": "#ffd3ecfd", + "--mw-pink-surface": "#31132980", + "--mw-pink-indicator": "var(--mw-pink-9)", + "--mw-pink-track": "var(--mw-pink-9)", + "--mw-pink-contrast": "white", + "--mw-plum-1": "#181118", + "--mw-plum-2": "#201320", + "--mw-plum-3": "#351a35", + "--mw-plum-4": "#451d47", + "--mw-plum-5": "#512454", + "--mw-plum-6": "#5e3061", + "--mw-plum-7": "#734079", + "--mw-plum-8": "#92549c", + "--mw-plum-9": "#ab4aba", + "--mw-plum-10": "#b658c4", + "--mw-plum-11": "#e796f3", + "--mw-plum-12": "#f4d4f4", + "--mw-plum-a1": "#f112f108", + "--mw-plum-a2": "#f22ff211", + "--mw-plum-a3": "#fd4cfd27", + "--mw-plum-a4": "#f646ff3a", + "--mw-plum-a5": "#f455ff48", + "--mw-plum-a6": "#f66dff56", + "--mw-plum-a7": "#f07cfd70", + "--mw-plum-a8": "#ee84ff95", + "--mw-plum-a9": "#e961feb6", + "--mw-plum-a10": "#ed70ffc0", + "--mw-plum-a11": "#f19cfef3", + "--mw-plum-a12": "#feddfef4", + "--mw-plum-surface": "#2f152f80", + "--mw-plum-indicator": "var(--mw-plum-9)", + "--mw-plum-track": "var(--mw-plum-9)", + "--mw-plum-contrast": "white", + "--mw-purple-1": "#18111b", + "--mw-purple-2": "#1e1523", + "--mw-purple-3": "#301c3b", + "--mw-purple-4": "#3d224e", + "--mw-purple-5": "#48295c", + "--mw-purple-6": "#54346b", + "--mw-purple-7": "#664282", + "--mw-purple-8": "#8457aa", + "--mw-purple-9": "#8e4ec6", + "--mw-purple-10": "#9a5cd0", + "--mw-purple-11": "#d19dff", + "--mw-purple-12": "#ecd9fa", + "--mw-purple-a1": "#b412f90b", + "--mw-purple-a2": "#b744f714", + "--mw-purple-a3": "#c150ff2d", + "--mw-purple-a4": "#bb53fd42", + "--mw-purple-a5": "#be5cfd51", + "--mw-purple-a6": "#c16dfd61", + "--mw-purple-a7": "#c378fd7a", + "--mw-purple-a8": "#c47effa4", + "--mw-purple-a9": "#b661ffc2", + "--mw-purple-a10": "#bc6fffcd", + "--mw-purple-a11": "#d19dff", + "--mw-purple-a12": "#f1ddfffa", + "--mw-purple-surface": "#2b173580", + "--mw-purple-indicator": "var(--mw-purple-9)", + "--mw-purple-track": "var(--mw-purple-9)", + "--mw-purple-contrast": "white", + "--mw-red-1": "#191111", + "--mw-red-2": "#201314", + "--mw-red-3": "#3b1219", + "--mw-red-4": "#500f1c", + "--mw-red-5": "#611623", + "--mw-red-6": "#72232d", + "--mw-red-7": "#8c333a", + "--mw-red-8": "#b54548", + "--mw-red-9": "#e5484d", + "--mw-red-10": "#ec5d5e", + "--mw-red-11": "#ff9592", + "--mw-red-12": "#ffd1d9", + "--mw-red-a1": "#f4121209", + "--mw-red-a2": "#f22f3e11", + "--mw-red-a3": "#ff173f2d", + "--mw-red-a4": "#fe0a3b44", + "--mw-red-a5": "#ff204756", + "--mw-red-a6": "#ff3e5668", + "--mw-red-a7": "#ff536184", + "--mw-red-a8": "#ff5d61b0", + "--mw-red-a9": "#fe4e54e4", + "--mw-red-a10": "#ff6465eb", + "--mw-red-a11": "#ff9592", + "--mw-red-a12": "#ffd1d9", + "--mw-red-surface": "#2f151780", + "--mw-red-indicator": "var(--mw-red-9)", + "--mw-red-track": "var(--mw-red-9)", + "--mw-red-contrast": "white", + "--mw-ruby-1": "#191113", + "--mw-ruby-2": "#1e1517", + "--mw-ruby-3": "#3a141e", + "--mw-ruby-4": "#4e1325", + "--mw-ruby-5": "#5e1a2e", + "--mw-ruby-6": "#6f2539", + "--mw-ruby-7": "#883447", + "--mw-ruby-8": "#b3445a", + "--mw-ruby-9": "#e54666", + "--mw-ruby-10": "#ec5a72", + "--mw-ruby-11": "#ff949d", + "--mw-ruby-12": "#fed2e1", + "--mw-ruby-a1": "#f4124a09", + "--mw-ruby-a2": "#fe5a7f0e", + "--mw-ruby-a3": "#ff235d2c", + "--mw-ruby-a4": "#fd195e42", + "--mw-ruby-a5": "#fe2d6b53", + "--mw-ruby-a6": "#ff447665", + "--mw-ruby-a7": "#ff577d80", + "--mw-ruby-a8": "#ff5c7cae", + "--mw-ruby-a9": "#fe4c70e4", + "--mw-ruby-a10": "#ff617beb", + "--mw-ruby-a11": "#ff949d", + "--mw-ruby-a12": "#ffd3e2fe", + "--mw-ruby-surface": "#2b191d80", + "--mw-ruby-indicator": "var(--mw-ruby-9)", + "--mw-ruby-track": "var(--mw-ruby-9)", + "--mw-ruby-contrast": "white", + "--mw-sky-1": "#0d141f", + "--mw-sky-2": "#111a27", + "--mw-sky-3": "#112840", + "--mw-sky-4": "#113555", + "--mw-sky-5": "#154467", + "--mw-sky-6": "#1b537b", + "--mw-sky-7": "#1f6692", + "--mw-sky-8": "#197cae", + "--mw-sky-9": "#7ce2fe", + "--mw-sky-10": "#a8eeff", + "--mw-sky-11": "#75c7f0", + "--mw-sky-12": "#c2f3ff", + "--mw-sky-a1": "#0044ff0f", + "--mw-sky-a2": "#1171fb18", + "--mw-sky-a3": "#1184fc33", + "--mw-sky-a4": "#128fff49", + "--mw-sky-a5": "#1c9dfd5d", + "--mw-sky-a6": "#28a5ff72", + "--mw-sky-a7": "#2badfe8b", + "--mw-sky-a8": "#1db2fea9", + "--mw-sky-a9": "#7ce3fffe", + "--mw-sky-a10": "#a8eeff", + "--mw-sky-a11": "#7cd3ffef", + "--mw-sky-a12": "#c2f3ff", + "--mw-sky-surface": "#13233b80", + "--mw-sky-indicator": "var(--mw-sky-9)", + "--mw-sky-track": "var(--mw-sky-9)", + "--mw-sky-contrast": "#1c2024", + "--mw-teal-1": "#0d1514", + "--mw-teal-2": "#111c1b", + "--mw-teal-3": "#0d2d2a", + "--mw-teal-4": "#023b37", + "--mw-teal-5": "#084843", + "--mw-teal-6": "#145750", + "--mw-teal-7": "#1c6961", + "--mw-teal-8": "#207e73", + "--mw-teal-9": "#12a594", + "--mw-teal-10": "#0eb39e", + "--mw-teal-11": "#0bd8b6", + "--mw-teal-12": "#adf0dd", + "--mw-teal-a1": "#00deab05", + "--mw-teal-a2": "#12fbe60c", + "--mw-teal-a3": "#00ffe61e", + "--mw-teal-a4": "#00ffe92d", + "--mw-teal-a5": "#00ffea3b", + "--mw-teal-a6": "#1cffe84b", + "--mw-teal-a7": "#2efde85f", + "--mw-teal-a8": "#32ffe775", + "--mw-teal-a9": "#13ffe49f", + "--mw-teal-a10": "#0dffe0ae", + "--mw-teal-a11": "#0afed5d6", + "--mw-teal-a12": "#b8ffebef", + "--mw-teal-surface": "#13272580", + "--mw-teal-indicator": "var(--mw-teal-9)", + "--mw-teal-track": "var(--mw-teal-9)", + "--mw-teal-contrast": "white", + "--mw-tomato-1": "#181111", + "--mw-tomato-2": "#1f1513", + "--mw-tomato-3": "#391714", + "--mw-tomato-4": "#4e1511", + "--mw-tomato-5": "#5e1c16", + "--mw-tomato-6": "#6e2920", + "--mw-tomato-7": "#853a2d", + "--mw-tomato-8": "#ac4d39", + "--mw-tomato-9": "#e54d2e", + "--mw-tomato-10": "#ec6142", + "--mw-tomato-11": "#ff977d", + "--mw-tomato-12": "#fbd3cb", + "--mw-tomato-a1": "#f1121208", + "--mw-tomato-a2": "#ff55330f", + "--mw-tomato-a3": "#ff35232b", + "--mw-tomato-a4": "#fd201142", + "--mw-tomato-a5": "#fe332153", + "--mw-tomato-a6": "#ff4f3864", + "--mw-tomato-a7": "#fd644a7d", + "--mw-tomato-a8": "#fe6d4ea7", + "--mw-tomato-a9": "#fe5431e4", + "--mw-tomato-a10": "#ff6847eb", + "--mw-tomato-a11": "#ff977d", + "--mw-tomato-a12": "#ffd6cefb", + "--mw-tomato-surface": "#2d191580", + "--mw-tomato-indicator": "var(--mw-tomato-9)", + "--mw-tomato-track": "var(--mw-tomato-9)", + "--mw-tomato-contrast": "white", + "--mw-violet-1": "#14121f", + "--mw-violet-2": "#1b1525", + "--mw-violet-3": "#291f43", + "--mw-violet-4": "#33255b", + "--mw-violet-5": "#3c2e69", + "--mw-violet-6": "#473876", + "--mw-violet-7": "#56468b", + "--mw-violet-8": "#6958ad", + "--mw-violet-9": "#6e56cf", + "--mw-violet-10": "#7d66d9", + "--mw-violet-11": "#baa7ff", + "--mw-violet-12": "#e2ddfe", + "--mw-violet-a1": "#4422ff0f", + "--mw-violet-a2": "#853ff916", + "--mw-violet-a3": "#8354fe36", + "--mw-violet-a4": "#7d51fd50", + "--mw-violet-a5": "#845ffd5f", + "--mw-violet-a6": "#8f6cfd6d", + "--mw-violet-a7": "#9879ff83", + "--mw-violet-a8": "#977dfea8", + "--mw-violet-a9": "#8668ffcc", + "--mw-violet-a10": "#9176fed7", + "--mw-violet-a11": "#baa7ff", + "--mw-violet-a12": "#e3defffe", + "--mw-violet-surface": "#25193980", + "--mw-violet-indicator": "var(--mw-violet-9)", + "--mw-violet-track": "var(--mw-violet-9)", + "--mw-violet-contrast": "white", + "--mw-yellow-1": "#14120b", + "--mw-yellow-2": "#1b180f", + "--mw-yellow-3": "#2d2305", + "--mw-yellow-4": "#362b00", + "--mw-yellow-5": "#433500", + "--mw-yellow-6": "#524202", + "--mw-yellow-7": "#665417", + "--mw-yellow-8": "#836a21", + "--mw-yellow-9": "#ffe629", + "--mw-yellow-10": "#ffff57", + "--mw-yellow-11": "#f5e147", + "--mw-yellow-12": "#f6eeb4", + "--mw-yellow-a1": "#d1510004", + "--mw-yellow-a2": "#f9b4000b", + "--mw-yellow-a3": "#ffaa001e", + "--mw-yellow-a4": "#fdb70028", + "--mw-yellow-a5": "#febb0036", + "--mw-yellow-a6": "#fec40046", + "--mw-yellow-a7": "#fdcb225c", + "--mw-yellow-a8": "#fdca327b", + "--mw-yellow-a9": "#ffe629", + "--mw-yellow-a10": "#ffff57", + "--mw-yellow-a11": "#fee949f5", + "--mw-yellow-a12": "#fef6baf6", + "--mw-yellow-surface": "#231f1380", + "--mw-yellow-indicator": "var(--mw-yellow-9)", + "--mw-yellow-track": "var(--mw-yellow-9)", + "--mw-yellow-contrast": "#21201c", +} From 1db89067645e2e9bf0406a4e1e09c038571b267f Mon Sep 17 00:00:00 2001 From: Gjore Milevski Date: Thu, 23 Jul 2026 16:41:57 +0200 Subject: [PATCH 3/8] feat: add theme primitives --- src/manywidgets/themes/_theme.py | 221 +++++++++++++++++++++++++++++++ 1 file changed, 221 insertions(+) create mode 100644 src/manywidgets/themes/_theme.py diff --git a/src/manywidgets/themes/_theme.py b/src/manywidgets/themes/_theme.py new file mode 100644 index 0000000..9cb7672 --- /dev/null +++ b/src/manywidgets/themes/_theme.py @@ -0,0 +1,221 @@ +"""Small, serializable theming primitives for manywidgets. + +The public contract is manywidgets-owned CSS custom properties. A ``Theme`` +serializes to a flat ``{"--mw-*": value}`` dict that widgets sync as ordinary +trait state. Built-in themes may derive values from other systems, but user code +should target the ``--mw-*`` layer. +""" + +from __future__ import annotations + +from dataclasses import dataclass, field, fields, replace +from typing import Mapping + +_NON_VAR_FIELDS = {"chart_palette", "tokens"} +_MW_PREFIX = "--mw-" + + +def _normalize_vars(values: Mapping[str, object] | None) -> dict[str, str]: + out: dict[str, str] = {} + for key, value in (values or {}).items(): + name = str(key) + if not name.startswith(_MW_PREFIX): + raise ValueError(f"Theme token names must start with {_MW_PREFIX!r}: {name!r}") + out[name] = str(value) + return out + + +@dataclass(frozen=True) +class Theme: + """A reusable bundle of manywidgets token values. + + Common semantic tokens are available as named fields. Broader token scales, + component-specific escape hatches, or future tokens can be supplied through + ``tokens`` as explicit ``--mw-*`` names. + """ + + # Semantic colors + color_mode: str | None = None + color_accent: str | None = None + color_accent_hover: str | None = None + color_accent_soft: str | None = None + color_accent_surface: str | None = None + color_text: str | None = None + color_text_muted: str | None = None + color_border: str | None = None + color_border_strong: str | None = None + color_background: str | None = None + color_overlay: str | None = None + color_panel: str | None = None + color_panel_solid: str | None = None + color_panel_translucent: str | None = None + color_surface: str | None = None + color_surface_elevated: str | None = None + color_surface_translucent: str | None = None + color_on_accent: str | None = None + color_code_bg: str | None = None + color_positive: str | None = None + color_negative: str | None = None + color_warning: str | None = None + color_info: str | None = None + color_focus: str | None = None + accent_contrast: str | None = None + accent_surface: str | None = None + accent_indicator: str | None = None + accent_track: str | None = None + backdrop_filter_panel: str | None = None + + # Typography + font_family: str | None = None + font_size_1: str | None = None + font_size_2: str | None = None + font_size_3: str | None = None + font_size_4: str | None = None + font_size_5: str | None = None + font_size_6: str | None = None + font_size_7: str | None = None + font_size_8: str | None = None + font_size_9: str | None = None + font_size_sm: str | None = None + font_size_md: str | None = None + font_weight_light: str | None = None + font_weight_regular: str | None = None + font_weight_medium: str | None = None + font_weight_bold: str | None = None + font_weight_strong: str | None = None + line_height_1: str | None = None + line_height_2: str | None = None + line_height_3: str | None = None + line_height_4: str | None = None + line_height_5: str | None = None + line_height_6: str | None = None + line_height_7: str | None = None + line_height_8: str | None = None + line_height_9: str | None = None + letter_spacing_1: str | None = None + letter_spacing_2: str | None = None + letter_spacing_3: str | None = None + letter_spacing_4: str | None = None + letter_spacing_5: str | None = None + letter_spacing_6: str | None = None + letter_spacing_7: str | None = None + letter_spacing_8: str | None = None + letter_spacing_9: str | None = None + + # Rhythm + block_margin: str | None = None + space_1: str | None = None + space_2: str | None = None + space_3: str | None = None + space_4: str | None = None + space_5: str | None = None + space_6: str | None = None + space_7: str | None = None + space_8: str | None = None + space_9: str | None = None + + # Shape + scaling: str | None = None + radius_factor: str | None = None + radius: str | None = None + radius_sm: str | None = None + radius_1: str | None = None + radius_2: str | None = None + radius_3: str | None = None + radius_4: str | None = None + radius_5: str | None = None + radius_6: str | None = None + radius_full: str | None = None + radius_thumb: str | None = None + + # Elevation + shadow_1: str | None = None + shadow_2: str | None = None + shadow_3: str | None = None + shadow_4: str | None = None + shadow_5: str | None = None + shadow_6: str | None = None + control_shadow: str | None = None + panel_shadow: str | None = None + + # Interaction + cursor_button: str | None = None + cursor_checkbox: str | None = None + cursor_disabled: str | None = None + cursor_link: str | None = None + cursor_menu_item: str | None = None + cursor_radio: str | None = None + cursor_slider_thumb: str | None = None + cursor_slider_thumb_active: str | None = None + cursor_switch: str | None = None + + # Component-level aliases used by widget CSS. + control_padding_x: str | None = None + control_padding_y: str | None = None + control_gap: str | None = None + control_max_width: str | None = None + control_radius: str | None = None + input_padding_x: str | None = None + input_padding_y: str | None = None + input_radius: str | None = None + panel_padding_x: str | None = None + panel_padding_y: str | None = None + panel_radius: str | None = None + stat_value_size: str | None = None + + # Non-DOM renderers need explicit values instead of CSS variables. + chart_palette: list[str] | None = None + + # Escape hatch for any other manywidgets-owned CSS custom property. + tokens: Mapping[str, object] = field(default_factory=dict) + + def __post_init__(self) -> None: + object.__setattr__(self, "tokens", _normalize_vars(self.tokens)) + + def to_vars(self) -> dict[str, str]: + """Serialize set fields to a flat ``{"--mw-*": value}`` dict.""" + out: dict[str, str] = dict(self.tokens) + for f in fields(self): + if f.name in _NON_VAR_FIELDS: + continue + value = getattr(self, f.name) + if value is not None: + out[_MW_PREFIX + f.name.replace("_", "-")] = str(value) + return out + + def extend(self, **overrides: object) -> "Theme": + """Return a copy with overrides applied. + + ``tokens`` is merged instead of replaced so broad token scales and + semantic overrides can accumulate. + """ + if "tokens" in overrides: + merged = { + **self.tokens, + **_normalize_vars(overrides.pop("tokens") or {}), # type: ignore[arg-type] + } + overrides["tokens"] = merged + return replace(self, **overrides) + + @staticmethod + def from_vars(values: Mapping[str, object]) -> "Theme": + """Create a theme from explicit ``--mw-*`` CSS custom properties.""" + return Theme(tokens=values) + + @staticmethod + def merge(*themes: "Theme | None") -> "Theme": + """Field-wise merge of themes. Later non-``None`` values win.""" + result = Theme() + for theme in themes: + if theme is None: + continue + overrides = { + f.name: getattr(theme, f.name) + for f in fields(theme) + if f.name not in _NON_VAR_FIELDS and getattr(theme, f.name) is not None + } + overrides["tokens"] = {**result.tokens, **theme.tokens} + if theme.chart_palette is not None: + overrides["chart_palette"] = list(theme.chart_palette) + result = replace(result, **overrides) + return result From 3c38180d1071f342e1220bee0913e1f5de673982 Mon Sep 17 00:00:00 2001 From: Gjore Milevski Date: Thu, 23 Jul 2026 16:42:10 +0200 Subject: [PATCH 4/8] feat: add radix theme helpers --- src/manywidgets/themes/__init__.py | 31 ++ src/manywidgets/themes/radix.py | 516 +++++++++++++++++++++++++++++ 2 files changed, 547 insertions(+) create mode 100644 src/manywidgets/themes/__init__.py create mode 100644 src/manywidgets/themes/radix.py diff --git a/src/manywidgets/themes/__init__.py b/src/manywidgets/themes/__init__.py new file mode 100644 index 0000000..4fe6b3b --- /dev/null +++ b/src/manywidgets/themes/__init__.py @@ -0,0 +1,31 @@ +"""Theming primitives and built-in token themes for manywidgets.""" + +from ._theme import Theme +from .radix import ( + RADIX_ACCENT_COLORS, + RADIX_COLOR_FAMILIES, + RADIX_GRAY_COLORS, + RADIX_RADIUS_PRESETS, + RADIX_SCALING_PRESETS, + RADIX_SOURCE, + dark, + dark_theme, + light, + light_theme, + radix_theme, +) + +__all__ = [ + "RADIX_ACCENT_COLORS", + "RADIX_COLOR_FAMILIES", + "RADIX_GRAY_COLORS", + "RADIX_RADIUS_PRESETS", + "RADIX_SCALING_PRESETS", + "RADIX_SOURCE", + "Theme", + "dark", + "dark_theme", + "light", + "light_theme", + "radix_theme", +] diff --git a/src/manywidgets/themes/radix.py b/src/manywidgets/themes/radix.py new file mode 100644 index 0000000..2fa98c0 --- /dev/null +++ b/src/manywidgets/themes/radix.py @@ -0,0 +1,516 @@ +"""Radix-adapted token values under the manywidgets ``--mw-*`` namespace. + +Values in this module are adapted from Radix Themes and Radix Colors token +scales. Radix is MIT licensed. The public API remains manywidgets-owned: +callers should set or override ``--mw-*`` tokens, not Radix's raw CSS variable +names or selectors. +""" + +from __future__ import annotations + +from collections.abc import Mapping + +from ._radix_tokens import ( + RADIX_ACCENT_COLORS, + RADIX_COLOR_FAMILIES, + RADIX_DARK_COLOR_TOKENS, + RADIX_GRAY_COLORS, + RADIX_LIGHT_COLOR_TOKENS, + RADIX_MATCHING_GRAY_COLORS, + RADIX_ROOT_COLOR_TOKENS, +) +from ._theme import Theme + +RADIX_SOURCE = "Adapted from Radix Themes/Colors token values, MIT license." + +RADIX_SCALING_PRESETS = { + "90%": "0.9", + "95%": "0.95", + "100%": "1", + "105%": "1.05", + "110%": "1.1", +} + +RADIX_RADIUS_PRESETS = { + "none": { + "--mw-radius-factor": "0", + "--mw-radius-full": "0px", + "--mw-radius-thumb": "0.5px", + }, + "small": { + "--mw-radius-factor": "0.75", + "--mw-radius-full": "0px", + "--mw-radius-thumb": "0.5px", + }, + "medium": { + "--mw-radius-factor": "1", + "--mw-radius-full": "0px", + "--mw-radius-thumb": "9999px", + }, + "large": { + "--mw-radius-factor": "1.5", + "--mw-radius-full": "0px", + "--mw-radius-thumb": "9999px", + }, + "full": { + "--mw-radius-factor": "1.5", + "--mw-radius-full": "9999px", + "--mw-radius-thumb": "9999px", + }, +} + +_SYSTEM_FONT = ( + '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", ' + "system-ui, sans-serif" +) +_CODE_FONT = ( + '"Menlo", "Consolas", "Bitstream Vera Sans Mono", monospace, ' + '"Apple Color Emoji", "Segoe UI Emoji"' +) +_SERIF_FONT = '"Times New Roman", "Times", serif' + +_NUMBER_SUFFIXES = tuple(str(i) for i in range(1, 13)) +_ALPHA_SUFFIXES = tuple(f"a{i}" for i in range(1, 13)) +_COLOR_SUFFIXES = ( + *_NUMBER_SUFFIXES, + *_ALPHA_SUFFIXES, + "contrast", + "surface", + "indicator", + "track", +) + +_COMMON_TOKENS: dict[str, str] = { + "--mw-scaling": "1", + "--mw-scaling-90": "0.9", + "--mw-scaling-95": "0.95", + "--mw-scaling-100": "1", + "--mw-scaling-105": "1.05", + "--mw-scaling-110": "1.1", + "--mw-radius-1": "calc(3px * var(--mw-scaling) * var(--mw-radius-factor))", + "--mw-radius-2": "calc(4px * var(--mw-scaling) * var(--mw-radius-factor))", + "--mw-radius-3": "calc(6px * var(--mw-scaling) * var(--mw-radius-factor))", + "--mw-radius-4": "calc(8px * var(--mw-scaling) * var(--mw-radius-factor))", + "--mw-radius-5": "calc(12px * var(--mw-scaling) * var(--mw-radius-factor))", + "--mw-radius-6": "calc(16px * var(--mw-scaling) * var(--mw-radius-factor))", + "--mw-radius-sm": "var(--mw-radius-3)", + "--mw-radius": "var(--mw-radius-4)", + "--mw-radius-md": "var(--mw-radius-4)", + "--mw-radius-lg": "var(--mw-radius-5)", + "--mw-space-1": "calc(4px * var(--mw-scaling))", + "--mw-space-2": "calc(8px * var(--mw-scaling))", + "--mw-space-3": "calc(12px * var(--mw-scaling))", + "--mw-space-4": "calc(16px * var(--mw-scaling))", + "--mw-space-5": "calc(24px * var(--mw-scaling))", + "--mw-space-6": "calc(32px * var(--mw-scaling))", + "--mw-space-7": "calc(40px * var(--mw-scaling))", + "--mw-space-8": "calc(48px * var(--mw-scaling))", + "--mw-space-9": "calc(64px * var(--mw-scaling))", + "--mw-block-margin": "10px 0", +} + +_TYPOGRAPHY_TOKENS: dict[str, str] = { + "--mw-font-size-1": "calc(12px * var(--mw-scaling))", + "--mw-font-size-2": "calc(14px * var(--mw-scaling))", + "--mw-font-size-3": "calc(16px * var(--mw-scaling))", + "--mw-font-size-4": "calc(18px * var(--mw-scaling))", + "--mw-font-size-5": "calc(20px * var(--mw-scaling))", + "--mw-font-size-6": "calc(24px * var(--mw-scaling))", + "--mw-font-size-7": "calc(28px * var(--mw-scaling))", + "--mw-font-size-8": "calc(35px * var(--mw-scaling))", + "--mw-font-size-9": "calc(60px * var(--mw-scaling))", + "--mw-font-weight-light": "300", + "--mw-font-weight-regular": "400", + "--mw-font-weight-medium": "500", + "--mw-font-weight-bold": "700", + "--mw-line-height-1": "calc(16px * var(--mw-scaling))", + "--mw-line-height-2": "calc(20px * var(--mw-scaling))", + "--mw-line-height-3": "calc(24px * var(--mw-scaling))", + "--mw-line-height-4": "calc(26px * var(--mw-scaling))", + "--mw-line-height-5": "calc(28px * var(--mw-scaling))", + "--mw-line-height-6": "calc(30px * var(--mw-scaling))", + "--mw-line-height-7": "calc(36px * var(--mw-scaling))", + "--mw-line-height-8": "calc(40px * var(--mw-scaling))", + "--mw-line-height-9": "calc(60px * var(--mw-scaling))", + "--mw-letter-spacing-1": "0.0025em", + "--mw-letter-spacing-2": "0em", + "--mw-letter-spacing-3": "0em", + "--mw-letter-spacing-4": "-0.0025em", + "--mw-letter-spacing-5": "-0.005em", + "--mw-letter-spacing-6": "-0.00625em", + "--mw-letter-spacing-7": "-0.0075em", + "--mw-letter-spacing-8": "-0.01em", + "--mw-letter-spacing-9": "-0.025em", + "--mw-default-font-family": _SYSTEM_FONT, + "--mw-default-font-size": "var(--mw-font-size-3)", + "--mw-default-font-style": "normal", + "--mw-default-font-weight": "var(--mw-font-weight-regular)", + "--mw-default-line-height": "1.5", + "--mw-default-letter-spacing": "0em", + "--mw-default-leading-trim-start": "0.42em", + "--mw-default-leading-trim-end": "0.36em", + "--mw-heading-font-family": "var(--mw-default-font-family)", + "--mw-heading-font-size-adjust": "1", + "--mw-heading-font-style": "normal", + "--mw-heading-leading-trim-start": "var(--mw-default-leading-trim-start)", + "--mw-heading-leading-trim-end": "var(--mw-default-leading-trim-end)", + "--mw-heading-letter-spacing": "0em", + "--mw-heading-line-height-1": "calc(16px * var(--mw-scaling))", + "--mw-heading-line-height-2": "calc(18px * var(--mw-scaling))", + "--mw-heading-line-height-3": "calc(22px * var(--mw-scaling))", + "--mw-heading-line-height-4": "calc(24px * var(--mw-scaling))", + "--mw-heading-line-height-5": "calc(26px * var(--mw-scaling))", + "--mw-heading-line-height-6": "calc(30px * var(--mw-scaling))", + "--mw-heading-line-height-7": "calc(36px * var(--mw-scaling))", + "--mw-heading-line-height-8": "calc(40px * var(--mw-scaling))", + "--mw-heading-line-height-9": "calc(60px * var(--mw-scaling))", + "--mw-code-font-family": _CODE_FONT, + "--mw-code-font-size-adjust": "0.95", + "--mw-code-font-style": "normal", + "--mw-code-font-weight": "inherit", + "--mw-code-letter-spacing": "-0.007em", + "--mw-code-padding-top": "0.1em", + "--mw-code-padding-bottom": "0.1em", + "--mw-code-padding-left": "0.25em", + "--mw-code-padding-right": "0.25em", + "--mw-strong-font-family": "var(--mw-default-font-family)", + "--mw-strong-font-size-adjust": "1", + "--mw-strong-font-style": "inherit", + "--mw-strong-font-weight": "var(--mw-font-weight-bold)", + "--mw-strong-letter-spacing": "0em", + "--mw-em-font-family": _SERIF_FONT, + "--mw-em-font-size-adjust": "1.18", + "--mw-em-font-style": "italic", + "--mw-em-font-weight": "inherit", + "--mw-em-letter-spacing": "-0.025em", + "--mw-quote-font-family": _SERIF_FONT, + "--mw-quote-font-size-adjust": "1.18", + "--mw-quote-font-style": "italic", + "--mw-quote-font-weight": "inherit", + "--mw-quote-letter-spacing": "-0.025em", + "--mw-tab-active-letter-spacing": "-0.01em", + "--mw-tab-active-word-spacing": "0em", + "--mw-tab-inactive-letter-spacing": "0em", + "--mw-tab-inactive-word-spacing": "0em", + "--mw-font-family": "var(--mw-default-font-family)", + "--mw-font-size-sm": "var(--mw-font-size-1)", + "--mw-font-size-md": "var(--mw-font-size-2)", + "--mw-font-weight-strong": "600", +} + +_CURSOR_TOKENS: dict[str, str] = { + "--mw-cursor-button": "default", + "--mw-cursor-checkbox": "default", + "--mw-cursor-disabled": "not-allowed", + "--mw-cursor-link": "pointer", + "--mw-cursor-menu-item": "default", + "--mw-cursor-radio": "default", + "--mw-cursor-slider-thumb": "default", + "--mw-cursor-slider-thumb-active": "default", + "--mw-cursor-switch": "default", +} + +_COMPONENT_TOKENS: dict[str, str] = { + "--mw-control-padding-x": "var(--mw-space-3)", + "--mw-control-padding-y": "calc(10px * var(--mw-scaling))", + "--mw-control-gap": "calc(6px * var(--mw-scaling))", + "--mw-control-max-width": "320px", + "--mw-control-radius": "var(--mw-radius-4)", + "--mw-control-shadow": "none", + "--mw-input-padding-x": "var(--mw-space-2)", + "--mw-input-padding-y": "calc(6px * var(--mw-scaling))", + "--mw-input-radius": "var(--mw-radius-3)", + "--mw-panel-padding-x": "calc(18px * var(--mw-scaling))", + "--mw-panel-padding-y": "var(--mw-space-3)", + "--mw-panel-radius": "var(--mw-radius-4)", + "--mw-panel-shadow": "var(--mw-shadow-2)", + "--mw-stat-min-width": "140px", + "--mw-stat-value-size": "calc(30px * var(--mw-scaling))", + "--mw-number-display-value-size": "calc(40px * var(--mw-scaling))", + "--mw-toggle-track-width": "calc(40px * var(--mw-scaling))", + "--mw-toggle-track-height": "calc(22px * var(--mw-scaling))", + "--mw-toggle-thumb-size": "calc(18px * var(--mw-scaling))", +} + +_LIGHT_SHADOWS = { + "--mw-shadow-1": ( + "inset 0 0 0 1px var(--mw-gray-a5), " + "inset 0 1.5px 2px 0 var(--mw-gray-a2), " + "inset 0 1.5px 2px 0 var(--mw-black-a2)" + ), + "--mw-shadow-2": ( + "0 0 0 1px var(--mw-gray-a3), " + "0 0 0 0.5px var(--mw-black-a1), " + "0 1px 1px 0 var(--mw-gray-a2), " + "0 2px 1px -1px var(--mw-black-a1), " + "0 1px 3px 0 var(--mw-black-a1)" + ), + "--mw-shadow-3": ( + "0 0 0 1px var(--mw-gray-a3), " + "0 2px 3px -2px var(--mw-gray-a3), " + "0 3px 12px -4px var(--mw-black-a2), " + "0 4px 16px -8px var(--mw-black-a2)" + ), + "--mw-shadow-4": ( + "0 0 0 1px var(--mw-gray-a3), " + "0 8px 40px var(--mw-black-a1), " + "0 12px 32px -16px var(--mw-gray-a3)" + ), + "--mw-shadow-5": ( + "0 0 0 1px var(--mw-gray-a3), " + "0 12px 60px var(--mw-black-a3), " + "0 12px 32px -16px var(--mw-gray-a5)" + ), + "--mw-shadow-6": ( + "0 0 0 1px var(--mw-gray-a3), " + "0 12px 60px var(--mw-black-a3), " + "0 16px 64px var(--mw-gray-a2), " + "0 16px 36px -20px var(--mw-gray-a7)" + ), +} + +_DARK_SHADOWS = { + "--mw-shadow-1": ( + "inset 0 -1px 1px 0 var(--mw-gray-a3), " + "inset 0 0 0 1px var(--mw-gray-a3), " + "inset 0 3px 4px 0 var(--mw-black-a5), " + "inset 0 0 0 1px var(--mw-gray-a4)" + ), + "--mw-shadow-2": ( + "0 0 0 1px var(--mw-gray-a6), " + "0 0 0 0.5px var(--mw-black-a3), " + "0 1px 1px 0 var(--mw-black-a6), " + "0 2px 1px -1px var(--mw-black-a6), " + "0 1px 3px 0 var(--mw-black-a5)" + ), + "--mw-shadow-3": ( + "0 0 0 1px var(--mw-gray-a6), " + "0 2px 3px -2px var(--mw-black-a3), " + "0 3px 8px -2px var(--mw-black-a6), " + "0 4px 12px -4px var(--mw-black-a7)" + ), + "--mw-shadow-4": ( + "0 0 0 1px var(--mw-gray-a6), " + "0 8px 40px var(--mw-black-a3), " + "0 12px 32px -16px var(--mw-black-a5)" + ), + "--mw-shadow-5": ( + "0 0 0 1px var(--mw-gray-a6), " + "0 12px 60px var(--mw-black-a5), " + "0 12px 32px -16px var(--mw-black-a7)" + ), + "--mw-shadow-6": ( + "0 0 0 1px var(--mw-gray-a6), " + "0 12px 60px var(--mw-black-a4), " + "0 16px 64px var(--mw-black-a6), " + "0 16px 36px -20px var(--mw-black-a11)" + ), +} + +_LIGHT_SEMANTIC_TOKENS = { + "--mw-color-mode": "light", + "--mw-color-background": "white", + "--mw-color-overlay": "var(--mw-black-a6)", + "--mw-color-panel-solid": "white", + "--mw-color-panel-translucent": "rgba(255, 255, 255, 0.7)", + "--mw-color-panel": "var(--mw-color-panel-translucent)", + "--mw-color-surface-translucent": "rgba(255, 255, 255, 0.85)", + "--mw-backdrop-filter-panel": "blur(64px)", +} + +_DARK_SEMANTIC_TOKENS = { + "--mw-color-mode": "dark", + "--mw-color-background": "var(--mw-gray-1)", + "--mw-color-overlay": "var(--mw-black-a8)", + "--mw-color-panel-solid": "var(--mw-gray-2)", + "--mw-color-panel-translucent": "var(--mw-gray-a2)", + "--mw-color-panel": "var(--mw-color-panel-translucent)", + "--mw-color-surface-translucent": "rgba(0, 0, 0, 0.25)", + "--mw-backdrop-filter-panel": "blur(64px)", +} + +_SEMANTIC_TOKENS = { + "--mw-color-accent": "var(--myst-color-primary, var(--mw-accent-9))", + "--mw-color-accent-hover": "var(--myst-color-primary-hover, var(--mw-accent-10))", + "--mw-color-accent-soft": "var(--myst-color-active-bg, var(--mw-accent-a3))", + "--mw-color-accent-surface": "var(--myst-color-accent-surface, var(--mw-accent-surface))", + "--mw-color-text": "var(--myst-color-text, var(--jp-content-font-color1, var(--mw-gray-12)))", + "--mw-color-text-muted": ( + "var(--myst-color-text-secondary, var(--jp-content-font-color2, var(--mw-gray-11)))" + ), + "--mw-color-border": "var(--myst-color-border, var(--jp-border-color2, var(--mw-gray-6)))", + "--mw-color-border-strong": ( + "var(--myst-color-border-strong, var(--jp-border-color1, var(--mw-gray-7)))" + ), + "--mw-color-surface": ( + "var(--myst-color-bg, var(--jp-layout-color1, var(--mw-color-background)))" + ), + "--mw-color-surface-elevated": ( + "var(--myst-color-surface, var(--jp-layout-color2, var(--mw-color-panel-solid)))" + ), + "--mw-color-on-accent": "var(--mw-accent-contrast)", + "--mw-color-code-bg": ( + "var(--myst-color-bg-secondary, var(--jp-layout-color2, var(--mw-gray-3)))" + ), + "--mw-color-positive": "var(--myst-color-success, var(--mw-green-11))", + "--mw-color-negative": "var(--myst-color-danger, var(--mw-red-11))", + "--mw-color-warning": "var(--myst-color-warning, var(--mw-amber-11))", + "--mw-color-info": "var(--myst-color-info, var(--mw-blue-11))", + "--mw-color-focus": "var(--myst-color-focus-ring, var(--mw-focus-8))", +} + +_LIGHT_CHART_PALETTE = [ + "#3e63dd", + "#e5484d", + "#30a46c", + "#f76b15", + "#8e4ec6", + "#0090ff", + "#ffc53d", + "#d6409f", + "#00a2c7", + "#46a758", +] + +_DARK_CHART_PALETTE = [ + "#9eb1ff", + "#ff9592", + "#3dd68c", + "#ffa057", + "#d19dff", + "#70b8ff", + "#ffd60a", + "#ff8dcc", + "#4ccce6", + "#71d083", +] + + +def radix_theme( + *, + appearance: str = "light", + accent: str = "indigo", + gray: str = "auto", + radius: str = "medium", + scaling: str = "100%", +) -> Theme: + """Return a Radix-adapted manywidgets theme. + + The returned theme is plain serialized ``--mw-*`` variables. It does not + depend on ``@radix-ui/themes`` or React at runtime. + """ + + _validate_choice("appearance", appearance, ("light", "dark")) + _validate_choice("accent", accent, RADIX_ACCENT_COLORS) + _validate_choice("gray", gray, RADIX_GRAY_COLORS) + _validate_choice("radius", radius, tuple(RADIX_RADIUS_PRESETS)) + _validate_choice("scaling", scaling, tuple(RADIX_SCALING_PRESETS)) + + resolved_gray = RADIX_MATCHING_GRAY_COLORS[accent] if gray == "auto" else gray + source = RADIX_LIGHT_COLOR_TOKENS if appearance == "light" else RADIX_DARK_COLOR_TOKENS + tokens = { + **_COMMON_TOKENS, + **_TYPOGRAPHY_TOKENS, + **_CURSOR_TOKENS, + **_COMPONENT_TOKENS, + **RADIX_ROOT_COLOR_TOKENS, + **source, + **_alias_color(source, "gray", resolved_gray), + } + tokens.update(_alias_color(source, "accent", resolved_gray if accent == "gray" else accent)) + tokens.update(_focus_tokens()) + tokens.update(_LIGHT_SHADOWS if appearance == "light" else _DARK_SHADOWS) + tokens.update(_LIGHT_SEMANTIC_TOKENS if appearance == "light" else _DARK_SEMANTIC_TOKENS) + tokens.update(_SEMANTIC_TOKENS) + tokens.update(RADIX_RADIUS_PRESETS[radius]) + tokens["--mw-scaling"] = RADIX_SCALING_PRESETS[scaling] + + return Theme(tokens=tokens, chart_palette=_chart_palette(appearance)) + + +def light_theme( + *, + accent: str = "indigo", + gray: str = "auto", + radius: str = "medium", + scaling: str = "100%", +) -> Theme: + """Return a light Radix-adapted manywidgets theme.""" + + return radix_theme( + appearance="light", + accent=accent, + gray=gray, + radius=radius, + scaling=scaling, + ) + + +def dark_theme( + *, + accent: str = "indigo", + gray: str = "auto", + radius: str = "medium", + scaling: str = "100%", +) -> Theme: + """Return a dark Radix-adapted manywidgets theme.""" + + return radix_theme( + appearance="dark", + accent=accent, + gray=gray, + radius=radius, + scaling=scaling, + ) + + +def _validate_choice(name: str, value: str, options: tuple[str, ...]) -> None: + if value not in options: + allowed = ", ".join(options) + raise ValueError(f"Unknown Radix {name} {value!r}. Expected one of: {allowed}") + + +def _alias_color(source: Mapping[str, str], target: str, family: str) -> dict[str, str]: + aliases: dict[str, str] = {} + for suffix in _COLOR_SUFFIXES: + source_key = _color_key(family, suffix) + value = source[source_key] + if suffix in {"indicator", "track"}: + value = f"var(--mw-{target}-9)" + aliases[f"--mw-{target}-{suffix}"] = value + return aliases + + +def _color_key(family: str, suffix: str) -> str: + if family == "gray": + return f"--mw-radix-gray-{suffix}" + return f"--mw-{family}-{suffix}" + + +def _focus_tokens() -> dict[str, str]: + tokens: dict[str, str] = {} + for suffix in (*_NUMBER_SUFFIXES, *_ALPHA_SUFFIXES): + tokens[f"--mw-focus-{suffix}"] = f"var(--mw-accent-{suffix})" + return tokens + + +def _chart_palette(appearance: str) -> list[str]: + return list(_LIGHT_CHART_PALETTE if appearance == "light" else _DARK_CHART_PALETTE) + + +light = light_theme() +dark = dark_theme() + +__all__ = [ + "RADIX_ACCENT_COLORS", + "RADIX_COLOR_FAMILIES", + "RADIX_GRAY_COLORS", + "RADIX_RADIUS_PRESETS", + "RADIX_SCALING_PRESETS", + "RADIX_SOURCE", + "dark", + "dark_theme", + "light", + "light_theme", + "radix_theme", +] From 46f6cf51464f299e231a82777cfd03c7fb18f605 Mon Sep 17 00:00:00 2001 From: Gjore Milevski Date: Thu, 23 Jul 2026 16:42:24 +0200 Subject: [PATCH 5/8] feat: sync theme vars from widgets --- src/manywidgets/__init__.py | 2 ++ src/manywidgets/_base.py | 23 +++++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/src/manywidgets/__init__.py b/src/manywidgets/__init__.py index 6af8e2c..e631c16 100644 --- a/src/manywidgets/__init__.py +++ b/src/manywidgets/__init__.py @@ -26,6 +26,7 @@ from .slider import Slider from .stat import Stat from .text import Text +from .themes import Theme from .toggle import Toggle __all__ = [ @@ -44,6 +45,7 @@ "Slider", "Stat", "Text", + "Theme", "Toggle", "__version__", ] diff --git a/src/manywidgets/_base.py b/src/manywidgets/_base.py index e912389..c1772d6 100644 --- a/src/manywidgets/_base.py +++ b/src/manywidgets/_base.py @@ -16,6 +16,8 @@ import anywidget import traitlets +from .themes._theme import _normalize_vars + # Per-class monotonic counters so auto-generated ids are stable and readable # (``chart_1``, ``chart_2``, ``slider_1``, …) within a kernel session. _id_counters: dict[str, int] = defaultdict(int) @@ -61,13 +63,34 @@ class BaseWidget(anywidget.AnyWidget): cross-widget linking. Subclasses set their own ``_esm`` / ``_css`` (relative to their own file, via :func:`asset`) exactly like the golden-example structure. + + Widgets also accept optional ``theme`` and ``style`` keyword arguments. + Both resolve to a flat ``{"--mw-*": value}`` dict synced to the frontend as + ``theme_vars``. Individual widgets opt into using those variables from their + own render/CSS layer. """ widget_id = traitlets.Unicode( help="Stable unique id used for cross-widget linking (auto-assigned)." ).tag(sync=True) + theme_vars = traitlets.Dict( + help="Resolved manywidgets CSS custom properties from theme/style kwargs." + ).tag(sync=True) + def __init__(self, **kwargs): + theme = kwargs.pop("theme", None) + style = kwargs.pop("style", None) super().__init__(**kwargs) if not self.widget_id: self.widget_id = _next_id(type(self).__name__.lower()) + + resolved = dict(self.theme_vars) + if theme is not None: + if not hasattr(theme, "to_vars"): + raise TypeError("theme must expose a to_vars() method") + resolved.update(_normalize_vars(theme.to_vars())) + if style: + resolved.update(_normalize_vars(style)) + if resolved: + self.theme_vars = resolved From dc3edc0e4f287ba4d415f0cf0fa41db373f44e11 Mon Sep 17 00:00:00 2001 From: Gjore Milevski Date: Thu, 23 Jul 2026 16:42:34 +0200 Subject: [PATCH 6/8] feat: apply theme vars in core --- packages/core/src/index.ts | 224 ++++++++++++++++++++++++++++++++++++- 1 file changed, 221 insertions(+), 3 deletions(-) diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 30b23f2..c47d2b7 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -166,7 +166,7 @@ export function deliverCustomMessage( } } -// ── Static-export host registry ────────────────────────────────────────────── +// Static-export host registry type Registry = { get?: (key: string) => AnyModel | undefined; @@ -313,7 +313,7 @@ function withTimeout(promise: Promise, ms: number): Promise { }); } -// ── Child rendering (layout widgets) ───────────────────────────────────────── +// Child rendering for layout widgets const noop = (): void => {}; @@ -367,7 +367,225 @@ export async function renderChild( }; } -// ── Shadow-DOM-safe CSS injection ──────────────────────────────────────────── +// Theme variables + +export type HostColorMode = "light" | "dark"; + +export const HOST_DARK_MODE_SELECTORS = [ + ".dark", + ".dark-theme", + "[data-theme='dark']", + "[data-color-mode='dark']", +] as const; + +export const HOST_LIGHT_MODE_SELECTORS = [ + ".light", + ".light-theme", + "[data-theme='light']", + "[data-color-mode='light']", +] as const; + +const THEME_DEFAULT_CSS = ` +.manywidgets-theme-defaults { + --mw-font-family: var(--jp-ui-font-family, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, sans-serif); + --mw-font-family-mono: var(--jp-code-font-family, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace); + --mw-font-size-sm: 12px; + --mw-font-size-md: 14px; + --mw-font-weight-strong: 600; + --mw-color-text: var(--myst-color-text, var(--jp-content-font-color1, #24292e)); + --mw-color-text-muted: var(--myst-color-text-secondary, var(--jp-content-font-color2, #586069)); + --mw-color-surface: var(--myst-color-bg, var(--jp-layout-color1, #ffffff)); + --mw-color-surface-elevated: var(--myst-color-surface, var(--jp-layout-color2, #f6f8fa)); + --mw-color-border: var(--myst-color-border, var(--jp-border-color2, #e1e4e8)); + --mw-color-border-strong: var(--myst-color-border-strong, var(--jp-border-color1, #d0d7de)); + --mw-color-accent: var(--myst-color-primary, var(--jp-brand-color1, #0366d6)); + --mw-color-accent-hover: var(--myst-color-primary-hover, var(--jp-brand-color0, #0256c7)); + --mw-color-accent-soft: var(--myst-color-active-bg, #ddf4ff); + --mw-color-on-accent: #ffffff; + --mw-color-code-bg: var(--myst-color-bg-secondary, var(--jp-layout-color2, #f6f8fa)); + --mw-color-positive: var(--myst-color-success, #1a7f37); + --mw-color-negative: var(--myst-color-danger, #cf222e); + --mw-color-warning: var(--myst-color-warning, #9a6700); + --mw-color-info: var(--myst-color-info, var(--mw-color-accent)); + --mw-color-focus: var(--myst-color-focus-ring, var(--mw-color-accent)); + --mw-radius-2: 4px; + --mw-radius-3: 6px; + --mw-radius-4: 8px; + --mw-radius-5: 10px; + --mw-radius-thumb: 9999px; + --mw-shadow-1: 0 1px 2px rgba(0, 0, 0, 0.25); + --mw-shadow-2: 0 0 0 1px rgba(0, 0, 0, 0.1); + --mw-control-padding-x: 14px; + --mw-control-padding-y: 10px; + --mw-control-gap: 6px; + --mw-control-max-width: 320px; + --mw-control-radius: var(--mw-radius-4); + --mw-input-padding-x: 8px; + --mw-input-padding-y: 6px; + --mw-input-radius: var(--mw-radius-3); + --mw-panel-padding-x: 18px; + --mw-panel-padding-y: 14px; + --mw-panel-radius: var(--mw-radius-5); + --mw-stat-min-width: 140px; + --mw-stat-value-size: 30px; + --mw-number-display-value-size: 40px; + --mw-toggle-track-width: 40px; + --mw-toggle-track-height: 22px; + --mw-toggle-thumb-size: 18px; + --mw-cursor-button: pointer; + --mw-cursor-slider-thumb: default; +} + +.manywidgets-theme-defaults[data-mw-color-mode="dark"] { + --mw-color-text: var(--myst-color-text, var(--jp-content-font-color1, #f0f6fc)); + --mw-color-text-muted: var(--myst-color-text-secondary, var(--jp-content-font-color2, #8b949e)); + --mw-color-surface: var(--myst-color-bg, var(--jp-layout-color1, #111113)); + --mw-color-surface-elevated: var(--myst-color-surface, var(--jp-layout-color2, #18191b)); + --mw-color-border: var(--myst-color-border, var(--jp-border-color2, #3a3f44)); + --mw-color-border-strong: var(--myst-color-border-strong, var(--jp-border-color1, #4d5358)); + --mw-color-accent: var(--myst-color-primary, var(--jp-brand-color1, #6b9cff)); + --mw-color-accent-hover: var(--myst-color-primary-hover, var(--jp-brand-color0, #8bb3ff)); + --mw-color-accent-soft: var(--myst-color-active-bg, #1d2d50); + --mw-color-code-bg: var(--myst-color-bg-secondary, var(--jp-layout-color2, #1f2328)); + --mw-color-positive: var(--myst-color-success, #7ee787); + --mw-color-negative: var(--myst-color-danger, #ff7b72); + --mw-color-warning: var(--myst-color-warning, #f2cc60); + --mw-shadow-1: 0 1px 2px rgba(0, 0, 0, 0.5); + --mw-shadow-2: 0 0 0 1px rgba(255, 255, 255, 0.12); +} +`; + +function readThemeVars(model: AnyModel): Record { + const vars = model.get("theme_vars"); + return vars && typeof vars === "object" ? vars as Record : {}; +} + +function colorModeFromThemeVars(vars: Record): HostColorMode | null { + const mode = vars["--mw-color-mode"]; + if (typeof mode !== "string") return null; + const normalized = mode.trim().toLowerCase(); + if (normalized === "dark" || normalized === "light") return normalized; + return null; +} + +function elementHasSelector(el: Element, selectors: readonly string[]): boolean { + return selectors.some((selector) => el.matches(selector) || !!el.closest(selector)); +} + +function hasThemeAncestor(el: HTMLElement): boolean { + if (el.parentElement?.closest(".manywidgets-theme")) return true; + const root = el.getRootNode(); + const host = typeof ShadowRoot !== "undefined" && root instanceof ShadowRoot ? root.host : null; + return !!host?.closest(".manywidgets-theme"); +} + +/** + * Detect the host page's current color mode. + * + * MyST's default themes expose dark mode through Tailwind's `.dark` class. + * The extra selectors cover common class/data-attribute host conventions so + * widgets can share one detection path in notebooks and static exports. + */ +export function detectHostColorMode(el: HTMLElement): HostColorMode | null { + const doc = el.ownerDocument; + const root = el.getRootNode(); + const host = typeof ShadowRoot !== "undefined" && root instanceof ShadowRoot ? root.host : null; + const candidates = [el, host, doc.body, doc.documentElement].filter( + (candidate): candidate is Element => candidate instanceof Element, + ); + + if (candidates.some((candidate) => elementHasSelector(candidate, HOST_DARK_MODE_SELECTORS))) { + return "dark"; + } + if (candidates.some((candidate) => elementHasSelector(candidate, HOST_LIGHT_MODE_SELECTORS))) { + return "light"; + } + + const colorScheme = [el, doc.documentElement] + .map((candidate) => getComputedStyle(candidate).colorScheme) + .find((value) => value && value !== "normal") || ""; + const schemes = colorScheme.split(/\s+/); + if (schemes.includes("dark") && !schemes.includes("light")) return "dark"; + if (schemes.includes("light") && !schemes.includes("dark")) return "light"; + return null; +} + +export function observeHostColorMode(el: HTMLElement, fn: () => void): () => void { + const doc = el.ownerDocument; + const root = el.getRootNode(); + const host = typeof ShadowRoot !== "undefined" && root instanceof ShadowRoot ? root.host : null; + const targets = [host, doc.body, doc.documentElement].filter( + (target): target is Element => target instanceof Element, + ); + const observer = typeof MutationObserver !== "undefined" + ? new MutationObserver(fn) + : null; + for (const target of targets) { + observer?.observe(target, { + attributes: true, + attributeFilter: ["class", "data-theme", "data-color-mode", "style"], + }); + } + + const media = typeof globalThis.matchMedia === "function" + ? globalThis.matchMedia("(prefers-color-scheme: dark)") + : null; + media?.addEventListener?.("change", fn); + + return () => { + observer?.disconnect(); + media?.removeEventListener?.("change", fn); + }; +} + +/** + * Apply a widget's `theme_vars` trait as inline manywidgets CSS custom + * properties on `el`. + * + * The Python side resolves `theme=` and `style=` to a flat `{ "--mw-*": value }` + * dict. This helper intentionally stays dumb: set each manywidgets-owned var, + * clear vars that disappeared and ignore any non-`--mw-*` key. Vars set here + * cascade to descendants, so a themed layout can theme nested widgets once + * individual widgets opt into this helper. + */ +export function applyThemeVars(el: HTMLElement, model: AnyModel): () => void { + let applied: string[] = []; + ensureShadowCss(el, THEME_DEFAULT_CSS, "manywidgets-theme-defaults"); + el.classList.add("manywidgets-theme"); + if (!hasThemeAncestor(el)) el.classList.add("manywidgets-theme-defaults"); + + const apply = () => { + const vars = readThemeVars(model); + const next = Object.keys(vars).filter((k) => k.startsWith("--mw-")); + for (const key of applied) { + if (!next.includes(key)) el.style.removeProperty(key); + } + for (const key of next) { + el.style.setProperty(key, String(vars[key])); + } + applied = next; + applyColorMode(); + }; + + const applyColorMode = () => { + const mode = colorModeFromThemeVars(readThemeVars(model)) ?? detectHostColorMode(el); + if (mode) { + el.dataset.mwColorMode = mode; + } else { + delete el.dataset.mwColorMode; + } + }; + + apply(); + const offTheme = onChange(model, "theme_vars", apply); + const offHost = observeHostColorMode(el, applyColorMode); + return () => { + offTheme(); + offHost(); + }; +} + +// Shadow-DOM-safe CSS injection /** * Inject a `