# RFC — Eje `scaling` (zoom global), separado de la densidad > **Estado: ✅ IMPLEMENTADO.** (diseño 2026-06-01 · implementado 2026-06-02) > Surge de P1-2: la tipografía-por-densidad (`content-scale`) estaba mal planteada. > Densidad y zoom son cosas distintas; este RFC introduce el zoom como su propio eje. > > **Código**: `lib/config-types.ts` (`SCALING_KEYS` / `ScalingKey` / `DEFAULT_SCALING`), > `lib/primitives/static.ts` (`STATIC_SCALING`), `lib/render-css.ts` > (`appendScalingDeclarations` / `appendScaledMetricDeclarations` / `renderScalingBlocks`), > `active-eidos.svelte.ts` (`scaling` / `scalingSource` / `getScaling()` / `data-scaling`). > Doc consolidada en THEMING.md §23. `--density-scale` y `--density-content-scale` > fueron eliminados en este sprint. ## 0. Motivación `scaling` en Radix Themes (90/95/100/105/110%) es un **zoom global** que escala espacio, tipografía, alturas y line-box con UN factor — accesibilidad/zoom, no densidad. Eidos tenía un `--density-content-scale` (±4%) muerto que intentaba escalar tipografía bajo el eje de densidad, lo cual **confunde densidad con zoom**: - **Densidad** (`compact` / `comfortable` / `spacious`): aprieta layout (espacio + altura de control), **texto estable** (legibilidad — Material/Carbon). Ya hecho. - **Scaling** (este RFC): zoom — escala las métricas px **incluida la tipografía**. Los dos ejes son **ortogonales** y **componen** (puedes tener `compact` + `110%`). ## 1. Decisiones - **Discreto**, paridad Radix: `90 / 95 / 100 / 105 / 110` (%). Default `100`. Se proyecta como `[data-scaling='90']` (bloques, cacheable) + `--scaling`. - **Escala** (px): `font-size`, `space`, `control-height`, `icon-size`. - **NO escala**: - `line-height` → es **ratio unitless** (1.45…); ya escala vía el font-size escalado. Multiplicarlo lo **duplicaría** (bug). Excluir. - `border-width` (1px nítido), `radius` (independiente — como en Radix), `shadow`, `z-index`, `opacity`, `motion`. Excluir. - **Composición con densidad** (multiplicativa) en las 2 métricas compartidas: `--space-N: calc(base × var(--density-space-scale) × var(--scaling))`, `--control-height-N: calc(base × var(--density-control-scale) × var(--scaling))`. - **Poda** `--density-scale` (maestro) + `--density-content-scale`: eran el intento a-medias de lo que este eje hace bien. Reconcilia §20.1 (densidad = texto estable; scaling = zoom incluye texto). ## 2. Diseño **Primitiva** (`lib/primitives/static.ts`): ```ts export const STATIC_SCALING = { '90': 0.9, '95': 0.95, '100': 1, '105': 1.05, '110': 1.1 } ``` Default activo: `100`. **Tipos** (`config-types.ts`): `SCALING_KEYS = ['90','95','100','105','110']`, `ScalingKey`. La primitiva de densidad pierde `scale` + `contentScale`. **Emisión** (`render-css.ts`): - `:root` declara `--scaling-90: 0.9 … --scaling-110: 1.1` (constantes) y `--scaling: var(--scaling-100)` (activo). - Bloques `[data-scaling='90'] { --scaling: var(--scaling-90); }` … (los ≠100). - `font-size` + `icon-size` pasan de verbatim a `calc(value × var(--scaling))`. - `space` + `control-height` añaden `× var(--scaling)` al `calc` que ya tienen. - `line-height`, `radius`, `border`, `shadow`, etc.: **sin cambios**. **Runtime** (`active-eidos.svelte.ts`): nueva `scalingSource` (get/onChange, espejo de `densitySource`); `apply()` escribe `data-scaling` en el host (junto a `data-mode` / `data-density`); `dispose()` lo limpia. `EIDOS_SCALING_ATTR`. **Contrato** (`contract.ts`): emite `--scaling` + las constantes como knobs. ## 3. Conflictos (resueltos) | Punto | Resolución | |---|---| | Densidad × scaling en space/control-height | Composición multiplicativa en el `calc`. Ortogonales en intención. | | line-height (ratio) | NO escalar — escala vía font-size. | | radius/border/shadow/z/opacity/motion | NO escalar (paridad Radix + corrección). | | `--density-scale` + `content-scale` muertos | Podados — superados por este eje. | | `size` prop | Ortogonal — `size` elige tier, scaling multiplica el valor del tier. Compone. | | Zoom de navegador | Compone multiplicativamente (ambos px). Es app-level, distinto. | | §20.1 (tipografía no escala con densidad) | Sigue cierto — densidad no la escala; **scaling sí**. Dos ejes. | ## 4. Plan de implementación 1. `STATIC_SCALING` + quitar `scale`/`contentScale` de `STATIC_DENSITY`. 2. Tipos (`SCALING_KEYS`/`ScalingKey`; ajustar `DensityPrimitiveSet`). 3. `render-css`: emisión scaling + bloques + `× var(--scaling)` en las 4 familias; podar emisión de density scale/content-scale. 4. `ActiveEidos`: `scalingSource` + `data-scaling` + cleanup. 5. `contract`: tokens scaling; quitar density scale/content-scale. 6. Regenerar `generated/base.css`. 7. Tests: actualizar forma de `--space-4`/`--control-height` (× scaling); test de font-size escalado; bloque `[data-scaling]`; test de `scalingSource`. 8. Verificar (`check` + `vitest src/uix/eidos` + navegador) + doc en THEMING.md.