
Xaem Theme Ui
- 12 installs
- 1 repo stars
- Updated August 4, 2026
- cleanexpo/nodejs-starter-v1
Generate high-entropy visual themes then translate them into CSS variables, TypeScript design tokens, Tailwind config, and Framer Motion presets.
About
A two-pass pipeline that generates visual themes (palettes, glow, timing, typography) then translates them into CSS variables, design tokens, Tailwind config, and Framer Motion presets. A developer uses it to create theme variations upstream of design-constraint enforcement.
- Pass 1 generates themes, Pass 2 emits implementable code
- Complements the scientific-luxury structural constraints
Xaem Theme Ui by the numbers
- 12 all-time installs (skills.sh)
- Ranked #1,432 of 1,880 Design & UI/UX skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/cleanexpo/nodejs-starter-v1 --skill xaem-theme-uiAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 12 |
|---|---|
| repo stars | ★ 1 |
| Last updated | August 4, 2026 |
| Repository | cleanexpo/nodejs-starter-v1 ↗ |
What it does
Generate high-entropy visual themes then translate them into CSS variables, TypeScript design tokens, Tailwind config, and Framer Motion presets.
Files
XAEM Theme UI - Theme Generation & Code Translation
Two-pass pipeline for generating high-entropy visual themes and translating them into implementable code. Works upstream of scientific-luxury constraint enforcement.
Description
XAEM Theme UI adds a creative generation layer to the design system. While scientific-luxury enforces structural constraints (OLED black, 0.5px borders, rounded-sm, physics-based easings), it does not generate themes. This skill fills that gap with a two-pass pipeline:
1. Pass 1 (Generate): Create high-entropy visual themes -- spectral colour palettes, glow intensities, animation timing scales, typography weight distributions, opacity hierarchies 2. Pass 2 (Translate): Convert generated themes into implementable code -- CSS variables, TypeScript design tokens, Tailwind config extensions, Framer Motion preset overrides, component style maps
The structural skeleton remains immutable. Only the visual skin is customisable.
When to Apply
Positive Triggers
- Generating new colour palettes or theme variations
- Creating design tokens for a new feature area
- Building theme presets (dark variants, branded themes)
- User mentions: "theme", "palette", "colour scheme", "design tokens", "generate theme"
- Translating a mood board or colour brief into code
- Customising glow intensities, animation timing, or opacity scales
Negative Triggers
- Enforcing existing design constraints (use
scientific-luxuryinstead) - Reviewing component layout compliance (use
scientific-luxuryinstead) - Optimising algorithm performance (use
council-of-logicinstead) - Writing backend logic, API routes, or database schemas
The Two Laws
Law 1: Generate Then Translate
Every theme goes through both passes sequentially. Never ship a palette without its code translation. Never write design token code without a generation rationale.
Law 2: Never Violate Structural Constraints
The following are immutable and cannot be overridden by any theme:
| Constraint | Locked Value | Reason |
|---|---|---|
| Background | #050505 (OLED Black) | Foundation of visual hierarchy |
| Border width | 0.5px | Single-pixel precision |
| Border radius | rounded-sm (2px) | Sharp, professional appearance |
| Animation engine | Framer Motion only | Physics-based motion |
| Easing curves | Physics-based (outExpo, snappy, etc.) | No linear transitions |
| Layout pattern | Timeline / asymmetrical | No symmetrical card grids |
| Status icons | Breathing orbs | No Lucide/FontAwesome for status |
---
Pass 1: Theme Generation
1.1 Colour Palette Generation
Every theme defines exactly six spectral colours mapped to semantic roles:
| Role | Semantic Purpose | Default Hex |
|---|---|---|
| Primary | Active, in-progress, CTA | #00F5FF |
| Success | Completed, approved, positive | #00FF88 |
| Warning | Verification, awaiting, caution | #FFB800 |
| Danger | Error, failed, rejected | #FF4444 |
| Accent | Escalation, human intervention | #FF00FF |
| Neutral | Pending, inactive, disabled | #6B7280 |
Palette Strategies
Analogous -- Colours within 30 degrees on the colour wheel. Produces harmonious, low-contrast themes suited for ambient dashboards.
Example: Primary #00F5FF → Success #00FFC8 → Warning #88FF00Complementary -- Pairs colours from opposite sides of the wheel. High contrast, suited for alert-heavy interfaces.
Example: Primary #00F5FF → Accent #FF0A55Triadic -- Three colours evenly spaced at 120 degrees. Balanced vibrancy for data-rich views.
Example: Primary #00F5FF → Warning #FF8800 → Accent #AA00FFPalette Constraints
- All colours must have sufficient contrast against
#050505(minimum 4.5:1 for text) - No pastel or desaturated colours (saturation must be >= 70%)
- No pure white (
#FFFFFF) as a spectral colour - Each colour must be visually distinct at 50% opacity over OLED black
1.2 Glow Intensity Curves
Glow is the primary visual feedback mechanism. Three intensity tiers:
| Tier | Inner Opacity | Outer Opacity | Spread (px) | Use Case |
|---|---|---|---|---|
| Low | 20% | 10% | 20 | Subtle ambient presence |
| Medium | 40% | 20% | 40 | Default interactive |
| High | 60% | 30% | 60 | Alert, active focus |
Themes may adjust these values within these bounds:
- Inner opacity: 15%--65%
- Outer opacity: 8%--35%
- Spread: 12px--80px
1.3 Animation Timing Scale
Themes define a timing scale with six duration values:
| Token | Default (s) | Range (s) | Purpose |
|---|---|---|---|
fast | 0.2 | 0.15--0.3 | Micro-interactions |
normal | 0.4 | 0.3--0.6 | Standard transitions |
slow | 0.6 | 0.5--0.9 | Deliberate, emphasised |
breathe | 2.0 | 1.5--3.0 | Breathing pulse loops |
pulse | 1.5 | 1.0--2.5 | Glow pulse cycles |
ambient | 3.0 | 2.0--4.0 | Background ambient effects |
All durations must use physics-based easing. Linear timing is banned.
1.4 Typography Weight Distribution
Themes select from the permitted weight range:
| Token | Default | Range | Usage |
|---|---|---|---|
heroWeight | 200 | 100--300 | Hero titles |
titleWeight | 300 | 200--400 | Section headings |
bodyWeight | 400 | 300--500 | Body text |
dataWeight | 500 | 400--600 | Monospace data |
labelWeight | 400 | 300--500 | Uppercase labels |
Font families are locked: JetBrains Mono (data), Inter/SF Pro (editorial).
1.5 Opacity Hierarchy Tuning
Themes define a six-step text opacity scale and a three-step border opacity scale:
Text: primary(0.85-0.95) → secondary(0.65-0.75) → tertiary(0.45-0.55)
→ muted(0.35-0.45) → subtle(0.25-0.35) → ghost(0.15-0.25)
Border: visible(0.08-0.12) → subtle(0.04-0.08) → ghost(0.02-0.04)---
Pass 2: Code Translation
2.1 CSS Variable Output
:root {
/* Spectral Palette */
--spectral-primary: #00F5FF;
--spectral-success: #00FF88;
--spectral-warning: #FFB800;
--spectral-danger: #FF4444;
--spectral-accent: #FF00FF;
--spectral-neutral: #6B7280;
/* Glow Intensities */
--glow-low-inner: 20;
--glow-low-outer: 10;
--glow-med-inner: 40;
--glow-med-outer: 20;
--glow-high-inner: 60;
--glow-high-outer: 30;
/* Animation Timing */
--duration-fast: 0.2s;
--duration-normal: 0.4s;
--duration-slow: 0.6s;
--duration-breathe: 2s;
--duration-pulse: 1.5s;
--duration-ambient: 3s;
/* Text Opacity Hierarchy */
--text-primary: rgba(255, 255, 255, 0.9);
--text-secondary: rgba(255, 255, 255, 0.7);
--text-tertiary: rgba(255, 255, 255, 0.5);
--text-muted: rgba(255, 255, 255, 0.4);
--text-subtle: rgba(255, 255, 255, 0.3);
--text-ghost: rgba(255, 255, 255, 0.2);
/* Border Opacity Hierarchy */
--border-visible: rgba(255, 255, 255, 0.1);
--border-subtle: rgba(255, 255, 255, 0.06);
--border-ghost: rgba(255, 255, 255, 0.03);
}2.2 TypeScript Design Token File
export const THEME = {
spectral: {
primary: '#00F5FF',
success: '#00FF88',
warning: '#FFB800',
danger: '#FF4444',
accent: '#FF00FF',
neutral: '#6B7280',
},
glow: {
low: { inner: '20', outer: '10', spread: 20 },
medium: { inner: '40', outer: '20', spread: 40 },
high: { inner: '60', outer: '30', spread: 60 },
},
durations: {
fast: 0.2,
normal: 0.4,
slow: 0.6,
breathe: 2.0,
pulse: 1.5,
ambient: 3.0,
},
weights: {
hero: 200,
title: 300,
body: 400,
data: 500,
label: 400,
},
} as const;2.3 Tailwind Theme Extension
// tailwind.config.ts (theme.extend block)
{
colors: {
spectral: {
primary: 'var(--spectral-primary)',
success: 'var(--spectral-success)',
warning: 'var(--spectral-warning)',
danger: 'var(--spectral-danger)',
accent: 'var(--spectral-accent)',
neutral: 'var(--spectral-neutral)',
},
},
transitionDuration: {
fast: 'var(--duration-fast)',
normal: 'var(--duration-normal)',
slow: 'var(--duration-slow)',
},
}2.4 Framer Motion Preset Overrides
import { THEME } from './design-tokens';
export const themeMotion = {
fadeInLeft: {
initial: { opacity: 0, x: -20 },
animate: { opacity: 1, x: 0 },
transition: {
duration: THEME.durations.normal,
ease: [0.19, 1, 0.22, 1],
},
},
breathing: {
animate: { opacity: [1, 0.6, 1], scale: [1, 1.05, 1] },
transition: {
duration: THEME.durations.breathe,
repeat: Infinity,
ease: 'easeInOut',
},
},
glowPulse: (colour: string) => ({
animate: {
boxShadow: [
`0 0 0 ${colour}00`,
`0 0 ${THEME.glow.medium.spread}px ${colour}${THEME.glow.medium.inner}`,
`0 0 0 ${colour}00`,
],
},
transition: { duration: THEME.durations.pulse, repeat: Infinity },
}),
};2.5 Status Colour Mapping
import { THEME } from './design-tokens';
export const STATUS_MAP = {
pending: THEME.spectral.neutral,
in_progress: THEME.spectral.primary,
awaiting_verification: THEME.spectral.warning,
verification_in_progress: THEME.spectral.warning,
verification_passed: THEME.spectral.success,
verification_failed: THEME.spectral.danger,
completed: THEME.spectral.success,
failed: THEME.spectral.danger,
blocked: THEME.spectral.warning,
escalated_to_human: THEME.spectral.accent,
} as const;---
Existing Design Tokens Reference
The current baseline lives at apps/web/lib/design-tokens.ts. Key exports:
SPECTRAL-- Six-colour palette (cyan, emerald, amber, red, magenta, grey)BACKGROUNDS-- OLED black foundation with elevation stepsTEXT-- Six-step text opacity hierarchyBORDERS-- Three-step border opacity hierarchyEASINGS-- Four physics-based cubic-bezier curvesDURATIONS-- Six animation duration tokensMOTION_PRESETS-- Framer Motion animation presetsTW-- Tailwind class helper constants
All generated themes must be compatible with this token structure.
---
Theme Presets
Scientific Luxury (Default)
The baseline theme. All values match apps/web/lib/design-tokens.ts.
Primary: #00F5FF (Cyan) Success: #00FF88 (Emerald)
Warning: #FFB800 (Amber) Danger: #FF4444 (Red)
Accent: #FF00FF (Magenta) Neutral: #6B7280 (Grey)
Glow: standard | Timing: standard | Weights: standardMidnight Aurora
Cool-shifted palette with extended glow spread for ambient dashboards.
Primary: #00D4FF (Ice Blue) Success: #00E87A (Mint)
Warning: #FF9F00 (Deep Amber) Danger: #FF3355 (Crimson)
Accent: #CC44FF (Violet) Neutral: #5A6270 (Slate)
Glow: high-spread (50px med) Timing: slower (+20%)
Weights: lighter (hero 100, title 200)Solar Flare
Warm-shifted palette with snappy timing for alert-dense interfaces.
Primary: #FFAA00 (Solar Gold) Success: #44FF66 (Neon Green)
Warning: #FF6600 (Flame) Danger: #FF2222 (Hot Red)
Accent: #FF44AA (Hot Pink) Neutral: #7A7A80 (Warm Grey)
Glow: tight (spread 16px) Timing: faster (-15%)
Weights: heavier (data 600, title 400)Deep Ocean
Desaturated blue-green palette with slow, ambient timing for monitoring views.
Primary: #0099CC (Deep Teal) Success: #00CC99 (Sea Green)
Warning: #CCAA00 (Muted Gold) Danger: #CC3344 (Muted Red)
Accent: #9944CC (Deep Purple) Neutral: #556677 (Ocean Grey)
Glow: diffuse (spread 70px) Timing: slowest (+30%)
Weights: standard---
Anti-Patterns
| Anti-Pattern | Why It Fails | Correct Approach |
|---|---|---|
Overriding #050505 background in theme config | Breaks OLED black foundation | Background is structural, not thematic. Leave it locked. |
Using transition: linear in generated presets | Violates physics-based motion requirement | Use outExpo, snappy, or smooth cubic-bezier curves |
| Generating pastel or low-saturation colours | Insufficient contrast on OLED black | Maintain >= 70% saturation, >= 4.5:1 contrast ratio |
Producing grid-cols-2 or grid-cols-4 layout | Symmetrical grids banned by structural rules | Theme controls colour/timing, not layout. Layout is locked. |
Setting rounded-lg or rounded-xl in tokens | Violates sharp corner constraint | rounded-sm is structural. Themes cannot modify border radius. |
Using CSS @keyframes instead of Framer Motion | Bypasses physics-based animation engine | All motion via Framer Motion presets |
| Generating white text at 100% opacity | Harsh, breaks opacity hierarchy | Maximum text opacity is 0.95; use the six-step scale |
Checklist
Before merging any generated theme:
- [ ] Six spectral colours defined with hex values
- [ ] All colours pass 4.5:1 contrast against
#050505 - [ ] Glow intensities within permitted bounds (inner 15-65%, outer 8-35%)
- [ ] Animation durations within permitted ranges (0.15s--4.0s)
- [ ] Typography weights within permitted ranges (100--600)
- [ ] Text opacity scale has six steps, all within bounds
- [ ] Border opacity scale has three steps, all within bounds
- [ ] CSS variables generated and valid
- [ ] TypeScript design token file compiles without errors
- [ ] Tailwind config extension is syntactically correct
- [ ] Framer Motion presets use physics-based easing only
- [ ] Status colour mapping covers all
AgentStatusvalues - [ ] No structural constraints overridden (background, borders, radius, layout)
- [ ] Australian English used throughout (colour, not color)
Response Format
[AGENT_ACTIVATED]: XAEM Theme UI
[PHASE]: {Generation | Translation | Review}
[PASS]: {1 - Generate | 2 - Translate}
[STATUS]: {in_progress | awaiting_verification | complete}
{theme generation output or code translation}
[NEXT_ACTION]: {what happens next}Integration Points
| System | Relationship |
|---|---|
scientific-luxury | Downstream consumer. XAEM generates, scientific-luxury enforces. |
council-of-logic | Shannon check on token count -- no redundant variables. |
design-tokens.ts | Baseline reference. Generated themes must be structurally compatible. |
genesis-orchestrator | Theme generation may be triggered during SECTION_D (frontend shell). |
Australian Localisation
| Element | Format | Example |
|---|---|---|
| Date | DD/MM/YYYY | 13/02/2026 |
| Time | H:MM am/pm | 2:30 pm |
| Timezone | AEST/AEDT | 2:30 pm AEDT |
| Currency | AUD ($) | $1,234.56 |
| Spelling | Australian English | colour, behaviour |
All generated tokens, comments, and documentation must use Australian English spelling conventions: colour (not color), customise (not customize), optimise (not optimize), analyse (not analyze).
---
XAEM THEME UI - GENERATION PIPELINE ACTIVE
XAEM Theme UI — Before/After Examples
Demonstrates the transformation from default theme values to a custom Scientific Luxury theme preset.
---
Example 1: Default Theme → Midnight Aurora
BEFORE — Default / No Theme System
// Hardcoded colours scattered across components
const ActiveBadge = () => (
<span className="bg-blue-500 text-white rounded-full px-3 py-1">Active</span>
);
const ErrorBadge = () => (
<span className="bg-red-500 text-white rounded-full px-3 py-1">Error</span>
);
// No duration tokens — magic numbers everywhere
<div className="transition-all duration-300 ease-linear hover:bg-gray-100">
Content
</div>Problems: Hardcoded Tailwind colours, no semantic mapping, rounded-full (banned), CSS transitions (banned), ease-linear (banned), bg-gray-100 (banned).
AFTER — Midnight Aurora Theme Applied
// theme-config.ts — Midnight Aurora preset
export const THEME = {
spectral: {
primary: '#00D4FF', // Ice Blue
success: '#00E87A', // Mint
warning: '#FF9F00', // Deep Amber
danger: '#FF3355', // Crimson
accent: '#CC44FF', // Violet
neutral: '#5A6270', // Slate
},
glow: {
low: { inner: '25', outer: '12', spread: 25 },
medium: { inner: '45', outer: '22', spread: 50 },
high: { inner: '65', outer: '32', spread: 70 },
},
durations: {
fast: 0.24,
normal: 0.48,
slow: 0.72,
breathe: 2.4,
pulse: 1.8,
ambient: 3.6,
},
weights: {
hero: 100,
title: 200,
body: 400,
data: 500,
label: 400,
},
} as const;// Components use theme tokens — no hardcoded colours
import { THEME } from './theme-config';
const StatusBadge = ({ status }: { status: keyof typeof STATUS_MAP }) => {
const colour = STATUS_MAP[status];
return (
<motion.span
className="rounded-sm border-[0.5px] px-3 py-1 font-mono text-xs"
style={{
borderColor: `${colour}30`,
color: colour,
backgroundColor: `${colour}08`,
}}
whileHover={{ backgroundColor: `${colour}15` }}
transition={{ duration: THEME.durations.fast, ease: [0.19, 1, 0.22, 1] }}
>
{status.replace('_', ' ')}
</motion.span>
);
};---
Example 2: CSS Variables — Default → Solar Flare
BEFORE — No CSS Variables
/* Colours hardcoded in component styles */
.header { background: #1a1a2e; }
.accent { color: #00bcd4; }
.success { color: #4caf50; }
.error { color: #f44336; }AFTER — Solar Flare Theme via CSS Variables
:root {
/* Solar Flare Spectral Palette */
--spectral-primary: #FFAA00;
--spectral-success: #44FF66;
--spectral-warning: #FF6600;
--spectral-danger: #FF2222;
--spectral-accent: #FF44AA;
--spectral-neutral: #7A7A80;
/* Tight Glow */
--glow-low-spread: 12px;
--glow-med-spread: 16px;
--glow-high-spread: 24px;
/* Faster Timing (-15%) */
--duration-fast: 0.17s;
--duration-normal: 0.34s;
--duration-slow: 0.51s;
--duration-breathe: 1.7s;
--duration-pulse: 1.28s;
--duration-ambient: 2.55s;
/* Heavier Weights */
--weight-hero: 200;
--weight-title: 400;
--weight-data: 600;
/* Text Opacity (standard) */
--text-primary: rgba(255, 255, 255, 0.9);
--text-secondary: rgba(255, 255, 255, 0.7);
--text-tertiary: rgba(255, 255, 255, 0.5);
--text-muted: rgba(255, 255, 255, 0.4);
--text-subtle: rgba(255, 255, 255, 0.3);
--text-ghost: rgba(255, 255, 255, 0.2);
/* Border Opacity (standard) */
--border-visible: rgba(255, 255, 255, 0.1);
--border-subtle: rgba(255, 255, 255, 0.06);
--border-ghost: rgba(255, 255, 255, 0.03);
}---
Key Transformation Principles
| Before | After |
|---|---|
| Hardcoded colours in components | Semantic tokens from theme config |
CSS transition: linear | Framer Motion with physics easing |
rounded-full / rounded-lg | rounded-sm (structural, not themed) |
| No glow/shadow system | Three-tier glow intensity scale |
| Magic number durations | Named duration tokens with bounds |
| Single font weight | Five-level weight distribution |
| Binary text opacity (100% or muted) | Six-step opacity hierarchy |
Generic Theme Config — TypeScript Template
Portable theme configuration for any dark-mode design system. Replace values with your project's tokens.
// theme-config.ts — Generic Dark-Mode Theme
export const THEME = {
/** Semantic colour palette */
colours: {
primary: '#00B4D8', // Active, CTAs
success: '#06D6A0', // Positive states
warning: '#FFD166', // Caution states
danger: '#EF476F', // Error states
accent: '#A855F7', // Special states
neutral: '#6B7280', // Disabled, inactive
},
/** Background tokens */
backgrounds: {
primary: '#0A0A0A',
elevated: 'rgba(255, 255, 255, 0.02)',
hover: 'rgba(255, 255, 255, 0.04)',
},
/** Animation duration scale (seconds) */
durations: {
fast: 0.15,
normal: 0.3,
slow: 0.5,
breathing: 2.0,
ambient: 3.0,
},
/** Typography weight distribution */
weights: {
display: 200,
heading: 300,
body: 400,
emphasis: 500,
label: 400,
},
/** Text opacity hierarchy */
textOpacity: {
primary: 0.9,
secondary: 0.7,
tertiary: 0.5,
muted: 0.35,
},
/** Border tokens */
borders: {
width: '1px',
radius: '2px',
opacity: {
visible: 0.1,
subtle: 0.06,
},
},
} as const;
/** Easing curves */
export const EASINGS = {
smooth: [0.4, 0, 0.2, 1] as const,
spring: [0.68, -0.55, 0.265, 1.55] as const,
outExpo: [0.19, 1, 0.22, 1] as const,
};CSS Variables Output
:root {
/* Colours */
--colour-primary: #00B4D8;
--colour-success: #06D6A0;
--colour-warning: #FFD166;
--colour-danger: #EF476F;
--colour-accent: #A855F7;
--colour-neutral: #6B7280;
/* Backgrounds */
--bg-primary: #0A0A0A;
--bg-elevated: rgba(255, 255, 255, 0.02);
/* Durations */
--duration-fast: 0.15s;
--duration-normal: 0.3s;
--duration-slow: 0.5s;
/* Text Opacity */
--text-primary: rgba(255, 255, 255, 0.9);
--text-secondary: rgba(255, 255, 255, 0.7);
--text-tertiary: rgba(255, 255, 255, 0.5);
--text-muted: rgba(255, 255, 255, 0.35);
/* Borders */
--border-visible: rgba(255, 255, 255, 0.1);
--border-subtle: rgba(255, 255, 255, 0.06);
}Customisation
- Replace colour hex values with your brand palette
- Adjust background primary to your desired dark tone
- Modify duration scale to match your animation preferences
- Extend
coloursobject with additional semantic roles as needed - Add
glowconfiguration if your design system uses glow effects
SL Theme Config — TypeScript Template
Scientific Luxury theme configuration. Copy and modify spectral colours, glow, timing, weights, and opacity values. Structural constraints (background, borders, radius, engine) are locked and not included.
// theme-config.ts — Scientific Luxury Theme
// Structural constraints (bg #050505, border 0.5px, rounded-sm, Framer Motion)
// are enforced by the design system layer and are NOT part of theme config.
export const THEME = {
/** Six spectral colours with semantic roles */
spectral: {
primary: '#00F5FF', // Active, in-progress, CTA
success: '#00FF88', // Completed, approved, positive
warning: '#FFB800', // Verification, awaiting, caution
danger: '#FF4444', // Error, failed, rejected
accent: '#FF00FF', // Escalation, human intervention
neutral: '#6B7280', // Pending, inactive, disabled
},
/** Glow intensity tiers */
glow: {
low: { inner: '20', outer: '10', spread: 20 },
medium: { inner: '40', outer: '20', spread: 40 },
high: { inner: '60', outer: '30', spread: 60 },
},
/** Animation duration scale (seconds) */
durations: {
fast: 0.2, // Micro-interactions
normal: 0.4, // Standard transitions
slow: 0.6, // Deliberate, emphasised
breathe: 2.0, // Breathing pulse loops
pulse: 1.5, // Glow pulse cycles
ambient: 3.0, // Background ambient effects
},
/** Typography weight distribution */
weights: {
hero: 200, // Hero display titles
title: 300, // Section headings
body: 400, // Body text
data: 500, // Monospace data values
label: 400, // Uppercase labels
},
/** Text opacity hierarchy (6 steps) */
textOpacity: {
primary: 0.9,
secondary: 0.7,
tertiary: 0.5,
muted: 0.4,
subtle: 0.3,
ghost: 0.2,
},
/** Border opacity hierarchy (3 steps) */
borderOpacity: {
visible: 0.1,
subtle: 0.06,
ghost: 0.03,
},
} as const;
/** Physics-based easing curves — locked, not themeable */
export const EASINGS = {
outExpo: [0.19, 1, 0.22, 1] as const,
smooth: [0.4, 0, 0.2, 1] as const,
snappy: [0.68, -0.55, 0.265, 1.55] as const,
};
/** Status colour mapping */
export const STATUS_MAP = {
pending: THEME.spectral.neutral,
in_progress: THEME.spectral.primary,
awaiting_verification: THEME.spectral.warning,
verification_in_progress: THEME.spectral.warning,
verification_passed: THEME.spectral.success,
verification_failed: THEME.spectral.danger,
completed: THEME.spectral.success,
failed: THEME.spectral.danger,
blocked: THEME.spectral.warning,
escalated_to_human: THEME.spectral.accent,
} as const;
/** Framer Motion presets using theme values */
export const MOTION_PRESETS = {
fadeInLeft: {
initial: { opacity: 0, x: -20 },
animate: { opacity: 1, x: 0 },
transition: { duration: THEME.durations.normal, ease: EASINGS.outExpo },
},
breathing: {
animate: { opacity: [1, 0.6, 1], scale: [1, 1.05, 1] },
transition: {
duration: THEME.durations.breathe,
repeat: Infinity,
ease: 'easeInOut',
},
},
glowPulse: (colour: string) => ({
animate: {
boxShadow: [
`0 0 0 ${colour}00`,
`0 0 ${THEME.glow.medium.spread}px ${colour}${THEME.glow.medium.inner}`,
`0 0 0 ${colour}00`,
],
},
transition: { duration: THEME.durations.pulse, repeat: Infinity },
}),
};Customisation Guide
1. Change palette: Modify spectral values — ensure >= 70% saturation and 4.5:1 contrast against #050505 2. Adjust glow: Modify glow tiers within bounds (inner 15-65%, outer 8-35%, spread 12-80px) 3. Change timing: Modify durations within bounds (see SKILL.md timing ranges) 4. Adjust weights: Modify weights within bounds (hero 100-300, title 200-400, etc.) 5. Tune opacity: Modify textOpacity and borderOpacity within bounds
Do not add background, border-radius, or animation-engine properties — those are structural.
XAEM Theme UI — Anti-Patterns Reference
Extracted from SKILL.md §Anti-Patterns and §The Two Laws. Patterns that violate structural constraints during theme generation.---
Anti-Pattern 1: Overriding OLED Black Background
Why it fails: Background is structural, not thematic. Changing it destroys the visual hierarchy foundation.
// REJECTED — overrides structural constraint
export const THEME = {
background: '#1A1A2E', // NOT ALLOWED
// ...
};
// CORRECT — background is locked, theme controls colours only
export const THEME = {
spectral: {
primary: '#00D4FF',
// ...
},
// Background is NOT part of the theme — it is structural
};---
Anti-Pattern 2: Linear Transitions in Presets
Why it fails: Violates the physics-based motion requirement. Linear motion feels mechanical and lifeless.
// REJECTED
export const themeMotion = {
fadeIn: {
transition: { duration: 0.3, ease: 'linear' }, // BANNED
},
};
// CORRECT
export const themeMotion = {
fadeIn: {
transition: { duration: 0.4, ease: [0.19, 1, 0.22, 1] }, // outExpo
},
};---
Anti-Pattern 3: Pastel or Low-Saturation Colours
Why it fails: Insufficient contrast against OLED black. Colours appear washed out and lack the spectral intensity required.
// REJECTED — saturation below 70%, fails contrast check
export const THEME = {
spectral: {
primary: '#88AACC', // Pastel blue — saturation ~30%
success: '#99CC99', // Pastel green — saturation ~25%
warning: '#CCBB88', // Muted gold — saturation ~35%
},
};
// CORRECT — high saturation, passes 4.5:1 contrast against #050505
export const THEME = {
spectral: {
primary: '#00F5FF', // Cyan — saturation 100%
success: '#00FF88', // Emerald — saturation 100%
warning: '#FFB800', // Amber — saturation 100%
},
};Constraint: All spectral colours must have saturation >= 70% and pass 4.5:1 contrast ratio against #050505.
---
Anti-Pattern 4: Symmetrical Grid Layouts in Themes
Why it fails: Layout is structural, not thematic. Themes control colour, timing, and glow — not layout patterns.
// REJECTED — theme should not define layout
const themeLayout = {
grid: 'grid-cols-2 lg:grid-cols-4 gap-4', // NOT A THEME CONCERN
};
// CORRECT — layout is locked to timeline/asymmetric
// Themes only define: spectral palette, glow, timing, weights, opacity---
Anti-Pattern 5: Non-rounded-sm Border Radius in Tokens
Why it fails: Border radius is structural. Themes cannot modify it.
// REJECTED
export const THEME = {
borderRadius: {
card: 'rounded-lg', // STRUCTURAL — not themeable
button: 'rounded-xl', // STRUCTURAL — not themeable
},
};
// CORRECT — border radius is not part of theme config
// rounded-sm is enforced by the structural layer (scientific-luxury skill)---
Anti-Pattern 6: CSS @keyframes Instead of Framer Motion
Why it fails: Bypasses the physics-based animation engine. CSS keyframes cannot express spring physics.
/* REJECTED */
@keyframes breathe {
0%, 100% { opacity: 1; transform: scale(1); }
50% { opacity: 0.6; transform: scale(1.05); }
}
.breathing { animation: breathe 2s ease-in-out infinite; }
/* CORRECT — use Framer Motion preset */// CORRECT
export const themeMotion = {
breathing: {
animate: { opacity: [1, 0.6, 1], scale: [1, 1.05, 1] },
transition: {
duration: THEME.durations.breathe,
repeat: Infinity,
ease: 'easeInOut',
},
},
};---
Anti-Pattern 7: White Text at 100% Opacity
Why it fails: Harsh against OLED black. Breaks the six-step opacity hierarchy.
// REJECTED
<p className="text-white">Full white text</p>
// CORRECT — use opacity hierarchy
<p className="text-white/90">Primary text</p> {/* --text-primary */}
<p className="text-white/70">Secondary text</p> {/* --text-secondary */}
<p className="text-white/50">Tertiary text</p> {/* --text-tertiary */}Constraint: Maximum text opacity is 0.95. Use the six-step scale: 0.9 → 0.7 → 0.5 → 0.4 → 0.3 → 0.2.
---
Structural vs Thematic Summary
| Property | Structural (Locked) | Thematic (Customisable) |
|---|---|---|
| Background | #050505 | -- |
| Border width | 0.5px | -- |
| Border radius | rounded-sm | -- |
| Animation engine | Framer Motion | -- |
| Layout pattern | Timeline/asymmetric | -- |
| Status icons | Breathing orbs | -- |
| Spectral colours | -- | Six hex values |
| Glow intensity | -- | Inner/outer/spread |
| Animation timing | -- | Duration scale |
| Typography weight | -- | Weight distribution |
| Opacity scale | -- | Text + border steps |
| Easing curves | -- | Preset selection |
Generic Theme Generation Standards
Portable theme generation patterns for any dark-mode design system. No project-specific references.
---
Two-Pass Pipeline
Pass 1: Generate
Define the creative parameters of the theme:
1. Colour palette — 4-6 colours with semantic roles (primary, success, warning, danger, accent, neutral) 2. Glow/shadow intensity — Inner opacity, outer opacity, spread radius per tier (low, medium, high) 3. Animation timing scale — Duration tokens for micro-interactions, transitions, breathing, ambient 4. Typography weight distribution — Weight assignments for hero, title, body, data, label 5. Opacity hierarchy — Text opacity steps and border opacity steps
Pass 2: Translate
Convert generated values into implementable code:
1. CSS custom properties — :root variables 2. TypeScript design token file — Typed const object 3. Framework config extension — Tailwind theme.extend or equivalent 4. Animation presets — Framer Motion / CSS transition presets 5. Status colour mapping — Semantic status → colour lookup
---
Colour Palette Standards
Minimum Requirements
- Define at least 4 semantic roles (primary, success, warning, danger)
- All colours must pass WCAG AA contrast (4.5:1) against the background
- Each colour must be visually distinct from every other at reduced opacity
- No pure white as a theme colour
Generation Strategies
| Strategy | Method | Best For |
|---|---|---|
| Analogous | Colours within 30 degrees on wheel | Calm, harmonious interfaces |
| Complementary | Opposite sides of the wheel | High-contrast, alert-heavy UIs |
| Triadic | Three colours at 120 degree spacing | Balanced, data-rich displays |
| Split-complement | One base + two adjacent complements | Vibrant without harsh contrast |
Contrast Verification
For each colour in palette:
contrast_ratio = relative_luminance(colour) / relative_luminance(background)
ASSERT contrast_ratio >= 4.5---
Glow/Shadow Intensity
Define three tiers of visual emphasis:
| Tier | Use Case | Inner Opacity | Outer Opacity | Spread |
|---|---|---|---|---|
| Low | Ambient presence | 15-25% | 8-12% | 12-24px |
| Medium | Interactive default | 35-45% | 18-25% | 30-50px |
| High | Alert / active | 55-65% | 28-35% | 50-80px |
---
Animation Timing Scale
Define 4-6 duration tokens:
| Token | Purpose | Typical Range |
|---|---|---|
| fast | Micro-interactions | 0.1-0.3s |
| normal | Standard transitions | 0.3-0.6s |
| slow | Emphasised transitions | 0.5-1.0s |
| breathe | Breathing pulse loops | 1.5-3.0s |
| ambient | Background ambient effects | 2.0-5.0s |
All durations must use easing functions. Linear timing should be avoided.
---
Typography Weight Distribution
Map font weights to semantic roles:
| Role | Typical Range | Purpose |
|---|---|---|
| Hero | 100-300 | Large display text |
| Title | 200-400 | Section headings |
| Body | 300-500 | Paragraph text |
| Data | 400-600 | Numeric/code values |
| Label | 300-500 | Form/field labels |
---
Opacity Hierarchy
Text Opacity (6 steps)
primary → 0.85-0.95 (main content)
secondary → 0.65-0.75 (supporting content)
tertiary → 0.45-0.55 (de-emphasised)
muted → 0.35-0.45 (subtle)
subtle → 0.25-0.35 (barely visible)
ghost → 0.15-0.25 (decorative)Border Opacity (3 steps)
visible → 0.08-0.12 (clear separation)
subtle → 0.04-0.08 (soft separation)
ghost → 0.02-0.04 (hint of structure)---
Code Output Format
CSS Variables
:root {
--theme-primary: [hex];
--theme-success: [hex];
--theme-warning: [hex];
--theme-danger: [hex];
--duration-fast: [value]s;
--duration-normal: [value]s;
--text-primary: rgba(255, 255, 255, [opacity]);
--border-visible: rgba(255, 255, 255, [opacity]);
}TypeScript Tokens
export const THEME = {
colours: { primary: '[hex]', success: '[hex]', /* ... */ },
durations: { fast: [number], normal: [number], /* ... */ },
weights: { hero: [number], title: [number], /* ... */ },
} as const;---
Theme Validation Checklist
- [ ] All colours pass contrast check against background
- [ ] Glow intensities within defined bounds
- [ ] Animation durations within defined ranges
- [ ] Typography weights within defined ranges
- [ ] Opacity hierarchy has correct number of steps
- [ ] CSS variables are valid syntax
- [ ] TypeScript tokens compile without errors
- [ ] No structural constraints overridden
XAEM Theme UI — Theme Preset Standards
Extracted from SKILL.md §Theme Presets. The four predefined theme configurations.---
Preset 1: Scientific Luxury (Default)
The baseline theme. All values match apps/web/lib/design-tokens.ts.
| Property | Value |
|---|---|
| Primary | #00F5FF (Cyan) |
| Success | #00FF88 (Emerald) |
| Warning | #FFB800 (Amber) |
| Danger | #FF4444 (Red) |
| Accent | #FF00FF (Magenta) |
| Neutral | #6B7280 (Grey) |
| Glow | Standard |
| Timing | Standard |
| Weights | Standard (hero 200, title 300, body 400, data 500, label 400) |
---
Preset 2: Midnight Aurora
Cool-shifted palette with extended glow spread for ambient dashboards.
| Property | Value |
|---|---|
| Primary | #00D4FF (Ice Blue) |
| Success | #00E87A (Mint) |
| Warning | #FF9F00 (Deep Amber) |
| Danger | #FF3355 (Crimson) |
| Accent | #CC44FF (Violet) |
| Neutral | #5A6270 (Slate) |
| Glow | High-spread (medium spread 50px) |
| Timing | Slower (+20% all durations) |
| Weights | Lighter (hero 100, title 200) |
---
Preset 3: Solar Flare
Warm-shifted palette with snappy timing for alert-dense interfaces.
| Property | Value |
|---|---|
| Primary | #FFAA00 (Solar Gold) |
| Success | #44FF66 (Neon Green) |
| Warning | #FF6600 (Flame) |
| Danger | #FF2222 (Hot Red) |
| Accent | #FF44AA (Hot Pink) |
| Neutral | #7A7A80 (Warm Grey) |
| Glow | Tight (spread 16px) |
| Timing | Faster (-15% all durations) |
| Weights | Heavier (data 600, title 400) |
---
Preset 4: Deep Ocean
Desaturated blue-green palette with slow, ambient timing for monitoring views.
| Property | Value |
|---|---|
| Primary | #0099CC (Deep Teal) |
| Success | #00CC99 (Sea Green) |
| Warning | #CCAA00 (Muted Gold) |
| Danger | #CC3344 (Muted Red) |
| Accent | #9944CC (Deep Purple) |
| Neutral | #556677 (Ocean Grey) |
| Glow | Diffuse (spread 70px) |
| Timing | Slowest (+30% all durations) |
| Weights | Standard |
---
Theme Generation Bounds
Palette Constraints
- All colours must have >= 70% saturation
- All colours must pass 4.5:1 contrast against
#050505 - No pure white (
#FFFFFF) as a spectral colour - Each colour visually distinct at 50% opacity over OLED black
Glow Intensity Bounds
| Tier | Inner Opacity | Outer Opacity | Spread |
|---|---|---|---|
| Low | 15-25% | 8-12% | 12-24px |
| Medium | 35-45% | 18-25% | 30-50px |
| High | 55-65% | 28-35% | 50-80px |
Animation Timing Bounds
| Token | Min | Max | Default |
|---|---|---|---|
| fast | 0.15s | 0.3s | 0.2s |
| normal | 0.3s | 0.6s | 0.4s |
| slow | 0.5s | 0.9s | 0.6s |
| breathe | 1.5s | 3.0s | 2.0s |
| pulse | 1.0s | 2.5s | 1.5s |
| ambient | 2.0s | 4.0s | 3.0s |
Typography Weight Bounds
| Token | Min | Max | Default |
|---|---|---|---|
| heroWeight | 100 | 300 | 200 |
| titleWeight | 200 | 400 | 300 |
| bodyWeight | 300 | 500 | 400 |
| dataWeight | 400 | 600 | 500 |
| labelWeight | 300 | 500 | 400 |
Opacity Hierarchy Bounds
Text: primary(0.85-0.95) → secondary(0.65-0.75) → tertiary(0.45-0.55)
→ muted(0.35-0.45) → subtle(0.25-0.35) → ghost(0.15-0.25)
Border: visible(0.08-0.12) → subtle(0.04-0.08) → ghost(0.02-0.04)---
Palette Generation Strategies
| Strategy | Colour Wheel | Suited For |
|---|---|---|
| Analogous | Within 30 degrees | Ambient dashboards, harmonious feel |
| Complementary | Opposite sides | Alert-heavy interfaces, high contrast |
| Triadic | 120 degree spacing | Data-rich views, balanced vibrancy |