` desnudos del consumidor: 10 nodos y
ninguno era el panel — 9 de 19 knobs fuera del diff); **el guard cerraba el
panel que medía** (abre por `pointerenter`, y el aparcado del puntero en (0,0)
dispara el cierre) dando falso negativo Y falso positivo a la vez; y `color`
está EN TRANSICIÓN en esta parte, así que forzar `data-disabled` y leer en el
acto devuelve el valor viejo — la trampa del cuentagotas, en otro componente.
- 2026-08-23 — **`audio-player` 37 % → 56 %** (3 claves) **y el instrumento
medía CERO nodos**. El 44 % restante es préstamo con dueño (ocho filas
`--media-player-*`): es la piel de audio de ese chasis y se tema en su ficha.
Acuñado lo único que añade sobre el chasis: el peso del título y la insignia
LIVE (peso + tracking); los dos `600` pasan a `var(--font-weight-semibold)`.
**Tres cegueras encadenadas**: `/uix/components/audio-player` es un **404** —el
CUARTO canónico sin ruta—; sus partes son `data-media-player-*`, no
`data-audio-player-*` (con `extraNodes`, la sonda pasa de **0 a 48 nodos**); y
sólo existe tras el chip `media: audio` de la demo del chasis (sonda y guard lo
pulsan ahora, y el guard barre las cuatro variantes). Con eso, 0/8 → 6/8.
- 2026-08-23 — **COLA PEQUEÑA: seis componentes, cero claves nuevas.** `section`
(— · cuatro claves RESUCITADAS), `sticky` 0 → **100 %**, `button-group` 40 →
**100 %**, `qr-code` 43 → **100 %**, `toggle-group` 33 → **50 %** (su techo) y
`split-button` ADJUDICADO en 50 % (su techo). Global 65 %; **25 componentes al
100 %** y los de alcance <20 % bajan de 14 a 12.
**El hallazgo está en `section`: la receta TAPABA sus propias claves públicas.**
Declaraba los cuatro pasos de relleno en el host
(`[data-box][data-section] { --section-padding-block-sm: … }`), y esa
declaración gana a la que el contrato emite en `:root`: un tema que escribiera
`--section-padding-block-lg` perdía contra la receta. Borrado el bloque —mismos
valores, una sola fuente—, computado idéntico (48px antes y después), y las
cuatro claves alcanzan.
Lo demás es **identidad**: once `100 %` entre las seis recetas y el centinela
de 2px del sticky —el hilo invisible que el observador vigila—, todos con su
razón escrita. Más un respaldo muerto retirado en `toggle-group`, sobre un
token PRESTADO de `toggle` (el velo de un grupo deshabilitado es el del
toggle, y se tema en su ficha).
**Y una clase de adjudicación nueva, que se repetirá: UN PASO POR INSTANCIA.**
`section` y `qr-code` mapean su prop de talla a `var(--{c}-{eje}-{k})` y la
escriben INLINE, así que sólo el paso ACTIVO alcanza; los otros cuatro leen
muertos hasta que la prop cambia. No es deuda ni ceguera del instrumento: es
cómo funciona una escala resuelta por prop.
Gates: seis guards en verde · censo · audit PASS · suite con el rojo conocido
ajeno · rtl 0 · docs 0.
- 2026-08-23 — **`tooltip` 52 % → 75 %** (3 claves, 4 literales anotados) **y el
plano `overlay` ANULA SUS TRES VARIANTES**. Global 65 %.
Acuñados el desenfoque del velo `ghost` y las dos tintas de la flecha
`outline`. **No se acuñó `ghost-bg`**: lo intenté, el centinela lo delató y se
retiró antes de commitear.
**⚠⚠ El plano no sólo se queda la tipografía: se queda el fondo, el borde y la
sombra.** Medido: `--tooltip-bg`/`-border`/`-shadow` no mueven nada,
`--depth-overlay-*` repinta. Y la consecuencia visual es peor que la contable:
`solid`, `outline` y `ghost` computan lo MISMO — `outline` es indistinguible
de `solid`. → §13. Las cinco claves quedan adjudicadas, no retiradas: son la
fuente de la máquina de variantes.
Instrumento: el tooltip abre por HOVER (`openBy: 'hover'`, como link-preview) —
0/24 → 14/24—, y el resto se midió con el interruptor `open` de la demo, porque
un panel abierto por puntero exige el ratón quieto toda la pasada.
- 2026-08-23 — **`time-range-field` 29 % → 100 %** (4 claves), gemelo exacto de
`date-range-field` **defecto incluido**: la misma clave `row-gap` alimentando
el `column-gap`. Global **64 % → 65 %**.
Que los dos gemelos tuvieran el MISMO nombre equivocado dice algo: el error no
se coló al escribir, se copió al duplicar. **Donde hay un par, el defecto viene
en par** — mirar al gemelo es parte de la pasada.
- 2026-08-23 — **`date-range-field` 29 % → 100 %** (4 claves, una RENOMBRADA
porque mentía). Centinela 7/7.
**`row-gap` alimentaba el `column-gap`**: la clave pública movía el hueco entre
los dos campos, y el de fila —etiqueta ↔ campos— leía `--space-1-5` a pelo.
Dos claves ahora, cada una con el nombre de lo que alimenta, y **ningún
computado se mueve**. Un nombre equivocado es una perilla que gira otra cosa.
**La etiqueta se acuña con fecha de caducidad**: la raíz del rango NO es un
`[data-field]` —lo dice la propia receta— así que no puede heredar la etiqueta
de field.css y repetía los valores de la fundación. Nombrados aquí, y escrito
en el contrato que el mandato §5.3-3 los borra cuando la raíz sea un campo.
- 2026-08-23 — **`surface` ADJUDICADO: el 25 % es su techo**, cero claves nuevas.
Es la cara de PINTURA de Box y lo que pinta no es suyo: `bg` y `fg` salen del
puente de paleta (THM-2) y el acabado es canal de valor del generador (§39).
La rama `inherit` del `fg` suave es intencionada y está escrita en la receta.
**Pero no tiene ruta**: `/uix/components/surface` es un 404 y el guard medía
una página VACÍA — 0/25, incluido un `radius` vivísimo. Apuntado a
`/temas/gradientes` + `/blocks/cta`: 1/25, y el que mueve es el radio. Ya son
TRES los canónicos sin demo (picker-shell, mockup, surface) → §13.
Sus 24 claves de tono son la supersesión de paleta de hoy: patrón compartido.
- 2026-08-23 — **`banner` 30 % → 100 %** (11 claves) **y el guard pasa de 4/42 a
53/53**: sus 38 «muertos» estaban vivos, sólo que nadie los había mirado con
el atributo puesto. Global 64 %.
Cosida la densidad por talla, la interlínea y el trazo del anillo de
`outline` —la última fila que impedía al privado del borde derivar—. Dos
ausencias firmadas: los `transparent` de `outline`/`ghost` y los
`border-width: 0`, con el criterio de button.
**Dos cegueras del instrumento, arregladas**: (1) su paleta resuelve por
`data-intent`, no por `data-color`, y el barrido de tono estampaba sólo el
segundo — ahora estampa los dos nombres; (2) y luego por VARIANTE, así que el
guard recorre `data-variant` con `sweepAttr`. Es la diferencia entre «38
tokens que mienten» y «38 que nadie había mirado con el atributo puesto».
Gates: sonda 0 diffs en 192 valores × 7 estados · centinela 53/53 · censo
100 % · audit PASS · suite con el rojo conocido ajeno · rtl 0 · docs 0 ·
captura de cuatro variantes × cuatro intenciones.
- 2026-08-23 — **`anchor-nav` 20 % → 100 %** (11 claves) **y el censo aprende los
bordes POR LADO**. Global 64 %.
Tenía dos knobs y todo lo demás a pelo: la escala (que ahora lee el bundle),
el relleno y el radio del enlace, sus tres tintas, el peso del activo y las dos
tintas del RAÍL, que es lo que da nombre al componente.
**El raíl activo era INVISIBLE para la medida**: su color vive en un
`border-inline-start-color` y `KNOB_PROPS` sólo conocía `border-color` y los
shorthands. El centinela mira esos longhands desde el 2026-08-22 (los añadió
cuando prose y nav-tree leyeron muertos); el censo no. Añadidos los ocho por
lado, color y grosor: **+30 filas en el catálogo** (5.101 → 5.131) y esta ficha
baja a 18 % antes de coserse — el censo promete sobre-reportar, NUNCA
infra-reportar.
La tinta de reposo del raíl estaba escondida de otra manera: dentro de un
shorthand que el censo clasifica por el PRIMER token que casa (el trazo, ya
público). No hizo falta partirlo: basta nombrar el color dentro.
**Un susto útil**: una coma que faltaba en el contrato rompió el build de
tokens y lo delató la SONDA midiendo 0 nodos — la página no renderizaba. El
recuento de nodos es el canario.
Gates: sonda 0 diffs en 1.760 valores × 7 estados · centinela 11/12 · censo
100 % · audit PASS · suite con el rojo conocido ajeno · rtl 0 · docs 0.
- 2026-08-23 — **`image` 60 % → 96 %** (1 clave, 12 literales anotados) **y dos
instrumentos que morían en esta página**. Global 64 %.
Su deuda era casi toda IDENTIDAD: once `100 %` (la imagen, el fallback, el
error y sus dos `
` llenan su caja) y un `opacity: 1` (una imagen cargada
es opaca). Lo acuñado es la barra del esqueleto, que leía `--gradient-shimmer`
a pelo.
**La página NO alcanza `networkidle` NUNCA** —monta un `src` roto a propósito
para su estado de error— y sonda y guard morían con `TimeoutError` antes de
medir un nodo. Las dos caen ahora al evento `load` si la espera se agota.
**Un token bajo `@media (prefers-reduced-motion: reduce)` lee muerto**:
`placeholder-base` sólo existe ahí. Emulando la preferencia, alcanza — y vale
para cualquier token detrás de una media query de preferencia.
**Lectura fantasma cazada por repetición**: el primer diff acusó
`opacity: 0.925793 → 1` en la imagen cargada; era el fade EN VUELO, como el rim
animado de `onion-menu`. Repetida la medida, 0 diffs.
Gates: sonda 0 diffs en 544 valores × 7 estados (repetida) · centinela 20/23 ·
censo 96 % · audit PASS · suite con el rojo conocido ajeno · rtl 0 · docs 0.
- 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-subtle`, 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 | – |