|
|
# PLAN — Theming: que TODO componente sea personalizable por un tema (eje `theme-reach`)
|
|
|
|
|
|
> **Estado (act. 2026-08-21): EN EJECUCIÓN — alcance global 43 %, 15
|
|
|
> componentes con contrato, 49 sin él. Vocabulario CERRADO (codemod + R-5.3 +
|
|
|
> muro de tipos) y bloque F2-A CERRADO. Las D-TH.1…8 de §4 FIRMADAS TODAS el
|
|
|
> 2026-08-20** (más las
|
|
|
> tres decisiones hermanas del mismo día: familia calendar = capa compartida,
|
|
|
> mandato Field ejecutable, hover→capa de estado — ver «Firmas del 2026-08-20»
|
|
|
> del CONTINUE). El registro con cifras y commits está en §8, y el punto
|
|
|
> de entrada diario es [`CONTINUE-theming.md`](./CONTINUE-theming.md). Toda
|
|
|
> decisión NUEVA que surja se sigue presentando una por mensaje, con las
|
|
|
> cinco preguntas.
|
|
|
>
|
|
|
> **Origen (conversación 2026-08-19)**: al arreglar `navigation-menu` salió que
|
|
|
> el radio de su trigger vivía en un privado clavado a `--radius-default` y que
|
|
|
> el contrato del componente sólo publicaba tres knobs: ningún tema podía decir
|
|
|
> «píldora» sin mover el radio del sistema entero. El autor, textual: **«esto
|
|
|
> ha abierto una duda importante, y es si los componentes creados son
|
|
|
> themables; si no lo son, es un error como framework. Necesitaríamos
|
|
|
> desarrollar un plan para auditar todos los componentes, verificar qué grado
|
|
|
> de personalización soportan y desarrollar una corrección a cada uno de ellos
|
|
|
> para que sean totalmente personalizables.»** Y sobre la ejecución: **«lo
|
|
|
> ejecutará Opus, y Opus falla mucho, por lo que tienes que establecer procesos
|
|
|
> de verificación en todo el plan.»** Este documento obedece a las dos frases:
|
|
|
> §1 es la auditoría MEDIDA (reproducible por script, no por memoria), §5 son
|
|
|
> las fases, y §7 es el protocolo de verificación que cada sesión ejecuta sin
|
|
|
> excepción.
|
|
|
>
|
|
|
> **Kickoff para sesión nueva**: _«Lee `docs/process/PLAN-theming.md` ENTERO y
|
|
|
> después `CONTINUE-theming.md`; si las D-TH de §4 están firmadas, ejecuta el
|
|
|
> siguiente bloque de §5 con el protocolo de §7, un componente por commit; si
|
|
|
> no, PARA y preséntalas una a una.»_
|
|
|
>
|
|
|
> Fuentes de doctrina que este plan cita y NO copia:
|
|
|
> [`docs/theming/reference.md`](../theming/reference.md) §1bis, §3, §5, §6,
|
|
|
> §7, §12, §16 · [`docs/canon/tsc.md`](../canon/tsc.md) ·
|
|
|
> [`docs/canon/recipe-contract.md`](../canon/recipe-contract.md) §1–§5 ·
|
|
|
> [`docs/theming/motion.md`](../theming/motion.md) §"When both write
|
|
|
> `animation` on ONE node" · [`docs/guides/component-guide.md`](../guides/component-guide.md)
|
|
|
> §Build contract · [`src/uix/eidos/components/README.md`](../../src/uix/eidos/components/README.md)
|
|
|
> · el precedente ejecutado y firmado: [`PLAN-sidebar.md`](./PLAN-sidebar.md)
|
|
|
> §3 + F3 (el eje `size` de la fila, 2026-08-19) y `navigation-menu`
|
|
|
> (`ae9e277fa` · `a82794845`, el cromo del trigger en tokens públicos).
|
|
|
|
|
|
---
|
|
|
|
|
|
## 0. Veredicto corto
|
|
|
|
|
|
1. **La doctrina ya lo exige; los guards no lo comprueban.** recipe-contract §1:
|
|
|
«Every recipe declares its knobs in `lib/recipes/base.ts`»; theming §6: el
|
|
|
token público de componente es `--{c}-{slot}`; la TSC decide dónde se emite.
|
|
|
Pero R-1…R-4 comprueban que **no haya literales** (y que lo que haya sea un
|
|
|
`var(`), no que cada knob sea **alcanzable por un tema**. Una receta con
|
|
|
todo en `var(--radius-md)` y en privados `--_{c}-*` pasa `component:audit`
|
|
|
en PASS y la dimensión 10 «Adopción theming» de la ficha en ✓ — y sólo se
|
|
|
puede temar moviendo el planeta. Es un error de framework porque rompe la
|
|
|
promesa que el framework hace por escrito.
|
|
|
2. **Medido, no opinado** (§1, `scripts/theming-census.ts`): de 5.205 knobs
|
|
|
de apariencia en 162 recetas, **1.621 (33 %) pasan por un token público del
|
|
|
componente**; 1.880 atan directo a un primitivo global; 856 a privados;
|
|
|
614 son literales. **62 componentes no tienen una sola entrada en el
|
|
|
contrato**; 59 tienen alcance < 20 %; 6 están al 100 %. `navigation-menu`,
|
|
|
tras el trabajo de hoy, está en 44 %: el eje no se cierra arreglando un
|
|
|
componente.
|
|
|
3. **La corrección es mecánica y ya tiene forma firmada**: la de la fila del
|
|
|
`Sidebar` (D-SB.5/D-SB.6, `PLAN-sidebar.md` §3) y la del trigger del nav
|
|
|
(`ae9e277fa`): tokens públicos por talla que apuntan al bundle
|
|
|
`--size-{k}-*`, nombre RESUELTO por `data-size`, acentos de estado en
|
|
|
`background-color`, y **el default queda idéntico** — sólo cambia quién
|
|
|
puede moverlo. Lo que NO hay que hacer: rediseñar nada por el camino.
|
|
|
4. **Sin guard no hay cierre**: el censo de hoy se repetirá en seis meses si
|
|
|
R-5 no existe. F0 crea el guard en `warn` con la cifra de hoy como suelo; F3
|
|
|
lo gradúa a `error` cuando el backfill termina. Igual que hizo R-4.x el
|
|
|
2026-07-02.
|
|
|
|
|
|
---
|
|
|
|
|
|
## 1. Inventario medido (2026-08-19)
|
|
|
|
|
|
**Instrumento**: `node --import tsx/esm scripts/theming-census.ts` (añadido
|
|
|
con este plan; `--json` para máquina; `--only {c}` por componente). Cuenta, por
|
|
|
receta CSS, cada declaración de APARIENCIA (lista `KNOB_PROPS` en el script:
|
|
|
fondo, tinta, borde, radio, sombra, padding, gap, tipografía, tamaño, opacidad,
|
|
|
fill/stroke, filtros) y la clasifica por el ORIGEN de su valor:
|
|
|
|
|
|
| Clase | Qué es | ¿La alcanza un tema de componente? |
|
|
|
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
|
|
|
| `public` | `var(--{c}-…)` — token del contrato del componente | **Sí** |
|
|
|
| `private` | `var(--_{c}-…)` — nombre interno | No (salvo que el privado DERIVE de un público — el script no lo distingue, cuenta como no) |
|
|
|
| `global` | cualquier otro `var(--…)`: `--space-*`, `--radius-*`, `--color-*`, `--font-size-*`, `--size-*`… | Sólo moviendo el sistema |
|
|
|
| `literal` | sin `var(`: `8px`, `1.25`, `#fff` | No, y además viola R-4/R-2 |
|
|
|
| `system` | sistemas transversales que una receta CONSUME: 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)`.
|
|
|
|
|
|
### 1.1 Totales
|
|
|
|
|
|
| Medida | Valor |
|
|
|
| -------------------------------------- | ---------------- |
|
|
|
| Componentes con receta CSS | 162 |
|
|
|
| Knobs de apariencia | 5.205 |
|
|
|
| Por token público del componente | **1.621 (33 %)** |
|
|
|
| Por privado | 856 |
|
|
|
| Directo a primitivo global | 1.880 |
|
|
|
| Literales | 614 |
|
|
|
| Sistema transversal (fuera del ratio) | 234 |
|
|
|
| **Sin ninguna entrada en el contrato** | **62** |
|
|
|
| Alcance < 20 % | 59 |
|
|
|
| Alcance = 100 % | 6 |
|
|
|
| Con eje `data-size` en la receta | 82 |
|
|
|
|
|
|
### 1.2 Por familia (propuesta de familias en D-TH.4 — el autor la firma o la cambia)
|
|
|
|
|
|
| Familia | Comp. | Knobs | Alcance | Sin contrato | Fuera del contrato |
|
|
|
| ----------------------------------- | ----: | ----: | ------: | -----------: | -----------------: |
|
|
|
| Tiempo (chronos · fecha/hora) | 15 | 879 | 9 % | 9 | 774 |
|
|
|
| Campos | 24 | 905 | 38 % | 9 | 526 |
|
|
|
| Controles · marcas | 33 | 867 | 39 % | 9 | 502 |
|
|
|
| Menús · listas · navegación | 24 | 735 | 37 % | 10 | 432 |
|
|
|
| Superficies · overlays · estado | 34 | 807 | 45 % | 10 | 429 |
|
|
|
| WIP (`palabras`) | 1 | 471 | 22 % | 1 | 363 |
|
|
|
| Texto · tipografía | 12 | 238 | 9 % | 10 | 217 |
|
|
|
| Media · chat | 9 | 283 | 61 % | 1 | 104 |
|
|
|
| Layout (primitivos) | 9 | 14 | 93 % | 3 | 1 |
|
|
|
| (`separator`, sin familia asignada) | 1 | 6 | 67 % | 0 | 2 |
|
|
|
|
|
|
### 1.3 Los tres defectos que el censo NO ve y la ejecución sí tiene que mirar
|
|
|
|
|
|
El script es un regex sobre texto: sobre-reporta, nunca infra-reporta. Tres
|
|
|
clases de defecto de theming que un alcance del 100 % no garantiza:
|
|
|
|
|
|
- **Privado que no deriva de un público** (`--_c-radius: var(--radius-default)`):
|
|
|
cuenta como `private`; la corrección es que el privado lea el público o
|
|
|
desaparezca.
|
|
|
- **Velo o acento en el nodo equivocado**: `archetype: 'item'` en un `<li>`
|
|
|
envoltorio (`navigation-menu`, `822b78cf2`), o el shorthand `background`
|
|
|
matando la capa de estado (`Sidebar` F3, `navigation-menu` `ae9e277fa`). No
|
|
|
es un knob: es un nodo. Se detecta midiendo desde el píxel hacia arriba (§7.3).
|
|
|
- **Doble animación al mover un sello** a una superficie con animación propia
|
|
|
(`navigation-menu` `822b78cf2`: `present-rise` + la entrada de receta). Se
|
|
|
detecta con un registro de `animationstart/end`, no con `getComputedStyle`.
|
|
|
|
|
|
### 1.4 Tabla completa por componente
|
|
|
|
|
|
Al final del documento (§9), ordenada por alcance. Se REGENERA con el script
|
|
|
en cada bloque; no se edita a mano.
|
|
|
|
|
|
---
|
|
|
|
|
|
## 2. Contrato objetivo — qué significa «totalmente personalizable» (los cuatro ejes)
|
|
|
|
|
|
Un componente es personalizable cuando un tema puede moverlo **sin tocar el
|
|
|
sistema ni la receta**, en estos ejes:
|
|
|
|
|
|
| Eje | Mecanismo canónico | Cómo se comprueba |
|
|
|
| -------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
|
|
|
| **A · Tokens** (forma, color, espacio, tipografía) | todo knob de apariencia lee `--{c}-{slot}` del contrato (`recipes/base.ts`), nombre RESUELTO por talla/estado; los privados sólo derivan de públicos | censo al 100 % **+** prueba de centinela (§7.4) |
|
|
|
| **B · Talla** | `size` → `data-size` en el wrapper; tokens `{part}-{eje}-{k}` apuntando al bundle `--size-{k}-*` (theming §5; recipe-contract §1) | computed por talla = bundle; `md` idéntico al default anterior |
|
|
|
| **C · Color / variante** | `data-color` / `data-variant` vía paleta (`--{c}-{role}-{slot}`, `--{c}-palette-*`), los 9 roles (theming §4) | cada variante lee tokens, ninguna un `--scale-*` (R-4.6) |
|
|
|
| **D · Estados** | hover/press/selected neutros = la capa del sistema en el nodo CON forma; acentos de estado (`on-bg`…) en `background-color` para que la capa componga | `background-image` presente en hover, `<li>`/envoltorios sin velo, abierto + hover = acento + capa |
|
|
|
|
|
|
**Regla de oro del eje**: **el default no cambia.** Cada componente se mide
|
|
|
antes y después en sus estados (reposo · hover · activo/abierto · disabled ·
|
|
|
foco) y tallas, y el diff de computed styles es **cero** salvo donde una
|
|
|
decisión firmada diga lo contrario. Este eje mueve QUIÉN puede cambiar cada
|
|
|
cosa, no QUÉ se ve.
|
|
|
|
|
|
---
|
|
|
|
|
|
## 3. Contrato objetivo — la regla R-5 «alcance de tema»
|
|
|
|
|
|
Nueva regla de `component-audit` (familia R-5), misma mecánica que R-4.x:
|
|
|
|
|
|
- **R-5.1** — Toda declaración de apariencia (`KNOB_PROPS`) en una receta lee
|
|
|
(a) un público `var(--{c}-…)`, (b) un privado `--_{c}-*` cuya definición en
|
|
|
la misma receta lee un público, o (c) un token de sistema transversal (la
|
|
|
lista `SYSTEM` del censo). Otra cosa es fallo.
|
|
|
- **R-5.2** — Todo componente con receta tiene entrada en `recipes/base.ts`.
|
|
|
- **R-5.3** — Los nombres de los tokens siguen recipe-contract §1 (ejes
|
|
|
lógicos, `{part}-{eje}-{k}`) y theming §6 regla 7 (slots de color: `bg, fg,
|
|
|
border, on-bg, on-fg, on-border, hover-bg, on-hover-bg`). **Hoy no se
|
|
|
cumple** ni en recetas viejas (`tabs`: `trigger-color-*`) ni en las de hoy
|
|
|
(`navigation-menu`: `trigger-bg-active`, `trigger-color-active`) — ver
|
|
|
D-TH.6.
|
|
|
- **Válvula** (recipe-contract §3): `R-5.1 exception: <razón>` en el README
|
|
|
del componente, greppable, UNA por knob o grupo de knobs con la razón (p. ej.
|
|
|
«glifo ∝ diámetro, excepción canónica avatar/marker»). Sin razón escrita no
|
|
|
hay excepción.
|
|
|
- **Severidad**: `warn` desde F0 con el suelo del censo; `error` en F3 (D-TH.7
|
|
|
— firmada con enmienda: **R-5.3 gradúa a `error` directo tras el codemod**,
|
|
|
su deuda muere en el mismo pass; R-5.1/5.2 esperan F3).
|
|
|
|
|
|
---
|
|
|
|
|
|
## 4. Decisiones que firma el autor (una por mensaje, con sus cinco preguntas)
|
|
|
|
|
|
| Id | Decisión | Propuesta | Estado |
|
|
|
| ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
|
| **D-TH.1** | ¿R-5 es regla DURA? («todo knob público salvo sistema transversal o excepción firmada») | Sí. Es lo que recipe-contract §1 ya dice sin guard. | **FIRMADA 2026-08-20** tal cual. Ancla: la medición 2026-07-01 (canon sin guard deriva 30-85 %) y el mandato origen del eje. |
|
|
|
| **D-TH.2** | Perímetro de «knob» | La lista `KNOB_PROPS` del script (apariencia; layout fuera). Cambios a la lista = cambio del guard, firmados aquí. | **FIRMADA 2026-08-20** con la opción (b) de la ficha `heading`: la familia tipográfica B5 mide su superficie por `--style-*` como sistema transversal (verdad estructural — la vertebración tipográfica RECHAZA acoplar componentes a la capa semántica; acuñar `--heading-*` = 36 alias de una capa ya pública, la clase que §39 mató). No se acuñan `--{c}-*` para los primitivos tipográficos. |
|
|
|
| **D-TH.3** | Tracks WIP (`palabras`, `words`, `chronos` y su familia de fecha/hora) | En el CENSO siempre; en R-5 `error` sólo cuando salgan de su carril (coherente con R-4.x, que los excluye). | **FIRMADA 2026-08-20** tal cual. |
|
|
|
| **D-TH.4** | Familias y ORDEN del backfill | El de §5 F2: menús/navegación → campos → controles → superficies → texto → media/chat → tiempo (el último por ser el más grande y estar en carril propio). Dentro de cada familia, sin contrato primero, luego por knobs fuera del contrato. | **FIRMADA 2026-08-20** con enmienda: la cola REVISADA del CONTINUE (fichas con veredicto §5 verificado) tiene prioridad sobre el orden de familias — trabajo revisado no se deja enfriar. |
|
|
|
| **D-TH.5** | El default NO cambia en este eje | Sí. Toda mejora visual que aparezca se anota como deuda y se firma aparte (como hoy con `navigation-menu`). | **FIRMADA 2026-08-20** sin matices — es lo que hace verificable el eje (diff de computed = 0 como gate). Única excepción viva: la migración hover→capa de estado, firmada aparte el mismo día (ver «Firmas del 2026-08-20» del CONTINUE), que mueve píxel con captura y diff explicado. |
|
|
|
| **D-TH.6** | Vocabulario de slots (R-5.3): ¿se NORMALIZAN los nombres que ya se desvían (`trigger-color-*` de `tabs`, `*-bg-active`/`*-color-active` del nav de hoy, …) con un codemod value-preserving como el de px/py del 2026-07-06? | Sí, en F1, ANTES del backfill — si no, el backfill escribirá más nombres fuera de vocabulario. Inventario exacto de desviaciones sale en F0 (el censo añade `--names`). | **FIRMADA COMPLETA 2026-08-20**, en dos actos. (1) El slot de tinta es **`fg`**; `color` como slot MUERE (196 claves cola). Razón: el principio de plataforma del 2026-07-06 gobierna los ejes DIMENSIONALES, no la pareja `bg`/`fg` (si gobernara, `bg` sería `background-color`); `color` colisiona con `--color-*`, `data-color` y los 9 roles; `on-fg` compone. (2) Modificador recipe-level DELANTE — regla: **delante lo interactivo, detrás lo dimensional y contextual** (`hover-bg` pero `control-height-md`, `scrim-fg-over-dark`); rol/paleta conserva su gramática propia (detrás, `COLOR_ROLE_SLOTS` — las 47 `{rol}-{slot-de-rol}` son canónicas). Modificador válido ∈ vocabulario universal (+`current`, aria) ∪ valores `data-state`/ejes del MORFO del componente (así `partial` de rating-group y `read/failed` de chat-message validan contra el compilado, igual que la parte). `waveform.played/buffered` = pseudo-partes eidos-only (`played-fg`). Los hovers neutros se EXCLUYEN del codemod: migran a la capa de estado (firma aparte, mismo día). Detalle operativo: CONTINUE §«Mañana». |
|
|
|
| **D-TH.7** | Cuándo gradúa R-5 a `error` | Cuando el censo global dé 100 % o excepción documentada (F3), nunca antes de terminar F2 — un `error` a medio backfill rompe el `component:audit` de todo el parque. | **FIRMADA 2026-08-20** con enmienda: **R-5.3 (gramática de nombres) gradúa a `error` DIRECTO tras el codemod** — su deuda muere en el mismo pass (precedente R-4.4, «sin allowlist»). R-5.1/R-5.2 esperan F3 como propone la fila. |
|
|
|
| **D-TH.8** | ¿Entra la exposición en la demo de temas (`/temas`: un panel que liste los tokens públicos por componente y permita moverlos)? | Sí pero DESPUÉS (F4, opcional): es la prueba viva de A; sin el backfill no hay nada que exponer. | **FIRMADA 2026-08-20** tal cual — el instrumental existe (`listRecipes()` / `getRecipeTokens()`; la ruta `/temas` existe). |
|
|
|
|
|
|
---
|
|
|
|
|
|
## 5. Fases y gates
|
|
|
|
|
|
Cada fase: **qué leer ANTES** (entero), **qué producir**, **guard**. Ninguna
|
|
|
arranca sin la anterior en verde. Todo bloque de F2 ejecuta el protocolo de §7
|
|
|
**por componente**, sin atajos: es la parte del plan que existe porque «Opus
|
|
|
falla mucho».
|
|
|
|
|
|
### F0 — Instrumento + guard en `warn` (una sesión)
|
|
|
|
|
|
- Leer: theming §1bis, §3, §5, §6, §7, §12, §16 · tsc.md entero ·
|
|
|
recipe-contract §1–§5 · `scripts/component-audit.ts` (cómo se declara una
|
|
|
regla R-x, `readmeException`, severidades) · `src/uix/eidos/recipe-css-contract.test.ts`
|
|
|
(qué ya guarda) · `PLAN-sidebar.md` §3 y F3 · este plan entero.
|
|
|
- Producir: (a) `scripts/theming-census.ts` endurecido: `--names` (inventario
|
|
|
de nombres de token fuera del vocabulario §1/§6.7), detección «privado que
|
|
|
deriva de público» (leer `--_c-x: var(--c-y)` en la misma receta y
|
|
|
reclasificar), salida `--json` estable; (b) **R-5.1/5.2/5.3 en
|
|
|
`component-audit`** con severidad `warn` y la válvula `R-5.x exception:`;
|
|
|
(c) `docs/theming/reference.md` §12 (tabla de tooling) gana la fila del censo;
|
|
|
(d) **HECHO 2026-08-22** — `src/uix/eidos/theming-reach-floor.test.ts`, que
|
|
|
**fija el suelo**: alcance global ≥ el de hoy (33 %) y literales ≤ 614 — el
|
|
|
número SUBE o el test falla (muta-prueba: meter un literal en una receta y ver
|
|
|
el rojo antes de dar el test por bueno — memoria `a-guard-that-inspects-nothing-passes`.
|
|
|
Ya pasó una vez HOY: la primera versión del censo no contaba una regla de una
|
|
|
sola línea, y la mutación `padding-inline: 8px` no movió la cifra; se endureció
|
|
|
el regex y la mutación pasó a 6→7→8).
|
|
|
- Guard: `node --import tsx/esm scripts/theming-census.ts` reproduce §1.1 a
|
|
|
la cifra · `npm run component:audit` NO añade ningún `error` (sólo `warn`) ·
|
|
|
`npx vitest run src/uix/eidos` sin nuevos rojos (el rojo conocido es
|
|
|
`skin-media-player`, ajeno) · `npm run check` con cero errores en los
|
|
|
ficheros tocados (§7.6).
|
|
|
|
|
|
### F1 — Doctrina + vocabulario (una sesión)
|
|
|
|
|
|
- Leer: F0 + theming §6 (reglas estrictas) + el codemod del 2026-07-06
|
|
|
(recipe-contract §1, bloque «Normalización ejecutada») como molde.
|
|
|
- Producir: recipe-contract §1 gana la regla R-5 (y §2 una fila «Alcance de
|
|
|
tema»), §4 la tabla de enforcement, §5 el checklist (punto 12: «censo del
|
|
|
componente al 100 % o excepción»); theming §6 referencia cruzada; el
|
|
|
checklist de cierre (`docs/guides/completion-checklist.md`) y el
|
|
|
`COMPONENT_AUDIT_GUIDE` endurecen las dimensiones 5 y 10 («usa tokens» ≠
|
|
|
«es temable»: la ficha exige el % del censo). **D-TH.6**: codemod
|
|
|
value-preserving de los nombres fuera de vocabulario (lista de F0), con
|
|
|
`generated/base.css` regenerado y diff = renombres 1:1, computed idéntico en
|
|
|
navegador (mismo triple muro que px/py).
|
|
|
- Guard: `docs:check` 0 · el diff de `generated/base.css` son SOLO renombres ·
|
|
|
censo idéntico antes/después del codemod (un rename no cambia el alcance) ·
|
|
|
sonda de computed en 3 componentes renombrados = idéntico.
|
|
|
- **Repaso de lo ya ejecutado (2026-08-20)**: firmar una gramática obliga a
|
|
|
releer lo corregido ANTES de ella. Auditados los 7 de §8 contra `fg` +
|
|
|
familias (`scripts/__names-audit7.ts`): 6 limpios, y una sola corrección —
|
|
|
`gradient-builder.checker-color` → `checker-fg` (slot, no sustantivo; 4
|
|
|
consumos en `gradient-builder.css`). Las 4 claves `stop-color-*` del mismo
|
|
|
componente son falso amigo verificado (`stop-color` es la PARTE) y NO se
|
|
|
tocan. La corrección entra DENTRO del codemod. Detalle y tabla:
|
|
|
[`CONTINUE-theming.md`](./CONTINUE-theming.md) §«Primera posición».
|
|
|
|
|
|
### F2 — Backfill por familias (6–8 bloques de sesión; **un componente = un commit**)
|
|
|
|
|
|
Orden propuesto (D-TH.4). Dentro de cada bloque: sin contrato primero, luego
|
|
|
por knobs fuera del contrato. Cada componente sigue §7 entero.
|
|
|
|
|
|
| Bloque | Familia | Comp. | Knobs fuera | Entran primero (sin contrato) |
|
|
|
| ------ | ----------------------------------------------------- | ----: | ----------: | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
|
| B1 | Menús · listas · navegación | 24 | 432 | `command`, `listbox`, `table`, `tree-grid`, `tree-view`, `grid-list`, `virtual-list`, `virtual-grid`, `menu-dial`, `feed` — y `navigation-menu` (44 %) hasta el 100 % |
|
|
|
| B2 | Campos | 24 | 526 | `combobox` (1), `textarea`, `css-field`, `mask-field`, `number-field`, `field-langs`, `gradient-builder`, `gradient-picker`, `label` |
|
|
|
| B3 | Controles · marcas | 33 | 502 | `knob`, `avatar`, `kbd`, `link`, `mark`, `highlight`, `clipboard`, `proof-of-human`, `aspect-ratio` |
|
|
|
| B4 | Superficies · overlays · estado | 34 | 429 | `alert-dialog`, `announce`, `carousel`, `link-preview`, `skeleton`, `spinner`, `scroll-frames`, `motion`, `mockup`, `cascade`, `card-group` |
|
|
|
| B5 | Texto · tipografía | 12 | 217 | `heading`, `text`, `s-text`, `display`, `code`, `code-block`, `text-*` (los que no tienen contrato) |
|
|
|
| B6 | Media · chat | 9 | 104 | `skin-media-player` |
|
|
|
| B7 | Tiempo (chronos · fecha/hora) — **si D-TH.3 lo mete** | 15 | 774 | `range-calendar`, `month-grid`, `year-grid`, `date-picker`, `date-range-picker`, `time-picker`, `time-range-picker`, `natural-time-picker`, `picker-shell` |
|
|
|
| B8 | `palabras` — **si D-TH.3 lo mete** | 1 | 363 | — |
|
|
|
|
|
|
Por componente se produce: entrada (o ampliación) en `recipes/base.ts` con los
|
|
|
nombres de §1/§6.7 — dimensionales por talla si el componente tiene `size`
|
|
|
(patrón `Sidebar`: `{part}-{eje}-{k}` + nombre resuelto con `declarations` por
|
|
|
`scope: 'size:{k}'`), colores por rol/slot, acentos de estado; la receta
|
|
|
consume SOLO nombres resueltos (nunca un primitivo crudo, nunca un literal);
|
|
|
privados sólo si derivan de públicos; `generated/base.css` regenerado por el
|
|
|
script (**jamás a mano**, theming §16 F); README de eidos con la tabla de
|
|
|
tokens («Talla y tema», molde: `navigation-menu`); registro en §8.
|
|
|
|
|
|
- Guard por componente: §7 entero, y el censo `--only {c}` al **100 %** (o
|
|
|
`R-5.x exception:` con razón) — si no llega, el commit NO se hace.
|
|
|
- Guard por bloque: **revisión adversarial** (§7.7) antes de dar el bloque por
|
|
|
cerrado: un pase escéptico por componente que intente REFUTAR «el default es
|
|
|
idéntico» y «cada token alcanza» con medición propia, no con la del autor
|
|
|
del commit.
|
|
|
|
|
|
### F3 — R-5 a `error` + cierre (una sesión)
|
|
|
|
|
|
- Producir: severidad `error` en R-5.1/5.2/5.3 (D-TH.7); el test del suelo
|
|
|
pasa a exigir 100 % global (o excepciones listadas); theming §12 y
|
|
|
recipe-contract §4 lo reflejan; `CONTINUE-theming.md` cerrado.
|
|
|
- Guard: `component:audit` PASS en los 162 · censo 100 % · `docs:check` 0.
|
|
|
|
|
|
### F4 — Exposición en la demo de temas (opcional, D-TH.8)
|
|
|
|
|
|
- Producir: en `/temas` (o en cada demo) un panel que lista los públicos del
|
|
|
componente desde `recipes/base.ts` y los mueve en vivo — la prueba viva del
|
|
|
eje A, y el detector de tokens que no alcanzan (mover y que nada cambie).
|
|
|
- Guard: mover cada token del componente en la demo y ver cambiar el computed
|
|
|
(automatizable con el centinela de §7.4).
|
|
|
|
|
|
---
|
|
|
|
|
|
## 6. Deuda transversal que este plan destapa — NO se ejecuta aquí
|
|
|
|
|
|
| Id | Dónde | Qué |
|
|
|
| ---------- | ----------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
|
| **T-TH.1** | `component-audit` dims 5 y 10 | Dan ✓ a «usa tokens»; el criterio se endurece en F1. Las fichas ya escritas (`docs/audit/components/*.md`) quedan con el ✓ viejo: se corrigen al pasar cada componente por F2, no en masa. |
|
|
|
| **T-TH.2** | Vocabulario de slots (theming §6.7) | Existe y no se guarda: `tabs` (`trigger-color-*`), `navigation-menu` (`-bg-active`, `-color-active`) y más lo incumplen. D-TH.6. |
|
|
|
| **T-TH.3** | `menubar` | Misma clase que el nav: cromo de barra en privados («the bar itself styles via foundation privates», `recipes/base.ts`) + `commit-select` en el trigger al DESPLEGAR (otra sesión, sema). |
|
|
|
| **T-TH.4** | `archetype: 'item'` en envoltorios | Hay que censar qué otras partes `<li>`/wrapper lo declaran (memoria `archetype-item-pulls-interactive-styling`: Timeline, Breadcrumb, NavigationMenu ya corregidos). Un guard de morfo («un `item` no envuelve a un `trigger`») es candidato. |
|
|
|
| **T-TH.5** | `--control-height-*` en `:root` (T-6 del sidebar) | La densidad/zoom por SUBÁRBOL no re-deriva; afecta a la promesa de theming «por ámbito». Eje de theming aparte. |
|
|
|
| **T-TH.6** | 25 knobs visuales fuera del morfo (`component-visual-attrs`, eje Affix) | Filas sin firmar `image/skeleton/qr-code/s-text`. El eje C (variantes) depende de ellas. |
|
|
|
|
|
|
---
|
|
|
|
|
|
## 7. PROTOCOLO DE VERIFICACIÓN — por componente, sin excepciones
|
|
|
|
|
|
Existe porque el que ejecuta falla, y porque en un solo día (2026-08-19,
|
|
|
`navigation-menu`) cuatro de estos pasos ausentes costaron cuatro commits de
|
|
|
corrección: se dio por arreglado un hover leyendo el nodo equivocado; se
|
|
|
resolvió un doble de animación en la dirección contraria a la doctrina; se
|
|
|
inventó un hover por componente; y se declaró «idéntico» sin captura. Cada paso
|
|
|
tiene un **artefacto** (número, captura, salida de comando) que va al mensaje
|
|
|
de commit. Sin artefacto, el paso no se ha hecho.
|
|
|
|
|
|
### 7.1 Antes de tocar el componente (las cinco preguntas + lectura)
|
|
|
|
|
|
1. Las cinco preguntas del autor, UN componente por mensaje cuando haya
|
|
|
decisión (nombres fuera de vocabulario, una excepción, un default que
|
|
|
parece defecto): qué soluciona · leído todo o presupuesto · qué afecta ·
|
|
|
qué doctrina · qué modificaciones. Si no hay decisión nueva (el componente
|
|
|
sólo necesita tokens con nombres canónicos), se ejecuta sin preguntar y se
|
|
|
reporta.
|
|
|
2. Leer ENTEROS: la receta del componente, su entrada en `recipes/base.ts`,
|
|
|
su README de eidos y de soma, su morfo (¿qué partes llevan arquetipo?), su
|
|
|
ficha en `docs/audit/components/`. Y la doctrina de §0 (fuentes) si la
|
|
|
sesión no la ha leído hoy.
|
|
|
3. `git status` + `git log -1`: ¿hay otra sesión con el árbol sucio?
|
|
|
**Nunca `git stash`** para medir una base (le arranca el trabajo a otro).
|
|
|
|
|
|
### 7.2 Medir ANTES (el suelo del «idéntico»)
|
|
|
|
|
|
4. `node --import tsx/esm scripts/theming-census.ts --only {c}` → guardar la
|
|
|
línea.
|
|
|
5. Sonda Playwright **headless desde la raíz del repo** (la pantalla oculta
|
|
|
congela rAF; `playwright` no resuelve desde el scratchpad) contra la demo
|
|
|
del componente: para cada parte visible y cada talla, computed de los
|
|
|
knobs (`backgroundColor`, `backgroundImage`, `color`, `borderRadius`,
|
|
|
`padding*`, `fontSize`, `lineHeight`, `blockSize`/`inlineSize`,
|
|
|
`boxShadow`, `borderColor`) en reposo · hover · activo/abierto ·
|
|
|
disabled · `:focus-visible`. Muestrear FUERA de callbacks de
|
|
|
`MutationObserver` (miden el instante anterior al flush). Guardar JSON.
|
|
|
6. Captura 2× de la demo en reposo y en hover (sirve de «antes» para la
|
|
|
comparación a ojo).
|
|
|
|
|
|
### 7.3 Editar (la forma firmada — nada más)
|
|
|
|
|
|
7. Tokens con los nombres de recipe-contract §1 / theming §6.7. Por talla si
|
|
|
hay `size`. Acentos de estado en `background-color`. Hover/press/selected
|
|
|
neutros = la capa del sistema (nunca `background:` a mano, nunca
|
|
|
`background-image: none` para «limpiar», nunca una escalera de color
|
|
|
propia). Privados sólo derivando de públicos. Literales: cero.
|
|
|
8. `npm run generate:eidos-css` y `git diff --stat src/uix/eidos/generated/`:
|
|
|
el diff son SOLO los tokens del componente. Si toca otra cosa, parar.
|
|
|
9. Si un envoltorio lleva `archetype: 'item'`/`'option'`/`'trigger'` sin ser
|
|
|
el interactivo, es una DECISIÓN (morfo): se presenta, no se toca de oficio.
|
|
|
|
|
|
### 7.4 Medir DESPUÉS (los tres artefactos)
|
|
|
|
|
|
10. **Idéntico**: repetir la sonda de 7.2 → diff de computed por parte/estado/talla
|
|
|
= **vacío**. Un solo valor distinto = parar y explicar (o es defecto
|
|
|
previo que se firma, o es error del commit).
|
|
|
11. **Alcanza**: la **prueba de centinela**, que desde 2026-08-21 es el guard
|
|
|
**R-5.4** (`npm run theming:sentinel -- {c} <url>`, doctrina en
|
|
|
recipe-contract §4) — por cada token público, un valor imposible de
|
|
|
confundir (`1234px`, `rgb(1, 2, 3)`, `0.123`) y algún computed tiene que
|
|
|
seguirlo. Si un token no mueve nada, es un token que miente (fantasma,
|
|
|
nombre equivocado, o una cascada que jamás gana) — o su silencio tiene una
|
|
|
razón MEDIDA escrita en el ledger
|
|
|
(`scripts/theming-sentinel-exceptions.ts`): el guard falla con un muerto
|
|
|
sin adjudicar y avisa de excepciones STALE.
|
|
|
12. **Desde el píxel hacia arriba** en los estados de hover: `elementsFromPoint`
|
|
|
en el centro del control y la pila de ancestros con `backgroundImage` /
|
|
|
`backgroundColor` — el velo cae en el nodo CON forma y en ningún
|
|
|
envoltorio (memoria `measure-the-node-the-user-points-at`). Si hay
|
|
|
animación propia y un sello de sema en el mismo nodo, registro de
|
|
|
`animationstart/end` (no `getAnimations` en un solo instante): UNA
|
|
|
entrada por ocurrencia (memoria motion.md §"when both write `animation`").
|
|
|
13. Captura 2× después, al lado de la de antes. Mirarla.
|
|
|
|
|
|
### 7.5 Guards mecánicos (todos, cada componente)
|
|
|
|
|
|
14. `node --import tsx/esm scripts/theming-census.ts --only {c}` → **100 %** o
|
|
|
excepción escrita. Y el global NO baja.
|
|
|
15. `node --import tsx/esm scripts/component-audit.ts --only {c}` → PASS, sin
|
|
|
R-5 nuevos (en `warn` durante F2, pero se listan y se resuelven).
|
|
|
16. `node --import tsx/esm scripts/eidos-lint.ts {c}` → 0 invalid.
|
|
|
17. `npx vitest run src/uix/eidos` → sin rojos nuevos (comparar **por
|
|
|
fichero de test**, no por cifra: el rojo conocido es `skin-media-player`).
|
|
|
18. `npm run rtl:check` 0 · `npm run docs:check` 0 · `npx prettier --check`
|
|
|
en los ficheros tocados (ojo: `autocrlf=true` hace que prettier se queje
|
|
|
del CRLF del checkout — comprobar el contenido normalizado a LF, no el
|
|
|
fichero; git guarda LF).
|
|
|
19. `npm run check`: atribuir errores **por fichero** (`grep ERROR | grep {c}`),
|
|
|
nunca por cifra global; la rama tiene sesiones concurrentes y el total
|
|
|
se mueve solo. Si el log no llega a `COMPLETED`, es `tmp/lexical/`:
|
|
|
relanzar.
|
|
|
|
|
|
### 7.6 Commit (uno por componente)
|
|
|
|
|
|
20. `git add` con rutas EXPLÍCITAS (sólo lo del componente + `recipes/base.ts`
|
|
|
- `generated/base.css` + su README + este plan §8); `git diff --cached --stat`
|
|
|
y `git show :ruta` para verificar el ÁRBOL INDEXADO, no el de trabajo;
|
|
|
`git status` para ver que no entra nada de otra sesión. Mensaje con
|
|
|
`git commit -F fichero` (backticks en `-m` se ejecutan en bash), en
|
|
|
castellano, con: qué knobs entran, la cifra del censo antes → después,
|
|
|
el diff de computed (vacío), el centinela (n tokens probados), los
|
|
|
guards. **Nunca `--amend`** en la rama compartida.
|
|
|
21. Registro en §8 de este plan (componente · commit · censo antes→después ·
|
|
|
excepciones) y, si el bloque cierra, en `CONTINUE-theming.md`.
|
|
|
|
|
|
### 7.7 Revisión adversarial por bloque
|
|
|
|
|
|
22. Al cerrar un bloque, una pasada escéptica (otra sesión o un pase separado)
|
|
|
que por componente intente REFUTAR con medición propia: «el default es
|
|
|
idéntico» (sonda 7.2 vs 7.4 rehecha, no leída del commit), «cada token
|
|
|
alcanza» (centinela rehecho), «el velo cae donde debe» (píxel arriba),
|
|
|
«no hay doble animación». Hallazgos reales se arreglan en el bloque; los
|
|
|
refutados se anotan. El molde es la revisión del `Sidebar` (21
|
|
|
hallazgos · 17 refutados · 4 reales, `bae03e55c`).
|
|
|
|
|
|
### 7.8 Lo que NO se hace en este eje (y se anota como deuda si aparece)
|
|
|
|
|
|
- Rediseñar un default (radio, color, altura…): deuda firmable, no cambio.
|
|
|
- Tocar sema/morfo salvo un arquetipo en un envoltorio (decisión aparte).
|
|
|
- Cascadear a otro componente «ya que estamos» (memoria `no-cascade-changes`).
|
|
|
- Inventar nombres de token fuera de §1/§6.7, o un hover/estado por componente.
|
|
|
- Editar `generated/base.css` a mano.
|
|
|
- Dar un paso por hecho sin su artefacto.
|
|
|
|
|
|
---
|
|
|
|
|
|
## 8. Registro
|
|
|
|
|
|
- 2026-08-22 — **REVISIÓN ADVERSARIAL DEL BLOQUE (§7.7): 5 hipótesis, 1
|
|
|
hallazgo real, 4 refutadas.** Bloque de CATORCE componentes; global 56 % →
|
|
|
**62 %**.
|
|
|
|
|
|
**HALLAZGO REAL — la anomalía de `float-panel` tenía causa, y era del guard.**
|
|
|
`resize-grip-fg` movía aislado y leía muerto en una corrida completa. La
|
|
|
causa: **la pasada de HOVER deja el puntero sobre el último nodo que tocó**, y
|
|
|
una regla `:hover` gana a la de reposo con la que comparte nodo (el asa
|
|
|
re-apunta su color al acento). Es decir: **cualquier token de reposo probado
|
|
|
después de un token `hover-*` podía leer muerto** — misma clase que el
|
|
|
envenenamiento por clic-foco que F2-A arregló, una pasada más tarde.
|
|
|
Arreglado aparcando el puntero tras la pasada de hover. El propio guard
|
|
|
delató entonces DOS excepciones STALE —`float-panel.resize-grip-fg` y
|
|
|
`media-player.track`—, retiradas: dos tokens que se daban por muertos están
|
|
|
vivos. Se confirma la regla de F2-A: **un falso negativo siempre tiene causa**;
|
|
|
registrarlo como «sin causa» era el paso previo, no el final.
|
|
|
|
|
|
**REFUTADA «hay tokens huérfanos»**: comprobación ESTRICTA (comentarios
|
|
|
despojados —el hueco que dejó vivo el `popover.bg`— sobre todo el CSS del
|
|
|
árbol) de las **553 claves** de los catorce bloques: ninguna declarada sin que
|
|
|
una regla la lea.
|
|
|
|
|
|
**REFUTADA «el cambio de instrumento rompió algo»**: los **27 componentes con
|
|
|
ledger re-verificados** tras aparcar el puntero — cero regresiones. Los tres
|
|
|
rojos que quedan (`drawer` 24, `metrics` 16, `color-picker` 23) son
|
|
|
ANTERIORES al bloque y están anotados.
|
|
|
|
|
|
**REFUTADA «quedan fantasmas del barrido en lo tocado»**: el barrido pasa de
|
|
|
9 a **8** — el `--color-content-tertiary` de float-panel murió con su costura.
|
|
|
Los ocho restantes son de componentes que este bloque no tocó.
|
|
|
|
|
|
**CONFIRMADO, y ya estaba escrito: hay gates FINOS.** `popover` mide 1 nodo en
|
|
|
reposo (7 en abierto), `drawer` 1, `context-menu` 1 + 14 en abierto,
|
|
|
`color-picker` 5 + 12. Cada veredicto lo dice; el forzado a mano de sus
|
|
|
estados es lo que sostiene esas cifras, no la sonda.
|
|
|
|
|
|
- 2026-08-22 — **`password-field` 41 % → 62 %** (7 claves) **y el guard en
|
|
|
VERDE**: sus siete silencios quedan medidos, incluidos los tres que arrastraba
|
|
|
de antes.
|
|
|
|
|
|
Los cuatro peldaños del medidor de fuerza son una ESCALA DE INTENCIÓN —cada
|
|
|
uno lee su rol: pérdida, riesgo, cumplimiento, afirmación—, así que un tema
|
|
|
puede recorrerla entera sin tocar los roles del sistema. Fuera, por
|
|
|
composición: el padding del medidor y el tamaño de su rótulo leen privados de
|
|
|
FIELD (§5.3-3, se teman en la ficha del dueño).
|
|
|
|
|
|
Gates: sonda 0 diffs en 3.060 valores · censo 62 % · audit PASS · lint 0 ·
|
|
|
suite con el rojo conocido · rtl 0 · docs 0 · captura mirada.
|
|
|
|
|
|
- 2026-08-22 — **`context-menu` 53 % → 90 %** (11 claves, `global` a cero), y
|
|
|
**el instrumento aprende a abrir un menú contextual**: se abre con clic
|
|
|
DERECHO y con nada más, así que sonda y guard medían UN nodo. Con
|
|
|
`openBy: 'contextmenu'` y el clic derecho en la sonda: 14 nodos en abierto y
|
|
|
el guard en **27/29**.
|
|
|
|
|
|
Dos limpiezas: el `font-family` era respaldo de sí mismo y el peso del
|
|
|
encabezado llevaba un `500` muerto. Dos adjudicaciones, y una es la TERCERA
|
|
|
ocurrencia de §12.9 (el plano `overlay` impone la tipografía del panel).
|
|
|
|
|
|
Gates: sonda 0 diffs en 600 valores · censo 90 % · audit PASS · lint 0 · suite
|
|
|
con el rojo conocido · rtl 0 · docs 0 · captura del panel mirada.
|
|
|
|
|
|
- 2026-08-22 — **`metrics` 74 % → 82 %** (4 claves + prefijo abreviado fuera,
|
|
|
`global` a cero). **`--_mi-*` violaba theming §6 r5** —segundo caso del día
|
|
|
tras `--cp-*`—: 16 ocurrencias renombradas a `--_metrics-icon-*`. Son el
|
|
|
conmutador del icono por variante y ya derivaban de públicos, así que el censo
|
|
|
los reclasifica solo. Cosido: el ritmo del trend y las TRES formas del icono
|
|
|
(una clave por valor de `data-shape`; el radio es lo único que las distingue).
|
|
|
Dos adjudicaciones forzando las formas que la demo no monta. Sonda 0 diffs en
|
|
|
1.590 valores · censo 82 % · audit PASS · lint 0 · captura mirada.
|
|
|
|
|
|
- 2026-08-22 — **`float-panel` 59 % → 84 %** (12 claves, `global` a cero).
|
|
|
|
|
|
Las dos variantes que ajustan desde el default elevado, los botones de la
|
|
|
barra y el asa. **Muere uno de los nueve fantasmas del barrido**: el asa leía
|
|
|
`var(--color-content-tertiary, …)` y ese primitivo no existe — el contrato
|
|
|
guarda lo que de verdad pintaba.
|
|
|
|
|
|
Once adjudicaciones medidas (la demo monta la variante por defecto y no tiene
|
|
|
botón de acción genérico) **y una ANOMALÍA registrada**: `resize-grip-fg`
|
|
|
mueve bajo una réplica a mano de la secuencia del propio guard y aun así lo da
|
|
|
por muerto; causa no encontrada, descartadas cuatro. El token está vivo; la
|
|
|
lectura es lo que está en duda → §13, primer sitio por donde empezar la
|
|
|
revisión adversarial de este bloque.
|
|
|
|
|
|
Los 12 rojos que quedan son anteriores, y seis son el mismo conjunto que en
|
|
|
`popover`: el plano de profundidad gana sobre el panel (§12.9).
|
|
|
|
|
|
Gates: sonda 0 diffs en 1.890 valores · censo 84 % · `--names` sin desviadas ·
|
|
|
audit PASS · lint 0 · suite con el rojo conocido · rtl 0 · docs 0 · captura
|
|
|
mirada (cabecera, cierre y asa en su sitio).
|
|
|
|
|
|
- 2026-08-22 — **`nav-tree` 4 % → 96 %** (17 claves; tenía UNA). Global 61 %.
|
|
|
|
|
|
**La FILA es link + trigger a la vez** —mismo padding, tinta, radio y hover—,
|
|
|
así que el knob es de la fila (pseudo-parte, molde de `waveform`), con el
|
|
|
modificador DELANTE en lo interactivo (`hover-`/`active-`/`disabled-row-fg`)
|
|
|
y DETRÁS en lo contextual (`trail-row-fg`). El galón es una escuadra de dos
|
|
|
bordes: lado y trazo, como la esquina de `text-focus`.
|
|
|
|
|
|
**La suite cazó un incumplimiento heredado**, tercera vez en el eje: el
|
|
|
contrato copió `var(--font-size-sm)` verbatim del CSS y ésa es la coordenada
|
|
|
CRUDA que `recipe-css-contract` prohíbe. Al bundle, computa idéntico.
|
|
|
|
|
|
**Dos cegueras más del guard**: la fila es un `<div>` pelado sin atributo (su
|
|
|
`gap` leía muerto) y no leía el ANCHO de un borde que no fuera el de arriba.
|
|
|
Con las dos: **18/18 sin una sola excepción**. Los nueve componentes con
|
|
|
ledger re-verificados tras tocar las PROPS: sin regresiones ni STALE.
|
|
|
|
|
|
Gates: sonda **0 diffs en 22.140 valores** (102 nodos × 8 estados) · censo
|
|
|
96 % · `--names` sin desviadas · audit PASS · lint 0 · suite con el rojo
|
|
|
conocido · rtl 0 · docs 0 · captura del escenario mirada.
|
|
|
|
|
|
- 2026-08-22 — **`drawer` 57 % → 72 %** (10 claves: el disparador, gemelo del
|
|
|
de popover, con `min-block-size` al bundle). Global 61 %.
|
|
|
|
|
|
Lo que queda fuera es la FIRMA DE SALIDA (los cuatro bordes base que
|
|
|
`data-last-action` tiñe al cerrar) → §13, y ocho privados que son canales de
|
|
|
valor del wrapper.
|
|
|
|
|
|
**Una adjudicación de clase nueva**: el guard ABRE el cajón antes de probar y
|
|
|
el velo tapa el disparador, así que la pasada de hover no puede posarse en él.
|
|
|
Con el cajón cerrado y hover a mano, `hover-trigger-bg` alcanza. Los otros 24
|
|
|
rojos son anteriores (asa, anillo de arrastre, tallas del panel).
|
|
|
|
|
|
Gates: sonda 0 diffs en 390 valores · censo 72 % · `--names` sin desviadas ·
|
|
|
audit PASS · lint 0 · suite con el rojo conocido · rtl 0 · docs 0.
|
|
|
|
|
|
- 2026-08-22 — **`aura` 43 % → 80 %** (13 claves). Global 61 %.
|
|
|
|
|
|
Su texto de estado baja un paso del bundle por talla y las TRES coordenadas
|
|
|
viajan juntas: doce declaraciones, doce valores, doce claves (1:1, sin
|
|
|
inflación). Más `idle-opacity`. Identidad fuera: el radio del anillo, los
|
|
|
cuatro `100%` y el `1px` de la región sr-only.
|
|
|
|
|
|
**Doce adjudicaciones medidas**: las seis tintas de estado y el halo pintan el
|
|
|
fondo del INDICADOR y la demo corre con el canvas WebGL montado —
|
|
|
`:has(canvas)` pone `background: none` a propósito—; quitando el canvas en
|
|
|
vivo, el gradiente vuelve y las siete siguen. El arco y el halo son SLOTS que
|
|
|
sólo existen en los estados de trabajo: montados como `<circle>` en el SVG
|
|
|
real, alcanzan. Y el guard no veía ese SVG (sus `<circle>` no llevan
|
|
|
`data-aura*`): tercera vez que `extraNodes` salva tokens vivos.
|
|
|
|
|
|
Gates: sonda 0 diffs en 1.710 valores · centinela 25/37 con las doce
|
|
|
adjudicadas · censo 80 % · `--names` sin desviadas · audit PASS · lint 0 ·
|
|
|
suite con el rojo conocido · rtl 0 · docs 0.
|
|
|
|
|
|
- 2026-08-22 — **`color-picker` 51 % → 75 %** (20 costuras + un prefijo
|
|
|
abreviado retirado). Global **60 % → 61 %**.
|
|
|
|
|
|
**`--cp-*` violaba theming §6 r5** (no abreviar el nombre del componente):
|
|
|
cinco nombres, **45 ocurrencias en 8 ficheros**, tres de SOMA —el provider los
|
|
|
estampa inline, su test los lee, sus tipos los declaran—. Renombrados a
|
|
|
`--_color-picker-*` con `git ls-files` y 0 diffs; dos ya derivaban de un
|
|
|
público, así que el censo los reclasifica solo. Precedente: los `--gb-*` de
|
|
|
F2-A.
|
|
|
|
|
|
Cosido el ritmo, la tinta de la etiqueta, la tipografía del disparador y la
|
|
|
del VALOR (metadato: mono/regular/tinta propia), el borde de la muestra, el
|
|
|
raíl de canal y su pulgar, el hueco del anillo y el borde del cuentagotas.
|
|
|
**El pulgar lleva DOS sombras que hacen una cosa** (contorno + elevación):
|
|
|
un token, y la regla de foco lo compone con su tercer anillo.
|
|
|
|
|
|
**El instrumento no veía dos familias de nodo**: las muestras del picker SON
|
|
|
`<ColorSwatch>` (`data-color-swatch`) y sus sliders SON sliders
|
|
|
(`data-slider-*`); cuatro tokens vivos leían muertos. Con `extraNodes` para
|
|
|
las dos, 46/71.
|
|
|
|
|
|
**Lo rojo que queda es anterior**: 23 sin adjudicar (eran 24), del bloque
|
|
|
viejo — su pase propio queda en §13, con dos causas ya descartadas (el panel
|
|
|
SÍ abre y sobrevive al forzado de talla; el guard ya ve sus nodos).
|
|
|
|
|
|
Gates: sonda 0 diffs en 1.350 valores, medida DOS veces (tras el renombrado y
|
|
|
tras la costura) · tests de soma del color-picker 7/7 · censo 75 % ·
|
|
|
`--names` sin desviadas · audit PASS · lint 0 · suite con el rojo conocido ·
|
|
|
rtl 0 · docs 0 · `check` sin errores propios.
|
|
|
|
|
|
- 2026-08-22 — **`popover` 46 % → 67 %** (11 claves para el disparador + una
|
|
|
RETIRADA). Global 60 %.
|
|
|
|
|
|
El disparador genérico —el que no lleva el arquetipo `field-trigger`— montaba
|
|
|
su cromo sobre primitivos crudos: once costuras, con `trigger-height` leyendo
|
|
|
el BUNDLE y no el primitivo, y hover/abierto con su par cada uno (mismo valor
|
|
|
hoy, dos estados distintos).
|
|
|
|
|
|
**`bg` retirado: era un huérfano que el test de huérfanos no veía.** Ninguna
|
|
|
regla lo consumía; lo único que lo nombraba era un COMENTARIO de
|
|
|
`popover-arrow.svelte`, y ese test busca el nombre como texto en los ficheros
|
|
|
del componente. La superficie la pinta el plano de profundidad. → §13.
|
|
|
|
|
|
**Los doce que quedan son la FIRMA DE SALIDA y no se cosen aquí**: la misma
|
|
|
matriz `data-last-action` × 3 intents × 4 lados está repetida en drawer (22)
|
|
|
y dialog (9), y ya ha derivado (dialog tiñe sólo el color; popover y drawer
|
|
|
también el grosor). La tabla morfo→eidos la sitúa como mapeo transversal, así
|
|
|
que la salida es una regla sobre el arquetipo, no tres copias. → §13.
|
|
|
|
|
|
**Dos cegueras del instrumento**: la página tiene CINCO disparadores y el
|
|
|
guard abría el primero del documento en vez del del escenario; y `content-z`
|
|
|
se consume sobre el ENVOLTORIO FLOTANTE, un nodo sin atributo `data-popover*`,
|
|
|
así que leía muerto moviendo 80 → 4321. Las dos arregladas en
|
|
|
`COMPONENT_OVERRIDES`.
|
|
|
|
|
|
Gates: sonda 0 diffs en 420 valores (8 estados) · centinela 33/46 con trece
|
|
|
adjudicaciones medidas —nueve de partes que la demo no monta, dos del overlay
|
|
|
opcional y **dos que el plano `overlay` gana** (§12.9, pendiente de firma)— ·
|
|
|
censo 67 % · `--names` sin desviadas · audit PASS · lint 0 · suite con el rojo
|
|
|
conocido · rtl 0 · docs 0.
|
|
|
|
|
|
- 2026-08-22 — **`radio-cards` 60 % → 61 %: una sola clave, y ése es su techo.**
|
|
|
21 de sus 23 knobs fuera de alcance **no son suyos**: es un SKIN sobre
|
|
|
RadioGroup —renderiza `<RadioGroup.Provider>` y su indicador ES un radio—, así
|
|
|
que lee `--radio-group-*` y el puente de paleta del anfitrión. Mandato de
|
|
|
composición (`theming-audit` §5.3-3): se teman en la ficha del dueño. Lo suyo
|
|
|
es la TARJETA: `invalid-border`. Los dos `--radius-full` del indicador son
|
|
|
identidad (un radio es redondo por definición).
|
|
|
|
|
|
**La lección de la medición**: la primera lectura de `invalid-border` dio «sin
|
|
|
efecto» porque la tarjeta transiciona `border-color` y leer justo después de
|
|
|
escribir devuelve el valor de PARTIDA. Con las transiciones congeladas —lo que
|
|
|
el guard hace por defecto y mi sonda a mano no— alcanza. **Una medición
|
|
|
forzada tiene que congelar también.**
|
|
|
|
|
|
Gates: sonda 0 diffs en 3.540 valores · centinela 35/40 con las cinco
|
|
|
adjudicadas y medidas · censo 61 % · `--names` sin desviadas · audit PASS ·
|
|
|
lint 0.
|
|
|
|
|
|
- 2026-08-22 — **`prose` 1 % → 83 %** (35 claves de costura, 2 → 37).
|
|
|
Global **59 % → 60 %**; `global` del catálogo 1.064 → 1.021.
|
|
|
|
|
|
Estiliza HTML CRUDO por `:where([data-prose] el)`, así que sus partes son
|
|
|
ELEMENTOS y la costura va por parte, como en `result`. Su escala editorial
|
|
|
`em`-relativa no entra: es decisión de diseño de su README («No 5×
|
|
|
duplicated scale») y va anotada `/* literal: */` — las 21 excepciones que el
|
|
|
censo aprendió a leer esta misma sesión. Dos literales se cambiaron por su
|
|
|
paso de escala con idéntico valor (`3px` → `--border-width-thick`, los `1px`
|
|
|
→ `--border-width`).
|
|
|
|
|
|
**El instrumento estaba ciego de dos maneras**, las dos arregladas antes de
|
|
|
medir: sonda y centinela filtran por `data-{c}-*` y aquí NINGUNA parte lo
|
|
|
lleva —la sonda medía **1 nodo** y el guard daba 27 de 37 por muertos—, así
|
|
|
que ambos ganan un selector de nodos extra (63 nodos con él); y el centinela
|
|
|
no leía el color de un borde que no fuera el de arriba, con lo que el
|
|
|
blockquote (`border-inline-start`) y la tabla (bordes de bloque) leían
|
|
|
muertos estando vivos.
|
|
|
|
|
|
Ocho adjudicaciones medidas: cinco las tapa el harness de la documentación
|
|
|
(`[data-uix-docs] code|pre` (0,2,0) gana a `:where(…)` (0,0,0) — la
|
|
|
incidencia ya escrita para `code-block`) y tres son elementos que el HTML de
|
|
|
ejemplo no usa, montados dentro del contenedor real.
|
|
|
|
|
|
Gates: sonda **0 diffs en 11.910 valores** (63 nodos × 7 estados) · centinela
|
|
|
29/37 · censo 83 % · `--names` 37/37 · audit PASS · lint 0 · suite con el
|
|
|
rojo conocido · rtl 0 · docs 0 · `check` sin errores propios. Los del ledger
|
|
|
re-verificados tras tocar el guard: sin regresiones.
|
|
|
|
|
|
- 2026-08-22 — **`listbox` ADJUDICADO: 68 % es su techo, y coserlo habría
|
|
|
mentido.** Sin cambios de código: su veredicto §5.
|
|
|
|
|
|
Cinco de sus nueve privados adoptan la capa `list-surface` (el ritmo de fila
|
|
|
compartido con select, combobox, command y los tres menús), dos son el puente
|
|
|
de paleta y el noveno sí deriva de un público. La cola decía «cose como sus
|
|
|
hermanos» —`dropdown-menu` y `context-menu` sí acuñan el puente—, y la
|
|
|
medición lo desmontó: **ninguno de los dos nombres alcanza desde `:root`**
|
|
|
(fila a 36 px, `--dropdown-menu-item-height` y `--list-item-height` a
|
|
|
`1234px` en `:root` → 36 px). La capa declara sobre
|
|
|
`[data-list-surface][data-size]` y el puente sobre `[data-{c}-content]`: las
|
|
|
dos ganan a `:root`. Copiar el puente habría subido la cifra sin dar alcance
|
|
|
— un token que miente, la clase que R-5.4 existe para cazar.
|
|
|
|
|
|
Se arregla EN LA CAPA (entrada de receta, como `calendar-surface`), toca diez
|
|
|
componentes y es su propio eje → §13. **Y avisa sobre el instrumento**: el
|
|
|
centinela da por vivos estos tokens porque escribe inline en el nodo; para un
|
|
|
token que un tema sólo puede escribir en `:root`, «mueve un computed» no
|
|
|
equivale a «un tema lo alcanza».
|
|
|
|
|
|
- 2026-08-22 — **El censo aprende a leer la válvula del canon: clase
|
|
|
`exception`.** Global **58 % → 59 %**, sin tocar una línea de CSS.
|
|
|
|
|
|
`recipe-contract` §3 dice que una desviación anotada
|
|
|
`/* literal: <razón> */` **en su propia declaración** es válida, y
|
|
|
`component-audit` ya la honra desde siempre (`declarationWindow` +
|
|
|
`/literal:/i` en R-2.1/2.6/2.7). El censo era el único instrumento que no:
|
|
|
su `strip()` blanquea los comentarios ANTES de clasificar, así que las
|
|
|
**81 anotaciones del catálogo** contaban como deuda. Dos instrumentos, un
|
|
|
canon, dos respuestas.
|
|
|
|
|
|
Ahora un literal anotado cae en la clase `exception`, **fuera del ratio**
|
|
|
como `system` — y por la misma razón: no es que un tema no lo alcance, es que
|
|
|
el canon ya aceptó por escrito que ahí no va un token. **54 knobs** en 12
|
|
|
componentes: `prose` 21 (su escala editorial `em`-relativa, decisión de
|
|
|
diseño firmada en su README), `proof-of-human` 16 (la escena de tono fijo),
|
|
|
`palabras` 3, `timeline` 2 (73 % → **77 %**), `result` 1 (86 % → **90 %**),
|
|
|
y siete más con una cada uno.
|
|
|
|
|
|
**La anotación vale para la DECLARACIÓN entera**, no sólo para su primera
|
|
|
línea: un valor partido en varias líneas lleva la nota al final, y así se
|
|
|
mide. Muta-prueba: retirar una anotación de `prose` mueve el knob de
|
|
|
`exception` a `literal` (21 → 20) y devuelve el conteo al restaurarla.
|
|
|
|
|
|
Efecto colateral bueno: las fichas ganan una **§1.4** que LISTA las
|
|
|
excepciones con su razón. Antes estaban escritas en el CSS y no se leían
|
|
|
desde ninguna parte.
|
|
|
|
|
|
- 2026-08-22 — **Tres techos adjudicados: el PUENTE DE PALETA no es deuda.**
|
|
|
`tag-group` 65 %, `stepper` 79 %, `timeline` 73 % — sin cambios de código,
|
|
|
sus tres veredictos §5.
|
|
|
|
|
|
Los tres tienen `global` a cero: lo único fuera de alcance son sus privados
|
|
|
`--_{c}-palette-*`, el puente THM-2 que la capa compartida alimenta por
|
|
|
instancia desde `[data-color]`. **Un público encima del puente dejaría que un
|
|
|
tema lo fijara y matara en silencio el `color=` de cada instancia** — la misma
|
|
|
clase de daño que «declarar un público de facto mata una escala». Ya exponen
|
|
|
sus nueve roles × variante en claves públicas (91 en `tag-group`): ésa ES su
|
|
|
superficie de color. `timeline` suma la segunda razón firmada: sus
|
|
|
`--_timeline-hue-*` son un CONMUTADOR por `data-intent` (doctrina F2-B, cinco
|
|
|
precedentes) cuya rama por defecto es el puente.
|
|
|
|
|
|
Medido para no adjudicar de oído: de las **687** declaraciones del catálogo
|
|
|
que leen un privado, **130 leen un `--_{c}-palette-*`**, y son las que dominan
|
|
|
la columna `private` de todo componente con paleta (tag-group 14/14, stepper
|
|
|
11/11, radio-group 10, checkbox 8, file-upload 8, calendar / editable / los
|
|
|
tres grids 7). **El techo de un componente con paleta no es el 100 %** y su
|
|
|
cifra no compara con la de uno sin ella — registrado en §13, junto con la
|
|
|
única salida si algún día se quiere comparabilidad: una clase `bridge` en el
|
|
|
censo, no acuñar los tokens.
|
|
|
|
|
|
- 2026-08-22 — **LA COSTURA: `chart` 49 % → 89 % y `result` 23 % → 86 %**
|
|
|
(6 + 15 claves). Global **57 % → 58 %**; `global` del catálogo 1.113 → 1.064.
|
|
|
|
|
|
**Corrige una lectura mía de las dos horas anteriores.** Al tokenizar `chart`
|
|
|
y `result` di por doctrina que «el texto no recibe tokens del componente»
|
|
|
porque su valor viene del canon —la capa de estilos con nombre, las ranuras de
|
|
|
contenido, el bundle de talla— y lo dejé leyendo el canon A PELO desde el CSS.
|
|
|
Eso es media doctrina: **el valor es del sistema, pero el knob tiene que ser
|
|
|
del componente** (PLAN §2-A: todo knob de apariencia lee `--{c}-{slot}`). Sin
|
|
|
la costura, un tema no puede aclarar las anotaciones de un gráfico denso sin
|
|
|
mover `caption` en toda la app, y `getRecipeTokens()` / `/temas` no ven esa
|
|
|
superficie. El molde ya estaba escrito en la vertebración tipográfica
|
|
|
(`--accordion-trigger-font-family: var(--style-label-font-family)`) y D-TH.2
|
|
|
aclara que **sólo los seis PRIMITIVOS** quedan fuera («un componente que sólo
|
|
|
LEE un named style para un eje no es un primitivo»).
|
|
|
|
|
|
**Dos formas, porque los componentes son distintos** — y ésa es la parte que
|
|
|
se firmó:
|
|
|
|
|
|
- `chart`, **por ROL**: dos roles del canon (`caption` para las anotaciones,
|
|
|
`label` para el cromo) × tres ejes = 6 claves para 19 nodos de texto.
|
|
|
Nombrar por parte habría dado ~30 claves con dos valores. Tamaño y tinta
|
|
|
son ORTOGONALES a propósito (`empty` y `bar-list-value` son tamaño `label`
|
|
|
con tinta `caption`). El readout del gauge no tiene rol en el canon y su
|
|
|
costura toma el bundle.
|
|
|
- `result`, **por PARTE**: cinco partes con tipografía distinta y ningún rol
|
|
|
que las cubra → 15 claves `title-*`, `description-*`, `extra-*`, `code-*`,
|
|
|
`media-*`. Es la forma dominante del catálogo.
|
|
|
|
|
|
**Nombres**: los tres que propuse primero no aguantaron la revisión
|
|
|
(`label-font-size` chocando con las seis partes `*-label`, `emphasis-*`
|
|
|
inventando vocabulario, `fg-muted` apoyado en un solo precedente). Se nombra
|
|
|
por el ROL DEL CANON que el texto adopta, y la tinta lee el color DEL ROL
|
|
|
(`var(--style-caption-color)`), no la ranura a pelo.
|
|
|
|
|
|
Con esto **`global` cae a CERO en los dos**: lo que queda fuera son los diez
|
|
|
literales de identidad de chart (nueve `100%` + `max-content`) y tres de
|
|
|
result.
|
|
|
|
|
|
Gates: sonda **0 diffs en 161.850 valores** (chart, 16 rutas × 7 estados) y
|
|
|
**990** (result) · centinela chart **43/45** y result **15/27**, y las doce
|
|
|
que callan están medidas SOBRE NODOS REALES con los controles de la demo
|
|
|
(chip `not-found` para el código HTTP, casilla del `extra`, quitar
|
|
|
`data-status` para la tinta por defecto del glifo) · censo 89 % / 86 % ·
|
|
|
`--names` 45/45 y 27/27 · audit PASS · lint 0 · suite con el rojo conocido ·
|
|
|
rtl 0 · docs 0 · `check` sin errores propios.
|
|
|
|
|
|
**Y retira una nota equivocada de §13**: escribí que el censo penalizaba
|
|
|
consumir la capa tipográfica. El censo medía bien; faltaba la costura. La
|
|
|
lección queda escrita ahí: cuando la métrica y la doctrina discrepan,
|
|
|
sospecha de la lectura antes que del instrumento. `listbox` (68 %, ritmo de
|
|
|
fila prestado de `list-surface`) es la misma pregunta un piso más arriba y
|
|
|
queda pendiente de revisar con este molde.
|
|
|
|
|
|
- 2026-08-22 — **`result` 14 % → 23 %** (4 claves, 8 → 12). Global 57 %,
|
|
|
<20 % 18 → 17. Aplicación directa de la doctrina que cerró `chart`: **la
|
|
|
receta posee su CAJA** —inset de página, ritmo entre bloques— y nada más. Su
|
|
|
tipo ya leía el BUNDLE DE TALLA (`--size-{k}-font-size`), que es lo que
|
|
|
recipe-contract §1 prescribe, y su tinta las ranuras de contenido: acuñar
|
|
|
`--result-title-font-size` habría sido tipografía por componente. Las trece
|
|
|
lecturas de canon siguen contando `global` — §13, tercera ocurrencia.
|
|
|
|
|
|
Higiene de paso: el privado `--_result-media-color` → `--_result-media-fg`
|
|
|
(D-TH.6 dice `fg`; R-5.3 no mira privados).
|
|
|
|
|
|
Gates: sonda **0 diffs en 990 valores** · centinela 7/12 con **cinco
|
|
|
adjudicaciones medidas sobre nodos REALES** —los tres acentos pulsando su
|
|
|
chip de estado, el bloque `extra` marcando su casilla— y no sobre nodos
|
|
|
fabricados (la lección de `drag-drop`) · censo --only 23 % · --names 12/12 ·
|
|
|
audit PASS · lint 0 · suite con el rojo conocido · rtl 0 · docs 0 · `check`
|
|
|
sin errores propios.
|
|
|
|
|
|
- 2026-08-22 — **`chart` 9 % → 49 %** (22 claves nuevas fusionadas en su bloque,
|
|
|
17 → 39). El mayor de los de alcance <20 % que no estaba bloqueado.
|
|
|
|
|
|
**La ficha pedía 71 claves y ~20 habrían llevado el mismo valor.** Lo decidió
|
|
|
la medición: las 84 filas fuera de alcance colapsan a **26 valores distintos**
|
|
|
(9× `content-secondary`, 9× `content-primary`, 9× `100%`, 6× `font-size-sm`,
|
|
|
6× `font-size-xs`, 6× `font-weight-medium`, 5× `surface-default`). La
|
|
|
inflación de `spinner` con otra forma: nombrar por parte lo que es un
|
|
|
concepto.
|
|
|
|
|
|
**El texto no recibe tokens de chart**: toma su ROL DE TAMAÑO de los estilos
|
|
|
con nombre (`caption` para anotaciones, `label` para el cromo) y su tinta y
|
|
|
peso de las ranuras del sistema. Acuñarlos sería tipografía por componente,
|
|
|
lo que el autor prohibió el mismo día. Precedente de consumir la capa:
|
|
|
`code-block`, `kbd`, `announce`. **La receta sólo posee la tinta de lo que no
|
|
|
es texto** — `axis-fg`, `grid-fg`, `separator-fg` (el pelo de superficie que
|
|
|
separa marcas contiguas: cinco partes, una idea), `smith-boundary-fg`,
|
|
|
`track-bg` — más 17 de geometría de cromo. Identidad fuera de contrato: los
|
|
|
nueve `100%` y el `max-content` del tooltip.
|
|
|
|
|
|
**Incumplimiento heredado corregido**: el CSS leía la coordenada CRUDA
|
|
|
`var(--control-height-sm, var(--space-7))` (respaldo muerto); el contrato
|
|
|
guarda el bundle `var(--size-sm-control-height)`, 1:1.
|
|
|
|
|
|
**El instrumento estaba ciego de TRES maneras, arregladas antes de medir:**
|
|
|
|
|
|
1. **La superficie de chart vive en 16 rutas de demo**, una por tipo:
|
|
|
`/chart` monta 58 nodos de los 302 de la página y el resto vive en rutas
|
|
|
hermanas. El guard gana `urls`: un token está VIVO si ALGUNA superficie del
|
|
|
componente lo sigue, y cada URL sólo re-prueba lo que sigue pendiente.
|
|
|
De paso `picker-shell` recibe la suya (su ruta propia es un 404, se mide
|
|
|
dentro del date-picker: 0/31 → 6/31 sin pasar la URL a mano).
|
|
|
2. **El guard no leía NINGUNA propiedad SVG** — sin `fill`/`stroke`/
|
|
|
`strokeWidth`/`fillOpacity`/`r`/`rx`, doce claves de un componente que
|
|
|
dibuja en SVG leían muertas estando vivas. Misma clase que el hueco de
|
|
|
`filter` del día anterior.
|
|
|
3. **El valor centinela se elegía por SUBCADENA**: `slice-stroke-width`
|
|
|
recibía `rgb(1, 2, 3)` por contener «stroke» — inválido para una longitud,
|
|
|
así que leía muerta. Ahora la dimensión se decide por el final del nombre.
|
|
|
|
|
|
Gates: sonda **0 diffs en 161.850 valores** (16 rutas × 7 estados, 892 nodos
|
|
|
en reposo) · centinela **37/39** con dos adjudicaciones medidas sin la
|
|
|
congelación (`transition-duration` 0.12s → 11.5s, `-ease` → steps(4)) ·
|
|
|
censo `--only` 49 % y global **56 % → 57 %** (2.638 → 2.675 públicos,
|
|
|
<20 % 19 → 18) · `--names` 39/39 conformes · audit PASS · eidos-lint 0
|
|
|
invalid · suite eidos con el único rojo conocido · rtl 0 · docs 0 · `check`
|
|
|
sin errores en los ficheros tocados. **Los 28 componentes con ledger
|
|
|
re-verificados tras los tres cambios de instrumento: cero regresiones, cero
|
|
|
STALE.**
|
|
|
|
|
|
Abre (→ §13): el censo **penaliza consumir la capa tipográfica** si no eres
|
|
|
un primitivo (las doce declaraciones correctas siguen contando `global`) — la
|
|
|
nota de `listbox` con una segunda ocurrencia; y el número del gauge no tiene
|
|
|
estilo con nombre que lo represente (un readout de dato no es un `h2`).
|
|
|
|
|
|
- 2026-08-22 — **`text-scramble` ADJUDICADO: sin contrato que escribir** (y el
|
|
|
barrido de fantasmas, hecho). Sin cambios de código: su veredicto §5.
|
|
|
|
|
|
Su 50 % no es ni deuda ni logro. **Dos literales son la técnica sr-only**
|
|
|
(`width`/`height: 1px`), idéntica a `text-blur`. **Los dos «públicos» son
|
|
|
tipografía que el componente no debería acuñar** —`font` y `size`,
|
|
|
consumidos con fallback y sin declarar—, o sea la firma **1.bis**:
|
|
|
escribirles contrato ahora sería acuñar exactamente lo que esa firma propone
|
|
|
retirar. Con `text-scramble` la cuenta de esa firma sube a **7 claves en 4 de
|
|
|
los 5** componentes de la familia (`text-blur` es el único limpio: hereda).
|
|
|
|
|
|
Y su `font` apunta a un fantasma: `var(--font-mono, …)` no existe —el
|
|
|
canónico es `--font-family-mono`— así que pinta `ui-monospace` e **ignora la
|
|
|
mono del tema** (`Azeret Mono`). Medido en navegador.
|
|
|
|
|
|
**El barrido mecánico que `--radius-xs` y `--font-size-4xl` pedían está
|
|
|
HECHO**: 5.793 nombres declarados en `src/uix/eidos` contra los
|
|
|
`var(--x, fallback)` de las recetas → **9 referencias fantasma**, tabla en
|
|
|
next-features §13. La más grave no es de esta familia:
|
|
|
`--color-content-tertiary` sigue vivo en TRES recetas (el caso histórico que
|
|
|
`recipe-contract` §1 cita como origen de su regla) y los cuatro
|
|
|
`--style-*-font-variation-settings` de `text.css` significan que el eje de
|
|
|
fuente variable **no llega nunca al primitivo `Text`**. Ninguna se arregla
|
|
|
aquí; el barrido debería ser un guard (misma lógica que el test de fantasmas
|
|
|
sin fallback, con el filtro de vocabulario de sistema encima).
|
|
|
|
|
|
- 2026-08-22 — **`text-gradient` 67 % → 100 %** (7 claves, entrada nueva).
|
|
|
Tercero de la familia text-* con la forma de `text-circular` / `text-focus`
|
|
|
(públicos «de facto» con fallback y sin declarar), pero la propuesta §4
|
|
|
generada fallaba en las tres decisiones y las tres se resolvieron midiendo
|
|
|
contra el CATÁLOGO, no contra el CSS de partida:
|
|
|
|
|
|
- **`weight` → `font-weight`**: 77 claves `font-weight` en el catálogo
|
|
|
contra 4 `weight` a secas, dos de ellas escritas el mismo 22 en esta
|
|
|
familia. Y `500` **es** `var(--font-weight-medium)`.
|
|
|
- **`calc(100% - 2px)` no son dos knobs de eje físico** (que es lo que la
|
|
|
ficha marcaba con ⚠) sino UNO: los 2 px son el trazo del marco asomando a
|
|
|
cada lado. Knob = `border-width` con `var(--border-width)` (el paso
|
|
|
`thin`, no un literal igual a un paso), y el hueco DERIVA de él.
|
|
|
- **`blur(4px)` → `var(--blur-sm)`**: `blur` es familia MÉTRICA del eje
|
|
|
`scaling` (theming §23) y un literal es ciego al zoom global.
|
|
|
|
|
|
Fuera del contrato por naturaleza: `duration` y `play-direction`, que el
|
|
|
wrapper escribe INLINE desde `animationSpeed`/`yoyo` — misma clase que el
|
|
|
`item-gap` de `carousel` y el `preview-z` de `drag-drop`.
|
|
|
|
|
|
**Dos puntos ciegos del instrumento, arreglados ANTES de medir** (la lección
|
|
|
de F2-B aplicada por adelantado): la demo arranca con `showBorder=false`, así
|
|
|
que sonda y centinela veían 2 nodos y NINGUNO de los tres tokens del marco;
|
|
|
y la sonda no leía `backdropFilter`, que el censo sí cuenta como knob. La
|
|
|
sonda gana un mapa `DEMO_VARIANTS` (chips de variante que se re-pulsan tras
|
|
|
cada recarga) y el centinela una entrada `openWith` que no abre un panel sino
|
|
|
que ENCIENDE UNA VARIANTE — un uso nuevo del mismo gancho.
|
|
|
|
|
|
Gates: 4 nodos · 720 valores × 7 estados · **0 diffs** · centinela **7/7 sin
|
|
|
excepciones** · censo `--only` 100 % y global 2.634 → 2.638 públicos ·
|
|
|
`--names` 7/7 conformes · audit PASS · eidos-lint 0 invalid · suite eidos con
|
|
|
el único rojo conocido (`skin-media-player`) · rtl 0 · docs 0 · `check` sin
|
|
|
errores en los ficheros tocados. Demo con pestaña **Tokens** (y fuera la
|
|
|
tabla de tokens escrita a mano, que este mismo renombrado dejaba obsoleta).
|
|
|
|
|
|
Abre (→ next-features §13, **pendiente de firma, apuntado para después**):
|
|
|
**la familia text-effects ACUÑA tipografía propia contra el canon** — cinco
|
|
|
claves (`text-focus.word-size` vía el fantasma `--font-size-4xl` y
|
|
|
`word-weight` · `text-circular.weight` y `font-size` ·
|
|
|
`text-gradient.font-weight`, ésta subida aquí), opiniones del seed que el
|
|
|
«valor verbatim» hizo contrato. Doctrina F2-B regla 2: se CONSUME la capa
|
|
|
(`--style-*`) o se HEREDA (`link`); un efecto de pintura sobre texto real no
|
|
|
tiene tipografía propia. Resolución propuesta: retirar las cinco y heredar
|
|
|
(mueve defaults → firma). El módulo de tipografía es canon y no se toca. Las
|
|
|
demos NO forman parte del eje (autor, 2026-08-22).
|
|
|
|
|
|
- 2026-08-22 — **Bloque F2-B: 21 componentes tokenizados + 5 adjudicados como
|
|
|
«0 % estructural».** Global **45 % → 50 %**; sin contrato 49 → 29; al 100 %
|
|
|
7 → 10; alcance <20 % 43 → 22. Uno por commit, protocolo §7 entero, sonda
|
|
|
antes/después = 0 diffs en todos.
|
|
|
|
|
|
| componente | alcance | commit |
|
|
|
| --- | ---: | --- |
|
|
|
| `grid-list` | 0 → 85 % | `60b5b9896` |
|
|
|
| `textarea` | 0 → 80 % | `893aeaf81` |
|
|
|
| `tree-view` | 0 → 92 % | `dd188f125` |
|
|
|
| `code-block` | 0 → 81 % | `354d166df` |
|
|
|
| `card-group` | 0 → 90 % | `c56d6544e` |
|
|
|
| `spinner` | 0 → 70 % | `42a3e7413` |
|
|
|
| `picker-shell` | 0 → 76 % | `67b4c810c` |
|
|
|
| `link-preview` | 0 → 100 % | `7a0fc2ead` |
|
|
|
| `drag-drop` | 0 → 89 % | `650d76aa0` |
|
|
|
| `kbd` | 0 → 86 % | `adb77863c` |
|
|
|
| `link` | 0 → 36 % | `d3089e880` |
|
|
|
| `code` | 0 → 100 % | `e4bcd505d` |
|
|
|
| `virtual-list` | 0 → 67 % | `070145786` |
|
|
|
| `virtual-grid` | 0 → 73 % | `e3f39ce28` |
|
|
|
| `skeleton` | 0 → 45 % | `a6d4d4f5a` |
|
|
|
| `label` | 0 → 100 % | `7565eff47` |
|
|
|
| `announce` | 0 → 88 % | `d568577eb` |
|
|
|
| `clipboard` | 0 → 63 % | `151e5159b` |
|
|
|
| `scroll-frames` | 0 → 33 % | `1f692629e` |
|
|
|
| `mark` | 0 → 60 % | `9f24a31eb` |
|
|
|
| `menu-dial` | 0 → 25 % | `471ba96d2` |
|
|
|
| 5 estructurales (fichas) | 0 % FINAL | `ed2e3cd7c` |
|
|
|
|
|
|
**Lo que el bloque enseñó, y no estaba en el plan:**
|
|
|
|
|
|
1. **Un alcance bajo puede ser doctrina bien aplicada.** `menu-dial` 25 %
|
|
|
porque sus ejes de colocación son de la capa `viewport-placement` y la
|
|
|
receta escribe en sus RANURAS DE OVERRIDE; `link` 36 % porque sus
|
|
|
escotillas caen en `inherit`, que es semántico; `scroll-frames` 33 %
|
|
|
porque es layout puro. El % no es la métrica de calidad.
|
|
|
2. **Un privado con DOS fuentes es un conmutador, no deuda** — cinco casos
|
|
|
con el mismo veredicto (`textarea`, `spinner`, `skeleton`, `code`,
|
|
|
`label`): aplanarlo obligaría a duplicar cada regla por color.
|
|
|
3. **Lo que la capa tipográfica posee no se acuña** — cinco casos
|
|
|
(`code-block`, `kbd`, `announce`, `code`, `label`).
|
|
|
4. **Cinco componentes tienen 0 % POR NATURALEZA** y ninguna deuda:
|
|
|
`aspect-ratio` (faceta de Box, knob prestado), `text-blur` (sr-only),
|
|
|
`cascade` y `motion` (gate antiparpadeo del canal), `date-picker`
|
|
|
(corrección `max-content` de composición). El censo no los distingue de
|
|
|
la deuda real, **así que el gate de F3 «censo 100 %» es inalcanzable por
|
|
|
construcción** hasta que exista una clase `structural` — §13.
|
|
|
5. **La propuesta §4 generada hereda el incumplimiento del CSS de partida**:
|
|
|
copia el valor verbatim, y si ese valor ya violaba `recipe-css-contract`
|
|
|
(primitivo crudo en vez del bundle), la propuesta lo repite. Lo cazó la
|
|
|
suite en `code-block`.
|
|
|
6. **La inflación del generador puede ser 4×**: en `spinner` proponía 71
|
|
|
tokens para 23 knobs, multiplicando UNA coordenada de talla por
|
|
|
variante × parte × dimensión.
|
|
|
|
|
|
**El guard R-5.4 ganó SEIS capacidades**, todas nacidas de una medición y
|
|
|
con los componentes del ledger re-verificados sin regresión tras cada una:
|
|
|
puntero parqueado tras el blur (`reopen()` corre antes de cada token),
|
|
|
`::placeholder` en el snapshot (la nota de §13 que decía que no se lee era
|
|
|
falsa), `COMPONENT_OVERRIDES` de prefijo y selector de apertura, apertura
|
|
|
por `hover` para hover-cards, y `text-decoration-thickness` /
|
|
|
`-underline-offset` en la lista de propiedades.
|
|
|
|
|
|
**Revisión adversarial §7.7 — HECHA 2026-08-22.** Molde F2-A: worktree en la
|
|
|
base del bloque (`8400e5bdd`) con su propio dev server, medición
|
|
|
independiente. **4 hipótesis · 3 refutadas · 1 hallazgo real.**
|
|
|
|
|
|
- **REFUTADA «el default cambió en algún sitio que la demo no mira»**: 77
|
|
|
casos FORZADOS (variantes, formas, tallas y estados que las demos NO
|
|
|
montan, en los 21 componentes) comparados base vs HEAD → **0 diferencias**.
|
|
|
- **REFUTADA «hay tokens huérfanos»**: 339 públicos de los 21 bloques, 0 sin
|
|
|
consumo. Con muta-prueba: un token falso inyectado sale detectado, y el
|
|
|
árbol se restaura.
|
|
|
- **REFUTADA «el gate de 0 diffs pasó sobre casi nada»**: se contaron los
|
|
|
nodos que ve cada sonda. Cuatro componentes miden 1 nodo (`link`, `code`,
|
|
|
`skeleton`, `link-preview`), y por eso se forzaron sus variantes en el
|
|
|
punto anterior — ahí es donde viven sus tokens, y salieron idénticos.
|
|
|
- **HALLAZGO REAL: `drag-drop.preview-z` mentía.** El ledger lo daba por vivo
|
|
|
con «forzado → alcanza», pero el nodo se había creado a mano; el preview
|
|
|
REAL que soma monta durante un arrastre lleva `z-index: 9999` INLINE, así
|
|
|
que ninguna cascada puede ganarle. Retirado con 0 diffs. Misma clase que el
|
|
|
`item-gap*` de carousel en F2-A. **La lección: una adjudicación «forzado →
|
|
|
alcanza» vale lo que valga el nodo que se forzó.** Re-verificado el resto de
|
|
|
la clase contra nodos reales (`clipboard`, `picker-shell`): correctos.
|
|
|
|
|
|
Dos hallazgos de INSTRUMENTO en la propia revisión, ambos registrados en §13:
|
|
|
el orden de carga **no es el mismo en dev que en producción** (medido con
|
|
|
build + CDP; el ganador coincide por casualidad), y un **worktree cuyo
|
|
|
`node_modules` es una junction fuera del root no hidrata** — Vite responde 403
|
|
|
a `@fs/…` y la primera pasada de esta revisión comparó contra una base
|
|
|
muerta sin que nada lo delatara.
|
|
|
|
|
|
- 2026-08-21 — **La capa `calendar-surface`** (firma 1 del acta, diseño
|
|
|
presentado y firmado el mismo día). La medición desmontó el encargo: la capa
|
|
|
ya existía de hecho — `--calendar-*` en `:root`, y `range-calendar` /
|
|
|
`month-grid` / `year-grid` con 114 / 77 / 77 referencias prestadas y CERO
|
|
|
tokens propios. Se le dio nombre y casa (`lib/calendar-surface.css`, hook
|
|
|
`data-calendar-surface`, cuatro coordenadas xs..lg sin xl, celda dos pasos
|
|
|
bajo el bundle) y se cerró el defecto que la justificaba: las dos sombras del
|
|
|
anillo se emitían con ámbito `[data-calendar]` y los otros tres las leían
|
|
|
vacías, así que el anillo sema **no pintaba** en tres componentes. Capa
|
|
|
HÍBRIDA: el vocabulario se queda en la entrada de receta (76 claves
|
|
|
semánticas alcanzables por config), la capa posee la resolución por talla y
|
|
|
la forma del anillo. **Siete wrappers estampan**, no cuatro — los pickers
|
|
|
renderizan la superficie soma por los suyos y un panel portalado no hereda.
|
|
|
Censo: `LAYER_VOCABULARY` deja de penalizar consumir una capa; global 43 % →
|
|
|
**45 %**, `calendar` 75 % → **84 %**.
|
|
|
|
|
|
- 2026-08-21 — **Revisión adversarial de F2-A (§7.7) + nace R-5.4.** Molde
|
|
|
Sidebar sobre worktree con solo el CSS revertido a la base: 34 hipótesis ·
|
|
|
26 refutadas · 8 reales, todas las de código arregladas con diff de computed
|
|
|
VACÍO (command 8.091 · carousel 2.842 valores). Retiradas: el re-point
|
|
|
muerto de `--command-radius` en el Dialog (su comentario mentía: el input
|
|
|
nunca lo leyó) y el trío `item-gap*` de carousel (el `gap` INLINE de soma
|
|
|
gana siempre — canal de valor, no knob). Tokenizado: el `2.25` vertical del
|
|
|
indicador activo. El instrumento viejo cargaba 22 falsos negativos de 26
|
|
|
«no effect» (clic-foco · override solo en `[data-{c}]` · pseudos) y la
|
|
|
no-determinación de `feed` era la demo cargando — cuatro causas arregladas.
|
|
|
**R-5.4**: `theming-sentinel.ts` + ledger de adjudicaciones, los ocho
|
|
|
componentes en verde con 46 excepciones medidas. El `striped` inerte se
|
|
|
firmó y ejecutó el mismo día: `:nth-child(even of [data-table-row])` +
|
|
|
`:where(:not([data-selected]))` al mismo (0,6,0) — 12 diffs exactos, hover
|
|
|
y selected verificados, la excepción del ledger retirada (table 42/45).
|
|
|
Pendiente de firma: el `item` en fila Y celda, y el gap de soma.
|
|
|
Detalle en [`CONTINUE-theming.md`](./CONTINUE-theming.md) §«Registro».
|
|
|
|
|
|
- 2026-08-20/21 — **Las 14 firmas, el vocabulario y el bloque F2-A.** El día se
|
|
|
abrió presentando D-TH.6 y acabó con las catorce decisiones pendientes
|
|
|
firmadas en bloque, el vocabulario normalizado con guard, y ocho componentes
|
|
|
tokenizados. Detalle en [`CONTINUE-theming.md`](./CONTINUE-theming.md)
|
|
|
§«Registro de la sesión».
|
|
|
|
|
|
**El vocabulario** (`f09e04fab` acta · `bd916ef3f` codemod · `93017975c`
|
|
|
segunda pasada · `7781d6e4c` guard + doctrina · `476da2dd2` muro de tipos):
|
|
|
307 claves al idioma firmado —tinta `fg`, modificador interactivo delante—
|
|
|
con censo de alcance IDÉNTICO y 0 diffs de computed. R-5.3 entra en `error`
|
|
|
directo; el tipo de `defineRecipes` impide la regresión sin ejecutar nada.
|
|
|
La medición corrigió el inventario heredado: 370 «desviadas» eran 301, porque
|
|
|
47 claves `{rol}-{slot-de-rol}` son canónicas por construcción y un codemod
|
|
|
sobre ellas habría roto `button` entero.
|
|
|
|
|
|
**El bloque F2-A** (pieza 0 `bd032534b` + ocho componentes): global
|
|
|
**37 % → 43 %**, sin contrato **56 → 49**, al 100 % **6 → 7**. `command` 98 %
|
|
|
· `table` 86 % · `media-player` 88 % · `tree-grid` 95 % · `gradient-picker`
|
|
|
88 % · `listbox` 68 % (techo deliberado: su ritmo es de `list-surface`) ·
|
|
|
`carousel` 77 % · `feed` 94 %. Protocolo §7 entero en los ocho; diff de
|
|
|
computed vacío en todos.
|
|
|
|
|
|
**Lo que el bloque destapó y NO se arregló aquí** está en
|
|
|
[`next-features.md`](../next-features.md) §12 y §13: el contrato de cascada
|
|
|
del velo de estado (131 declaraciones-atajo en 45 componentes, la prop
|
|
|
`hoverable` que no suprime nada, un empate de especificidad resuelto por orden
|
|
|
de carga) y los huecos de instrumento y demo. La regla que el eje adoptó: si
|
|
|
una incidencia mueve píxel o toca morfo, se mide, se anota y se sigue.
|
|
|
|
|
|
**Tres veredictos de ocho tenían un error de lectura** que sólo apareció
|
|
|
midiendo, y esa es la lección de método del bloque: el veredicto orienta, la
|
|
|
medición decide.
|
|
|
|
|
|
Además: la demo enseña ahora el contrato de tokens (`90aa6dc5f`,
|
|
|
`TokensPanel` leyendo `getRecipeTokens()` en vivo) — hasta ese día ninguna
|
|
|
demo mostraba la superficie que este eje construye.
|
|
|
|
|
|
- 2026-08-19 — Censo medido (§1) con `scripts/theming-census.ts` (añadido en
|
|
|
este commit como instrumento, sin guard). Plan entregado. **Nada firmado,
|
|
|
nada construido.** Precedente ejecutado hoy que fija la forma:
|
|
|
`navigation-menu` (`ae9e277fa`: tokens del trigger por talla, default
|
|
|
idéntico; `a82794845`: el hover es el del sistema; `822b78cf2`: el `<li>`
|
|
|
sin arquetipo) — y aun así el componente queda en 44 %, prueba de que hace
|
|
|
falta el guard.
|
|
|
|
|
|
- 2026-08-20 — **Informe + primeros siete componentes** (`2591ec2f0` el informe
|
|
|
y el instrumento; `3bfe0d413` la revisión de las fichas 11-20). El censo pasa
|
|
|
a `--report`: `docs/audit/theming/` con un README de conjunto y **170 fichas**
|
|
|
(162 recetas + 8 sin receta), cada una con análisis, propuesta derivada de la
|
|
|
doctrina y un bloque de **veredicto** que se conserva al regenerar.
|
|
|
|
|
|
| Componente | Censo antes → después | Commit | Excepciones / lo que queda fuera |
|
|
|
| --------------------------- | --------------------: | ----------- | ------------------------------------------------------------------------------------------------------------------------ |
|
|
|
| `gradient-builder` (piloto) | 0 % → 80 % | `3cdb5b5f0` | foco (sistema) + 3 literales de layout; damero tapado por el `background` inline del wrapper (anotado) |
|
|
|
| `combobox` | 0 % → 76 % | `cef2d32f1` | 3 hovers bespoke (esperan firma) + 6 literales; `content-font-family/-line-height` inertes bajo `[data-depth='overlay']` |
|
|
|
| `natural-time-picker` | 0 % → 61 % | `e774ca7e8` | cielos = excepción de tono fijo ya firmada; panel presta `--popover-*` por composición |
|
|
|
| `date-range-picker` | 0 % → 42 % | `07778b597` | mitad calendario (§B) + mitad campo (§5.3-3) |
|
|
|
| `time-range-picker` | 0 % → 19 % | `68eb8af26` | préstamos de Field/Slider/Toggle |
|
|
|
| `time-picker` | 0 % → 18 % | `e4fcdd62e` | préstamos de Field |
|
|
|
| `proof-of-human` | 0 % → 14 % | `ae91573c3` | escena = `FIXED_TONE_COMPONENTS`; hooks de clase (eje aparte) |
|
|
|
|
|
|
**Global: 33 % → 37 %** (1.621 → 1.841 públicos; 62 → 56 sin contrato).
|
|
|
Protocolo §7 aplicado entero en los siete: diff de computed **vacío** en todos
|
|
|
(6.612 · 1.566 · 6.438 · 493 · 725 · 580 · 406 valores, 7-8 estados cada uno),
|
|
|
centinela por token, `component:audit` PASS, `eidos-lint` 0 invalid,
|
|
|
`rtl:check` 0, `docs:check` 0, suite eidos con el único rojo conocido
|
|
|
(`skin-media-player`).
|
|
|
|
|
|
Cuatro defectos del método que la verificación destapó y que el handoff
|
|
|
recoge: **clave duplicada** en `recipes/base.ts` descarta el bloque en
|
|
|
silencio · dejar vivos los bloques `[data-size]` del CSS hace que el diff dé
|
|
|
0 por la ruta vieja · la sonda debe congelar `transition` pero **no**
|
|
|
`animation` (Presence no monta) · un token RESUELTO no se mueve desde `:root`
|
|
|
por diseño.
|
|
|
|
|
|
Prefijos abreviados o ajenos corregidos de paso (el censo los contaba como
|
|
|
`global` y se cruzarían al anidar): `--gb-*`, `--_ntp-*`, `--_time-field-*` en
|
|
|
los dos time-pickers, `--_date-field-*` y `--_calendar-font-size` en el
|
|
|
date-range-picker.
|
|
|
|
|
|
---
|
|
|
|
|
|
## 9. Tabla completa por componente (2026-08-19 — regenerar con el script, no editar)
|
|
|
|
|
|
| Componente | Familia | Alcance | Knobs | Público | Privado | Global | Literal | Sistema | Contrato | size |
|
|
|
| --------------------- | ------------------------------- | ------: | ----: | ------: | ------: | -----: | ------: | ------: | -------: | :--: |
|
|
|
| `range-calendar` | Tiempo (chronos · fecha/hora) | 0% | 98 | 0 | 7 | 84 | 4 | 3 | 0 | y |
|
|
|
| `combobox` | Campos | 0% | 96 | 0 | 15 | 67 | 6 | 8 | 1 | y |
|
|
|
| `proof-of-human` | Controles · marcas | 0% | 95 | 0 | 18 | 36 | 37 | 4 | 0 | y |
|
|
|
| `time-range-picker` | Tiempo (chronos · fecha/hora) | 0% | 88 | 0 | 6 | 61 | 17 | 4 | 0 | y |
|
|
|
| `natural-time-picker` | Tiempo (chronos · fecha/hora) | 0% | 78 | 0 | 0 | 69 | 7 | 2 | 0 | y |
|
|
|
| `gradient-builder` | Campos | 0% | 62 | 0 | 8 | 46 | 3 | 5 | 0 | y |
|
|
|
| `month-grid` | Tiempo (chronos · fecha/hora) | 0% | 61 | 0 | 13 | 40 | 5 | 3 | 0 | y |
|
|
|
| `year-grid` | Tiempo (chronos · fecha/hora) | 0% | 61 | 0 | 13 | 40 | 5 | 3 | 0 | y |
|
|
|
| `time-picker` | Tiempo (chronos · fecha/hora) | 0% | 59 | 0 | 3 | 42 | 12 | 2 | 0 | y |
|
|
|
| `date-range-picker` | Tiempo (chronos · fecha/hora) | 0% | 55 | 0 | 0 | 49 | 3 | 3 | 0 | y |
|
|
|
| `command` | Menús · listas · navegación | 0% | 52 | 0 | 9 | 35 | 6 | 2 | 0 | y |
|
|
|
| `table` | Menús · listas · navegación | 0% | 46 | 0 | 23 | 14 | 5 | 4 | 0 | y |
|
|
|
| `media-player` | Media · chat | 0% | 45 | 0 | 0 | 37 | 8 | 0 | 2 | y |
|
|
|
| `tree-grid` | Menús · listas · navegación | 0% | 42 | 0 | 29 | 8 | 2 | 3 | 0 | y |
|
|
|
| `field-langs` | Campos | 0% | 41 | 0 | 0 | 31 | 8 | 2 | 0 | – |
|
|
|
| `gradient-picker` | Campos | 0% | 38 | 0 | 7 | 23 | 5 | 3 | 0 | y |
|
|
|
| `listbox` | Campos | 0% | 38 | 0 | 9 | 23 | 3 | 3 | 0 | – |
|
|
|
| `carousel` | Superficies · overlays · estado | 0% | 36 | 0 | 14 | 12 | 5 | 5 | 0 | y |
|
|
|
| `heading` | Texto · tipografía | 0% | 36 | 0 | 36 | 0 | 0 | 0 | 0 | – |
|
|
|
| `feed` | Menús · listas · navegación | 0% | 33 | 0 | 13 | 16 | 3 | 1 | 0 | y |
|
|
|
| `grid-list` | Menús · listas · navegación | 0% | 32 | 0 | 8 | 17 | 2 | 5 | 0 | y |
|
|
|
| `textarea` | Campos | 0% | 28 | 0 | 16 | 5 | 4 | 3 | 0 | y |
|
|
|
| `tree-view` | Menús · listas · navegación | 0% | 28 | 0 | 8 | 14 | 4 | 2 | 0 | y |
|
|
|
| `code-block` | Texto · tipografía | 0% | 26 | 0 | 2 | 24 | 0 | 0 | 0 | – |
|
|
|
| `card-group` | Superficies · overlays · estado | 0% | 24 | 0 | 0 | 18 | 4 | 2 | 0 | y |
|
|
|
| `text` | Texto · tipografía | 0% | 24 | 0 | 24 | 0 | 0 | 0 | 0 | – |
|
|
|
| `spinner` | Superficies · overlays · estado | 0% | 23 | 0 | 15 | 4 | 4 | 0 | 0 | y |
|
|
|
| `picker-shell` | Tiempo (chronos · fecha/hora) | 0% | 21 | 0 | 4 | 17 | 0 | 0 | 0 | y |
|
|
|
| `link-preview` | Superficies · overlays · estado | 0% | 17 | 0 | 4 | 9 | 1 | 3 | 0 | y |
|
|
|
| `drag-drop` | Controles · marcas | 0% | 16 | 0 | 3 | 6 | 0 | 7 | 1 | – |
|
|
|
| `kbd` | Controles · marcas | 0% | 14 | 0 | 1 | 9 | 4 | 0 | 0 | – |
|
|
|
| `link` | Controles · marcas | 0% | 14 | 0 | 4 | 2 | 5 | 3 | 0 | – |
|
|
|
| `code` | Texto · tipografía | 0% | 13 | 0 | 6 | 3 | 4 | 0 | 0 | – |
|
|
|
| `virtual-list` | Menús · listas · navegación | 0% | 13 | 0 | 2 | 6 | 4 | 1 | 0 | y |
|
|
|
| `virtual-grid` | Menús · listas · navegación | 0% | 12 | 0 | 2 | 6 | 3 | 1 | 0 | y |
|
|
|
| `skeleton` | Superficies · overlays · estado | 0% | 11 | 0 | 9 | 1 | 1 | 0 | 0 | y |
|
|
|
| `skin-media-player` | Media · chat | 0% | 11 | 0 | 0 | 2 | 7 | 2 | 0 | y |
|
|
|
| `scroll-frames` | Superficies · overlays · estado | 0% | 9 | 0 | 1 | 4 | 4 | 0 | 0 | – |
|
|
|
| `announce` | Superficies · overlays · estado | 0% | 8 | 0 | 0 | 8 | 0 | 0 | 0 | – |
|
|
|
| `clipboard` | Controles · marcas | 0% | 8 | 0 | 2 | 5 | 1 | 0 | 0 | – |
|
|
|
| `label` | Campos | 0% | 8 | 0 | 6 | 2 | 0 | 0 | 0 | – |
|
|
|
| `menu-dial` | Menús · listas · navegación | 0% | 8 | 0 | 3 | 1 | 4 | 0 | 0 | y |
|
|
|
| `display` | Texto · tipografía | 0% | 6 | 0 | 6 | 0 | 0 | 0 | 0 | – |
|
|
|
| `mark` | Controles · marcas | 0% | 5 | 0 | 2 | 1 | 2 | 0 | 0 | – |
|
|
|
| `aspect-ratio` | Controles · marcas | 0% | 3 | 0 | 0 | 1 | 2 | 0 | 0 | – |
|
|
|
| `date-picker` | Tiempo (chronos · fecha/hora) | 0% | 2 | 0 | 0 | 0 | 2 | 0 | 0 | – |
|
|
|
| `sticky` | Superficies · overlays · estado | 0% | 2 | 0 | 1 | 0 | 1 | 0 | 1 | – |
|
|
|
| `text-blur` | Texto · tipografía | 0% | 2 | 0 | 0 | 0 | 2 | 0 | 0 | – |
|
|
|
| `cascade` | Menús · listas · navegación | 0% | 1 | 0 | 0 | 0 | 1 | 0 | 0 | – |
|
|
|
| `motion` | Superficies · overlays · estado | 0% | 1 | 0 | 0 | 0 | 1 | 0 | 0 | – |
|
|
|
| `section` | Layout (primitivos) | 0% | 1 | 0 | 0 | 0 | 1 | 0 | 4 | – |
|
|
|
| `chronos` | Tiempo (chronos · fecha/hora) | 1% | 245 | 2 | 22 | 202 | 12 | 7 | 9 | y |
|
|
|
| `prose` | Texto · tipografía | 1% | 74 | 1 | 0 | 43 | 30 | 0 | 2 | y |
|
|
|
| `nav-tree` | Menús · listas · navegación | 4% | 25 | 1 | 0 | 17 | 6 | 1 | 1 | – |
|
|
|
| `s-text` | Texto · tipografía | 7% | 30 | 2 | 28 | 0 | 0 | 0 | 3 | – |
|
|
|
| `chart` | Controles · marcas | 9% | 92 | 8 | 0 | 66 | 14 | 4 | 17 | – |
|
|
|
| `result` | Superficies · overlays · estado | 9% | 22 | 2 | 1 | 15 | 4 | 0 | 8 | – |
|
|
|
| `mockup` | Superficies · overlays · estado | 14% | 29 | 4 | 7 | 13 | 5 | 0 | 0 | – |
|
|
|
| `menubar` | Menús · listas · navegación | 15% | 27 | 4 | 6 | 16 | 0 | 1 | 5 | y |
|
|
|
| `anchor-nav` | Menús · listas · navegación | 20% | 11 | 2 | 0 | 8 | 0 | 1 | 2 | – |
|
|
|
| `banner` | Superficies · overlays · estado | 20% | 10 | 2 | 6 | 1 | 1 | 0 | 42 | y |
|
|
|
| `button` | Controles · marcas | 21% | 30 | 6 | 16 | 0 | 7 | 1 | 105 | y |
|
|
|
| `palabras` | WIP (tracks paralelos) | 22% | 471 | 103 | 1 | 272 | 90 | 5 | 0 | – |
|
|
|
| `toggle` | Controles · marcas | 22% | 28 | 6 | 17 | 1 | 3 | 1 | 119 | y |
|
|
|
| `date-range-field` | Tiempo (chronos · fecha/hora) | 25% | 9 | 2 | 0 | 4 | 2 | 1 | 3 | – |
|
|
|
| `time-range-field` | Tiempo (chronos · fecha/hora) | 25% | 9 | 2 | 0 | 4 | 2 | 1 | 3 | – |
|
|
|
| `surface` | Superficies · overlays · estado | 25% | 4 | 1 | 3 | 0 | 0 | 0 | 25 | – |
|
|
|
| `callout` | Superficies · overlays · estado | 27% | 15 | 4 | 3 | 7 | 1 | 0 | 28 | – |
|
|
|
| `meter` | Superficies · overlays · estado | 29% | 14 | 4 | 6 | 2 | 2 | 0 | 28 | y |
|
|
|
| `knob` | Controles · marcas | 29% | 27 | 7 | 4 | 9 | 4 | 3 | 0 | y |
|
|
|
| `onion-menu` | Menús · listas · navegación | 29% | 27 | 7 | 0 | 8 | 9 | 3 | 12 | – |
|
|
|
| `empty-state` | Superficies · overlays · estado | 29% | 17 | 5 | 7 | 5 | 0 | 0 | 6 | y |
|
|
|
| `search-field` | Campos | 31% | 14 | 4 | 5 | 0 | 4 | 1 | 17 | y |
|
|
|
| `password-field` | Campos | 31% | 36 | 11 | 5 | 9 | 10 | 1 | 23 | y |
|
|
|
| `aura` | Superficies · overlays · estado | 31% | 35 | 11 | 4 | 14 | 6 | 0 | 24 | y |
|
|
|
| `toggle-group` | Controles · marcas | 33% | 3 | 1 | 0 | 1 | 1 | 0 | 1 | – |
|
|
|
| `background` | Superficies · overlays · estado | 35% | 26 | 8 | 6 | 6 | 3 | 3 | 31 | – |
|
|
|
| `avatar` | Controles · marcas | 36% | 36 | 13 | 17 | 0 | 6 | 0 | 0 | y |
|
|
|
| `audio-player` | Media · chat | 37% | 19 | 7 | 0 | 8 | 4 | 0 | 5 | – |
|
|
|
| `tooltip` | Superficies · overlays · estado | 38% | 22 | 8 | 9 | 3 | 1 | 1 | 20 | y |
|
|
|
| `button-group` | Controles · marcas | 40% | 5 | 2 | 0 | 0 | 3 | 0 | 1 | – |
|
|
|
| `badge` | Controles · marcas | 41% | 22 | 9 | 10 | 1 | 2 | 0 | 65 | y |
|
|
|
| `popover` | Superficies · overlays · estado | 42% | 51 | 20 | 6 | 22 | 0 | 3 | 36 | y |
|
|
|
| `qr-code` | Controles · marcas | 43% | 7 | 3 | 0 | 0 | 4 | 0 | 10 | – |
|
|
|
| `navigation-menu` | Menús · listas · navegación | 44% | 38 | 15 | 1 | 13 | 5 | 4 | 26 | y |
|
|
|
| `waveform` | Media · chat | 45% | 11 | 5 | 1 | 1 | 4 | 0 | 10 | y |
|
|
|
| `color-picker` | Campos | 46% | 82 | 36 | 10 | 22 | 11 | 3 | 54 | y |
|
|
|
| `checkbox` | Controles · marcas | 48% | 34 | 16 | 12 | 2 | 3 | 1 | 45 | y |
|
|
|
| `progress` | Superficies · overlays · estado | 49% | 35 | 17 | 9 | 3 | 6 | 0 | 41 | y |
|
|
|
| `tag-group` | Controles · marcas | 49% | 46 | 21 | 21 | 0 | 1 | 3 | 91 | y |
|
|
|
| `color-swatch` | Controles · marcas | 50% | 10 | 5 | 2 | 3 | 0 | 0 | 12 | y |
|
|
|
| `text-scramble` | Texto · tipografía | 50% | 4 | 2 | 0 | 0 | 2 | 0 | 0 | – |
|
|
|
| `split-button` | Controles · marcas | 50% | 2 | 1 | 0 | 1 | 0 | 0 | 1 | y |
|
|
|
| `timeline` | Superficies · overlays · estado | 51% | 49 | 25 | 21 | 0 | 3 | 0 | 45 | y |
|
|
|
| `field` | Campos | 51% | 73 | 35 | 15 | 7 | 11 | 5 | 60 | y |
|
|
|
| `context-menu` | Menús · listas · navegación | 53% | 33 | 16 | 0 | 11 | 3 | 3 | 18 | – |
|
|
|
| `rating-group` | Controles · marcas | 53% | 16 | 8 | 4 | 1 | 2 | 1 | 25 | y |
|
|
|
| `metrics` | Controles · marcas | 54% | 50 | 27 | 10 | 9 | 4 | 0 | 68 | y |
|
|
|
| `sidebar` | Menús · listas · navegación | 55% | 45 | 23 | 0 | 14 | 5 | 3 | 50 | – |
|
|
|
| `drawer` | Superficies · overlays · estado | 55% | 62 | 33 | 9 | 13 | 5 | 2 | 44 | y |
|
|
|
| `color-field` | Campos | 56% | 16 | 9 | 0 | 2 | 5 | 0 | 22 | y |
|
|
|
| `image` | Controles · marcas | 57% | 35 | 20 | 2 | 1 | 12 | 0 | 22 | y |
|
|
|
| `dropdown-menu` | Menús · listas · navegación | 57% | 30 | 16 | 0 | 9 | 3 | 2 | 19 | – |
|
|
|
| `switch` | Controles · marcas | 57% | 22 | 12 | 8 | 1 | 0 | 1 | 52 | y |
|
|
|
| `s-text-virtual-list` | Menús · listas · navegación | 58% | 12 | 7 | 0 | 3 | 2 | 0 | 9 | – |
|
|
|
| `form` | Campos | 59% | 52 | 30 | 14 | 5 | 2 | 1 | 54 | y |
|
|
|
| `float-panel` | Superficies · overlays · estado | 59% | 53 | 29 | 3 | 12 | 5 | 4 | 28 | – |
|
|
|
| `slider` | Controles · marcas | 59% | 33 | 19 | 12 | 0 | 1 | 1 | 39 | y |
|
|
|
| `radio-cards` | Controles · marcas | 60% | 72 | 42 | 0 | 24 | 4 | 2 | 39 | y |
|
|
|
| `card` | Superficies · overlays · estado | 60% | 36 | 21 | 14 | 0 | 0 | 1 | 97 | y |
|
|
|
| `cropper` | Controles · marcas | 60% | 27 | 15 | 0 | 3 | 7 | 2 | 15 | – |
|
|
|
| `emoji-picker` | Campos | 61% | 32 | 17 | 0 | 8 | 3 | 4 | 17 | – |
|
|
|
| `pin-input` | Campos | 61% | 19 | 11 | 0 | 6 | 1 | 1 | 20 | y |
|
|
|
| `editable` | Campos | 63% | 44 | 25 | 12 | 1 | 2 | 4 | 56 | y |
|
|
|
| `text-focus` | Texto · tipografía | 63% | 8 | 5 | 0 | 1 | 2 | 0 | 0 | – |
|
|
|
| `spin-field` | Campos | 64% | 27 | 16 | 0 | 8 | 1 | 2 | 20 | – |
|
|
|
| `file-upload` | Campos | 64% | 61 | 38 | 16 | 1 | 4 | 2 | 98 | y |
|
|
|
| `tags-input` | Campos | 67% | 46 | 28 | 13 | 1 | 0 | 4 | 90 | y |
|
|
|
| `toolbar` | Menús · listas · navegación | 67% | 35 | 22 | 10 | 0 | 1 | 2 | 54 | y |
|
|
|
| `image-adjustments` | Controles · marcas | 67% | 18 | 10 | 0 | 4 | 1 | 3 | 12 | – |
|
|
|
| `text-gradient` | Texto · tipografía | 67% | 9 | 6 | 0 | 0 | 3 | 0 | 0 | – |
|
|
|
| `separator` | SIN FAMILIA | 67% | 6 | 4 | 0 | 0 | 2 | 0 | 3 | – |
|
|
|
| `select` | Campos | 69% | 72 | 45 | 14 | 3 | 3 | 7 | 101 | y |
|
|
|
| `dialog` | Superficies · overlays · estado | 70% | 33 | 23 | 5 | 4 | 1 | 0 | 37 | y |
|
|
|
| `image-picker` | Campos | 71% | 20 | 12 | 0 | 1 | 4 | 3 | 13 | – |
|
|
|
| `pagination` | Menús · listas · navegación | 71% | 26 | 17 | 7 | 0 | 0 | 2 | 34 | y |
|
|
|
| `stepper` | Menús · listas · navegación | 71% | 60 | 40 | 15 | 0 | 1 | 4 | 69 | y |
|
|
|
| `skip-link` | Superficies · overlays · estado | 71% | 8 | 5 | 0 | 0 | 2 | 1 | 8 | – |
|
|
|
| `date-field` | Tiempo (chronos · fecha/hora) | 73% | 11 | 8 | 3 | 0 | 0 | 0 | 21 | y |
|
|
|
| `time-field` | Tiempo (chronos · fecha/hora) | 73% | 11 | 8 | 3 | 0 | 0 | 0 | 21 | y |
|
|
|
| `calendar` | Tiempo (chronos · fecha/hora) | 75% | 71 | 51 | 13 | 0 | 4 | 3 | 76 | y |
|
|
|
| `accordion` | Superficies · overlays · estado | 77% | 65 | 49 | 10 | 0 | 5 | 1 | 76 | y |
|
|
|
| `radio-group` | Controles · marcas | 77% | 75 | 56 | 10 | 7 | 0 | 2 | 61 | y |
|
|
|
| `chat-log` | Media · chat | 77% | 42 | 30 | 0 | 4 | 5 | 3 | 31 | – |
|
|
|
| `chat-composer` | Media · chat | 79% | 44 | 31 | 0 | 3 | 5 | 5 | 31 | – |
|
|
|
| `chat-message` | Media · chat | 82% | 84 | 63 | 2 | 6 | 6 | 7 | 75 | y |
|
|
|
| `fab` | Controles · marcas | 82% | 17 | 14 | 0 | 2 | 1 | 0 | 10 | – |
|
|
|
| `toast` | Superficies · overlays · estado | 83% | 42 | 35 | 6 | 0 | 1 | 0 | 85 | – |
|
|
|
| `text-circular` | Texto · tipografía | 83% | 6 | 5 | 0 | 1 | 0 | 0 | 0 | – |
|
|
|
| `tabs` | Menús · listas · navegación | 88% | 76 | 66 | 6 | 2 | 1 | 1 | 79 | y |
|
|
|
| `chat-typing` | Media · chat | 89% | 9 | 8 | 0 | 1 | 0 | 0 | 7 | – |
|
|
|
| `breadcrumb` | Menús · listas · navegación | 90% | 23 | 18 | 2 | 0 | 0 | 3 | 28 | y |
|
|
|
| `collapsible` | Superficies · overlays · estado | 90% | 12 | 9 | 0 | 1 | 0 | 2 | 11 | – |
|
|
|
| `scroll-area` | Superficies · overlays · estado | 94% | 17 | 15 | 0 | 0 | 1 | 1 | 13 | – |
|
|
|
| `splitter` | Superficies · overlays · estado | 100% | 19 | 18 | 0 | 0 | 0 | 1 | 16 | – |
|
|
|
| `chat-list` | Media · chat | 100% | 18 | 18 | 0 | 0 | 0 | 0 | 18 | – |
|
|
|
| `box` | Layout (primitivos) | 100% | 9 | 9 | 0 | 0 | 0 | 0 | 43 | – |
|
|
|
| `barcode` | Controles · marcas | 100% | 5 | 5 | 0 | 0 | 0 | 0 | 7 | – |
|
|
|
| `flex` | Layout (primitivos) | 100% | 2 | 2 | 0 | 0 | 0 | 0 | 7 | – |
|
|
|
| `grid` | Layout (primitivos) | 100% | 2 | 2 | 0 | 0 | 0 | 0 | 13 | – |
|
|
|
| `alert-dialog` | Superficies · overlays · estado | — | 0 | 0 | 0 | 0 | 0 | 0 | 0 | – |
|
|
|
| `auto-grid` | Layout (primitivos) | — | 0 | 0 | 0 | 0 | 0 | 0 | 0 | – |
|
|
|
| `container` | Layout (primitivos) | — | 0 | 0 | 0 | 0 | 0 | 0 | 1 | – |
|
|
|
| `css-field` | Campos | — | 0 | 0 | 0 | 0 | 0 | 0 | 0 | – |
|
|
|
| `float` | Superficies · overlays · estado | — | 0 | 0 | 0 | 0 | 0 | 0 | 1 | – |
|
|
|
| `group` | Layout (primitivos) | — | 0 | 0 | 0 | 0 | 0 | 0 | 1 | – |
|
|
|
| `highlight` | Controles · marcas | — | 0 | 0 | 0 | 0 | 0 | 0 | 0 | – |
|
|
|
| `icon` | Controles · marcas | — | 0 | 0 | 0 | 0 | 0 | 0 | 2 | – |
|
|
|
| `mask-field` | Campos | — | 0 | 0 | 0 | 0 | 0 | 0 | 0 | – |
|
|
|
| `number-field` | Campos | — | 0 | 0 | 0 | 0 | 0 | 0 | 0 | – |
|
|
|
| `stack` | Layout (primitivos) | — | 0 | 0 | 0 | 0 | 0 | 0 | 0 | – |
|
|
|
| `wrap` | Layout (primitivos) | — | 0 | 0 | 0 | 0 | 0 | 0 | 0 | – |
|