9 claves fusionadas en el bloque `skeleton` de `recipes/base.ts` (donde ya
vivía el forward de paleta). Censo 0 % → 45 %, cero globales.
Nueve de sus once knobs pasaban por privado, y la lectura correcta es que **dos
de esos privados NO son deuda: son conmutadores**. `--_skeleton-bg` y
`--_skeleton-highlight` tienen DOS fuentes cada uno según haya `data-color` —
la mezcla neutra cross-mode (un `color-mix` hacia `neutral-solid`, para que el
placeholder siga siendo un gris visible en los dos modos: el `neutral-track`
desnudo desaparece sobre una superficie clara) o el forward de paleta.
Aplanarlos exigiría duplicar cada regla por color, así que se quedan — mismo
criterio que el borde de foco de textarea y la tinta de spinner. Son el grueso
del 55 % que no alcanza, y es honesto.
- **Una coordenada por talla** (`size`) gobierna el alto del bloque, el diámetro
del círculo (vía `aspect-ratio`) y el hueco entre líneas de la forma `text`.
Ese hueco es `calc(size * 0.5)`: una PROPORCIÓN, construcción, no un knob.
- **El radio es por FORMA, no por talla**: `radius-md` en `rect` y `50%` en
`circle`, donde el `50%` es identidad (un círculo es redondo) — el knob es
sólo el del rectángulo. La línea de la forma `text` lleva el suyo.
- `duration` entra al contrato en vez de seguir en `1.4s` a pelo, igual que se
hizo con el spinner (§13).
Artefactos y gates:
- Sonda antes/después = 0 diffs en 203 valores × 7 estados.
- R-5.4: 8/9. `line-radius` adjudicado: sólo la forma `text` renderiza
`[data-skeleton-line]` y la demo monta `rect` (0 líneas, contadas); forzada
la forma, alcanza (4 → 1234px).
- censo --only 45 % · component:audit PASS · suite eidos sin rojos nuevos ·
rtl:check 0 · docs:check 0 · check por fichero limpio.
- README con «Talla y tema» y tab `Tokens` en la demo (9 claves).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
| `--_skeleton-radius` | 3 | `var(--skeleton-radius)`, `50%` | literal, public | no |
Consumidos y **no declarados en el CSS** (vienen de `base.ts` o de un estilo inline del wrapper): `--_skeleton-palette-track`.
## 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` (30)
### 4.1 Tokens a declarar en `lib/recipes/base.ts` (5)
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
@ -70,46 +60,20 @@ 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** — 1: `inline-size`.
### 4.3 Avisos sobre los tokens propuestos (3)
### 4.3 Avisos sobre los tokens propuestos (2)
- **el privado `--_skeleton-bg` debe pasar a leer este público (o desaparecer)** — `--skeleton-bg`, `--skeleton-line-bg`, `--skeleton-bg-image`, `--skeleton-line-bg-image`
- **el privado `--_skeleton-radius` debe pasar a leer este público (o desaparecer)** — `--skeleton-radius`
- **el privado `--_skeleton-size` debe pasar a leer este público (o desaparecer)** — `--skeleton-height`, `--skeleton-height-xs`, `--skeleton-height-sm`, `--skeleton-height-md`, `--skeleton-height-lg`, `--skeleton-height-xl`, `--skeleton-width`, `--skeleton-width-xs`, `--skeleton-width-sm`, `--skeleton-width-md`, `--skeleton-width-lg`, `--skeleton-width-xl`, `--skeleton-gap`, `--skeleton-gap-xs`, `--skeleton-gap-sm`, `--skeleton-gap-md`, `--skeleton-gap-lg`, `--skeleton-gap-xl`, `--skeleton-line-height`, `--skeleton-line-height-xs`, `--skeleton-line-height-sm`, `--skeleton-line-height-md`, `--skeleton-line-height-lg`, `--skeleton-line-height-xl`
### 4.4 Lo que hay que comprobar a mano (PLAN-theming §1.3 · §7.4)
@ -123,6 +87,25 @@ no distingue lo que debería — se marca `⚠`.
<!-- veredicto:start -->
_(pendiente — lo escribe el autor; se conserva al regenerar)_
**Medido 2026-08-22.** Nueve de sus once knobs pasan por privado, y la lectura
correcta es que **dos de esos privados NO son deuda**: son conmutadores.
1. **`--_skeleton-bg` y `--_skeleton-highlight` se quedan privados.** Cada uno
tiene DOS fuentes según haya `data-color`: la mezcla neutra cross-mode
(`color-mix` hacia `neutral-solid`, para que el placeholder siga siendo un
gris visible en los dos modos — el `neutral-track` desnudo desaparece sobre
una superficie clara) o el forward de paleta. Aplanarlos exigiría duplicar
cada regla por color. Mismo patrón que el borde de foco de `textarea` y la
tinta de `spinner`, y son el ~18 % que no alcanza.
2. **`--_skeleton-size` es la coordenada por talla** y gobierna el alto del
bloque, el diámetro del círculo (via `aspect-ratio`) y el hueco entre líneas
de la forma `text` — ese hueco es `calc(size * 0.5)`, una PROPORCIÓN, o sea
construcción, no un knob.
3. **`--_skeleton-radius` no es una coordenada por talla sino por FORMA**:
`radius-md` en `rect`, `50%` en `circle`. El `50%` es identidad (un círculo
es redondo), así que el knob es sólo el del rectángulo. La línea de la forma
`text` tiene el suyo propio, más pequeño.
4. **`duration` entra al contrato** en vez de quedarse en `1.4s` a pelo —
mismo criterio que se aplicó al spinner (`next-features.md` §13).
'the time row is CLASS-hooked (.picker-time-row) and the date-picker demo does not render it; the guard filters nodes by attribute, so it cannot see it either way (§13 class-hook debt). Forced → reaches (gap/padding → 1234px, border 1→9px + rgb(7,8,9), label → rgb(10,11,12) / 99px)'
},
skeleton:{
'line-radius':
"only the `text` shape renders [data-skeleton-line]; the demo mounts `rect` (0 lines, counted). Forced shape='text' → reaches (4 → 1234px)"
},
spinner:{
'bar-radius':
"the demo mounts the RING variant only (0 bars, 0 dots, counted); forced variant='bars' → reaches (1234px)",