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
# float-panel — alcance de tema: análisis y propuesta
> Generado por `node --import tsx/esm scripts/theming-census.ts --report`.
> Lo **medido** y la **propuesta** se regeneran; el **Veredicto** (§5) se conserva.
> Vista de conjunto: [README](./README.md) · método y protocolo:
> [`PLAN-theming.md`](../../process/PLAN-theming.md) §1, §2, §7.
docs(theming): 164 fichas regeneradas — dos perdían prosa medida, y el generador es el culpable
Una sesión regeneró todas las fichas de docs/audit/theming con el --report del
censo y las dejó sucias en el árbol. Antes de commitearlas las clasifiqué una a
una en vez de mirar la cifra:
- 155 sólo cambiaban la FECHA de medida. Inocuo, y correcto: el censo corrió
hoy.
- 7 traían cifras nuevas y buenas (collapsible y toolbar, que acaban de cerrar)
o retiraban una propuesta §4 ya cumplida. Mejora.
- 2 —chat-log y chat-composer— BORRABAN prosa medida: donde un humano escribió
«_Ninguno_ — los cuatro que había (el padding-block del divisor, el radio de
foco de la fila de evento…) están cosidos», la plantilla dejaba «_Ninguno._»,
y en chat-composer se llevaba además el bloque de las cuatro declaraciones
retiradas por muertas.
Esas dos van cosidas: el cuerpo de HEAD con la línea de cabecera regenerada.
El resto entra tal cual.
Que la regeneración sea mayoritariamente buena y ocasionalmente destructiva es
el peor reparto posible, porque nadie la mira. Registrado en §13 con su
arreglo: extender los marcadores tipo veredicto:end a cualquier bloque que un
humano haya ampliado, o que el generador respete una línea que no empiece por
su propia plantilla. Mientras tanto, regenerar fichas y commitear sin leer el
diff es una pérdida de datos silenciosa.
Y con él, la hermana que reportó una sesión de la tanda: snapshot-y-restaura
sobre un directorio COMPARTIDO pisa a quien escriba en medio. Dos sesiones
hicieron cp -r de docs/audit/theming y la segunda restauró desde un snapshot
anterior al trabajo de la primera, devolviéndole sus veredictos a «pendiente» a
media faena. El árbol de trabajo también es compartido: respalda por FICHERO
tocado, nunca por directorio.
Quedan fuera a propósito las fichas de chat-message y tags-input: sus sesiones
siguen trabajando.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
- **Medido**: 2026-08-24 · **Alcance** : **84%** — 41 de 49 knobs por token público
uix(float-panel): temable — 59 % → 84 %, muere un fantasma y queda una anomalía registrada
12 claves (28 → 40). Censo float-panel 59 % → **84 %** con `global` a CERO.
Cosido: las dos VARIANTES que ajustan desde el default elevado (`outline-*`,
`ghost-*`), los botones de su barra (`action-*`, `hover-action-*`) y el asa de
redimensionado.
MUERE UNO DE LOS NUEVE FANTASMAS DEL BARRIDO de esta mañana: el asa leía
`var(--color-content-tertiary, var(--color-content-secondary))` y ese primitivo
NO EXISTE, así que pintaba el respaldo. El contrato guarda lo que de verdad
pintaba, con lo que la referencia muerta desaparece sin mover un píxel.
ONCE ADJUDICACIONES MEDIDAS: la demo monta la variante por DEFECTO —ni outline ni
ghost— y no tiene botón de acción genérico, sólo el control de cierre; se forzó
el atributo de variante y se montó el botón donde el CSS lo selecciona, y el
radio del asa sólo pinta bajo `:focus-visible`. Las once alcanzan.
Y UNA ANOMALÍA REGISTRADA EN VEZ DE ESCONDIDA: `resize-grip-fg` **mueve** bajo
una réplica a mano de la secuencia del propio guard —congelar transiciones, blur,
aparcar el ratón, escribir en `:root` y en cada nodo con el prefijo, fotografiar
los mismos props con `::before`/`::after`/`::placeholder`— (oklch(0.5032 0 0) →
rgb(1,2,3)), y aun así el guard lo da por muerto. Descartado que el nodo no lleve
el atributo (lo lleva), que la regla necesite un estado (es la regla base), que
sea el valor centinela (es el mismo) y que sea HMR (dos corridas). Queda
adjudicado CON la medición y marcado como anomalía en §13: el token está vivo, lo
que está en duda es la lectura. Es por donde debe empezar la revisión adversarial
de este bloque — el precedente de F2-A dice que estos casos sí tienen causa.
Lo rojo que queda son 12 tokens anteriores, y seis de ellos —`bg`, `border`,
`border-width`, `shadow`, `font-family`, `line-height`— son el mismo conjunto que
en `popover`: el PLANO de profundidad gana sobre el panel (§12.9, pendiente de
firma).
Gates: sonda antes/después **0 diffs en 1.890 valores** (9 nodos × 7 estados) ·
censo --only 84 % · `--names` sin desviadas · component-audit PASS · eidos-lint 0
invalid · suite eidos con el único rojo conocido · rtl:check 0 · docs:check 0 ·
captura mirada (cabecera, botón de cierre y asa de la esquina en su sitio).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
- **Knobs de apariencia**: 53 — público 41 · privado 3 · global 0 · literal 5 · sistema 4 · excepción 0 _(los dos últimos, fuera del ratio)_
- **Contrato hoy** (`lib/recipes/base.ts`): 40 pública(s) — `outline-bg` , `outline-border` , `ghost-bg` , `ghost-border` , `ghost-shadow` , `action-radius` , `action-fg` , `action-font-size` , `hover-action-bg` , `hover-action-fg` , `resize-grip-fg` , `resize-grip-radius` , `bg` , `border` , `border-width` , `radius` , `shadow` , `shadow-topmost` , `active-shadow` , `fg` , `font-family` , `font-size` , `line-height` , `header-bg` , `header-padding-inline` , `header-padding-block` , `header-gap` , `controls-gap` , `title-font-size` , `title-font-weight` , `title-fg` , `body-padding-inline` , `body-padding-block` , `resize-size` , `resize-edge` , `button-size` , `grip-size` , `accent` , `transition-duration` , `transition-ease` · 1 privada(s) forward — `_palette-border`
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
- **Eje `size` **: no · **ficheros** : `float-panel.css`
## 1. Knobs fuera de alcance
uix(float-panel): temable — 59 % → 84 %, muere un fantasma y queda una anomalía registrada
12 claves (28 → 40). Censo float-panel 59 % → **84 %** con `global` a CERO.
Cosido: las dos VARIANTES que ajustan desde el default elevado (`outline-*`,
`ghost-*`), los botones de su barra (`action-*`, `hover-action-*`) y el asa de
redimensionado.
MUERE UNO DE LOS NUEVE FANTASMAS DEL BARRIDO de esta mañana: el asa leía
`var(--color-content-tertiary, var(--color-content-secondary))` y ese primitivo
NO EXISTE, así que pintaba el respaldo. El contrato guarda lo que de verdad
pintaba, con lo que la referencia muerta desaparece sin mover un píxel.
ONCE ADJUDICACIONES MEDIDAS: la demo monta la variante por DEFECTO —ni outline ni
ghost— y no tiene botón de acción genérico, sólo el control de cierre; se forzó
el atributo de variante y se montó el botón donde el CSS lo selecciona, y el
radio del asa sólo pinta bajo `:focus-visible`. Las once alcanzan.
Y UNA ANOMALÍA REGISTRADA EN VEZ DE ESCONDIDA: `resize-grip-fg` **mueve** bajo
una réplica a mano de la secuencia del propio guard —congelar transiciones, blur,
aparcar el ratón, escribir en `:root` y en cada nodo con el prefijo, fotografiar
los mismos props con `::before`/`::after`/`::placeholder`— (oklch(0.5032 0 0) →
rgb(1,2,3)), y aun así el guard lo da por muerto. Descartado que el nodo no lleve
el atributo (lo lleva), que la regla necesite un estado (es la regla base), que
sea el valor centinela (es el mismo) y que sea HMR (dos corridas). Queda
adjudicado CON la medición y marcado como anomalía en §13: el token está vivo, lo
que está en duda es la lectura. Es por donde debe empezar la revisión adversarial
de este bloque — el precedente de F2-A dice que estos casos sí tienen causa.
Lo rojo que queda son 12 tokens anteriores, y seis de ellos —`bg`, `border`,
`border-width`, `shadow`, `font-family`, `line-height`— son el mismo conjunto que
en `popover`: el PLANO de profundidad gana sobre el panel (§12.9, pendiente de
firma).
Gates: sonda antes/después **0 diffs en 1.890 valores** (9 nodos × 7 estados) ·
censo --only 84 % · `--names` sin desviadas · component-audit PASS · eidos-lint 0
invalid · suite eidos con el único rojo conocido · rtl:check 0 · docs:check 0 ·
captura mirada (cabecera, botón de cierre y asa de la esquina en su sitio).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
### 1.1 Directo a primitivo global (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
uix(float-panel): temable — 59 % → 84 %, muere un fantasma y queda una anomalía registrada
12 claves (28 → 40). Censo float-panel 59 % → **84 %** con `global` a CERO.
Cosido: las dos VARIANTES que ajustan desde el default elevado (`outline-*`,
`ghost-*`), los botones de su barra (`action-*`, `hover-action-*`) y el asa de
redimensionado.
MUERE UNO DE LOS NUEVE FANTASMAS DEL BARRIDO de esta mañana: el asa leía
`var(--color-content-tertiary, var(--color-content-secondary))` y ese primitivo
NO EXISTE, así que pintaba el respaldo. El contrato guarda lo que de verdad
pintaba, con lo que la referencia muerta desaparece sin mover un píxel.
ONCE ADJUDICACIONES MEDIDAS: la demo monta la variante por DEFECTO —ni outline ni
ghost— y no tiene botón de acción genérico, sólo el control de cierre; se forzó
el atributo de variante y se montó el botón donde el CSS lo selecciona, y el
radio del asa sólo pinta bajo `:focus-visible`. Las once alcanzan.
Y UNA ANOMALÍA REGISTRADA EN VEZ DE ESCONDIDA: `resize-grip-fg` **mueve** bajo
una réplica a mano de la secuencia del propio guard —congelar transiciones, blur,
aparcar el ratón, escribir en `:root` y en cada nodo con el prefijo, fotografiar
los mismos props con `::before`/`::after`/`::placeholder`— (oklch(0.5032 0 0) →
rgb(1,2,3)), y aun así el guard lo da por muerto. Descartado que el nodo no lleve
el atributo (lo lleva), que la regla necesite un estado (es la regla base), que
sea el valor centinela (es el mismo) y que sea HMR (dos corridas). Queda
adjudicado CON la medición y marcado como anomalía en §13: el token está vivo, lo
que está en duda es la lectura. Es por donde debe empezar la revisión adversarial
de este bloque — el precedente de F2-A dice que estos casos sí tienen causa.
Lo rojo que queda son 12 tokens anteriores, y seis de ellos —`bg`, `border`,
`border-width`, `shadow`, `font-family`, `line-height`— son el mismo conjunto que
en `popover`: el PLANO de profundidad gana sobre el panel (§12.9, pendiente de
firma).
Gates: sonda antes/después **0 diffs en 1.890 valores** (9 nodos × 7 estados) ·
censo --only 84 % · `--names` sin desviadas · component-audit PASS · eidos-lint 0
invalid · suite eidos con el único rojo conocido · rtl:check 0 · docs:check 0 ·
captura mirada (cabecera, botón de cierre y asa de la esquina en su sitio).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
_Ninguno._
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
### 1.2 A través de un privado (3)
| # | fichero:línea | selector | propiedad | valor |
| ---: | --- | --- | --- | --- |
| 1 | `float-panel.css:107` | `[data-float-panel-header]` | `border-block-end` | `var(--border-width-medium) solid var(--_float-panel-accent)` |
| 2 | `float-panel.css:184` | `[data-float-panel-action]:focus-visible, [data-float-panel-stage-trigger]:focus-visible` | `box-shadow` | `0 0 0 2px var(--_float-panel-accent)` |
| 3 | `float-panel.css:255` | `[data-float-panel-resize-grip]:hover, [data-float-panel-resize-grip][data-grabbed]` | `color` | `var(--_float-panel-accent)` |
### 1.3 Literales (5)
| # | fichero:línea | selector | propiedad | valor |
| ---: | --- | --- | --- | --- |
| 1 | `float-panel.css:173` | `[data-float-panel-action], [data-float-panel-stage-trigger]` | `line-height` | `1` |
| 2 | `float-panel.css:231` | `[data-float-panel-resize-grip]` | `background-image` | `repeating-linear-gradient( -45deg, transparent 0 3px, currentColor 3px 4.5px )` |
| 3 | `float-panel.css:248` | `[data-float-panel-resize-grip]:dir(rtl)` | `background-image` | `repeating-linear-gradient(45deg, transparent 0 3px, currentColor 3px 4.5px)` |
| 4 | `float-panel.css:254` | `[data-float-panel-resize-grip]:hover, [data-float-panel-resize-grip][data-grabbed]` | `opacity` | `1` |
| 5 | `float-panel.css:259` | `[data-float-panel-resize-grip]:focus-visible` | `opacity` | `1` |
tooling(theming): el censo aprende a leer la válvula del canon — clase `exception`
Global 58 % → **59 %** sin tocar una línea de CSS: 54 knobs que eran deuda
resultan ser desviaciones que el canon ya había firmado.
`recipe-contract` §3 dice que una desviación anotada `/* literal: <razón> */`
EN SU PROPIA DECLARACIÓN es válida, y `component-audit` la honra desde siempre
(`declarationWindow` + `/literal:/i` en R-2.1, R-2.6 y R-2.7). El censo era el
único instrumento que no: su `strip()` blanquea los comentarios ANTES de
clasificar, así que las **81 anotaciones del catálogo** contaban como literales
sin excusa. Dos instrumentos, un canon, dos respuestas — y la que mandaba era la
del que no sabía leerlo.
Ahora un literal anotado cae en la clase **`exception`, fuera del ratio** como
`system`, y por la misma razón: no es que un tema no lo alcance, es que el canon
ya aceptó por escrito que ahí no va un token.
**54 knobs en 12 componentes**: `prose` 21 (su escala editorial em-relativa, que
su README documenta como decisión — «No 5× duplicated scale»), `proof-of-human`
16 (la escena de tono fijo), `palabras` 3, `timeline` 2 (73 % → **77 %**),
`result` 1 (86 % → **90 %**), y siete más con una cada uno.
Detalles que costaron medición:
- **La anotación vale para la DECLARACIÓN entera**, no sólo para su primera
línea: un valor partido en varias líneas lleva la nota al final. Se comprueban
todas las líneas que abarca la declaración.
- **`strip()` blanquea en el sitio** (sustituye por espacios, conserva los
saltos), así que el cuerpo despojado y el crudo quedan alineados línea a línea
y basta con guardar el crudo al lado.
- Muta-prueba: retirar una anotación de `prose` mueve el knob de `exception` a
`literal` (21 → 20) y el conteo vuelve al restaurarla.
Efecto colateral bueno: cada ficha gana una **§1.4 «Excepciones firmadas»** que
las LISTA con su razón. Estaban escritas en el CSS y no se leían desde ninguna
parte; ahora la ficha del componente las enseña, que es donde se decide si una
sigue siendo cierta.
Las 163 fichas cambian porque la plantilla cambia (sección nueva + la línea de
reparto); el README de la auditoría gana la fila de la clase y la nota de que
`system` y `exception` quedan fuera del denominador.
Guards: `--names` 4.105 claves, DESVIADAS 0 · component-audit PASS · docs:check
0 · `check` con 72 errores globales y 0 en los ficheros tocados.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
### 1.4 Excepciones firmadas (0) — fuera del ratio
Literales que llevan su anotación `/* literal: <razón> */` en la propia
declaración: la válvula de recipe-contract §3, la misma que honra
`component-audit` . **Una desviación firmada no es deuda** — se listan para que la
razón se lea, no para acuñarlas.
_Ninguno._
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
## 2. Sistema transversal (4) — informativo, fuera del ratio
Un tema los alcanza **a nivel de sistema** , por diseño (recipe-contract §2).
| # | fichero:línea | selector | propiedad | valor |
| ---: | --- | --- | --- | --- |
| 1 | `float-panel.css:121` | `[data-float-panel-header]:focus-visible` | `box-shadow` | `inset 0 0 0 var(--ring-inset-width) var(--ring-inset-color, currentColor)` |
| 2 | `float-panel.css:125` | `[data-float-panel-header][data-grabbed]` | `box-shadow` | `inset 0 0 0 var(--ring-inset-width) var(--ring-inset-color, currentColor)` |
| 3 | `float-panel.css:239` | `[data-float-panel-resize-grip]` | `opacity` | `var(--opacity-muted)` |
| 4 | `float-panel.css:261` | `[data-float-panel-resize-grip]:focus-visible` | `box-shadow` | `inset 0 0 0 var(--ring-inset-width) var(--ring-inset-color, currentColor)` |
## 3. Privados de la receta — ¿de dónde sale su valor?
| privado | declaraciones | valor(es) | origen | ¿deriva de un público? |
| --- | ---: | --- | --- | :-: |
| `--_float-panel-accent` | 2 | `var(--float-panel-accent)` , `var(--_float-panel-palette-border)` | private, public | no |
Consumidos y **no declarados en el CSS** (vienen de `base.ts` o de un estilo inline del wrapper): `--_float-panel-palette-border` .
## 4. Propuesta de corrección
uix(float-panel): temable — 59 % → 84 %, muere un fantasma y queda una anomalía registrada
12 claves (28 → 40). Censo float-panel 59 % → **84 %** con `global` a CERO.
Cosido: las dos VARIANTES que ajustan desde el default elevado (`outline-*`,
`ghost-*`), los botones de su barra (`action-*`, `hover-action-*`) y el asa de
redimensionado.
MUERE UNO DE LOS NUEVE FANTASMAS DEL BARRIDO de esta mañana: el asa leía
`var(--color-content-tertiary, var(--color-content-secondary))` y ese primitivo
NO EXISTE, así que pintaba el respaldo. El contrato guarda lo que de verdad
pintaba, con lo que la referencia muerta desaparece sin mover un píxel.
ONCE ADJUDICACIONES MEDIDAS: la demo monta la variante por DEFECTO —ni outline ni
ghost— y no tiene botón de acción genérico, sólo el control de cierre; se forzó
el atributo de variante y se montó el botón donde el CSS lo selecciona, y el
radio del asa sólo pinta bajo `:focus-visible`. Las once alcanzan.
Y UNA ANOMALÍA REGISTRADA EN VEZ DE ESCONDIDA: `resize-grip-fg` **mueve** bajo
una réplica a mano de la secuencia del propio guard —congelar transiciones, blur,
aparcar el ratón, escribir en `:root` y en cada nodo con el prefijo, fotografiar
los mismos props con `::before`/`::after`/`::placeholder`— (oklch(0.5032 0 0) →
rgb(1,2,3)), y aun así el guard lo da por muerto. Descartado que el nodo no lleve
el atributo (lo lleva), que la regla necesite un estado (es la regla base), que
sea el valor centinela (es el mismo) y que sea HMR (dos corridas). Queda
adjudicado CON la medición y marcado como anomalía en §13: el token está vivo, lo
que está en duda es la lectura. Es por donde debe empezar la revisión adversarial
de este bloque — el precedente de F2-A dice que estos casos sí tienen causa.
Lo rojo que queda son 12 tokens anteriores, y seis de ellos —`bg`, `border`,
`border-width`, `shadow`, `font-family`, `line-height`— son el mismo conjunto que
en `popover`: el PLANO de profundidad gana sobre el panel (§12.9, pendiente de
firma).
Gates: sonda antes/después **0 diffs en 1.890 valores** (9 nodos × 7 estados) ·
censo --only 84 % · `--names` sin desviadas · component-audit PASS · eidos-lint 0
invalid · suite eidos con el único rojo conocido · rtl:check 0 · docs:check 0 ·
captura mirada (cabecera, botón de cierre y asa de la esquina en su sitio).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
### 4.1 Tokens a declarar en `lib/recipes/base.ts` (3)
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
Valor **verbatim** del CSS de hoy: el default no se mueve, sólo cambia quién
puede moverlo. Nombres derivados de recipe-contract §1 (ejes lógicos, talla
al final) y theming §6.7 (slots de color, modificador delante). Un token con
DOS valores distintos es una colisión de nombre: son dos knobs, o el nombre
no distingue lo que debería — se marca `⚠` .
| token (`--float-panel-…`) | scope TSC | valor propuesto | usos |
| --- | --- | --- | ---: |
| `action-shadow` | `root` | ⚠ `var(--float-panel-accent)` / `var(--_float-panel-palette-border)` | 2 |
| `resize-grip-bg-image` | `root` | ⚠ `repeating-linear-gradient( -45deg, transparent 0 3px, currentColor 3px 4.5px )` / `repeating-linear-gradient(45deg, transparent 0 3px, currentColor 3px 4.5px)` | 2 |
| `hover-resize-grip-fg` | `root` | ⚠ `var(--float-panel-accent)` / `var(--_float-panel-palette-border)` | 2 |
### 4.2 Sin nombre mecánico (4)
- **⚠ decisión: `border-block-end` es shorthand o eje físico — hay que partirlo en ejes lógicos antes de nombrarlo (recipe-contract §1, R-4.4)** — 1: `border-block-end` .
- **⚠ decisión: `1` es un valor identidad o geometría de layout, no un knob de tema — el perímetro de «knob» es D-TH.2, sin firmar** — 3: `line-height` , `opacity` .
### 4.3 Avisos sobre los tokens propuestos (1)
- **el privado `--_float-panel-accent` debe pasar a leer este público (o desaparecer)** — `--float-panel-action-shadow` , `--float-panel-hover-resize-grip-fg`
### 4.4 Lo que hay que comprobar a mano (PLAN-theming §1.3 · §7.4)
- [ ] **Privado que no deriva de un público** — §3 lo marca; el privado debe leer el público o desaparecer.
- [ ] **Velo o acento en el nodo equivocado** (`archetype: 'item'` en un envoltorio, un `background` en shorthand que mata la capa de estado) — se mide desde el píxel hacia arriba.
- [ ] **Doble animación** al mover un sello a una superficie con animación propia — registro de `animationstart` /`animationend`.
- [ ] **Diff de computed = 0** en reposo · hover · abierto · disabled · foco, por talla, antes y después.
- [ ] **Centinela por token nuevo** : valor imposible en el root → el nodo lo sigue. Si no, el token miente.
## 5. Veredicto
<!-- veredicto:start -->
uix(float-panel): temable — 59 % → 84 %, muere un fantasma y queda una anomalía registrada
12 claves (28 → 40). Censo float-panel 59 % → **84 %** con `global` a CERO.
Cosido: las dos VARIANTES que ajustan desde el default elevado (`outline-*`,
`ghost-*`), los botones de su barra (`action-*`, `hover-action-*`) y el asa de
redimensionado.
MUERE UNO DE LOS NUEVE FANTASMAS DEL BARRIDO de esta mañana: el asa leía
`var(--color-content-tertiary, var(--color-content-secondary))` y ese primitivo
NO EXISTE, así que pintaba el respaldo. El contrato guarda lo que de verdad
pintaba, con lo que la referencia muerta desaparece sin mover un píxel.
ONCE ADJUDICACIONES MEDIDAS: la demo monta la variante por DEFECTO —ni outline ni
ghost— y no tiene botón de acción genérico, sólo el control de cierre; se forzó
el atributo de variante y se montó el botón donde el CSS lo selecciona, y el
radio del asa sólo pinta bajo `:focus-visible`. Las once alcanzan.
Y UNA ANOMALÍA REGISTRADA EN VEZ DE ESCONDIDA: `resize-grip-fg` **mueve** bajo
una réplica a mano de la secuencia del propio guard —congelar transiciones, blur,
aparcar el ratón, escribir en `:root` y en cada nodo con el prefijo, fotografiar
los mismos props con `::before`/`::after`/`::placeholder`— (oklch(0.5032 0 0) →
rgb(1,2,3)), y aun así el guard lo da por muerto. Descartado que el nodo no lleve
el atributo (lo lleva), que la regla necesite un estado (es la regla base), que
sea el valor centinela (es el mismo) y que sea HMR (dos corridas). Queda
adjudicado CON la medición y marcado como anomalía en §13: el token está vivo, lo
que está en duda es la lectura. Es por donde debe empezar la revisión adversarial
de este bloque — el precedente de F2-A dice que estos casos sí tienen causa.
Lo rojo que queda son 12 tokens anteriores, y seis de ellos —`bg`, `border`,
`border-width`, `shadow`, `font-family`, `line-height`— son el mismo conjunto que
en `popover`: el PLANO de profundidad gana sobre el panel (§12.9, pendiente de
firma).
Gates: sonda antes/después **0 diffs en 1.890 valores** (9 nodos × 7 estados) ·
censo --only 84 % · `--names` sin desviadas · component-audit PASS · eidos-lint 0
invalid · suite eidos con el único rojo conocido · rtl:check 0 · docs:check 0 ·
captura mirada (cabecera, botón de cierre y asa de la esquina en su sitio).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
**EJECUTADO 2026-08-22 — 59 % → 84 %**, 12 claves. `global` a CERO.
Lo cosido: las dos VARIANTES que ajustan desde el default elevado
(`outline-*` / `ghost-*` ) y los botones de su barra (`action-*` +
`hover-action-*` ), más el asa de redimensionado.
**Y de paso muere uno de los nueve fantasmas del barrido**: el asa leía
`var(--color-content-tertiary, var(--color-content-secondary))` — ese primitivo
NO EXISTE, así que pintaba el respaldo. El contrato guarda lo que de verdad
pintaba (`--color-content-secondary`), con lo que la referencia muerta
desaparece sin mover un píxel.
**Once adjudicaciones medidas**: la demo monta la variante por DEFECTO (no
outline ni ghost) y no tiene botón de acción genérico —sólo el control de
cierre—, así que se forzaron el atributo de variante y se montó el botón donde
el CSS lo selecciona; el radio del asa sólo pinta bajo `:focus-visible` . Las
once alcanzan.
uix(theming): revisión adversarial del bloque — la pasada de HOVER envenenaba a todos los tokens de reposo
Cinco hipótesis, un hallazgo real, cuatro refutadas. Bloque de CATORCE
componentes; global del eje 56 % → **62 %**.
HALLAZGO REAL — la anomalía de `float-panel` tenía causa, y era del guard.
`resize-grip-fg` movía aislado y leía muerto en una corrida completa. Instrumenté
el propio guard para probar UNA clave y salió `moved=true`; luego, en la corrida
entera, muerto. La causa: **la pasada de HOVER deja el puntero sobre el último
nodo que tocó**, y una regla `:hover` gana a la de reposo con la que comparte
nodo — el asa re-apunta su color al acento al pasar el ratón. Es decir:
**cualquier token de reposo probado DESPUÉS de un token `hover-*` podía leer
muerto**. Es exactamente la clase que F2-A arregló con el clic-foco, una pasada
más tarde: allí se aparcó el puntero tras ABRIR, aquí faltaba aparcarlo tras
HOVERAR.
Arreglado. Y entonces el propio guard delató DOS excepciones STALE —
`float-panel.resize-grip-fg` y `media-player.track` —, retiradas: dos tokens que
el ledger daba por muertos están vivos. Se confirma la regla de F2-A: **un falso
negativo siempre tiene causa**; registrarlo como «sin causa» era el paso previo,
no el final.
REFUTADA «hay tokens huérfanos»: comprobación ESTRICTA —comentarios despojados,
que es el hueco por el que `popover.bg` sobrevivió, sobre todo el CSS del árbol—
de las **553 claves** de los catorce bloques: ninguna declarada sin que una regla
la lea.
REFUTADA «el cambio de instrumento rompió algo»: los **27 componentes con ledger
re-verificados** tras aparcar el puntero — cero regresiones. Los tres rojos que
quedan (`drawer` 24, `metrics` 16, `color-picker` 23) son ANTERIORES al bloque y
están anotados con lo que ya se descartó de cada uno.
REFUTADA «quedan fantasmas del barrido en lo tocado»: pasa de 9 a **8** — el
`--color-content-tertiary` de float-panel murió con su costura. Los ocho
restantes son de componentes que este bloque no tocó.
CONFIRMADO, y ya estaba escrito: hay gates FINOS. `popover` mide 1 nodo en reposo
(7 en abierto), `drawer` 1, `context-menu` 1 + 14 en abierto, `color-picker`
5 + 12. Cada veredicto lo dice, y lo que sostiene esas cifras es el forzado a
mano de sus estados, no la sonda.
Guards: `--names` sin desviadas · docs:check 0 · censo 62 % (2.877 públicos de
5.137 knobs; `global` 1.145 → 912).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
**La ANOMALÍA que registré aquí quedó RESUELTA el mismo día**, en la revisión
adversarial del bloque: `resize-grip-fg` movía aislado y leía muerto en una
corrida completa porque **la pasada de hover deja el puntero sobre el último
nodo que tocó**, y el asa re-apunta su color al acento bajo `:hover` . Con el
puntero aparcado tras esa pasada, el token vive y el guard delató su propia
excepción como STALE.
uix(float-panel): temable — 59 % → 84 %, muere un fantasma y queda una anomalía registrada
12 claves (28 → 40). Censo float-panel 59 % → **84 %** con `global` a CERO.
Cosido: las dos VARIANTES que ajustan desde el default elevado (`outline-*`,
`ghost-*`), los botones de su barra (`action-*`, `hover-action-*`) y el asa de
redimensionado.
MUERE UNO DE LOS NUEVE FANTASMAS DEL BARRIDO de esta mañana: el asa leía
`var(--color-content-tertiary, var(--color-content-secondary))` y ese primitivo
NO EXISTE, así que pintaba el respaldo. El contrato guarda lo que de verdad
pintaba, con lo que la referencia muerta desaparece sin mover un píxel.
ONCE ADJUDICACIONES MEDIDAS: la demo monta la variante por DEFECTO —ni outline ni
ghost— y no tiene botón de acción genérico, sólo el control de cierre; se forzó
el atributo de variante y se montó el botón donde el CSS lo selecciona, y el
radio del asa sólo pinta bajo `:focus-visible`. Las once alcanzan.
Y UNA ANOMALÍA REGISTRADA EN VEZ DE ESCONDIDA: `resize-grip-fg` **mueve** bajo
una réplica a mano de la secuencia del propio guard —congelar transiciones, blur,
aparcar el ratón, escribir en `:root` y en cada nodo con el prefijo, fotografiar
los mismos props con `::before`/`::after`/`::placeholder`— (oklch(0.5032 0 0) →
rgb(1,2,3)), y aun así el guard lo da por muerto. Descartado que el nodo no lleve
el atributo (lo lleva), que la regla necesite un estado (es la regla base), que
sea el valor centinela (es el mismo) y que sea HMR (dos corridas). Queda
adjudicado CON la medición y marcado como anomalía en §13: el token está vivo, lo
que está en duda es la lectura. Es por donde debe empezar la revisión adversarial
de este bloque — el precedente de F2-A dice que estos casos sí tienen causa.
Lo rojo que queda son 12 tokens anteriores, y seis de ellos —`bg`, `border`,
`border-width`, `shadow`, `font-family`, `line-height`— son el mismo conjunto que
en `popover`: el PLANO de profundidad gana sobre el panel (§12.9, pendiente de
firma).
Gates: sonda antes/después **0 diffs en 1.890 valores** (9 nodos × 7 estados) ·
censo --only 84 % · `--names` sin desviadas · component-audit PASS · eidos-lint 0
invalid · suite eidos con el único rojo conocido · rtl:check 0 · docs:check 0 ·
captura mirada (cabecera, botón de cierre y asa de la esquina en su sitio).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
**Lo rojo que queda es ANTERIOR**: 12 tokens del bloque viejo, y seis de ellos
—`bg`, `border` , `border-width` , `shadow` , `font-family` ,
`line-height` — son el mismo conjunto que en `popover` : el PLANO de profundidad
gana sobre el panel (§12.9, pendiente de firma).
Sonda antes/después: **0 diffs en 1.890 valores** (9 nodos × 7 estados).
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
fix(theming): float-panel tenía DOCE rojos sin medir — el guard R-5.4 vuelve a verde
El barrido del centinela sobre TODO el ledger (59 componentes) destapó que
`float-panel` fallaba: 17/40 con doce tokens públicos sin adjudicar. No es
regresión —la bisección de las NUEVE versiones del guard desde `cd6a9f4e3` da
siempre 17/40 con los mismos doce— sino un rojo que su propio commit del 22
dejó escrito («lo rojo que queda son 12 tokens anteriores») y que nadie midió.
Y la frase del handoff «desde el 23 no queda ningún rojo del bloque viejo» era
FALSA: se adjudicaron drawer, metrics y color-picker; éste no. Corregida, con
la lección: un componente cuyo commit dice «lo que queda» NO está cerrado, y la
única forma de saberlo es correr el guard sobre el ledger ENTERO.
LOS DOCE, MEDIDOS UNO A UNO
SEIS son el plano de profundidad, y la predicción del 22 era exacta: el
contenido lleva data-depth=overlay y [data-depth=overlay] declara background,
border, box-shadow, font-family y line-height a la MISMA especificidad (0,1,0)
y más tarde en la cascada. Verificado moviendo los tokens del propio plano
sobre el nodo (superficie, borde, fuente y leading lo repintan) y enumerando
las reglas que casan. border-width cae con border (el plano escribe el
shorthand). Misma adjudicación que tooltip, misma decisión abierta (§12.9).
⚠ Y una corrección a mi propio diagnóstico: primero atribuí la sombra a
[data-topmost] porque el panel de la demo arranca frontal. Falso — quitando el
atributo sigue muerta: es el plano también. Lo que sí depende de topmost es su
compañero shadow-topmost, que SÍ alcanza (→ rgb(4,5,6)) porque su regla es
(0,2,0) y le gana al plano: la prueba de que la causa es la cascada y no un
token roto.
TRES son estados o partes que la demo no monta: active-shadow (forzado
data-dragging → alcanza), resize-size (lo consumen las asas de ESQUINA
se/ne/sw/nw y la demo monta sólo las de borde, e y s) y button-size (lo
consumen [data-float-panel-action] y [data-float-panel-stage-trigger], ninguno
montado — el único control es el cierre, un <Button> compuesto que se
dimensiona solo: el mismo grupo que las tres action-* ya adjudicadas).
UNO es el PUENTE DE PALETA: el contenido lleva data-color, así que
--_float-panel-accent viene del forward THM-2 (--_float-panel-palette-border →
rgb(7,8,9)); sin data-color la clave alcanza (→ rgb(1,2,3)).
DOS son la ley del congelado: transition-duration / -ease no pueden moverse
bajo un guard que congela `transition`. Pasada aparte: 0.12s → 11.5s y
cubic-bezier(0.4,0,0.2,1) → steps(7).
DE PASO, DOS ARREGLOS DE LA MISMA REVISIÓN
- `background.parallax-travel` estaba MAL CLASIFICADO como estructural («el
escenario no tiene scroll timeline»): lo tiene (animation-timeline: view()).
Forzando data-parallax + speed 1, el translate sigue al token (14,6 → 60,5 px
al mismo scrollY). La causa real es que el guard NO fotografía translate ni
transform — registrado en §13 junto al hueco de mask-image, para entrar en
PROPS en un pase con re-verificación del ledger entero.
- `cropper`: el hueco de composición que el README daba por «anotado» y no lo
estaba, ahora es fila de §Gaps con su disposición. Y las tablas de tokens de
`cropper` y `waveform` pasan a la sección «Talla y tema», el molde del resto.
La nueva constante PLANE_SUPERSEDED se iza sobre el objeto (un `const` usado
antes de su declaración reventaba el guard, y el fallo se veía sólo mirando el
exit REAL: tras la tubería, `$?` es el del grep).
Verificación: R-5.4 float-panel 17/40 con 23 adjudicaciones, cero STALE, exit 0
· docs:check 0 · el ledger vuelve a sus 63 hunks de prettier preexistentes (mis
entradas se reformatearon a mano, sin tocar las ajenas).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
---
**ADJUDICADO 2026-08-23 — los DOCE, uno a uno.** Quedaron escritos como «rojo
que queda» el 22 y nadie los midió: el guard R-5.4 **fallaba** en este
componente y el handoff daba por cerrado el bloque viejo. Ninguna regresión —la
bisección de las nueve versiones del guard desde `cd6a9f4e3` da siempre 17/40
con estos mismos doce—, sólo un rojo sin medir. Ahora el guard pasa: **17/40 con
23 adjudicaciones, cero STALE**.
**SEIS son el plano, y la predicción del 22 era exacta.** El contenido lleva
`data-depth='overlay'` , y `[data-depth='overlay']` declara `background` ,
`border` , `box-shadow` , `font-family` y `line-height` a la MISMA especificidad
(0,1,0) y más tarde en la cascada. Verificado moviendo los tokens del propio
plano sobre este nodo (superficie, borde, fuente y leading lo repintan) y
enumerando las reglas que casan: la del plano está ahí, después de la de la
receta. `border-width` cae con `border` porque el plano escribe el shorthand.
Misma adjudicación que `tooltip` , misma decisión abierta.
⚠ **Y una corrección a mi propio diagnóstico** : primero atribuí la sombra a
`[data-topmost]` (el panel de la demo arranca frontal). Falso: quitando el
atributo, `--float-panel-shadow` sigue muerto. Es el plano también. Lo que sí
depende de `topmost` es su compañero ** `shadow-topmost` , que SÍ alcanza**
(→ `rgb(4,5,6)` ) porque su regla es (0,2,0) y le gana al plano — la prueba de
que la cascada es la explicación y no un token roto.
**Tres son estados o partes que la demo no monta**: `active-shadow` (forzado
`data-dragging` → alcanza), `resize-size` (lo consumen las asas de ESQUINA
`se/ne/sw/nw` y la demo monta sólo las de borde, `e` y `s` ) y `button-size`
(lo consumen `[data-float-panel-action]` y `[data-float-panel-stage-trigger]` ,
ninguno montado — el único control es el cierre, que es un `<Button>` compuesto
y se dimensiona solo: el mismo grupo que las tres `action-*` ya adjudicadas).
**Uno es el PUENTE DE PALETA** (§3.pre, no es deuda): el contenido lleva
`data-color` , así que `--_float-panel-accent` viene del forward THM-2
(`--_float-panel-palette-border` → `rgb(7,8,9)` ); quitando `data-color` , la
clave alcanza (→ `rgb(1,2,3)` ). Es la base sin color, no una clave muerta.
**Dos son la ley del congelado**: `transition-duration` / `-ease` no pueden
moverse bajo un guard que congela `transition` para hacer medible todo lo demás.
Pasada aparte sin congelar: `0.12s → 11.5s` y
`cubic-bezier(0.4,0,0.2,1) → steps(7)` .
Sin cambios de código: cero diffs por construcción.
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
<!-- veredicto:end -->