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(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
- **Alcance global**: **47%** — 2195 de 4680 knobs pasan por un token público del componente
- **Reparto**: público 2195 · privado 654 · global 1251 · literal 580 · sistema transversal 509 _(fuera del ratio)_
- **Sin token público propio**: 45 · **alcance < 20 %**: 39 · **alcance 100 %**: 7 · **con eje `size`**: 65
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(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
## Sin ningún token público propio (45)
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(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
[`alert-dialog`](./alert-dialog.md) · [`announce`](./announce.md) · [`aspect-ratio`](./aspect-ratio.md) · [`auto-grid`](./auto-grid.md) · [`avatar`](./avatar.md) · [`card-group`](./card-group.md) · [`cascade`](./cascade.md) · [`clipboard`](./clipboard.md) · [`code`](./code.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) · [`kbd`](./kbd.md) · [`knob`](./knob.md) · [`label`](./label.md) · [`link`](./link.md) · [`link-preview`](./link-preview.md) · [`mark`](./mark.md) · [`mask-field`](./mask-field.md) · [`menu-dial`](./menu-dial.md) · [`mockup`](./mockup.md) · [`month-grid`](./month-grid.md) · [`motion`](./motion.md) · [`number-field`](./number-field.md) · [`palabras`](./palabras.md) · [`picker-shell`](./picker-shell.md) · [`range-calendar`](./range-calendar.md) · [`scroll-frames`](./scroll-frames.md) · [`skeleton`](./skeleton.md) · [`skin-media-player`](./skin-media-player.md) · [`spinner`](./spinner.md) · [`stack`](./stack.md) · [`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) · [`virtual-grid`](./virtual-grid.md) · [`virtual-list`](./virtual-list.md) · [`wrap`](./wrap.md) · [`year-grid`](./year-grid.md)
docs(theming): la auditoría de alcance de tema, componente a componente, con su propuesta El censo medía el eje y no lo explicaba: 5.205 knobs en dos tablas del plan no dicen QUÉ knob de QUÉ línea no alcanza un tema, ni qué token habría que crear. Ahora `theming-census.ts --report` escribe la auditoría entera bajo `docs/audit/theming/`: un README con la vista de conjunto y 170 fichas — 162 recetas con CSS + 8 componentes sin receta, el árbol completo de `eidos/components/`. Cada ficha de receta: knobs fuera de alcance con fichero:línea Y selector (agrupados por clase), sistema transversal aparte, los privados con la columna que decide («¿deriva de un público?»), y una PROPUESTA de corrección — el token a declarar en `base.ts` con su valor VERBATIM y su scope TSC. La propuesta deriva los nombres de recipe-contract §1 y theming §6.7; donde la doctrina no decide, marca `⚠ decisión` en vez de inventar. Y no propone acuñar lo que la doctrina prohíbe: lo que posee una capa compartida, el foco, la capa de estado, un token prestado de otra receta, un shorthand o un eje físico. Las 8 fichas sin receta dicen —medido, no supuesto— dónde vive su visual: el componente que componen (icon-button → button), la capa que consumen (affix → viewport-placement) o la receta ajena que pinta sus attrs (svg → badge/button). Defectos del instrumento corregidos en el mismo pase, todos encontrados mirando la salida: un `@import` pegado al primer selector se comía 2 knobs de color-picker (el suelo del censo no puede moverse); `:not(:disabled)` se leía como estado y producía `hover-disabled-*`; un knob que lee un privado se proponía a sí mismo en vez de resolverse por talla; `--icon-size-sm` se reportaba como préstamo del componente `icon` (ahora el préstamo se verifica contra las claves del dueño en `base.ts`); y el default de talla salía sin nombrar en vez de `-md`. Verificación: censo global idéntico al suelo publicado (5205 · 1621/33% · 856 · 1880 · 614 · 234) y COMPONENTE A COMPONENTE contra la tabla §9 del plan — 0 diferencias en 162 · regenerar dos veces da el árbol idéntico · el bloque de veredicto escrito a mano sobrevive · docs:check 0 errores sobre 813 docs · prettier limpio (el árbol generado entra en .prettierignore junto a eidos/generated). Las 10 primeras fichas llevan ya su veredicto de revisión: análisis correcto en las 10, propuesta apta en 2 (gradient-builder como piloto, combobox con cinco correcciones — dos de ellas evitaban romper el default), y 5 que no se tokenizan en solitario porque son alias de --calendar-*/--field-* y esperan la decisión de familia. Cuatro destaparon privados con prefijo ajeno o abreviado declarados en su propio CSS. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
## Tabla completa (162 recetas, por alcance ascendente)
La columna «contrato» cuenta las claves **públicas** del bloque del componente.
| componente | alcance | knobs | público | privado | global | literal | sistema | contrato | size |
| --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | :-: |
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 | – |
| [card-group](./card-group.md) | 0% | 24 | 0 | 0 | 18 | 4 | 2 | 0 | y |
| [spinner](./spinner.md) | 0% | 23 | 0 | 15 | 4 | 4 | 0 | 0 | y |
| [picker-shell](./picker-shell.md) | 0% | 21 | 0 | 4 | 17 | 0 | 0 | 0 | y |
| [link-preview](./link-preview.md) | 0% | 17 | 0 | 4 | 9 | 1 | 3 | 0 | y |
| [drag-drop](./drag-drop.md) | 0% | 16 | 0 | 3 | 6 | 0 | 7 | 1 | – |
| [kbd](./kbd.md) | 0% | 14 | 0 | 1 | 9 | 4 | 0 | 0 | – |
| [link](./link.md) | 0% | 14 | 0 | 4 | 2 | 5 | 3 | 0 | – |
feat(census): los primitivos tipográficos se miden contra su capa — pieza 0 de F2-A D-TH.2-b, la firma que va ANTES del bloque porque cambia el suelo del censo: medirla a mitad de camino falsearía todos los antes/después. `heading` marcaba «36 knobs, 0 % alcanzable» y eso no era deuda: era una lectura equivocada. Su receta resuelve cada eje como `var(--_heading-font-size, var(--style-h2-font-size))` — el privado es el escape POR INSTANCIA que el wrapper escribe desde una prop, y el named style es la superficie de tema, ya pública y viva. Acuñar `--heading-*` para espejarla sería un alias por eje × nivel: la clase que mató la purga del changelog §39. El criterio de qué ES un primitivo tipográfico se midió, no se supuso: o la receta SELECCIONA por `data-style` (`heading`, `text`, `s-text` — el named style es su API) o está atada entera a UN style (`code` → `--style-code-*`, `display` → `--style-hero-*`, `label` → `--style-label-*`). `code-block` queda FUERA a propósito: lee un par de tokens de style para su texto pero posee cromo de caja real, y eso sí es suyo. Detalle que costó una vuelta: la comprobación va ANTES de la de privado. Leer el privado primero puntúa el primitivo entero como inalcanzable cuando es completamente temable — por la capa que lo posee. antes 5.199 knobs · 1.837 públicos (37 %) · 894 privados · 232 sistema después 5.199 knobs · 1.837 públicos (38 %) · 788 privados · 338 sistema **Gate**: 106 knobs pasan de `private` a `system` en los SEIS primitivos y **cero** de los otros 156 se mueve — verificado componente a componente contra la versión en HEAD, no a ojo. Alcance `—` (nada que poseer) para heading, text y display; `s-text` al 100 %; `code` y `label` bajan a 7 y 2 knobs de deuda real. Informe regenerado (171 veredictos a mano intactos), veredicto de heading anotado como ejecutado, y recipe-contract §1 gana el párrafo que fija el criterio — incluida la frontera: un menú que lee `--style-label-font-family` para una etiqueta NO es un primitivo y no entra en el conjunto. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [code](./code.md) | 0% | 13 | 0 | 0 | 3 | 4 | 6 | 0 | – |
docs(theming): la auditoría de alcance de tema, componente a componente, con su propuesta El censo medía el eje y no lo explicaba: 5.205 knobs en dos tablas del plan no dicen QUÉ knob de QUÉ línea no alcanza un tema, ni qué token habría que crear. Ahora `theming-census.ts --report` escribe la auditoría entera bajo `docs/audit/theming/`: un README con la vista de conjunto y 170 fichas — 162 recetas con CSS + 8 componentes sin receta, el árbol completo de `eidos/components/`. Cada ficha de receta: knobs fuera de alcance con fichero:línea Y selector (agrupados por clase), sistema transversal aparte, los privados con la columna que decide («¿deriva de un público?»), y una PROPUESTA de corrección — el token a declarar en `base.ts` con su valor VERBATIM y su scope TSC. La propuesta deriva los nombres de recipe-contract §1 y theming §6.7; donde la doctrina no decide, marca `⚠ decisión` en vez de inventar. Y no propone acuñar lo que la doctrina prohíbe: lo que posee una capa compartida, el foco, la capa de estado, un token prestado de otra receta, un shorthand o un eje físico. Las 8 fichas sin receta dicen —medido, no supuesto— dónde vive su visual: el componente que componen (icon-button → button), la capa que consumen (affix → viewport-placement) o la receta ajena que pinta sus attrs (svg → badge/button). Defectos del instrumento corregidos en el mismo pase, todos encontrados mirando la salida: un `@import` pegado al primer selector se comía 2 knobs de color-picker (el suelo del censo no puede moverse); `:not(:disabled)` se leía como estado y producía `hover-disabled-*`; un knob que lee un privado se proponía a sí mismo en vez de resolverse por talla; `--icon-size-sm` se reportaba como préstamo del componente `icon` (ahora el préstamo se verifica contra las claves del dueño en `base.ts`); y el default de talla salía sin nombrar en vez de `-md`. Verificación: censo global idéntico al suelo publicado (5205 · 1621/33% · 856 · 1880 · 614 · 234) y COMPONENTE A COMPONENTE contra la tabla §9 del plan — 0 diferencias en 162 · regenerar dos veces da el árbol idéntico · el bloque de veredicto escrito a mano sobrevive · docs:check 0 errores sobre 813 docs · prettier limpio (el árbol generado entra en .prettierignore junto a eidos/generated). Las 10 primeras fichas llevan ya su veredicto de revisión: análisis correcto en las 10, propuesta apta en 2 (gradient-builder como piloto, combobox con cinco correcciones — dos de ellas evitaban romper el default), y 5 que no se tokenizan en solitario porque son alias de --calendar-*/--field-* y esperan la decisión de familia. Cuatro destaparon privados con prefijo ajeno o abreviado declarados en su propio CSS. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [virtual-list](./virtual-list.md) | 0% | 13 | 0 | 2 | 6 | 4 | 1 | 0 | y |
| [virtual-grid](./virtual-grid.md) | 0% | 12 | 0 | 2 | 6 | 3 | 1 | 0 | y |
| [skeleton](./skeleton.md) | 0% | 11 | 0 | 9 | 1 | 1 | 0 | 0 | y |
| [skin-media-player](./skin-media-player.md) | 0% | 11 | 0 | 0 | 2 | 7 | 2 | 0 | y |
| [scroll-frames](./scroll-frames.md) | 0% | 9 | 0 | 1 | 4 | 4 | 0 | 0 | – |
| [announce](./announce.md) | 0% | 8 | 0 | 0 | 8 | 0 | 0 | 0 | – |
| [clipboard](./clipboard.md) | 0% | 8 | 0 | 2 | 5 | 1 | 0 | 0 | – |
feat(census): los primitivos tipográficos se miden contra su capa — pieza 0 de F2-A D-TH.2-b, la firma que va ANTES del bloque porque cambia el suelo del censo: medirla a mitad de camino falsearía todos los antes/después. `heading` marcaba «36 knobs, 0 % alcanzable» y eso no era deuda: era una lectura equivocada. Su receta resuelve cada eje como `var(--_heading-font-size, var(--style-h2-font-size))` — el privado es el escape POR INSTANCIA que el wrapper escribe desde una prop, y el named style es la superficie de tema, ya pública y viva. Acuñar `--heading-*` para espejarla sería un alias por eje × nivel: la clase que mató la purga del changelog §39. El criterio de qué ES un primitivo tipográfico se midió, no se supuso: o la receta SELECCIONA por `data-style` (`heading`, `text`, `s-text` — el named style es su API) o está atada entera a UN style (`code` → `--style-code-*`, `display` → `--style-hero-*`, `label` → `--style-label-*`). `code-block` queda FUERA a propósito: lee un par de tokens de style para su texto pero posee cromo de caja real, y eso sí es suyo. Detalle que costó una vuelta: la comprobación va ANTES de la de privado. Leer el privado primero puntúa el primitivo entero como inalcanzable cuando es completamente temable — por la capa que lo posee. antes 5.199 knobs · 1.837 públicos (37 %) · 894 privados · 232 sistema después 5.199 knobs · 1.837 públicos (38 %) · 788 privados · 338 sistema **Gate**: 106 knobs pasan de `private` a `system` en los SEIS primitivos y **cero** de los otros 156 se mueve — verificado componente a componente contra la versión en HEAD, no a ojo. Alcance `—` (nada que poseer) para heading, text y display; `s-text` al 100 %; `code` y `label` bajan a 7 y 2 knobs de deuda real. Informe regenerado (171 veredictos a mano intactos), veredicto de heading anotado como ejecutado, y recipe-contract §1 gana el párrafo que fija el criterio — incluida la frontera: un menú que lee `--style-label-font-family` para una etiqueta NO es un primitivo y no entra en el conjunto. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [label](./label.md) | 0% | 8 | 0 | 0 | 2 | 0 | 6 | 0 | – |
docs(theming): la auditoría de alcance de tema, componente a componente, con su propuesta El censo medía el eje y no lo explicaba: 5.205 knobs en dos tablas del plan no dicen QUÉ knob de QUÉ línea no alcanza un tema, ni qué token habría que crear. Ahora `theming-census.ts --report` escribe la auditoría entera bajo `docs/audit/theming/`: un README con la vista de conjunto y 170 fichas — 162 recetas con CSS + 8 componentes sin receta, el árbol completo de `eidos/components/`. Cada ficha de receta: knobs fuera de alcance con fichero:línea Y selector (agrupados por clase), sistema transversal aparte, los privados con la columna que decide («¿deriva de un público?»), y una PROPUESTA de corrección — el token a declarar en `base.ts` con su valor VERBATIM y su scope TSC. La propuesta deriva los nombres de recipe-contract §1 y theming §6.7; donde la doctrina no decide, marca `⚠ decisión` en vez de inventar. Y no propone acuñar lo que la doctrina prohíbe: lo que posee una capa compartida, el foco, la capa de estado, un token prestado de otra receta, un shorthand o un eje físico. Las 8 fichas sin receta dicen —medido, no supuesto— dónde vive su visual: el componente que componen (icon-button → button), la capa que consumen (affix → viewport-placement) o la receta ajena que pinta sus attrs (svg → badge/button). Defectos del instrumento corregidos en el mismo pase, todos encontrados mirando la salida: un `@import` pegado al primer selector se comía 2 knobs de color-picker (el suelo del censo no puede moverse); `:not(:disabled)` se leía como estado y producía `hover-disabled-*`; un knob que lee un privado se proponía a sí mismo en vez de resolverse por talla; `--icon-size-sm` se reportaba como préstamo del componente `icon` (ahora el préstamo se verifica contra las claves del dueño en `base.ts`); y el default de talla salía sin nombrar en vez de `-md`. Verificación: censo global idéntico al suelo publicado (5205 · 1621/33% · 856 · 1880 · 614 · 234) y COMPONENTE A COMPONENTE contra la tabla §9 del plan — 0 diferencias en 162 · regenerar dos veces da el árbol idéntico · el bloque de veredicto escrito a mano sobrevive · docs:check 0 errores sobre 813 docs · prettier limpio (el árbol generado entra en .prettierignore junto a eidos/generated). Las 10 primeras fichas llevan ya su veredicto de revisión: análisis correcto en las 10, propuesta apta en 2 (gradient-builder como piloto, combobox con cinco correcciones — dos de ellas evitaban romper el default), y 5 que no se tokenizan en solitario porque son alias de --calendar-*/--field-* y esperan la decisión de familia. Cuatro destaparon privados con prefijo ajeno o abreviado declarados en su propio CSS. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [menu-dial](./menu-dial.md) | 0% | 8 | 0 | 3 | 1 | 4 | 0 | 0 | y |
| [mark](./mark.md) | 0% | 5 | 0 | 2 | 1 | 2 | 0 | 0 | – |
| [aspect-ratio](./aspect-ratio.md) | 0% | 3 | 0 | 0 | 1 | 2 | 0 | 0 | – |
| [date-picker](./date-picker.md) | 0% | 2 | 0 | 0 | 0 | 2 | 0 | 0 | – |
| [sticky](./sticky.md) | 0% | 2 | 0 | 1 | 0 | 1 | 0 | 1 | – |
| [text-blur](./text-blur.md) | 0% | 2 | 0 | 0 | 0 | 2 | 0 | 0 | – |
| [cascade](./cascade.md) | 0% | 1 | 0 | 0 | 0 | 1 | 0 | 0 | – |
| [motion](./motion.md) | 0% | 1 | 0 | 0 | 0 | 1 | 0 | 0 | – |
| [section](./section.md) | 0% | 1 | 0 | 0 | 0 | 1 | 0 | 4 | – |
| [chronos](./chronos.md) | 1% | 245 | 2 | 22 | 202 | 12 | 7 | 9 | y |
| [prose](./prose.md) | 1% | 74 | 1 | 0 | 43 | 30 | 0 | 2 | y |
| [nav-tree](./nav-tree.md) | 4% | 25 | 1 | 0 | 17 | 6 | 1 | 1 | – |
| [chart](./chart.md) | 9% | 92 | 8 | 0 | 66 | 14 | 4 | 17 | – |
| [result](./result.md) | 9% | 22 | 2 | 1 | 15 | 4 | 0 | 8 | – |
| [mockup](./mockup.md) | 14% | 29 | 4 | 7 | 13 | 5 | 0 | 0 | – |
uix(proof-of-human): el cromo del reto se puede temar; la paloma y el cielo no, y eso ya estaba firmado Cuarto del eje theme-reach. El reto ataba su escenario a primitivos globales: alto mínimo, radio, fondo, borde y los bordes de veredicto no los alcanzaba ningún tema. Ahora son 20 claves públicas, con el alto por talla en el canon de dos piezas y `parts: ['root']`, más la guía del trazo (corredor, línea, estela, marcador de meta) y el token arrastrable. Lo que NO entra es la escena — la paloma, la carta, los cielos del reloj — y no por falta de tiempo: el guard de recetas ya lista este componente en la excepción de tono fijo, y sus literales ya llevan anotación línea a línea. Un sello no se vuelve azul porque el tema lo haga. La revisión había anotado esto como decisión pendiente del autor; era una firma que ya existía y no había leído. Dos fallos míos que la verificación cazó y que quedan escritos porque son reutilizables. El primero: añadí un bloque `'proof-of-human'` a las recetas sin ver que ya había uno (el forward de paleta), y en un object literal la segunda clave gana — mi bloque se descartaba EN SILENCIO. Lo delató el diff de computed con 28 diferencias, empezando por un `border-radius` que caía a cero. El segundo: al fusionar los bloques perdí la última clave, y el guard de tokens fantasma lo cazó al instante. Verificación: diff de computed vacío sobre 406 valores en siete estados · component:audit PASS · suite eidos sin rojos nuevos · rtl:check 0 · docs:check 0. El centinela no vale aquí y así queda dicho: la demo declara su propio `min-block-size` y un degradado sobre el escenario, de modo que tapa dos de los tokens; los que no pisa responden. El 86 % que el censo sigue contando fuera son los dos ficheros de la escena, que enganchan por CLASE en vez de por data-attr — migrarlos es otro eje, anotado. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [proof-of-human](./proof-of-human.md) | 14% | 95 | 13 | 18 | 29 | 31 | 4 | 20 | – |
docs(theming): la auditoría de alcance de tema, componente a componente, con su propuesta El censo medía el eje y no lo explicaba: 5.205 knobs en dos tablas del plan no dicen QUÉ knob de QUÉ línea no alcanza un tema, ni qué token habría que crear. Ahora `theming-census.ts --report` escribe la auditoría entera bajo `docs/audit/theming/`: un README con la vista de conjunto y 170 fichas — 162 recetas con CSS + 8 componentes sin receta, el árbol completo de `eidos/components/`. Cada ficha de receta: knobs fuera de alcance con fichero:línea Y selector (agrupados por clase), sistema transversal aparte, los privados con la columna que decide («¿deriva de un público?»), y una PROPUESTA de corrección — el token a declarar en `base.ts` con su valor VERBATIM y su scope TSC. La propuesta deriva los nombres de recipe-contract §1 y theming §6.7; donde la doctrina no decide, marca `⚠ decisión` en vez de inventar. Y no propone acuñar lo que la doctrina prohíbe: lo que posee una capa compartida, el foco, la capa de estado, un token prestado de otra receta, un shorthand o un eje físico. Las 8 fichas sin receta dicen —medido, no supuesto— dónde vive su visual: el componente que componen (icon-button → button), la capa que consumen (affix → viewport-placement) o la receta ajena que pinta sus attrs (svg → badge/button). Defectos del instrumento corregidos en el mismo pase, todos encontrados mirando la salida: un `@import` pegado al primer selector se comía 2 knobs de color-picker (el suelo del censo no puede moverse); `:not(:disabled)` se leía como estado y producía `hover-disabled-*`; un knob que lee un privado se proponía a sí mismo en vez de resolverse por talla; `--icon-size-sm` se reportaba como préstamo del componente `icon` (ahora el préstamo se verifica contra las claves del dueño en `base.ts`); y el default de talla salía sin nombrar en vez de `-md`. Verificación: censo global idéntico al suelo publicado (5205 · 1621/33% · 856 · 1880 · 614 · 234) y COMPONENTE A COMPONENTE contra la tabla §9 del plan — 0 diferencias en 162 · regenerar dos veces da el árbol idéntico · el bloque de veredicto escrito a mano sobrevive · docs:check 0 errores sobre 813 docs · prettier limpio (el árbol generado entra en .prettierignore junto a eidos/generated). Las 10 primeras fichas llevan ya su veredicto de revisión: análisis correcto en las 10, propuesta apta en 2 (gradient-builder como piloto, combobox con cinco correcciones — dos de ellas evitaban romper el default), y 5 que no se tokenizan en solitario porque son alias de --calendar-*/--field-* y esperan la decisión de familia. Cuatro destaparon privados con prefijo ajeno o abreviado declarados en su propio CSS. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [menubar](./menubar.md) | 15% | 27 | 4 | 6 | 16 | 0 | 1 | 5 | y |
uix(time-picker): el reloj es suyo y pasa a tokens; el campo sigue siendo del Field Quinto del eje theme-reach, y el primero donde la mitad del componente NO debe tokenizarse: time-picker compone Field, así que su parte con forma de campo lee `--field-*` por diseño y duplicar esos ejes bajo prefijo propio sería el vocabulario paralelo que el contrato prohíbe. Lo que sí es invención suya —la cara del reloj— pasa a contrato: separación, ancho, tinta y tipografía del reloj, los colores de las tres manecillas, el refuerzo del pulgar sobre la superficie del popover y el radio del trigger en línea. Más el acento, que ahora es público en vez de esconderse tras un privado. Y un defecto que el censo no podía ver: la receta declaraba sus privados con el prefijo de OTRO componente (`--_time-field-*`) dentro de su propio CSS. No era sólo cosmético — un TimeField anidado y este picker se habrían pisado el nombre. Son 44 referencias renombradas, con el diff de computed en cero. El 82 % que el censo sigue contando fuera son esos préstamos de Field: no es deriva, es un préstamo con dueño, y su corrección es el mandato de composición de Field que la auditoría del sistema dejó apuntado (§5.3-3), no este eje. El guard de huérfanos me corrigió por el camino: había declarado doce tokens de más, copiados del range-picker (la franja AM/PM y los ticks), que este componente no tiene. Retirados; sólo `trigger-radius` tenía consumidor real y se cableó. Verificación: diff de computed vacío sobre 580 valores en ocho estados · component:audit PASS · suite eidos sin rojos nuevos · rtl:check 0 · docs:check 0. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [time-picker](./time-picker.md) | 18% | 59 | 10 | 12 | 24 | 11 | 2 | 16 | y |
| [time-range-picker](./time-range-picker.md) | 19% | 88 | 16 | 20 | 33 | 15 | 4 | 22 | y |
docs(theming): la auditoría de alcance de tema, componente a componente, con su propuesta El censo medía el eje y no lo explicaba: 5.205 knobs en dos tablas del plan no dicen QUÉ knob de QUÉ línea no alcanza un tema, ni qué token habría que crear. Ahora `theming-census.ts --report` escribe la auditoría entera bajo `docs/audit/theming/`: un README con la vista de conjunto y 170 fichas — 162 recetas con CSS + 8 componentes sin receta, el árbol completo de `eidos/components/`. Cada ficha de receta: knobs fuera de alcance con fichero:línea Y selector (agrupados por clase), sistema transversal aparte, los privados con la columna que decide («¿deriva de un público?»), y una PROPUESTA de corrección — el token a declarar en `base.ts` con su valor VERBATIM y su scope TSC. La propuesta deriva los nombres de recipe-contract §1 y theming §6.7; donde la doctrina no decide, marca `⚠ decisión` en vez de inventar. Y no propone acuñar lo que la doctrina prohíbe: lo que posee una capa compartida, el foco, la capa de estado, un token prestado de otra receta, un shorthand o un eje físico. Las 8 fichas sin receta dicen —medido, no supuesto— dónde vive su visual: el componente que componen (icon-button → button), la capa que consumen (affix → viewport-placement) o la receta ajena que pinta sus attrs (svg → badge/button). Defectos del instrumento corregidos en el mismo pase, todos encontrados mirando la salida: un `@import` pegado al primer selector se comía 2 knobs de color-picker (el suelo del censo no puede moverse); `:not(:disabled)` se leía como estado y producía `hover-disabled-*`; un knob que lee un privado se proponía a sí mismo en vez de resolverse por talla; `--icon-size-sm` se reportaba como préstamo del componente `icon` (ahora el préstamo se verifica contra las claves del dueño en `base.ts`); y el default de talla salía sin nombrar en vez de `-md`. Verificación: censo global idéntico al suelo publicado (5205 · 1621/33% · 856 · 1880 · 614 · 234) y COMPONENTE A COMPONENTE contra la tabla §9 del plan — 0 diferencias en 162 · regenerar dos veces da el árbol idéntico · el bloque de veredicto escrito a mano sobrevive · docs:check 0 errores sobre 813 docs · prettier limpio (el árbol generado entra en .prettierignore junto a eidos/generated). Las 10 primeras fichas llevan ya su veredicto de revisión: análisis correcto en las 10, propuesta apta en 2 (gradient-builder como piloto, combobox con cinco correcciones — dos de ellas evitaban romper el default), y 5 que no se tokenizan en solitario porque son alias de --calendar-*/--field-* y esperan la decisión de familia. Cuatro destaparon privados con prefijo ajeno o abreviado declarados en su propio CSS. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [anchor-nav](./anchor-nav.md) | 20% | 11 | 2 | 0 | 8 | 0 | 1 | 2 | – |
| [banner](./banner.md) | 20% | 10 | 2 | 6 | 1 | 1 | 0 | 42 | y |
| [button](./button.md) | 21% | 30 | 6 | 16 | 0 | 7 | 1 | 105 | y |
| [palabras](./palabras.md) | 22% | 471 | 103 | 1 | 272 | 90 | 5 | 0 | – |
| [toggle](./toggle.md) | 22% | 28 | 6 | 17 | 1 | 3 | 1 | 119 | y |
| [date-range-field](./date-range-field.md) | 25% | 9 | 2 | 0 | 4 | 2 | 1 | 3 | – |
| [time-range-field](./time-range-field.md) | 25% | 9 | 2 | 0 | 4 | 2 | 1 | 3 | – |
| [surface](./surface.md) | 25% | 4 | 1 | 3 | 0 | 0 | 0 | 25 | – |
| [callout](./callout.md) | 27% | 15 | 4 | 3 | 7 | 1 | 0 | 28 | – |
| [meter](./meter.md) | 29% | 14 | 4 | 6 | 2 | 2 | 0 | 28 | y |
| [knob](./knob.md) | 29% | 27 | 7 | 4 | 9 | 4 | 3 | 0 | y |
| [onion-menu](./onion-menu.md) | 29% | 27 | 7 | 0 | 8 | 9 | 3 | 12 | – |
| [empty-state](./empty-state.md) | 29% | 17 | 5 | 7 | 5 | 0 | 0 | 6 | y |
| [search-field](./search-field.md) | 31% | 14 | 4 | 5 | 0 | 4 | 1 | 17 | y |
| [password-field](./password-field.md) | 31% | 36 | 11 | 5 | 9 | 10 | 1 | 23 | y |
| [aura](./aura.md) | 31% | 35 | 11 | 4 | 14 | 6 | 0 | 24 | y |
| [toggle-group](./toggle-group.md) | 33% | 3 | 1 | 0 | 1 | 1 | 0 | 1 | – |
| [background](./background.md) | 35% | 26 | 8 | 6 | 6 | 3 | 3 | 31 | – |
| [avatar](./avatar.md) | 36% | 36 | 13 | 17 | 0 | 6 | 0 | 0 | y |
| [audio-player](./audio-player.md) | 37% | 19 | 7 | 0 | 8 | 4 | 0 | 5 | – |
| [tooltip](./tooltip.md) | 38% | 22 | 8 | 9 | 3 | 1 | 1 | 20 | y |
| [date-range-picker](./date-range-picker.md) | 40% | 53 | 20 | 9 | 19 | 2 | 3 | 22 | y |
docs(theming): la auditoría de alcance de tema, componente a componente, con su propuesta El censo medía el eje y no lo explicaba: 5.205 knobs en dos tablas del plan no dicen QUÉ knob de QUÉ línea no alcanza un tema, ni qué token habría que crear. Ahora `theming-census.ts --report` escribe la auditoría entera bajo `docs/audit/theming/`: un README con la vista de conjunto y 170 fichas — 162 recetas con CSS + 8 componentes sin receta, el árbol completo de `eidos/components/`. Cada ficha de receta: knobs fuera de alcance con fichero:línea Y selector (agrupados por clase), sistema transversal aparte, los privados con la columna que decide («¿deriva de un público?»), y una PROPUESTA de corrección — el token a declarar en `base.ts` con su valor VERBATIM y su scope TSC. La propuesta deriva los nombres de recipe-contract §1 y theming §6.7; donde la doctrina no decide, marca `⚠ decisión` en vez de inventar. Y no propone acuñar lo que la doctrina prohíbe: lo que posee una capa compartida, el foco, la capa de estado, un token prestado de otra receta, un shorthand o un eje físico. Las 8 fichas sin receta dicen —medido, no supuesto— dónde vive su visual: el componente que componen (icon-button → button), la capa que consumen (affix → viewport-placement) o la receta ajena que pinta sus attrs (svg → badge/button). Defectos del instrumento corregidos en el mismo pase, todos encontrados mirando la salida: un `@import` pegado al primer selector se comía 2 knobs de color-picker (el suelo del censo no puede moverse); `:not(:disabled)` se leía como estado y producía `hover-disabled-*`; un knob que lee un privado se proponía a sí mismo en vez de resolverse por talla; `--icon-size-sm` se reportaba como préstamo del componente `icon` (ahora el préstamo se verifica contra las claves del dueño en `base.ts`); y el default de talla salía sin nombrar en vez de `-md`. Verificación: censo global idéntico al suelo publicado (5205 · 1621/33% · 856 · 1880 · 614 · 234) y COMPONENTE A COMPONENTE contra la tabla §9 del plan — 0 diferencias en 162 · regenerar dos veces da el árbol idéntico · el bloque de veredicto escrito a mano sobrevive · docs:check 0 errores sobre 813 docs · prettier limpio (el árbol generado entra en .prettierignore junto a eidos/generated). Las 10 primeras fichas llevan ya su veredicto de revisión: análisis correcto en las 10, propuesta apta en 2 (gradient-builder como piloto, combobox con cinco correcciones — dos de ellas evitaban romper el default), y 5 que no se tokenizan en solitario porque son alias de --calendar-*/--field-* y esperan la decisión de familia. Cuatro destaparon privados con prefijo ajeno o abreviado declarados en su propio CSS. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [button-group](./button-group.md) | 40% | 5 | 2 | 0 | 0 | 3 | 0 | 1 | – |
| [badge](./badge.md) | 41% | 22 | 9 | 10 | 1 | 2 | 0 | 65 | y |
| [popover](./popover.md) | 42% | 51 | 20 | 6 | 22 | 0 | 3 | 36 | y |
| [qr-code](./qr-code.md) | 43% | 7 | 3 | 0 | 0 | 4 | 0 | 10 | – |
| [navigation-menu](./navigation-menu.md) | 44% | 38 | 15 | 1 | 13 | 5 | 4 | 26 | y |
| [waveform](./waveform.md) | 45% | 11 | 5 | 1 | 1 | 4 | 0 | 10 | y |
| [color-picker](./color-picker.md) | 46% | 82 | 36 | 10 | 22 | 11 | 3 | 54 | y |
| [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 |
| [text-focus](./text-focus.md) | 63% | 8 | 5 | 0 | 1 | 2 | 0 | 0 | – |
| [spin-field](./spin-field.md) | 64% | 27 | 16 | 0 | 8 | 1 | 2 | 20 | – |
| [file-upload](./file-upload.md) | 64% | 61 | 38 | 16 | 1 | 4 | 2 | 98 | y |
| [tags-input](./tags-input.md) | 67% | 46 | 28 | 13 | 1 | 0 | 4 | 90 | y |
| [toolbar](./toolbar.md) | 67% | 35 | 22 | 10 | 0 | 1 | 2 | 54 | y |
| [image-adjustments](./image-adjustments.md) | 67% | 18 | 10 | 0 | 4 | 1 | 3 | 12 | – |
| [text-gradient](./text-gradient.md) | 67% | 9 | 6 | 0 | 0 | 3 | 0 | 0 | – |
| [separator](./separator.md) | 67% | 6 | 4 | 0 | 0 | 2 | 0 | 3 | – |
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 |
| [dialog](./dialog.md) | 70% | 33 | 23 | 5 | 4 | 1 | 0 | 37 | y |
| [image-picker](./image-picker.md) | 71% | 20 | 12 | 0 | 1 | 4 | 3 | 13 | – |
| [pagination](./pagination.md) | 71% | 26 | 17 | 7 | 0 | 0 | 2 | 34 | y |
| [stepper](./stepper.md) | 71% | 60 | 40 | 15 | 0 | 1 | 4 | 69 | y |
| [skip-link](./skip-link.md) | 71% | 8 | 5 | 0 | 0 | 2 | 1 | 8 | – |
| [date-field](./date-field.md) | 73% | 11 | 8 | 3 | 0 | 0 | 0 | 21 | y |
| [time-field](./time-field.md) | 73% | 11 | 8 | 3 | 0 | 0 | 0 | 21 | y |
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 | – |
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 | – |
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 | – |
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 |
| [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 | – |
docs(theming): la auditoría de alcance de tema, componente a componente, con su propuesta El censo medía el eje y no lo explicaba: 5.205 knobs en dos tablas del plan no dicen QUÉ knob de QUÉ línea no alcanza un tema, ni qué token habría que crear. Ahora `theming-census.ts --report` escribe la auditoría entera bajo `docs/audit/theming/`: un README con la vista de conjunto y 170 fichas — 162 recetas con CSS + 8 componentes sin receta, el árbol completo de `eidos/components/`. Cada ficha de receta: knobs fuera de alcance con fichero:línea Y selector (agrupados por clase), sistema transversal aparte, los privados con la columna que decide («¿deriva de un público?»), y una PROPUESTA de corrección — el token a declarar en `base.ts` con su valor VERBATIM y su scope TSC. La propuesta deriva los nombres de recipe-contract §1 y theming §6.7; donde la doctrina no decide, marca `⚠ decisión` en vez de inventar. Y no propone acuñar lo que la doctrina prohíbe: lo que posee una capa compartida, el foco, la capa de estado, un token prestado de otra receta, un shorthand o un eje físico. Las 8 fichas sin receta dicen —medido, no supuesto— dónde vive su visual: el componente que componen (icon-button → button), la capa que consumen (affix → viewport-placement) o la receta ajena que pinta sus attrs (svg → badge/button). Defectos del instrumento corregidos en el mismo pase, todos encontrados mirando la salida: un `@import` pegado al primer selector se comía 2 knobs de color-picker (el suelo del censo no puede moverse); `:not(:disabled)` se leía como estado y producía `hover-disabled-*`; un knob que lee un privado se proponía a sí mismo en vez de resolverse por talla; `--icon-size-sm` se reportaba como préstamo del componente `icon` (ahora el préstamo se verifica contra las claves del dueño en `base.ts`); y el default de talla salía sin nombrar en vez de `-md`. Verificación: censo global idéntico al suelo publicado (5205 · 1621/33% · 856 · 1880 · 614 · 234) y COMPONENTE A COMPONENTE contra la tabla §9 del plan — 0 diferencias en 162 · regenerar dos veces da el árbol idéntico · el bloque de veredicto escrito a mano sobrevive · docs:check 0 errores sobre 813 docs · prettier limpio (el árbol generado entra en .prettierignore junto a eidos/generated). Las 10 primeras fichas llevan ya su veredicto de revisión: análisis correcto en las 10, propuesta apta en 2 (gradient-builder como piloto, combobox con cinco correcciones — dos de ellas evitaban romper el default), y 5 que no se tokenizan en solitario porque son alias de --calendar-*/--field-* y esperan la decisión de familia. Cuatro destaparon privados con prefijo ajeno o abreviado declarados en su propio CSS. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [box](./box.md) | 100% | 9 | 9 | 0 | 0 | 0 | 0 | 43 | – |
feat(census): los primitivos tipográficos se miden contra su capa — pieza 0 de F2-A D-TH.2-b, la firma que va ANTES del bloque porque cambia el suelo del censo: medirla a mitad de camino falsearía todos los antes/después. `heading` marcaba «36 knobs, 0 % alcanzable» y eso no era deuda: era una lectura equivocada. Su receta resuelve cada eje como `var(--_heading-font-size, var(--style-h2-font-size))` — el privado es el escape POR INSTANCIA que el wrapper escribe desde una prop, y el named style es la superficie de tema, ya pública y viva. Acuñar `--heading-*` para espejarla sería un alias por eje × nivel: la clase que mató la purga del changelog §39. El criterio de qué ES un primitivo tipográfico se midió, no se supuso: o la receta SELECCIONA por `data-style` (`heading`, `text`, `s-text` — el named style es su API) o está atada entera a UN style (`code` → `--style-code-*`, `display` → `--style-hero-*`, `label` → `--style-label-*`). `code-block` queda FUERA a propósito: lee un par de tokens de style para su texto pero posee cromo de caja real, y eso sí es suyo. Detalle que costó una vuelta: la comprobación va ANTES de la de privado. Leer el privado primero puntúa el primitivo entero como inalcanzable cuando es completamente temable — por la capa que lo posee. antes 5.199 knobs · 1.837 públicos (37 %) · 894 privados · 232 sistema después 5.199 knobs · 1.837 públicos (38 %) · 788 privados · 338 sistema **Gate**: 106 knobs pasan de `private` a `system` en los SEIS primitivos y **cero** de los otros 156 se mueve — verificado componente a componente contra la versión en HEAD, no a ojo. Alcance `—` (nada que poseer) para heading, text y display; `s-text` al 100 %; `code` y `label` bajan a 7 y 2 knobs de deuda real. Informe regenerado (171 veredictos a mano intactos), veredicto de heading anotado como ejecutado, y recipe-contract §1 gana el párrafo que fija el criterio — incluida la frontera: un menú que lee `--style-label-font-family` para una etiqueta NO es un primitivo y no entra en el conjunto. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [display](./display.md) | — | 6 | 0 | 0 | 0 | 0 | 6 | 0 | – |
docs(theming): la auditoría de alcance de tema, componente a componente, con su propuesta El censo medía el eje y no lo explicaba: 5.205 knobs en dos tablas del plan no dicen QUÉ knob de QUÉ línea no alcanza un tema, ni qué token habría que crear. Ahora `theming-census.ts --report` escribe la auditoría entera bajo `docs/audit/theming/`: un README con la vista de conjunto y 170 fichas — 162 recetas con CSS + 8 componentes sin receta, el árbol completo de `eidos/components/`. Cada ficha de receta: knobs fuera de alcance con fichero:línea Y selector (agrupados por clase), sistema transversal aparte, los privados con la columna que decide («¿deriva de un público?»), y una PROPUESTA de corrección — el token a declarar en `base.ts` con su valor VERBATIM y su scope TSC. La propuesta deriva los nombres de recipe-contract §1 y theming §6.7; donde la doctrina no decide, marca `⚠ decisión` en vez de inventar. Y no propone acuñar lo que la doctrina prohíbe: lo que posee una capa compartida, el foco, la capa de estado, un token prestado de otra receta, un shorthand o un eje físico. Las 8 fichas sin receta dicen —medido, no supuesto— dónde vive su visual: el componente que componen (icon-button → button), la capa que consumen (affix → viewport-placement) o la receta ajena que pinta sus attrs (svg → badge/button). Defectos del instrumento corregidos en el mismo pase, todos encontrados mirando la salida: un `@import` pegado al primer selector se comía 2 knobs de color-picker (el suelo del censo no puede moverse); `:not(:disabled)` se leía como estado y producía `hover-disabled-*`; un knob que lee un privado se proponía a sí mismo en vez de resolverse por talla; `--icon-size-sm` se reportaba como préstamo del componente `icon` (ahora el préstamo se verifica contra las claves del dueño en `base.ts`); y el default de talla salía sin nombrar en vez de `-md`. Verificación: censo global idéntico al suelo publicado (5205 · 1621/33% · 856 · 1880 · 614 · 234) y COMPONENTE A COMPONENTE contra la tabla §9 del plan — 0 diferencias en 162 · regenerar dos veces da el árbol idéntico · el bloque de veredicto escrito a mano sobrevive · docs:check 0 errores sobre 813 docs · prettier limpio (el árbol generado entra en .prettierignore junto a eidos/generated). Las 10 primeras fichas llevan ya su veredicto de revisión: análisis correcto en las 10, propuesta apta en 2 (gradient-builder como piloto, combobox con cinco correcciones — dos de ellas evitaban romper el default), y 5 que no se tokenizan en solitario porque son alias de --calendar-*/--field-* y esperan la decisión de familia. Cuatro destaparon privados con prefijo ajeno o abreviado declarados en su propio CSS. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
| [barcode](./barcode.md) | 100% | 5 | 5 | 0 | 0 | 0 | 0 | 7 | – |
| [flex](./flex.md) | 100% | 2 | 2 | 0 | 0 | 0 | 0 | 7 | – |
| [grid](./grid.md) | 100% | 2 | 2 | 0 | 0 | 0 | 0 | 13 | – |
| [alert-dialog](./alert-dialog.md) | — | 0 | 0 | 0 | 0 | 0 | 0 | 0 | – |
| [auto-grid](./auto-grid.md) | — | 0 | 0 | 0 | 0 | 0 | 0 | 0 | – |
| [container](./container.md) | — | 0 | 0 | 0 | 0 | 0 | 0 | 1 | – |
| [css-field](./css-field.md) | — | 0 | 0 | 0 | 0 | 0 | 0 | 0 | – |
| [float](./float.md) | — | 0 | 0 | 0 | 0 | 0 | 0 | 1 | – |
| [group](./group.md) | — | 0 | 0 | 0 | 0 | 0 | 0 | 1 | – |
| [highlight](./highlight.md) | — | 0 | 0 | 0 | 0 | 0 | 0 | 0 | – |
| [icon](./icon.md) | — | 0 | 0 | 0 | 0 | 0 | 0 | 2 | – |
| [mask-field](./mask-field.md) | — | 0 | 0 | 0 | 0 | 0 | 0 | 0 | – |
| [number-field](./number-field.md) | — | 0 | 0 | 0 | 0 | 0 | 0 | 0 | – |
| [stack](./stack.md) | — | 0 | 0 | 0 | 0 | 0 | 0 | 0 | – |
| [wrap](./wrap.md) | — | 0 | 0 | 0 | 0 | 0 | 0 | 0 | – |
## Veredicto y decisiones
<!-- veredicto:start -->
_(pendiente — lo escribe el autor; se conserva al regenerar)_
<!-- veredicto:end -->

Powered by TurnKey Linux.