|
|
# PLAN — Theming: que TODO componente sea personalizable por un tema (eje `theme-reach`)
|
|
|
|
|
|
> **Estado (act. 2026-08-23): EN EJECUCIÓN — alcance global 65 %, 25
|
|
|
> componentes al 100 %, 24 sin contrato, 12 por debajo del 20 %. Vocabulario
|
|
|
> CERRADO (codemod + R-5.3 + muro de tipos), bloques F2-A y F2-B CERRADOS y la
|
|
|
> cola avanzando: dieciséis componentes el 2026-08-23. 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).
|
|
|
|
|
|
**6.bis — CUENTA LOS NODOS ANTES DE CREER NADA.** La sonda imprime cuántos mide;
|
|
|
el guard, cuántos tokens mueven. Un recuento de 0–2 nodos, o un 0/N del guard, NO
|
|
|
es un resultado: es el instrumento ciego. Las siete causas medidas hasta el
|
|
|
2026-08-23, con el interruptor que las arregla (todos en `COMPONENT_OVERRIDES`
|
|
|
del guard y en `EXTRA_NODES`/`DEMO_VARIANTS` de la sonda):
|
|
|
|
|
|
| síntoma | causa | interruptor |
|
|
|
| --- | --- | --- |
|
|
|
| 0 nodos, ruta 404 | el componente **no tiene demo** (picker-shell, mockup, surface, audio-player) | `urls: ['/ruta/donde/sí/vive']` |
|
|
|
| 0–2 nodos con la página llena | sus partes **no llevan `data-{c}-*`**: hooks de clase (onion-menu, prose) o partes de OTRO chasis (audio-player) | `extraNodes` / `EXTRA_NODES` |
|
|
|
| la superficie no está en el DOM | abre por **hover**, no por clic (tooltip, link-preview) | `openBy: 'hover'` |
|
|
|
| la superficie se CIERRA sola | nace abierta y el guard la pulsa (onion-menu) | `openMarker` |
|
|
|
| media docena de tokens muertos por variante | el panel/skin sólo existe tras un **chip de la demo** | `openWith` + `DEMO_VARIANTS` |
|
|
|
| todos los tonos muertos | la paleta resuelve por `data-color` **o `data-intent`**, y por VARIANTE | barrido de tono (automático) + `sweepAttr` |
|
|
|
| `TimeoutError` antes de medir | la página **nunca alcanza `networkidle`** (image reintenta un `src` roto) | caída a `load` (automática) |
|
|
|
|
|
|
**Y tres lecturas que mienten aunque el nodo esté bien**: una propiedad EN
|
|
|
TRANSICIÓN devuelve el valor viejo (congela antes de leer, salvo que el token SEA
|
|
|
la transición); un nodo ANIMADO devuelve el valor de la animación (congela
|
|
|
también `animation`, a mano); y `::placeholder` sobre un input sin `placeholder`
|
|
|
devuelve el estilo del ELEMENTO.
|
|
|
|
|
|
### 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-23 — **`navigation-menu` 44 % → 100 %** (`85988785d`), bloque B1.
|
|
|
Contrato 26 → 44 claves: **19 nuevas y UNA retirada**. Diff 0 sobre 2.752
|
|
|
valores en 8 estados; R-5.4 43/44 con una adjudicación.
|
|
|
|
|
|
**Los nombres los dio el catálogo**: los gemelos cerrados el mismo día
|
|
|
(`dropdown-menu`, `context-menu`) para `content-{min-width,padding,radius,fg}`
|
|
|
y `chevron-{size,stroke}`; `accordion` para `trigger-font-family` y
|
|
|
`disabled-trigger-fg`. Las CUATRO recetas que declaran un chevron lo
|
|
|
dimensionan con un literal — un glifo no es un paso de la escala de espacio —,
|
|
|
y al revés el subrayado: su `2px` ES `--border-width-medium`.
|
|
|
|
|
|
**La §4 generada falla de CINCO maneras, una nueva**: llamaba `trigger-width`
|
|
|
/ `trigger-height` al CHEVRON (colisionando con la altura del control, que ya
|
|
|
existe), fundía dos nodos en `content-radius`, cruzaba `content-padding-*`
|
|
|
(era de la FILA) y llamaba `content-width` a un `min-inline-size` — y abría
|
|
|
exigiendo consumir la capa `menu-indicator`, que es **homonimia**: esa capa es
|
|
|
el check de los CheckboxItem, no el subrayado de esta barra.
|
|
|
|
|
|
**Las filas del panel no son `item-` ni `link-`**: aquí `item` es el `<li>` de
|
|
|
la barra y el `Link` de barra viste el cromo del trigger, así que esos nombres
|
|
|
prometerían un nodo que no alcanzan. `content-link-*` nombra el nodo por donde
|
|
|
vive. **El privado era una ESCALA** (tres fuentes por talla), y sube al TSC.
|
|
|
**`indicator-x` era declaración muerta** — soma escribe el rect inline y la
|
|
|
receta lee sólo `-w`/`-h`; retirada, 0 diffs.
|
|
|
|
|
|
**El instrumento, dos cegueras y una trampa** (§13): sonda y centinela no
|
|
|
veían el panel ni sus filas (los `<a>` desnudos del consumidor: 10 nodos y
|
|
|
ninguno era el panel — 9 de 19 knobs fuera del diff); **el guard cerraba el
|
|
|
panel que medía** (abre por `pointerenter`, y el aparcado del puntero en (0,0)
|
|
|
dispara el cierre) dando falso negativo Y falso positivo a la vez; y `color`
|
|
|
está EN TRANSICIÓN en esta parte, así que forzar `data-disabled` y leer en el
|
|
|
acto devuelve el valor viejo — la trampa del cuentagotas, en otro componente.
|
|
|
|
|
|
- 2026-08-23 — **`audio-player` 37 % → 56 %** (3 claves) **y el instrumento
|
|
|
medía CERO nodos**. El 44 % restante es préstamo con dueño (ocho filas
|
|
|
`--media-player-*`): es la piel de audio de ese chasis y se tema en su ficha.
|
|
|
|
|
|
Acuñado lo único que añade sobre el chasis: el peso del título y la insignia
|
|
|
LIVE (peso + tracking); los dos `600` pasan a `var(--font-weight-semibold)`.
|
|
|
|
|
|
**Tres cegueras encadenadas**: `/uix/components/audio-player` es un **404** —el
|
|
|
CUARTO canónico sin ruta—; sus partes son `data-media-player-*`, no
|
|
|
`data-audio-player-*` (con `extraNodes`, la sonda pasa de **0 a 48 nodos**); y
|
|
|
sólo existe tras el chip `media: audio` de la demo del chasis (sonda y guard lo
|
|
|
pulsan ahora, y el guard barre las cuatro variantes). Con eso, 0/8 → 6/8.
|
|
|
|
|
|
- 2026-08-23 — **COLA PEQUEÑA: seis componentes, cero claves nuevas.** `section`
|
|
|
(— · cuatro claves RESUCITADAS), `sticky` 0 → **100 %**, `button-group` 40 →
|
|
|
**100 %**, `qr-code` 43 → **100 %**, `toggle-group` 33 → **50 %** (su techo) y
|
|
|
`split-button` ADJUDICADO en 50 % (su techo). Global 65 %; **25 componentes al
|
|
|
100 %** y los de alcance <20 % bajan de 14 a 12.
|
|
|
|
|
|
**El hallazgo está en `section`: la receta TAPABA sus propias claves públicas.**
|
|
|
Declaraba los cuatro pasos de relleno en el host
|
|
|
(`[data-box][data-section] { --section-padding-block-sm: … }`), y esa
|
|
|
declaración gana a la que el contrato emite en `:root`: un tema que escribiera
|
|
|
`--section-padding-block-lg` perdía contra la receta. Borrado el bloque —mismos
|
|
|
valores, una sola fuente—, computado idéntico (48px antes y después), y las
|
|
|
cuatro claves alcanzan.
|
|
|
|
|
|
Lo demás es **identidad**: once `100 %` entre las seis recetas y el centinela
|
|
|
de 2px del sticky —el hilo invisible que el observador vigila—, todos con su
|
|
|
razón escrita. Más un respaldo muerto retirado en `toggle-group`, sobre un
|
|
|
token PRESTADO de `toggle` (el velo de un grupo deshabilitado es el del
|
|
|
toggle, y se tema en su ficha).
|
|
|
|
|
|
**Y una clase de adjudicación nueva, que se repetirá: UN PASO POR INSTANCIA.**
|
|
|
`section` y `qr-code` mapean su prop de talla a `var(--{c}-{eje}-{k})` y la
|
|
|
escriben INLINE, así que sólo el paso ACTIVO alcanza; los otros cuatro leen
|
|
|
muertos hasta que la prop cambia. No es deuda ni ceguera del instrumento: es
|
|
|
cómo funciona una escala resuelta por prop.
|
|
|
|
|
|
Gates: seis guards en verde · censo · audit PASS · suite con el rojo conocido
|
|
|
ajeno · rtl 0 · docs 0.
|
|
|
|
|
|
- 2026-08-23 — **`tooltip` 52 % → 75 %** (3 claves, 4 literales anotados) **y el
|
|
|
plano `overlay` ANULA SUS TRES VARIANTES**. Global 65 %.
|
|
|
|
|
|
Acuñados el desenfoque del velo `ghost` y las dos tintas de la flecha
|
|
|
`outline`. **No se acuñó `ghost-bg`**: lo intenté, el centinela lo delató y se
|
|
|
retiró antes de commitear.
|
|
|
|
|
|
**⚠⚠ El plano no sólo se queda la tipografía: se queda el fondo, el borde y la
|
|
|
sombra.** Medido: `--tooltip-bg`/`-border`/`-shadow` no mueven nada,
|
|
|
`--depth-overlay-*` repinta. Y la consecuencia visual es peor que la contable:
|
|
|
`solid`, `outline` y `ghost` computan lo MISMO — `outline` es indistinguible
|
|
|
de `solid`. → §13. Las cinco claves quedan adjudicadas, no retiradas: son la
|
|
|
fuente de la máquina de variantes.
|
|
|
|
|
|
Instrumento: el tooltip abre por HOVER (`openBy: 'hover'`, como link-preview) —
|
|
|
0/24 → 14/24—, y el resto se midió con el interruptor `open` de la demo, porque
|
|
|
un panel abierto por puntero exige el ratón quieto toda la pasada.
|
|
|
|
|
|
- 2026-08-23 — **`time-range-field` 29 % → 100 %** (4 claves), gemelo exacto de
|
|
|
`date-range-field` **defecto incluido**: la misma clave `row-gap` alimentando
|
|
|
el `column-gap`. Global **64 % → 65 %**.
|
|
|
|
|
|
Que los dos gemelos tuvieran el MISMO nombre equivocado dice algo: el error no
|
|
|
se coló al escribir, se copió al duplicar. **Donde hay un par, el defecto viene
|
|
|
en par** — mirar al gemelo es parte de la pasada.
|
|
|
|
|
|
- 2026-08-23 — **`date-range-field` 29 % → 100 %** (4 claves, una RENOMBRADA
|
|
|
porque mentía). Centinela 7/7.
|
|
|
|
|
|
**`row-gap` alimentaba el `column-gap`**: la clave pública movía el hueco entre
|
|
|
los dos campos, y el de fila —etiqueta ↔ campos— leía `--space-1-5` a pelo.
|
|
|
Dos claves ahora, cada una con el nombre de lo que alimenta, y **ningún
|
|
|
computado se mueve**. Un nombre equivocado es una perilla que gira otra cosa.
|
|
|
|
|
|
**La etiqueta se acuña con fecha de caducidad**: la raíz del rango NO es un
|
|
|
`[data-field]` —lo dice la propia receta— así que no puede heredar la etiqueta
|
|
|
de field.css y repetía los valores de la fundación. Nombrados aquí, y escrito
|
|
|
en el contrato que el mandato §5.3-3 los borra cuando la raíz sea un campo.
|
|
|
|
|
|
- 2026-08-23 — **`surface` ADJUDICADO: el 25 % es su techo**, cero claves nuevas.
|
|
|
Es la cara de PINTURA de Box y lo que pinta no es suyo: `bg` y `fg` salen del
|
|
|
puente de paleta (THM-2) y el acabado es canal de valor del generador (§39).
|
|
|
La rama `inherit` del `fg` suave es intencionada y está escrita en la receta.
|
|
|
|
|
|
**Pero no tiene ruta**: `/uix/components/surface` es un 404 y el guard medía
|
|
|
una página VACÍA — 0/25, incluido un `radius` vivísimo. Apuntado a
|
|
|
`/temas/gradientes` + `/blocks/cta`: 1/25, y el que mueve es el radio. Ya son
|
|
|
TRES los canónicos sin demo (picker-shell, mockup, surface) → §13.
|
|
|
|
|
|
Sus 24 claves de tono son la supersesión de paleta de hoy: patrón compartido.
|
|
|
|
|
|
- 2026-08-23 — **`banner` 30 % → 100 %** (11 claves) **y el guard pasa de 4/42 a
|
|
|
53/53**: sus 38 «muertos» estaban vivos, sólo que nadie los había mirado con
|
|
|
el atributo puesto. Global 64 %.
|
|
|
|
|
|
Cosida la densidad por talla, la interlínea y el trazo del anillo de
|
|
|
`outline` —la última fila que impedía al privado del borde derivar—. Dos
|
|
|
ausencias firmadas: los `transparent` de `outline`/`ghost` y los
|
|
|
`border-width: 0`, con el criterio de button.
|
|
|
|
|
|
**Dos cegueras del instrumento, arregladas**: (1) su paleta resuelve por
|
|
|
`data-intent`, no por `data-color`, y el barrido de tono estampaba sólo el
|
|
|
segundo — ahora estampa los dos nombres; (2) y luego por VARIANTE, así que el
|
|
|
guard recorre `data-variant` con `sweepAttr`. Es la diferencia entre «38
|
|
|
tokens que mienten» y «38 que nadie había mirado con el atributo puesto».
|
|
|
|
|
|
Gates: sonda 0 diffs en 192 valores × 7 estados · centinela 53/53 · censo
|
|
|
100 % · audit PASS · suite con el rojo conocido ajeno · rtl 0 · docs 0 ·
|
|
|
captura de cuatro variantes × cuatro intenciones.
|
|
|
|
|
|
- 2026-08-23 — **`anchor-nav` 20 % → 100 %** (11 claves) **y el censo aprende los
|
|
|
bordes POR LADO**. Global 64 %.
|
|
|
|
|
|
Tenía dos knobs y todo lo demás a pelo: la escala (que ahora lee el bundle),
|
|
|
el relleno y el radio del enlace, sus tres tintas, el peso del activo y las dos
|
|
|
tintas del RAÍL, que es lo que da nombre al componente.
|
|
|
|
|
|
**El raíl activo era INVISIBLE para la medida**: su color vive en un
|
|
|
`border-inline-start-color` y `KNOB_PROPS` sólo conocía `border-color` y los
|
|
|
shorthands. El centinela mira esos longhands desde el 2026-08-22 (los añadió
|
|
|
cuando prose y nav-tree leyeron muertos); el censo no. Añadidos los ocho por
|
|
|
lado, color y grosor: **+30 filas en el catálogo** (5.101 → 5.131) y esta ficha
|
|
|
baja a 18 % antes de coserse — el censo promete sobre-reportar, NUNCA
|
|
|
infra-reportar.
|
|
|
|
|
|
La tinta de reposo del raíl estaba escondida de otra manera: dentro de un
|
|
|
shorthand que el censo clasifica por el PRIMER token que casa (el trazo, ya
|
|
|
público). No hizo falta partirlo: basta nombrar el color dentro.
|
|
|
|
|
|
**Un susto útil**: una coma que faltaba en el contrato rompió el build de
|
|
|
tokens y lo delató la SONDA midiendo 0 nodos — la página no renderizaba. El
|
|
|
recuento de nodos es el canario.
|
|
|
|
|
|
Gates: sonda 0 diffs en 1.760 valores × 7 estados · centinela 11/12 · censo
|
|
|
100 % · audit PASS · suite con el rojo conocido ajeno · rtl 0 · docs 0.
|
|
|
|
|
|
- 2026-08-23 — **`image` 60 % → 96 %** (1 clave, 12 literales anotados) **y dos
|
|
|
instrumentos que morían en esta página**. Global 64 %.
|
|
|
|
|
|
Su deuda era casi toda IDENTIDAD: once `100 %` (la imagen, el fallback, el
|
|
|
error y sus dos `<img>` llenan su caja) y un `opacity: 1` (una imagen cargada
|
|
|
es opaca). Lo acuñado es la barra del esqueleto, que leía `--gradient-shimmer`
|
|
|
a pelo.
|
|
|
|
|
|
**La página NO alcanza `networkidle` NUNCA** —monta un `src` roto a propósito
|
|
|
para su estado de error— y sonda y guard morían con `TimeoutError` antes de
|
|
|
medir un nodo. Las dos caen ahora al evento `load` si la espera se agota.
|
|
|
|
|
|
**Un token bajo `@media (prefers-reduced-motion: reduce)` lee muerto**:
|
|
|
`placeholder-base` sólo existe ahí. Emulando la preferencia, alcanza — y vale
|
|
|
para cualquier token detrás de una media query de preferencia.
|
|
|
|
|
|
**Lectura fantasma cazada por repetición**: el primer diff acusó
|
|
|
`opacity: 0.925793 → 1` en la imagen cargada; era el fade EN VUELO, como el rim
|
|
|
animado de `onion-menu`. Repetida la medida, 0 diffs.
|
|
|
|
|
|
Gates: sonda 0 diffs en 544 valores × 7 estados (repetida) · centinela 20/23 ·
|
|
|
censo 96 % · audit PASS · suite con el rojo conocido ajeno · rtl 0 · docs 0.
|
|
|
|
|
|
- 2026-08-23 — **`checkbox` 59 % → 72 %** (3 claves, 3 literales anotados) **y un
|
|
|
HUÉRFANO cableado**. El 28 % restante es el puente de paleta (8 filas, THM-2).
|
|
|
|
|
|
**`indicator-fg` era un huérfano que el test de huérfanos no puede ver**: la
|
|
|
clave estaba en el contrato, pero la receta pintaba la tinta de la casilla
|
|
|
marcada leyendo `--color-content-on-solid` DIRECTAMENTE, sin nombrarla — y el
|
|
|
test busca el NOMBRE en los ficheros del componente. Cableada al privado de
|
|
|
paleta (computado idéntico), el propio guard lo confirmó marcando su
|
|
|
adjudicación como STALE: ahora mueve. Misma clase que el `--popover-bg` que
|
|
|
vivía de un COMENTARIO, al revés.
|
|
|
|
|
|
Acuñado el estado INVALID: el borde y el doble anillo de foco (hueco +
|
|
|
anillo), que era una sombra con dos colores cableados; la geometría 2px/4px se
|
|
|
queda dentro de la declaración, que es la forma del anillo.
|
|
|
|
|
|
**Dos trampas de ALCANCE del instrumento**, anotadas: el glifo sólo existe
|
|
|
dentro de una casilla MARCADA (medir «el primer indicador del documento» mide
|
|
|
otro nodo) y la etiqueta de grupo lleva su PROPIO `[data-disabled]`, no lo
|
|
|
hereda.
|
|
|
|
|
|
Gates: sonda 0 diffs en 2.688 valores × 7 estados · centinela 22/47 con todo
|
|
|
adjudicado · censo 72 % · audit PASS · suite con el rojo conocido ajeno · rtl 0
|
|
|
· docs 0 · captura de cinco estados.
|
|
|
|
|
|
- 2026-08-23 — **`dropdown-menu` 57 % → 96 %** (9 claves, 18 respaldos muertos
|
|
|
retirados) **y la tipografía del gemelo, RETIRADA**: `context-menu` 90 % →
|
|
|
87 %, a la baja y a propósito. Global 64 %.
|
|
|
|
|
|
Cosidos la tinta del panel y de la fila, su interlínea, el encabezado entero y
|
|
|
el galón del submenú (trazo + caja). **El filo del separador deja de ser un
|
|
|
`1px` suelto** y pasa a `--border-width`. Las dos limpiezas del gemelo se
|
|
|
repiten aquí: `font-family` era respaldo de SÍ MISMO y el peso del encabezado
|
|
|
llevaba un `500` muerto.
|
|
|
|
|
|
**Los 18 respaldos**: cada `var(--dropdown-menu-x, …)` llevaba detrás un valor
|
|
|
que no puede ocurrir —las claves están en el contrato— y sólo servía para
|
|
|
envejecer contra él; dos ya discrepaban en la FUENTE.
|
|
|
|
|
|
**⚠ `content-font-family` no se acuña, y la de `context-menu` se RETIRA.** El
|
|
|
panel lleva `data-depth='overlay'` y el plano gana (quinta prueba de §12.9).
|
|
|
Tenerla acuñada con una adjudicación escrita —como quedó ayer en el gemelo—
|
|
|
era media doctrina: **un público que no alcanza es un token que miente**
|
|
|
(R-5.4). Las dos recetas vuelven a la fuente literal con la razón encima.
|
|
|
`combobox` tiene la misma clave sobre el mismo plano: medido, registrado en
|
|
|
§13, no tocado aquí.
|
|
|
|
|
|
Gates: sonda 0 diffs en 928 valores × 8 estados · centinela 27/28 · censo
|
|
|
96 % · audit PASS · suite con el rojo conocido ajeno · rtl 0 · docs 0 ·
|
|
|
captura del panel.
|
|
|
|
|
|
- 2026-08-23 — **`empty-state` 29 % → 100 %** (20 claves, 6 → 26) **y el
|
|
|
centinela 26/26 sin una sola adjudicación**. Global 64 %.
|
|
|
|
|
|
Su deuda era de una clase: **la escala de talla vivía entera en privados** que
|
|
|
leían el bundle a pelo. Cada paso tiene ya su público (relleno, título, cuerpo
|
|
|
y glifo en `sm`/`md`/`lg`) y los privados los derivan; con eso el resto —peso,
|
|
|
interlínea y tinta del título, interlínea y tinta de la descripción— sale
|
|
|
solo. La caja del glifo se sigue derivando (2×) de su tamaño, ahora público.
|
|
|
|
|
|
**Siete respaldos muertos retirados**, dos de ellos MENTIROSOS: el `, 1.4` de
|
|
|
`--font-line-height-sm` (vale 1.45) y el `, 1.5` de `--font-line-height-md`.
|
|
|
Mismo defecto que `callout` hoy: **un respaldo escrito a mano envejece contra
|
|
|
el token**.
|
|
|
|
|
|
Gates: sonda 0 diffs en 1.056 valores × 7 estados · centinela 26/26 · censo
|
|
|
100 % · audit PASS · suite con el rojo conocido ajeno · rtl 0 · docs 0 ·
|
|
|
captura de las tres tallas.
|
|
|
|
|
|
- 2026-08-23 — **`callout` 27 % → 79 %** (7 claves, un literal anotado). Global
|
|
|
**63 % → 64 %**. El 21 % restante es el PUENTE DE PALETA (THM-2), que no es
|
|
|
deuda.
|
|
|
|
|
|
Cosidos el hueco de fila, la tipografía del cuerpo, la tinta, el tamaño del
|
|
|
icono y el peso del título, todos leyendo el BUNDLE. **La línea base óptica
|
|
|
del icono deja de repetir las métricas del sistema**: la misma derivación,
|
|
|
ahora sobre los tokens del propio callout, así que un tema que agrande la
|
|
|
copia mueve la caja del glifo con ella.
|
|
|
|
|
|
**Cinco respaldos muertos retirados** (`var(--callout-gap, var(--space-3))` y
|
|
|
compañía: las claves están en el contrato) incluido el `, 1.5` de
|
|
|
`--font-line-height-md`, que además mentía — el token existe y vale 1.45.
|
|
|
|
|
|
Los 24 rojos del guard son los TONOS: la supersesión que `button` destapó el
|
|
|
mismo día, adjudicada con el patrón compartido.
|
|
|
|
|
|
Gates: sonda 0 diffs en 896 valores × 7 estados · centinela 10/34 · censo
|
|
|
79 % · audit PASS · suite con el rojo conocido ajeno · rtl 0 · docs 0 ·
|
|
|
captura de cuatro tonos.
|
|
|
|
|
|
- 2026-08-23 — **`button` 55 % → 91 %** (1 clave, 17 declaraciones anotadas) **y
|
|
|
el hallazgo más gordo del eje: la cascada de paleta ANULA los tonos del
|
|
|
componente — 419 claves en el catálogo.** Global 63 %.
|
|
|
|
|
|
Acuñado lo único que faltaba: **el paso `full` de la escala de radio**
|
|
|
(`[data-rounded='full']` leía el primitivo global a pelo). Anotadas 7
|
|
|
identidades (`fit-content` × 2, el `100 %` de `[data-block]`, los cuatro
|
|
|
`1px` de las cajas sr-only) y **10 ausencias**: los `transparent` de `soft`,
|
|
|
`outline`, `ghost` y `plain` — la variante ES la ausencia de cromo, y diez
|
|
|
claves de `transparent` habrían sido el antipatrón que la doctrina avisa.
|
|
|
|
|
|
Para que la ausencia cuente, **el censo aprende la válvula de recipe-contract
|
|
|
§3 un piso más abajo**: un PRIVADO cuyo valor es un literal CON su razón
|
|
|
escrita es una ausencia firmada, no deuda (`derivesFromPublic` la acepta).
|
|
|
Sin eso, cuatro privados marcaban «no deriva» y seis knobs leían
|
|
|
inalcanzables mientras todas las demás ramas del mismo privado leen un
|
|
|
público. El censo global sube 5 knobs por esto, no por retoque de ratio.
|
|
|
|
|
|
**⚠⚠ EL HALLAZGO.** El último bloque del forward, `[data-button][data-color]`,
|
|
|
resuelve `--button-palette-*` desde el `--palette-*` GLOBAL —que
|
|
|
`[data-color='{tono}']` llena desde `--color-{tono}-*`— y **gana a las reglas
|
|
|
por tono por ORDEN**, con la misma especificidad (0,2,0). Medido sobre
|
|
|
`data-color='risk'`: `--button-risk-solid` no mueve nada, ni en `:root` ni en
|
|
|
el nodo; `--palette-solid` y `--color-risk-solid` en el nodo repintan. Las
|
|
|
siete `primary-*` son el RESPALDO de esa regla y sólo actúan SIN
|
|
|
`data-color`. **49 recetas emiten ese mismo forward y el catálogo tiene 419
|
|
|
claves de tono**; medido igual en `badge` y `callout`. → §13, con el arreglo
|
|
|
propuesto (orden de emisión) y su contrapartida (la jaula del color).
|
|
|
|
|
|
El techo restante son dos filas de canal de valor (`--_button-fill-finish`,
|
|
|
el acabado que el generador deriva por instancia; su dial es del sistema).
|
|
|
|
|
|
**Un error de método que casi cuela**: anclé la clave nueva en la primera
|
|
|
línea `'radius-xl'` del fichero y aterrizó en **`meter`**. Lo delató el
|
|
|
navegador (`--button-radius-full` sin definir ⇒ radio 0). Una inserción se
|
|
|
ancla en el BLOQUE del componente, nunca en una línea de clave.
|
|
|
|
|
|
Instrumento: el guard aprende **`sweepAttr`** (barrer una variante mientras
|
|
|
mide) y a estampar **el tono que la clave nombra**; y el fichero de
|
|
|
excepciones gana **patrones** (`SENTINEL_PATTERN_EXCEPTIONS`), para que una
|
|
|
razón arquitectónica se escriba UNA vez y no 56.
|
|
|
|
|
|
Gates: sonda 0 diffs (416 valores; la demo monta UN botón) · equivalencia del
|
|
|
paso `full` comprobada aparte · centinela 34/106 con el resto adjudicado ·
|
|
|
censo 91 % · audit PASS · suite con el rojo conocido ajeno · rtl 0 · docs 0 ·
|
|
|
captura de las seis variantes + píldora + tono `risk`.
|
|
|
|
|
|
- 2026-08-23 — **`onion-menu` 29 % → 84 %** (7 claves + 5 literales anotados), y
|
|
|
**una regla del recipe que el navegador DESCARTA**. Global 63 %.
|
|
|
|
|
|
Acuñados el color del anillo del sector —UNO para los dos estados: el propio
|
|
|
CSS dice que el hover usa «el mismo color que el anillo de selección, más
|
|
|
claro», y lo que los separa es la opacidad que ya tenía token—, la tipografía
|
|
|
de la etiqueta, el radio y la tinta del disparador y las dos piezas del glifo
|
|
|
`+`→`×`. Dos limpiezas de paso: un `var(--style-label-font-family, var(--style-label-font-family))`
|
|
|
—respaldo de sí mismo, el defecto de context-menu— y dos `var(--radius-full, …)`
|
|
|
con respaldo imposible.
|
|
|
|
|
|
**⚠ `.onion-menu-icon :global(svg)` NO EXISTE**: `:global()` es un envoltorio
|
|
|
de Svelte y esto es un CSS plano, así que el selector es inválido y la regla
|
|
|
entera se descarta. Medido: el glifo computa 14px (el tamaño propio del Icon)
|
|
|
y el `70 %` que el fichero cree pintar no pinta. Acuñé `icon-glyph-size`, el
|
|
|
centinela lo delató y lo RETIRÉ: arreglar el selector mueve píxel. Mismo bug
|
|
|
en `timeline.css:331`; `image-picker.css` ya documentaba la trampa. → §13.
|
|
|
|
|
|
**Tres cegueras del instrumento, dos nuevas y genéricas**:
|
|
|
|
|
|
1. **El guard CERRABA la superficie.** Este menú nace ABIERTO y el clic de
|
|
|
«abrir» lo cerraba — 12 de 20 tokens muertos. Ahora, si hay `openMarker` y
|
|
|
ya casa, no se pulsa nada (8 → 14 de golpe).
|
|
|
2. Sus tripas cuelgan de CLASES, no de `data-onion-*`: sonda y guard las miden
|
|
|
con `extraNodes` (37 nodos en reposo contra 5).
|
|
|
3. **Congelar las transiciones no basta cuando el nodo está ANIMADO**:
|
|
|
`rim-glow-opacity` leía 0,482956 —el valor animado— y parecía muerto;
|
|
|
congelando también la animación computa 0,45 y sigue al token.
|
|
|
|
|
|
Los cuatro tokens del rim son del look `luminous`, **que la demo del
|
|
|
componente no renderiza** (prop de Svelte que emite otro marcado, no hay
|
|
|
atributo que forzar): medidos en `/active/docs/agnt`.
|
|
|
|
|
|
Gates: sonda **0 diffs** en 7.328 valores × 8 estados · centinela 14/19 con
|
|
|
las cinco adjudicadas · censo 84 % · audit PASS · suite con el rojo conocido
|
|
|
ajeno · rtl 0 · docs 0 · `check` sin errores propios · capturas.
|
|
|
|
|
|
- 2026-08-23 — **`field` 73 % → 98 %** (8 claves + 8 literales ANOTADOS) **y sus
|
|
|
18 rojos, medidos**. Global **63 %**. El 2 % que falta es el puente de paleta
|
|
|
(THM-2), que no es deuda.
|
|
|
|
|
|
Es el componente más COMPUESTO del sistema: lo que otras fichas llaman
|
|
|
«préstamo con dueño» se cobra aquí, así que su techo pesa más que el de nadie.
|
|
|
|
|
|
Acuñados el **disparador de control** —el icono que abre el calendario, el
|
|
|
reloj o la muestra, y revela la contraseña: `size`, `radius`, `fg` y sus dos
|
|
|
estados—, el indicador `optional` (gemelo del `required`, que ya tenía token)
|
|
|
y el **lateral de la etiqueta flotante**, que es lo que CORTA el borde bajo el
|
|
|
texto. La caja del disparador se mide en `em` a propósito, así que el token
|
|
|
guarda la RAZÓN (`1.75em`), no un píxel por talla.
|
|
|
|
|
|
**Ocho literales pasan a excepción firmada por IDENTIDAD, no por inflar el
|
|
|
ratio**: cuatro `inline-size: 100%`, dos `line-height: 1` de un glifo suelto y
|
|
|
dos `1em` del icono dentro del disparador (el glifo ES el tamaño del texto).
|
|
|
|
|
|
**Los 20 rojos del guard estaban VIVOS**, y tres enseñan algo:
|
|
|
`disabled-opacity` vive en el CONTROL y el guard leía la raíz;
|
|
|
**`control-placeholder-fg` no leía porque el input de la demo NO TIENE
|
|
|
`placeholder`** —sin atributo no hay caja `::placeholder` y
|
|
|
`getComputedStyle(nd, '::placeholder')` devuelve el estilo del ELEMENTO—; y
|
|
|
`segment-height` es un token de FAMILIA que field posee y los pickers
|
|
|
consumen, además de RESUELTO: desde `:root` no se mueve por diseño (medido en
|
|
|
`/time-picker`: desde el host 28px → 1234px, moviendo la coordenada
|
|
|
`--field-control-height-md` 28px → 992px).
|
|
|
|
|
|
**Instrumento**: el disparador de control no lo monta NINGUNA demo de field,
|
|
|
así que el guard mide ahora `field` sobre DOS rutas (`/field` + `/date-picker`).
|
|
|
|
|
|
Gates: sonda **0 diffs** en 2.280 valores × 8 estados · equivalencia del
|
|
|
disparador comprobada aparte · centinela 48/68 con las 20 adjudicadas · censo
|
|
|
98 % · `--names` 0 · audit PASS · rtl 0 · docs 0 · suite eidos con el rojo
|
|
|
conocido ajeno · `check` sin errores propios · capturas de reposo, invalid,
|
|
|
disabled, etiqueta flotante y disparador.
|
|
|
|
|
|
- 2026-08-23 — **`menubar` 15 % → 88 %** (30 claves, 5 → 35). Global **62 % →
|
|
|
63 %**. Las tres filas que quedan fuera NO son deuda de este eje.
|
|
|
|
|
|
Cosidas la barra (superficie, marco, radio desacoplado de la talla, y las
|
|
|
tres escalas `gap`/`padding`/`height`), el disparador (tinta, tipografía,
|
|
|
escala de `font-size` y de `padding-inline`, el par de la entrada ABIERTA y
|
|
|
la tinta deshabilitada) y el Panel `role=dialog` (tinta + escala). Los pasos
|
|
|
leen el BUNDLE (`--size-{k}-control-height` / `--size-{k}-font-size`), no el
|
|
|
primitivo crudo que el CSS venía consumiendo, y el `calc(var(--space-1) * 0.5)`
|
|
|
del paso `sm` pasa a `var(--space-0-5)` (mismo computado).
|
|
|
|
|
|
**El hueco del panel deja de repetir el valor del padding**: las tres reglas
|
|
|
de `--floating-gap` compensaban el sangrado del disparador con una COPIA del
|
|
|
padding de la barra; ahora leen `--menubar-padding-{k}`, su fuente. No pueden
|
|
|
leer el privado: esas superficies viajan por PORTAL, y un privado de la raíz
|
|
|
no cruza esa frontera (la ley de ayer, aplicada al derecho).
|
|
|
|
|
|
**⚠ El plano `overlay` GANA a la receta — cuarta prueba de §12.9, y la
|
|
|
primera con MECANISMO.** Acuñé `panel-font-family` y `panel-line-height`; el
|
|
|
centinela las dio muertas. Medido: `[data-depth='overlay']` declara las dos
|
|
|
con la MISMA especificidad (0,1,0) y más tarde en la cascada, así que gana,
|
|
|
mientras `panel-fg` y `panel-font-size-*` —del mismo bloque— sí alcanzan.
|
|
|
Retiradas del contrato, devueltas a su fuente literal con la razón en el CSS.
|
|
|
**Mientras §12.9 no se firme, un token de tipografía en cualquier superficie
|
|
|
`overlay` miente**, y eso vale para los veinte componentes del empate.
|
|
|
|
|
|
**El hover no se acuña: es del eje navigation-menu.** `background:
|
|
|
var(--color-surface-overlay)` sobre el disparador mata la capa del sistema
|
|
|
—medido: `background-image` computa `none` en hover con `--state-hover`
|
|
|
vivo—, por las dos razones que `navigation-menu.css` ya documenta al haber
|
|
|
retirado esa misma regla: el shorthand resetea `background-image`, y la regla
|
|
|
del arquetipo va en `:where()` (especificidad CERO). Acuñar `hover-trigger-bg`
|
|
|
habría fosilizado la invención. → §13.
|
|
|
|
|
|
**Instrumento**: la barra suelta DOS superficies y el Panel —el que lleva sus
|
|
|
knobs— cuelga de la entrada «Format», no de la primera; sonda (`OPEN_TRIGGER`)
|
|
|
y guard (`openWith`) aprenden a abrir la que toca. Y el guard necesitó
|
|
|
`openMarker`: su comprobación de «ya está abierto» busca `[data-{c}-content]`,
|
|
|
que aquí no existe, así que volvía a pulsar el disparador antes de cada token
|
|
|
y CERRABA el panel.
|
|
|
|
|
|
Gates: sonda **0 diffs** en 1.470 valores × 8 estados · centinela 34/35 (la
|
|
|
deshabilitada adjudicada) · censo 88 % · `--names` 0 · audit PASS · rtl 0 ·
|
|
|
docs 0 · suite eidos con el rojo conocido ajeno · `check` sin errores propios
|
|
|
· capturas de barra, tallas, menú y panel.
|
|
|
|
|
|
- 2026-08-23 — **Los dos rojos que quedaban del bloque viejo, medidos: `metrics`
|
|
|
(18) y `color-picker` (25). Los dos guards en verde; sin cambios de código.**
|
|
|
|
|
|
**`metrics`: los 18 están VIVOS, uno por uno.** Ninguno miente — lo que
|
|
|
faltaba era el escenario: seis piden el paso `xxl` (la demo llega a `xl`),
|
|
|
dos el icono SIN `data-color` (el defecto que sólo pinta cuando no hay
|
|
|
color, y todos los iconos de la demo llevan uno), dos las formas `circle` /
|
|
|
`square` (la demo monta `rounded`), cuatro la fila de acciones (no montada),
|
|
|
uno el gráfico en `end` (la demo los coloca `full`), uno el borde de la
|
|
|
variante `outline`, y **dos el sello de sema durante el hold**
|
|
|
(`data-event-family=signal` + `phase=active`): el destello del valor se mide
|
|
|
estampando el sello a mano, porque cuando el guard lee ya se ha ido.
|
|
|
|
|
|
**`color-picker`: 23 de 25 vivos, y los otros dos son un DEFECTO REAL —
|
|
|
el eje `size` muere en el portal.** `--_color-picker-content-width` se
|
|
|
declara TRES veces y no lo consume NADIE: la anchura del panel la fija
|
|
|
`--_popover-content-width-override` cableada al paso `md`, así que un picker
|
|
|
`sm` y uno `lg` abren el mismo panel de 344 px. Lo mismo con las muestras
|
|
|
dentro del panel (`--_color-picker-swatch-size` clavado a `md`): fuera del
|
|
|
portal los tres pasos alcanzan (20 / 24 / 28 px), dentro sólo el `md`. La
|
|
|
causa es una sola y vale como ley: **el portal es una frontera de cascada —
|
|
|
un privado declarado en la raíz del componente no la cruza.** → §13, porque
|
|
|
arreglarlo mueve píxel en `sm` y `lg`.
|
|
|
|
|
|
Tres cegueras del instrumento, medidas y anotadas: **el guard congela las
|
|
|
transiciones y `transition-duration` / `transition-ease` SON la transición**
|
|
|
(sin congelar: 0.12s → 11.5s) — es genérico, cualquier componente con esos
|
|
|
dos públicos los reportará muertos; **una lectura inmediata de una propiedad
|
|
|
en transición devuelve el valor VIEJO**, que es lo que hacía ilegible el
|
|
|
fondo del cuentagotas; y **la demo pisa el cuentagotas con su propia regla
|
|
|
de ámbito** (`.cp-tools-row` le pone `inline-size:auto` y `background`), así
|
|
|
que sus dos tokens sólo se pueden medir devolviéndole el consumo.
|
|
|
|
|
|
- 2026-08-22 — **`drawer`: los 24 rojos que arrastraba, medidos uno a uno — y
|
|
|
uno era un DEFECTO REAL.** El guard queda en verde; sin cambios de código.
|
|
|
|
|
|
**EL VELO DEL CAJÓN NO PINTA.** Su regla es
|
|
|
`color-mix(in srgb, var(--drawer-overlay-bg) var(--drawer-overlay-opacity), transparent)`
|
|
|
y **soma escribe `--drawer-overlay-opacity: 1` INLINE** —su progreso de
|
|
|
arrastre, un número sin unidad—. `color-mix` exige ahí un PORCENTAJE: con
|
|
|
`1` la función entera es inválida y el fondo cae a `transparent`. Medido
|
|
|
(`rgba(0, 0, 0, 0)` en el velo abierto; con `80%` en el nodo, pinta) y VISTO
|
|
|
en captura: el fondo tras el cajón sale desenfocado pero sin atenuar. Mueve
|
|
|
píxel y toca soma, así que va a §13 con su lección: **un valor que soma
|
|
|
escribe inline y una receta consume tiene que compartir UNIDAD**, o el fallo
|
|
|
es silencioso.
|
|
|
|
|
|
El segundo hallazgo: **las tallas son canal de valor en el eje que manda** —
|
|
|
soma escribe `width`/`height` inline según el lado, así que
|
|
|
`content-width-*` no gana desde `:root` en un cajón izquierda/derecha (el
|
|
|
eje cruzado sí: `height-sm` 260px → 976px). Misma clase que el `item-gap`
|
|
|
de carousel, pero aquí el token sigue siendo la fuente del valor que soma
|
|
|
resuelve: retirar o no es firma.
|
|
|
|
|
|
Los otros 22 son lo esperable y quedan medidos: el asa (no montada, y su
|
|
|
tamaño INTERCAMBIA ejes según el lado), el anillo de arrastre, el padding
|
|
|
`full`, la cabecera y el pie opcionales, la z de la variante inline.
|
|
|
|
|
|
- 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 | – |
|