`, doctrina en
recipe-contract §4) — por cada token público, un valor imposible de
confundir (`1234px`, `rgb(1, 2, 3)`, `0.123`) y algún computed tiene que
seguirlo. Si un token no mueve nada, es un token que miente (fantasma,
nombre equivocado, o una cascada que jamás gana) — o su silencio tiene una
razón MEDIDA escrita en el ledger
(`scripts/theming-sentinel-exceptions.ts`): el guard falla con un muerto
sin adjudicar y avisa de excepciones STALE.
12. **Desde el píxel hacia arriba** en los estados de hover: `elementsFromPoint`
en el centro del control y la pila de ancestros con `backgroundImage` /
`backgroundColor` — el velo cae en el nodo CON forma y en ningún
envoltorio (memoria `measure-the-node-the-user-points-at`). Si hay
animación propia y un sello de sema en el mismo nodo, registro de
`animationstart/end` (no `getAnimations` en un solo instante): UNA
entrada por ocurrencia (memoria motion.md §"when both write `animation`").
13. Captura 2× después, al lado de la de antes. Mirarla.
### 7.5 Guards mecánicos (todos, cada componente)
14. `node --import tsx/esm scripts/theming-census.ts --only {c}` → **100 %** o
excepción escrita. Y el global NO baja.
15. `node --import tsx/esm scripts/component-audit.ts --only {c}` → PASS, sin
R-5 nuevos (en `warn` durante F2, pero se listan y se resuelven).
16. `node --import tsx/esm scripts/eidos-lint.ts {c}` → 0 invalid.
17. `npx vitest run src/uix/eidos` → sin rojos nuevos (comparar **por
fichero de test**, no por cifra: el rojo conocido es `skin-media-player`).
18. `npm run rtl:check` 0 · `npm run docs:check` 0 · `npx prettier --check`
en los ficheros tocados (ojo: `autocrlf=true` hace que prettier se queje
del CRLF del checkout — comprobar el contenido normalizado a LF, no el
fichero; git guarda LF).
19. `npm run check`: atribuir errores **por fichero** (`grep ERROR | grep {c}`),
nunca por cifra global; la rama tiene sesiones concurrentes y el total
se mueve solo. Si el log no llega a `COMPLETED`, es `tmp/lexical/`:
relanzar.
### 7.6 Commit (uno por componente)
20. `git add` con rutas EXPLÍCITAS (sólo lo del componente + `recipes/base.ts`
- `generated/base.css` + su README + este plan §8); `git diff --cached --stat`
y `git show :ruta` para verificar el ÁRBOL INDEXADO, no el de trabajo;
`git status` para ver que no entra nada de otra sesión. Mensaje con
`git commit -F fichero` (backticks en `-m` se ejecutan en bash), en
castellano, con: qué knobs entran, la cifra del censo antes → después,
el diff de computed (vacío), el centinela (n tokens probados), los
guards. **Nunca `--amend`** en la rama compartida.
21. Registro en §8 de este plan (componente · commit · censo antes→después ·
excepciones) y, si el bloque cierra, en `CONTINUE-theming.md`.
### 7.7 Revisión adversarial por bloque
22. Al cerrar un bloque, una pasada escéptica (otra sesión o un pase separado)
que por componente intente REFUTAR con medición propia: «el default es
idéntico» (sonda 7.2 vs 7.4 rehecha, no leída del commit), «cada token
alcanza» (centinela rehecho), «el velo cae donde debe» (píxel arriba),
«no hay doble animación». Hallazgos reales se arreglan en el bloque; los
refutados se anotan. El molde es la revisión del `Sidebar` (21
hallazgos · 17 refutados · 4 reales, `bae03e55c`).
### 7.8 Lo que NO se hace en este eje (y se anota como deuda si aparece)
- Rediseñar un default (radio, color, altura…): deuda firmable, no cambio.
- Tocar sema/morfo salvo un arquetipo en un envoltorio (decisión aparte).
- Cascadear a otro componente «ya que estamos» (memoria `no-cascade-changes`).
- Inventar nombres de token fuera de §1/§6.7, o un hover/estado por componente.
- Editar `generated/base.css` a mano.
- Dar un paso por hecho sin su artefacto.
---
## 8. Registro
- 2026-08-23 — **`checkbox` 59 % → 72 %** (3 claves, 3 literales anotados) **y un
HUÉRFANO cableado**. El 28 % restante es el puente de paleta (8 filas, THM-2).
**`indicator-fg` era un huérfano que el test de huérfanos no puede ver**: la
clave estaba en el contrato, pero la receta pintaba la tinta de la casilla
marcada leyendo `--color-content-on-solid` DIRECTAMENTE, sin nombrarla — y el
test busca el NOMBRE en los ficheros del componente. Cableada al privado de
paleta (computado idéntico), el propio guard lo confirmó marcando su
adjudicación como STALE: ahora mueve. Misma clase que el `--popover-bg` que
vivía de un COMENTARIO, al revés.
Acuñado el estado INVALID: el borde y el doble anillo de foco (hueco +
anillo), que era una sombra con dos colores cableados; la geometría 2px/4px se
queda dentro de la declaración, que es la forma del anillo.
**Dos trampas de ALCANCE del instrumento**, anotadas: el glifo sólo existe
dentro de una casilla MARCADA (medir «el primer indicador del documento» mide
otro nodo) y la etiqueta de grupo lleva su PROPIO `[data-disabled]`, no lo
hereda.
Gates: sonda 0 diffs en 2.688 valores × 7 estados · centinela 22/47 con todo
adjudicado · censo 72 % · audit PASS · suite con el rojo conocido ajeno · rtl 0
· docs 0 · captura de cinco estados.
- 2026-08-23 — **`dropdown-menu` 57 % → 96 %** (9 claves, 18 respaldos muertos
retirados) **y la tipografía del gemelo, RETIRADA**: `context-menu` 90 % →
87 %, a la baja y a propósito. Global 64 %.
Cosidos la tinta del panel y de la fila, su interlínea, el encabezado entero y
el galón del submenú (trazo + caja). **El filo del separador deja de ser un
`1px` suelto** y pasa a `--border-width`. Las dos limpiezas del gemelo se
repiten aquí: `font-family` era respaldo de SÍ MISMO y el peso del encabezado
llevaba un `500` muerto.
**Los 18 respaldos**: cada `var(--dropdown-menu-x, …)` llevaba detrás un valor
que no puede ocurrir —las claves están en el contrato— y sólo servía para
envejecer contra él; dos ya discrepaban en la FUENTE.
**⚠ `content-font-family` no se acuña, y la de `context-menu` se RETIRA.** El
panel lleva `data-depth='overlay'` y el plano gana (quinta prueba de §12.9).
Tenerla acuñada con una adjudicación escrita —como quedó ayer en el gemelo—
era media doctrina: **un público que no alcanza es un token que miente**
(R-5.4). Las dos recetas vuelven a la fuente literal con la razón encima.
`combobox` tiene la misma clave sobre el mismo plano: medido, registrado en
§13, no tocado aquí.
Gates: sonda 0 diffs en 928 valores × 8 estados · centinela 27/28 · censo
96 % · audit PASS · suite con el rojo conocido ajeno · rtl 0 · docs 0 ·
captura del panel.
- 2026-08-23 — **`empty-state` 29 % → 100 %** (20 claves, 6 → 26) **y el
centinela 26/26 sin una sola adjudicación**. Global 64 %.
Su deuda era de una clase: **la escala de talla vivía entera en privados** que
leían el bundle a pelo. Cada paso tiene ya su público (relleno, título, cuerpo
y glifo en `sm`/`md`/`lg`) y los privados los derivan; con eso el resto —peso,
interlínea y tinta del título, interlínea y tinta de la descripción— sale
solo. La caja del glifo se sigue derivando (2×) de su tamaño, ahora público.
**Siete respaldos muertos retirados**, dos de ellos MENTIROSOS: el `, 1.4` de
`--font-line-height-sm` (vale 1.45) y el `, 1.5` de `--font-line-height-md`.
Mismo defecto que `callout` hoy: **un respaldo escrito a mano envejece contra
el token**.
Gates: sonda 0 diffs en 1.056 valores × 7 estados · centinela 26/26 · censo
100 % · audit PASS · suite con el rojo conocido ajeno · rtl 0 · docs 0 ·
captura de las tres tallas.
- 2026-08-23 — **`callout` 27 % → 79 %** (7 claves, un literal anotado). Global
**63 % → 64 %**. El 21 % restante es el PUENTE DE PALETA (THM-2), que no es
deuda.
Cosidos el hueco de fila, la tipografía del cuerpo, la tinta, el tamaño del
icono y el peso del título, todos leyendo el BUNDLE. **La línea base óptica
del icono deja de repetir las métricas del sistema**: la misma derivación,
ahora sobre los tokens del propio callout, así que un tema que agrande la
copia mueve la caja del glifo con ella.
**Cinco respaldos muertos retirados** (`var(--callout-gap, var(--space-3))` y
compañía: las claves están en el contrato) incluido el `, 1.5` de
`--font-line-height-md`, que además mentía — el token existe y vale 1.45.
Los 24 rojos del guard son los TONOS: la supersesión que `button` destapó el
mismo día, adjudicada con el patrón compartido.
Gates: sonda 0 diffs en 896 valores × 7 estados · centinela 10/34 · censo
79 % · audit PASS · suite con el rojo conocido ajeno · rtl 0 · docs 0 ·
captura de cuatro tonos.
- 2026-08-23 — **`button` 55 % → 91 %** (1 clave, 17 declaraciones anotadas) **y
el hallazgo más gordo del eje: la cascada de paleta ANULA los tonos del
componente — 419 claves en el catálogo.** Global 63 %.
Acuñado lo único que faltaba: **el paso `full` de la escala de radio**
(`[data-rounded='full']` leía el primitivo global a pelo). Anotadas 7
identidades (`fit-content` × 2, el `100 %` de `[data-block]`, los cuatro
`1px` de las cajas sr-only) y **10 ausencias**: los `transparent` de `soft`,
`outline`, `ghost` y `plain` — la variante ES la ausencia de cromo, y diez
claves de `transparent` habrían sido el antipatrón que la doctrina avisa.
Para que la ausencia cuente, **el censo aprende la válvula de recipe-contract
§3 un piso más abajo**: un PRIVADO cuyo valor es un literal CON su razón
escrita es una ausencia firmada, no deuda (`derivesFromPublic` la acepta).
Sin eso, cuatro privados marcaban «no deriva» y seis knobs leían
inalcanzables mientras todas las demás ramas del mismo privado leen un
público. El censo global sube 5 knobs por esto, no por retoque de ratio.
**⚠⚠ EL HALLAZGO.** El último bloque del forward, `[data-button][data-color]`,
resuelve `--button-palette-*` desde el `--palette-*` GLOBAL —que
`[data-color='{tono}']` llena desde `--color-{tono}-*`— y **gana a las reglas
por tono por ORDEN**, con la misma especificidad (0,2,0). Medido sobre
`data-color='risk'`: `--button-risk-solid` no mueve nada, ni en `:root` ni en
el nodo; `--palette-solid` y `--color-risk-solid` en el nodo repintan. Las
siete `primary-*` son el RESPALDO de esa regla y sólo actúan SIN
`data-color`. **49 recetas emiten ese mismo forward y el catálogo tiene 419
claves de tono**; medido igual en `badge` y `callout`. → §13, con el arreglo
propuesto (orden de emisión) y su contrapartida (la jaula del color).
El techo restante son dos filas de canal de valor (`--_button-fill-finish`,
el acabado que el generador deriva por instancia; su dial es del sistema).
**Un error de método que casi cuela**: anclé la clave nueva en la primera
línea `'radius-xl'` del fichero y aterrizó en **`meter`**. Lo delató el
navegador (`--button-radius-full` sin definir ⇒ radio 0). Una inserción se
ancla en el BLOQUE del componente, nunca en una línea de clave.
Instrumento: el guard aprende **`sweepAttr`** (barrer una variante mientras
mide) y a estampar **el tono que la clave nombra**; y el fichero de
excepciones gana **patrones** (`SENTINEL_PATTERN_EXCEPTIONS`), para que una
razón arquitectónica se escriba UNA vez y no 56.
Gates: sonda 0 diffs (416 valores; la demo monta UN botón) · equivalencia del
paso `full` comprobada aparte · centinela 34/106 con el resto adjudicado ·
censo 91 % · audit PASS · suite con el rojo conocido ajeno · rtl 0 · docs 0 ·
captura de las seis variantes + píldora + tono `risk`.
- 2026-08-23 — **`onion-menu` 29 % → 84 %** (7 claves + 5 literales anotados), y
**una regla del recipe que el navegador DESCARTA**. Global 63 %.
Acuñados el color del anillo del sector —UNO para los dos estados: el propio
CSS dice que el hover usa «el mismo color que el anillo de selección, más
claro», y lo que los separa es la opacidad que ya tenía token—, la tipografía
de la etiqueta, el radio y la tinta del disparador y las dos piezas del glifo
`+`→`×`. Dos limpiezas de paso: un `var(--style-label-font-family, var(--style-label-font-family))`
—respaldo de sí mismo, el defecto de context-menu— y dos `var(--radius-full, …)`
con respaldo imposible.
**⚠ `.onion-menu-icon :global(svg)` NO EXISTE**: `:global()` es un envoltorio
de Svelte y esto es un CSS plano, así que el selector es inválido y la regla
entera se descarta. Medido: el glifo computa 14px (el tamaño propio del Icon)
y el `70 %` que el fichero cree pintar no pinta. Acuñé `icon-glyph-size`, el
centinela lo delató y lo RETIRÉ: arreglar el selector mueve píxel. Mismo bug
en `timeline.css:331`; `image-picker.css` ya documentaba la trampa. → §13.
**Tres cegueras del instrumento, dos nuevas y genéricas**:
1. **El guard CERRABA la superficie.** Este menú nace ABIERTO y el clic de
«abrir» lo cerraba — 12 de 20 tokens muertos. Ahora, si hay `openMarker` y
ya casa, no se pulsa nada (8 → 14 de golpe).
2. Sus tripas cuelgan de CLASES, no de `data-onion-*`: sonda y guard las miden
con `extraNodes` (37 nodos en reposo contra 5).
3. **Congelar las transiciones no basta cuando el nodo está ANIMADO**:
`rim-glow-opacity` leía 0,482956 —el valor animado— y parecía muerto;
congelando también la animación computa 0,45 y sigue al token.
Los cuatro tokens del rim son del look `luminous`, **que la demo del
componente no renderiza** (prop de Svelte que emite otro marcado, no hay
atributo que forzar): medidos en `/active/docs/agnt`.
Gates: sonda **0 diffs** en 7.328 valores × 8 estados · centinela 14/19 con
las cinco adjudicadas · censo 84 % · audit PASS · suite con el rojo conocido
ajeno · rtl 0 · docs 0 · `check` sin errores propios · capturas.
- 2026-08-23 — **`field` 73 % → 98 %** (8 claves + 8 literales ANOTADOS) **y sus
18 rojos, medidos**. Global **63 %**. El 2 % que falta es el puente de paleta
(THM-2), que no es deuda.
Es el componente más COMPUESTO del sistema: lo que otras fichas llaman
«préstamo con dueño» se cobra aquí, así que su techo pesa más que el de nadie.
Acuñados el **disparador de control** —el icono que abre el calendario, el
reloj o la muestra, y revela la contraseña: `size`, `radius`, `fg` y sus dos
estados—, el indicador `optional` (gemelo del `required`, que ya tenía token)
y el **lateral de la etiqueta flotante**, que es lo que CORTA el borde bajo el
texto. La caja del disparador se mide en `em` a propósito, así que el token
guarda la RAZÓN (`1.75em`), no un píxel por talla.
**Ocho literales pasan a excepción firmada por IDENTIDAD, no por inflar el
ratio**: cuatro `inline-size: 100%`, dos `line-height: 1` de un glifo suelto y
dos `1em` del icono dentro del disparador (el glifo ES el tamaño del texto).
**Los 20 rojos del guard estaban VIVOS**, y tres enseñan algo:
`disabled-opacity` vive en el CONTROL y el guard leía la raíz;
**`control-placeholder-fg` no leía porque el input de la demo NO TIENE
`placeholder`** —sin atributo no hay caja `::placeholder` y
`getComputedStyle(nd, '::placeholder')` devuelve el estilo del ELEMENTO—; y
`segment-height` es un token de FAMILIA que field posee y los pickers
consumen, además de RESUELTO: desde `:root` no se mueve por diseño (medido en
`/time-picker`: desde el host 28px → 1234px, moviendo la coordenada
`--field-control-height-md` 28px → 992px).
**Instrumento**: el disparador de control no lo monta NINGUNA demo de field,
así que el guard mide ahora `field` sobre DOS rutas (`/field` + `/date-picker`).
Gates: sonda **0 diffs** en 2.280 valores × 8 estados · equivalencia del
disparador comprobada aparte · centinela 48/68 con las 20 adjudicadas · censo
98 % · `--names` 0 · audit PASS · rtl 0 · docs 0 · suite eidos con el rojo
conocido ajeno · `check` sin errores propios · capturas de reposo, invalid,
disabled, etiqueta flotante y disparador.
- 2026-08-23 — **`menubar` 15 % → 88 %** (30 claves, 5 → 35). Global **62 % →
63 %**. Las tres filas que quedan fuera NO son deuda de este eje.
Cosidas la barra (superficie, marco, radio desacoplado de la talla, y las
tres escalas `gap`/`padding`/`height`), el disparador (tinta, tipografía,
escala de `font-size` y de `padding-inline`, el par de la entrada ABIERTA y
la tinta deshabilitada) y el Panel `role=dialog` (tinta + escala). Los pasos
leen el BUNDLE (`--size-{k}-control-height` / `--size-{k}-font-size`), no el
primitivo crudo que el CSS venía consumiendo, y el `calc(var(--space-1) * 0.5)`
del paso `sm` pasa a `var(--space-0-5)` (mismo computado).
**El hueco del panel deja de repetir el valor del padding**: las tres reglas
de `--floating-gap` compensaban el sangrado del disparador con una COPIA del
padding de la barra; ahora leen `--menubar-padding-{k}`, su fuente. No pueden
leer el privado: esas superficies viajan por PORTAL, y un privado de la raíz
no cruza esa frontera (la ley de ayer, aplicada al derecho).
**⚠ El plano `overlay` GANA a la receta — cuarta prueba de §12.9, y la
primera con MECANISMO.** Acuñé `panel-font-family` y `panel-line-height`; el
centinela las dio muertas. Medido: `[data-depth='overlay']` declara las dos
con la MISMA especificidad (0,1,0) y más tarde en la cascada, así que gana,
mientras `panel-fg` y `panel-font-size-*` —del mismo bloque— sí alcanzan.
Retiradas del contrato, devueltas a su fuente literal con la razón en el CSS.
**Mientras §12.9 no se firme, un token de tipografía en cualquier superficie
`overlay` miente**, y eso vale para los veinte componentes del empate.
**El hover no se acuña: es del eje navigation-menu.** `background:
var(--color-surface-overlay)` sobre el disparador mata la capa del sistema
—medido: `background-image` computa `none` en hover con `--state-hover`
vivo—, por las dos razones que `navigation-menu.css` ya documenta al haber
retirado esa misma regla: el shorthand resetea `background-image`, y la regla
del arquetipo va en `:where()` (especificidad CERO). Acuñar `hover-trigger-bg`
habría fosilizado la invención. → §13.
**Instrumento**: la barra suelta DOS superficies y el Panel —el que lleva sus
knobs— cuelga de la entrada «Format», no de la primera; sonda (`OPEN_TRIGGER`)
y guard (`openWith`) aprenden a abrir la que toca. Y el guard necesitó
`openMarker`: su comprobación de «ya está abierto» busca `[data-{c}-content]`,
que aquí no existe, así que volvía a pulsar el disparador antes de cada token
y CERRABA el panel.
Gates: sonda **0 diffs** en 1.470 valores × 8 estados · centinela 34/35 (la
deshabilitada adjudicada) · censo 88 % · `--names` 0 · audit PASS · rtl 0 ·
docs 0 · suite eidos con el rojo conocido ajeno · `check` sin errores propios
· capturas de barra, tallas, menú y panel.
- 2026-08-23 — **Los dos rojos que quedaban del bloque viejo, medidos: `metrics`
(18) y `color-picker` (25). Los dos guards en verde; sin cambios de código.**
**`metrics`: los 18 están VIVOS, uno por uno.** Ninguno miente — lo que
faltaba era el escenario: seis piden el paso `xxl` (la demo llega a `xl`),
dos el icono SIN `data-color` (el defecto que sólo pinta cuando no hay
color, y todos los iconos de la demo llevan uno), dos las formas `circle` /
`square` (la demo monta `rounded`), cuatro la fila de acciones (no montada),
uno el gráfico en `end` (la demo los coloca `full`), uno el borde de la
variante `outline`, y **dos el sello de sema durante el hold**
(`data-event-family=signal` + `phase=active`): el destello del valor se mide
estampando el sello a mano, porque cuando el guard lee ya se ha ido.
**`color-picker`: 23 de 25 vivos, y los otros dos son un DEFECTO REAL —
el eje `size` muere en el portal.** `--_color-picker-content-width` se
declara TRES veces y no lo consume NADIE: la anchura del panel la fija
`--_popover-content-width-override` cableada al paso `md`, así que un picker
`sm` y uno `lg` abren el mismo panel de 344 px. Lo mismo con las muestras
dentro del panel (`--_color-picker-swatch-size` clavado a `md`): fuera del
portal los tres pasos alcanzan (20 / 24 / 28 px), dentro sólo el `md`. La
causa es una sola y vale como ley: **el portal es una frontera de cascada —
un privado declarado en la raíz del componente no la cruza.** → §13, porque
arreglarlo mueve píxel en `sm` y `lg`.
Tres cegueras del instrumento, medidas y anotadas: **el guard congela las
transiciones y `transition-duration` / `transition-ease` SON la transición**
(sin congelar: 0.12s → 11.5s) — es genérico, cualquier componente con esos
dos públicos los reportará muertos; **una lectura inmediata de una propiedad
en transición devuelve el valor VIEJO**, que es lo que hacía ilegible el
fondo del cuentagotas; y **la demo pisa el cuentagotas con su propia regla
de ámbito** (`.cp-tools-row` le pone `inline-size:auto` y `background`), así
que sus dos tokens sólo se pueden medir devolviéndole el consumo.
- 2026-08-22 — **`drawer`: los 24 rojos que arrastraba, medidos uno a uno — y
uno era un DEFECTO REAL.** El guard queda en verde; sin cambios de código.
**EL VELO DEL CAJÓN NO PINTA.** Su regla es
`color-mix(in srgb, var(--drawer-overlay-bg) var(--drawer-overlay-opacity), transparent)`
y **soma escribe `--drawer-overlay-opacity: 1` INLINE** —su progreso de
arrastre, un número sin unidad—. `color-mix` exige ahí un PORCENTAJE: con
`1` la función entera es inválida y el fondo cae a `transparent`. Medido
(`rgba(0, 0, 0, 0)` en el velo abierto; con `80%` en el nodo, pinta) y VISTO
en captura: el fondo tras el cajón sale desenfocado pero sin atenuar. Mueve
píxel y toca soma, así que va a §13 con su lección: **un valor que soma
escribe inline y una receta consume tiene que compartir UNIDAD**, o el fallo
es silencioso.
El segundo hallazgo: **las tallas son canal de valor en el eje que manda** —
soma escribe `width`/`height` inline según el lado, así que
`content-width-*` no gana desde `:root` en un cajón izquierda/derecha (el
eje cruzado sí: `height-sm` 260px → 976px). Misma clase que el `item-gap`
de carousel, pero aquí el token sigue siendo la fuente del valor que soma
resuelve: retirar o no es firma.
Los otros 22 son lo esperable y quedan medidos: el asa (no montada, y su
tamaño INTERCAMBIA ejes según el lado), el anillo de arrastre, el padding
`full`, la cabecera y el pie opcionales, la z de la variante inline.
- 2026-08-22 — **REVISIÓN ADVERSARIAL DEL BLOQUE (§7.7): 5 hipótesis, 1
hallazgo real, 4 refutadas.** Bloque de CATORCE componentes; global 56 % →
**62 %**.
**HALLAZGO REAL — la anomalía de `float-panel` tenía causa, y era del guard.**
`resize-grip-fg` movía aislado y leía muerto en una corrida completa. La
causa: **la pasada de HOVER deja el puntero sobre el último nodo que tocó**, y
una regla `:hover` gana a la de reposo con la que comparte nodo (el asa
re-apunta su color al acento). Es decir: **cualquier token de reposo probado
después de un token `hover-*` podía leer muerto** — misma clase que el
envenenamiento por clic-foco que F2-A arregló, una pasada más tarde.
Arreglado aparcando el puntero tras la pasada de hover. El propio guard
delató entonces DOS excepciones STALE —`float-panel.resize-grip-fg` y
`media-player.track`—, retiradas: dos tokens que se daban por muertos están
vivos. Se confirma la regla de F2-A: **un falso negativo siempre tiene causa**;
registrarlo como «sin causa» era el paso previo, no el final.
**REFUTADA «hay tokens huérfanos»**: comprobación ESTRICTA (comentarios
despojados —el hueco que dejó vivo el `popover.bg`— sobre todo el CSS del
árbol) de las **553 claves** de los catorce bloques: ninguna declarada sin que
una regla la lea.
**REFUTADA «el cambio de instrumento rompió algo»**: los **27 componentes con
ledger re-verificados** tras aparcar el puntero — cero regresiones. Los tres
rojos que quedan (`drawer` 24, `metrics` 16, `color-picker` 23) son
ANTERIORES al bloque y están anotados.
**REFUTADA «quedan fantasmas del barrido en lo tocado»**: el barrido pasa de
9 a **8** — el `--color-content-tertiary` de float-panel murió con su costura.
Los ocho restantes son de componentes que este bloque no tocó.
**CONFIRMADO, y ya estaba escrito: hay gates FINOS.** `popover` mide 1 nodo en
reposo (7 en abierto), `drawer` 1, `context-menu` 1 + 14 en abierto,
`color-picker` 5 + 12. Cada veredicto lo dice; el forzado a mano de sus
estados es lo que sostiene esas cifras, no la sonda.
- 2026-08-22 — **`password-field` 41 % → 62 %** (7 claves) **y el guard en
VERDE**: sus siete silencios quedan medidos, incluidos los tres que arrastraba
de antes.
Los cuatro peldaños del medidor de fuerza son una ESCALA DE INTENCIÓN —cada
uno lee su rol: pérdida, riesgo, cumplimiento, afirmación—, así que un tema
puede recorrerla entera sin tocar los roles del sistema. Fuera, por
composición: el padding del medidor y el tamaño de su rótulo leen privados de
FIELD (§5.3-3, se teman en la ficha del dueño).
Gates: sonda 0 diffs en 3.060 valores · censo 62 % · audit PASS · lint 0 ·
suite con el rojo conocido · rtl 0 · docs 0 · captura mirada.
- 2026-08-22 — **`context-menu` 53 % → 90 %** (11 claves, `global` a cero), y
**el instrumento aprende a abrir un menú contextual**: se abre con clic
DERECHO y con nada más, así que sonda y guard medían UN nodo. Con
`openBy: 'contextmenu'` y el clic derecho en la sonda: 14 nodos en abierto y
el guard en **27/29**.
Dos limpiezas: el `font-family` era respaldo de sí mismo y el peso del
encabezado llevaba un `500` muerto. Dos adjudicaciones, y una es la TERCERA
ocurrencia de §12.9 (el plano `overlay` impone la tipografía del panel).
Gates: sonda 0 diffs en 600 valores · censo 90 % · audit PASS · lint 0 · suite
con el rojo conocido · rtl 0 · docs 0 · captura del panel mirada.
- 2026-08-22 — **`metrics` 74 % → 82 %** (4 claves + prefijo abreviado fuera,
`global` a cero). **`--_mi-*` violaba theming §6 r5** —segundo caso del día
tras `--cp-*`—: 16 ocurrencias renombradas a `--_metrics-icon-*`. Son el
conmutador del icono por variante y ya derivaban de públicos, así que el censo
los reclasifica solo. Cosido: el ritmo del trend y las TRES formas del icono
(una clave por valor de `data-shape`; el radio es lo único que las distingue).
Dos adjudicaciones forzando las formas que la demo no monta. Sonda 0 diffs en
1.590 valores · censo 82 % · audit PASS · lint 0 · captura mirada.
- 2026-08-22 — **`float-panel` 59 % → 84 %** (12 claves, `global` a cero).
Las dos variantes que ajustan desde el default elevado, los botones de la
barra y el asa. **Muere uno de los nueve fantasmas del barrido**: el asa leía
`var(--color-content-tertiary, …)` y ese primitivo no existe — el contrato
guarda lo que de verdad pintaba.
Once adjudicaciones medidas (la demo monta la variante por defecto y no tiene
botón de acción genérico) **y una ANOMALÍA registrada**: `resize-grip-fg`
mueve bajo una réplica a mano de la secuencia del propio guard y aun así lo da
por muerto; causa no encontrada, descartadas cuatro. El token está vivo; la
lectura es lo que está en duda → §13, primer sitio por donde empezar la
revisión adversarial de este bloque.
Los 12 rojos que quedan son anteriores, y seis son el mismo conjunto que en
`popover`: el plano de profundidad gana sobre el panel (§12.9).
Gates: sonda 0 diffs en 1.890 valores · censo 84 % · `--names` sin desviadas ·
audit PASS · lint 0 · suite con el rojo conocido · rtl 0 · docs 0 · captura
mirada (cabecera, cierre y asa en su sitio).
- 2026-08-22 — **`nav-tree` 4 % → 96 %** (17 claves; tenía UNA). Global 61 %.
**La FILA es link + trigger a la vez** —mismo padding, tinta, radio y hover—,
así que el knob es de la fila (pseudo-parte, molde de `waveform`), con el
modificador DELANTE en lo interactivo (`hover-`/`active-`/`disabled-row-fg`)
y DETRÁS en lo contextual (`trail-row-fg`). El galón es una escuadra de dos
bordes: lado y trazo, como la esquina de `text-focus`.
**La suite cazó un incumplimiento heredado**, tercera vez en el eje: el
contrato copió `var(--font-size-sm)` verbatim del CSS y ésa es la coordenada
CRUDA que `recipe-css-contract` prohíbe. Al bundle, computa idéntico.
**Dos cegueras más del guard**: la fila es un `` pelado sin atributo (su
`gap` leía muerto) y no leía el ANCHO de un borde que no fuera el de arriba.
Con las dos: **18/18 sin una sola excepción**. Los nueve componentes con
ledger re-verificados tras tocar las PROPS: sin regresiones ni STALE.
Gates: sonda **0 diffs en 22.140 valores** (102 nodos × 8 estados) · censo
96 % · `--names` sin desviadas · audit PASS · lint 0 · suite con el rojo
conocido · rtl 0 · docs 0 · captura del escenario mirada.
- 2026-08-22 — **`drawer` 57 % → 72 %** (10 claves: el disparador, gemelo del
de popover, con `min-block-size` al bundle). Global 61 %.
Lo que queda fuera es la FIRMA DE SALIDA (los cuatro bordes base que
`data-last-action` tiñe al cerrar) → §13, y ocho privados que son canales de
valor del wrapper.
**Una adjudicación de clase nueva**: el guard ABRE el cajón antes de probar y
el velo tapa el disparador, así que la pasada de hover no puede posarse en él.
Con el cajón cerrado y hover a mano, `hover-trigger-bg` alcanza. Los otros 24
rojos son anteriores (asa, anillo de arrastre, tallas del panel).
Gates: sonda 0 diffs en 390 valores · censo 72 % · `--names` sin desviadas ·
audit PASS · lint 0 · suite con el rojo conocido · rtl 0 · docs 0.
- 2026-08-22 — **`aura` 43 % → 80 %** (13 claves). Global 61 %.
Su texto de estado baja un paso del bundle por talla y las TRES coordenadas
viajan juntas: doce declaraciones, doce valores, doce claves (1:1, sin
inflación). Más `idle-opacity`. Identidad fuera: el radio del anillo, los
cuatro `100%` y el `1px` de la región sr-only.
**Doce adjudicaciones medidas**: las seis tintas de estado y el halo pintan el
fondo del INDICADOR y la demo corre con el canvas WebGL montado —
`:has(canvas)` pone `background: none` a propósito—; quitando el canvas en
vivo, el gradiente vuelve y las siete siguen. El arco y el halo son SLOTS que
sólo existen en los estados de trabajo: montados como `` en el SVG
real, alcanzan. Y el guard no veía ese SVG (sus `` no llevan
`data-aura*`): tercera vez que `extraNodes` salva tokens vivos.
Gates: sonda 0 diffs en 1.710 valores · centinela 25/37 con las doce
adjudicadas · censo 80 % · `--names` sin desviadas · audit PASS · lint 0 ·
suite con el rojo conocido · rtl 0 · docs 0.
- 2026-08-22 — **`color-picker` 51 % → 75 %** (20 costuras + un prefijo
abreviado retirado). Global **60 % → 61 %**.
**`--cp-*` violaba theming §6 r5** (no abreviar el nombre del componente):
cinco nombres, **45 ocurrencias en 8 ficheros**, tres de SOMA —el provider los
estampa inline, su test los lee, sus tipos los declaran—. Renombrados a
`--_color-picker-*` con `git ls-files` y 0 diffs; dos ya derivaban de un
público, así que el censo los reclasifica solo. Precedente: los `--gb-*` de
F2-A.
Cosido el ritmo, la tinta de la etiqueta, la tipografía del disparador y la
del VALOR (metadato: mono/regular/tinta propia), el borde de la muestra, el
raíl de canal y su pulgar, el hueco del anillo y el borde del cuentagotas.
**El pulgar lleva DOS sombras que hacen una cosa** (contorno + elevación):
un token, y la regla de foco lo compone con su tercer anillo.
**El instrumento no veía dos familias de nodo**: las muestras del picker SON
`` (`data-color-swatch`) y sus sliders SON sliders
(`data-slider-*`); cuatro tokens vivos leían muertos. Con `extraNodes` para
las dos, 46/71.
**Lo rojo que queda es anterior**: 23 sin adjudicar (eran 24), del bloque
viejo — su pase propio queda en §13, con dos causas ya descartadas (el panel
SÍ abre y sobrevive al forzado de talla; el guard ya ve sus nodos).
Gates: sonda 0 diffs en 1.350 valores, medida DOS veces (tras el renombrado y
tras la costura) · tests de soma del color-picker 7/7 · censo 75 % ·
`--names` sin desviadas · audit PASS · lint 0 · suite con el rojo conocido ·
rtl 0 · docs 0 · `check` sin errores propios.
- 2026-08-22 — **`popover` 46 % → 67 %** (11 claves para el disparador + una
RETIRADA). Global 60 %.
El disparador genérico —el que no lleva el arquetipo `field-trigger`— montaba
su cromo sobre primitivos crudos: once costuras, con `trigger-height` leyendo
el BUNDLE y no el primitivo, y hover/abierto con su par cada uno (mismo valor
hoy, dos estados distintos).
**`bg` retirado: era un huérfano que el test de huérfanos no veía.** Ninguna
regla lo consumía; lo único que lo nombraba era un COMENTARIO de
`popover-arrow.svelte`, y ese test busca el nombre como texto en los ficheros
del componente. La superficie la pinta el plano de profundidad. → §13.
**Los doce que quedan son la FIRMA DE SALIDA y no se cosen aquí**: la misma
matriz `data-last-action` × 3 intents × 4 lados está repetida en drawer (22)
y dialog (9), y ya ha derivado (dialog tiñe sólo el color; popover y drawer
también el grosor). La tabla morfo→eidos la sitúa como mapeo transversal, así
que la salida es una regla sobre el arquetipo, no tres copias. → §13.
**Dos cegueras del instrumento**: la página tiene CINCO disparadores y el
guard abría el primero del documento en vez del del escenario; y `content-z`
se consume sobre el ENVOLTORIO FLOTANTE, un nodo sin atributo `data-popover*`,
así que leía muerto moviendo 80 → 4321. Las dos arregladas en
`COMPONENT_OVERRIDES`.
Gates: sonda 0 diffs en 420 valores (8 estados) · centinela 33/46 con trece
adjudicaciones medidas —nueve de partes que la demo no monta, dos del overlay
opcional y **dos que el plano `overlay` gana** (§12.9, pendiente de firma)— ·
censo 67 % · `--names` sin desviadas · audit PASS · lint 0 · suite con el rojo
conocido · rtl 0 · docs 0.
- 2026-08-22 — **`radio-cards` 60 % → 61 %: una sola clave, y ése es su techo.**
21 de sus 23 knobs fuera de alcance **no son suyos**: es un SKIN sobre
RadioGroup —renderiza `` y su indicador ES un radio—, así
que lee `--radio-group-*` y el puente de paleta del anfitrión. Mandato de
composición (`theming-audit` §5.3-3): se teman en la ficha del dueño. Lo suyo
es la TARJETA: `invalid-border`. Los dos `--radius-full` del indicador son
identidad (un radio es redondo por definición).
**La lección de la medición**: la primera lectura de `invalid-border` dio «sin
efecto» porque la tarjeta transiciona `border-color` y leer justo después de
escribir devuelve el valor de PARTIDA. Con las transiciones congeladas —lo que
el guard hace por defecto y mi sonda a mano no— alcanza. **Una medición
forzada tiene que congelar también.**
Gates: sonda 0 diffs en 3.540 valores · centinela 35/40 con las cinco
adjudicadas y medidas · censo 61 % · `--names` sin desviadas · audit PASS ·
lint 0.
- 2026-08-22 — **`prose` 1 % → 83 %** (35 claves de costura, 2 → 37).
Global **59 % → 60 %**; `global` del catálogo 1.064 → 1.021.
Estiliza HTML CRUDO por `:where([data-prose] el)`, así que sus partes son
ELEMENTOS y la costura va por parte, como en `result`. Su escala editorial
`em`-relativa no entra: es decisión de diseño de su README («No 5×
duplicated scale») y va anotada `/* literal: */` — las 21 excepciones que el
censo aprendió a leer esta misma sesión. Dos literales se cambiaron por su
paso de escala con idéntico valor (`3px` → `--border-width-thick`, los `1px`
→ `--border-width`).
**El instrumento estaba ciego de dos maneras**, las dos arregladas antes de
medir: sonda y centinela filtran por `data-{c}-*` y aquí NINGUNA parte lo
lleva —la sonda medía **1 nodo** y el guard daba 27 de 37 por muertos—, así
que ambos ganan un selector de nodos extra (63 nodos con él); y el centinela
no leía el color de un borde que no fuera el de arriba, con lo que el
blockquote (`border-inline-start`) y la tabla (bordes de bloque) leían
muertos estando vivos.
Ocho adjudicaciones medidas: cinco las tapa el harness de la documentación
(`[data-uix-docs] code|pre` (0,2,0) gana a `:where(…)` (0,0,0) — la
incidencia ya escrita para `code-block`) y tres son elementos que el HTML de
ejemplo no usa, montados dentro del contenedor real.
Gates: sonda **0 diffs en 11.910 valores** (63 nodos × 7 estados) · centinela
29/37 · censo 83 % · `--names` 37/37 · audit PASS · lint 0 · suite con el
rojo conocido · rtl 0 · docs 0 · `check` sin errores propios. Los del ledger
re-verificados tras tocar el guard: sin regresiones.
- 2026-08-22 — **`listbox` ADJUDICADO: 68 % es su techo, y coserlo habría
mentido.** Sin cambios de código: su veredicto §5.
Cinco de sus nueve privados adoptan la capa `list-surface` (el ritmo de fila
compartido con select, combobox, command y los tres menús), dos son el puente
de paleta y el noveno sí deriva de un público. La cola decía «cose como sus
hermanos» —`dropdown-menu` y `context-menu` sí acuñan el puente—, y la
medición lo desmontó: **ninguno de los dos nombres alcanza desde `:root`**
(fila a 36 px, `--dropdown-menu-item-height` y `--list-item-height` a
`1234px` en `:root` → 36 px). La capa declara sobre
`[data-list-surface][data-size]` y el puente sobre `[data-{c}-content]`: las
dos ganan a `:root`. Copiar el puente habría subido la cifra sin dar alcance
— un token que miente, la clase que R-5.4 existe para cazar.
Se arregla EN LA CAPA (entrada de receta, como `calendar-surface`), toca diez
componentes y es su propio eje → §13. **Y avisa sobre el instrumento**: el
centinela da por vivos estos tokens porque escribe inline en el nodo; para un
token que un tema sólo puede escribir en `:root`, «mueve un computed» no
equivale a «un tema lo alcanza».
- 2026-08-22 — **El censo aprende a leer la válvula del canon: clase
`exception`.** Global **58 % → 59 %**, sin tocar una línea de CSS.
`recipe-contract` §3 dice que una desviación anotada
`/* literal: */` **en su propia declaración** es válida, y
`component-audit` ya la honra desde siempre (`declarationWindow` +
`/literal:/i` en R-2.1/2.6/2.7). El censo era el único instrumento que no:
su `strip()` blanquea los comentarios ANTES de clasificar, así que las
**81 anotaciones del catálogo** contaban como deuda. Dos instrumentos, un
canon, dos respuestas.
Ahora un literal anotado cae en la clase `exception`, **fuera del ratio**
como `system` — y por la misma razón: no es que un tema no lo alcance, es que
el canon ya aceptó por escrito que ahí no va un token. **54 knobs** en 12
componentes: `prose` 21 (su escala editorial `em`-relativa, decisión de
diseño firmada en su README), `proof-of-human` 16 (la escena de tono fijo),
`palabras` 3, `timeline` 2 (73 % → **77 %**), `result` 1 (86 % → **90 %**),
y siete más con una cada uno.
**La anotación vale para la DECLARACIÓN entera**, no sólo para su primera
línea: un valor partido en varias líneas lleva la nota al final, y así se
mide. Muta-prueba: retirar una anotación de `prose` mueve el knob de
`exception` a `literal` (21 → 20) y devuelve el conteo al restaurarla.
Efecto colateral bueno: las fichas ganan una **§1.4** que LISTA las
excepciones con su razón. Antes estaban escritas en el CSS y no se leían
desde ninguna parte.
- 2026-08-22 — **Tres techos adjudicados: el PUENTE DE PALETA no es deuda.**
`tag-group` 65 %, `stepper` 79 %, `timeline` 73 % — sin cambios de código,
sus tres veredictos §5.
Los tres tienen `global` a cero: lo único fuera de alcance son sus privados
`--_{c}-palette-*`, el puente THM-2 que la capa compartida alimenta por
instancia desde `[data-color]`. **Un público encima del puente dejaría que un
tema lo fijara y matara en silencio el `color=` de cada instancia** — la misma
clase de daño que «declarar un público de facto mata una escala». Ya exponen
sus nueve roles × variante en claves públicas (91 en `tag-group`): ésa ES su
superficie de color. `timeline` suma la segunda razón firmada: sus
`--_timeline-hue-*` son un CONMUTADOR por `data-intent` (doctrina F2-B, cinco
precedentes) cuya rama por defecto es el puente.
Medido para no adjudicar de oído: de las **687** declaraciones del catálogo
que leen un privado, **130 leen un `--_{c}-palette-*`**, y son las que dominan
la columna `private` de todo componente con paleta (tag-group 14/14, stepper
11/11, radio-group 10, checkbox 8, file-upload 8, calendar / editable / los
tres grids 7). **El techo de un componente con paleta no es el 100 %** y su
cifra no compara con la de uno sin ella — registrado en §13, junto con la
única salida si algún día se quiere comparabilidad: una clase `bridge` en el
censo, no acuñar los tokens.
- 2026-08-22 — **LA COSTURA: `chart` 49 % → 89 % y `result` 23 % → 86 %**
(6 + 15 claves). Global **57 % → 58 %**; `global` del catálogo 1.113 → 1.064.
**Corrige una lectura mía de las dos horas anteriores.** Al tokenizar `chart`
y `result` di por doctrina que «el texto no recibe tokens del componente»
porque su valor viene del canon —la capa de estilos con nombre, las ranuras de
contenido, el bundle de talla— y lo dejé leyendo el canon A PELO desde el CSS.
Eso es media doctrina: **el valor es del sistema, pero el knob tiene que ser
del componente** (PLAN §2-A: todo knob de apariencia lee `--{c}-{slot}`). Sin
la costura, un tema no puede aclarar las anotaciones de un gráfico denso sin
mover `caption` en toda la app, y `getRecipeTokens()` / `/temas` no ven esa
superficie. El molde ya estaba escrito en la vertebración tipográfica
(`--accordion-trigger-font-family: var(--style-label-font-family)`) y D-TH.2
aclara que **sólo los seis PRIMITIVOS** quedan fuera («un componente que sólo
LEE un named style para un eje no es un primitivo»).
**Dos formas, porque los componentes son distintos** — y ésa es la parte que
se firmó:
- `chart`, **por ROL**: dos roles del canon (`caption` para las anotaciones,
`label` para el cromo) × tres ejes = 6 claves para 19 nodos de texto.
Nombrar por parte habría dado ~30 claves con dos valores. Tamaño y tinta
son ORTOGONALES a propósito (`empty` y `bar-list-value` son tamaño `label`
con tinta `caption`). El readout del gauge no tiene rol en el canon y su
costura toma el bundle.
- `result`, **por PARTE**: cinco partes con tipografía distinta y ningún rol
que las cubra → 15 claves `title-*`, `description-*`, `extra-*`, `code-*`,
`media-*`. Es la forma dominante del catálogo.
**Nombres**: los tres que propuse primero no aguantaron la revisión
(`label-font-size` chocando con las seis partes `*-label`, `emphasis-*`
inventando vocabulario, `fg-muted` apoyado en un solo precedente). Se nombra
por el ROL DEL CANON que el texto adopta, y la tinta lee el color DEL ROL
(`var(--style-caption-color)`), no la ranura a pelo.
Con esto **`global` cae a CERO en los dos**: lo que queda fuera son los diez
literales de identidad de chart (nueve `100%` + `max-content`) y tres de
result.
Gates: sonda **0 diffs en 161.850 valores** (chart, 16 rutas × 7 estados) y
**990** (result) · centinela chart **43/45** y result **15/27**, y las doce
que callan están medidas SOBRE NODOS REALES con los controles de la demo
(chip `not-found` para el código HTTP, casilla del `extra`, quitar
`data-status` para la tinta por defecto del glifo) · censo 89 % / 86 % ·
`--names` 45/45 y 27/27 · audit PASS · lint 0 · suite con el rojo conocido ·
rtl 0 · docs 0 · `check` sin errores propios.
**Y retira una nota equivocada de §13**: escribí que el censo penalizaba
consumir la capa tipográfica. El censo medía bien; faltaba la costura. La
lección queda escrita ahí: cuando la métrica y la doctrina discrepan,
sospecha de la lectura antes que del instrumento. `listbox` (68 %, ritmo de
fila prestado de `list-surface`) es la misma pregunta un piso más arriba y
queda pendiente de revisar con este molde.
- 2026-08-22 — **`result` 14 % → 23 %** (4 claves, 8 → 12). Global 57 %,
<20 % 18 → 17. Aplicación directa de la doctrina que cerró `chart`: **la
receta posee su CAJA** —inset de página, ritmo entre bloques— y nada más. Su
tipo ya leía el BUNDLE DE TALLA (`--size-{k}-font-size`), que es lo que
recipe-contract §1 prescribe, y su tinta las ranuras de contenido: acuñar
`--result-title-font-size` habría sido tipografía por componente. Las trece
lecturas de canon siguen contando `global` — §13, tercera ocurrencia.
Higiene de paso: el privado `--_result-media-color` → `--_result-media-fg`
(D-TH.6 dice `fg`; R-5.3 no mira privados).
Gates: sonda **0 diffs en 990 valores** · centinela 7/12 con **cinco
adjudicaciones medidas sobre nodos REALES** —los tres acentos pulsando su
chip de estado, el bloque `extra` marcando su casilla— y no sobre nodos
fabricados (la lección de `drag-drop`) · censo --only 23 % · --names 12/12 ·
audit PASS · lint 0 · suite con el rojo conocido · rtl 0 · docs 0 · `check`
sin errores propios.
- 2026-08-22 — **`chart` 9 % → 49 %** (22 claves nuevas fusionadas en su bloque,
17 → 39). El mayor de los de alcance <20 % que no estaba bloqueado.
**La ficha pedía 71 claves y ~20 habrían llevado el mismo valor.** Lo decidió
la medición: las 84 filas fuera de alcance colapsan a **26 valores distintos**
(9× `content-secondary`, 9× `content-primary`, 9× `100%`, 6× `font-size-sm`,
6× `font-size-xs`, 6× `font-weight-medium`, 5× `surface-default`). La
inflación de `spinner` con otra forma: nombrar por parte lo que es un
concepto.
**El texto no recibe tokens de chart**: toma su ROL DE TAMAÑO de los estilos
con nombre (`caption` para anotaciones, `label` para el cromo) y su tinta y
peso de las ranuras del sistema. Acuñarlos sería tipografía por componente,
lo que el autor prohibió el mismo día. Precedente de consumir la capa:
`code-block`, `kbd`, `announce`. **La receta sólo posee la tinta de lo que no
es texto** — `axis-fg`, `grid-fg`, `separator-fg` (el pelo de superficie que
separa marcas contiguas: cinco partes, una idea), `smith-boundary-fg`,
`track-bg` — más 17 de geometría de cromo. Identidad fuera de contrato: los
nueve `100%` y el `max-content` del tooltip.
**Incumplimiento heredado corregido**: el CSS leía la coordenada CRUDA
`var(--control-height-sm, var(--space-7))` (respaldo muerto); el contrato
guarda el bundle `var(--size-sm-control-height)`, 1:1.
**El instrumento estaba ciego de TRES maneras, arregladas antes de medir:**
1. **La superficie de chart vive en 16 rutas de demo**, una por tipo:
`/chart` monta 58 nodos de los 302 de la página y el resto vive en rutas
hermanas. El guard gana `urls`: un token está VIVO si ALGUNA superficie del
componente lo sigue, y cada URL sólo re-prueba lo que sigue pendiente.
De paso `picker-shell` recibe la suya (su ruta propia es un 404, se mide
dentro del date-picker: 0/31 → 6/31 sin pasar la URL a mano).
2. **El guard no leía NINGUNA propiedad SVG** — sin `fill`/`stroke`/
`strokeWidth`/`fillOpacity`/`r`/`rx`, doce claves de un componente que
dibuja en SVG leían muertas estando vivas. Misma clase que el hueco de
`filter` del día anterior.
3. **El valor centinela se elegía por SUBCADENA**: `slice-stroke-width`
recibía `rgb(1, 2, 3)` por contener «stroke» — inválido para una longitud,
así que leía muerta. Ahora la dimensión se decide por el final del nombre.
Gates: sonda **0 diffs en 161.850 valores** (16 rutas × 7 estados, 892 nodos
en reposo) · centinela **37/39** con dos adjudicaciones medidas sin la
congelación (`transition-duration` 0.12s → 11.5s, `-ease` → steps(4)) ·
censo `--only` 49 % y global **56 % → 57 %** (2.638 → 2.675 públicos,
<20 % 19 → 18) · `--names` 39/39 conformes · audit PASS · eidos-lint 0
invalid · suite eidos con el único rojo conocido · rtl 0 · docs 0 · `check`
sin errores en los ficheros tocados. **Los 28 componentes con ledger
re-verificados tras los tres cambios de instrumento: cero regresiones, cero
STALE.**
Abre (→ §13): el censo **penaliza consumir la capa tipográfica** si no eres
un primitivo (las doce declaraciones correctas siguen contando `global`) — la
nota de `listbox` con una segunda ocurrencia; y el número del gauge no tiene
estilo con nombre que lo represente (un readout de dato no es un `h2`).
- 2026-08-22 — **`text-scramble` ADJUDICADO: sin contrato que escribir** (y el
barrido de fantasmas, hecho). Sin cambios de código: su veredicto §5.
Su 50 % no es ni deuda ni logro. **Dos literales son la técnica sr-only**
(`width`/`height: 1px`), idéntica a `text-blur`. **Los dos «públicos» son
tipografía que el componente no debería acuñar** —`font` y `size`,
consumidos con fallback y sin declarar—, o sea la firma **1.bis**:
escribirles contrato ahora sería acuñar exactamente lo que esa firma propone
retirar. Con `text-scramble` la cuenta de esa firma sube a **7 claves en 4 de
los 5** componentes de la familia (`text-blur` es el único limpio: hereda).
Y su `font` apunta a un fantasma: `var(--font-mono, …)` no existe —el
canónico es `--font-family-mono`— así que pinta `ui-monospace` e **ignora la
mono del tema** (`Azeret Mono`). Medido en navegador.
**El barrido mecánico que `--radius-xs` y `--font-size-4xl` pedían está
HECHO**: 5.793 nombres declarados en `src/uix/eidos` contra los
`var(--x, fallback)` de las recetas → **9 referencias fantasma**, tabla en
next-features §13. La más grave no es de esta familia:
`--color-content-tertiary` sigue vivo en TRES recetas (el caso histórico que
`recipe-contract` §1 cita como origen de su regla) y los cuatro
`--style-*-font-variation-settings` de `text.css` significan que el eje de
fuente variable **no llega nunca al primitivo `Text`**. Ninguna se arregla
aquí; el barrido debería ser un guard (misma lógica que el test de fantasmas
sin fallback, con el filtro de vocabulario de sistema encima).
- 2026-08-22 — **`text-gradient` 67 % → 100 %** (7 claves, entrada nueva).
Tercero de la familia text-* con la forma de `text-circular` / `text-focus`
(públicos «de facto» con fallback y sin declarar), pero la propuesta §4
generada fallaba en las tres decisiones y las tres se resolvieron midiendo
contra el CATÁLOGO, no contra el CSS de partida:
- **`weight` → `font-weight`**: 77 claves `font-weight` en el catálogo
contra 4 `weight` a secas, dos de ellas escritas el mismo 22 en esta
familia. Y `500` **es** `var(--font-weight-medium)`.
- **`calc(100% - 2px)` no son dos knobs de eje físico** (que es lo que la
ficha marcaba con ⚠) sino UNO: los 2 px son el trazo del marco asomando a
cada lado. Knob = `border-width` con `var(--border-width)` (el paso
`thin`, no un literal igual a un paso), y el hueco DERIVA de él.
- **`blur(4px)` → `var(--blur-sm)`**: `blur` es familia MÉTRICA del eje
`scaling` (theming §23) y un literal es ciego al zoom global.
Fuera del contrato por naturaleza: `duration` y `play-direction`, que el
wrapper escribe INLINE desde `animationSpeed`/`yoyo` — misma clase que el
`item-gap` de `carousel` y el `preview-z` de `drag-drop`.
**Dos puntos ciegos del instrumento, arreglados ANTES de medir** (la lección
de F2-B aplicada por adelantado): la demo arranca con `showBorder=false`, así
que sonda y centinela veían 2 nodos y NINGUNO de los tres tokens del marco;
y la sonda no leía `backdropFilter`, que el censo sí cuenta como knob. La
sonda gana un mapa `DEMO_VARIANTS` (chips de variante que se re-pulsan tras
cada recarga) y el centinela una entrada `openWith` que no abre un panel sino
que ENCIENDE UNA VARIANTE — un uso nuevo del mismo gancho.
Gates: 4 nodos · 720 valores × 7 estados · **0 diffs** · centinela **7/7 sin
excepciones** · censo `--only` 100 % y global 2.634 → 2.638 públicos ·
`--names` 7/7 conformes · audit PASS · eidos-lint 0 invalid · suite eidos con
el único rojo conocido (`skin-media-player`) · rtl 0 · docs 0 · `check` sin
errores en los ficheros tocados. Demo con pestaña **Tokens** (y fuera la
tabla de tokens escrita a mano, que este mismo renombrado dejaba obsoleta).
Abre (→ next-features §13, **pendiente de firma, apuntado para después**):
**la familia text-effects ACUÑA tipografía propia contra el canon** — cinco
claves (`text-focus.word-size` vía el fantasma `--font-size-4xl` y
`word-weight` · `text-circular.weight` y `font-size` ·
`text-gradient.font-weight`, ésta subida aquí), opiniones del seed que el
«valor verbatim» hizo contrato. Doctrina F2-B regla 2: se CONSUME la capa
(`--style-*`) o se HEREDA (`link`); un efecto de pintura sobre texto real no
tiene tipografía propia. Resolución propuesta: retirar las cinco y heredar
(mueve defaults → firma). El módulo de tipografía es canon y no se toca. Las
demos NO forman parte del eje (autor, 2026-08-22).
- 2026-08-22 — **Bloque F2-B: 21 componentes tokenizados + 5 adjudicados como
«0 % estructural».** Global **45 % → 50 %**; sin contrato 49 → 29; al 100 %
7 → 10; alcance <20 % 43 → 22. Uno por commit, protocolo §7 entero, sonda
antes/después = 0 diffs en todos.
| componente | alcance | commit |
| --- | ---: | --- |
| `grid-list` | 0 → 85 % | `60b5b9896` |
| `textarea` | 0 → 80 % | `893aeaf81` |
| `tree-view` | 0 → 92 % | `dd188f125` |
| `code-block` | 0 → 81 % | `354d166df` |
| `card-group` | 0 → 90 % | `c56d6544e` |
| `spinner` | 0 → 70 % | `42a3e7413` |
| `picker-shell` | 0 → 76 % | `67b4c810c` |
| `link-preview` | 0 → 100 % | `7a0fc2ead` |
| `drag-drop` | 0 → 89 % | `650d76aa0` |
| `kbd` | 0 → 86 % | `adb77863c` |
| `link` | 0 → 36 % | `d3089e880` |
| `code` | 0 → 100 % | `e4bcd505d` |
| `virtual-list` | 0 → 67 % | `070145786` |
| `virtual-grid` | 0 → 73 % | `e3f39ce28` |
| `skeleton` | 0 → 45 % | `a6d4d4f5a` |
| `label` | 0 → 100 % | `7565eff47` |
| `announce` | 0 → 88 % | `d568577eb` |
| `clipboard` | 0 → 63 % | `151e5159b` |
| `scroll-frames` | 0 → 33 % | `1f692629e` |
| `mark` | 0 → 60 % | `9f24a31eb` |
| `menu-dial` | 0 → 25 % | `471ba96d2` |
| 5 estructurales (fichas) | 0 % FINAL | `ed2e3cd7c` |
**Lo que el bloque enseñó, y no estaba en el plan:**
1. **Un alcance bajo puede ser doctrina bien aplicada.** `menu-dial` 25 %
porque sus ejes de colocación son de la capa `viewport-placement` y la
receta escribe en sus RANURAS DE OVERRIDE; `link` 36 % porque sus
escotillas caen en `inherit`, que es semántico; `scroll-frames` 33 %
porque es layout puro. El % no es la métrica de calidad.
2. **Un privado con DOS fuentes es un conmutador, no deuda** — cinco casos
con el mismo veredicto (`textarea`, `spinner`, `skeleton`, `code`,
`label`): aplanarlo obligaría a duplicar cada regla por color.
3. **Lo que la capa tipográfica posee no se acuña** — cinco casos
(`code-block`, `kbd`, `announce`, `code`, `label`).
4. **Cinco componentes tienen 0 % POR NATURALEZA** y ninguna deuda:
`aspect-ratio` (faceta de Box, knob prestado), `text-blur` (sr-only),
`cascade` y `motion` (gate antiparpadeo del canal), `date-picker`
(corrección `max-content` de composición). El censo no los distingue de
la deuda real, **así que el gate de F3 «censo 100 %» es inalcanzable por
construcción** hasta que exista una clase `structural` — §13.
5. **La propuesta §4 generada hereda el incumplimiento del CSS de partida**:
copia el valor verbatim, y si ese valor ya violaba `recipe-css-contract`
(primitivo crudo en vez del bundle), la propuesta lo repite. Lo cazó la
suite en `code-block`.
6. **La inflación del generador puede ser 4×**: en `spinner` proponía 71
tokens para 23 knobs, multiplicando UNA coordenada de talla por
variante × parte × dimensión.
**El guard R-5.4 ganó SEIS capacidades**, todas nacidas de una medición y
con los componentes del ledger re-verificados sin regresión tras cada una:
puntero parqueado tras el blur (`reopen()` corre antes de cada token),
`::placeholder` en el snapshot (la nota de §13 que decía que no se lee era
falsa), `COMPONENT_OVERRIDES` de prefijo y selector de apertura, apertura
por `hover` para hover-cards, y `text-decoration-thickness` /
`-underline-offset` en la lista de propiedades.
**Revisión adversarial §7.7 — HECHA 2026-08-22.** Molde F2-A: worktree en la
base del bloque (`8400e5bdd`) con su propio dev server, medición
independiente. **4 hipótesis · 3 refutadas · 1 hallazgo real.**
- **REFUTADA «el default cambió en algún sitio que la demo no mira»**: 77
casos FORZADOS (variantes, formas, tallas y estados que las demos NO
montan, en los 21 componentes) comparados base vs HEAD → **0 diferencias**.
- **REFUTADA «hay tokens huérfanos»**: 339 públicos de los 21 bloques, 0 sin
consumo. Con muta-prueba: un token falso inyectado sale detectado, y el
árbol se restaura.
- **REFUTADA «el gate de 0 diffs pasó sobre casi nada»**: se contaron los
nodos que ve cada sonda. Cuatro componentes miden 1 nodo (`link`, `code`,
`skeleton`, `link-preview`), y por eso se forzaron sus variantes en el
punto anterior — ahí es donde viven sus tokens, y salieron idénticos.
- **HALLAZGO REAL: `drag-drop.preview-z` mentía.** El ledger lo daba por vivo
con «forzado → alcanza», pero el nodo se había creado a mano; el preview
REAL que soma monta durante un arrastre lleva `z-index: 9999` INLINE, así
que ninguna cascada puede ganarle. Retirado con 0 diffs. Misma clase que el
`item-gap*` de carousel en F2-A. **La lección: una adjudicación «forzado →
alcanza» vale lo que valga el nodo que se forzó.** Re-verificado el resto de
la clase contra nodos reales (`clipboard`, `picker-shell`): correctos.
Dos hallazgos de INSTRUMENTO en la propia revisión, ambos registrados en §13:
el orden de carga **no es el mismo en dev que en producción** (medido con
build + CDP; el ganador coincide por casualidad), y un **worktree cuyo
`node_modules` es una junction fuera del root no hidrata** — Vite responde 403
a `@fs/…` y la primera pasada de esta revisión comparó contra una base
muerta sin que nada lo delatara.
- 2026-08-21 — **La capa `calendar-surface`** (firma 1 del acta, diseño
presentado y firmado el mismo día). La medición desmontó el encargo: la capa
ya existía de hecho — `--calendar-*` en `:root`, y `range-calendar` /
`month-grid` / `year-grid` con 114 / 77 / 77 referencias prestadas y CERO
tokens propios. Se le dio nombre y casa (`lib/calendar-surface.css`, hook
`data-calendar-surface`, cuatro coordenadas xs..lg sin xl, celda dos pasos
bajo el bundle) y se cerró el defecto que la justificaba: las dos sombras del
anillo se emitían con ámbito `[data-calendar]` y los otros tres las leían
vacías, así que el anillo sema **no pintaba** en tres componentes. Capa
HÍBRIDA: el vocabulario se queda en la entrada de receta (76 claves
semánticas alcanzables por config), la capa posee la resolución por talla y
la forma del anillo. **Siete wrappers estampan**, no cuatro — los pickers
renderizan la superficie soma por los suyos y un panel portalado no hereda.
Censo: `LAYER_VOCABULARY` deja de penalizar consumir una capa; global 43 % →
**45 %**, `calendar` 75 % → **84 %**.
- 2026-08-21 — **Revisión adversarial de F2-A (§7.7) + nace R-5.4.** Molde
Sidebar sobre worktree con solo el CSS revertido a la base: 34 hipótesis ·
26 refutadas · 8 reales, todas las de código arregladas con diff de computed
VACÍO (command 8.091 · carousel 2.842 valores). Retiradas: el re-point
muerto de `--command-radius` en el Dialog (su comentario mentía: el input
nunca lo leyó) y el trío `item-gap*` de carousel (el `gap` INLINE de soma
gana siempre — canal de valor, no knob). Tokenizado: el `2.25` vertical del
indicador activo. El instrumento viejo cargaba 22 falsos negativos de 26
«no effect» (clic-foco · override solo en `[data-{c}]` · pseudos) y la
no-determinación de `feed` era la demo cargando — cuatro causas arregladas.
**R-5.4**: `theming-sentinel.ts` + ledger de adjudicaciones, los ocho
componentes en verde con 46 excepciones medidas. El `striped` inerte se
firmó y ejecutó el mismo día: `:nth-child(even of [data-table-row])` +
`:where(:not([data-selected]))` al mismo (0,6,0) — 12 diffs exactos, hover
y selected verificados, la excepción del ledger retirada (table 42/45).
Pendiente de firma: el `item` en fila Y celda, y el gap de soma.
Detalle en [`CONTINUE-theming.md`](./CONTINUE-theming.md) §«Registro».
- 2026-08-20/21 — **Las 14 firmas, el vocabulario y el bloque F2-A.** El día se
abrió presentando D-TH.6 y acabó con las catorce decisiones pendientes
firmadas en bloque, el vocabulario normalizado con guard, y ocho componentes
tokenizados. Detalle en [`CONTINUE-theming.md`](./CONTINUE-theming.md)
§«Registro de la sesión».
**El vocabulario** (`f09e04fab` acta · `bd916ef3f` codemod · `93017975c`
segunda pasada · `7781d6e4c` guard + doctrina · `476da2dd2` muro de tipos):
307 claves al idioma firmado —tinta `fg`, modificador interactivo delante—
con censo de alcance IDÉNTICO y 0 diffs de computed. R-5.3 entra en `error`
directo; el tipo de `defineRecipes` impide la regresión sin ejecutar nada.
La medición corrigió el inventario heredado: 370 «desviadas» eran 301, porque
47 claves `{rol}-{slot-de-rol}` son canónicas por construcción y un codemod
sobre ellas habría roto `button` entero.
**El bloque F2-A** (pieza 0 `bd032534b` + ocho componentes): global
**37 % → 43 %**, sin contrato **56 → 49**, al 100 % **6 → 7**. `command` 98 %
· `table` 86 % · `media-player` 88 % · `tree-grid` 95 % · `gradient-picker`
88 % · `listbox` 68 % (techo deliberado: su ritmo es de `list-surface`) ·
`carousel` 77 % · `feed` 94 %. Protocolo §7 entero en los ocho; diff de
computed vacío en todos.
**Lo que el bloque destapó y NO se arregló aquí** está en
[`next-features.md`](../next-features.md) §12 y §13: el contrato de cascada
del velo de estado (131 declaraciones-atajo en 45 componentes, la prop
`hoverable` que no suprime nada, un empate de especificidad resuelto por orden
de carga) y los huecos de instrumento y demo. La regla que el eje adoptó: si
una incidencia mueve píxel o toca morfo, se mide, se anota y se sigue.
**Tres veredictos de ocho tenían un error de lectura** que sólo apareció
midiendo, y esa es la lección de método del bloque: el veredicto orienta, la
medición decide.
Además: la demo enseña ahora el contrato de tokens (`90aa6dc5f`,
`TokensPanel` leyendo `getRecipeTokens()` en vivo) — hasta ese día ninguna
demo mostraba la superficie que este eje construye.
- 2026-08-19 — Censo medido (§1) con `scripts/theming-census.ts` (añadido en
este commit como instrumento, sin guard). Plan entregado. **Nada firmado,
nada construido.** Precedente ejecutado hoy que fija la forma:
`navigation-menu` (`ae9e277fa`: tokens del trigger por talla, default
idéntico; `a82794845`: el hover es el del sistema; `822b78cf2`: el ``
sin arquetipo) — y aun así el componente queda en 44 %, prueba de que hace
falta el guard.
- 2026-08-20 — **Informe + primeros siete componentes** (`2591ec2f0` el informe
y el instrumento; `3bfe0d413` la revisión de las fichas 11-20). El censo pasa
a `--report`: `docs/audit/theming/` con un README de conjunto y **170 fichas**
(162 recetas + 8 sin receta), cada una con análisis, propuesta derivada de la
doctrina y un bloque de **veredicto** que se conserva al regenerar.
| Componente | Censo antes → después | Commit | Excepciones / lo que queda fuera |
| --------------------------- | --------------------: | ----------- | ------------------------------------------------------------------------------------------------------------------------ |
| `gradient-builder` (piloto) | 0 % → 80 % | `3cdb5b5f0` | foco (sistema) + 3 literales de layout; damero tapado por el `background` inline del wrapper (anotado) |
| `combobox` | 0 % → 76 % | `cef2d32f1` | 3 hovers bespoke (esperan firma) + 6 literales; `content-font-family/-line-height` inertes bajo `[data-depth='overlay']` |
| `natural-time-picker` | 0 % → 61 % | `e774ca7e8` | cielos = excepción de tono fijo ya firmada; panel presta `--popover-*` por composición |
| `date-range-picker` | 0 % → 42 % | `07778b597` | mitad calendario (§B) + mitad campo (§5.3-3) |
| `time-range-picker` | 0 % → 19 % | `68eb8af26` | préstamos de Field/Slider/Toggle |
| `time-picker` | 0 % → 18 % | `e4fcdd62e` | préstamos de Field |
| `proof-of-human` | 0 % → 14 % | `ae91573c3` | escena = `FIXED_TONE_COMPONENTS`; hooks de clase (eje aparte) |
**Global: 33 % → 37 %** (1.621 → 1.841 públicos; 62 → 56 sin contrato).
Protocolo §7 aplicado entero en los siete: diff de computed **vacío** en todos
(6.612 · 1.566 · 6.438 · 493 · 725 · 580 · 406 valores, 7-8 estados cada uno),
centinela por token, `component:audit` PASS, `eidos-lint` 0 invalid,
`rtl:check` 0, `docs:check` 0, suite eidos con el único rojo conocido
(`skin-media-player`).
Cuatro defectos del método que la verificación destapó y que el handoff
recoge: **clave duplicada** en `recipes/base.ts` descarta el bloque en
silencio · dejar vivos los bloques `[data-size]` del CSS hace que el diff dé
0 por la ruta vieja · la sonda debe congelar `transition` pero **no**
`animation` (Presence no monta) · un token RESUELTO no se mueve desde `:root`
por diseño.
Prefijos abreviados o ajenos corregidos de paso (el censo los contaba como
`global` y se cruzarían al anidar): `--gb-*`, `--_ntp-*`, `--_time-field-*` en
los dos time-pickers, `--_date-field-*` y `--_calendar-font-size` en el
date-range-picker.
---
## 9. Tabla completa por componente (2026-08-19 — regenerar con el script, no editar)
| Componente | Familia | Alcance | Knobs | Público | Privado | Global | Literal | Sistema | Contrato | size |
| --------------------- | ------------------------------- | ------: | ----: | ------: | ------: | -----: | ------: | ------: | -------: | :--: |
| `range-calendar` | Tiempo (chronos · fecha/hora) | 0% | 98 | 0 | 7 | 84 | 4 | 3 | 0 | y |
| `combobox` | Campos | 0% | 96 | 0 | 15 | 67 | 6 | 8 | 1 | y |
| `proof-of-human` | Controles · marcas | 0% | 95 | 0 | 18 | 36 | 37 | 4 | 0 | y |
| `time-range-picker` | Tiempo (chronos · fecha/hora) | 0% | 88 | 0 | 6 | 61 | 17 | 4 | 0 | y |
| `natural-time-picker` | Tiempo (chronos · fecha/hora) | 0% | 78 | 0 | 0 | 69 | 7 | 2 | 0 | y |
| `gradient-builder` | Campos | 0% | 62 | 0 | 8 | 46 | 3 | 5 | 0 | y |
| `month-grid` | Tiempo (chronos · fecha/hora) | 0% | 61 | 0 | 13 | 40 | 5 | 3 | 0 | y |
| `year-grid` | Tiempo (chronos · fecha/hora) | 0% | 61 | 0 | 13 | 40 | 5 | 3 | 0 | y |
| `time-picker` | Tiempo (chronos · fecha/hora) | 0% | 59 | 0 | 3 | 42 | 12 | 2 | 0 | y |
| `date-range-picker` | Tiempo (chronos · fecha/hora) | 0% | 55 | 0 | 0 | 49 | 3 | 3 | 0 | y |
| `command` | Menús · listas · navegación | 0% | 52 | 0 | 9 | 35 | 6 | 2 | 0 | y |
| `table` | Menús · listas · navegación | 0% | 46 | 0 | 23 | 14 | 5 | 4 | 0 | y |
| `media-player` | Media · chat | 0% | 45 | 0 | 0 | 37 | 8 | 0 | 2 | y |
| `tree-grid` | Menús · listas · navegación | 0% | 42 | 0 | 29 | 8 | 2 | 3 | 0 | y |
| `field-langs` | Campos | 0% | 41 | 0 | 0 | 31 | 8 | 2 | 0 | – |
| `gradient-picker` | Campos | 0% | 38 | 0 | 7 | 23 | 5 | 3 | 0 | y |
| `listbox` | Campos | 0% | 38 | 0 | 9 | 23 | 3 | 3 | 0 | – |
| `carousel` | Superficies · overlays · estado | 0% | 36 | 0 | 14 | 12 | 5 | 5 | 0 | y |
| `heading` | Texto · tipografía | 0% | 36 | 0 | 36 | 0 | 0 | 0 | 0 | – |
| `feed` | Menús · listas · navegación | 0% | 33 | 0 | 13 | 16 | 3 | 1 | 0 | y |
| `grid-list` | Menús · listas · navegación | 0% | 32 | 0 | 8 | 17 | 2 | 5 | 0 | y |
| `textarea` | Campos | 0% | 28 | 0 | 16 | 5 | 4 | 3 | 0 | y |
| `tree-view` | Menús · listas · navegación | 0% | 28 | 0 | 8 | 14 | 4 | 2 | 0 | y |
| `code-block` | Texto · tipografía | 0% | 26 | 0 | 2 | 24 | 0 | 0 | 0 | – |
| `card-group` | Superficies · overlays · estado | 0% | 24 | 0 | 0 | 18 | 4 | 2 | 0 | y |
| `text` | Texto · tipografía | 0% | 24 | 0 | 24 | 0 | 0 | 0 | 0 | – |
| `spinner` | Superficies · overlays · estado | 0% | 23 | 0 | 15 | 4 | 4 | 0 | 0 | y |
| `picker-shell` | Tiempo (chronos · fecha/hora) | 0% | 21 | 0 | 4 | 17 | 0 | 0 | 0 | y |
| `link-preview` | Superficies · overlays · estado | 0% | 17 | 0 | 4 | 9 | 1 | 3 | 0 | y |
| `drag-drop` | Controles · marcas | 0% | 16 | 0 | 3 | 6 | 0 | 7 | 1 | – |
| `kbd` | Controles · marcas | 0% | 14 | 0 | 1 | 9 | 4 | 0 | 0 | – |
| `link` | Controles · marcas | 0% | 14 | 0 | 4 | 2 | 5 | 3 | 0 | – |
| `code` | Texto · tipografía | 0% | 13 | 0 | 6 | 3 | 4 | 0 | 0 | – |
| `virtual-list` | Menús · listas · navegación | 0% | 13 | 0 | 2 | 6 | 4 | 1 | 0 | y |
| `virtual-grid` | Menús · listas · navegación | 0% | 12 | 0 | 2 | 6 | 3 | 1 | 0 | y |
| `skeleton` | Superficies · overlays · estado | 0% | 11 | 0 | 9 | 1 | 1 | 0 | 0 | y |
| `skin-media-player` | Media · chat | 0% | 11 | 0 | 0 | 2 | 7 | 2 | 0 | y |
| `scroll-frames` | Superficies · overlays · estado | 0% | 9 | 0 | 1 | 4 | 4 | 0 | 0 | – |
| `announce` | Superficies · overlays · estado | 0% | 8 | 0 | 0 | 8 | 0 | 0 | 0 | – |
| `clipboard` | Controles · marcas | 0% | 8 | 0 | 2 | 5 | 1 | 0 | 0 | – |
| `label` | Campos | 0% | 8 | 0 | 6 | 2 | 0 | 0 | 0 | – |
| `menu-dial` | Menús · listas · navegación | 0% | 8 | 0 | 3 | 1 | 4 | 0 | 0 | y |
| `display` | Texto · tipografía | 0% | 6 | 0 | 6 | 0 | 0 | 0 | 0 | – |
| `mark` | Controles · marcas | 0% | 5 | 0 | 2 | 1 | 2 | 0 | 0 | – |
| `aspect-ratio` | Controles · marcas | 0% | 3 | 0 | 0 | 1 | 2 | 0 | 0 | – |
| `date-picker` | Tiempo (chronos · fecha/hora) | 0% | 2 | 0 | 0 | 0 | 2 | 0 | 0 | – |
| `sticky` | Superficies · overlays · estado | 0% | 2 | 0 | 1 | 0 | 1 | 0 | 1 | – |
| `text-blur` | Texto · tipografía | 0% | 2 | 0 | 0 | 0 | 2 | 0 | 0 | – |
| `cascade` | Menús · listas · navegación | 0% | 1 | 0 | 0 | 0 | 1 | 0 | 0 | – |
| `motion` | Superficies · overlays · estado | 0% | 1 | 0 | 0 | 0 | 1 | 0 | 0 | – |
| `section` | Layout (primitivos) | 0% | 1 | 0 | 0 | 0 | 1 | 0 | 4 | – |
| `chronos` | Tiempo (chronos · fecha/hora) | 1% | 245 | 2 | 22 | 202 | 12 | 7 | 9 | y |
| `prose` | Texto · tipografía | 1% | 74 | 1 | 0 | 43 | 30 | 0 | 2 | y |
| `nav-tree` | Menús · listas · navegación | 4% | 25 | 1 | 0 | 17 | 6 | 1 | 1 | – |
| `s-text` | Texto · tipografía | 7% | 30 | 2 | 28 | 0 | 0 | 0 | 3 | – |
| `chart` | Controles · marcas | 9% | 92 | 8 | 0 | 66 | 14 | 4 | 17 | – |
| `result` | Superficies · overlays · estado | 9% | 22 | 2 | 1 | 15 | 4 | 0 | 8 | – |
| `mockup` | Superficies · overlays · estado | 14% | 29 | 4 | 7 | 13 | 5 | 0 | 0 | – |
| `menubar` | Menús · listas · navegación | 15% | 27 | 4 | 6 | 16 | 0 | 1 | 5 | y |
| `anchor-nav` | Menús · listas · navegación | 20% | 11 | 2 | 0 | 8 | 0 | 1 | 2 | – |
| `banner` | Superficies · overlays · estado | 20% | 10 | 2 | 6 | 1 | 1 | 0 | 42 | y |
| `button` | Controles · marcas | 21% | 30 | 6 | 16 | 0 | 7 | 1 | 105 | y |
| `palabras` | WIP (tracks paralelos) | 22% | 471 | 103 | 1 | 272 | 90 | 5 | 0 | – |
| `toggle` | Controles · marcas | 22% | 28 | 6 | 17 | 1 | 3 | 1 | 119 | y |
| `date-range-field` | Tiempo (chronos · fecha/hora) | 25% | 9 | 2 | 0 | 4 | 2 | 1 | 3 | – |
| `time-range-field` | Tiempo (chronos · fecha/hora) | 25% | 9 | 2 | 0 | 4 | 2 | 1 | 3 | – |
| `surface` | Superficies · overlays · estado | 25% | 4 | 1 | 3 | 0 | 0 | 0 | 25 | – |
| `callout` | Superficies · overlays · estado | 27% | 15 | 4 | 3 | 7 | 1 | 0 | 28 | – |
| `meter` | Superficies · overlays · estado | 29% | 14 | 4 | 6 | 2 | 2 | 0 | 28 | y |
| `knob` | Controles · marcas | 29% | 27 | 7 | 4 | 9 | 4 | 3 | 0 | y |
| `onion-menu` | Menús · listas · navegación | 29% | 27 | 7 | 0 | 8 | 9 | 3 | 12 | – |
| `empty-state` | Superficies · overlays · estado | 29% | 17 | 5 | 7 | 5 | 0 | 0 | 6 | y |
| `search-field` | Campos | 31% | 14 | 4 | 5 | 0 | 4 | 1 | 17 | y |
| `password-field` | Campos | 31% | 36 | 11 | 5 | 9 | 10 | 1 | 23 | y |
| `aura` | Superficies · overlays · estado | 31% | 35 | 11 | 4 | 14 | 6 | 0 | 24 | y |
| `toggle-group` | Controles · marcas | 33% | 3 | 1 | 0 | 1 | 1 | 0 | 1 | – |
| `background` | Superficies · overlays · estado | 35% | 26 | 8 | 6 | 6 | 3 | 3 | 31 | – |
| `avatar` | Controles · marcas | 36% | 36 | 13 | 17 | 0 | 6 | 0 | 0 | y |
| `audio-player` | Media · chat | 37% | 19 | 7 | 0 | 8 | 4 | 0 | 5 | – |
| `tooltip` | Superficies · overlays · estado | 38% | 22 | 8 | 9 | 3 | 1 | 1 | 20 | y |
| `button-group` | Controles · marcas | 40% | 5 | 2 | 0 | 0 | 3 | 0 | 1 | – |
| `badge` | Controles · marcas | 41% | 22 | 9 | 10 | 1 | 2 | 0 | 65 | y |
| `popover` | Superficies · overlays · estado | 42% | 51 | 20 | 6 | 22 | 0 | 3 | 36 | y |
| `qr-code` | Controles · marcas | 43% | 7 | 3 | 0 | 0 | 4 | 0 | 10 | – |
| `navigation-menu` | Menús · listas · navegación | 44% | 38 | 15 | 1 | 13 | 5 | 4 | 26 | y |
| `waveform` | Media · chat | 45% | 11 | 5 | 1 | 1 | 4 | 0 | 10 | y |
| `color-picker` | Campos | 46% | 82 | 36 | 10 | 22 | 11 | 3 | 54 | y |
| `checkbox` | Controles · marcas | 48% | 34 | 16 | 12 | 2 | 3 | 1 | 45 | y |
| `progress` | Superficies · overlays · estado | 49% | 35 | 17 | 9 | 3 | 6 | 0 | 41 | y |
| `tag-group` | Controles · marcas | 49% | 46 | 21 | 21 | 0 | 1 | 3 | 91 | y |
| `color-swatch` | Controles · marcas | 50% | 10 | 5 | 2 | 3 | 0 | 0 | 12 | y |
| `text-scramble` | Texto · tipografía | 50% | 4 | 2 | 0 | 0 | 2 | 0 | 0 | – |
| `split-button` | Controles · marcas | 50% | 2 | 1 | 0 | 1 | 0 | 0 | 1 | y |
| `timeline` | Superficies · overlays · estado | 51% | 49 | 25 | 21 | 0 | 3 | 0 | 45 | y |
| `field` | Campos | 51% | 73 | 35 | 15 | 7 | 11 | 5 | 60 | y |
| `context-menu` | Menús · listas · navegación | 53% | 33 | 16 | 0 | 11 | 3 | 3 | 18 | – |
| `rating-group` | Controles · marcas | 53% | 16 | 8 | 4 | 1 | 2 | 1 | 25 | y |
| `metrics` | Controles · marcas | 54% | 50 | 27 | 10 | 9 | 4 | 0 | 68 | y |
| `sidebar` | Menús · listas · navegación | 55% | 45 | 23 | 0 | 14 | 5 | 3 | 50 | – |
| `drawer` | Superficies · overlays · estado | 55% | 62 | 33 | 9 | 13 | 5 | 2 | 44 | y |
| `color-field` | Campos | 56% | 16 | 9 | 0 | 2 | 5 | 0 | 22 | y |
| `image` | Controles · marcas | 57% | 35 | 20 | 2 | 1 | 12 | 0 | 22 | y |
| `dropdown-menu` | Menús · listas · navegación | 57% | 30 | 16 | 0 | 9 | 3 | 2 | 19 | – |
| `switch` | Controles · marcas | 57% | 22 | 12 | 8 | 1 | 0 | 1 | 52 | y |
| `s-text-virtual-list` | Menús · listas · navegación | 58% | 12 | 7 | 0 | 3 | 2 | 0 | 9 | – |
| `form` | Campos | 59% | 52 | 30 | 14 | 5 | 2 | 1 | 54 | y |
| `float-panel` | Superficies · overlays · estado | 59% | 53 | 29 | 3 | 12 | 5 | 4 | 28 | – |
| `slider` | Controles · marcas | 59% | 33 | 19 | 12 | 0 | 1 | 1 | 39 | y |
| `radio-cards` | Controles · marcas | 60% | 72 | 42 | 0 | 24 | 4 | 2 | 39 | y |
| `card` | Superficies · overlays · estado | 60% | 36 | 21 | 14 | 0 | 0 | 1 | 97 | y |
| `cropper` | Controles · marcas | 60% | 27 | 15 | 0 | 3 | 7 | 2 | 15 | – |
| `emoji-picker` | Campos | 61% | 32 | 17 | 0 | 8 | 3 | 4 | 17 | – |
| `pin-input` | Campos | 61% | 19 | 11 | 0 | 6 | 1 | 1 | 20 | y |
| `editable` | Campos | 63% | 44 | 25 | 12 | 1 | 2 | 4 | 56 | y |
| `text-focus` | Texto · tipografía | 63% | 8 | 5 | 0 | 1 | 2 | 0 | 0 | – |
| `spin-field` | Campos | 64% | 27 | 16 | 0 | 8 | 1 | 2 | 20 | – |
| `file-upload` | Campos | 64% | 61 | 38 | 16 | 1 | 4 | 2 | 98 | y |
| `tags-input` | Campos | 67% | 46 | 28 | 13 | 1 | 0 | 4 | 90 | y |
| `toolbar` | Menús · listas · navegación | 67% | 35 | 22 | 10 | 0 | 1 | 2 | 54 | y |
| `image-adjustments` | Controles · marcas | 67% | 18 | 10 | 0 | 4 | 1 | 3 | 12 | – |
| `text-gradient` | Texto · tipografía | 67% | 9 | 6 | 0 | 0 | 3 | 0 | 0 | – |
| `separator` | SIN FAMILIA | 67% | 6 | 4 | 0 | 0 | 2 | 0 | 3 | – |
| `select` | Campos | 69% | 72 | 45 | 14 | 3 | 3 | 7 | 101 | y |
| `dialog` | Superficies · overlays · estado | 70% | 33 | 23 | 5 | 4 | 1 | 0 | 37 | y |
| `image-picker` | Campos | 71% | 20 | 12 | 0 | 1 | 4 | 3 | 13 | – |
| `pagination` | Menús · listas · navegación | 71% | 26 | 17 | 7 | 0 | 0 | 2 | 34 | y |
| `stepper` | Menús · listas · navegación | 71% | 60 | 40 | 15 | 0 | 1 | 4 | 69 | y |
| `skip-link` | Superficies · overlays · estado | 71% | 8 | 5 | 0 | 0 | 2 | 1 | 8 | – |
| `date-field` | Tiempo (chronos · fecha/hora) | 73% | 11 | 8 | 3 | 0 | 0 | 0 | 21 | y |
| `time-field` | Tiempo (chronos · fecha/hora) | 73% | 11 | 8 | 3 | 0 | 0 | 0 | 21 | y |
| `calendar` | Tiempo (chronos · fecha/hora) | 75% | 71 | 51 | 13 | 0 | 4 | 3 | 76 | y |
| `accordion` | Superficies · overlays · estado | 77% | 65 | 49 | 10 | 0 | 5 | 1 | 76 | y |
| `radio-group` | Controles · marcas | 77% | 75 | 56 | 10 | 7 | 0 | 2 | 61 | y |
| `chat-log` | Media · chat | 77% | 42 | 30 | 0 | 4 | 5 | 3 | 31 | – |
| `chat-composer` | Media · chat | 79% | 44 | 31 | 0 | 3 | 5 | 5 | 31 | – |
| `chat-message` | Media · chat | 82% | 84 | 63 | 2 | 6 | 6 | 7 | 75 | y |
| `fab` | Controles · marcas | 82% | 17 | 14 | 0 | 2 | 1 | 0 | 10 | – |
| `toast` | Superficies · overlays · estado | 83% | 42 | 35 | 6 | 0 | 1 | 0 | 85 | – |
| `text-circular` | Texto · tipografía | 83% | 6 | 5 | 0 | 1 | 0 | 0 | 0 | – |
| `tabs` | Menús · listas · navegación | 88% | 76 | 66 | 6 | 2 | 1 | 1 | 79 | y |
| `chat-typing` | Media · chat | 89% | 9 | 8 | 0 | 1 | 0 | 0 | 7 | – |
| `breadcrumb` | Menús · listas · navegación | 90% | 23 | 18 | 2 | 0 | 0 | 3 | 28 | y |
| `collapsible` | Superficies · overlays · estado | 90% | 12 | 9 | 0 | 1 | 0 | 2 | 11 | – |
| `scroll-area` | Superficies · overlays · estado | 94% | 17 | 15 | 0 | 0 | 1 | 1 | 13 | – |
| `splitter` | Superficies · overlays · estado | 100% | 19 | 18 | 0 | 0 | 0 | 1 | 16 | – |
| `chat-list` | Media · chat | 100% | 18 | 18 | 0 | 0 | 0 | 0 | 18 | – |
| `box` | Layout (primitivos) | 100% | 9 | 9 | 0 | 0 | 0 | 0 | 43 | – |
| `barcode` | Controles · marcas | 100% | 5 | 5 | 0 | 0 | 0 | 0 | 7 | – |
| `flex` | Layout (primitivos) | 100% | 2 | 2 | 0 | 0 | 0 | 0 | 7 | – |
| `grid` | Layout (primitivos) | 100% | 2 | 2 | 0 | 0 | 0 | 0 | 13 | – |
| `alert-dialog` | Superficies · overlays · estado | — | 0 | 0 | 0 | 0 | 0 | 0 | 0 | – |
| `auto-grid` | Layout (primitivos) | — | 0 | 0 | 0 | 0 | 0 | 0 | 0 | – |
| `container` | Layout (primitivos) | — | 0 | 0 | 0 | 0 | 0 | 0 | 1 | – |
| `css-field` | Campos | — | 0 | 0 | 0 | 0 | 0 | 0 | 0 | – |
| `float` | Superficies · overlays · estado | — | 0 | 0 | 0 | 0 | 0 | 0 | 1 | – |
| `group` | Layout (primitivos) | — | 0 | 0 | 0 | 0 | 0 | 0 | 1 | – |
| `highlight` | Controles · marcas | — | 0 | 0 | 0 | 0 | 0 | 0 | 0 | – |
| `icon` | Controles · marcas | — | 0 | 0 | 0 | 0 | 0 | 0 | 2 | – |
| `mask-field` | Campos | — | 0 | 0 | 0 | 0 | 0 | 0 | 0 | – |
| `number-field` | Campos | — | 0 | 0 | 0 | 0 | 0 | 0 | 0 | – |
| `stack` | Layout (primitivos) | — | 0 | 0 | 0 | 0 | 0 | 0 | 0 | – |
| `wrap` | Layout (primitivos) | — | 0 | 0 | 0 | 0 | 0 | 0 | 0 | – |