You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte-kit-vice/docs/audit/theming/README.md

277 lines
19 KiB

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(grid-list): temable — 0 % → 85 %, y una selección que nunca pintó 38 claves nuevas en el bloque `grid-list` de `recipes/base.ts` (que ya existía con los dos forwards de paleta: se FUSIONA, no se añade un segundo). Alcance del censo 0 % → 85 % (22 de 26 puntuables); global 45 % → 46 %, sin contrato 49 → 48. El eje `size` se estampa en el PROVIDER —el wrapper de eidos no tiene parte `root`—, así que los tres nombres resueltos van SIN `parts`: molde `command`, no `table`/`tree-grid`. Fuera los cuatro bloques `[data-size]` del CSS; los emite el TSC. Altura de fila 1:1 con el bundle, `row-padding-inline` con ritmo propio, y la tipografía un paso por debajo de md en adelante — verbatim, como table y tree-grid. LO QUE LA MEDICIÓN CAMBIÓ (la §4 generada tenía un error de doctrina y dos defectos que sólo aparecieron midiendo; el §5 Veredicto se escribió con la sonda delante, porque estaba vacío): 1. La selección de fila NUNCA HA PINTADO. La receta seleccionaba `[data-grid-list-row][data-selected]`, un atributo que ni el morfo declara ni soma estampa (estampa `data-state='selected'` + `aria-selected`): la regla no casaba jamás y su acento `--_grid-list-palette-element` no llegó nunca al píxel — una fila seleccionada muestra el velo NEUTRO del arquetipo, indistinguible del hover (capturado). Retirada la declaración muerta y su forward huérfano: 0 diffs, que es la prueba. Repararlo mueve píxel y choca con §12.5 (el arquetipo fija también `color`) → §13, espera firma. El acento del checkbox (`_palette-solid`) sí vive y se conserva. 2. NO se acuña `hover-row-bg` aunque la propuesta lo pedía. La fila es `archetype: 'item'`: el velo del sistema la pinta a especificidad plena y el plano de la receta pierde — medido, el hover pinta DOS VECES sobre el MISMO nodo (a diferencia de table/tree-grid, donde velo y plano caen en nodos distintos). Sería un token que no puede ganar; mismo criterio que listbox.highlighted → §12.7. Y fila Y celda llevan ambas `item`, así que bajo el puntero se apilan tres capas. 3. «Consume la capa compartida `menu-indicator`» es FALSO. Sale de `SHARED_LAYERS` (`theming-census.ts:432`), pero esa capa no tiene un solo selector de grid-list, la receta no la importa y soma no renderiza indicator: el checkbox ESPEJA el visual pintándolo por su cuenta. Entrada desviada del censo → §13 (listbox / menubar / navigation-menu están en la misma entrada y tampoco aparecen en el fichero). Nombres, sobre la propuesta: `selection-checkbox-{width,height}` son UN knob → `selection-checkbox-size`; `on-selection-checkbox-bg` → `checked-selection-checkbox-fg` (es la tinta del glifo, y `on-` es prefijo reservado); `border` partido en `border-width` + color (molde `command.input-border*`), que el checkbox comparte; `padding` uniforme se queda `padding` (precedente `command.viewport-padding`); `max-block` entra al contrato (molde `command.viewport-max-block`). Artefactos y gates: - Sonda antes/después = 0 diffs en 6.090 valores × 7 estados. Determinismo verificado: dos corridas del mismo código, 0 diffs. - R-5.4: 37/38 tokens mueven un computed. `invalid-border` adjudicado EN EL LEDGER con su razón medida (la demo arranca con su control en off; activado a mano alcanza: oklch(0.9555 0.0207 13.86) → rgb(1,2,3)). - censo --only 85 % · component:audit PASS (R-5.3 incluida) · eidos-lint invalid 0, class-hooks 0 · suite eidos sin rojos nuevos (el único es el conocido skin-media-player) · rtl:check 0 · docs:check 0 · check por fichero limpio (72 globales, ninguno mío). - README con su «Talla y tema» y tab `Tokens` en la demo (38 claves, leídas en vivo). El tab `Recipe` documentaba la regla retirada: corregido. Las fichas de calendar / carousel / command / month-grid / range-calendar / table / year-grid entran porque `--report` regenera el informe entero: sólo actualizan NÚMEROS DE LÍNEA de commits ya hechos que no lo regeneraron. Cero cambios de alcance. Las otras 161, que sólo cambiaban la fecha, se revirtieron. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2 months ago
- **Medido**: 2026-08-21 · **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**?
uix(clipboard): temable — 0 % → 63 %, todo en la píldora de «Copied!» 6 claves fusionadas en el bloque `clipboard` de `recipes/base.ts` (donde ya vivían los dos forwards de paleta). Censo 0 % → 63 %. **Todo lo tokenizable es el INDICADOR.** El host va `display: contents` y el trigger reusa la receta de `Button` por el patrón de consumidor, así que la receta sólo posee la píldora que aparece un instante tras copiar. - Los dos forwards de paleta siguen privados (THM-2): el fondo y la tinta del chip los leen a pelo, sin sitio donde meter un público sin duplicar la regla — son el 37 % que no alcanza. - `font-family` queda fuera por la misma razón que en code-block, kbd y announce: lo posee la capa tipográfica. - El padding es un shorthand de dos valores → dos knobs lógicos. - **Los `--motion-*` no son knobs de tema**: son los ganchos con que el indicador afina el preset `scale-fade` del canal de motion (escala 0.85, rápida). Pertenecen al canal, no al contrato, y la política de `prefers-reduced-motion` la emite el generador. Artefactos y gates: - Sonda antes/después = 0 diffs en 1.392 valores × 8 estados. - R-5.4: 0/6, los seis adjudicados con su medición — el indicador sólo existe un instante tras copiar (0 nodos en reposo, contados) y forzándolo los seis mueven su propiedad (gap 4→1234px, padding 2/8→1235/1236px, radio 9999→1237px, tipo 12→99px, peso 500→123). - censo --only 63 % · component:audit PASS · suite eidos sin rojos nuevos · rtl:check 0 · docs:check 0 · check por fichero limpio. - README con «Talla y tema» y tab `Tokens` en la demo (6 claves). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2 months ago
- **Alcance global**: **50%** — 2323 de 4676 knobs pasan por un token público del componente
- **Reparto**: público 2323 · privado 627 · global 1160 · literal 566 · sistema transversal 509 _(fuera del ratio)_
- **Sin token público propio**: 32 · **alcance < 20 %**: 25 · **alcance 100 %**: 10 · **con eje `size`**: 59
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 |
uix(grid-list): temable — 0 % → 85 %, y una selección que nunca pintó 38 claves nuevas en el bloque `grid-list` de `recipes/base.ts` (que ya existía con los dos forwards de paleta: se FUSIONA, no se añade un segundo). Alcance del censo 0 % → 85 % (22 de 26 puntuables); global 45 % → 46 %, sin contrato 49 → 48. El eje `size` se estampa en el PROVIDER —el wrapper de eidos no tiene parte `root`—, así que los tres nombres resueltos van SIN `parts`: molde `command`, no `table`/`tree-grid`. Fuera los cuatro bloques `[data-size]` del CSS; los emite el TSC. Altura de fila 1:1 con el bundle, `row-padding-inline` con ritmo propio, y la tipografía un paso por debajo de md en adelante — verbatim, como table y tree-grid. LO QUE LA MEDICIÓN CAMBIÓ (la §4 generada tenía un error de doctrina y dos defectos que sólo aparecieron midiendo; el §5 Veredicto se escribió con la sonda delante, porque estaba vacío): 1. La selección de fila NUNCA HA PINTADO. La receta seleccionaba `[data-grid-list-row][data-selected]`, un atributo que ni el morfo declara ni soma estampa (estampa `data-state='selected'` + `aria-selected`): la regla no casaba jamás y su acento `--_grid-list-palette-element` no llegó nunca al píxel — una fila seleccionada muestra el velo NEUTRO del arquetipo, indistinguible del hover (capturado). Retirada la declaración muerta y su forward huérfano: 0 diffs, que es la prueba. Repararlo mueve píxel y choca con §12.5 (el arquetipo fija también `color`) → §13, espera firma. El acento del checkbox (`_palette-solid`) sí vive y se conserva. 2. NO se acuña `hover-row-bg` aunque la propuesta lo pedía. La fila es `archetype: 'item'`: el velo del sistema la pinta a especificidad plena y el plano de la receta pierde — medido, el hover pinta DOS VECES sobre el MISMO nodo (a diferencia de table/tree-grid, donde velo y plano caen en nodos distintos). Sería un token que no puede ganar; mismo criterio que listbox.highlighted → §12.7. Y fila Y celda llevan ambas `item`, así que bajo el puntero se apilan tres capas. 3. «Consume la capa compartida `menu-indicator`» es FALSO. Sale de `SHARED_LAYERS` (`theming-census.ts:432`), pero esa capa no tiene un solo selector de grid-list, la receta no la importa y soma no renderiza indicator: el checkbox ESPEJA el visual pintándolo por su cuenta. Entrada desviada del censo → §13 (listbox / menubar / navigation-menu están en la misma entrada y tampoco aparecen en el fichero). Nombres, sobre la propuesta: `selection-checkbox-{width,height}` son UN knob → `selection-checkbox-size`; `on-selection-checkbox-bg` → `checked-selection-checkbox-fg` (es la tinta del glifo, y `on-` es prefijo reservado); `border` partido en `border-width` + color (molde `command.input-border*`), que el checkbox comparte; `padding` uniforme se queda `padding` (precedente `command.viewport-padding`); `max-block` entra al contrato (molde `command.viewport-max-block`). Artefactos y gates: - Sonda antes/después = 0 diffs en 6.090 valores × 7 estados. Determinismo verificado: dos corridas del mismo código, 0 diffs. - R-5.4: 37/38 tokens mueven un computed. `invalid-border` adjudicado EN EL LEDGER con su razón medida (la demo arranca con su control en off; activado a mano alcanza: oklch(0.9555 0.0207 13.86) → rgb(1,2,3)). - censo --only 85 % · component:audit PASS (R-5.3 incluida) · eidos-lint invalid 0, class-hooks 0 · suite eidos sin rojos nuevos (el único es el conocido skin-media-player) · rtl:check 0 · docs:check 0 · check por fichero limpio (72 globales, ninguno mío). - README con su «Talla y tema» y tab `Tokens` en la demo (38 claves, leídas en vivo). El tab `Recipe` documentaba la regla retirada: corregido. Las fichas de calendar / carousel / command / month-grid / range-calendar / table / year-grid entran porque `--report` regenera el informe entero: sólo actualizan NÚMEROS DE LÍNEA de commits ya hechos que no lo regeneraron. Cero cambios de alcance. Las otras 161, que sólo cambiaban la fecha, se revirtieron. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2 months ago
| 3 | [chart](./chart.md) | 80 | 9% | 92 | 17 |
| 4 | [proof-of-human](./proof-of-human.md) | 78 | 14% | 95 | 20 |
| 5 | [prose](./prose.md) | 73 | 1% | 74 | 2 |
| 6 | [time-range-picker](./time-range-picker.md) | 68 | 19% | 88 | 22 |
| 7 | [time-picker](./time-picker.md) | 47 | 18% | 59 | 16 |
| 8 | [color-picker](./color-picker.md) | 43 | 46% | 82 | 54 |
| 9 | [field-langs](./field-langs.md) | 39 | 0% | 41 | 0 |
| 10 | [field](./field.md) | 33 | 51% | 73 | 60 |
| 11 | [date-range-picker](./date-range-picker.md) | 30 | 40% | 53 | 22 |
| 12 | [natural-time-picker](./natural-time-picker.md) | 30 | 61% | 77 | 62 |
| 13 | [popover](./popover.md) | 28 | 42% | 51 | 36 |
| 14 | [radio-cards](./radio-cards.md) | 28 | 60% | 72 | 39 |
| 15 | [drawer](./drawer.md) | 27 | 55% | 62 | 44 |
uix(code-block): temable — 0 % → 81 %, y la demo que no enseña el componente 20 claves en una entrada NUEVA de `recipes/base.ts` (no tenía). Censo 0 % → 81 %. Global 46 % → 47 %, sin contrato 46 → 45. El handoff lo llamaba «el más mecánico de los que quedan». No lo es: sus 26 knobs se parten en dos grupos con doctrinas distintas. 1. **El nodo del código NO acuña nada, y la §4 pedía que lo hiciera.** `[data-code-block-code]` consume la capa tipográfica `--style-code-*` en sus cinco declaraciones, y las dos que pasan por privado usan la forma canónica de la escotilla por instancia (`var(--_code-block-font-size, var(--style-code-font-size))`, escrita por el wrapper desde la prop `size` y sólo si llega). Es el patrón que D-TH.2-b fijó para heading/text/code. Acuñar `code-font-family` y compañía sería el vocabulario paralelo que la regla 2 de capas prohíbe. Todo lo que entra al contrato es el CASCO alrededor. 2. **Los tres `font-size` iban al primitivo crudo, y lo cazó un guard.** La propuesta copia el valor del CSS verbatim, y ese valor ya violaba `recipe-css-contract` («recipes consume the size bundle, not the raw size-coordinate primitives»): `title/lang/copy-font-size` corregidos a `var(--size-{k}-font-size)`. Los alias son 1:1 → 0 diffs tras aplicarlo. Aviso general: cuando el CSS de partida ya incumple el contrato, la propuesta generada hereda el incumplimiento. 3. Shorthand partidos: los dos `border` y el `border-bottom` de la cabecera comparten anchura y color → `border-width` + `border`; el `padding` del `<pre>` → `pre-padding`. Los `transparent` de outline/ghost y el `border: 0` de ghost son identidad de variante. El 19 % que falta son esas cinco de la capa, que el censo cuenta como `global` porque `code-block` no está en `TYPOGRAPHIC_PRIMITIVES` — es un compuesto que CONTIENE un primitivo tipográfico, no uno de ellos. Extender la clase `system` del censo a las capas sigue pendiente de tu firma; la métrica penaliza hacer lo correcto y no se fuerza de oficio. DOS HALLAZGOS QUE NO SE ARREGLAN AQUÍ (→ next-features §13): - **La demo de `code-block` no enseña el `code-block`.** `[data-uix-docs] pre` (`web/routes/uix/uix.css:801`) pesa (0,1,1) contra los (0,1,0) de `[data-code-block-pre]`, y `[data-uix-docs]` es el shell de TODAS las páginas. Siete propiedades del `<pre>` las pinta el harness y no la receta: padding (16px 20px contra 12px), border (1px contra ninguno), radius (8px contra 0), background (gris contra transparente), font-family, font-size (13 contra 14) y line-height (18.2 contra 20.3). El fondo, el borde y el radio que se ven ahí son del sitio. Por eso `pre-padding` lee muerto en el guard, adjudicado con esa medición. Acotar la regla toca el CSS del SITIO, que sirve a ~162 páginas: decisión aparte. - **El guard de claves duplicadas del handoff inspeccionaba el VACÍO.** El comando documentado usa `grep -oE "^\t…"`, y `grep -E` lee `\t` como una `t` literal: 0 coincidencias sobre 130 bloques reales, así que salía «vacío = OK» sin mirar nada — el antipatrón que el proyecto tiene registrado, dentro del propio handoff. Comprobado con un contador fiable: cero duplicados en el árbol, así que no hay daño en los commits que confiaron en él. CONTINUE queda corregido con una versión que CUENTA los bloques y avisa de que «0 bloques» significa guard roto, no fichero limpio. Artefactos y gates: - Sonda antes/después = 0 diffs en 1.305 valores × 7 estados (dos veces: tras la tokenización y tras la corrección del bundle). Determinismo verificado. - R-5.4: 19/20; `pre-padding` adjudicado con las siete propiedades medidas. - censo --only 81 % · component:audit PASS · eidos-lint invalid 0, class-hooks 0 · suite eidos de vuelta al único rojo conocido (skin-media-player) tras corregir el bundle · rtl:check 0 · docs:check 0 · check por fichero limpio. - README con su «Talla y tema» y tab `Tokens` en la demo (20 claves, en vivo). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2 months ago
| 16 | [mockup](./mockup.md) | 25 | 14% | 29 | 0 |
| 17 | [aura](./aura.md) | 24 | 31% | 35 | 24 |
| 18 | [password-field](./password-field.md) | 24 | 31% | 36 | 23 |
| 19 | [timeline](./timeline.md) | 24 | 51% | 49 | 45 |
| 20 | [avatar](./avatar.md) | 23 | 36% | 36 | 0 |
uix(grid-list): temable — 0 % → 85 %, y una selección que nunca pintó 38 claves nuevas en el bloque `grid-list` de `recipes/base.ts` (que ya existía con los dos forwards de paleta: se FUSIONA, no se añade un segundo). Alcance del censo 0 % → 85 % (22 de 26 puntuables); global 45 % → 46 %, sin contrato 49 → 48. El eje `size` se estampa en el PROVIDER —el wrapper de eidos no tiene parte `root`—, así que los tres nombres resueltos van SIN `parts`: molde `command`, no `table`/`tree-grid`. Fuera los cuatro bloques `[data-size]` del CSS; los emite el TSC. Altura de fila 1:1 con el bundle, `row-padding-inline` con ritmo propio, y la tipografía un paso por debajo de md en adelante — verbatim, como table y tree-grid. LO QUE LA MEDICIÓN CAMBIÓ (la §4 generada tenía un error de doctrina y dos defectos que sólo aparecieron midiendo; el §5 Veredicto se escribió con la sonda delante, porque estaba vacío): 1. La selección de fila NUNCA HA PINTADO. La receta seleccionaba `[data-grid-list-row][data-selected]`, un atributo que ni el morfo declara ni soma estampa (estampa `data-state='selected'` + `aria-selected`): la regla no casaba jamás y su acento `--_grid-list-palette-element` no llegó nunca al píxel — una fila seleccionada muestra el velo NEUTRO del arquetipo, indistinguible del hover (capturado). Retirada la declaración muerta y su forward huérfano: 0 diffs, que es la prueba. Repararlo mueve píxel y choca con §12.5 (el arquetipo fija también `color`) → §13, espera firma. El acento del checkbox (`_palette-solid`) sí vive y se conserva. 2. NO se acuña `hover-row-bg` aunque la propuesta lo pedía. La fila es `archetype: 'item'`: el velo del sistema la pinta a especificidad plena y el plano de la receta pierde — medido, el hover pinta DOS VECES sobre el MISMO nodo (a diferencia de table/tree-grid, donde velo y plano caen en nodos distintos). Sería un token que no puede ganar; mismo criterio que listbox.highlighted → §12.7. Y fila Y celda llevan ambas `item`, así que bajo el puntero se apilan tres capas. 3. «Consume la capa compartida `menu-indicator`» es FALSO. Sale de `SHARED_LAYERS` (`theming-census.ts:432`), pero esa capa no tiene un solo selector de grid-list, la receta no la importa y soma no renderiza indicator: el checkbox ESPEJA el visual pintándolo por su cuenta. Entrada desviada del censo → §13 (listbox / menubar / navigation-menu están en la misma entrada y tampoco aparecen en el fichero). Nombres, sobre la propuesta: `selection-checkbox-{width,height}` son UN knob → `selection-checkbox-size`; `on-selection-checkbox-bg` → `checked-selection-checkbox-fg` (es la tinta del glifo, y `on-` es prefijo reservado); `border` partido en `border-width` + color (molde `command.input-border*`), que el checkbox comparte; `padding` uniforme se queda `padding` (precedente `command.viewport-padding`); `max-block` entra al contrato (molde `command.viewport-max-block`). Artefactos y gates: - Sonda antes/después = 0 diffs en 6.090 valores × 7 estados. Determinismo verificado: dos corridas del mismo código, 0 diffs. - R-5.4: 37/38 tokens mueven un computed. `invalid-border` adjudicado EN EL LEDGER con su razón medida (la demo arranca con su control en off; activado a mano alcanza: oklch(0.9555 0.0207 13.86) → rgb(1,2,3)). - censo --only 85 % · component:audit PASS (R-5.3 incluida) · eidos-lint invalid 0, class-hooks 0 · suite eidos sin rojos nuevos (el único es el conocido skin-media-player) · rtl:check 0 · docs:check 0 · check por fichero limpio (72 globales, ninguno mío). - README con su «Talla y tema» y tab `Tokens` en la demo (38 claves, leídas en vivo). El tab `Recipe` documentaba la regla retirada: corregido. Las fichas de calendar / carousel / command / month-grid / range-calendar / table / year-grid entran porque `--report` regenera el informe entero: sólo actualizan NÚMEROS DE LÍNEA de commits ya hechos que no lo regeneraron. Cero cambios de alcance. Las otras 161, que sólo cambiaban la fecha, se revirtieron. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2 months ago
uix(clipboard): temable — 0 % → 63 %, todo en la píldora de «Copied!» 6 claves fusionadas en el bloque `clipboard` de `recipes/base.ts` (donde ya vivían los dos forwards de paleta). Censo 0 % → 63 %. **Todo lo tokenizable es el INDICADOR.** El host va `display: contents` y el trigger reusa la receta de `Button` por el patrón de consumidor, así que la receta sólo posee la píldora que aparece un instante tras copiar. - Los dos forwards de paleta siguen privados (THM-2): el fondo y la tinta del chip los leen a pelo, sin sitio donde meter un público sin duplicar la regla — son el 37 % que no alcanza. - `font-family` queda fuera por la misma razón que en code-block, kbd y announce: lo posee la capa tipográfica. - El padding es un shorthand de dos valores → dos knobs lógicos. - **Los `--motion-*` no son knobs de tema**: son los ganchos con que el indicador afina el preset `scale-fade` del canal de motion (escala 0.85, rápida). Pertenecen al canal, no al contrato, y la política de `prefers-reduced-motion` la emite el generador. Artefactos y gates: - Sonda antes/después = 0 diffs en 1.392 valores × 8 estados. - R-5.4: 0/6, los seis adjudicados con su medición — el indicador sólo existe un instante tras copiar (0 nodos en reposo, contados) y forzándolo los seis mueven su propiedad (gap 4→1234px, padding 2/8→1235/1236px, radio 9999→1237px, tipo 12→99px, peso 500→123). - censo --only 63 % · component:audit PASS · suite eidos sin rojos nuevos · rtl:check 0 · docs:check 0 · check por fichero limpio. - README con «Talla y tema» y tab `Tokens` en la demo (6 claves). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2 months ago
## Sin ningún token público propio (32)
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.
uix(clipboard): temable — 0 % → 63 %, todo en la píldora de «Copied!» 6 claves fusionadas en el bloque `clipboard` de `recipes/base.ts` (donde ya vivían los dos forwards de paleta). Censo 0 % → 63 %. **Todo lo tokenizable es el INDICADOR.** El host va `display: contents` y el trigger reusa la receta de `Button` por el patrón de consumidor, así que la receta sólo posee la píldora que aparece un instante tras copiar. - Los dos forwards de paleta siguen privados (THM-2): el fondo y la tinta del chip los leen a pelo, sin sitio donde meter un público sin duplicar la regla — son el 37 % que no alcanza. - `font-family` queda fuera por la misma razón que en code-block, kbd y announce: lo posee la capa tipográfica. - El padding es un shorthand de dos valores → dos knobs lógicos. - **Los `--motion-*` no son knobs de tema**: son los ganchos con que el indicador afina el preset `scale-fade` del canal de motion (escala 0.85, rápida). Pertenecen al canal, no al contrato, y la política de `prefers-reduced-motion` la emite el generador. Artefactos y gates: - Sonda antes/después = 0 diffs en 1.392 valores × 8 estados. - R-5.4: 0/6, los seis adjudicados con su medición — el indicador sólo existe un instante tras copiar (0 nodos en reposo, contados) y forzándolo los seis mueven su propiedad (gap 4→1234px, padding 2/8→1235/1236px, radio 9999→1237px, tipo 12→99px, peso 500→123). - censo --only 63 % · component:audit PASS · suite eidos sin rojos nuevos · rtl:check 0 · docs:check 0 · check por fichero limpio. - README con «Talla y tema» y tab `Tokens` en la demo (6 claves). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2 months ago
[`alert-dialog`](./alert-dialog.md) · [`aspect-ratio`](./aspect-ratio.md) · [`auto-grid`](./auto-grid.md) · [`avatar`](./avatar.md) · [`cascade`](./cascade.md) · [`css-field`](./css-field.md) · [`date-picker`](./date-picker.md) · [`display`](./display.md) · [`field-langs`](./field-langs.md) · [`heading`](./heading.md) · [`highlight`](./highlight.md) · [`knob`](./knob.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) · [`range-calendar`](./range-calendar.md) · [`scroll-frames`](./scroll-frames.md) · [`skin-media-player`](./skin-media-player.md) · [`stack`](./stack.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) · [`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 |
| --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | :-: |
uix(grid-list): temable — 0 % → 85 %, y una selección que nunca pintó 38 claves nuevas en el bloque `grid-list` de `recipes/base.ts` (que ya existía con los dos forwards de paleta: se FUSIONA, no se añade un segundo). Alcance del censo 0 % → 85 % (22 de 26 puntuables); global 45 % → 46 %, sin contrato 49 → 48. El eje `size` se estampa en el PROVIDER —el wrapper de eidos no tiene parte `root`—, así que los tres nombres resueltos van SIN `parts`: molde `command`, no `table`/`tree-grid`. Fuera los cuatro bloques `[data-size]` del CSS; los emite el TSC. Altura de fila 1:1 con el bundle, `row-padding-inline` con ritmo propio, y la tipografía un paso por debajo de md en adelante — verbatim, como table y tree-grid. LO QUE LA MEDICIÓN CAMBIÓ (la §4 generada tenía un error de doctrina y dos defectos que sólo aparecieron midiendo; el §5 Veredicto se escribió con la sonda delante, porque estaba vacío): 1. La selección de fila NUNCA HA PINTADO. La receta seleccionaba `[data-grid-list-row][data-selected]`, un atributo que ni el morfo declara ni soma estampa (estampa `data-state='selected'` + `aria-selected`): la regla no casaba jamás y su acento `--_grid-list-palette-element` no llegó nunca al píxel — una fila seleccionada muestra el velo NEUTRO del arquetipo, indistinguible del hover (capturado). Retirada la declaración muerta y su forward huérfano: 0 diffs, que es la prueba. Repararlo mueve píxel y choca con §12.5 (el arquetipo fija también `color`) → §13, espera firma. El acento del checkbox (`_palette-solid`) sí vive y se conserva. 2. NO se acuña `hover-row-bg` aunque la propuesta lo pedía. La fila es `archetype: 'item'`: el velo del sistema la pinta a especificidad plena y el plano de la receta pierde — medido, el hover pinta DOS VECES sobre el MISMO nodo (a diferencia de table/tree-grid, donde velo y plano caen en nodos distintos). Sería un token que no puede ganar; mismo criterio que listbox.highlighted → §12.7. Y fila Y celda llevan ambas `item`, así que bajo el puntero se apilan tres capas. 3. «Consume la capa compartida `menu-indicator`» es FALSO. Sale de `SHARED_LAYERS` (`theming-census.ts:432`), pero esa capa no tiene un solo selector de grid-list, la receta no la importa y soma no renderiza indicator: el checkbox ESPEJA el visual pintándolo por su cuenta. Entrada desviada del censo → §13 (listbox / menubar / navigation-menu están en la misma entrada y tampoco aparecen en el fichero). Nombres, sobre la propuesta: `selection-checkbox-{width,height}` son UN knob → `selection-checkbox-size`; `on-selection-checkbox-bg` → `checked-selection-checkbox-fg` (es la tinta del glifo, y `on-` es prefijo reservado); `border` partido en `border-width` + color (molde `command.input-border*`), que el checkbox comparte; `padding` uniforme se queda `padding` (precedente `command.viewport-padding`); `max-block` entra al contrato (molde `command.viewport-max-block`). Artefactos y gates: - Sonda antes/después = 0 diffs en 6.090 valores × 7 estados. Determinismo verificado: dos corridas del mismo código, 0 diffs. - R-5.4: 37/38 tokens mueven un computed. `invalid-border` adjudicado EN EL LEDGER con su razón medida (la demo arranca con su control en off; activado a mano alcanza: oklch(0.9555 0.0207 13.86) → rgb(1,2,3)). - censo --only 85 % · component:audit PASS (R-5.3 incluida) · eidos-lint invalid 0, class-hooks 0 · suite eidos sin rojos nuevos (el único es el conocido skin-media-player) · rtl:check 0 · docs:check 0 · check por fichero limpio (72 globales, ninguno mío). - README con su «Talla y tema» y tab `Tokens` en la demo (38 claves, leídas en vivo). El tab `Recipe` documentaba la regla retirada: corregido. Las fichas de calendar / carousel / command / month-grid / range-calendar / table / year-grid entran porque `--report` regenera el informe entero: sólo actualizan NÚMEROS DE LÍNEA de commits ya hechos que no lo regeneraron. Cero cambios de alcance. Las otras 161, que sólo cambiaban la fecha, se revirtieron. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2 months ago
| [range-calendar](./range-calendar.md) | 0% | 98 | 0 | 7 | 2 | 4 | 85 | 0 | – |
| [month-grid](./month-grid.md) | 0% | 61 | 0 | 7 | 0 | 5 | 49 | 0 | – |
| [year-grid](./year-grid.md) | 0% | 61 | 0 | 7 | 0 | 5 | 49 | 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
| [field-langs](./field-langs.md) | 0% | 41 | 0 | 0 | 31 | 8 | 2 | 0 | – |
| [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 | – |
| [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 |
| [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 |
uix(link): temable — 0 % → 36 %, y ese techo bajo es la respuesta correcta 5 claves fusionadas en el bloque `link` de `recipes/base.ts` (donde ya vivían los dos forwards de paleta). Censo 0 % → 36 %. **Un enlace en línea hereda casi todo del texto que lo rodea**, así que su superficie de tema es pequeña por diseño. Sus dos escotillas por instancia (`--_link-font-size`, `--_link-line-height`) tienen como fallback `inherit`, y ese `inherit` es SEMÁNTICO: el enlace toma la tipografía del párrafo en el que vive. Convertirlo en token exigiría un público con valor `inherit`, que en `:root` no significa lo mismo — se quedan privadas. Con los dos forwards de paleta, ésos son los cuatro privados que forman el grueso del 64 % restante. Lo tokenizable es la GEOMETRÍA: radio del anillo, hueco del glifo externo, tamaño del glifo (`0.85em` en las dos dimensiones → UN knob) y el grosor y desplazamiento del subrayado, cada uno declarado en las DOS reglas que lo dibujan (`always` y `hover`) con el mismo valor. Las tres opacidades son sistema; el `fill: currentColor` del glifo es identidad, sigue a la tinta del enlace a propósito. **La cascada no se toca.** El CSS lleva dos correcciones de especificidad ya medidas y explicadas en su sitio (el `inherit` condicional, para que un `color` pedido por el consumidor no se descarte en silencio; y el `:active` al final, porque una pulsación es siempre también un hover). El diff de computed confirma que tokenizar no las altera. Artefactos y gates: - Sonda antes/después = 0 diffs en 203 valores × 7 estados. Determinismo verificado. - R-5.4: 2/5, los tres mudos adjudicados con su medición. Ninguno es deuda: el glifo externo no se monta en la demo (0 nodos, contados) y el enlace arranca en `data-underline='hover'` sin puntero encima, así que NO HAY subrayado que mover (`text-decoration-line: none`, `thickness: auto`). Forzando el estado, los tres alcanzan. - En el mismo pase, `text-decoration-thickness` y `text-underline-offset` entran en la lista de propiedades del guard, que no las miraba — verificado que los otros DIECISÉIS componentes con ledger no cambian. - censo --only 36 % · component:audit PASS · eidos-lint invalid 0, class-hooks 0 · suite eidos sin rojos nuevos · rtl:check 0 · docs:check 0 · check por fichero limpio · README con «Talla y tema» y tab `Tokens` (5 claves). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2 months ago
| [link](./link.md) | 36% | 14 | 4 | 4 | 1 | 2 | 3 | 5 | – |
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
| [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 |
| [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 |
uix(skeleton): temable — 0 % → 45 %, y dos privados que son conmutadores 9 claves fusionadas en el bloque `skeleton` de `recipes/base.ts` (donde ya vivía el forward de paleta). Censo 0 % → 45 %, cero globales. Nueve de sus once knobs pasaban por privado, y la lectura correcta es que **dos de esos privados NO son deuda: son conmutadores**. `--_skeleton-bg` y `--_skeleton-highlight` tienen DOS fuentes cada uno según haya `data-color` — la mezcla neutra cross-mode (un `color-mix` hacia `neutral-solid`, para que el placeholder siga siendo un gris visible en los dos modos: el `neutral-track` desnudo desaparece sobre una superficie clara) o el forward de paleta. Aplanarlos exigiría duplicar cada regla por color, así que se quedan — mismo criterio que el borde de foco de textarea y la tinta de spinner. Son el grueso del 55 % que no alcanza, y es honesto. - **Una coordenada por talla** (`size`) gobierna el alto del bloque, el diámetro del círculo (vía `aspect-ratio`) y el hueco entre líneas de la forma `text`. Ese hueco es `calc(size * 0.5)`: una PROPORCIÓN, construcción, no un knob. - **El radio es por FORMA, no por talla**: `radius-md` en `rect` y `50%` en `circle`, donde el `50%` es identidad (un círculo es redondo) — el knob es sólo el del rectángulo. La línea de la forma `text` lleva el suyo. - `duration` entra al contrato en vez de seguir en `1.4s` a pelo, igual que se hizo con el spinner (§13). Artefactos y gates: - Sonda antes/después = 0 diffs en 203 valores × 7 estados. - R-5.4: 8/9. `line-radius` adjudicado: sólo la forma `text` renderiza `[data-skeleton-line]` y la demo monta `rect` (0 líneas, contadas); forzada la forma, alcanza (4 → 1234px). - censo --only 45 % · component:audit PASS · suite eidos sin rojos nuevos · rtl:check 0 · docs:check 0 · check por fichero limpio. - README con «Talla y tema» y tab `Tokens` en la demo (9 claves). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2 months ago
| [skeleton](./skeleton.md) | 45% | 11 | 5 | 5 | 0 | 1 | 0 | 9 | – |
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
| [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 |
| [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 | – |
| [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 |
uix(clipboard): temable — 0 % → 63 %, todo en la píldora de «Copied!» 6 claves fusionadas en el bloque `clipboard` de `recipes/base.ts` (donde ya vivían los dos forwards de paleta). Censo 0 % → 63 %. **Todo lo tokenizable es el INDICADOR.** El host va `display: contents` y el trigger reusa la receta de `Button` por el patrón de consumidor, así que la receta sólo posee la píldora que aparece un instante tras copiar. - Los dos forwards de paleta siguen privados (THM-2): el fondo y la tinta del chip los leen a pelo, sin sitio donde meter un público sin duplicar la regla — son el 37 % que no alcanza. - `font-family` queda fuera por la misma razón que en code-block, kbd y announce: lo posee la capa tipográfica. - El padding es un shorthand de dos valores → dos knobs lógicos. - **Los `--motion-*` no son knobs de tema**: son los ganchos con que el indicador afina el preset `scale-fade` del canal de motion (escala 0.85, rápida). Pertenecen al canal, no al contrato, y la política de `prefers-reduced-motion` la emite el generador. Artefactos y gates: - Sonda antes/después = 0 diffs en 1.392 valores × 8 estados. - R-5.4: 0/6, los seis adjudicados con su medición — el indicador sólo existe un instante tras copiar (0 nodos en reposo, contados) y forzándolo los seis mueven su propiedad (gap 4→1234px, padding 2/8→1235/1236px, radio 9999→1237px, tipo 12→99px, peso 500→123). - censo --only 63 % · component:audit PASS · suite eidos sin rojos nuevos · rtl:check 0 · docs:check 0 · check por fichero limpio. - README con «Talla y tema» y tab `Tokens` en la demo (6 claves). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2 months ago
| [clipboard](./clipboard.md) | 63% | 8 | 5 | 2 | 1 | 0 | 0 | 6 | – |
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
| [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 | – |
uix(virtual-list): temable — 0 % → 67 %, y 12/12 en el guard 12 claves en una entrada NUEVA de `recipes/base.ts`. Censo 0 % → 67 %, cero globales y cero privados. **La talla mueve SÓLO el tipo del cromo**, y eso acota el contrato antes de nombrar nada: las dimensiones de cada item salen de las props (`itemSize` / `estimateSize`), no de esta escala — lo dice el propio comentario de la receta. Así que hay UNA coordenada por talla, `font-size`, y el `radius` está DESACOPLADO a propósito (modelo Radix: constante en las cinco). Acuñar `radius-{k}` habría sido vocabulario muerto. La escala tipográfica va un paso por debajo desde lg (xs→xs, sm→sm, md→sm, lg→md, xl→lg) — el patrón de `table`, `tree-grid` y `tree-view` — y lee al bundle, no al primitivo crudo. El resuelto declara `parts: ['root']`: el `data-size` se estampa en `[data-virtual-list-root]`, un wrapper de eidos. Surface y outline comparten anchura y color de borde → un par de knobs. El `transparent` de ghost y los `100%` del viewport son identidad de variante y de layout (D-TH.2): son el 33 % que no alcanza, y es correcto que no lo haga. Artefactos y gates: - Sonda antes/después = 0 diffs en 3.451 valores × 7 estados. - R-5.4: **12/12**, sin una sola entrada en el ledger. - censo --only 67 % · component:audit PASS · eidos-lint invalid 0, class-hooks 0 · suite eidos sin rojos nuevos · rtl:check 0 · docs:check 0 · check por fichero limpio. - README con «Talla y tema» y tab `Tokens` en la demo. La demo no ataba ninguna referencia al stage, así que se ata una: sin ella el panel no puede leer los computados en vivo (lo cazó `npm run check`, no una suposición). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2 months ago
| [virtual-list](./virtual-list.md) | 67% | 13 | 8 | 0 | 0 | 4 | 1 | 12 | – |
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
| [text-gradient](./text-gradient.md) | 67% | 9 | 6 | 0 | 0 | 3 | 0 | 0 | – |
| [separator](./separator.md) | 67% | 6 | 4 | 0 | 0 | 2 | 0 | 3 | – |
feat(listbox): temable hasta donde le toca — 0 % → 68 % Sexto del bloque F2-A, y el primero cuyo techo es DELIBERADO. censo 0 % → 68 % · global 42 % computed 2.813 valores en 7 estados: 0 diffs **Este componente no puede acuñar su ritmo de fila, y esa es la regla de oro de las capas compartidas.** Altura, padding inline y block, gap y tamaño de letra los posee `lib/list-surface.css`, por talla, para TODAS las superficies de lista —select, combobox, command y los menús—. Acuñar `--listbox-item-height` sería el vocabulario paralelo que las reglas de esa capa prohíben, y encima ganaría a la capa para todas las demás. Los cinco privados ADOPTAN la capa y se quedan privados; un tema mueve ese ritmo por `--list-*`, que es donde vive. Consecuencia honesta: el censo cuenta esos cinco como privados y el alcance se queda en 68 % en vez de ~86 %. **La métrica penaliza hacer lo correcto** — el mismo defecto de medición que D-TH.2-b arregló para los primitivos tipográficos (`--style-*` pasó a `system`). Registrado en `next-features.md` §13; extenderlo a las capas compartidas es decisión, no corrección al paso. **Dos cosas medidas que NO se tocaron:** - El `highlighted` pinta DOS veces: la receta pone un `--color-surface-overlay` plano y encima el arquetipo `item` añade su velo del 8 %. El plano es el duplicado que §38 deprecó, así que se dejó SIN token — bendecir con un nombre público algo condenado a morir es el error que este eje ya evitó en el codemod. Retirarlo mueve píxel. - La tinta de la fila seleccionada era código MUERTO y se retiró: el arquetipo la fija a (0,4,0) contra los (0,3,0) de la receta. Mismo hallazgo que en `table`, verificado igual, 0 diffs al quitarlo. Lo que sí es suyo y ahora es público: la superficie que sostiene las filas (fondo, borde, radio, padding, gap, tipografía, alto máximo), la esquina y la tinta de la fila, el glifo de selección y el grupo con su etiqueta. audit PASS · eidos-lint 0 invalid · rtl 0 · docs 0 · check 0 en tocados · suite: sólo el rojo conocido Demo con tab Tokens: 21 filas, 0 sin computar. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [listbox](./listbox.md) | 68% | 37 | 23 | 9 | 1 | 1 | 3 | 21 | – |
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
| [select](./select.md) | 69% | 72 | 45 | 14 | 3 | 3 | 7 | 101 | y |
uix(spinner): temable — 0 % → 70 %, y 71 tokens propuestos que eran 18 18 claves en el bloque `spinner` de `recipes/base.ts` (fusionadas con los dos forwards de paleta). Censo 0 % → 70 %, cero globales. Global 48 %, sin contrato 44 → 43. **La §4 proponía 71 tokens para 23 knobs — la peor inflación que ha dado el generador en todo el eje.** El spinner tiene UNA coordenada de talla (`--spinner-size`) que gobierna el anillo, la pista de puntos y las barras, más el trazo (`--spinner-thickness`). La propuesta multiplicaba esa única coordenada por variante × parte × dimensión × talla y producía `ring-track-width-xs`, `dots-track-gap-xs`, `dots-dot-width-xs`, `bars-track-gap-xs`… todos con el mismo `0.75rem`, porque todos SON el tamaño en xs. Un tema habría necesitado veinte claves para cambiar un número. 1. Las proporciones son CONSTRUCCIÓN, no knobs: `calc(size * 0.3)` es el punto, `* 0.18` la barra, `* 0.2` y `* 0.12` los huecos. Definen la FORMA de cada variante y se quedan en la receta — mismo reparto que los gradientes de las guías de tree-grid o el damero de gradient-builder. 2. `fg` / `dots-dot-bg` / `bars-bar-bg` ⚠ no eran tres knobs con dos valores en pugna: son UNA variable (`--_spinner-color`) leída en tres sitios, con el conmutador `data-color='inherit'` que la cambia de forward de paleta a `currentColor`. Se queda privada, igual que `--_spinner-track`, que además envuelve su fuente en un color-mix distinto por rama (60 % / 25 %). Aplanarlas exigiría duplicar cada regla por color. 3. La escala es PROPIA, no la del bundle de iconos: medido, 12/16/20/28/40 px contra los 14/16/18/20/32 de `--icon-size-*`, y sólo coinciden en sm. Verbatim con la desviación anotada — forzar el bundle habría movido el default en cuatro tallas de cinco. 4. `duration` entra al contrato en vez de seguir en `0.9s` a pelo: el registro ya tenía abierta la incoherencia de que el spinner de feed ganó tokens de duración y el de media-player no (§13). Aquí se hace bien de entrada. El 30 % que falta son los dos privados conmutadores, los dos `border-radius: 50%` (identidad de forma) y los fotogramas de los @keyframes. Artefactos y gates: - Sonda antes/después = 0 diffs en 377 valores × 7 estados. Determinismo verificado. - R-5.4: 14/18. Los cuatro mudos, medidos uno a uno y adjudicados: la demo monta SÓLO la variante ring y sin etiqueta (0 barras, 0 puntos, 0 labels, contados), y `track-opacity` sólo se declara dentro de `prefers-reduced-motion` — forzando variante, etiqueta y contexto reduce, los cuatro alcanzan. - censo --only 70 % · component:audit PASS · eidos-lint invalid 0, class-hooks 0 · suite eidos sin rojos nuevos (el conocido skin-media-player) · rtl:check 0 · docs:check 0 · check por fichero limpio. - README con su «Talla y tema» y tab `Tokens` en la demo (18 claves, en vivo). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2 months ago
| [spinner](./spinner.md) | 70% | 23 | 16 | 3 | 0 | 4 | 0 | 18 | – |
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
| [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 | – |
uix(virtual-grid): temable — 0 % → 73 %, gemelo exacto de virtual-list 12 claves en una entrada NUEVA de `recipes/base.ts`. Censo 0 % → 73 %, cero globales y cero privados. Es el **gemelo exacto de `virtual-list`**: mismo chasis, mismos valores, misma escala. Se tokeniza igual, y en su propio commit — un componente, un commit. **La talla mueve SÓLO el tipo del cromo**: las dimensiones de cada celda salen de las props (`rowSize` / `columnSize`), no de esta escala, así que hay UNA coordenada por talla y el `radius` está DESACOPLADO a propósito (modelo Radix, constante en las cinco). La escala tipográfica va un paso por debajo desde lg (xs→xs, sm→sm, md→sm, lg→md, xl→lg) y lee al bundle. El resuelto declara `parts: ['root']` porque el `data-size` se estampa en `[data-virtual-grid-root]`, un wrapper de eidos. Surface y outline comparten anchura y color de borde → un par de knobs. El `transparent` de ghost y los `100%` del viewport son identidad de variante y de layout: el 27 % que no alcanza, y es correcto que no lo haga. Artefactos y gates: - Sonda antes/después = **0 diffs en 20.010 valores** × 7 estados (111 nodos: la demo renderiza la ventana entera de celdas). - R-5.4: **12/12**, sin una sola entrada en el ledger. - censo --only 73 % · component:audit PASS · eidos-lint invalid 0, class-hooks 0 · suite eidos sin rojos nuevos · rtl:check 0 · docs:check 0 · check por fichero limpio. - README con «Talla y tema» y tab `Tokens`; como en su gemelo, la demo no ataba referencia al stage y se ata una para que el panel lea los computados vivos. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2 months ago
| [virtual-grid](./virtual-grid.md) | 73% | 12 | 8 | 0 | 0 | 3 | 1 | 12 | – |
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
| [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 |
uix(picker-shell): temable — 0 % → 76 %, y el componente que el instrumento no veía 31 claves en una entrada NUEVA de `recipes/base.ts`. Censo 0 % → 76 %. Global 48 %, sin contrato 43 → 42. La cola avisaba «es CAPA de los pickers: mirar antes qué posee y qué presta». Mirarlo cambió tres cosas del encargo: 1. **NO es una capa compartida: es un COMPONENTE.** A diferencia de list-surface o calendar-surface no hay hook de capa ni vocabulario prestado — color-picker, date-picker y chronos importan sus `.svelte` directamente. No toca `LAYER_VOCABULARY` y el censo ya lo puntuaba bien. 2. **Su eje de talla no es `data-size`, es `data-picker-size` sobre `[data-popover-content]`**, un ancestro PORTALADO. El TSC no puede emitir esa cascada (`scope: 'size:xs'` generaría `[data-picker-shell][data-size='xs']`, que no casa nunca), así que las coordenadas por talla quedan como públicos PLANOS y la receta las consume desde sus propios selectores. Es el único componente del eje donde el patrón de nombres resueltos no aplica; la regla base es el default `sm` y `md` sólo re-declara lo que cambia. La fila de tiempo lleva un TERCER eje, `data-size` sobre su propia clase. 3. **El instrumental del eje estaba CIEGO aquí, y la sonda genérica devolvió 0 nodos** — el antipatrón de comparar cero valores y pasar. Dos causas a la vez: `picker-shell` no tiene demo propia (404, se mide dentro de un picker anfitrión y detrás de su popover), y sus partes se llaman `data-picker-header` / `-body` / `-footer` en vez de `data-picker-shell-{parte}` — genéricas A PROPÓSITO, dice la receta, «so every picker gets the same visual contract for free» —, así que todo filtro por prefijo del componente ve sólo la raíz. CÓMO SE VERIFICÓ, ya que el instrumento estándar no servía: - Sonda DIRIGIDA (abre el popover del date-picker, captura los seis nodos reales en las cuatro picker-sizes): determinismo comprobado (576 valores, 0 diffs entre dos corridas del mismo código) y **gate antes/después = 0 diffs**. - Los knobs que la demo no monta —el header entero y la fila de tiempo— se midieron FORZANDO el nodo: los quince mueven su propiedad, y el font-size del header se comprobó talla a talla (12/14/16/16px → 102px, cada uno en su picker-size). - El guard R-5.4 pasó de **0/31 a 6/31** al ganar un `COMPONENT_OVERRIDES` (prefijo de atributo + selector de apertura) acotado a este componente. Verificado que los otros CATORCE con ledger no se mueven ni una cifra. Adjudicar 31 excepciones sin ese arreglo habría sido escribir una mentira en el ledger; los 25 que siguen mudos llevan cada uno su razón medida. Header y footer comparten la regla que los separa del cuerpo → UN par de knobs (`border-width` + `border`), no dos. Sin tab `Tokens`: este componente no tiene página donde ponerlo. Registrado en next-features §13 junto con la pregunta de fondo — si el precio de los nombres genéricos (un contrato visual común para todos los pickers) compensa la ceguera del instrumental — y con el eje portalado como caso de prueba si el TSC llega a ganar un scope configurable. Gates: censo --only 76 % · suite eidos sin rojos nuevos (el conocido skin-media-player) · rtl:check 0 · docs:check 0 · check por fichero limpio · `component:audit` no lo cubre (eidos-only, sin morfo) y `eidos-lint` tampoco. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2 months ago
| [picker-shell](./picker-shell.md) | 76% | 21 | 16 | 4 | 1 | 0 | 0 | 31 | 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 |
uix(grid-list): temable — 0 % → 85 %, y una selección que nunca pintó 38 claves nuevas en el bloque `grid-list` de `recipes/base.ts` (que ya existía con los dos forwards de paleta: se FUSIONA, no se añade un segundo). Alcance del censo 0 % → 85 % (22 de 26 puntuables); global 45 % → 46 %, sin contrato 49 → 48. El eje `size` se estampa en el PROVIDER —el wrapper de eidos no tiene parte `root`—, así que los tres nombres resueltos van SIN `parts`: molde `command`, no `table`/`tree-grid`. Fuera los cuatro bloques `[data-size]` del CSS; los emite el TSC. Altura de fila 1:1 con el bundle, `row-padding-inline` con ritmo propio, y la tipografía un paso por debajo de md en adelante — verbatim, como table y tree-grid. LO QUE LA MEDICIÓN CAMBIÓ (la §4 generada tenía un error de doctrina y dos defectos que sólo aparecieron midiendo; el §5 Veredicto se escribió con la sonda delante, porque estaba vacío): 1. La selección de fila NUNCA HA PINTADO. La receta seleccionaba `[data-grid-list-row][data-selected]`, un atributo que ni el morfo declara ni soma estampa (estampa `data-state='selected'` + `aria-selected`): la regla no casaba jamás y su acento `--_grid-list-palette-element` no llegó nunca al píxel — una fila seleccionada muestra el velo NEUTRO del arquetipo, indistinguible del hover (capturado). Retirada la declaración muerta y su forward huérfano: 0 diffs, que es la prueba. Repararlo mueve píxel y choca con §12.5 (el arquetipo fija también `color`) → §13, espera firma. El acento del checkbox (`_palette-solid`) sí vive y se conserva. 2. NO se acuña `hover-row-bg` aunque la propuesta lo pedía. La fila es `archetype: 'item'`: el velo del sistema la pinta a especificidad plena y el plano de la receta pierde — medido, el hover pinta DOS VECES sobre el MISMO nodo (a diferencia de table/tree-grid, donde velo y plano caen en nodos distintos). Sería un token que no puede ganar; mismo criterio que listbox.highlighted → §12.7. Y fila Y celda llevan ambas `item`, así que bajo el puntero se apilan tres capas. 3. «Consume la capa compartida `menu-indicator`» es FALSO. Sale de `SHARED_LAYERS` (`theming-census.ts:432`), pero esa capa no tiene un solo selector de grid-list, la receta no la importa y soma no renderiza indicator: el checkbox ESPEJA el visual pintándolo por su cuenta. Entrada desviada del censo → §13 (listbox / menubar / navigation-menu están en la misma entrada y tampoco aparecen en el fichero). Nombres, sobre la propuesta: `selection-checkbox-{width,height}` son UN knob → `selection-checkbox-size`; `on-selection-checkbox-bg` → `checked-selection-checkbox-fg` (es la tinta del glifo, y `on-` es prefijo reservado); `border` partido en `border-width` + color (molde `command.input-border*`), que el checkbox comparte; `padding` uniforme se queda `padding` (precedente `command.viewport-padding`); `max-block` entra al contrato (molde `command.viewport-max-block`). Artefactos y gates: - Sonda antes/después = 0 diffs en 6.090 valores × 7 estados. Determinismo verificado: dos corridas del mismo código, 0 diffs. - R-5.4: 37/38 tokens mueven un computed. `invalid-border` adjudicado EN EL LEDGER con su razón medida (la demo arranca con su control en off; activado a mano alcanza: oklch(0.9555 0.0207 13.86) → rgb(1,2,3)). - censo --only 85 % · component:audit PASS (R-5.3 incluida) · eidos-lint invalid 0, class-hooks 0 · suite eidos sin rojos nuevos (el único es el conocido skin-media-player) · rtl:check 0 · docs:check 0 · check por fichero limpio (72 globales, ninguno mío). - README con su «Talla y tema» y tab `Tokens` en la demo (38 claves, leídas en vivo). El tab `Recipe` documentaba la regla retirada: corregido. Las fichas de calendar / carousel / command / month-grid / range-calendar / table / year-grid entran porque `--report` regenera el informe entero: sólo actualizan NÚMEROS DE LÍNEA de commits ya hechos que no lo regeneraron. Cero cambios de alcance. Las otras 161, que sólo cambiaban la fecha, se revirtieron. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2 months ago
| [carousel](./carousel.md) | 77% | 35 | 23 | 2 | 0 | 5 | 5 | 27 | – |
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
| [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(textarea): temable — 0 % → 80 %, y el contador que casi pierde su 0.85 37 claves en el bloque `textarea` de `recipes/base.ts` (fusionadas con el forward de paleta que ya estaba). Censo 0 % → 80 %, con **cero globales y cero literales de valor**: los 16 privados leen ya su público. Global 46 %, sin contrato 48 → 47. LO QUE LA MEDICIÓN CAMBIÓ. La §4 generada proponía 35 tokens; cuatro eran colisiones y uno habría movido el default: 1. `count-font-size-{k}` × 5 BORRABA el factor 0.85. El CSS calcula `calc(var(--_textarea-font-size) * 0.85)` y la propuesta ponía el tipo del input crudo en las cinco tallas: el contador habría crecido un 18 %. D-TH.5 lo prohíbe. Queda en UN token con el `calc` sobre el público del input — la escala se escribe una vez y la talla la resuelve el input. Pide `scope: 'host'`: emitido en `:root` su dependencia no existe, y el contrato de scope de la receta lo caza (lo cazó). 2. `input-fg` ⚠ eran DOS knobs (texto y placeholder) → `input-fg` + `input-placeholder-fg`. Igual `count-fg` → `count-fg` + `overflow-count-fg`. 3. `input-border` ⚠ NO eran dos knobs sino UNA variable con su swap de paleta, y el nombre estaba mal: es el borde de FOCO → `focus-input-border`. El de reposo es otro token, que la propuesta ni listó por viajar en el atajo. 4. `ghost-input-border` se RETIRA: la regla ghost lee ese mismo conmutador — sería un valor con dos nombres. Bundle, medido: la tipografía casa 1:1 en las cinco (lee `--size-{k}-font-size`); el spacing NO — `padding-inline` casa salvo en xs (8px vs 6px) y `padding-block` sólo en xs. Verbatim y documentado: un campo multi-línea respira más, y el spacing queda fuera del guard del bundle. Resueltos sin `parts` (el `data-size` va en `[data-textarea]` y el input hereda); fuera los cuatro `[data-size]`. DOS ARREGLOS DEL INSTRUMENTO, los dos por medición y no por sospecha: - **El guard medía con el PUNTERO encima.** `reopen()` corre antes de CADA token y hace clic en `[data-{c}-input]` cuando el componente no tiene parte `content`; el `blur()` de la revisión adversarial quitaba el foco pero no el puntero, así que `:hover` casaba toda la corrida y toda regla de hover pisaba a sus vecinas. Costaba TRES falsos negativos aquí. Con `mouse.move(0,0)` tras cada blur, `input-border` revive solo (31 → 32). - **`::placeholder` SÍ se lee con `getComputedStyle`.** La nota de §13 que decía lo contrario nunca se comprobó; medido, el color centinela vuelve tal cual. Entra en el snapshot (32 → 33) y deja STALE la entrada `command.input-placeholder-fg`, que el guard señaló y se ha borrado. Corridos los DIEZ componentes con ledger tras los dos arreglos: ningún otro cambia, un único STALE, el previsto. Y un hallazgo de píxel que NO se toca aquí (→ next-features §13): el borde de foco sólo se ve con Tab. Las tres reglas de `border-color` del input están ordenadas al revés de lo que significan — hover (0,4,0) > foco (0,3,0) > invalid (0,2,0) — y hacer clic deja el puntero encima por definición, así que gana el hover; un campo inválido pierde su borde rojo al enfocarlo o al pasar el ratón. El anillo de foco del sistema sí se ve siempre, así que no es fallo de accesibilidad. Arreglarlo mueve píxel. El 20 % que falta son las dos declaraciones que consumen `--_textarea-border-focus`, privado a propósito: es el conmutador de una variable con dos fuentes (el público y el forward THM-2), y aplanarlo exigiría duplicar la regla por color. Mismo techo que `listbox` paga por consumir bien su capa. Mi propio veredicto predecía ~100 % y la medición lo corrigió a 80 %. Artefactos y gates: - Sonda antes/después = 0 diffs en 1.247 valores × 8 estados (el 0.85 intacto, que era el riesgo). Determinismo verificado: dos corridas, 0 diffs. - R-5.4: 33/37; los 4 mudos adjudicados en el ledger con su medición (foco, invalid y las dos del contador rebasado — estados que la demo no monta). - censo --only 80 % · component:audit PASS · eidos-lint invalid 0, class-hooks 0 · suite eidos sin rojos nuevos (el conocido skin-media-player) · rtl:check 0 · docs:check 0 · check por fichero limpio (72 globales, ninguno mío). - README con su «Talla y tema» y tab `Tokens` en la demo (37 claves; el panel muestra el contador computando `calc(calc(1rem * 1) * 0.85)`). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2 months ago
| [textarea](./textarea.md) | 80% | 28 | 20 | 2 | 0 | 3 | 3 | 37 | – |
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 | – |
uix(code-block): temable — 0 % → 81 %, y la demo que no enseña el componente 20 claves en una entrada NUEVA de `recipes/base.ts` (no tenía). Censo 0 % → 81 %. Global 46 % → 47 %, sin contrato 46 → 45. El handoff lo llamaba «el más mecánico de los que quedan». No lo es: sus 26 knobs se parten en dos grupos con doctrinas distintas. 1. **El nodo del código NO acuña nada, y la §4 pedía que lo hiciera.** `[data-code-block-code]` consume la capa tipográfica `--style-code-*` en sus cinco declaraciones, y las dos que pasan por privado usan la forma canónica de la escotilla por instancia (`var(--_code-block-font-size, var(--style-code-font-size))`, escrita por el wrapper desde la prop `size` y sólo si llega). Es el patrón que D-TH.2-b fijó para heading/text/code. Acuñar `code-font-family` y compañía sería el vocabulario paralelo que la regla 2 de capas prohíbe. Todo lo que entra al contrato es el CASCO alrededor. 2. **Los tres `font-size` iban al primitivo crudo, y lo cazó un guard.** La propuesta copia el valor del CSS verbatim, y ese valor ya violaba `recipe-css-contract` («recipes consume the size bundle, not the raw size-coordinate primitives»): `title/lang/copy-font-size` corregidos a `var(--size-{k}-font-size)`. Los alias son 1:1 → 0 diffs tras aplicarlo. Aviso general: cuando el CSS de partida ya incumple el contrato, la propuesta generada hereda el incumplimiento. 3. Shorthand partidos: los dos `border` y el `border-bottom` de la cabecera comparten anchura y color → `border-width` + `border`; el `padding` del `<pre>` → `pre-padding`. Los `transparent` de outline/ghost y el `border: 0` de ghost son identidad de variante. El 19 % que falta son esas cinco de la capa, que el censo cuenta como `global` porque `code-block` no está en `TYPOGRAPHIC_PRIMITIVES` — es un compuesto que CONTIENE un primitivo tipográfico, no uno de ellos. Extender la clase `system` del censo a las capas sigue pendiente de tu firma; la métrica penaliza hacer lo correcto y no se fuerza de oficio. DOS HALLAZGOS QUE NO SE ARREGLAN AQUÍ (→ next-features §13): - **La demo de `code-block` no enseña el `code-block`.** `[data-uix-docs] pre` (`web/routes/uix/uix.css:801`) pesa (0,1,1) contra los (0,1,0) de `[data-code-block-pre]`, y `[data-uix-docs]` es el shell de TODAS las páginas. Siete propiedades del `<pre>` las pinta el harness y no la receta: padding (16px 20px contra 12px), border (1px contra ninguno), radius (8px contra 0), background (gris contra transparente), font-family, font-size (13 contra 14) y line-height (18.2 contra 20.3). El fondo, el borde y el radio que se ven ahí son del sitio. Por eso `pre-padding` lee muerto en el guard, adjudicado con esa medición. Acotar la regla toca el CSS del SITIO, que sirve a ~162 páginas: decisión aparte. - **El guard de claves duplicadas del handoff inspeccionaba el VACÍO.** El comando documentado usa `grep -oE "^\t…"`, y `grep -E` lee `\t` como una `t` literal: 0 coincidencias sobre 130 bloques reales, así que salía «vacío = OK» sin mirar nada — el antipatrón que el proyecto tiene registrado, dentro del propio handoff. Comprobado con un contador fiable: cero duplicados en el árbol, así que no hay daño en los commits que confiaron en él. CONTINUE queda corregido con una versión que CUENTA los bloques y avisa de que «0 bloques» significa guard roto, no fichero limpio. Artefactos y gates: - Sonda antes/después = 0 diffs en 1.305 valores × 7 estados (dos veces: tras la tokenización y tras la corrección del bundle). Determinismo verificado. - R-5.4: 19/20; `pre-padding` adjudicado con las siete propiedades medidas. - censo --only 81 % · component:audit PASS · eidos-lint invalid 0, class-hooks 0 · suite eidos de vuelta al único rojo conocido (skin-media-player) tras corregir el bundle · rtl:check 0 · docs:check 0 · check por fichero limpio. - README con su «Talla y tema» y tab `Tokens` en la demo (20 claves, en vivo). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2 months ago
| [code-block](./code-block.md) | 81% | 26 | 21 | 2 | 3 | 0 | 0 | 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
| [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 | – |
uix(grid-list): temable — 0 % → 85 %, y una selección que nunca pintó 38 claves nuevas en el bloque `grid-list` de `recipes/base.ts` (que ya existía con los dos forwards de paleta: se FUSIONA, no se añade un segundo). Alcance del censo 0 % → 85 % (22 de 26 puntuables); global 45 % → 46 %, sin contrato 49 → 48. El eje `size` se estampa en el PROVIDER —el wrapper de eidos no tiene parte `root`—, así que los tres nombres resueltos van SIN `parts`: molde `command`, no `table`/`tree-grid`. Fuera los cuatro bloques `[data-size]` del CSS; los emite el TSC. Altura de fila 1:1 con el bundle, `row-padding-inline` con ritmo propio, y la tipografía un paso por debajo de md en adelante — verbatim, como table y tree-grid. LO QUE LA MEDICIÓN CAMBIÓ (la §4 generada tenía un error de doctrina y dos defectos que sólo aparecieron midiendo; el §5 Veredicto se escribió con la sonda delante, porque estaba vacío): 1. La selección de fila NUNCA HA PINTADO. La receta seleccionaba `[data-grid-list-row][data-selected]`, un atributo que ni el morfo declara ni soma estampa (estampa `data-state='selected'` + `aria-selected`): la regla no casaba jamás y su acento `--_grid-list-palette-element` no llegó nunca al píxel — una fila seleccionada muestra el velo NEUTRO del arquetipo, indistinguible del hover (capturado). Retirada la declaración muerta y su forward huérfano: 0 diffs, que es la prueba. Repararlo mueve píxel y choca con §12.5 (el arquetipo fija también `color`) → §13, espera firma. El acento del checkbox (`_palette-solid`) sí vive y se conserva. 2. NO se acuña `hover-row-bg` aunque la propuesta lo pedía. La fila es `archetype: 'item'`: el velo del sistema la pinta a especificidad plena y el plano de la receta pierde — medido, el hover pinta DOS VECES sobre el MISMO nodo (a diferencia de table/tree-grid, donde velo y plano caen en nodos distintos). Sería un token que no puede ganar; mismo criterio que listbox.highlighted → §12.7. Y fila Y celda llevan ambas `item`, así que bajo el puntero se apilan tres capas. 3. «Consume la capa compartida `menu-indicator`» es FALSO. Sale de `SHARED_LAYERS` (`theming-census.ts:432`), pero esa capa no tiene un solo selector de grid-list, la receta no la importa y soma no renderiza indicator: el checkbox ESPEJA el visual pintándolo por su cuenta. Entrada desviada del censo → §13 (listbox / menubar / navigation-menu están en la misma entrada y tampoco aparecen en el fichero). Nombres, sobre la propuesta: `selection-checkbox-{width,height}` son UN knob → `selection-checkbox-size`; `on-selection-checkbox-bg` → `checked-selection-checkbox-fg` (es la tinta del glifo, y `on-` es prefijo reservado); `border` partido en `border-width` + color (molde `command.input-border*`), que el checkbox comparte; `padding` uniforme se queda `padding` (precedente `command.viewport-padding`); `max-block` entra al contrato (molde `command.viewport-max-block`). Artefactos y gates: - Sonda antes/después = 0 diffs en 6.090 valores × 7 estados. Determinismo verificado: dos corridas del mismo código, 0 diffs. - R-5.4: 37/38 tokens mueven un computed. `invalid-border` adjudicado EN EL LEDGER con su razón medida (la demo arranca con su control en off; activado a mano alcanza: oklch(0.9555 0.0207 13.86) → rgb(1,2,3)). - censo --only 85 % · component:audit PASS (R-5.3 incluida) · eidos-lint invalid 0, class-hooks 0 · suite eidos sin rojos nuevos (el único es el conocido skin-media-player) · rtl:check 0 · docs:check 0 · check por fichero limpio (72 globales, ninguno mío). - README con su «Talla y tema» y tab `Tokens` en la demo (38 claves, leídas en vivo). El tab `Recipe` documentaba la regla retirada: corregido. Las fichas de calendar / carousel / command / month-grid / range-calendar / table / year-grid entran porque `--report` regenera el informe entero: sólo actualizan NÚMEROS DE LÍNEA de commits ya hechos que no lo regeneraron. Cero cambios de alcance. Las otras 161, que sólo cambiaban la fecha, se revirtieron. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2 months ago
| [calendar](./calendar.md) | 84% | 71 | 57 | 7 | 0 | 4 | 3 | 74 | – |
| [grid-list](./grid-list.md) | 85% | 31 | 22 | 2 | 1 | 1 | 5 | 38 | – |
uix(kbd): temable — 0 % → 86 %, y 13/13 en el guard sin una sola excepción 13 claves en una entrada NUEVA de `recipes/base.ts`. Censo 0 % → 86 %. 1. **`font-family` NO se acuña**: lee `var(--style-code-font-family)`, la capa tipográfica, y un consumidor no re-declara el vocabulario de su capa — precedente inmediato, `code-block`. El `font-size` SÍ entra, y la diferencia está medida: su fallback era un PRIMITIVO, no la capa. `--_kbd-font-size` es la escotilla por instancia que el wrapper escribe desde la prop `size` (`kbd.svelte:37`), y el fallback pasa a ser el público. 2. **El padding y el min-width son em-relativos a propósito** — una tecla crece con su letra —, así que son knobs con valor `em`, no literales pendientes de corregir. El `line-height: 1` sí es identidad: una tecla no tiene interlineado. 3. **El relieve de tecla física es de la variante `surface`**: borde inferior más grueso + luz interior. Dos knobs propios, no adorno del borde general; outline y ghost son planas por identidad. Artefactos y gates: - Sonda antes/después = 0 diffs en 522 valores × 7 estados. Determinismo verificado. - R-5.4: **13/13**, sin una sola entrada en el ledger — el primero de la tanda que no necesita adjudicar nada. - censo --only 86 % · component:audit PASS · eidos-lint invalid 0, class-hooks 0 · suite eidos sin rojos nuevos · rtl:check 0 · docs:check 0 · check por fichero limpio. - README con su «Talla y tema» y tab `Tokens` en la demo (13 claves, en vivo). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2 months ago
| [kbd](./kbd.md) | 86% | 14 | 12 | 0 | 1 | 1 | 0 | 13 | – |
feat(media-player): el proyector se vuelve temable — 0 % → 88 % Tercero del bloque F2-A. 45 knobs sin contrato salvo el acento; ahora 61 claves públicas, **cero privados y cero globales**. censo 0 % → 88 % · global 40 % → 41 % computed 3.277 valores en 7 estados: **0 diffs** **El veredicto pedía renombrar `--_mp-*` → `--_media-player-*`; hacen falta menos pasos que eso.** El prefijo abreviado viola theming §6 r5, cierto, pero al leerlos uno a uno los dieciséis privados eran ALIAS PUROS de su fuente (`--_mp-fg: var(--color-content-primary)`, `--_mp-accent: var(--media-player-accent)`…). Un alias puro no se renombra: se borra. La capa privada entera desaparece y cada knob pasa a público. **El acento firmado NO se tocó**: `accent`/`accent-strong` siguen siendo `--scale-amber-9/10` — acento de proyector theme-stable, que debe leerse sobre cualquier vídeo en claro Y oscuro, con su doctrina escrita en el propio bloque. Verificado en vivo que sigue re-tintando el rango del Slider compuesto. **El scrim: UN color, dos gradientes.** La tira inferior de controles y el degradado del título salen del mismo `--media-player-scrim`; dos tokens dejarían que un tema rompiera la pareja sin querer. **`audio-player` viajaba en el mismo barco y no era obvio**: consume siete de esos tokens sin declarar ninguno. No es fuga entre componentes — es un SKIN sobre las mismas partes (`[data-media-player][data-variant]`), así que están en ámbito. Su receta se migró en el mismo pass. **Lo que no se pudo medir, y se dice**: `audio-player` no tiene página de demo (la ruta da 404), así que la sonda encontró 0 nodos — y una comparación de 0 valores pasa siempre, que es justo la clase de guard que no vale. Se verificó a mano estampando `data-variant` sobre el player vivo: el padding pasó a `6px 12px`, exactamente los tokens nuevos. Hueco de demo anotado en el README. Centinela 36/61. Los 25 restantes, adjudicados por clase: partes no montadas en la demo (captions, buffering, título de audio, paneles portalados), un pseudo-elemento (`::after` del scrim) y los que pintan DENTRO del Slider compuesto — verificado a mano que `--media-player-track` sí llega hasta `--slider-track-bg`. Los 6 knobs que quedan son literales de relleno (`100%`, `max-content`). audit PASS · eidos-lint 0 invalid · rtl 0 · docs 0 · check 0 en tocados · suite: sólo el rojo conocido `skin-media-player` Demo con tab Tokens: 61 filas, 0 sin computar. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [table](./table.md) | 86% | 46 | 37 | 3 | 0 | 3 | 3 | 45 | – |
| [announce](./announce.md) | 88% | 8 | 7 | 0 | 1 | 0 | 0 | 9 | – |
feat(tree-grid): el árbol se vuelve temable — 0 % → 95 % Cuarto del bloque F2-A. 42 knobs con 29 privados que no derivaban de nada; ahora 47 claves públicas y tres privados, los tres legítimos. censo 0 % → 95 % · global 41 % → 42 % computed 9.744 valores en 7 estados: 0 diffs **Las guías de indentación eran UN color, no un fondo.** Lo que la propuesta llamaba `root-bg-image` son las líneas verticales por `aria-level`: cinco gradientes apilados que dibujan una línea por ancestro. El knob es `guide-fg` (+ `guide-width`); la construcción se queda en la receta — el mismo reparto que el damero de gradient-builder, donde el color es el token y el patrón es de la receta. **Tres privados sobreviven, y por razones distintas**: `--_tree-grid-columns` no es un knob de tema sino un CANAL de layout que el wrapper escribe inline desde la definición de columnas del consumidor; `--_tree-grid-palette-element` es el forward THM-2; `--_tree-grid-stable-rows` es dato del consumidor. **El hover de fila es no determinista, y viene de antes de este eje.** Dos hallazgos medidos: 1. En filas CON BANDA el hover está muerto: la regla de `striped` pesa (0,7,0) contra los (0,5,0) del hover y usa el atajo, así que en las pares no ocurre nada al pasar el ratón. 2. En las demás, quién gana depende del ORDEN DE CARGA: el velo del arquetipo `item` y el hover de la receta empatan EXACTAMENTE a (0,5,0). Seis corridas de la misma configuración dieron cuatro veces «sin velo» y dos «con velo». Eso segundo obligó a parar y caracterizarlo: al ver 3 diffs tras un cambio trivial (un `border-width` a token) lo primero que hice fue sospechar de mi cambio; comparar dos corridas del MISMO código dio los mismos 3 diffs, así que no era el código sino un empate de especificidad resuelto por orden — la misma clase de fragilidad que el canon documenta para las bandas de z-index. No se toca aquí: decidir quién manda mueve píxel y es la decisión pendiente del velo. El guard de huérfanos cazó tres tokens que acuñé suponiendo (`font-family`, `fg`, `surface-bg`): existían en la receta pero leyendo el valor crudo. Ahora los leen, que es justo lo que el eje persigue. audit PASS · eidos-lint 0 invalid · rtl 0 · docs 0 · check 0 en tocados · suite: sólo el rojo conocido `skin-media-player` Demo con tab Tokens: 47 filas, 0 sin computar. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [media-player](./media-player.md) | 88% | 49 | 43 | 0 | 0 | 6 | 0 | 61 | – |
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
| [tabs](./tabs.md) | 88% | 76 | 66 | 6 | 2 | 1 | 1 | 79 | y |
feat(gradient-picker): temable — y su trigger resultó estar muerto entero Quinto del bloque F2-A. censo 0 % → 88 % · global 42 % computed 609 valores en 8 estados: 0 diffs **El hallazgo llegó por el centinela: 36 de 45 tokens no movían nada.** Con esa cifra no se sigue adelante. El trigger es un POPOVER TRIGGER, y `popover.css` le pinta el cromo entero —altura, padding inline, tipografía, color, fondo, borde, radio, hover y foco— desde `[data-popover-trigger]:not([data-archetype='field-trigger'])`, que gana a `[data-gradient-picker-trigger]` en base (0,2,0 contra 0,1,0) y en los estados (0,3,0 contra 0,2,0). Esta receta re-declaraba TODO eso y nada pintaba: la altura, el padding, el tamaño de letra y el radio venían de popover, y con valores distintos —12px contra el `space-2-5` de la receta, 14px contra su `font-size-md`—. Llevaba así desde que el trigger se volvió trigger de popover. Así que no se tokeniza: **se retira**. Un token sobre una declaración muerta es un token que miente, y este eje ya retiró uno por lo mismo en `table`. Retirarlo dio **0 diffs**, que es la prueba de que estaba muerto. Un tema viste este trigger por el contrato de POPOVER, que es composición funcionando. Lo que sí es del picker se queda y alcanza (verificado a mano, porque el chip usa un hook de CLASE que el centinela no ve): el `gap` de la fila, el chip del degradado (tamaño por talla, radio, borde), las tres anchuras del panel, la lista de paradas y la rejilla de presets. **Correcciones al veredicto**, ambas medidas: `--gp-current-gradient` NO lo estampa el wrapper sino SOMA (`gradient-picker-provider.svelte.ts:197`), así que renombrarlo toca otra capa y no es de este commit; y no es un knob de tema sino un canal de valor —el degradado que eligió el usuario—, sobre el que un tema no tiene nada que decir. Las tres anchuras del panel se quedan como tokens planos leídos por tres reglas, no como cascada del TSC: el content va por PORTAL y dimensiona con `data-picker-size` (el atributo de picker-shell), y el vocabulario de scopes no tiene palabra para el atributo de otro componente. Al registro (`next-features.md` §13) van cuatro incidencias nuevas: que un componente compuesto pueda tener el cromo entero muerto sin que nada avise —merece guard, y el instrumento ya existe—, el nombre abreviado en soma, los dos hooks por CLASE que `eidos-lint` cuenta, y el foco opaco del trigger contra la mezcla suave del sistema. audit PASS · eidos-lint 0 invalid · rtl 0 · docs 0 · check 0 en tocados · suite: sólo el rojo conocido Demo con tab Tokens: 25 filas, 0 sin computar. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [gradient-picker](./gradient-picker.md) | 88% | 27 | 23 | 0 | 2 | 1 | 1 | 25 | – |
uix(drag-drop): temable — 0 % → 89 %, casi todo en el fantasma del arrastre 10 claves en el bloque `drag-drop` de `recipes/base.ts` (fusionadas con `preview-z`, que ya estaba, y los dos forwards de paleta). Censo 0 % → 89 %, cero globales. **Siete de sus dieciséis knobs YA eran sistema** y no entran al ratio (las opacidades de fantasma y deshabilitado, los dos anillos de foco y el anillo `inset` de los droppables), así que los puntuables eran nueve — seis de ellos en el PREVIEW, el fantasma que sigue al puntero. 1. Los dos forwards de paleta siguen privados (THM-2): el fondo del `[data-dragover]` los lee a pelo y no admite un público sin duplicar la regla — es el 11 % que falta. En cambio el `border` y el `box-shadow` del preview los COMBINAN con una anchura y una sombra que sí son knobs propios, así que esas dos declaraciones entran al alcance. 2. El `--ring-inset-*` de los droppables no se toca: es vocabulario del anillo del SISTEMA y la receta se limita a alimentarlo con su acento. Acuñar un `droppable-ring-*` sería vocabulario paralelo sobre un transversal. 3. El `padding` del preview es un shorthand de dos valores → dos knobs lógicos. Artefactos y gates: - Sonda antes/después = 0 diffs en 1.827 valores × 7 estados. Determinismo verificado. - R-5.4: 0/10 en vivo, y los DIEZ adjudicados con su medición. No es un instrumento roto ni tokens muertos: el preview se crea sólo mientras hay un arrastre en curso (0 nodos en reposo, contados), y forzando el nodo los diez mueven su propiedad — padding 8→1234px, radio 6→1236px, borde 1→9px, fondo, tinta, familia, tamaño 14→99px, sombra y z 100→4321. - censo --only 89 % · component:audit PASS · eidos-lint invalid 0, class-hooks 0 · suite eidos sin rojos nuevos (el conocido skin-media-player) · rtl:check 0 · docs:check 0 · check por fichero limpio. - README con su «Talla y tema» y tab `Tokens` en la demo (10 claves, en vivo). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2 months ago
| [drag-drop](./drag-drop.md) | 89% | 16 | 8 | 1 | 0 | 0 | 7 | 10 | – |
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-typing](./chat-typing.md) | 89% | 9 | 8 | 0 | 1 | 0 | 0 | 7 | – |
| [breadcrumb](./breadcrumb.md) | 90% | 23 | 18 | 2 | 0 | 0 | 3 | 28 | y |
uix(card-group): temable — 0 % → 90 %, y dos privados abreviados que mueren 20 claves en una entrada NUEVA de `recipes/base.ts`. Censo 0 % → 90 %, cero globales y cero privados. Global 47 %, sin contrato 45 → 44. Es un CASCO de composición y su propia cabecera ya lo decía: compone ToggleGroup, Collapsible, Card y Button, y la receta posee «ONLY the genuinely CardGroup-level visual». Eso acota el contrato antes de nombrar nada — el cromo de las tarjetas es de Card, el del título de disclosure es de Button. 1. **`--_cg-pad` y `--_cg-card-radius` eran privados ABREVIADOS** (§6 r5 los prohíbe: `cg` por `card-group`), el mismo defecto que los `--_mp-*` de media-player. Pasar a públicos con el nombre completo es a la vez el renombrado que la regla pedía y la tokenización. La §3 de la ficha decía «la receta no declara privados propios»: los declaraba en su bloque raíz (`card-group.css:15-16`), y el escáner no los veía por buscarlos con el prefijo completo del componente. 2. **`--shape-outer-radius` NO se acuña: se CALCULA.** La receta lo compone como `card-radius + padding` para que las tarjetas aniden concéntricamente (§30). Un tema mueve las dos coordenadas y el radio exterior se recompone solo; el censo ya lo clasifica como sistema. 3. **El eje `size` es sm|md|lg, no las cinco tallas** (`Extract<Size, 'sm' | 'md' | 'lg'>`): seis coordenadas por talla, no diez. Escribir xs/xl habría sido vocabulario muerto. 4. Los tres `padding` son shorthand con una parte fija y otra variable; lo que varía y no es el inset del grupo es el hueco inferior → `title-padding-block-end` y `description-padding-block-end`. 5. El chevron es geometría propia (dos bordes girados 45°): `chevron-size` cubre las dos dimensiones y `chevron-width` el trazo. Su `currentColor` hereda del título a propósito y no es knob. 6. Los `font-size` van al BUNDLE (`--size-{k}-font-size`, alias 1:1) y no al primitivo crudo — misma trampa que cayó en code-block: la propuesta copia el CSS verbatim y hereda el incumplimiento cuando el valor de partida ya violaba `recipe-css-contract`. Aquí se aplicó de entrada. Artefactos y gates: - Sonda antes/después = 0 diffs en 2.581 valores × 7 estados. Determinismo verificado: dos corridas, 0 diffs. - R-5.4: 15/20. Los cinco mudos son los del encabezado ESTÁTICO, que la demo no monta (0 nodos `[data-static]` contra 1 `[data-button]`, CONTADOS); forzado `data-static` alcanzan los cinco, y cada uno lleva su medición en el ledger. El hueco de demo queda registrado en next-features §13, misma clase que el `kind='month'|'year'` de date-range-picker. - censo --only 90 % · component:audit PASS · eidos-lint invalid 0, class-hooks 0 · suite eidos sin rojos nuevos (el conocido skin-media-player) · rtl:check 0 · docs:check 0 · check por fichero limpio. - README con su «Talla y tema» y tab `Tokens` en la demo (20 claves, en vivo). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2 months ago
| [card-group](./card-group.md) | 90% | 22 | 18 | 0 | 0 | 2 | 2 | 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
| [collapsible](./collapsible.md) | 90% | 12 | 9 | 0 | 1 | 0 | 2 | 11 | – |
uix(tree-view): temable — 0 % → 92 %, y el velo que tiñe la carpeta entera 46 claves en el bloque `tree-view` de `recipes/base.ts` (fusionadas con el forward de paleta). Censo 0 % → 92 %, cero globales. Global 46 %, sin contrato 47 → 46. Molde del hermano `tree-grid` allí donde el problema es el mismo. LA PROPUESTA GENERADA FALLABA EN EL NOMBRE DE CASI TODO LO QUE IMPORTA: el clasificador toma el PRIMER selector de cada regla como si fuera la parte pintada, y aquí ese primero es el root o el branch-control cuando el nodo real es otro. 1. `root-width: 1px` / `root-bg` NO son del root: son la GUÍA de indentación (el `::before` del branch, una línea vertical). → `guide-width` + `guide-fg`, literalmente los nombres de tree-grid. Un `root-bg` que tiñe una línea es la clase de nombre que miente. 2. `branch-control-padding-inline-{k}` ⚠ fundía DOS ejes que se SUMAN en el mismo calc: el ritmo de la fila y el PASO DE PROFUNDIDAD (`--tree-depth × indent + padding`). Fundidos, tematizar la sangría habría movido el padding. → `row-padding-inline-{k}` + `indent-{k}`. 3. El prefijo `branch-control-` es erróneo: la regla reza `[data-tree-view-branch-control], [data-tree-view-item]` — las DOS filas. El CSS ya llamaba `row` a sus privados. → `row-*`, como tree-grid y como la lección de table. Y fuera el prefijo `root-` del chasis: el wrapper ES el componente. 4. `row-padding-block` ⚠ no eran dos valores en pugna sino cinco por talla: xs colapsa a `0`, las otras cuatro `--space-1`. 5. `branch-indicator-width` + `-height` son UN knob (`1em`) → `branch-indicator-size`. Bundle: la altura de fila casa 1:1; padding e indent llevan ritmo propio; la tipografía un paso por debajo desde lg — verbatim, como table y tree-grid. Los resueltos con `parts: ['root']` (el `data-size` va en `[data-tree-view-root]`, wrapper de eidos, no parte del morfo). Los `transparent` de outline/ghost y el `padding: 0` de ghost son identidad de variante y siguen literales. `hover-row-bg` SÍ se acuña, al revés que en grid-list, y por medición: la misma regla pinta dos nodos con arquetipo distinto, y `branch-control` NO lleva archetype — ahí el plano de la receta es la única pintura (velo medido ausente) y el token es toda la superficie de tema del hover. Tener un consumidor legítimo es lo que lo distingue del caso grid-list. EL DEFECTO QUE LA MEDICIÓN DESTAPÓ (preexistente, NO se toca aquí → next-features §12.8): al pasar el ratón por la fila de una carpeta abierta se tiñe LA CARPETA ENTERA, hijos incluidos. `archetype: 'item'` está declarado en el `<li>` branch (`morfo/components/tree-view.ts:103`), que contiene el control Y todo el `branch-content`, mientras la fila que el usuario señala es el `branch-control` de dentro: el nodo velado mide 336 px frente a los 36 px de la fila — medido y capturado. Un branch anidado acumula además el velo de sus ancestros, así que sus filas se ven más oscuras que las hermanas. Mover el arquetipo es morfo y mueve píxel en toda la demo. Es la TERCERA variante de la misma familia: table lo tiene en fila Y celda, grid-list en fila Y celda sobre el mismo nodo, y tree-view en un ANCESTRO del nodo señalado. Artefactos y gates: - Sonda antes/después = 0 diffs en 8.062 valores × 7 estados. - R-5.4: 45/46; `disabled-row-fg` adjudicado en el ledger (la demo monta CERO filas deshabilitadas, contadas; forzada alcanza oklch(0.61 0 0) → rgb(1,2,3)). - censo --only 92 % · component:audit PASS · eidos-lint invalid 0, class-hooks 0 · suite eidos sin rojos nuevos (el conocido skin-media-player) · rtl:check 0 · docs:check 0 · check por fichero limpio (72 globales, ninguno mío). - README con su «Talla y tema» y tab `Tokens` en la demo (46 claves, en vivo). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2 months ago
| [tree-view](./tree-view.md) | 92% | 28 | 24 | 1 | 0 | 1 | 2 | 46 | – |
feat(feed): temable — 0 % → 94 %, y cierra el bloque F2-A Octavo y último del bloque. censo 0 % → 94 % · global 43 % computed reposo y las CINCO tallas, idénticas al byte **El título no escala por talla: escala por NIVEL DE ENCABEZADO.** El informe leyó sus cuatro valores como una colisión de `size`, y son `aria-level` 3..6 — un encabezado más profundo es más pequeño porque es más profundo. Sus tokens son `article-title-font-size-{3,4,5,6}`, no coordenadas de talla. Tercera corrección de este tipo a un veredicto en el bloque. **El ⚠ del `sentinel` eran DOS medidas**, como sospechaba el veredicto: la fila-sonda mantiene un alto mínimo para que el observador tenga algo que intersecar, y el spinner que va dentro tiene su propio diámetro. El feed tipa por debajo del 1:1 de md en adelante, como `table` y `tree-grid`; la coordenada lo nombra en vez de esconderlo. **Sobre la medición, que aquí hubo que trabajarla.** La sonda dio 7 diffs y ninguno era un cambio: - el `box-shadow` del nodo `[data-busy]` está ANIMADO, y la sonda congela `transition` pero nunca `animation` —a propósito, porque congelarla impide que Presence monte nada—, así que lo muestrea en una fase distinta cada vez: dos corridas del MISMO código dan cinco diffs; - y el estado `hover` se mide después de haber forzado las tallas, así que su altura arrastra la última. Lo que decide es que las SEIS medidas estables —reposo y las cinco tallas— salieron idénticas al byte: 544,5 · 564,5 · 628,5 · 792,5 · 966,5 px. Queda escrito en el README para que el siguiente no persiga el mismo fantasma. audit PASS · eidos-lint 0 invalid · rtl 0 · docs 0 · check 0 en tocados · suite: sólo el rojo conocido Demo con tab Tokens: 50 filas, 0 sin computar. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [feed](./feed.md) | 94% | 33 | 30 | 0 | 1 | 1 | 1 | 50 | – |
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
| [scroll-area](./scroll-area.md) | 94% | 17 | 15 | 0 | 0 | 1 | 1 | 13 | – |
feat(tree-grid): el árbol se vuelve temable — 0 % → 95 % Cuarto del bloque F2-A. 42 knobs con 29 privados que no derivaban de nada; ahora 47 claves públicas y tres privados, los tres legítimos. censo 0 % → 95 % · global 41 % → 42 % computed 9.744 valores en 7 estados: 0 diffs **Las guías de indentación eran UN color, no un fondo.** Lo que la propuesta llamaba `root-bg-image` son las líneas verticales por `aria-level`: cinco gradientes apilados que dibujan una línea por ancestro. El knob es `guide-fg` (+ `guide-width`); la construcción se queda en la receta — el mismo reparto que el damero de gradient-builder, donde el color es el token y el patrón es de la receta. **Tres privados sobreviven, y por razones distintas**: `--_tree-grid-columns` no es un knob de tema sino un CANAL de layout que el wrapper escribe inline desde la definición de columnas del consumidor; `--_tree-grid-palette-element` es el forward THM-2; `--_tree-grid-stable-rows` es dato del consumidor. **El hover de fila es no determinista, y viene de antes de este eje.** Dos hallazgos medidos: 1. En filas CON BANDA el hover está muerto: la regla de `striped` pesa (0,7,0) contra los (0,5,0) del hover y usa el atajo, así que en las pares no ocurre nada al pasar el ratón. 2. En las demás, quién gana depende del ORDEN DE CARGA: el velo del arquetipo `item` y el hover de la receta empatan EXACTAMENTE a (0,5,0). Seis corridas de la misma configuración dieron cuatro veces «sin velo» y dos «con velo». Eso segundo obligó a parar y caracterizarlo: al ver 3 diffs tras un cambio trivial (un `border-width` a token) lo primero que hice fue sospechar de mi cambio; comparar dos corridas del MISMO código dio los mismos 3 diffs, así que no era el código sino un empate de especificidad resuelto por orden — la misma clase de fragilidad que el canon documenta para las bandas de z-index. No se toca aquí: decidir quién manda mueve píxel y es la decisión pendiente del velo. El guard de huérfanos cazó tres tokens que acuñé suponiendo (`font-family`, `fg`, `surface-bg`): existían en la receta pero leyendo el valor crudo. Ahora los leen, que es justo lo que el eje persigue. audit PASS · eidos-lint 0 invalid · rtl 0 · docs 0 · check 0 en tocados · suite: sólo el rojo conocido `skin-media-player` Demo con tab Tokens: 47 filas, 0 sin computar. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [tree-grid](./tree-grid.md) | 95% | 42 | 37 | 1 | 0 | 1 | 3 | 47 | – |
feat(table): la rejilla se vuelve temable — 0 % → 86 % Segundo del bloque F2-A. 46 knobs sin una sola entrada de contrato; ahora 45 claves públicas. censo 0 % → 86 % · global 39 % → 40 % computed 13.050 valores en 7 estados: **0 diffs** **Una trampa esquivada de milagro**: `table` YA tenía bloque en `base.ts` — los forwards de paleta THM-2. Insertar uno nuevo habría creado un segundo bloque `table:` y el catálogo lo habría descartado EN SILENCIO (gana el último). Las claves se fusionan en el existente; el guard de duplicadas lo confirma. **Dos nombres corregidos, como decía el veredicto**: lo que el privado llamaba `root-height-{k}` es la altura de la FILA (`row-height-{k}`), y el prefijo `root-` desaparece del resto — el envoltorio ES el componente y recipe-contract §1 no repite la parte en ese caso. **Qué casa con el bundle y qué no**, medido eje a eje: la altura de fila sí (1:1); el padding NO (la rejilla empaqueta más denso en xs y más suelto de md en adelante — forzar el bundle cambiaría el default); y la tipografía casa DESPLAZADA: de md en adelante la tabla tipa un paso por debajo (`font-size-md` = `var(--size-sm-font-size)`), que es deliberado y ahora se lee en el propio nombre de la coordenada en vez de esconderse en un primitivo. **Dos hallazgos del arquetipo `item`, y ninguno es mío** — la fila lo lleva, y ese velo de `archetypes.css` está a especificidad PLENA (0,5,0), a propósito: 1. **La prop `hoverable` no suprime nada.** Una fila se ilumina al pasar el ratón aunque el atributo no esté — medido con hover real, y ocurría ANTES de tocar esta receta. El arquetipo y la prop no se ponen de acuerdo sobre quién decide: es decisión de morfo, se presenta, no se toca de oficio. 2. **`selected-row-fg` era un token que mentía.** La misma regla fija el `color` de la fila seleccionada y gana a la receta (0,5,0 contra 0,3,0), así que el token no podía mover nada nunca. Lo cazó el centinela; retirado con su declaración muerta. La tinta de la fila seleccionada es del arquetipo. Y una corrección de rumbo a mitad de camino: al pasar todo a `background-color` el velo apareció en 3 sort-triggers (su velo sí va en `:where()`, 0,0,0). Eso es el barrido sistemático del velo, que NO está firmado — así que en los nodos velados se mantiene el atajo a propósito, con el porqué escrito en la línea. Primero lo diagnostiqué como regresión mía; la medición lo corrigió. Los 6 knobs que quedan: 3 privados de paleta (patrón THM-2, capa compartida) y 3 literales de layout/identidad (`inline-size: 100%` ×2, `opacity: 1`). El test `horizontal-escape` afirmaba el nombre del privado; ahora afirma el público, que es justo lo que este eje persigue. audit PASS · eidos-lint 0 invalid · rtl 0 · docs 0 · check 0 en tocados · suite: sólo el rojo conocido `skin-media-player` Demo con tab Tokens: 46 filas, 0 sin computar. README con «Talla y tema» y los dos hallazgos del arquetipo. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [command](./command.md) | 98% | 52 | 49 | 0 | 0 | 1 | 2 | 57 | – |
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 | – |
| [splitter](./splitter.md) | 100% | 18 | 17 | 0 | 0 | 0 | 1 | 15 | – |
uix(link-preview): temable — 0 % → 100 %, y el plano overlay que traía tipografía 33 claves en una entrada NUEVA de `recipes/base.ts`. Censo 0 % → **100 %**: no queda un knob de apariencia fuera del contrato (los tres restantes son sistema — anillo de foco y los dos del plano de profundidad que pintan la flecha). Global 48 %, sin contrato 42 → 41, al 100 % 7 → 8. 1. **Los per-talla llevan `parts: ['content']`**, no el host: el panel está PORTALADO y su `data-size` vive en el content, así que una cascada colgada del host no lo alcanza nunca. La talla mueve sólo dimensiones físicas (padding, min-width, tipo); familia, peso e interlineado son constantes a propósito, como ya decía la receta. 2. **La flecha no se tokeniza**: su fill y su stroke consumen el plano `overlay` para casar siempre con el panel; acuñar `arrow-fg` rompería justo esa garantía. El subrayado del trigger es un `color-mix` sobre `currentColor` — la mezcla ES el aspecto, así que el knob es la declaración entera, no el 35 %. Y el fallback encadenado del color del trigger viaja verbatim: la coma es parte del valor, no un segundo knob. EL HALLAZGO — el plano `overlay` impone TIPOGRAFÍA (→ next-features §12.9): `[data-depth='overlay']` (`generated/base.css:7088`) no declara sólo fondo, borde y sombra: también `font-family` y `line-height`. El panel estampa ese plano para su elevación, así que la declaración del plano empata a (0,1,0) con la de la receta y **gana por orden de carga** (la hoja generada va después del chunk de la receta). Medido con CDP `getMatchedStylesForNode`: el par `font-family` / `line-height` de esta receta **no había pintado nunca**. Retirado con **0 diffs**, que es la prueba. Afecta a los **veinte** componentes que estampan el plano. Lo que hay que decidir —aparte, mueve píxel— es si un plano de profundidad tiene competencia sobre la tipografía o sólo sobre la superficie. Cuarta ocurrencia de la clase «empate resuelto por orden de carga». CÓMO SE MIDIÓ, porque el instrumento estándar tampoco servía aquí: El panel abre en HOVER con retardo y está portalado → la sonda genérica ve **1 nodo**, y una sonda que compara un nodo pasa en falso. Sonda dirigida (abre por hover, captura los cinco nodos reales en las cinco tallas): determinismo verificado y **gate antes/después = 0 diffs sobre 550 valores**, repetido tras la retirada. El guard R-5.4 pasó de **3/35 a 31/33** con dos extensiones: `openBy: 'hover'` para este componente (un hover card no se abre con clic — clicar su `<a>` navega) y `text-decoration-color` en la lista de propiedades, que faltaba pese a estar en `KNOB_PROPS` del censo. Verificado que los otros QUINCE componentes con ledger no se mueven ni una cifra. Los dos tokens que siguen mudos son un conflicto ESTRUCTURAL, no un hueco de demo: para abrir el panel hay que tener el puntero en el trigger, y el hover es justo el estado cuya regla pisa la tinta y el subrayado de reposo — el token de hover lee vivo en la misma corrida. Adjudicados con esa razón. Gates: censo --only 100 % · component:audit PASS · eidos-lint invalid 0, class-hooks 0 · suite eidos sin rojos nuevos (el conocido skin-media-player) · rtl:check 0 · docs:check 0 · check por fichero limpio · README con «Talla y tema» y tab `Tokens` en la demo (33 claves, en vivo). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2 months ago
| [link-preview](./link-preview.md) | 100% | 15 | 12 | 0 | 0 | 0 | 3 | 33 | – |
uix(code): temable — 0 % → 100 %, y el harness que también le pisa el radio 6 claves fusionadas en el bloque `code` de `recipes/base.ts` (donde ya vivía el forward de paleta). Censo 0 % → **100 %**: no queda un knob de apariencia fuera del contrato. **Seis de sus trece knobs son SISTEMA y no se acuñan.** `code` es el primitivo tipográfico canónico: sus seis ejes de tipo consumen `--style-code-*` con la escotilla por instancia (`var(--_code-{eje}, var(--style-code-{eje}))`), la forma que D-TH.2-b fijó, y un primitivo no re-declara el vocabulario de su capa. Lo que entra al contrato es el CROMO de las variantes `soft` y `outline`. - El padding es em-relativo a propósito (la píldora crece con el código que envuelve) y lo declaran IGUAL las dos variantes con cromo: un knob por eje, no cuatro. - `--_code-color` sigue privado: conmutador de dos fuentes (tinta de contenido en línea / forward de paleta cuando llega `data-color`), mismo patrón que el borde de foco de textarea. - El `margin: 0` / `padding: 0` / `background: transparent` / `border: 0` de la base es RESET: la variante `plain` es texto desnudo por identidad. EL HALLAZGO — el harness pisa también a `code` (→ next-features §13, ampliado): Medido con CDP: `[data-uix-docs] code` declara `font-family`, `font-size`, `padding` y `border-radius` y gana **(0,1,1)** contra la regla BASE de la receta **(0,1,0)**. En la página de documentación el radio del componente es el del sitio (3px), no el suyo (4px). Sus reglas de VARIANTE (0,2,0) sí ganan, así que el efecto es selectivo y por eso sólo `radius` lee muerto. **No es un caso aislado**: es la misma familia de reglas del harness que tapa el `<pre>` de code-block con siete propiedades. Cualquier decisión sobre esa regla cubre los dos componentes. Artefactos y gates: - Sonda antes/después = 0 diffs en 174 valores × 7 estados. Determinismo verificado. - R-5.4: 0/6, los seis adjudicados con su medición — `radius` por el harness (CDP), los otros cinco porque la demo monta sólo la variante `plain`, sin cromo; forzando las variantes, los cinco alcanzan. - censo --only 100 % · component:audit PASS · rtl:check 0 · docs:check 0 · check por fichero limpio · suite eidos sin rojos nuevos. - README con «Talla y tema» y tab `Tokens` en la demo (6 claves). Nota de proceso: el fichero de excepciones llegó a quedar con sintaxis TS inválida por un apóstrofe sin escapar, y la comprobación que hice lo dio por bueno porque el `$?` capturado era el del `grep` de la tubería, no el del guard. Corregido, y re-verificados los ONCE componentes con ledger comprobando el código de salida REAL: cero fallos. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2 months ago
| [code](./code.md) | 100% | 13 | 7 | 0 | 0 | 0 | 6 | 6 | – |
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 | – |
uix(label): temable — 0 % → 100 % con dos claves 2 claves fusionadas en el bloque `label` de `recipes/base.ts` (donde ya vivía el forward de paleta). Censo 0 % → **100 %**. **Seis de sus ocho knobs son SISTEMA y no se acuñan.** `label` es uno de los seis primitivos tipográficos: sus seis ejes consumen `--style-label-*` a través de la escotilla por instancia (`var(--_label-{eje}, var(--style-label-{eje}))`), la forma que D-TH.2-b fijó y la que hace que un `<Label>` y un `<Text style="label">` se lean idénticos. La capa los posee; re-declararlos sería el vocabulario paralelo que la regla 2 prohíbe. Quedan DOS knobs propios, los que el primitivo añade por su cuenta: el `gap` al icono o indicador que puede acompañar al texto, y `disabled-fg`, la tinta cuando el consumidor marca la etiqueta como deshabilitada junto a su control. `--_label-color` sigue privado: conmutador de dos fuentes (eje de tinta en línea / forward de paleta cuando llega `data-color`), el mismo patrón ya resuelto igual en `code`, `textarea`, `spinner` y `skeleton`. Artefactos y gates: - Sonda antes/después = 0 diffs en 174 valores × 7 estados. - R-5.4: 1/2. `disabled-fg` adjudicado: la demo no monta ninguna etiqueta deshabilitada (0 nodos, contados); forzada, alcanza (rgb(1,2,3)). - censo --only 100 % · component:audit PASS · suite eidos sin rojos nuevos · rtl:check 0 · docs:check 0 · check por fichero limpio. - README con «Talla y tema» y tab `Tokens` en la demo. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2 months ago
| [label](./label.md) | 100% | 8 | 2 | 0 | 0 | 0 | 6 | 2 | – |
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 -->

Powered by TurnKey Linux.