--dual-* variables). iris-core will adopt this dual-output model additively under the iris namespace — no separate dual namespace ships. See research/README.md.
Single SCSS source compiles to both shadow-DOM web components and light-DOM SUIT CSS classes.
Three-layer tokens (reference → semantic → component). All page chrome uses --dual-* variables.
Click any node to highlight downstream delivery. SCSS source → build tools → compiled CSS / web components → consumer page.
Single SCSS source compiles two outputs via $namespace: .Dual-Button (light DOM CSS classes)
and .Button (shadow-scoped web components). Tokens flow reference → semantic → component through both paths identically.
| Layer | Example | Role |
|---|---|---|
| Reference | $dual-teal-500, $dual-navy-900 | Raw palette primitives (SCSS only, never emitted) |
| Semantic | --dual-action-fill-1, --dual-base-1 | Meaning-based tokens, emitted as CSS custom properties |
| Component | --dual-button-fill, --dual-card-border | Per-component tokens defaulting from semantic layer |
Tokens compile from SCSS $primitives → semantic SCSS map → emitted CSS custom properties. Component vars default from semantic and can be overridden per-instance.
Both paths use the same token contract. CSS var overrides work identically on both.
A single SCSS source, two outputs.
The 84 variations are 2 families × 16 style-roles × up to 3 weights, reachable
via the composable utility axes (iris-font-* · iris-text-* ·
iris-weight-*) generated from the same type maps — ~21 classes composing to ≥84
combinations (intro roman-only, topline bold-only → 84 not 96).
Each sample composes three utility classes (family + role + weight). Switch the theme in the toolbar — the type re-colors via the semantic --dual-text-* tokens while metrics stay constant.
| Override method | Scope | Shadow DOM | Light DOM |
|---|---|---|---|
CSS variable on :root | Global | ✓ | ✓ |
| CSS variable on element | Instance | ✓ | ✓ |
SCSS $variable (build-time) | Global | ✓ | ✓ |
.dual-theme-dark class | Global | ✓ | ✓ |
/* Override any component via CSS vars — works on BOTH paths */
dual-button, .Dual-Button { --dual-button-fill: hotpink; }
/* Or override at the semantic layer (affects all components) */
:root { --dual-action-fill-1: #6b2fb3; }
Both paths are equivalent. The dual architecture ensures a single override surface works for both consumption models.
| Feature | Dual | iris | iX |
|---|---|---|---|
| CSS-only usage (no JS) | [x] | [ ] | [ ] |
| Per-file imports | [x] dist/components/*.css | [ ] monolithic | [x] theme separate |
| Component token overrides | [x] color-only tier, 14 comps | [ ] 1 var | [x] 25+ vars |
| Naming convention | [x] SUIT CSS | [ ] generic shadow | [ ] generic shadow |
| Utility classes | [x] composable type + u-* | [x] 84 typo utils | [ ] none |
| CSS Grid system | [x] .Grid-cell | [ ] none | [ ] none |
| Tree-shaking (CSS) | [x] config-driven | [ ] bundled | [ ] bundled |
| Framework wrapper needed | [ ] no | [x] Stencil | [x] Stencil |
Landed in the POC and compiled into the granular dist/css/*.css layers and the dist/preset/full.css barrel: a parameterized composite typography mixin, content-measure + fluid size scales with a dual-space() multiplier, and attribute-scoped theme modes.
type($family,$group,$size,$weight) + base element stylesblockquote()Base element styles (h1–h6, p, blockquote) map onto type() in the base layer (opt-in). The mixin validates its axes with @error.
clamp(), and dual-space()clamp() — resize the windowdual-space(3) = calc(var(--dual-spacing) × 3)[data-dual-theme] on a subtreeThe theme() mixin now emits both the root .dual-theme-* class and a [data-dual-theme] attribute, so a subtree switches mode independently of the page.
iris keeps its iris-ui-theme-* class names; the attribute form is the portable, nestable pattern the POC demonstrates.
This overview is the hub. Each area below is its own interactive demo, all rendering against the same built dist/preset/full.css:
| Demo | Shows |
|---|---|
| Output Architecture | dual architecture + config-gated pipeline stages (iris-core build + consumer presets) |
| Token Architecture | the reference → semantic → component token pipeline |
| SCSS Structure | global + component file structure, variable groups, functions, mixins |
| SUIT CSS & Schemas | SUIT class naming + the three machine-readable naming schemas |
| Layout & Base | base + utilities + grid + 10 primitives, and how they stack & combine |
| Consumer Theming | live semantic-vs-component variable override |
| Benchmarks & Comparison | standardized package benchmarks + adoption impact vs iris & iX |