--- title: RFC — Eidos structural systems (space · density · scale) type: rfc audience: human + agent status: implemented — the space builder (`buildSpaceScale`/`applySpacing`) landed, and the `applyTheme(seed)` capstone composes it (status corrected 2026-07-07, theming audit C) source: migrated from src/uix/eidos/STRUCTURE_ENGINE_RFC.md (2026-07-02, docs-book F7.4) --- # RFC — Eidos structural systems (space · density · scale) > Sibling of [`rfc-color-engine.md`](./rfc-color-engine.md), > [`rfc-typography.md`](./rfc-typography.md), [`rfc-depth.md`](./rfc-depth.md) and > [`rfc-shape.md`](./rfc-shape.md). Takes the **structural** systems to > reference-grade. Unlike the **expressive** channels (the book's 8), the > structural is **state-only** — the stage, not the happening. So the novelty > here is **not eventful**: it is **rhythm**, **fluidity** and **axis > composition**, under the open cage. ## 0. Thesis > **Space is not a lookup table of arbitrary pixels; it is a _rhythm_ — derived > from a base unit, _fluid_ (it breathes with the viewport) and _composed_ with > density and zoom from a minimal seed.** Everybody ships a **flat** space scale (`4 · 8 · 12 · 16 · 24…`), **arbitrary**, **static** and detached from typography. Eidos already has the other two structural axes —**density** (compactness) and **scaling** (zoom)— above the average; what's missing is for **space itself** to be rhythm: modular, fluid and with a runtime builder, as typography already did. ## 1. The survey — how the references do it and where they stop | Framework | Space | Limit | |---|---|---| | **Tailwind** | fixed scale (`0.25rem` × N) | flat, arbitrary, **static** | | **Material** | `8dp` grid | multiples of 8, static, no fluidity | | **Radix / Chakra / Mantine** | space tokens | flat static scale; density (if any) = global preset | | **Bootstrap / Ant / Carbon / Fluent** | spacer scale | same — flat + static | | **Utopia.fyi** | fluid space (technique) | an **external calculator**, not a token system integrated with density + zoom | **Common limit**: space is a **flat px scale**, **static** (doesn't breathe with the viewport), **arbitrary** (derives from nothing), and **disconnected** from density / zoom as a system. Utopia proved fluid space but as a spreadsheet, not as a token engine. ## 2. Where Eidos stands today (strong on 2 of 3 axes) - **Density** — 3 levels (`compact · comfortable · spacious`) × **2 axes** (`spaceScale` + `controlScale`). Tightens layout without touching text legibility. ✓ (above average) - **Scaling** — global zoom `90–110` that scales the px **including typography** (Radix parity), composing with density. ✓ - **Layout** — containers + padding + breakpoints + aspect-ratios. ✓ - **Composition** — `--space-{key}` is emitted as `calc(value · var(--density-space-scale) · var(--scaling))`: density × zoom already compose. ✓ - **BUT space ITSELF** (`STATIC_SPACE`) is **flat, arbitrary** px (base 4, hand-placed half-steps), **static** (doesn't breathe) and **builder-less** — unlike type, which has `buildTypeScale` (modular + fluid) + `applyTypeScale` (runtime). It is the **lagging axis**. ## 3. The novel model — space as rhythm 1. **Modular** — every step = base unit × N (a coherent ladder), not loose px. 2. **Fluid** — `clamp()`: space **breathes with the viewport** (like fluid type — almost no framework does it for space). Reuses the type scale's `fluidClamp`. 3. **Three orthogonal axes** — **rhythm** (the scale) × **density** (compactness) × **scaling** (zoom), composed multiplicatively. One minimal seed governs them. 4. **Runtime builder** — `buildSpaceScale(seed)` (pure) + `applySpacing(seed)` (DOM), sibling of `applyColorScheme` / `applyTypeScale` / `applyDepth` / `applyShape`. Completes the quintet. ## 3.bis Structural = state-only (no two moments) Unlike motion / depth / shape, space **does not "happen"**: it is the stage, not the happening. The **two-moments** model (state vs event) belongs to the **expressive** channels. Forcing an "eventful space" would be a costume — the doctrinally honest position is that the novelty here is **rhythm + fluidity + axis composition**, not eventfulness. (Same rigor: don't invent a moment that doesn't exist.) ## 4. Doctrine — _strong default, open cage_ | Piece | Strong default | Open door | |---|---|---| | **space scale** | authored `STATIC_SPACE` (stable, curated) | `buildSpaceScale` / `applySpacing` = **modular + fluid opt-in** alternative (same stance as `applyTypeScale` over the authored scale) | | **density** | 3 levels × 2 axes | config-driven + runtime (`[data-density]`) | | **scaling** | `90–110`, universal factors | runtime (`[data-scaling]`); composes with density | | **composition** | `calc(value · density · scaling)` | the raw `--space-*` primitives always reachable; the builder **preserves** the composition | | **whole system** | canonical theme | runtime `applySpacing(seed)` | ## 5. Token contract ``` --space-{key} value · var(--density-space-scale) · var(--scaling) (existing scale — kept) ``` The builder **rewrites the `value`** (managed block) with a modular/fluid one, **preserving** the `calc(… · density · scaling)` so density and zoom keep composing. Zero renames → zero breakage. ## 6. Phases 1. **Space builder** — `buildSpaceScale(seed)` (pure: base unit × ladder, fluid via `fluidClamp`) + `ActiveEidos.applySpacing` / `clearSpacing` (managed block that preserves `· density · scaling`) + export + test. Opt-in; `STATIC_SPACE` untouched. 2. **Showcase + docs** — `/temas/estructura` (density × scaling × fluid space, live) + theming reference §structure + this RFC. 3. ⏸️ (future) **`applyTheme(seed)`** — one seed composing type + space (shared rhythm). ## 7. Composition with the existing - **`fluidClamp`** (from the type scale) → fluid space (not reinvented). - **`calc(value · density · scaling)`** → preserved (density + zoom keep composing). - **`buildTypeScale`** → the exact pattern `buildSpaceScale` mirrors (seed → fluid ladder). - **Box/Flex/Grid/Stack/Container** → consume `--space-*`; untouched. ## 8. Doctrine (parallel to color / typography / depth / shape) - **Authored scale = stable canon**; the builder = **opt-in** mathematical alternative (same as typography). The theme retunes, the builder recomposes. - **Density and scaling = axes orthogonal** to rhythm; the three compose. - **Open cage**: raw `--space-*` always one step away. ## 9. Out of scope - **Rigid baseline grid** (pixel-perfect vertical rhythm): modular + fluid rhythm gives cadence without imposing a rigid grid that fights real content. - **Reinventing layout**: `Box · Flex · Grid · Stack · Container · AutoGrid` already cover composition; here we elevate **space**, not the layout primitives.