Build your palette with the Palette Generator. The web tool produces every USS file described on this page — base color vars, utility classes, and component templates — in a single round-trip you drop into your project's
Assets/UI/Theme/.Already have a palette and just want to override individual values? See Theme Stack — where to put your overrides so package updates don't overwrite them.
Luna's default palette — what the Essentials sample defines in Theme/Colors/color-variables.uss, and what the Palette Generator's LunaUI preset reproduces — is 32 chromatic ramps plus 3 neutral ramps (slate, neutral, stone), 11 tones each (50 → 950). Browse them below; click a swatch to copy its var(--color-{name}-{tone}) reference or hex value.
The Palette Generator is a web tool that:
50 → 100 → … → 900 → 950) for as many hue palettes as you want — same scale as Tailwind.Open the tool, pick a preset (LunaUI / Tailwind / Material / Midnight / Pastel) or start from scratch, adjust per-ramp, then click Export.
The Export modal has three tabs. You can download some or all.
color-variables.uss)The raw :root { --color-{name}-{tone}: #...; } declarations — one block per hue palette, plus neutrals. Every other USS layer references these via var(--color-...).
Example fragment from an export:
:root {
--color-red-50: #fcf8f8;
--color-red-100: #fae5e5;
/* … 200–800 … */
--color-red-900: #420d0d;
--color-red-950: #150505;
--color-blue-50: #f7f9fc;
/* … */
--color-neutral-50: #fafafa;
/* … */
}This is the foundation layer — every other export depends on these tokens existing. Always include this in your bundle.
utility-colors.uss)Tailwind-style one-property USS classes that route each token to a single CSS property:
.bg-red-500 { background-color: var(--color-red-500); }
.bg-blue-700 { background-color: var(--color-blue-700); }
.text-amber-300 { color: var(--color-amber-300); }
.border-lime-500 { border-color: var(--color-lime-500); }Use these for ad-hoc styling — backgrounds on panels, accent colors on labels — without writing custom selectors.
Two export options on this tab:
.uss — single combined file (typical choice)..uss — separate file per CSS property (bg-colors.uss, text-colors.uss, border-colors.uss, …) for tree-shaking large palettes.-half suffixElsewhere in these docs and in a few sample files you'll meet a -half variant — --color-scarlet-500-half, class="text-red-500-half". It means the same tone at 50% opacity. It's a convention carried over from earlier Luna palettes: the current Palette Generator exports and the shipped Essentials theme do not define -half tokens or classes, so where you want one, define the alias yourself (in a USS file imported after your base colors):
:root {
/* scarlet-500 (#ed583b) at 50% opacity */
--color-scarlet-500-half: rgba(237, 88, 59, 0.5);
}
.text-scarlet-500-half { color: var(--color-scarlet-500-half); }The thing that makes Luna's components recolor with one class. Each Luna control has an internal set of CSS variables (--btn-bg, --btn-bg-hover, --color-slider-fill, …). The component templates route palette tokens onto those internal variables, per color class:
.btn.red {
--btn-bg: var(--color-red-400);
--btn-bg-hover: var(--color-red-300);
--btn-bg-disabled: var(--color-red-200);
--btn-border-disabled: var(--color-red-200);
/* … ghost / outline / soft / link / masked variants … */
}
.btn.blue { --btn-bg: var(--color-blue-400); … }
.btn.coral { --btn-bg: var(--color-coral-400); … }That's why <engine:Button class="btn red"/> works — btn defines the structure (padding, border-radius, layout); red routes the red palette into the button. Change one class to recolor.
The Components tab ships templates for 13 controls, each enableable independently:
| File | Routes onto |
|---|---|
UButton_Colors.uss | .btn.{color} |
UToggle_Colors.uss | .unity-toggle.{color} |
URadio_Colors.uss | .unity-radio-button-group.{color} |
UTabView_Colors.uss | .unity-tab-view.{color} / .TabView.{color} (plus tabs-, checked-, inactive- prefixed variants) |
USlider_Colors.uss | Slider.fill-{color}, Slider.dragger-{color}, Slider.focus-{color} (and the SliderInt equivalents) |
UListView_Colors.uss | .unity-collection-view.{color}, .unity-scroll-view.{color} |
UDropdown_Colors.uss | .unity-base-popup-field.{color} |
UTextField_Colors.uss | .unity-base-text-field.{color} |
ComponentProgressBar_Colors.uss | .ProgressBar.{color} |
ComponentRadialProgressBar_Colors.uss | .radial-progress.{color} |
UInputPrompt_Colors.uss | .InputPrompt.hold-{color} |
ComponentRadialLoading_Colors.uss | .radial-loading.{color} |
UIEffect_Colors.uss | .luna-fx.{color} — routes the --luna-fx-* variables (gradient tones + hover/active steps, inner/shine/flash colors) |
Plus a Custom template option — write your own component-internal-variable mapping using the same {color} placeholder. Useful for routing palette tokens onto your project's own components.
Note the UI Effects row: the color is the same plain color word as everywhere else, scoped by the compound selector .luna-fx.{color} so it only activates on elements that carry the luna-fx marker class. So <Button class="luna-fx luna-fx-btn luna-fx-clay yellow"/> shares its yellow with class="btn yellow" — one palette word drives buttons and effects alike. See UI Effects for the effect classes themselves.
You already have all of this if you imported Essentials. The sample theme ships the same routing pre-baked:
Theme/Colors/component-colors.ussholds the.{component}.{color}blocks for all 32 chromatic ramps across every control above, andTheme/Colors/component-colors-neutral.ussholds the slate / neutral / stone versions. The generator's component templates exist so you can re-export that routing for your own palette — the export replaces those two files' role in your TSS.
Each component template has two modes in the editor:
--btn-bg: {color}-400; --btn-bg-hover: {color}-300).100/200 instead of 400).The generator emits a {name}.uss for chromatics and a {name}_Neutral.uss for neutrals — both reference the same base tokens but with different {color}-{tone} routing.
Open the Components tab to see the per-line tone editor:
var(--color-{color}-{tone}) reference is parseable. Click the tone (e.g. 400) to swap it to a different tone, or use ± buttons to bump by ±1.{color} itself shift the palette family by an offset (e.g. {color+1}-50 becomes {color-2}-50) — useful for "the focus border picks the next palette" patterns.{color}. Click the pushpin to switch to a colour picker — handy for "always use the neutral-50 for text" routes that shouldn't shift per color class.Or edit the template raw if you prefer — both views stay in sync.
Place the files under Assets/UI/Theme/Colors/ (or wherever your project's theme lives):
Assets/UI/Theme/Colors/
├── color-variables.uss
├── utility-colors.uss
├── UButton_Colors.uss
├── USlider_Colors.uss
└── … (the component templates you enabled)@import them in your TSS — color-variables.uss first, then utilities, then component templates:
/* MyProjectTheme.tss */
@import url("/Packages/com.cupkekgames.luna/Runtime/Setup/CupkekGamesMainTheme.tss");
@import url("/Assets/UI/Theme/Colors/color-variables.uss");
@import url("/Assets/UI/Theme/Colors/utility-colors.uss");
@import url("/Assets/UI/Theme/Colors/UButton_Colors.uss");
@import url("/Assets/UI/Theme/Colors/USlider_Colors.uss");
/* … */Order matters: component templates reference variables defined in color-variables.uss, so the base file must import first.
Wire to Panel Settings — point your Panel Settings' Theme StyleSheet at your TSS. See Theme Stack for detail.
Use the color classes in UXML:
<engine:Button class="btn red" text="Buy"/>
<engine:Button class="btn coral" text="Cancel"/>
<engine:Toggle class="unity-toggle violet" label="Notifications"/>
<engine:VisualElement class="bg-neutral-100 text-neutral-900"/>The component class defines structure; the color class routes palette variables into the component's internal vars. Switch a button's color by changing one class — no per-element style overrides.
The tone scale is consistent across all palettes — these conventions are what the default templates encode:
| Tone | Use |
|---|---|
| 50–100 | Lightest tints; backgrounds for soft variants |
| 200–300 | Disabled states, subtle borders |
| 400–500 | Primary fills — buttons, sliders, active accents |
| 600–700 | Hover-pressed fills, semantic text on light backgrounds |
| 800–900 | Dark backgrounds, semantic text on dark backgrounds |
| 950 | Deepest shade; high-contrast outlines, shadows |
The Palette Generator's WCAG-contrast preview bakes this into the UI — you can see legibility per tone pairing as you tune the ramp.
The exported --color-{hue}-{tone} tokens are hue-named. If you'd rather refer to colors by role (--color-primary-500), alias them in your own USS imported after color-variables.uss:
:root {
--color-primary-50: var(--color-blue-50);
--color-primary-500: var(--color-blue-500);
/* … */
--color-secondary-500: var(--color-teal-500);
}Then re-skin the whole project by swapping which raw palette each semantic alias points at — no need to re-export.
color-variables.uss fits into the broader Theme @import chainvar(--…)Settings
Theme
Light
Contrast
Material
Dark
Dim
Material Dark
System
Sidebar(Light & Contrast only)
Font Family
DM Sans
Wix
Inclusive Sans
AR One Sans
Direction