# CONTINUE — eje Theming «theme-reach» (handoff, act. 2026-08-20) **Estado: EN EJECUCIÓN.** 7 componentes corregidos, 20 fichas revisadas, el informe de auditoría vivo y regenerable. **Las decisiones D-TH.1…D-TH.8 del plan SIGUEN SIN FIRMAR** — lo hecho hasta ahora es lo que NO depende de ellas. - Fuente viva del método: [`PLAN-theming.md`](./PLAN-theming.md) (§7 el protocolo, sin excepciones). - **Informe por componente**: [`docs/audit/theming/`](../audit/theming/) — un README de conjunto + 170 fichas (162 recetas + 8 sin receta). Cada ficha lleva su análisis, su propuesta y, en §5, el **veredicto** escrito a mano, que sobrevive a la regeneración. ## Por dónde entrar mañana 1. `node --import tsx/esm scripts/theming-census.ts` — debe dar **162 recetas · 5.203 knobs · 1.841 públicos (37 %) · 56 sin contrato**. Si no cuadra, alguien tocó recetas: regenerar el informe (`--report`) antes de nada. 2. Abrir la ficha del componente que toque y leer su **§5 Veredicto**: dice qué de la propuesta es correcto, qué está mal y qué espera firma. Está verificado contra el CSS; la §4 generada NO se sigue a ciegas. 3. Ejecutar con el protocolo §7 entero. **Un componente = un commit.** ## Cola inmediata — ejecutables SIN firma (revisados, con veredicto) Por orden del informe (peor alcance primero): | # | componente | qué hacer | ojo | | --- | ----------------- | ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------- | | 1 | `command` | tokens + talla resuelta | el ⚠ de `radius` es adaptación al Dialog, no colisión; el de `list-padding-inline` es el hueco del scrollbar (patrón `scrollbar-inset` de combobox) | | 2 | `table` | tokens + talla | `root-height-{k}` es la **fila** → `row-height-{k}` al bundle; el prefijo `root-` sobra en el resto | | 3 | `media-player` | renombrar `--_mp-*` + tokens | su acento YA está firmado theme-stable en `base.ts` — no tocarlo; el ⚠ de `bg` son dos knobs (superficie y velo) | | 4 | `tree-grid` | renombrar nada; tokens + talla | `root-bg-image` son las **guías de indentación**: el knob es un color (`guide-color`), los 5 gradientes se quedan en la receta | | 5 | `gradient-picker` | renombrar `--gp-*` + tokens | el ⚠ de `content-width` es **por talla** (20/18/22rem) | | 6 | `listbox` | tokens | **retirar** la fila `font-size = var(--list-font-size)`: es público de la capa `list-surface` | | 7 | `carousel` | tokens + talla | los `indicator-width-{k}` son geometría propia (rem), ni bundle ni desviación | | 8 | `feed` | tokens + talla | el ⚠ del título es **por talla**; el feed tipa por debajo del 1:1 (md → sm), verbatim | ## Esperan FIRMA del autor (no ejecutar) - **Decisión de familia calendar** (`theming-audit.md` §B) → desbloquea `range-calendar`, `month-grid`, `year-grid` (gemelos byte-a-byte) y la mitad de `date-range-picker`. Sin ella, tokenizarlos sería acuñar ~150 alias de `--calendar-*` — lo que la purga del changelog §39 mató. - **Mandato de composición de Field** (`theming-audit.md` §5.3-3) → la mitad de `time-picker`, `time-range-picker`, `date-range-picker` y dos knobs de `field-langs`. - **D-TH.2 (perímetro del knob)** → `heading` y toda la familia tipográfica (B5): su superficie de tema ES la capa de named styles; propuesta escrita en su ficha (medir `--style-*` como sistema transversal, no acuñar `--heading-*`). - **hover → capa de estado** en `combobox` (3 knobs) y donde reaparezca: mueve píxel, así que es decisión, no limpieza. - Las **D-TH.1…D-TH.8** del plan §4, que siguen sin firmar (R-5 dura, perímetro, familias, orden, vocabulario, graduación a `error`, demo). ## Lo ejecutado (censo antes → después) | componente | alcance | commit | | --------------------------- | -------------: | ----------- | | `gradient-builder` (piloto) | 0 % → **80 %** | `3cdb5b5f0` | | `combobox` | 0 % → **76 %** | `cef2d32f1` | | `natural-time-picker` | 0 % → **61 %** | `e774ca7e8` | | `date-range-picker` | 0 % → **42 %** | `07778b597` | | `time-range-picker` | 0 % → **19 %** | `68eb8af26` | | `time-picker` | 0 % → **18 %** | `e4fcdd62e` | | `proof-of-human` | 0 % → **14 %** | `ae91573c3` | Global del catálogo: **33 % → 37 %** (1.621 → 1.841 knobs públicos). Informe + instrumento: `2591ec2f0`; revisión de las fichas 11-20: `3bfe0d413`. ## El instrumental (vive en `scripts/`, prefijo `__` = temporal del eje) ```bash node scripts/__theming-probe.ts # sonda antes/después node scripts/__theming-diff.ts # el gate: diff VACÍO node scripts/__theming-sentinel.ts # ¿alcanza cada token? node scripts/__shot.ts # captura 2× del stage ``` Se ejecutan **con `node`, no con `tsx`** (tsx inyecta helpers que rompen `page.evaluate`) y **desde la raíz** del repo, contra el dev server en `localhost:5173`. Los `scripts/__dbg*.ts` y `__sentinel-targeted*.ts` son de un solo uso (verificaciones dirigidas de ayer); no se commitean. ## Lo que el instrumento aprendió a fuerza de mentir - **La sonda congela `transition`, NUNCA `animation`**: una propiedad transicionada devuelve su valor INICIAL justo tras escribir el token (un token vivo parecía muerto), pero congelar `animation` impide que Presence monte el panel — y entonces mides un popup que no existe. - **Un token RESUELTO no se mueve desde `:root`**: se declara en `[data-{c}]` o en su parte, así que el tema mueve la **coordenada**. El centinela escribe en `:root` **y** en el host, y aun así los resueltos salen «muertos» por diseño. - **Un panel portalado no ve el ámbito del componente**: sus tokens se emiten en `:root` (o con `parts`), y un override scoped no lo alcanza. - **La demo puede tapar el componente**: `proof-of-human` declara su propio `min-block-size` y fondo sobre el stage — ahí el centinela no sirve, y se dice. - **Un valor centinela igual al real lee como «no efecto»** (`9999px` contra un `--radius-full` que ya era 9999px). ## Trampas que costaron un commit cada una (no repetirlas) - **Clave duplicada en `recipes/base.ts`**: añadir un bloque que ya existía lo descarta **en silencio** (gana la segunda). Guard antes de generar: `grep -oE "^\t'?[a-z0-9-]+'?: \{" src/uix/eidos/lib/recipes/base.ts | sed "s/[\t':{ ]//g" | sort | uniq -d` → debe salir vacío. - **Dejar vivos los bloques `[data-…][data-size='…']` del CSS** al emitir la cascada por el TSC: pisan los tokens nuevos con los valores viejos, y el diff de computed da 0 **porque la ruta vieja sigue mandando**. Lo cazó el centinela. - **Correr `component:audit` DESPUÉS de `prettier`, no antes**: al renombrar un privado a su nombre completo, prettier partió tres declaraciones en varias líneas y **separó la anotación `/* literal: … */` de su valor** — R-2.1 la exige en la MISMA línea, así que el guard pasó a ver colores crudos donde antes veía excepciones anotadas. Se arregla con `/* prettier-ignore */` sobre la declaración: NO acortando el comentario ni tocando el valor. Regresión real en `natural-time-picker`, cazada un día tarde por correr el audit antes del formateo. - **Backticks en `node -e "…"` desde bash**: se ejecutan y vacían el texto. Para editar markdown con código, usar el editor, no el shell. - **`prettier --write` sobre un README** no protege de que un Edit se coma un encabezado: comprobar `grep -c "^## Gaps"` después de insertar secciones. - Lo de ayer sigue vigente: medir el nodo que el usuario señala (píxel arriba), el hover es del sistema, el default no cambia, rama compartida sin `stash` ni `--amend`, `check` **por fichero**. ## Fuentes - Plan y decisiones: [`PLAN-theming.md`](./PLAN-theming.md) · informe: [`docs/audit/theming/README.md`](../audit/theming/README.md). - Auditoría del SISTEMA (fase 1, cerrada): [`theming-audit.md`](../audit/theming-audit.md) — §B familia calendar, §5.3-3 mandato de Field. - Doctrina: `docs/theming/reference.md` (§5 talla, §6 nombres, §38 capa de estado) · `docs/canon/recipe-contract.md` · `docs/canon/tsc.md` · `docs/architecture/eidos.md` (vertebración tipográfica, columna `unused`) · `src/uix/eidos/components/README.md` (capas compartidas). - Precedente de la forma por talla: [`PLAN-sidebar.md`](./PLAN-sidebar.md) §3 + F3 y el bloque `sidebar` de `recipes/base.ts`.