docs(theming): la auditoría de alcance de tema, componente a componente, con su propuesta
El censo medía el eje y no lo explicaba: 5.205 knobs en dos tablas del plan no
dicen QUÉ knob de QUÉ línea no alcanza un tema, ni qué token habría que crear.
Ahora `theming-census.ts --report` escribe la auditoría entera bajo
`docs/audit/theming/`: un README con la vista de conjunto y 170 fichas — 162
recetas con CSS + 8 componentes sin receta, el árbol completo de
`eidos/components/`.
Cada ficha de receta: knobs fuera de alcance con fichero:línea Y selector
(agrupados por clase), sistema transversal aparte, los privados con la columna
que decide («¿deriva de un público?»), y una PROPUESTA de corrección — el token
a declarar en `base.ts` con su valor VERBATIM y su scope TSC. La propuesta
deriva los nombres de recipe-contract §1 y theming §6.7; donde la doctrina no
decide, marca `⚠ decisión` en vez de inventar. Y no propone acuñar lo que la
doctrina prohíbe: lo que posee una capa compartida, el foco, la capa de estado,
un token prestado de otra receta, un shorthand o un eje físico.
Las 8 fichas sin receta dicen —medido, no supuesto— dónde vive su visual: el
componente que componen (icon-button → button), la capa que consumen (affix →
viewport-placement) o la receta ajena que pinta sus attrs (svg → badge/button).
Defectos del instrumento corregidos en el mismo pase, todos encontrados
mirando la salida: un `@import` pegado al primer selector se comía 2 knobs de
color-picker (el suelo del censo no puede moverse); `:not(:disabled)` se leía
como estado y producía `hover-disabled-*`; un knob que lee un privado se
proponía a sí mismo en vez de resolverse por talla; `--icon-size-sm` se
reportaba como préstamo del componente `icon` (ahora el préstamo se verifica
contra las claves del dueño en `base.ts`); y el default de talla salía sin
nombrar en vez de `-md`.
Verificación: censo global idéntico al suelo publicado (5205 · 1621/33% · 856 ·
1880 · 614 · 234) y COMPONENTE A COMPONENTE contra la tabla §9 del plan — 0
diferencias en 162 · regenerar dos veces da el árbol idéntico · el bloque de
veredicto escrito a mano sobrevive · docs:check 0 errores sobre 813 docs ·
prettier limpio (el árbol generado entra en .prettierignore junto a
eidos/generated).
Las 10 primeras fichas llevan ya su veredicto de revisión: análisis correcto en
las 10, propuesta apta en 2 (gradient-builder como piloto, combobox con cinco
correcciones — dos de ellas evitaban romper el default), y 5 que no se
tokenizan en solitario porque son alias de --calendar-*/--field-* y esperan la
decisión de familia. Cuatro destaparon privados con prefijo ajeno o abreviado
declarados en su propio CSS.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
# Auditoría de alcance de tema — el catálogo entero
> **Generado**, no escrito a mano: `node --import tsx/esm scripts/theming-census.ts --report`.
> Este README es la vista de conjunto; **una ficha por componente** al lado, con
> su análisis y su **propuesta de corrección**. Método, clases, protocolo de
> verificación y fases: [`PLAN-theming.md`](../../process/PLAN-theming.md).
> La auditoría del SISTEMA de theming (fase 1, cerrada 2026-07-07) es
> [`theming-audit.md`](../theming-audit.md); ésta es la deuda de adopción que
> aquélla dejó apuntada en su §5.3-3.
uix(combobox): el campo y su panel pasan a tokens públicos, con la talla resuelta donde manda
Segundo del eje theme-reach. El combobox tenía UN token propio (`content-z`) y
todo lo demás atado a primitivos globales o enterrado en privados: alcance 0 %.
Ahora son 106 claves públicas y el 76 % medido — lo que queda fuera son tres
hovers que esperan firma, seis literales de layout y doce knobs que pasan por
privados que ya derivan de un público.
La talla sigue el canon de dos piezas (coordenada + nombre resuelto), pero con
una diferencia que el DOM impone: los resueltos del control se emiten sobre
`control` e `input`, no sobre el root, porque el `data-size` que manda vive en el
control — y el input suelto lo necesita fuera de él. Los del panel se emiten
sobre `content`, que viaja por portal y nunca vería un token del root. Es el
precedente de `select` aplicado donde toca.
Altura, tipografía y separación del control consumen la coordenada del bundle
`--size-{k}-*`; el relleno inline SE DESVÍA del bundle en cuatro tallas y
conserva su valor de hoy — la desviación queda visible en el contrato en vez de
redondearse a la coordenada, que habría sido un cambio visual disfrazado de
limpieza. El chip conserva sus expresiones (`control-height − inset`,
`control-font-size − offset`), así que mover el control sigue arrastrándolo.
El centinela cazó un fallo real a mitad del trabajo: la primera pasada dejó
vivos los ocho bloques `[data-…][data-size='…']` de la receta, que pisaban los
tokens nuevos con los valores viejos. El diff de computed daba cero JUSTAMENTE
porque la ruta vieja seguía mandando; sin centinela habría pasado por bueno.
Verificación: diff de computed vacío sobre 1.566 valores en ocho estados —
reposo, las cinco tallas, el panel ABIERTO y hover. Centinela 67/106 automático
y el resto verificado a mano: `content-z` alcanza (80 → 4321) aunque viva en el
wrapper flotante; placeholder, disabled e ink del trigger forzando su estado;
los del panel abriéndolo por teclado. Los siete nombres resueltos no se mueven
por diseño — el tema mueve la coordenada. Los catorce `selected-tag-*`, los tres
`separator-*` y `scrollbar-inset` no son verificables en esta demo (no monta
modo múltiple, ni separadores, ni scroll): queda dicho, con su consumidor
comprobado en la receta, en vez de darlos por buenos.
Un token nace inerte y se anota como tal: `content-font-family` y
`content-line-height` los pisa `[data-depth='overlay']` con la misma
especificidad — es la tipografía de portal del Build contract, y tocarla sería
otro eje.
Guards: component:audit PASS · eidos-lint 0 invalid · suite eidos sin rojos
nuevos · rtl:check 0 · docs:check 0 · el guard del bundle obligó a apuntar
`indicator-size` e `item-indicator-size` a `--size-sm-icon-size`.
El informe `docs/audit/theming/` se regenera entero, así que todas las fichas
actualizan su fecha de medida; las que cambian de contenido son combobox y
gradient-builder.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
- **Medido**: 2026-08-20 · **162 recetas** con CSS + **8 componentes sin receta** = 170 fichas, el árbol entero de `eidos/components/`
docs(theming): la auditoría de alcance de tema, componente a componente, con su propuesta
El censo medía el eje y no lo explicaba: 5.205 knobs en dos tablas del plan no
dicen QUÉ knob de QUÉ línea no alcanza un tema, ni qué token habría que crear.
Ahora `theming-census.ts --report` escribe la auditoría entera bajo
`docs/audit/theming/`: un README con la vista de conjunto y 170 fichas — 162
recetas con CSS + 8 componentes sin receta, el árbol completo de
`eidos/components/`.
Cada ficha de receta: knobs fuera de alcance con fichero:línea Y selector
(agrupados por clase), sistema transversal aparte, los privados con la columna
que decide («¿deriva de un público?»), y una PROPUESTA de corrección — el token
a declarar en `base.ts` con su valor VERBATIM y su scope TSC. La propuesta
deriva los nombres de recipe-contract §1 y theming §6.7; donde la doctrina no
decide, marca `⚠ decisión` en vez de inventar. Y no propone acuñar lo que la
doctrina prohíbe: lo que posee una capa compartida, el foco, la capa de estado,
un token prestado de otra receta, un shorthand o un eje físico.
Las 8 fichas sin receta dicen —medido, no supuesto— dónde vive su visual: el
componente que componen (icon-button → button), la capa que consumen (affix →
viewport-placement) o la receta ajena que pinta sus attrs (svg → badge/button).
Defectos del instrumento corregidos en el mismo pase, todos encontrados
mirando la salida: un `@import` pegado al primer selector se comía 2 knobs de
color-picker (el suelo del censo no puede moverse); `:not(:disabled)` se leía
como estado y producía `hover-disabled-*`; un knob que lee un privado se
proponía a sí mismo en vez de resolverse por talla; `--icon-size-sm` se
reportaba como préstamo del componente `icon` (ahora el préstamo se verifica
contra las claves del dueño en `base.ts`); y el default de talla salía sin
nombrar en vez de `-md`.
Verificación: censo global idéntico al suelo publicado (5205 · 1621/33% · 856 ·
1880 · 614 · 234) y COMPONENTE A COMPONENTE contra la tabla §9 del plan — 0
diferencias en 162 · regenerar dos veces da el árbol idéntico · el bloque de
veredicto escrito a mano sobrevive · docs:check 0 errores sobre 813 docs ·
prettier limpio (el árbol generado entra en .prettierignore junto a
eidos/generated).
Las 10 primeras fichas llevan ya su veredicto de revisión: análisis correcto en
las 10, propuesta apta en 2 (gradient-builder como piloto, combobox con cinco
correcciones — dos de ellas evitaban romper el default), y 5 que no se
tokenizan en solitario porque son alias de --calendar-*/--field-* y esperan la
decisión de familia. Cuatro destaparon privados con prefijo ajeno o abreviado
declarados en su propio CSS.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
- **La pregunta**: ¿cuánto de la apariencia de cada componente puede cambiar un tema **sin tocar el sistema ni la receta** ?
feat(census): los primitivos tipográficos se miden contra su capa — pieza 0 de F2-A
D-TH.2-b, la firma que va ANTES del bloque porque cambia el suelo del censo:
medirla a mitad de camino falsearía todos los antes/después.
`heading` marcaba «36 knobs, 0 % alcanzable» y eso no era deuda: era una
lectura equivocada. Su receta resuelve cada eje como
`var(--_heading-font-size, var(--style-h2-font-size))` — el privado es el
escape POR INSTANCIA que el wrapper escribe desde una prop, y el named style es
la superficie de tema, ya pública y viva. Acuñar `--heading-*` para espejarla
sería un alias por eje × nivel: la clase que mató la purga del changelog §39.
El criterio de qué ES un primitivo tipográfico se midió, no se supuso: o la
receta SELECCIONA por `data-style` (`heading`, `text`, `s-text` — el named
style es su API) o está atada entera a UN style (`code` → `--style-code-*`,
`display` → `--style-hero-*`, `label` → `--style-label-*`). `code-block` queda
FUERA a propósito: lee un par de tokens de style para su texto pero posee
cromo de caja real, y eso sí es suyo.
Detalle que costó una vuelta: la comprobación va ANTES de la de privado. Leer
el privado primero puntúa el primitivo entero como inalcanzable cuando es
completamente temable — por la capa que lo posee.
antes 5.199 knobs · 1.837 públicos (37 %) · 894 privados · 232 sistema
después 5.199 knobs · 1.837 públicos (38 %) · 788 privados · 338 sistema
**Gate**: 106 knobs pasan de `private` a `system` en los SEIS primitivos y
**cero** de los otros 156 se mueve — verificado componente a componente contra
la versión en HEAD, no a ojo. Alcance `—` (nada que poseer) para heading, text
y display; `s-text` al 100 %; `code` y `label` bajan a 7 y 2 knobs de deuda
real.
Informe regenerado (171 veredictos a mano intactos), veredicto de heading
anotado como ejecutado, y recipe-contract §1 gana el párrafo que fija el
criterio — incluida la frontera: un menú que lee `--style-label-font-family`
para una etiqueta NO es un primitivo y no entra en el conjunto.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
- **Alcance global**: **38%** — 1837 de 4861 knobs pasan por un token público del componente
- **Reparto**: público 1837 · privado 788 · global 1633 · literal 603 · sistema transversal 338 _(fuera del ratio)_
- **Sin token público propio**: 56 · **alcance < 20 %** : 51 · **alcance 100 %** : 7 · **con eje `size`** : 79
docs(theming): la auditoría de alcance de tema, componente a componente, con su propuesta
El censo medía el eje y no lo explicaba: 5.205 knobs en dos tablas del plan no
dicen QUÉ knob de QUÉ línea no alcanza un tema, ni qué token habría que crear.
Ahora `theming-census.ts --report` escribe la auditoría entera bajo
`docs/audit/theming/`: un README con la vista de conjunto y 170 fichas — 162
recetas con CSS + 8 componentes sin receta, el árbol completo de
`eidos/components/`.
Cada ficha de receta: knobs fuera de alcance con fichero:línea Y selector
(agrupados por clase), sistema transversal aparte, los privados con la columna
que decide («¿deriva de un público?»), y una PROPUESTA de corrección — el token
a declarar en `base.ts` con su valor VERBATIM y su scope TSC. La propuesta
deriva los nombres de recipe-contract §1 y theming §6.7; donde la doctrina no
decide, marca `⚠ decisión` en vez de inventar. Y no propone acuñar lo que la
doctrina prohíbe: lo que posee una capa compartida, el foco, la capa de estado,
un token prestado de otra receta, un shorthand o un eje físico.
Las 8 fichas sin receta dicen —medido, no supuesto— dónde vive su visual: el
componente que componen (icon-button → button), la capa que consumen (affix →
viewport-placement) o la receta ajena que pinta sus attrs (svg → badge/button).
Defectos del instrumento corregidos en el mismo pase, todos encontrados
mirando la salida: un `@import` pegado al primer selector se comía 2 knobs de
color-picker (el suelo del censo no puede moverse); `:not(:disabled)` se leía
como estado y producía `hover-disabled-*`; un knob que lee un privado se
proponía a sí mismo en vez de resolverse por talla; `--icon-size-sm` se
reportaba como préstamo del componente `icon` (ahora el préstamo se verifica
contra las claves del dueño en `base.ts`); y el default de talla salía sin
nombrar en vez de `-md`.
Verificación: censo global idéntico al suelo publicado (5205 · 1621/33% · 856 ·
1880 · 614 · 234) y COMPONENTE A COMPONENTE contra la tabla §9 del plan — 0
diferencias en 162 · regenerar dos veces da el árbol idéntico · el bloque de
veredicto escrito a mano sobrevive · docs:check 0 errores sobre 813 docs ·
prettier limpio (el árbol generado entra en .prettierignore junto a
eidos/generated).
Las 10 primeras fichas llevan ya su veredicto de revisión: análisis correcto en
las 10, propuesta apta en 2 (gradient-builder como piloto, combobox con cinco
correcciones — dos de ellas evitaban romper el default), y 5 que no se
tokenizan en solitario porque son alias de --calendar-*/--field-* y esperan la
decisión de familia. Cuatro destaparon privados con prefijo ajeno o abreviado
declarados en su propio CSS.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
## Cómo se lee
| clase | qué es | ¿lo alcanza un tema del componente? |
| --- | --- | --- |
| `public` | `var(--{c}-…)` , el contrato del componente | **sí** |
| `private` | `var(--_{c}-…)` , nombre interno | sólo si el privado deriva de un público (cada ficha lo dice en §3) |
| `global` | primitivo del sistema (`--space-*`, `--radius-*` , `--color-*` , bundle `--size-{k}-*` …) | sólo moviendo el sistema entero |
| `literal` | ni token: `8px` , `1.25` , `#fff` | no — y viola R-2/R-4 |
| `system` | sistemas transversales que la receta CONSUME por contrato (capa de estado, anillo de foco, planos de depth, motion, bandas z, opacidad, shape, floating-gap) | sí, **a nivel de sistema** , por diseño (recipe-contract §2) — fuera del ratio |
**Alcance** = `public / (public + private + global + literal)` .
**Límites de la medida** (regex sobre el CSS; sobre-reporta, nunca infra-reporta):
una declaración con varios tokens se clasifica por la primera clase que casa
(público → privado → sistema → global); el token público de OTRO componente
cuenta como `global` y la ficha lo marca «⤴ prestado»; los valores dentro de
`@keyframes` cuentan como cualquier otro. Tres defectos que ningún regex ve —
privado que no deriva, velo en el nodo equivocado, doble animación — van en la
checklist §4.4 de cada ficha.
## Qué NO propone una ficha
La propuesta deriva nombres de la doctrina; **no la contradice** . Por eso una
ficha nunca propone acuñar un token para:
- **lo que posee una capa compartida** (`list-surface`, `spin-field` ,
`picker-shell` , `viewport-placement` , `field-segment-state` ,
`menu-indicator` , `sliding-indicator` ): un eje = un token público de la capa
+ una ranura privada, consumido `var(--_x, var(--x))` — el consumidor no acuña
`--{c}-{eje}` (README de `eidos/components` , «Capas compartidas» regla 2);
- **el foco** (`--focus-ring-*`, theming §32) ni **la capa de estado**
(`--state-*`, §38): un knob del sistema, no del componente;
- **un token prestado de otro componente** (la familia `calendar` en los
pickers): la corrección es la decisión de familia registrada en
[`theming-audit.md` ](../theming-audit.md ) §B, no un duplicado con prefijo propio;
- **un shorthand o un eje físico** (`padding`, `border` , `height` ): primero se
parte en ejes lógicos (recipe-contract §1, R-4.4), y eso es decisión.
## Sin receta CSS (8)
Ni un `.css` en su directorio: **no hay knob que medir** , y eso es una
respuesta, no un hueco. Cada ficha dice —medido, no supuesto— dónde vive su
visual: el componente que compone, la capa compartida que consume, o la receta
ajena que pinta sus attrs (y cuyos knobs ya están contados allí).
[`affix` ](./affix.md ) · [`count-up` ](./count-up.md ) · [`format-date` ](./format-date.md ) · [`format-number` ](./format-number.md ) · [`icon-button` ](./icon-button.md ) · [`relative-time` ](./relative-time.md ) · [`svg` ](./svg.md ) · [`trans` ](./trans.md )
Y el **vocabulario de nombres tiene una desviación medida** : el catálogo habla
mayoritariamente con el modificador al final (`-bg-hover`, `-bg-active` ) mientras
theming §6.7 lo pone delante (`hover-bg`). Las fichas proponen la forma
**documentada** y lo dejan anotado: la normalización es **D-TH.6** , sin firmar.
## Los 20 con más knobs fuera del contrato
| # | componente | fuera de alcance | alcance | knobs | contrato |
| ---: | --- | ---: | ---: | ---: | ---: |
| 1 | [palabras ](./palabras.md ) | 363 | 22% | 471 | 0 |
| 2 | [chronos ](./chronos.md ) | 236 | 1% | 245 | 9 |
| 3 | [range-calendar ](./range-calendar.md ) | 95 | 0% | 98 | 0 |
uix(time-range-picker): el reloj de dos columnas y la franja AM/PM pasan a tokens
Sexto del eje theme-reach, y gemelo de time-picker: mismo reparto, mismas
razones. A contrato lo que el componente inventa — el reloj de dos columnas (su
separación, ancho, tinta y tipografía), los colores de las tres manecillas y la
franja AM/PM entera — y sin tocar el lado con forma de campo, que lee `--field-*`
porque compone Field.
Y el mismo defecto de prefijo que su gemelo: 56 referencias declaraban
`--_time-field-*` dentro de este CSS (más una mención en el wrapper). Renombradas
a `--_time-range-picker-*`, con el diff de computed en cero.
Dos cosas que la revisión había marcado como acuñables y NO lo son, confirmadas
al ejecutar: el realce del reloj al puntero lee `--toggle-palette-solid`, que es
la paleta de otro componente — si procede, es un bloque de composición cruzada,
y eso es decisión, no corrección; y el `padding-inline` del raíl consume el
tamaño del pulgar del Slider, un eje que publica su dueño o no se publica.
Verificación: diff de computed vacío sobre 725 valores en ocho estados ·
component:audit PASS · suite eidos sin rojos nuevos · rtl:check 0 · docs:check 0.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| 4 | [chart ](./chart.md ) | 80 | 9% | 92 | 17 |
| 5 | [proof-of-human ](./proof-of-human.md ) | 78 | 14% | 95 | 20 |
| 6 | [prose ](./prose.md ) | 73 | 1% | 74 | 2 |
| 7 | [time-range-picker ](./time-range-picker.md ) | 68 | 19% | 88 | 22 |
uix(natural-time-picker): el cromo de la banda se puede temar, y el cielo sigue siendo el cielo
Tercero del eje theme-reach. La receta ataba todo a primitivos globales y
guardaba su geometría en privados con un prefijo abreviado, `--_ntp-*`, que ni
el censo veía ni el vocabulario permite: alcance 0 %. Ahora son 60 claves
públicas y el 61 % medido.
Dos de los tres bloqueos que la revisión había anotado no existían: la doctrina
ya estaba escrita y no la había leído. El guard de recetas ya lista este
componente en la excepción de TONO FIJO — un cielo no cambia con el tema, y sus
literales ya llevaban su válvula línea a línea, así que los cielos, la tinta del
sol/luna y la línea de posición se quedan privados y anotados, sin decisión que
pedir. Y el panel sigue leyendo `--popover-*` porque su propia cabecera dice que
esa superficie ES el flotante canónico: duplicarla con prefijo propio habría
sido el vocabulario paralelo que el contrato prohíbe. De ahí que el 39 % restante
no sea deuda sino préstamo deliberado.
Lo que sí es suyo pasa a contrato: banda y knob por talla con `parts: ['panel']`
—conservando su derivación de la altura de control, así que la expresión sigue
siendo el knob y mover la talla arrastra ambos—, la línea indicadora, los ticks,
el readout (hora, meridiem, periodo), los steppers, los chips y el trigger. Más
el `panel-gap`, que sí es del panel y no del popover.
Las 37 referencias `--_ntp-*` mueren: el prefijo de un privado es el nombre
completo del componente (theming §6 regla 5). El rename alcanza receta, wrapper,
README y el propio guard que las citaba.
Verificación: diff de computed vacío sobre 6.438 valores en ocho estados.
Centinela 40/62 automático, y cada uno de los marcados muertos verificado a
mano: banda, knob, gap del panel, línea, radio de la línea e inset de los ticks
alcanzan; los `trigger-*` NO, porque `[data-popover-trigger]` gana la cascada y
viste el trigger — ya eran inertes antes de tokenizarlos, y ahora está dicho en
el README en vez de fingir que el token pinta.
Guards: component:audit PASS · eidos-lint 0 invalid · suite eidos sin rojos
nuevos · rtl:check 0 · docs:check 0 · el guard del bundle obligó a apuntar
`tick-font-size` a la coordenada `--size-xxs-font-size`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| 8 | [month-grid ](./month-grid.md ) | 58 | 0% | 61 | 0 |
| 9 | [year-grid ](./year-grid.md ) | 58 | 0% | 61 | 0 |
| 10 | [command ](./command.md ) | 50 | 0% | 52 | 0 |
| 11 | [time-picker ](./time-picker.md ) | 47 | 18% | 59 | 16 |
| 12 | [media-player ](./media-player.md ) | 45 | 0% | 45 | 2 |
| 13 | [color-picker ](./color-picker.md ) | 43 | 46% | 82 | 54 |
| 14 | [table ](./table.md ) | 42 | 0% | 46 | 0 |
| 15 | [field-langs ](./field-langs.md ) | 39 | 0% | 41 | 0 |
| 16 | [tree-grid ](./tree-grid.md ) | 39 | 0% | 42 | 0 |
feat(census): los primitivos tipográficos se miden contra su capa — pieza 0 de F2-A
D-TH.2-b, la firma que va ANTES del bloque porque cambia el suelo del censo:
medirla a mitad de camino falsearía todos los antes/después.
`heading` marcaba «36 knobs, 0 % alcanzable» y eso no era deuda: era una
lectura equivocada. Su receta resuelve cada eje como
`var(--_heading-font-size, var(--style-h2-font-size))` — el privado es el
escape POR INSTANCIA que el wrapper escribe desde una prop, y el named style es
la superficie de tema, ya pública y viva. Acuñar `--heading-*` para espejarla
sería un alias por eje × nivel: la clase que mató la purga del changelog §39.
El criterio de qué ES un primitivo tipográfico se midió, no se supuso: o la
receta SELECCIONA por `data-style` (`heading`, `text`, `s-text` — el named
style es su API) o está atada entera a UN style (`code` → `--style-code-*`,
`display` → `--style-hero-*`, `label` → `--style-label-*`). `code-block` queda
FUERA a propósito: lee un par de tokens de style para su texto pero posee
cromo de caja real, y eso sí es suyo.
Detalle que costó una vuelta: la comprobación va ANTES de la de privado. Leer
el privado primero puntúa el primitivo entero como inalcanzable cuando es
completamente temable — por la capa que lo posee.
antes 5.199 knobs · 1.837 públicos (37 %) · 894 privados · 232 sistema
después 5.199 knobs · 1.837 públicos (38 %) · 788 privados · 338 sistema
**Gate**: 106 knobs pasan de `private` a `system` en los SEIS primitivos y
**cero** de los otros 156 se mueve — verificado componente a componente contra
la versión en HEAD, no a ojo. Alcance `—` (nada que poseer) para heading, text
y display; `s-text` al 100 %; `code` y `label` bajan a 7 y 2 knobs de deuda
real.
Informe regenerado (171 veredictos a mano intactos), veredicto de heading
anotado como ejecutado, y recipe-contract §1 gana el párrafo que fija el
criterio — incluida la frontera: un menú que lee `--style-label-font-family`
para una etiqueta NO es un primitivo y no entra en el conjunto.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| 17 | [gradient-picker ](./gradient-picker.md ) | 35 | 0% | 38 | 0 |
| 18 | [listbox ](./listbox.md ) | 35 | 0% | 38 | 0 |
| 19 | [field ](./field.md ) | 33 | 51% | 73 | 60 |
| 20 | [feed ](./feed.md ) | 32 | 0% | 33 | 0 |
## Sin ningún token público propio (56)
docs(theming): la auditoría de alcance de tema, componente a componente, con su propuesta
El censo medía el eje y no lo explicaba: 5.205 knobs en dos tablas del plan no
dicen QUÉ knob de QUÉ línea no alcanza un tema, ni qué token habría que crear.
Ahora `theming-census.ts --report` escribe la auditoría entera bajo
`docs/audit/theming/`: un README con la vista de conjunto y 170 fichas — 162
recetas con CSS + 8 componentes sin receta, el árbol completo de
`eidos/components/`.
Cada ficha de receta: knobs fuera de alcance con fichero:línea Y selector
(agrupados por clase), sistema transversal aparte, los privados con la columna
que decide («¿deriva de un público?»), y una PROPUESTA de corrección — el token
a declarar en `base.ts` con su valor VERBATIM y su scope TSC. La propuesta
deriva los nombres de recipe-contract §1 y theming §6.7; donde la doctrina no
decide, marca `⚠ decisión` en vez de inventar. Y no propone acuñar lo que la
doctrina prohíbe: lo que posee una capa compartida, el foco, la capa de estado,
un token prestado de otra receta, un shorthand o un eje físico.
Las 8 fichas sin receta dicen —medido, no supuesto— dónde vive su visual: el
componente que componen (icon-button → button), la capa que consumen (affix →
viewport-placement) o la receta ajena que pinta sus attrs (svg → badge/button).
Defectos del instrumento corregidos en el mismo pase, todos encontrados
mirando la salida: un `@import` pegado al primer selector se comía 2 knobs de
color-picker (el suelo del censo no puede moverse); `:not(:disabled)` se leía
como estado y producía `hover-disabled-*`; un knob que lee un privado se
proponía a sí mismo en vez de resolverse por talla; `--icon-size-sm` se
reportaba como préstamo del componente `icon` (ahora el préstamo se verifica
contra las claves del dueño en `base.ts`); y el default de talla salía sin
nombrar en vez de `-md`.
Verificación: censo global idéntico al suelo publicado (5205 · 1621/33% · 856 ·
1880 · 614 · 234) y COMPONENTE A COMPONENTE contra la tabla §9 del plan — 0
diferencias en 162 · regenerar dos veces da el árbol idéntico · el bloque de
veredicto escrito a mano sobrevive · docs:check 0 errores sobre 813 docs ·
prettier limpio (el árbol generado entra en .prettierignore junto a
eidos/generated).
Las 10 primeras fichas llevan ya su veredicto de revisión: análisis correcto en
las 10, propuesta apta en 2 (gradient-builder como piloto, combobox con cinco
correcciones — dos de ellas evitaban romper el default), y 5 que no se
tokenizan en solitario porque son alias de --calendar-*/--field-* y esperan la
decisión de familia. Cuatro destaparon privados con prefijo ajeno o abreviado
declarados en su propio CSS.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
Ni una clave pública en `lib/recipes/base.ts` — alguno tiene privados forward
(`_palette-*`), que no son contrato: un tema no puede nombrarlos.
[`alert-dialog` ](./alert-dialog.md ) · [`announce` ](./announce.md ) · [`aspect-ratio` ](./aspect-ratio.md ) · [`auto-grid` ](./auto-grid.md ) · [`avatar` ](./avatar.md ) · [`card-group` ](./card-group.md ) · [`carousel` ](./carousel.md ) · [`cascade` ](./cascade.md ) · [`clipboard` ](./clipboard.md ) · [`code` ](./code.md ) · [`code-block` ](./code-block.md ) · [`command` ](./command.md ) · [`css-field` ](./css-field.md ) · [`date-picker` ](./date-picker.md ) · [`display` ](./display.md ) · [`feed` ](./feed.md ) · [`field-langs` ](./field-langs.md ) · [`gradient-picker` ](./gradient-picker.md ) · [`grid-list` ](./grid-list.md ) · [`heading` ](./heading.md ) · [`highlight` ](./highlight.md ) · [`kbd` ](./kbd.md ) · [`knob` ](./knob.md ) · [`label` ](./label.md ) · [`link` ](./link.md ) · [`link-preview` ](./link-preview.md ) · [`listbox` ](./listbox.md ) · [`mark` ](./mark.md ) · [`mask-field` ](./mask-field.md ) · [`menu-dial` ](./menu-dial.md ) · [`mockup` ](./mockup.md ) · [`month-grid` ](./month-grid.md ) · [`motion` ](./motion.md ) · [`number-field` ](./number-field.md ) · [`palabras` ](./palabras.md ) · [`picker-shell` ](./picker-shell.md ) · [`range-calendar` ](./range-calendar.md ) · [`scroll-frames` ](./scroll-frames.md ) · [`skeleton` ](./skeleton.md ) · [`skin-media-player` ](./skin-media-player.md ) · [`spinner` ](./spinner.md ) · [`stack` ](./stack.md ) · [`table` ](./table.md ) · [`text` ](./text.md ) · [`text-blur` ](./text-blur.md ) · [`text-circular` ](./text-circular.md ) · [`text-focus` ](./text-focus.md ) · [`text-gradient` ](./text-gradient.md ) · [`text-scramble` ](./text-scramble.md ) · [`textarea` ](./textarea.md ) · [`tree-grid` ](./tree-grid.md ) · [`tree-view` ](./tree-view.md ) · [`virtual-grid` ](./virtual-grid.md ) · [`virtual-list` ](./virtual-list.md ) · [`wrap` ](./wrap.md ) · [`year-grid` ](./year-grid.md )
docs(theming): la auditoría de alcance de tema, componente a componente, con su propuesta
El censo medía el eje y no lo explicaba: 5.205 knobs en dos tablas del plan no
dicen QUÉ knob de QUÉ línea no alcanza un tema, ni qué token habría que crear.
Ahora `theming-census.ts --report` escribe la auditoría entera bajo
`docs/audit/theming/`: un README con la vista de conjunto y 170 fichas — 162
recetas con CSS + 8 componentes sin receta, el árbol completo de
`eidos/components/`.
Cada ficha de receta: knobs fuera de alcance con fichero:línea Y selector
(agrupados por clase), sistema transversal aparte, los privados con la columna
que decide («¿deriva de un público?»), y una PROPUESTA de corrección — el token
a declarar en `base.ts` con su valor VERBATIM y su scope TSC. La propuesta
deriva los nombres de recipe-contract §1 y theming §6.7; donde la doctrina no
decide, marca `⚠ decisión` en vez de inventar. Y no propone acuñar lo que la
doctrina prohíbe: lo que posee una capa compartida, el foco, la capa de estado,
un token prestado de otra receta, un shorthand o un eje físico.
Las 8 fichas sin receta dicen —medido, no supuesto— dónde vive su visual: el
componente que componen (icon-button → button), la capa que consumen (affix →
viewport-placement) o la receta ajena que pinta sus attrs (svg → badge/button).
Defectos del instrumento corregidos en el mismo pase, todos encontrados
mirando la salida: un `@import` pegado al primer selector se comía 2 knobs de
color-picker (el suelo del censo no puede moverse); `:not(:disabled)` se leía
como estado y producía `hover-disabled-*`; un knob que lee un privado se
proponía a sí mismo en vez de resolverse por talla; `--icon-size-sm` se
reportaba como préstamo del componente `icon` (ahora el préstamo se verifica
contra las claves del dueño en `base.ts`); y el default de talla salía sin
nombrar en vez de `-md`.
Verificación: censo global idéntico al suelo publicado (5205 · 1621/33% · 856 ·
1880 · 614 · 234) y COMPONENTE A COMPONENTE contra la tabla §9 del plan — 0
diferencias en 162 · regenerar dos veces da el árbol idéntico · el bloque de
veredicto escrito a mano sobrevive · docs:check 0 errores sobre 813 docs ·
prettier limpio (el árbol generado entra en .prettierignore junto a
eidos/generated).
Las 10 primeras fichas llevan ya su veredicto de revisión: análisis correcto en
las 10, propuesta apta en 2 (gradient-builder como piloto, combobox con cinco
correcciones — dos de ellas evitaban romper el default), y 5 que no se
tokenizan en solitario porque son alias de --calendar-*/--field-* y esperan la
decisión de familia. Cuatro destaparon privados con prefijo ajeno o abreviado
declarados en su propio CSS.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
## Tabla completa (162 recetas, por alcance ascendente)
La columna «contrato» cuenta las claves **públicas** del bloque del componente.
| componente | alcance | knobs | público | privado | global | literal | sistema | contrato | size |
| --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | :-: |
| [range-calendar ](./range-calendar.md ) | 0% | 98 | 0 | 7 | 84 | 4 | 3 | 0 | y |
| [month-grid ](./month-grid.md ) | 0% | 61 | 0 | 13 | 40 | 5 | 3 | 0 | y |
| [year-grid ](./year-grid.md ) | 0% | 61 | 0 | 13 | 40 | 5 | 3 | 0 | y |
| [command ](./command.md ) | 0% | 52 | 0 | 9 | 35 | 6 | 2 | 0 | y |
| [table ](./table.md ) | 0% | 46 | 0 | 23 | 14 | 5 | 4 | 0 | y |
| [media-player ](./media-player.md ) | 0% | 45 | 0 | 0 | 37 | 8 | 0 | 2 | y |
| [tree-grid ](./tree-grid.md ) | 0% | 42 | 0 | 29 | 8 | 2 | 3 | 0 | y |
| [field-langs ](./field-langs.md ) | 0% | 41 | 0 | 0 | 31 | 8 | 2 | 0 | – |
| [gradient-picker ](./gradient-picker.md ) | 0% | 38 | 0 | 7 | 23 | 5 | 3 | 0 | y |
| [listbox ](./listbox.md ) | 0% | 38 | 0 | 9 | 23 | 3 | 3 | 0 | – |
| [carousel ](./carousel.md ) | 0% | 36 | 0 | 14 | 12 | 5 | 5 | 0 | y |
| [feed ](./feed.md ) | 0% | 33 | 0 | 13 | 16 | 3 | 1 | 0 | y |
| [grid-list ](./grid-list.md ) | 0% | 32 | 0 | 8 | 17 | 2 | 5 | 0 | y |
| [textarea ](./textarea.md ) | 0% | 28 | 0 | 16 | 5 | 4 | 3 | 0 | y |
| [tree-view ](./tree-view.md ) | 0% | 28 | 0 | 8 | 14 | 4 | 2 | 0 | y |
| [code-block ](./code-block.md ) | 0% | 26 | 0 | 2 | 24 | 0 | 0 | 0 | – |
| [card-group ](./card-group.md ) | 0% | 24 | 0 | 0 | 18 | 4 | 2 | 0 | y |
| [spinner ](./spinner.md ) | 0% | 23 | 0 | 15 | 4 | 4 | 0 | 0 | y |
| [picker-shell ](./picker-shell.md ) | 0% | 21 | 0 | 4 | 17 | 0 | 0 | 0 | y |
| [link-preview ](./link-preview.md ) | 0% | 17 | 0 | 4 | 9 | 1 | 3 | 0 | y |
| [drag-drop ](./drag-drop.md ) | 0% | 16 | 0 | 3 | 6 | 0 | 7 | 1 | – |
| [kbd ](./kbd.md ) | 0% | 14 | 0 | 1 | 9 | 4 | 0 | 0 | – |
| [link ](./link.md ) | 0% | 14 | 0 | 4 | 2 | 5 | 3 | 0 | – |
feat(census): los primitivos tipográficos se miden contra su capa — pieza 0 de F2-A
D-TH.2-b, la firma que va ANTES del bloque porque cambia el suelo del censo:
medirla a mitad de camino falsearía todos los antes/después.
`heading` marcaba «36 knobs, 0 % alcanzable» y eso no era deuda: era una
lectura equivocada. Su receta resuelve cada eje como
`var(--_heading-font-size, var(--style-h2-font-size))` — el privado es el
escape POR INSTANCIA que el wrapper escribe desde una prop, y el named style es
la superficie de tema, ya pública y viva. Acuñar `--heading-*` para espejarla
sería un alias por eje × nivel: la clase que mató la purga del changelog §39.
El criterio de qué ES un primitivo tipográfico se midió, no se supuso: o la
receta SELECCIONA por `data-style` (`heading`, `text`, `s-text` — el named
style es su API) o está atada entera a UN style (`code` → `--style-code-*`,
`display` → `--style-hero-*`, `label` → `--style-label-*`). `code-block` queda
FUERA a propósito: lee un par de tokens de style para su texto pero posee
cromo de caja real, y eso sí es suyo.
Detalle que costó una vuelta: la comprobación va ANTES de la de privado. Leer
el privado primero puntúa el primitivo entero como inalcanzable cuando es
completamente temable — por la capa que lo posee.
antes 5.199 knobs · 1.837 públicos (37 %) · 894 privados · 232 sistema
después 5.199 knobs · 1.837 públicos (38 %) · 788 privados · 338 sistema
**Gate**: 106 knobs pasan de `private` a `system` en los SEIS primitivos y
**cero** de los otros 156 se mueve — verificado componente a componente contra
la versión en HEAD, no a ojo. Alcance `—` (nada que poseer) para heading, text
y display; `s-text` al 100 %; `code` y `label` bajan a 7 y 2 knobs de deuda
real.
Informe regenerado (171 veredictos a mano intactos), veredicto de heading
anotado como ejecutado, y recipe-contract §1 gana el párrafo que fija el
criterio — incluida la frontera: un menú que lee `--style-label-font-family`
para una etiqueta NO es un primitivo y no entra en el conjunto.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [code ](./code.md ) | 0% | 13 | 0 | 0 | 3 | 4 | 6 | 0 | – |
docs(theming): la auditoría de alcance de tema, componente a componente, con su propuesta
El censo medía el eje y no lo explicaba: 5.205 knobs en dos tablas del plan no
dicen QUÉ knob de QUÉ línea no alcanza un tema, ni qué token habría que crear.
Ahora `theming-census.ts --report` escribe la auditoría entera bajo
`docs/audit/theming/`: un README con la vista de conjunto y 170 fichas — 162
recetas con CSS + 8 componentes sin receta, el árbol completo de
`eidos/components/`.
Cada ficha de receta: knobs fuera de alcance con fichero:línea Y selector
(agrupados por clase), sistema transversal aparte, los privados con la columna
que decide («¿deriva de un público?»), y una PROPUESTA de corrección — el token
a declarar en `base.ts` con su valor VERBATIM y su scope TSC. La propuesta
deriva los nombres de recipe-contract §1 y theming §6.7; donde la doctrina no
decide, marca `⚠ decisión` en vez de inventar. Y no propone acuñar lo que la
doctrina prohíbe: lo que posee una capa compartida, el foco, la capa de estado,
un token prestado de otra receta, un shorthand o un eje físico.
Las 8 fichas sin receta dicen —medido, no supuesto— dónde vive su visual: el
componente que componen (icon-button → button), la capa que consumen (affix →
viewport-placement) o la receta ajena que pinta sus attrs (svg → badge/button).
Defectos del instrumento corregidos en el mismo pase, todos encontrados
mirando la salida: un `@import` pegado al primer selector se comía 2 knobs de
color-picker (el suelo del censo no puede moverse); `:not(:disabled)` se leía
como estado y producía `hover-disabled-*`; un knob que lee un privado se
proponía a sí mismo en vez de resolverse por talla; `--icon-size-sm` se
reportaba como préstamo del componente `icon` (ahora el préstamo se verifica
contra las claves del dueño en `base.ts`); y el default de talla salía sin
nombrar en vez de `-md`.
Verificación: censo global idéntico al suelo publicado (5205 · 1621/33% · 856 ·
1880 · 614 · 234) y COMPONENTE A COMPONENTE contra la tabla §9 del plan — 0
diferencias en 162 · regenerar dos veces da el árbol idéntico · el bloque de
veredicto escrito a mano sobrevive · docs:check 0 errores sobre 813 docs ·
prettier limpio (el árbol generado entra en .prettierignore junto a
eidos/generated).
Las 10 primeras fichas llevan ya su veredicto de revisión: análisis correcto en
las 10, propuesta apta en 2 (gradient-builder como piloto, combobox con cinco
correcciones — dos de ellas evitaban romper el default), y 5 que no se
tokenizan en solitario porque son alias de --calendar-*/--field-* y esperan la
decisión de familia. Cuatro destaparon privados con prefijo ajeno o abreviado
declarados en su propio CSS.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [virtual-list ](./virtual-list.md ) | 0% | 13 | 0 | 2 | 6 | 4 | 1 | 0 | y |
| [virtual-grid ](./virtual-grid.md ) | 0% | 12 | 0 | 2 | 6 | 3 | 1 | 0 | y |
| [skeleton ](./skeleton.md ) | 0% | 11 | 0 | 9 | 1 | 1 | 0 | 0 | y |
| [skin-media-player ](./skin-media-player.md ) | 0% | 11 | 0 | 0 | 2 | 7 | 2 | 0 | y |
| [scroll-frames ](./scroll-frames.md ) | 0% | 9 | 0 | 1 | 4 | 4 | 0 | 0 | – |
| [announce ](./announce.md ) | 0% | 8 | 0 | 0 | 8 | 0 | 0 | 0 | – |
| [clipboard ](./clipboard.md ) | 0% | 8 | 0 | 2 | 5 | 1 | 0 | 0 | – |
feat(census): los primitivos tipográficos se miden contra su capa — pieza 0 de F2-A
D-TH.2-b, la firma que va ANTES del bloque porque cambia el suelo del censo:
medirla a mitad de camino falsearía todos los antes/después.
`heading` marcaba «36 knobs, 0 % alcanzable» y eso no era deuda: era una
lectura equivocada. Su receta resuelve cada eje como
`var(--_heading-font-size, var(--style-h2-font-size))` — el privado es el
escape POR INSTANCIA que el wrapper escribe desde una prop, y el named style es
la superficie de tema, ya pública y viva. Acuñar `--heading-*` para espejarla
sería un alias por eje × nivel: la clase que mató la purga del changelog §39.
El criterio de qué ES un primitivo tipográfico se midió, no se supuso: o la
receta SELECCIONA por `data-style` (`heading`, `text`, `s-text` — el named
style es su API) o está atada entera a UN style (`code` → `--style-code-*`,
`display` → `--style-hero-*`, `label` → `--style-label-*`). `code-block` queda
FUERA a propósito: lee un par de tokens de style para su texto pero posee
cromo de caja real, y eso sí es suyo.
Detalle que costó una vuelta: la comprobación va ANTES de la de privado. Leer
el privado primero puntúa el primitivo entero como inalcanzable cuando es
completamente temable — por la capa que lo posee.
antes 5.199 knobs · 1.837 públicos (37 %) · 894 privados · 232 sistema
después 5.199 knobs · 1.837 públicos (38 %) · 788 privados · 338 sistema
**Gate**: 106 knobs pasan de `private` a `system` en los SEIS primitivos y
**cero** de los otros 156 se mueve — verificado componente a componente contra
la versión en HEAD, no a ojo. Alcance `—` (nada que poseer) para heading, text
y display; `s-text` al 100 %; `code` y `label` bajan a 7 y 2 knobs de deuda
real.
Informe regenerado (171 veredictos a mano intactos), veredicto de heading
anotado como ejecutado, y recipe-contract §1 gana el párrafo que fija el
criterio — incluida la frontera: un menú que lee `--style-label-font-family`
para una etiqueta NO es un primitivo y no entra en el conjunto.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [label ](./label.md ) | 0% | 8 | 0 | 0 | 2 | 0 | 6 | 0 | – |
docs(theming): la auditoría de alcance de tema, componente a componente, con su propuesta
El censo medía el eje y no lo explicaba: 5.205 knobs en dos tablas del plan no
dicen QUÉ knob de QUÉ línea no alcanza un tema, ni qué token habría que crear.
Ahora `theming-census.ts --report` escribe la auditoría entera bajo
`docs/audit/theming/`: un README con la vista de conjunto y 170 fichas — 162
recetas con CSS + 8 componentes sin receta, el árbol completo de
`eidos/components/`.
Cada ficha de receta: knobs fuera de alcance con fichero:línea Y selector
(agrupados por clase), sistema transversal aparte, los privados con la columna
que decide («¿deriva de un público?»), y una PROPUESTA de corrección — el token
a declarar en `base.ts` con su valor VERBATIM y su scope TSC. La propuesta
deriva los nombres de recipe-contract §1 y theming §6.7; donde la doctrina no
decide, marca `⚠ decisión` en vez de inventar. Y no propone acuñar lo que la
doctrina prohíbe: lo que posee una capa compartida, el foco, la capa de estado,
un token prestado de otra receta, un shorthand o un eje físico.
Las 8 fichas sin receta dicen —medido, no supuesto— dónde vive su visual: el
componente que componen (icon-button → button), la capa que consumen (affix →
viewport-placement) o la receta ajena que pinta sus attrs (svg → badge/button).
Defectos del instrumento corregidos en el mismo pase, todos encontrados
mirando la salida: un `@import` pegado al primer selector se comía 2 knobs de
color-picker (el suelo del censo no puede moverse); `:not(:disabled)` se leía
como estado y producía `hover-disabled-*`; un knob que lee un privado se
proponía a sí mismo en vez de resolverse por talla; `--icon-size-sm` se
reportaba como préstamo del componente `icon` (ahora el préstamo se verifica
contra las claves del dueño en `base.ts`); y el default de talla salía sin
nombrar en vez de `-md`.
Verificación: censo global idéntico al suelo publicado (5205 · 1621/33% · 856 ·
1880 · 614 · 234) y COMPONENTE A COMPONENTE contra la tabla §9 del plan — 0
diferencias en 162 · regenerar dos veces da el árbol idéntico · el bloque de
veredicto escrito a mano sobrevive · docs:check 0 errores sobre 813 docs ·
prettier limpio (el árbol generado entra en .prettierignore junto a
eidos/generated).
Las 10 primeras fichas llevan ya su veredicto de revisión: análisis correcto en
las 10, propuesta apta en 2 (gradient-builder como piloto, combobox con cinco
correcciones — dos de ellas evitaban romper el default), y 5 que no se
tokenizan en solitario porque son alias de --calendar-*/--field-* y esperan la
decisión de familia. Cuatro destaparon privados con prefijo ajeno o abreviado
declarados en su propio CSS.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [menu-dial ](./menu-dial.md ) | 0% | 8 | 0 | 3 | 1 | 4 | 0 | 0 | y |
| [mark ](./mark.md ) | 0% | 5 | 0 | 2 | 1 | 2 | 0 | 0 | – |
| [aspect-ratio ](./aspect-ratio.md ) | 0% | 3 | 0 | 0 | 1 | 2 | 0 | 0 | – |
| [date-picker ](./date-picker.md ) | 0% | 2 | 0 | 0 | 0 | 2 | 0 | 0 | – |
| [sticky ](./sticky.md ) | 0% | 2 | 0 | 1 | 0 | 1 | 0 | 1 | – |
| [text-blur ](./text-blur.md ) | 0% | 2 | 0 | 0 | 0 | 2 | 0 | 0 | – |
| [cascade ](./cascade.md ) | 0% | 1 | 0 | 0 | 0 | 1 | 0 | 0 | – |
| [motion ](./motion.md ) | 0% | 1 | 0 | 0 | 0 | 1 | 0 | 0 | – |
| [section ](./section.md ) | 0% | 1 | 0 | 0 | 0 | 1 | 0 | 4 | – |
| [chronos ](./chronos.md ) | 1% | 245 | 2 | 22 | 202 | 12 | 7 | 9 | y |
| [prose ](./prose.md ) | 1% | 74 | 1 | 0 | 43 | 30 | 0 | 2 | y |
| [nav-tree ](./nav-tree.md ) | 4% | 25 | 1 | 0 | 17 | 6 | 1 | 1 | – |
| [chart ](./chart.md ) | 9% | 92 | 8 | 0 | 66 | 14 | 4 | 17 | – |
| [result ](./result.md ) | 9% | 22 | 2 | 1 | 15 | 4 | 0 | 8 | – |
| [mockup ](./mockup.md ) | 14% | 29 | 4 | 7 | 13 | 5 | 0 | 0 | – |
uix(proof-of-human): el cromo del reto se puede temar; la paloma y el cielo no, y eso ya estaba firmado
Cuarto del eje theme-reach. El reto ataba su escenario a primitivos globales:
alto mínimo, radio, fondo, borde y los bordes de veredicto no los alcanzaba
ningún tema. Ahora son 20 claves públicas, con el alto por talla en el canon de
dos piezas y `parts: ['root']`, más la guía del trazo (corredor, línea, estela,
marcador de meta) y el token arrastrable.
Lo que NO entra es la escena — la paloma, la carta, los cielos del reloj — y no
por falta de tiempo: el guard de recetas ya lista este componente en la excepción
de tono fijo, y sus literales ya llevan anotación línea a línea. Un sello no se
vuelve azul porque el tema lo haga. La revisión había anotado esto como decisión
pendiente del autor; era una firma que ya existía y no había leído.
Dos fallos míos que la verificación cazó y que quedan escritos porque son
reutilizables. El primero: añadí un bloque `'proof-of-human'` a las recetas sin
ver que ya había uno (el forward de paleta), y en un object literal la segunda
clave gana — mi bloque se descartaba EN SILENCIO. Lo delató el diff de computed
con 28 diferencias, empezando por un `border-radius` que caía a cero. El segundo:
al fusionar los bloques perdí la última clave, y el guard de tokens fantasma lo
cazó al instante.
Verificación: diff de computed vacío sobre 406 valores en siete estados ·
component:audit PASS · suite eidos sin rojos nuevos · rtl:check 0 · docs:check 0.
El centinela no vale aquí y así queda dicho: la demo declara su propio
`min-block-size` y un degradado sobre el escenario, de modo que tapa dos de los
tokens; los que no pisa responden. El 86 % que el censo sigue contando fuera son
los dos ficheros de la escena, que enganchan por CLASE en vez de por data-attr —
migrarlos es otro eje, anotado.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [proof-of-human ](./proof-of-human.md ) | 14% | 95 | 13 | 18 | 29 | 31 | 4 | 20 | – |
docs(theming): la auditoría de alcance de tema, componente a componente, con su propuesta
El censo medía el eje y no lo explicaba: 5.205 knobs en dos tablas del plan no
dicen QUÉ knob de QUÉ línea no alcanza un tema, ni qué token habría que crear.
Ahora `theming-census.ts --report` escribe la auditoría entera bajo
`docs/audit/theming/`: un README con la vista de conjunto y 170 fichas — 162
recetas con CSS + 8 componentes sin receta, el árbol completo de
`eidos/components/`.
Cada ficha de receta: knobs fuera de alcance con fichero:línea Y selector
(agrupados por clase), sistema transversal aparte, los privados con la columna
que decide («¿deriva de un público?»), y una PROPUESTA de corrección — el token
a declarar en `base.ts` con su valor VERBATIM y su scope TSC. La propuesta
deriva los nombres de recipe-contract §1 y theming §6.7; donde la doctrina no
decide, marca `⚠ decisión` en vez de inventar. Y no propone acuñar lo que la
doctrina prohíbe: lo que posee una capa compartida, el foco, la capa de estado,
un token prestado de otra receta, un shorthand o un eje físico.
Las 8 fichas sin receta dicen —medido, no supuesto— dónde vive su visual: el
componente que componen (icon-button → button), la capa que consumen (affix →
viewport-placement) o la receta ajena que pinta sus attrs (svg → badge/button).
Defectos del instrumento corregidos en el mismo pase, todos encontrados
mirando la salida: un `@import` pegado al primer selector se comía 2 knobs de
color-picker (el suelo del censo no puede moverse); `:not(:disabled)` se leía
como estado y producía `hover-disabled-*`; un knob que lee un privado se
proponía a sí mismo en vez de resolverse por talla; `--icon-size-sm` se
reportaba como préstamo del componente `icon` (ahora el préstamo se verifica
contra las claves del dueño en `base.ts`); y el default de talla salía sin
nombrar en vez de `-md`.
Verificación: censo global idéntico al suelo publicado (5205 · 1621/33% · 856 ·
1880 · 614 · 234) y COMPONENTE A COMPONENTE contra la tabla §9 del plan — 0
diferencias en 162 · regenerar dos veces da el árbol idéntico · el bloque de
veredicto escrito a mano sobrevive · docs:check 0 errores sobre 813 docs ·
prettier limpio (el árbol generado entra en .prettierignore junto a
eidos/generated).
Las 10 primeras fichas llevan ya su veredicto de revisión: análisis correcto en
las 10, propuesta apta en 2 (gradient-builder como piloto, combobox con cinco
correcciones — dos de ellas evitaban romper el default), y 5 que no se
tokenizan en solitario porque son alias de --calendar-*/--field-* y esperan la
decisión de familia. Cuatro destaparon privados con prefijo ajeno o abreviado
declarados en su propio CSS.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [menubar ](./menubar.md ) | 15% | 27 | 4 | 6 | 16 | 0 | 1 | 5 | y |
uix(time-picker): el reloj es suyo y pasa a tokens; el campo sigue siendo del Field
Quinto del eje theme-reach, y el primero donde la mitad del componente NO debe
tokenizarse: time-picker compone Field, así que su parte con forma de campo lee
`--field-*` por diseño y duplicar esos ejes bajo prefijo propio sería el
vocabulario paralelo que el contrato prohíbe. Lo que sí es invención suya —la
cara del reloj— pasa a contrato: separación, ancho, tinta y tipografía del
reloj, los colores de las tres manecillas, el refuerzo del pulgar sobre la
superficie del popover y el radio del trigger en línea. Más el acento, que ahora
es público en vez de esconderse tras un privado.
Y un defecto que el censo no podía ver: la receta declaraba sus privados con el
prefijo de OTRO componente (`--_time-field-*`) dentro de su propio CSS. No era
sólo cosmético — un TimeField anidado y este picker se habrían pisado el nombre.
Son 44 referencias renombradas, con el diff de computed en cero.
El 82 % que el censo sigue contando fuera son esos préstamos de Field: no es
deriva, es un préstamo con dueño, y su corrección es el mandato de composición
de Field que la auditoría del sistema dejó apuntado (§5.3-3), no este eje.
El guard de huérfanos me corrigió por el camino: había declarado doce tokens de
más, copiados del range-picker (la franja AM/PM y los ticks), que este
componente no tiene. Retirados; sólo `trigger-radius` tenía consumidor real y se
cableó.
Verificación: diff de computed vacío sobre 580 valores en ocho estados ·
component:audit PASS · suite eidos sin rojos nuevos · rtl:check 0 · docs:check 0.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [time-picker ](./time-picker.md ) | 18% | 59 | 10 | 12 | 24 | 11 | 2 | 16 | y |
uix(time-range-picker): el reloj de dos columnas y la franja AM/PM pasan a tokens
Sexto del eje theme-reach, y gemelo de time-picker: mismo reparto, mismas
razones. A contrato lo que el componente inventa — el reloj de dos columnas (su
separación, ancho, tinta y tipografía), los colores de las tres manecillas y la
franja AM/PM entera — y sin tocar el lado con forma de campo, que lee `--field-*`
porque compone Field.
Y el mismo defecto de prefijo que su gemelo: 56 referencias declaraban
`--_time-field-*` dentro de este CSS (más una mención en el wrapper). Renombradas
a `--_time-range-picker-*`, con el diff de computed en cero.
Dos cosas que la revisión había marcado como acuñables y NO lo son, confirmadas
al ejecutar: el realce del reloj al puntero lee `--toggle-palette-solid`, que es
la paleta de otro componente — si procede, es un bloque de composición cruzada,
y eso es decisión, no corrección; y el `padding-inline` del raíl consume el
tamaño del pulgar del Slider, un eje que publica su dueño o no se publica.
Verificación: diff de computed vacío sobre 725 valores en ocho estados ·
component:audit PASS · suite eidos sin rojos nuevos · rtl:check 0 · docs:check 0.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [time-range-picker ](./time-range-picker.md ) | 19% | 88 | 16 | 20 | 33 | 15 | 4 | 22 | y |
docs(theming): la auditoría de alcance de tema, componente a componente, con su propuesta
El censo medía el eje y no lo explicaba: 5.205 knobs en dos tablas del plan no
dicen QUÉ knob de QUÉ línea no alcanza un tema, ni qué token habría que crear.
Ahora `theming-census.ts --report` escribe la auditoría entera bajo
`docs/audit/theming/`: un README con la vista de conjunto y 170 fichas — 162
recetas con CSS + 8 componentes sin receta, el árbol completo de
`eidos/components/`.
Cada ficha de receta: knobs fuera de alcance con fichero:línea Y selector
(agrupados por clase), sistema transversal aparte, los privados con la columna
que decide («¿deriva de un público?»), y una PROPUESTA de corrección — el token
a declarar en `base.ts` con su valor VERBATIM y su scope TSC. La propuesta
deriva los nombres de recipe-contract §1 y theming §6.7; donde la doctrina no
decide, marca `⚠ decisión` en vez de inventar. Y no propone acuñar lo que la
doctrina prohíbe: lo que posee una capa compartida, el foco, la capa de estado,
un token prestado de otra receta, un shorthand o un eje físico.
Las 8 fichas sin receta dicen —medido, no supuesto— dónde vive su visual: el
componente que componen (icon-button → button), la capa que consumen (affix →
viewport-placement) o la receta ajena que pinta sus attrs (svg → badge/button).
Defectos del instrumento corregidos en el mismo pase, todos encontrados
mirando la salida: un `@import` pegado al primer selector se comía 2 knobs de
color-picker (el suelo del censo no puede moverse); `:not(:disabled)` se leía
como estado y producía `hover-disabled-*`; un knob que lee un privado se
proponía a sí mismo en vez de resolverse por talla; `--icon-size-sm` se
reportaba como préstamo del componente `icon` (ahora el préstamo se verifica
contra las claves del dueño en `base.ts`); y el default de talla salía sin
nombrar en vez de `-md`.
Verificación: censo global idéntico al suelo publicado (5205 · 1621/33% · 856 ·
1880 · 614 · 234) y COMPONENTE A COMPONENTE contra la tabla §9 del plan — 0
diferencias en 162 · regenerar dos veces da el árbol idéntico · el bloque de
veredicto escrito a mano sobrevive · docs:check 0 errores sobre 813 docs ·
prettier limpio (el árbol generado entra en .prettierignore junto a
eidos/generated).
Las 10 primeras fichas llevan ya su veredicto de revisión: análisis correcto en
las 10, propuesta apta en 2 (gradient-builder como piloto, combobox con cinco
correcciones — dos de ellas evitaban romper el default), y 5 que no se
tokenizan en solitario porque son alias de --calendar-*/--field-* y esperan la
decisión de familia. Cuatro destaparon privados con prefijo ajeno o abreviado
declarados en su propio CSS.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [anchor-nav ](./anchor-nav.md ) | 20% | 11 | 2 | 0 | 8 | 0 | 1 | 2 | – |
| [banner ](./banner.md ) | 20% | 10 | 2 | 6 | 1 | 1 | 0 | 42 | y |
| [button ](./button.md ) | 21% | 30 | 6 | 16 | 0 | 7 | 1 | 105 | y |
| [palabras ](./palabras.md ) | 22% | 471 | 103 | 1 | 272 | 90 | 5 | 0 | – |
| [toggle ](./toggle.md ) | 22% | 28 | 6 | 17 | 1 | 3 | 1 | 119 | y |
| [date-range-field ](./date-range-field.md ) | 25% | 9 | 2 | 0 | 4 | 2 | 1 | 3 | – |
| [time-range-field ](./time-range-field.md ) | 25% | 9 | 2 | 0 | 4 | 2 | 1 | 3 | – |
| [surface ](./surface.md ) | 25% | 4 | 1 | 3 | 0 | 0 | 0 | 25 | – |
| [callout ](./callout.md ) | 27% | 15 | 4 | 3 | 7 | 1 | 0 | 28 | – |
| [meter ](./meter.md ) | 29% | 14 | 4 | 6 | 2 | 2 | 0 | 28 | y |
| [knob ](./knob.md ) | 29% | 27 | 7 | 4 | 9 | 4 | 3 | 0 | y |
| [onion-menu ](./onion-menu.md ) | 29% | 27 | 7 | 0 | 8 | 9 | 3 | 12 | – |
| [empty-state ](./empty-state.md ) | 29% | 17 | 5 | 7 | 5 | 0 | 0 | 6 | y |
| [search-field ](./search-field.md ) | 31% | 14 | 4 | 5 | 0 | 4 | 1 | 17 | y |
| [password-field ](./password-field.md ) | 31% | 36 | 11 | 5 | 9 | 10 | 1 | 23 | y |
| [aura ](./aura.md ) | 31% | 35 | 11 | 4 | 14 | 6 | 0 | 24 | y |
| [toggle-group ](./toggle-group.md ) | 33% | 3 | 1 | 0 | 1 | 1 | 0 | 1 | – |
| [background ](./background.md ) | 35% | 26 | 8 | 6 | 6 | 3 | 3 | 31 | – |
| [avatar ](./avatar.md ) | 36% | 36 | 13 | 17 | 0 | 6 | 0 | 0 | y |
| [audio-player ](./audio-player.md ) | 37% | 19 | 7 | 0 | 8 | 4 | 0 | 5 | – |
| [tooltip ](./tooltip.md ) | 38% | 22 | 8 | 9 | 3 | 1 | 1 | 20 | y |
docs(theming): el informe habla el idioma nuevo — y el fleco del README, cerrado
Al rendir cuentas del repaso de los 7 salió un fleco: el README de
gradient-builder mencionaba `checker-color` por su clave SUELTA, sin el
prefijo `--gradient-builder-`, y el codemod busca tokens completos — quedó con
el nombre muerto. Dos líneas corregidas, más las dos del §5 de su ficha.
Y la causa de fondo: las 170 fichas del informe llevaban desde el codemod
citando el contrato con los nombres viejos en sus secciones generadas.
Regenerado entero (`--report`): 69 fichas cambian, los 171 veredictos §5
escritos a mano sobreviven (verificado), `docs:check` 0.
El censo del informe registra 5.199 knobs · 1.837 públicos — cuatro menos que
el suelo del codemod, que son EXACTAMENTE las cuatro declaraciones de hover
bespoke que la firma 3 retiró (checkbox, splitter, switch, drp ×2 −1 nueva del
checked). El alcance global sigue en 37 %.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [date-range-picker ](./date-range-picker.md ) | 40% | 53 | 20 | 9 | 19 | 2 | 3 | 22 | y |
docs(theming): la auditoría de alcance de tema, componente a componente, con su propuesta
El censo medía el eje y no lo explicaba: 5.205 knobs en dos tablas del plan no
dicen QUÉ knob de QUÉ línea no alcanza un tema, ni qué token habría que crear.
Ahora `theming-census.ts --report` escribe la auditoría entera bajo
`docs/audit/theming/`: un README con la vista de conjunto y 170 fichas — 162
recetas con CSS + 8 componentes sin receta, el árbol completo de
`eidos/components/`.
Cada ficha de receta: knobs fuera de alcance con fichero:línea Y selector
(agrupados por clase), sistema transversal aparte, los privados con la columna
que decide («¿deriva de un público?»), y una PROPUESTA de corrección — el token
a declarar en `base.ts` con su valor VERBATIM y su scope TSC. La propuesta
deriva los nombres de recipe-contract §1 y theming §6.7; donde la doctrina no
decide, marca `⚠ decisión` en vez de inventar. Y no propone acuñar lo que la
doctrina prohíbe: lo que posee una capa compartida, el foco, la capa de estado,
un token prestado de otra receta, un shorthand o un eje físico.
Las 8 fichas sin receta dicen —medido, no supuesto— dónde vive su visual: el
componente que componen (icon-button → button), la capa que consumen (affix →
viewport-placement) o la receta ajena que pinta sus attrs (svg → badge/button).
Defectos del instrumento corregidos en el mismo pase, todos encontrados
mirando la salida: un `@import` pegado al primer selector se comía 2 knobs de
color-picker (el suelo del censo no puede moverse); `:not(:disabled)` se leía
como estado y producía `hover-disabled-*`; un knob que lee un privado se
proponía a sí mismo en vez de resolverse por talla; `--icon-size-sm` se
reportaba como préstamo del componente `icon` (ahora el préstamo se verifica
contra las claves del dueño en `base.ts`); y el default de talla salía sin
nombrar en vez de `-md`.
Verificación: censo global idéntico al suelo publicado (5205 · 1621/33% · 856 ·
1880 · 614 · 234) y COMPONENTE A COMPONENTE contra la tabla §9 del plan — 0
diferencias en 162 · regenerar dos veces da el árbol idéntico · el bloque de
veredicto escrito a mano sobrevive · docs:check 0 errores sobre 813 docs ·
prettier limpio (el árbol generado entra en .prettierignore junto a
eidos/generated).
Las 10 primeras fichas llevan ya su veredicto de revisión: análisis correcto en
las 10, propuesta apta en 2 (gradient-builder como piloto, combobox con cinco
correcciones — dos de ellas evitaban romper el default), y 5 que no se
tokenizan en solitario porque son alias de --calendar-*/--field-* y esperan la
decisión de familia. Cuatro destaparon privados con prefijo ajeno o abreviado
declarados en su propio CSS.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [button-group ](./button-group.md ) | 40% | 5 | 2 | 0 | 0 | 3 | 0 | 1 | – |
| [badge ](./badge.md ) | 41% | 22 | 9 | 10 | 1 | 2 | 0 | 65 | y |
| [popover ](./popover.md ) | 42% | 51 | 20 | 6 | 22 | 0 | 3 | 36 | y |
| [qr-code ](./qr-code.md ) | 43% | 7 | 3 | 0 | 0 | 4 | 0 | 10 | – |
| [navigation-menu ](./navigation-menu.md ) | 44% | 38 | 15 | 1 | 13 | 5 | 4 | 26 | y |
| [waveform ](./waveform.md ) | 45% | 11 | 5 | 1 | 1 | 4 | 0 | 10 | y |
| [color-picker ](./color-picker.md ) | 46% | 82 | 36 | 10 | 22 | 11 | 3 | 54 | y |
docs(theming): el informe habla el idioma nuevo — y el fleco del README, cerrado
Al rendir cuentas del repaso de los 7 salió un fleco: el README de
gradient-builder mencionaba `checker-color` por su clave SUELTA, sin el
prefijo `--gradient-builder-`, y el codemod busca tokens completos — quedó con
el nombre muerto. Dos líneas corregidas, más las dos del §5 de su ficha.
Y la causa de fondo: las 170 fichas del informe llevaban desde el codemod
citando el contrato con los nombres viejos en sus secciones generadas.
Regenerado entero (`--report`): 69 fichas cambian, los 171 veredictos §5
escritos a mano sobreviven (verificado), `docs:check` 0.
El censo del informe registra 5.199 knobs · 1.837 públicos — cuatro menos que
el suelo del codemod, que son EXACTAMENTE las cuatro declaraciones de hover
bespoke que la firma 3 retiró (checkbox, splitter, switch, drp ×2 −1 nueva del
checked). El alcance global sigue en 37 %.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [checkbox ](./checkbox.md ) | 47% | 33 | 15 | 12 | 2 | 3 | 1 | 44 | y |
docs(theming): la auditoría de alcance de tema, componente a componente, con su propuesta
El censo medía el eje y no lo explicaba: 5.205 knobs en dos tablas del plan no
dicen QUÉ knob de QUÉ línea no alcanza un tema, ni qué token habría que crear.
Ahora `theming-census.ts --report` escribe la auditoría entera bajo
`docs/audit/theming/`: un README con la vista de conjunto y 170 fichas — 162
recetas con CSS + 8 componentes sin receta, el árbol completo de
`eidos/components/`.
Cada ficha de receta: knobs fuera de alcance con fichero:línea Y selector
(agrupados por clase), sistema transversal aparte, los privados con la columna
que decide («¿deriva de un público?»), y una PROPUESTA de corrección — el token
a declarar en `base.ts` con su valor VERBATIM y su scope TSC. La propuesta
deriva los nombres de recipe-contract §1 y theming §6.7; donde la doctrina no
decide, marca `⚠ decisión` en vez de inventar. Y no propone acuñar lo que la
doctrina prohíbe: lo que posee una capa compartida, el foco, la capa de estado,
un token prestado de otra receta, un shorthand o un eje físico.
Las 8 fichas sin receta dicen —medido, no supuesto— dónde vive su visual: el
componente que componen (icon-button → button), la capa que consumen (affix →
viewport-placement) o la receta ajena que pinta sus attrs (svg → badge/button).
Defectos del instrumento corregidos en el mismo pase, todos encontrados
mirando la salida: un `@import` pegado al primer selector se comía 2 knobs de
color-picker (el suelo del censo no puede moverse); `:not(:disabled)` se leía
como estado y producía `hover-disabled-*`; un knob que lee un privado se
proponía a sí mismo en vez de resolverse por talla; `--icon-size-sm` se
reportaba como préstamo del componente `icon` (ahora el préstamo se verifica
contra las claves del dueño en `base.ts`); y el default de talla salía sin
nombrar en vez de `-md`.
Verificación: censo global idéntico al suelo publicado (5205 · 1621/33% · 856 ·
1880 · 614 · 234) y COMPONENTE A COMPONENTE contra la tabla §9 del plan — 0
diferencias en 162 · regenerar dos veces da el árbol idéntico · el bloque de
veredicto escrito a mano sobrevive · docs:check 0 errores sobre 813 docs ·
prettier limpio (el árbol generado entra en .prettierignore junto a
eidos/generated).
Las 10 primeras fichas llevan ya su veredicto de revisión: análisis correcto en
las 10, propuesta apta en 2 (gradient-builder como piloto, combobox con cinco
correcciones — dos de ellas evitaban romper el default), y 5 que no se
tokenizan en solitario porque son alias de --calendar-*/--field-* y esperan la
decisión de familia. Cuatro destaparon privados con prefijo ajeno o abreviado
declarados en su propio CSS.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [progress ](./progress.md ) | 49% | 35 | 17 | 9 | 3 | 6 | 0 | 41 | y |
| [tag-group ](./tag-group.md ) | 49% | 46 | 21 | 21 | 0 | 1 | 3 | 91 | y |
| [color-swatch ](./color-swatch.md ) | 50% | 10 | 5 | 2 | 3 | 0 | 0 | 12 | y |
| [text-scramble ](./text-scramble.md ) | 50% | 4 | 2 | 0 | 0 | 2 | 0 | 0 | – |
| [split-button ](./split-button.md ) | 50% | 2 | 1 | 0 | 1 | 0 | 0 | 1 | y |
| [timeline ](./timeline.md ) | 51% | 49 | 25 | 21 | 0 | 3 | 0 | 45 | y |
| [field ](./field.md ) | 51% | 73 | 35 | 15 | 7 | 11 | 5 | 60 | y |
| [context-menu ](./context-menu.md ) | 53% | 33 | 16 | 0 | 11 | 3 | 3 | 18 | – |
| [rating-group ](./rating-group.md ) | 53% | 16 | 8 | 4 | 1 | 2 | 1 | 25 | y |
| [metrics ](./metrics.md ) | 54% | 50 | 27 | 10 | 9 | 4 | 0 | 68 | y |
| [sidebar ](./sidebar.md ) | 55% | 45 | 23 | 0 | 14 | 5 | 3 | 50 | – |
| [drawer ](./drawer.md ) | 55% | 62 | 33 | 9 | 13 | 5 | 2 | 44 | y |
| [color-field ](./color-field.md ) | 56% | 16 | 9 | 0 | 2 | 5 | 0 | 22 | y |
| [image ](./image.md ) | 57% | 35 | 20 | 2 | 1 | 12 | 0 | 22 | y |
| [dropdown-menu ](./dropdown-menu.md ) | 57% | 30 | 16 | 0 | 9 | 3 | 2 | 19 | – |
docs(theming): el informe habla el idioma nuevo — y el fleco del README, cerrado
Al rendir cuentas del repaso de los 7 salió un fleco: el README de
gradient-builder mencionaba `checker-color` por su clave SUELTA, sin el
prefijo `--gradient-builder-`, y el codemod busca tokens completos — quedó con
el nombre muerto. Dos líneas corregidas, más las dos del §5 de su ficha.
Y la causa de fondo: las 170 fichas del informe llevaban desde el codemod
citando el contrato con los nombres viejos en sus secciones generadas.
Regenerado entero (`--report`): 69 fichas cambian, los 171 veredictos §5
escritos a mano sobreviven (verificado), `docs:check` 0.
El censo del informe registra 5.199 knobs · 1.837 públicos — cuatro menos que
el suelo del codemod, que son EXACTAMENTE las cuatro declaraciones de hover
bespoke que la firma 3 retiró (checkbox, splitter, switch, drp ×2 −1 nueva del
checked). El alcance global sigue en 37 %.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [switch ](./switch.md ) | 57% | 22 | 12 | 8 | 1 | 0 | 1 | 51 | y |
docs(theming): la auditoría de alcance de tema, componente a componente, con su propuesta
El censo medía el eje y no lo explicaba: 5.205 knobs en dos tablas del plan no
dicen QUÉ knob de QUÉ línea no alcanza un tema, ni qué token habría que crear.
Ahora `theming-census.ts --report` escribe la auditoría entera bajo
`docs/audit/theming/`: un README con la vista de conjunto y 170 fichas — 162
recetas con CSS + 8 componentes sin receta, el árbol completo de
`eidos/components/`.
Cada ficha de receta: knobs fuera de alcance con fichero:línea Y selector
(agrupados por clase), sistema transversal aparte, los privados con la columna
que decide («¿deriva de un público?»), y una PROPUESTA de corrección — el token
a declarar en `base.ts` con su valor VERBATIM y su scope TSC. La propuesta
deriva los nombres de recipe-contract §1 y theming §6.7; donde la doctrina no
decide, marca `⚠ decisión` en vez de inventar. Y no propone acuñar lo que la
doctrina prohíbe: lo que posee una capa compartida, el foco, la capa de estado,
un token prestado de otra receta, un shorthand o un eje físico.
Las 8 fichas sin receta dicen —medido, no supuesto— dónde vive su visual: el
componente que componen (icon-button → button), la capa que consumen (affix →
viewport-placement) o la receta ajena que pinta sus attrs (svg → badge/button).
Defectos del instrumento corregidos en el mismo pase, todos encontrados
mirando la salida: un `@import` pegado al primer selector se comía 2 knobs de
color-picker (el suelo del censo no puede moverse); `:not(:disabled)` se leía
como estado y producía `hover-disabled-*`; un knob que lee un privado se
proponía a sí mismo en vez de resolverse por talla; `--icon-size-sm` se
reportaba como préstamo del componente `icon` (ahora el préstamo se verifica
contra las claves del dueño en `base.ts`); y el default de talla salía sin
nombrar en vez de `-md`.
Verificación: censo global idéntico al suelo publicado (5205 · 1621/33% · 856 ·
1880 · 614 · 234) y COMPONENTE A COMPONENTE contra la tabla §9 del plan — 0
diferencias en 162 · regenerar dos veces da el árbol idéntico · el bloque de
veredicto escrito a mano sobrevive · docs:check 0 errores sobre 813 docs ·
prettier limpio (el árbol generado entra en .prettierignore junto a
eidos/generated).
Las 10 primeras fichas llevan ya su veredicto de revisión: análisis correcto en
las 10, propuesta apta en 2 (gradient-builder como piloto, combobox con cinco
correcciones — dos de ellas evitaban romper el default), y 5 que no se
tokenizan en solitario porque son alias de --calendar-*/--field-* y esperan la
decisión de familia. Cuatro destaparon privados con prefijo ajeno o abreviado
declarados en su propio CSS.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [s-text-virtual-list ](./s-text-virtual-list.md ) | 58% | 12 | 7 | 0 | 3 | 2 | 0 | 9 | – |
| [form ](./form.md ) | 59% | 52 | 30 | 14 | 5 | 2 | 1 | 54 | y |
| [float-panel ](./float-panel.md ) | 59% | 53 | 29 | 3 | 12 | 5 | 4 | 28 | – |
| [slider ](./slider.md ) | 59% | 33 | 19 | 12 | 0 | 1 | 1 | 39 | y |
| [radio-cards ](./radio-cards.md ) | 60% | 72 | 42 | 0 | 24 | 4 | 2 | 39 | y |
| [card ](./card.md ) | 60% | 36 | 21 | 14 | 0 | 0 | 1 | 97 | y |
| [cropper ](./cropper.md ) | 60% | 27 | 15 | 0 | 3 | 7 | 2 | 15 | – |
uix(natural-time-picker): el cromo de la banda se puede temar, y el cielo sigue siendo el cielo
Tercero del eje theme-reach. La receta ataba todo a primitivos globales y
guardaba su geometría en privados con un prefijo abreviado, `--_ntp-*`, que ni
el censo veía ni el vocabulario permite: alcance 0 %. Ahora son 60 claves
públicas y el 61 % medido.
Dos de los tres bloqueos que la revisión había anotado no existían: la doctrina
ya estaba escrita y no la había leído. El guard de recetas ya lista este
componente en la excepción de TONO FIJO — un cielo no cambia con el tema, y sus
literales ya llevaban su válvula línea a línea, así que los cielos, la tinta del
sol/luna y la línea de posición se quedan privados y anotados, sin decisión que
pedir. Y el panel sigue leyendo `--popover-*` porque su propia cabecera dice que
esa superficie ES el flotante canónico: duplicarla con prefijo propio habría
sido el vocabulario paralelo que el contrato prohíbe. De ahí que el 39 % restante
no sea deuda sino préstamo deliberado.
Lo que sí es suyo pasa a contrato: banda y knob por talla con `parts: ['panel']`
—conservando su derivación de la altura de control, así que la expresión sigue
siendo el knob y mover la talla arrastra ambos—, la línea indicadora, los ticks,
el readout (hora, meridiem, periodo), los steppers, los chips y el trigger. Más
el `panel-gap`, que sí es del panel y no del popover.
Las 37 referencias `--_ntp-*` mueren: el prefijo de un privado es el nombre
completo del componente (theming §6 regla 5). El rename alcanza receta, wrapper,
README y el propio guard que las citaba.
Verificación: diff de computed vacío sobre 6.438 valores en ocho estados.
Centinela 40/62 automático, y cada uno de los marcados muertos verificado a
mano: banda, knob, gap del panel, línea, radio de la línea e inset de los ticks
alcanzan; los `trigger-*` NO, porque `[data-popover-trigger]` gana la cascada y
viste el trigger — ya eran inertes antes de tokenizarlos, y ahora está dicho en
el README en vez de fingir que el token pinta.
Guards: component:audit PASS · eidos-lint 0 invalid · suite eidos sin rojos
nuevos · rtl:check 0 · docs:check 0 · el guard del bundle obligó a apuntar
`tick-font-size` a la coordenada `--size-xxs-font-size`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [natural-time-picker ](./natural-time-picker.md ) | 61% | 77 | 46 | 10 | 14 | 6 | 1 | 62 | y |
docs(theming): la auditoría de alcance de tema, componente a componente, con su propuesta
El censo medía el eje y no lo explicaba: 5.205 knobs en dos tablas del plan no
dicen QUÉ knob de QUÉ línea no alcanza un tema, ni qué token habría que crear.
Ahora `theming-census.ts --report` escribe la auditoría entera bajo
`docs/audit/theming/`: un README con la vista de conjunto y 170 fichas — 162
recetas con CSS + 8 componentes sin receta, el árbol completo de
`eidos/components/`.
Cada ficha de receta: knobs fuera de alcance con fichero:línea Y selector
(agrupados por clase), sistema transversal aparte, los privados con la columna
que decide («¿deriva de un público?»), y una PROPUESTA de corrección — el token
a declarar en `base.ts` con su valor VERBATIM y su scope TSC. La propuesta
deriva los nombres de recipe-contract §1 y theming §6.7; donde la doctrina no
decide, marca `⚠ decisión` en vez de inventar. Y no propone acuñar lo que la
doctrina prohíbe: lo que posee una capa compartida, el foco, la capa de estado,
un token prestado de otra receta, un shorthand o un eje físico.
Las 8 fichas sin receta dicen —medido, no supuesto— dónde vive su visual: el
componente que componen (icon-button → button), la capa que consumen (affix →
viewport-placement) o la receta ajena que pinta sus attrs (svg → badge/button).
Defectos del instrumento corregidos en el mismo pase, todos encontrados
mirando la salida: un `@import` pegado al primer selector se comía 2 knobs de
color-picker (el suelo del censo no puede moverse); `:not(:disabled)` se leía
como estado y producía `hover-disabled-*`; un knob que lee un privado se
proponía a sí mismo en vez de resolverse por talla; `--icon-size-sm` se
reportaba como préstamo del componente `icon` (ahora el préstamo se verifica
contra las claves del dueño en `base.ts`); y el default de talla salía sin
nombrar en vez de `-md`.
Verificación: censo global idéntico al suelo publicado (5205 · 1621/33% · 856 ·
1880 · 614 · 234) y COMPONENTE A COMPONENTE contra la tabla §9 del plan — 0
diferencias en 162 · regenerar dos veces da el árbol idéntico · el bloque de
veredicto escrito a mano sobrevive · docs:check 0 errores sobre 813 docs ·
prettier limpio (el árbol generado entra en .prettierignore junto a
eidos/generated).
Las 10 primeras fichas llevan ya su veredicto de revisión: análisis correcto en
las 10, propuesta apta en 2 (gradient-builder como piloto, combobox con cinco
correcciones — dos de ellas evitaban romper el default), y 5 que no se
tokenizan en solitario porque son alias de --calendar-*/--field-* y esperan la
decisión de familia. Cuatro destaparon privados con prefijo ajeno o abreviado
declarados en su propio CSS.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [emoji-picker ](./emoji-picker.md ) | 61% | 32 | 17 | 0 | 8 | 3 | 4 | 17 | – |
| [pin-input ](./pin-input.md ) | 61% | 19 | 11 | 0 | 6 | 1 | 1 | 20 | y |
| [editable ](./editable.md ) | 63% | 44 | 25 | 12 | 1 | 2 | 4 | 56 | y |
| [text-focus ](./text-focus.md ) | 63% | 8 | 5 | 0 | 1 | 2 | 0 | 0 | – |
| [spin-field ](./spin-field.md ) | 64% | 27 | 16 | 0 | 8 | 1 | 2 | 20 | – |
| [file-upload ](./file-upload.md ) | 64% | 61 | 38 | 16 | 1 | 4 | 2 | 98 | y |
| [tags-input ](./tags-input.md ) | 67% | 46 | 28 | 13 | 1 | 0 | 4 | 90 | y |
| [toolbar ](./toolbar.md ) | 67% | 35 | 22 | 10 | 0 | 1 | 2 | 54 | y |
| [image-adjustments ](./image-adjustments.md ) | 67% | 18 | 10 | 0 | 4 | 1 | 3 | 12 | – |
| [text-gradient ](./text-gradient.md ) | 67% | 9 | 6 | 0 | 0 | 3 | 0 | 0 | – |
| [separator ](./separator.md ) | 67% | 6 | 4 | 0 | 0 | 2 | 0 | 3 | – |
| [select ](./select.md ) | 69% | 72 | 45 | 14 | 3 | 3 | 7 | 101 | y |
| [dialog ](./dialog.md ) | 70% | 33 | 23 | 5 | 4 | 1 | 0 | 37 | y |
| [image-picker ](./image-picker.md ) | 71% | 20 | 12 | 0 | 1 | 4 | 3 | 13 | – |
| [pagination ](./pagination.md ) | 71% | 26 | 17 | 7 | 0 | 0 | 2 | 34 | y |
| [stepper ](./stepper.md ) | 71% | 60 | 40 | 15 | 0 | 1 | 4 | 69 | y |
| [skip-link ](./skip-link.md ) | 71% | 8 | 5 | 0 | 0 | 2 | 1 | 8 | – |
| [date-field ](./date-field.md ) | 73% | 11 | 8 | 3 | 0 | 0 | 0 | 21 | y |
| [time-field ](./time-field.md ) | 73% | 11 | 8 | 3 | 0 | 0 | 0 | 21 | y |
| [calendar ](./calendar.md ) | 75% | 71 | 51 | 13 | 0 | 4 | 3 | 76 | y |
uix(combobox): el campo y su panel pasan a tokens públicos, con la talla resuelta donde manda
Segundo del eje theme-reach. El combobox tenía UN token propio (`content-z`) y
todo lo demás atado a primitivos globales o enterrado en privados: alcance 0 %.
Ahora son 106 claves públicas y el 76 % medido — lo que queda fuera son tres
hovers que esperan firma, seis literales de layout y doce knobs que pasan por
privados que ya derivan de un público.
La talla sigue el canon de dos piezas (coordenada + nombre resuelto), pero con
una diferencia que el DOM impone: los resueltos del control se emiten sobre
`control` e `input`, no sobre el root, porque el `data-size` que manda vive en el
control — y el input suelto lo necesita fuera de él. Los del panel se emiten
sobre `content`, que viaja por portal y nunca vería un token del root. Es el
precedente de `select` aplicado donde toca.
Altura, tipografía y separación del control consumen la coordenada del bundle
`--size-{k}-*`; el relleno inline SE DESVÍA del bundle en cuatro tallas y
conserva su valor de hoy — la desviación queda visible en el contrato en vez de
redondearse a la coordenada, que habría sido un cambio visual disfrazado de
limpieza. El chip conserva sus expresiones (`control-height − inset`,
`control-font-size − offset`), así que mover el control sigue arrastrándolo.
El centinela cazó un fallo real a mitad del trabajo: la primera pasada dejó
vivos los ocho bloques `[data-…][data-size='…']` de la receta, que pisaban los
tokens nuevos con los valores viejos. El diff de computed daba cero JUSTAMENTE
porque la ruta vieja seguía mandando; sin centinela habría pasado por bueno.
Verificación: diff de computed vacío sobre 1.566 valores en ocho estados —
reposo, las cinco tallas, el panel ABIERTO y hover. Centinela 67/106 automático
y el resto verificado a mano: `content-z` alcanza (80 → 4321) aunque viva en el
wrapper flotante; placeholder, disabled e ink del trigger forzando su estado;
los del panel abriéndolo por teclado. Los siete nombres resueltos no se mueven
por diseño — el tema mueve la coordenada. Los catorce `selected-tag-*`, los tres
`separator-*` y `scrollbar-inset` no son verificables en esta demo (no monta
modo múltiple, ni separadores, ni scroll): queda dicho, con su consumidor
comprobado en la receta, en vez de darlos por buenos.
Un token nace inerte y se anota como tal: `content-font-family` y
`content-line-height` los pisa `[data-depth='overlay']` con la misma
especificidad — es la tipografía de portal del Build contract, y tocarla sería
otro eje.
Guards: component:audit PASS · eidos-lint 0 invalid · suite eidos sin rojos
nuevos · rtl:check 0 · docs:check 0 · el guard del bundle obligó a apuntar
`indicator-size` e `item-indicator-size` a `--size-sm-icon-size`.
El informe `docs/audit/theming/` se regenera entero, así que todas las fichas
actualizan su fecha de medida; las que cambian de contenido son combobox y
gradient-builder.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [combobox ](./combobox.md ) | 76% | 97 | 68 | 12 | 3 | 6 | 8 | 106 | – |
docs(theming): la auditoría de alcance de tema, componente a componente, con su propuesta
El censo medía el eje y no lo explicaba: 5.205 knobs en dos tablas del plan no
dicen QUÉ knob de QUÉ línea no alcanza un tema, ni qué token habría que crear.
Ahora `theming-census.ts --report` escribe la auditoría entera bajo
`docs/audit/theming/`: un README con la vista de conjunto y 170 fichas — 162
recetas con CSS + 8 componentes sin receta, el árbol completo de
`eidos/components/`.
Cada ficha de receta: knobs fuera de alcance con fichero:línea Y selector
(agrupados por clase), sistema transversal aparte, los privados con la columna
que decide («¿deriva de un público?»), y una PROPUESTA de corrección — el token
a declarar en `base.ts` con su valor VERBATIM y su scope TSC. La propuesta
deriva los nombres de recipe-contract §1 y theming §6.7; donde la doctrina no
decide, marca `⚠ decisión` en vez de inventar. Y no propone acuñar lo que la
doctrina prohíbe: lo que posee una capa compartida, el foco, la capa de estado,
un token prestado de otra receta, un shorthand o un eje físico.
Las 8 fichas sin receta dicen —medido, no supuesto— dónde vive su visual: el
componente que componen (icon-button → button), la capa que consumen (affix →
viewport-placement) o la receta ajena que pinta sus attrs (svg → badge/button).
Defectos del instrumento corregidos en el mismo pase, todos encontrados
mirando la salida: un `@import` pegado al primer selector se comía 2 knobs de
color-picker (el suelo del censo no puede moverse); `:not(:disabled)` se leía
como estado y producía `hover-disabled-*`; un knob que lee un privado se
proponía a sí mismo en vez de resolverse por talla; `--icon-size-sm` se
reportaba como préstamo del componente `icon` (ahora el préstamo se verifica
contra las claves del dueño en `base.ts`); y el default de talla salía sin
nombrar en vez de `-md`.
Verificación: censo global idéntico al suelo publicado (5205 · 1621/33% · 856 ·
1880 · 614 · 234) y COMPONENTE A COMPONENTE contra la tabla §9 del plan — 0
diferencias en 162 · regenerar dos veces da el árbol idéntico · el bloque de
veredicto escrito a mano sobrevive · docs:check 0 errores sobre 813 docs ·
prettier limpio (el árbol generado entra en .prettierignore junto a
eidos/generated).
Las 10 primeras fichas llevan ya su veredicto de revisión: análisis correcto en
las 10, propuesta apta en 2 (gradient-builder como piloto, combobox con cinco
correcciones — dos de ellas evitaban romper el default), y 5 que no se
tokenizan en solitario porque son alias de --calendar-*/--field-* y esperan la
decisión de familia. Cuatro destaparon privados con prefijo ajeno o abreviado
declarados en su propio CSS.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [accordion ](./accordion.md ) | 77% | 65 | 49 | 10 | 0 | 5 | 1 | 76 | y |
| [radio-group ](./radio-group.md ) | 77% | 75 | 56 | 10 | 7 | 0 | 2 | 61 | y |
| [chat-log ](./chat-log.md ) | 77% | 42 | 30 | 0 | 4 | 5 | 3 | 31 | – |
| [chat-composer ](./chat-composer.md ) | 79% | 44 | 31 | 0 | 3 | 5 | 5 | 31 | – |
uix(gradient-builder): el editor entero pasa a tokens públicos — un tema lo mueve sin tocar el sistema
Primer componente del eje theme-reach, y su piloto: la receta declaraba CERO
tokens propios («self-contained», decía la cabecera) y ataba cada knob a un
primitivo global o a un privado. Alcance medido: 0 %. Un tema no podía cambiar
ni el alto del preview ni el radio de la tarjeta sin mover el ecosistema.
Ahora los 72 knobs son contrato público del componente. Los ejes dimensionales
siguen el canon de dos piezas que firmó el Sidebar: coordenadas por talla
(`preview-height-{sm,md,lg}`…) más UN nombre resuelto (`host` = md, `size:sm`,
`size:lg`) que es lo único que consume el CSS — así los bloques `[data-size]`
de la receta desaparecen y la cascada la emite el TSC. La geometría se queda
PROPIA (px × `--scaling`): un raíl de edición no tiene coordenada de
control-height, así que forzarlo al bundle habría sido rediseño. La tipografía
sí lo consume, que es lo que el guard `recipe-css-contract` exige.
De paso mueren dos abreviaturas que escondían tokens al censo y podían cruzarse
por anidamiento: `--gb-checker*` y `--gb-stop-fill` pasan a
`--_gradient-builder-*` (también en el wrapper). El damero de transparencia se
parametriza por `checker-color` + `checker-cell`, y el patrón de cuatro
gradientes se queda privado — un tema cambia el color de la celda, no reescribe
la rampa. El `padding` shorthand se parte en ejes lógicos.
El default no se mueve: sonda antes/después con 6.612 valores computados
comparados en 7 estados (reposo · cinco tallas · hover) sobre 34 nodos, diff
VACÍO. El único diff que apareció era la transición de hover de un Button
compuesto capturada a mitad — demostrado reproduciendo el valor interpolado en
el árbol ya modificado, bajando la espera de asentamiento.
Centinela: 72/72 tokens alcanzan. 49 desde el ámbito del componente en reposo;
las 12 coordenadas de talla y las 2 de preset seleccionado forzando su estado;
`hover-preset-border` con hover real; y los 4 del editor de color sólo desde
`:root`, porque el panel viaja por portal — anotado en el README para que nadie
lo lea como un token muerto.
Dos hallazgos que quedan anotados, no corregidos (mueven píxel, así que son
decisión): el wrapper pinta el preview con el shorthand `background` inline, que
resetea `background-image` y tapa el damero, de modo que la transparencia no
llega a verse; y el foco de la parada usa el patrón de dos anillos con
box-shadow cuando §32 canonizó `outline`.
Guards: component:audit PASS · eidos-lint 0 invalid · suite eidos sin rojos
nuevos (queda el conocido skin-media-player) · rtl:check 0 · docs:check 0 ·
check sin errores en los ficheros tocados · censo 0 % → 80 % (el resto son
privados que YA derivan de públicos, el anillo de foco y tres literales de
layout) · captura 2× revisada.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [gradient-builder ](./gradient-builder.md ) | 80% | 60 | 45 | 7 | 1 | 3 | 4 | 72 | – |
docs(theming): la auditoría de alcance de tema, componente a componente, con su propuesta
El censo medía el eje y no lo explicaba: 5.205 knobs en dos tablas del plan no
dicen QUÉ knob de QUÉ línea no alcanza un tema, ni qué token habría que crear.
Ahora `theming-census.ts --report` escribe la auditoría entera bajo
`docs/audit/theming/`: un README con la vista de conjunto y 170 fichas — 162
recetas con CSS + 8 componentes sin receta, el árbol completo de
`eidos/components/`.
Cada ficha de receta: knobs fuera de alcance con fichero:línea Y selector
(agrupados por clase), sistema transversal aparte, los privados con la columna
que decide («¿deriva de un público?»), y una PROPUESTA de corrección — el token
a declarar en `base.ts` con su valor VERBATIM y su scope TSC. La propuesta
deriva los nombres de recipe-contract §1 y theming §6.7; donde la doctrina no
decide, marca `⚠ decisión` en vez de inventar. Y no propone acuñar lo que la
doctrina prohíbe: lo que posee una capa compartida, el foco, la capa de estado,
un token prestado de otra receta, un shorthand o un eje físico.
Las 8 fichas sin receta dicen —medido, no supuesto— dónde vive su visual: el
componente que componen (icon-button → button), la capa que consumen (affix →
viewport-placement) o la receta ajena que pinta sus attrs (svg → badge/button).
Defectos del instrumento corregidos en el mismo pase, todos encontrados
mirando la salida: un `@import` pegado al primer selector se comía 2 knobs de
color-picker (el suelo del censo no puede moverse); `:not(:disabled)` se leía
como estado y producía `hover-disabled-*`; un knob que lee un privado se
proponía a sí mismo en vez de resolverse por talla; `--icon-size-sm` se
reportaba como préstamo del componente `icon` (ahora el préstamo se verifica
contra las claves del dueño en `base.ts`); y el default de talla salía sin
nombrar en vez de `-md`.
Verificación: censo global idéntico al suelo publicado (5205 · 1621/33% · 856 ·
1880 · 614 · 234) y COMPONENTE A COMPONENTE contra la tabla §9 del plan — 0
diferencias en 162 · regenerar dos veces da el árbol idéntico · el bloque de
veredicto escrito a mano sobrevive · docs:check 0 errores sobre 813 docs ·
prettier limpio (el árbol generado entra en .prettierignore junto a
eidos/generated).
Las 10 primeras fichas llevan ya su veredicto de revisión: análisis correcto en
las 10, propuesta apta en 2 (gradient-builder como piloto, combobox con cinco
correcciones — dos de ellas evitaban romper el default), y 5 que no se
tokenizan en solitario porque son alias de --calendar-*/--field-* y esperan la
decisión de familia. Cuatro destaparon privados con prefijo ajeno o abreviado
declarados en su propio CSS.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [chat-message ](./chat-message.md ) | 82% | 84 | 63 | 2 | 6 | 6 | 7 | 75 | y |
| [fab ](./fab.md ) | 82% | 17 | 14 | 0 | 2 | 1 | 0 | 10 | – |
| [toast ](./toast.md ) | 83% | 42 | 35 | 6 | 0 | 1 | 0 | 85 | – |
| [text-circular ](./text-circular.md ) | 83% | 6 | 5 | 0 | 1 | 0 | 0 | 0 | – |
| [tabs ](./tabs.md ) | 88% | 76 | 66 | 6 | 2 | 1 | 1 | 79 | y |
| [chat-typing ](./chat-typing.md ) | 89% | 9 | 8 | 0 | 1 | 0 | 0 | 7 | – |
| [breadcrumb ](./breadcrumb.md ) | 90% | 23 | 18 | 2 | 0 | 0 | 3 | 28 | y |
| [collapsible ](./collapsible.md ) | 90% | 12 | 9 | 0 | 1 | 0 | 2 | 11 | – |
| [scroll-area ](./scroll-area.md ) | 94% | 17 | 15 | 0 | 0 | 1 | 1 | 13 | – |
feat(census): los primitivos tipográficos se miden contra su capa — pieza 0 de F2-A
D-TH.2-b, la firma que va ANTES del bloque porque cambia el suelo del censo:
medirla a mitad de camino falsearía todos los antes/después.
`heading` marcaba «36 knobs, 0 % alcanzable» y eso no era deuda: era una
lectura equivocada. Su receta resuelve cada eje como
`var(--_heading-font-size, var(--style-h2-font-size))` — el privado es el
escape POR INSTANCIA que el wrapper escribe desde una prop, y el named style es
la superficie de tema, ya pública y viva. Acuñar `--heading-*` para espejarla
sería un alias por eje × nivel: la clase que mató la purga del changelog §39.
El criterio de qué ES un primitivo tipográfico se midió, no se supuso: o la
receta SELECCIONA por `data-style` (`heading`, `text`, `s-text` — el named
style es su API) o está atada entera a UN style (`code` → `--style-code-*`,
`display` → `--style-hero-*`, `label` → `--style-label-*`). `code-block` queda
FUERA a propósito: lee un par de tokens de style para su texto pero posee
cromo de caja real, y eso sí es suyo.
Detalle que costó una vuelta: la comprobación va ANTES de la de privado. Leer
el privado primero puntúa el primitivo entero como inalcanzable cuando es
completamente temable — por la capa que lo posee.
antes 5.199 knobs · 1.837 públicos (37 %) · 894 privados · 232 sistema
después 5.199 knobs · 1.837 públicos (38 %) · 788 privados · 338 sistema
**Gate**: 106 knobs pasan de `private` a `system` en los SEIS primitivos y
**cero** de los otros 156 se mueve — verificado componente a componente contra
la versión en HEAD, no a ojo. Alcance `—` (nada que poseer) para heading, text
y display; `s-text` al 100 %; `code` y `label` bajan a 7 y 2 knobs de deuda
real.
Informe regenerado (171 veredictos a mano intactos), veredicto de heading
anotado como ejecutado, y recipe-contract §1 gana el párrafo que fija el
criterio — incluida la frontera: un menú que lee `--style-label-font-family`
para una etiqueta NO es un primitivo y no entra en el conjunto.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [heading ](./heading.md ) | — | 36 | 0 | 0 | 0 | 0 | 36 | 0 | – |
| [s-text ](./s-text.md ) | 100% | 30 | 2 | 0 | 0 | 0 | 28 | 3 | – |
| [text ](./text.md ) | — | 24 | 0 | 0 | 0 | 0 | 24 | 0 | – |
docs(theming): la auditoría de alcance de tema, componente a componente, con su propuesta
El censo medía el eje y no lo explicaba: 5.205 knobs en dos tablas del plan no
dicen QUÉ knob de QUÉ línea no alcanza un tema, ni qué token habría que crear.
Ahora `theming-census.ts --report` escribe la auditoría entera bajo
`docs/audit/theming/`: un README con la vista de conjunto y 170 fichas — 162
recetas con CSS + 8 componentes sin receta, el árbol completo de
`eidos/components/`.
Cada ficha de receta: knobs fuera de alcance con fichero:línea Y selector
(agrupados por clase), sistema transversal aparte, los privados con la columna
que decide («¿deriva de un público?»), y una PROPUESTA de corrección — el token
a declarar en `base.ts` con su valor VERBATIM y su scope TSC. La propuesta
deriva los nombres de recipe-contract §1 y theming §6.7; donde la doctrina no
decide, marca `⚠ decisión` en vez de inventar. Y no propone acuñar lo que la
doctrina prohíbe: lo que posee una capa compartida, el foco, la capa de estado,
un token prestado de otra receta, un shorthand o un eje físico.
Las 8 fichas sin receta dicen —medido, no supuesto— dónde vive su visual: el
componente que componen (icon-button → button), la capa que consumen (affix →
viewport-placement) o la receta ajena que pinta sus attrs (svg → badge/button).
Defectos del instrumento corregidos en el mismo pase, todos encontrados
mirando la salida: un `@import` pegado al primer selector se comía 2 knobs de
color-picker (el suelo del censo no puede moverse); `:not(:disabled)` se leía
como estado y producía `hover-disabled-*`; un knob que lee un privado se
proponía a sí mismo en vez de resolverse por talla; `--icon-size-sm` se
reportaba como préstamo del componente `icon` (ahora el préstamo se verifica
contra las claves del dueño en `base.ts`); y el default de talla salía sin
nombrar en vez de `-md`.
Verificación: censo global idéntico al suelo publicado (5205 · 1621/33% · 856 ·
1880 · 614 · 234) y COMPONENTE A COMPONENTE contra la tabla §9 del plan — 0
diferencias en 162 · regenerar dos veces da el árbol idéntico · el bloque de
veredicto escrito a mano sobrevive · docs:check 0 errores sobre 813 docs ·
prettier limpio (el árbol generado entra en .prettierignore junto a
eidos/generated).
Las 10 primeras fichas llevan ya su veredicto de revisión: análisis correcto en
las 10, propuesta apta en 2 (gradient-builder como piloto, combobox con cinco
correcciones — dos de ellas evitaban romper el default), y 5 que no se
tokenizan en solitario porque son alias de --calendar-*/--field-* y esperan la
decisión de familia. Cuatro destaparon privados con prefijo ajeno o abreviado
declarados en su propio CSS.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [chat-list ](./chat-list.md ) | 100% | 18 | 18 | 0 | 0 | 0 | 0 | 18 | – |
docs(theming): el informe habla el idioma nuevo — y el fleco del README, cerrado
Al rendir cuentas del repaso de los 7 salió un fleco: el README de
gradient-builder mencionaba `checker-color` por su clave SUELTA, sin el
prefijo `--gradient-builder-`, y el codemod busca tokens completos — quedó con
el nombre muerto. Dos líneas corregidas, más las dos del §5 de su ficha.
Y la causa de fondo: las 170 fichas del informe llevaban desde el codemod
citando el contrato con los nombres viejos en sus secciones generadas.
Regenerado entero (`--report`): 69 fichas cambian, los 171 veredictos §5
escritos a mano sobreviven (verificado), `docs:check` 0.
El censo del informe registra 5.199 knobs · 1.837 públicos — cuatro menos que
el suelo del codemod, que son EXACTAMENTE las cuatro declaraciones de hover
bespoke que la firma 3 retiró (checkbox, splitter, switch, drp ×2 −1 nueva del
checked). El alcance global sigue en 37 %.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [splitter ](./splitter.md ) | 100% | 18 | 17 | 0 | 0 | 0 | 1 | 15 | – |
docs(theming): la auditoría de alcance de tema, componente a componente, con su propuesta
El censo medía el eje y no lo explicaba: 5.205 knobs en dos tablas del plan no
dicen QUÉ knob de QUÉ línea no alcanza un tema, ni qué token habría que crear.
Ahora `theming-census.ts --report` escribe la auditoría entera bajo
`docs/audit/theming/`: un README con la vista de conjunto y 170 fichas — 162
recetas con CSS + 8 componentes sin receta, el árbol completo de
`eidos/components/`.
Cada ficha de receta: knobs fuera de alcance con fichero:línea Y selector
(agrupados por clase), sistema transversal aparte, los privados con la columna
que decide («¿deriva de un público?»), y una PROPUESTA de corrección — el token
a declarar en `base.ts` con su valor VERBATIM y su scope TSC. La propuesta
deriva los nombres de recipe-contract §1 y theming §6.7; donde la doctrina no
decide, marca `⚠ decisión` en vez de inventar. Y no propone acuñar lo que la
doctrina prohíbe: lo que posee una capa compartida, el foco, la capa de estado,
un token prestado de otra receta, un shorthand o un eje físico.
Las 8 fichas sin receta dicen —medido, no supuesto— dónde vive su visual: el
componente que componen (icon-button → button), la capa que consumen (affix →
viewport-placement) o la receta ajena que pinta sus attrs (svg → badge/button).
Defectos del instrumento corregidos en el mismo pase, todos encontrados
mirando la salida: un `@import` pegado al primer selector se comía 2 knobs de
color-picker (el suelo del censo no puede moverse); `:not(:disabled)` se leía
como estado y producía `hover-disabled-*`; un knob que lee un privado se
proponía a sí mismo en vez de resolverse por talla; `--icon-size-sm` se
reportaba como préstamo del componente `icon` (ahora el préstamo se verifica
contra las claves del dueño en `base.ts`); y el default de talla salía sin
nombrar en vez de `-md`.
Verificación: censo global idéntico al suelo publicado (5205 · 1621/33% · 856 ·
1880 · 614 · 234) y COMPONENTE A COMPONENTE contra la tabla §9 del plan — 0
diferencias en 162 · regenerar dos veces da el árbol idéntico · el bloque de
veredicto escrito a mano sobrevive · docs:check 0 errores sobre 813 docs ·
prettier limpio (el árbol generado entra en .prettierignore junto a
eidos/generated).
Las 10 primeras fichas llevan ya su veredicto de revisión: análisis correcto en
las 10, propuesta apta en 2 (gradient-builder como piloto, combobox con cinco
correcciones — dos de ellas evitaban romper el default), y 5 que no se
tokenizan en solitario porque son alias de --calendar-*/--field-* y esperan la
decisión de familia. Cuatro destaparon privados con prefijo ajeno o abreviado
declarados en su propio CSS.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [box ](./box.md ) | 100% | 9 | 9 | 0 | 0 | 0 | 0 | 43 | – |
feat(census): los primitivos tipográficos se miden contra su capa — pieza 0 de F2-A
D-TH.2-b, la firma que va ANTES del bloque porque cambia el suelo del censo:
medirla a mitad de camino falsearía todos los antes/después.
`heading` marcaba «36 knobs, 0 % alcanzable» y eso no era deuda: era una
lectura equivocada. Su receta resuelve cada eje como
`var(--_heading-font-size, var(--style-h2-font-size))` — el privado es el
escape POR INSTANCIA que el wrapper escribe desde una prop, y el named style es
la superficie de tema, ya pública y viva. Acuñar `--heading-*` para espejarla
sería un alias por eje × nivel: la clase que mató la purga del changelog §39.
El criterio de qué ES un primitivo tipográfico se midió, no se supuso: o la
receta SELECCIONA por `data-style` (`heading`, `text`, `s-text` — el named
style es su API) o está atada entera a UN style (`code` → `--style-code-*`,
`display` → `--style-hero-*`, `label` → `--style-label-*`). `code-block` queda
FUERA a propósito: lee un par de tokens de style para su texto pero posee
cromo de caja real, y eso sí es suyo.
Detalle que costó una vuelta: la comprobación va ANTES de la de privado. Leer
el privado primero puntúa el primitivo entero como inalcanzable cuando es
completamente temable — por la capa que lo posee.
antes 5.199 knobs · 1.837 públicos (37 %) · 894 privados · 232 sistema
después 5.199 knobs · 1.837 públicos (38 %) · 788 privados · 338 sistema
**Gate**: 106 knobs pasan de `private` a `system` en los SEIS primitivos y
**cero** de los otros 156 se mueve — verificado componente a componente contra
la versión en HEAD, no a ojo. Alcance `—` (nada que poseer) para heading, text
y display; `s-text` al 100 %; `code` y `label` bajan a 7 y 2 knobs de deuda
real.
Informe regenerado (171 veredictos a mano intactos), veredicto de heading
anotado como ejecutado, y recipe-contract §1 gana el párrafo que fija el
criterio — incluida la frontera: un menú que lee `--style-label-font-family`
para una etiqueta NO es un primitivo y no entra en el conjunto.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [display ](./display.md ) | — | 6 | 0 | 0 | 0 | 0 | 6 | 0 | – |
docs(theming): la auditoría de alcance de tema, componente a componente, con su propuesta
El censo medía el eje y no lo explicaba: 5.205 knobs en dos tablas del plan no
dicen QUÉ knob de QUÉ línea no alcanza un tema, ni qué token habría que crear.
Ahora `theming-census.ts --report` escribe la auditoría entera bajo
`docs/audit/theming/`: un README con la vista de conjunto y 170 fichas — 162
recetas con CSS + 8 componentes sin receta, el árbol completo de
`eidos/components/`.
Cada ficha de receta: knobs fuera de alcance con fichero:línea Y selector
(agrupados por clase), sistema transversal aparte, los privados con la columna
que decide («¿deriva de un público?»), y una PROPUESTA de corrección — el token
a declarar en `base.ts` con su valor VERBATIM y su scope TSC. La propuesta
deriva los nombres de recipe-contract §1 y theming §6.7; donde la doctrina no
decide, marca `⚠ decisión` en vez de inventar. Y no propone acuñar lo que la
doctrina prohíbe: lo que posee una capa compartida, el foco, la capa de estado,
un token prestado de otra receta, un shorthand o un eje físico.
Las 8 fichas sin receta dicen —medido, no supuesto— dónde vive su visual: el
componente que componen (icon-button → button), la capa que consumen (affix →
viewport-placement) o la receta ajena que pinta sus attrs (svg → badge/button).
Defectos del instrumento corregidos en el mismo pase, todos encontrados
mirando la salida: un `@import` pegado al primer selector se comía 2 knobs de
color-picker (el suelo del censo no puede moverse); `:not(:disabled)` se leía
como estado y producía `hover-disabled-*`; un knob que lee un privado se
proponía a sí mismo en vez de resolverse por talla; `--icon-size-sm` se
reportaba como préstamo del componente `icon` (ahora el préstamo se verifica
contra las claves del dueño en `base.ts`); y el default de talla salía sin
nombrar en vez de `-md`.
Verificación: censo global idéntico al suelo publicado (5205 · 1621/33% · 856 ·
1880 · 614 · 234) y COMPONENTE A COMPONENTE contra la tabla §9 del plan — 0
diferencias en 162 · regenerar dos veces da el árbol idéntico · el bloque de
veredicto escrito a mano sobrevive · docs:check 0 errores sobre 813 docs ·
prettier limpio (el árbol generado entra en .prettierignore junto a
eidos/generated).
Las 10 primeras fichas llevan ya su veredicto de revisión: análisis correcto en
las 10, propuesta apta en 2 (gradient-builder como piloto, combobox con cinco
correcciones — dos de ellas evitaban romper el default), y 5 que no se
tokenizan en solitario porque son alias de --calendar-*/--field-* y esperan la
decisión de familia. Cuatro destaparon privados con prefijo ajeno o abreviado
declarados en su propio CSS.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [barcode ](./barcode.md ) | 100% | 5 | 5 | 0 | 0 | 0 | 0 | 7 | – |
| [flex ](./flex.md ) | 100% | 2 | 2 | 0 | 0 | 0 | 0 | 7 | – |
| [grid ](./grid.md ) | 100% | 2 | 2 | 0 | 0 | 0 | 0 | 13 | – |
| [alert-dialog ](./alert-dialog.md ) | — | 0 | 0 | 0 | 0 | 0 | 0 | 0 | – |
| [auto-grid ](./auto-grid.md ) | — | 0 | 0 | 0 | 0 | 0 | 0 | 0 | – |
| [container ](./container.md ) | — | 0 | 0 | 0 | 0 | 0 | 0 | 1 | – |
| [css-field ](./css-field.md ) | — | 0 | 0 | 0 | 0 | 0 | 0 | 0 | – |
| [float ](./float.md ) | — | 0 | 0 | 0 | 0 | 0 | 0 | 1 | – |
| [group ](./group.md ) | — | 0 | 0 | 0 | 0 | 0 | 0 | 1 | – |
| [highlight ](./highlight.md ) | — | 0 | 0 | 0 | 0 | 0 | 0 | 0 | – |
| [icon ](./icon.md ) | — | 0 | 0 | 0 | 0 | 0 | 0 | 2 | – |
| [mask-field ](./mask-field.md ) | — | 0 | 0 | 0 | 0 | 0 | 0 | 0 | – |
| [number-field ](./number-field.md ) | — | 0 | 0 | 0 | 0 | 0 | 0 | 0 | – |
| [stack ](./stack.md ) | — | 0 | 0 | 0 | 0 | 0 | 0 | 0 | – |
| [wrap ](./wrap.md ) | — | 0 | 0 | 0 | 0 | 0 | 0 | 0 | – |
## Veredicto y decisiones
<!-- veredicto:start -->
_(pendiente — lo escribe el autor; se conserva al regenerar)_
<!-- veredicto:end -->