Tokens
One variable is the whole identity
Colors are OKLCH with fixed lightness and chroma shared across every jixoai site; only --brand-hue varies. On this site it runs free — seeded from the time of day and one full day = one full 360° turn (4 minutes per degree). Use the palette popover in the header (or the slider below) to take manual control.
hue runtime
The runtime seeds --brand-hue from the time of day (one full day = one full 360° turn) and the hue always equals the wall-clock position (4min/deg). The slider writes manually — pausing the cycle; the play/pause toggle resumes from wherever the hue is. Every swatch and the CSS law below bind to the LIVE hue.
--primary (current theme)
header brand eyebrow
:root {
--brand-hue: 0; /* runs free: 24h wall-clock, 4min/deg */
--primary: oklch(0.6489 0.237 var(--brand-hue));
--ring: var(--primary);
--chart-1: var(--primary);
}
.dark {
/* perceptual compensation: the hue drifts -4° toward dark */
--primary: oklch(0.7044 0.1872 calc(var(--brand-hue) - 4));
}<script lang="ts">
import { currentHue, playing, setHueManually, toggleHuePlay } from '$lib/hue-runtime.svelte';
</script>
<!-- one variable is the whole identity: the slider writes (auto-pauses),
the toggle resumes toward the wall-clock hue (2s cubic-out) -->
let hue = $state(0);
let isPlaying = $state(true);
currentHue.subscribe((v) => (hue = v));
playing.subscribe((v) => (isPlaying = v));
<label for="hue-slider">--brand-hue</label>
<input
id="hue-slider"
type="range" min="0" max="359" step="1"
value={Math.round(hue)}
oninput={(e) => setHueManually(e.currentTarget.valueAsNumber)}
/>
<button type="button" onclick={toggleHuePlay}>
{isPlaying ? '❚❚ pause' : '▶ play'}
</button>Design Scale
The density kernel
One ruler, five densities (2xs: the opt-in pro-tool rung). Every dimension is an equation from --jx-unit (4px) and --jx-text-base (13px) — no hand-picked values. Components consume the inherited --jx-* tokens; [data-density] scopes switch all values simultaneously. Context injection (Kotlin Compose-inspired): providers set the scope, every child inherits.
Five densities, live
The same component at every density — text, spacing, hit targets, and media all scale from the ruler. No per-size branches in component CSS.
The five-row table
All dimensions computed at the 16px root, columns in ladder order 2xs / xs / sm / default / lg. These are the RESOLVED values the kernel gate asserts in real Chromium. Two honest footnotes at 2xs: its hit is the ONE scoped floor (6U = 24px, the WCAG 2.5.8 AA minimum, inside [data-density='2xs'] only), and its secondary text degenerates to the primary size (the 0.625rem floor binds).
| Token | Default | Source |
|---|---|---|
| --jx-text | 10 / 11 / 12 / 13 / 15px | density |
| --jx-line | 14 / 16 / 18 / 20 / 24px | density |
| --jx-gap | 8 / 8 / 8 / 12 / 16px | density |
| --jx-stack | 4 / 4 / 4 / 8 / 8px | density |
| --jx-inset | 8 / 8 / 8 / 12 / 16px | density |
| --jx-row-min | 24 / 28 / 32 / 40 / 48px | density |
| --jx-hit | 24 / 28 / 32 / 40 / 48px | density |
| --jx-icon | 14 / 16 / 18 / 20 / 24px | density |
| --jx-image | 28 / 32 / 36 / 40 / 48px | density |
| --jx-text-secondary | 10 / 10 / 11 / 12 / 14px | density |
| --jx-unit | 0.25rem (4px) | structural |
| --jx-text-base | 0.8125rem (13px) | structural |
Component supplement tokens
Components ADD tokens the global set doesn't cover — toggle geometry, slider rails, textarea heights. These are owned by their component and documented on each component's page.
| Token | Default | Source |
|---|---|---|
| --jx-toggle-track | var(--jx-line) | component |
| --jx-toggle-width | calc(var(--jx-toggle-track) * 2) | component |
| --jx-toggle-knob | calc(var(--jx-toggle-track) - var(--jx-unit)) | component |
| --jx-toggle-knob-border | 1px | component |
| --jx-toggle-knob-border-color | var(--primary) | component |
| --jx-slider-track | max(var(--jx-unit), calc(var(--jx-line) / 2)) | component |
| --jx-textarea-min | max(var(--jx-hit), calc(var(--jx-line) * 3 + ...)) | component |
| --jx-color-lane | max(var(--jx-hit), calc(var(--jx-icon) + ...)) | component |
Usage
<!-- Scope switch: one attribute, every child inherits -->
<div data-density="sm">
<MyComponent /> <!-- resolves to sm values -->
</div>
<!-- Svelte context: the provider pattern -->
<ItemGroup density="sm">
<Item><!-- inherits sm from the group --></Item>
</ItemGroup>
<!-- Component supplement: override what the global doesn't cover -->
<style>
.my-widget {
min-height: var(--jx-hit);
padding: var(--jx-stack) var(--jx-inset);
font-size: var(--jx-text);
}
</style>Palette
The full sheet, current theme
Values are literal from the registry token sheet (light / dark where they differ). Switch the site theme (header toggle or palette popover) to compare the other mode — no dual panels here.
Neutrals (achromatic by law)
- --background
- oklch(1 0 0) / oklch(0 0 0)
- --foreground
- oklch(0 0 0) / oklch(1 0 0)
- --card
- oklch(1 0 0) / oklch(0.3211 0 0)
- --muted
- oklch(0.9551 0 0) / oklch(0.2178 0 0)
- --muted-foreground
- oklch(0.3211 0 0) / oklch(0.8452 0 0)
- --border
- oklch(0 0 0) / oklch(1 0 0)
- --destructive
- oklch(0 0 0) / oklch(1 0 0)
Brand & functional (fixed hues)
- --primary
- oklch(0.6489 0.237 var(--brand-hue))
- --primary-foreground
- oklch(0 0 0) / oklch(0 0 0)
- --primary-text
- oklch(0.55 0.12 var(--brand-hue)) / var(--primary)
- --secondary
- oklch(0.968 0.211 109.7692) / oklch(0.9691 0.2005 109.6228)
- --secondary-foreground
- oklch(0 0 0)
- --accent
- oklch(0.5635 0.2408 260.8178) / oklch(0.6755 0.1765 252.2592)
- --accent-foreground
- oklch(1 0 0) / oklch(0 0 0)
Terminal surfaces (always dark)
- --terminal
- oklch(0.2 0 0)
- --terminal-foreground
- oklch(1 0 0)
- --terminal-hover
- mix(fg 14% → terminal)
- --terminal-muted
- mix(fg 8% → terminal)
Charts
- --chart-1
- var(--primary)
- --chart-2
- var(--secondary)
- --chart-3
- var(--accent)
- --chart-4
- oklch(0.7323 0.2492 142.4953)
- --chart-5
- oklch(0.5931 0.2726 328.3634)
Semantics
Rules that look negotiable but are not
Neutrals stay pure achromatic (no warm/cool grays), shadows stay hard (zero blur, tiny soft layer only at md+), radius stays 0 except the bevel upgrade and small status pills, and the terminal bar is dark in BOTH themes — it reads as a CRT bezel, not a themed surface.
Hard offset shadows
The shadow IS the affordance. Dark mode inverts the shadow color — including the small tiers — or press buttons lose their lift on the pure-black canvas.
Radius law
--radius is 0px; where CSS supports it, corner-shape: bevel upgrades it to 8px. rounded-full is reserved exclusively for small status dots and pills.
Glass material
The glass effect: translucent surface + real backdrop blur (14px, saturation 1.35),
painted by the shared glass law sheet off the data-jx-effect="blur" stamp
and tuned through --jx-glass-* vars. Drawn with an outline instead of a
border so the box line never shifts layout. The mobile ToC rail is made of this.
(forced-colors: this demo page is exempt from the consumer Canvas map by declaration.)
Beyond sRGB on purpose
Several chroma values intentionally exceed the sRGB gamut (secondary renders as pure #ffff00 after clipping). The neon clip IS the brutalist look. An HSL formulation was tried and rejected: sRGB HSL lightness is hue-dependent and distorts perceived weight; OKLCH keeps it perceptual.