37 claves en el bloque `textarea` de `recipes/base.ts` (fusionadas con el
forward de paleta que ya estaba). Censo 0 % → 80 %, con **cero globales y cero
literales de valor**: los 16 privados leen ya su público. Global 46 %, sin
contrato 48 → 47.
LO QUE LA MEDICIÓN CAMBIÓ. La §4 generada proponía 35 tokens; cuatro eran
colisiones y uno habría movido el default:
1. `count-font-size-{k}` × 5 BORRABA el factor 0.85. El CSS calcula
`calc(var(--_textarea-font-size) * 0.85)` y la propuesta ponía el tipo del
input crudo en las cinco tallas: el contador habría crecido un 18 %.
D-TH.5 lo prohíbe. Queda en UN token con el `calc` sobre el público del
input — la escala se escribe una vez y la talla la resuelve el input. Pide
`scope: 'host'`: emitido en `:root` su dependencia no existe, y el contrato
de scope de la receta lo caza (lo cazó).
2. `input-fg` ⚠ eran DOS knobs (texto y placeholder) → `input-fg` +
`input-placeholder-fg`. Igual `count-fg` → `count-fg` + `overflow-count-fg`.
3. `input-border` ⚠ NO eran dos knobs sino UNA variable con su swap de paleta,
y el nombre estaba mal: es el borde de FOCO → `focus-input-border`. El de
reposo es otro token, que la propuesta ni listó por viajar en el atajo.
4. `ghost-input-border` se RETIRA: la regla ghost lee ese mismo conmutador —
sería un valor con dos nombres.
Bundle, medido: la tipografía casa 1:1 en las cinco (lee `--size-{k}-font-size`);
el spacing NO — `padding-inline` casa salvo en xs (8px vs 6px) y `padding-block`
sólo en xs. Verbatim y documentado: un campo multi-línea respira más, y el
spacing queda fuera del guard del bundle. Resueltos sin `parts` (el `data-size`
va en `[data-textarea]` y el input hereda); fuera los cuatro `[data-size]`.
DOS ARREGLOS DEL INSTRUMENTO, los dos por medición y no por sospecha:
- **El guard medía con el PUNTERO encima.** `reopen()` corre antes de CADA
token y hace clic en `[data-{c}-input]` cuando el componente no tiene parte
`content`; el `blur()` de la revisión adversarial quitaba el foco pero no el
puntero, así que `:hover` casaba toda la corrida y toda regla de hover pisaba
a sus vecinas. Costaba TRES falsos negativos aquí. Con `mouse.move(0,0)`
tras cada blur, `input-border` revive solo (31 → 32).
- **`::placeholder` SÍ se lee con `getComputedStyle`.** La nota de §13 que
decía lo contrario nunca se comprobó; medido, el color centinela vuelve tal
cual. Entra en el snapshot (32 → 33) y deja STALE la entrada
`command.input-placeholder-fg`, que el guard señaló y se ha borrado.
Corridos los DIEZ componentes con ledger tras los dos arreglos: ningún otro
cambia, un único STALE, el previsto.
Y un hallazgo de píxel que NO se toca aquí (→ next-features §13): el borde de
foco sólo se ve con Tab. Las tres reglas de `border-color` del input están
ordenadas al revés de lo que significan — hover (0,4,0) > foco (0,3,0) >
invalid (0,2,0) — y hacer clic deja el puntero encima por definición, así que
gana el hover; un campo inválido pierde su borde rojo al enfocarlo o al pasar
el ratón. El anillo de foco del sistema sí se ve siempre, así que no es fallo
de accesibilidad. Arreglarlo mueve píxel.
El 20 % que falta son las dos declaraciones que consumen
`--_textarea-border-focus`, privado a propósito: es el conmutador de una
variable con dos fuentes (el público y el forward THM-2), y aplanarlo exigiría
duplicar la regla por color. Mismo techo que `listbox` paga por consumir bien
su capa. Mi propio veredicto predecía ~100 % y la medición lo corrigió a 80 %.
Artefactos y gates:
- Sonda antes/después = 0 diffs en 1.247 valores × 8 estados (el 0.85 intacto,
que era el riesgo). Determinismo verificado: dos corridas, 0 diffs.
- R-5.4: 33/37; los 4 mudos adjudicados en el ledger con su medición (foco,
invalid y las dos del contador rebasado — estados que la demo no monta).
- censo --only 80 % · component:audit PASS · eidos-lint invalid 0, class-hooks 0
· suite eidos sin rojos nuevos (el conocido skin-media-player) · rtl:check 0
· docs:check 0 · check por fichero limpio (72 globales, ninguno mío).
- README con su «Talla y tema» y tab `Tokens` en la demo (37 claves; el panel
muestra el contador computando `calc(calc(1rem * 1) * 0.85)`).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Consumidos y **no declarados en el CSS** (vienen de `base.ts` o de un estilo inline del wrapper): `--_textarea-palette-solid`.
## 4. Propuesta de corrección
- **Tiene eje `size`**: los tokens dimensionales van por talla (`{part}-{eje}-{k}`) apuntando al bundle `--size-{k}-*`, nunca al primitivo crudo (theming §5; el guard `recipe-css-contract` prohíbe el primitivo).
### 4.1 Tokens a declarar en `lib/recipes/base.ts` (35)
### 4.1 Tokens a declarar en `lib/recipes/base.ts` (2)
Valor **verbatim** del CSS de hoy: el default no se mueve, sólo cambia quién
puede moverlo. Nombres derivados de recipe-contract §1 (ejes lógicos, talla
@ -98,63 +62,17 @@ no distingue lo que debería — se marca `⚠`.
- **⚠ decisión: `100%` es un valor identidad o geometría de layout, no un knob de tema — el perímetro de «knob» es D-TH.2, sin firmar** — 2: `inline-size`.
- **⚠ decisión: `border` es shorthand o eje físico — hay que partirlo en ejes lógicos antes de nombrarlo (recipe-contract §1, R-4.4)** — 1: `border`.
- **⚠ decisión: `1` es un valor identidad o geometría de layout, no un knob de tema — el perímetro de «knob» es D-TH.2, sin firmar** — 1: `line-height`.
### 4.3 Avisos sobre los tokens propuestos (13)
- **el privado `--_textarea-gap` debe pasar a leer este público (o desaparecer)** — `--textarea-gap`
- **el privado `--_textarea-padding-block` debe pasar a leer este público (o desaparecer)** — `--textarea-input-padding-block-md`, `--textarea-input-padding-block-xs`, `--textarea-input-padding-block-sm`, `--textarea-input-padding-block-lg`, `--textarea-input-padding-block-xl`
- **el privado `--_textarea-padding-inline` debe pasar a leer este público (o desaparecer)** — `--textarea-input-padding-inline-md`, `--textarea-input-padding-inline-xs`, `--textarea-input-padding-inline-sm`, `--textarea-input-padding-inline-lg`, `--textarea-input-padding-inline-xl`
- **el privado `--_textarea-radius` debe pasar a leer este público (o desaparecer)** — `--textarea-input-radius`
- **el privado `--_textarea-bg` debe pasar a leer este público (o desaparecer)** — `--textarea-input-bg`
- **el privado `--_textarea-color` debe pasar a leer este público (o desaparecer)** — `--textarea-input-fg`
- **el privado `--_textarea-font-size` debe pasar a leer este público (o desaparecer)** — `--textarea-input-font-size-md`, `--textarea-input-font-size-xs`, `--textarea-input-font-size-sm`, `--textarea-input-font-size-lg`, `--textarea-input-font-size-xl`, `--textarea-count-font-size-md`, `--textarea-count-font-size-xs`, `--textarea-count-font-size-sm`, `--textarea-count-font-size-lg`, `--textarea-count-font-size-xl`
- **el privado `--_textarea-line-height` debe pasar a leer este público (o desaparecer)** — `--textarea-input-line-height`
- **el privado `--_textarea-border-hover` debe pasar a leer este público (o desaparecer)** — `--textarea-hover-input-border`
### 4.3 Avisos sobre los tokens propuestos (1)
- **el privado `--_textarea-border-focus` debe pasar a leer este público (o desaparecer)** — `--textarea-input-border`, `--textarea-ghost-input-border`
- **el privado `--_textarea-placeholder` debe pasar a leer este público (o desaparecer)** — `--textarea-input-fg`
- **el privado `--_textarea-count-color` debe pasar a leer este público (o desaparecer)** — `--textarea-count-fg`
- **el privado `--_textarea-count-overflow` debe pasar a leer este público (o desaparecer)** — `--textarea-count-fg`
### 4.4 Lo que hay que comprobar a mano (PLAN-theming §1.3 · §7.4)
@ -168,6 +86,67 @@ no distingue lo que debería — se marca `⚠`.
<!-- veredicto:start -->
_(pendiente — lo escribe el autor; se conserva al regenerar)_
**Medido 2026-08-21** (sonda ×2 sobre el mismo código = 0 diffs en 1.247
valores · 8 estados). La §4 propone 35 tokens y **cuatro de ellos son
colisiones que hay que partir o retirar**, más un error que cambiaría el
default. Corregido queda en 37 claves.
1. **`count-font-size-{k}`× 5 BORRARÍA el factor 0.85 — es el error grave de
la propuesta.** El CSS calcula `calc(var(--_textarea-font-size) * 0.85)`
(con su anotación `/* literal: */`), y la §4 propone cinco tokens con el
font-size del INPUT crudo: el contador crecería un 18 % en las cinco
tallas. D-TH.5 lo prohíbe. La corrección: **UN** token
`count-font-size` que conserva el `calc` sobre el público del input, así
sigue la talla sin repetir la escala. Mismo reparto que `tree-grid.guide-fg`
— el knob es el valor, la construcción se queda en la receta.
2. **`input-fg` ⚠ son DOS knobs**: la tinta del texto
(`--color-content-primary`) y la del placeholder
(`--color-content-muted`). El clasificador las fundió por caer ambas sobre
la parte `input`. → `input-fg` + `input-placeholder-fg` (precedente
'consumed only under [data-focused], which the guard blurs away ON PURPOSE (the click-focus poisoning fix); focused by hand with the pointer parked → reaches (rgb(4,5,6))',
'invalid-input-border':
'consumed only under [data-invalid]; the demo boots valid. Forced by hand 2026-08-21 → reaches (rgb(7,8,9))',
'overflow-count-fg':
'the count only carries [data-overflow] past maxLength (280 chars); forced → reaches (rgb(13,14,15))',
'overflow-count-font-weight':
'the count only carries [data-overflow] past maxLength (280 chars); forced → reaches (font-weight 333)'
},
'grid-list':{
'invalid-border':
'consumed only under [data-invalid]; the demo boots with its invalid control off, so the rule never matches at measurement. Toggled by hand 2026-08-21 → reaches (oklch(0.9555 0.0207 13.86) → rgb(1,2,3))'