@ -5,14 +5,14 @@
> Vista de conjunto: [README ](./README.md ) · método y protocolo:
> [`PLAN-theming.md` ](../../process/PLAN-theming.md ) §1, §2, §7.
- **Medido** : 2026-08-22 · **Alcance** : **6 0%** — 42 de 70 knobs por token público
- **Knobs de apariencia** : 72 — público 42 · privado 0 · global 24 · literal 4 · sistema 2 · excepción 0 _(los dos últimos, fuera del ratio)_
- **Contrato hoy** (`lib/recipes/base.ts`): 39 pública(s) — `gap` , `horizontal-basis` , `padding-xs` , `padding-sm` , `padding-md` , `padding-lg` , `padding-xl` , `radius` , `border-width` , `border` , `hover -border`, `bg` , `content-gap` , `text-gap` , `title-font-family` , `title-font-size-xs` , `title-font-size-sm` , `title-font-size-md` , `title-font-size-lg` , `title-font-size-xl` , `title-font-weight` , `title-line-height` , `title-fg` , `description-font-size-xs` , `description-font-size-sm` , `description-font-size-md` , `description-font-size-lg` , `description-font-size-xl` , `description-line-height` , `description-fg` , `icon-size-xs` , `icon-size-sm` , `icon-size-md` , `icon-size-lg` , `icon-size-xl` , `icon-fg` , `transition-duration` , `transition-ease` , `disabled-opacity`
- **Medido** : 2026-08-22 · **Alcance** : **6 1%** — 43 de 70 knobs por token público
- **Knobs de apariencia** : 72 — público 43 · privado 0 · global 23 · literal 4 · sistema 2 · excepción 0 _(los dos últimos, fuera del ratio)_
- **Contrato hoy** (`lib/recipes/base.ts`): 40 pública(s) — `gap` , `horizontal-basis` , `padding-xs` , `padding-sm` , `padding-md` , `padding-lg` , `padding-xl` , `radius` , `border-width` , `border` , `hover -border`, `invalid -border`, `bg` , `content-gap` , `text-gap` , `title-font-family` , `title-font-size-xs` , `title-font-size-sm` , `title-font-size-md` , `title-font-size-lg` , `title-font-size-xl` , `title-font-weight` , `title-line-height` , `title-fg` , `description-font-size-xs` , `description-font-size-sm` , `description-font-size-md` , `description-font-size-lg` , `description-font-size-xl` , `description-line-height` , `description-fg` , `icon-size-xs` , `icon-size-sm` , `icon-size-md` , `icon-size-lg` , `icon-size-xl` , `icon-fg` , `transition-duration` , `transition-ease` , `disabled-opacity`
- **Eje `size`** : sí · **ficheros** : `radio-cards.css`
## 1. Knobs fuera de alcance
### 1.1 Directo a primitivo global (24 )
### 1.1 Directo a primitivo global (23 )
| # | fichero:línea | selector | propiedad | valor |
| ---: | --- | --- | --- | --- |
@ -20,26 +20,25 @@
| 2 | `radio-cards.css:98` | `[data-radio-cards] [data-radio-cards-item][data-state='checked']:hover:not([data-disabled]):not([data-readonly])` | `background` | `color-mix(in srgb, var(--_radio-group-palette-solid) 12%, var(--color-surface-default))` ⤴ prestado de `radio-group` |
| 3 | `radio-cards.css:116` | `[data-radio-cards] [data-radio-cards-item][data-state='checked']` | `border-color` | `var(--_radio-group-palette-solid)` ⤴ prestado de `radio-group` |
| 4 | `radio-cards.css:117` | `[data-radio-cards] [data-radio-cards-item][data-state='checked']` | `background` | `color-mix(in srgb, var(--_radio-group-palette-solid) 7%, var(--color-surface-default))` ⤴ prestado de `radio-group` |
| 5 | `radio-cards.css:131` | `[data-radio-cards][data-invalid] [data-radio-cards-item]` | `border-color` | `var(--color-threat-element)` |
| 6 | `radio-cards.css:169` | `[data-radio-cards] [data-radio-cards-item][data-state='checked'] [data-radio-cards-icon]` | `color` | `var(--_radio-group-palette-solid)` ⤴ prestado de `radio-group` |
| 7 | `radio-cards.css:234` | `[data-radio-cards-indicator]` | `inline-size` | `var(--radio-group-item-size-md)` ⤴ prestado de `radio-group` |
| 8 | `radio-cards.css:235` | `[data-radio-cards-indicator]` | `block-size` | `var(--radio-group-item-size-md)` ⤴ prestado de `radio-group` |
| 9 | `radio-cards.css:236` | `[data-radio-cards-indicator]` | `border` | `var(--radio-group-indicator-border-width) solid var(--radio-group-indicator-border)` ⤴ prestado de `radio-group` |
| 10 | `radio-cards.css:237` | `[data-radio-cards-indicator]` | `border-radius` | `var(--radius-full)` |
| 11 | `radio-cards.css:238` | `[data-radio-cards-indicator]` | `background` | `var(--radio-group-indicator-bg)` ⤴ prestado de `radio-group` |
| 12 | `radio-cards.css:249` | `[data-radio-cards-indicator]::after` | `border-radius` | `var(--radius-full)` |
| 13 | `radio-cards.css:250` | `[data-radio-cards-indicator]::after` | `background` | `var(--_radio-group-palette-solid)` ⤴ prestado de `radio-group` |
| 14 | `radio-cards.css:256` | `[data-radio-cards][data-size='xs'] [data-radio-cards-indicator]` | `inline-size` | `var(--radio-group-item-size-xs)` ⤴ prestado de `radio-group` |
| 15 | `radio-cards.css:257` | `[data-radio-cards][data-size='xs'] [data-radio-cards-indicator]` | `block-size` | `var(--radio-group-item-size-xs)` ⤴ prestado de `radio-group` |
| 16 | `radio-cards.css:260` | `[data-radio-cards][data-size='sm'] [data-radio-cards-indicator]` | `inline-size` | `var(--radio-group-item-size-sm)` ⤴ prestado de `radio-group` |
| 17 | `radio-cards.css:261` | `[data-radio-cards][data-size='sm'] [data-radio-cards-indicator]` | `block-size` | `var(--radio-group-item-size-sm)` ⤴ prestado de `radio-group` |
| 18 | `radio-cards.css:264` | `[data-radio-cards][data-size='lg'] [data-radio-cards-indicator]` | `inline-size` | `var(--radio-group-item-size-lg)` ⤴ prestado de `radio-group` |
| 19 | `radio-cards.css:265` | `[data-radio-cards][data-size='lg'] [data-radio-cards-indicator]` | `block-size` | `var(--radio-group-item-size-lg)` ⤴ prestado de `radio-group` |
| 20 | `radio-cards.css:268` | `[data-radio-cards][data-size='xl'] [data-radio-cards-indicator]` | `inline-size` | `var(--radio-group-item-size-xl)` ⤴ prestado de `radio-group` |
| 21 | `radio-cards.css:269` | `[data-radio-cards][data-size='xl'] [data-radio-cards-indicator]` | `block-size` | `var(--radio-group-item-size-xl)` ⤴ prestado de `radio-group` |
| 22 | `radio-cards.css:274` | `[data-radio-cards] [data-radio-cards-item][data-state='checked'] [data-radio-cards-indicator]` | `border-color` | `var(--_radio-group-palette-solid)` ⤴ prestado de `radio-group` |
| 23 | `radio-cards.css:281` | `[data-radio-cards] [data-radio-cards-item][data-disabled] [data-radio-cards-indicator]` | `border-color` | `var(--radio-group-disabled-indicator-border)` ⤴ prestado de `radio-group` |
| 24 | `radio-cards.css:282` | `[data-radio-cards] [data-radio-cards-item][data-disabled] [data-radio-cards-indicator]` | `background` | `var(--radio-group-disabled-indicator-bg)` ⤴ prestado de `radio-group` |
| 5 | `radio-cards.css:169` | `[data-radio-cards] [data-radio-cards-item][data-state='checked'] [data-radio-cards-icon]` | `color` | `var(--_radio-group-palette-solid)` ⤴ prestado de `radio-group` |
| 6 | `radio-cards.css:234` | `[data-radio-cards-indicator]` | `inline-size` | `var(--radio-group-item-size-md)` ⤴ prestado de `radio-group` |
| 7 | `radio-cards.css:235` | `[data-radio-cards-indicator]` | `block-size` | `var(--radio-group-item-size-md)` ⤴ prestado de `radio-group` |
| 8 | `radio-cards.css:236` | `[data-radio-cards-indicator]` | `border` | `var(--radio-group-indicator-border-width) solid var(--radio-group-indicator-border)` ⤴ prestado de `radio-group` |
| 9 | `radio-cards.css:237` | `[data-radio-cards-indicator]` | `border-radius` | `var(--radius-full)` |
| 10 | `radio-cards.css:238` | `[data-radio-cards-indicator]` | `background` | `var(--radio-group-indicator-bg)` ⤴ prestado de `radio-group` |
| 11 | `radio-cards.css:249` | `[data-radio-cards-indicator]::after` | `border-radius` | `var(--radius-full)` |
| 12 | `radio-cards.css:250` | `[data-radio-cards-indicator]::after` | `background` | `var(--_radio-group-palette-solid)` ⤴ prestado de `radio-group` |
| 13 | `radio-cards.css:256` | `[data-radio-cards][data-size='xs'] [data-radio-cards-indicator]` | `inline-size` | `var(--radio-group-item-size-xs)` ⤴ prestado de `radio-group` |
| 14 | `radio-cards.css:257` | `[data-radio-cards][data-size='xs'] [data-radio-cards-indicator]` | `block-size` | `var(--radio-group-item-size-xs)` ⤴ prestado de `radio-group` |
| 15 | `radio-cards.css:260` | `[data-radio-cards][data-size='sm'] [data-radio-cards-indicator]` | `inline-size` | `var(--radio-group-item-size-sm)` ⤴ prestado de `radio-group` |
| 16 | `radio-cards.css:261` | `[data-radio-cards][data-size='sm'] [data-radio-cards-indicator]` | `block-size` | `var(--radio-group-item-size-sm)` ⤴ prestado de `radio-group` |
| 17 | `radio-cards.css:264` | `[data-radio-cards][data-size='lg'] [data-radio-cards-indicator]` | `inline-size` | `var(--radio-group-item-size-lg)` ⤴ prestado de `radio-group` |
| 18 | `radio-cards.css:265` | `[data-radio-cards][data-size='lg'] [data-radio-cards-indicator]` | `block-size` | `var(--radio-group-item-size-lg)` ⤴ prestado de `radio-group` |
| 19 | `radio-cards.css:268` | `[data-radio-cards][data-size='xl'] [data-radio-cards-indicator]` | `inline-size` | `var(--radio-group-item-size-xl)` ⤴ prestado de `radio-group` |
| 20 | `radio-cards.css:269` | `[data-radio-cards][data-size='xl'] [data-radio-cards-indicator]` | `block-size` | `var(--radio-group-item-size-xl)` ⤴ prestado de `radio-group` |
| 21 | `radio-cards.css:274` | `[data-radio-cards] [data-radio-cards-item][data-state='checked'] [data-radio-cards-indicator]` | `border-color` | `var(--_radio-group-palette-solid)` ⤴ prestado de `radio-group` |
| 22 | `radio-cards.css:281` | `[data-radio-cards] [data-radio-cards-item][data-disabled] [data-radio-cards-indicator]` | `border-color` | `var(--radio-group-disabled-indicator-border)` ⤴ prestado de `radio-group` |
| 23 | `radio-cards.css:282` | `[data-radio-cards] [data-radio-cards-item][data-disabled] [data-radio-cards-indicator]` | `background` | `var(--radio-group-disabled-indicator-bg)` ⤴ prestado de `radio-group` |
### 1.2 A través de un privado (0)
@ -82,7 +81,7 @@ Consumidos y **no declarados en el CSS** (vienen de `base.ts` o de un estilo inl
- **Consume tokens públicos de `radio-group`.** Un token prestado importa la semántica de su dueño: la corrección no es duplicarlo con prefijo propio, sino la decisión de familia que la auditoría de fase 1 dejó registrada (`theming-audit.md` §B, familia calendar).
- **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` (20 )
### 4.1 Tokens a declarar en `lib/recipes/base.ts` (19 )
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
@ -100,7 +99,6 @@ no distingue lo que debería — se marca `⚠`.
| `hover-on-item-border` | `root` | `var(--_radio-group-palette-solid-hover)` | 1 |
| `hover-on-item-bg` | `root` | `color-mix(in srgb, var(--_radio-group-palette-solid) 12%, var(--color-surface-default))` | 1 |
| `on-item-bg` | `root` | `color-mix(in srgb, var(--_radio-group-palette-solid) 7%, var(--color-surface-default))` | 1 |
| `invalid-item-border` | `root` | `var(--color-threat-element)` | 1 |
| `on-item-fg` | `root` | `var(--_radio-group-palette-solid)` | 1 |
| `indicator-width-xs` | `root` | `var(--radio-group-item-size-xs)` | 1 |
| `indicator-height-xs` | `root` | `var(--radio-group-item-size-xs)` | 1 |
@ -130,6 +128,34 @@ no distingue lo que debería — se marca `⚠`.
<!-- veredicto:start -->
_(pendiente — lo escribe el autor; se conserva al regenerar)_
**ADJUDICADO 2026-08-22 — 60 % → 61 %, y ése es su techo.** Una sola clave
nueva, porque **21 de sus 23 knobs fuera de alcance NO son suyos** .
`RadioCards` es un **skin sobre RadioGroup** : renderiza `<RadioGroup.Provider>`
y su indicador ES un radio. Por eso lee `--radio-group-item-size-*` ,
`--radio-group-indicator-*` y el puente de paleta del anfitrión
(`--_radio-group-palette-*`, declarado en el host `[data-radio-group]` donde
esta tarjeta vive). El censo los marca «⤴ prestado» y el mandato de composición
—`theming-audit` §5.3-3— dice que **se teman en la ficha del dueño** : coserlos
aquí sería vocabulario paralelo, y además dejaría que un tema rompiera «un radio
es un radio» sólo dentro de las tarjetas.
**Lo acuñado, que sí es suyo**: `invalid-border` — el borde de la TARJETA en
validación fallida. La tarjeta es de este skin; el indicador no.
**Los dos `--radius-full` del indicador son identidad**, no knobs: un radio es
redondo por definición (misma clase que el `100%` y el `50%` de un círculo). Y
sus cuatro literales son geometría del glifo (el `46%` del punto interior, el
`100%` del SVG del icono).
**Cinco adjudicaciones, todas forzadas a mano y con las transiciones
CONGELADAS**: la tarjeta transiciona `border-color` , y leer justo después de
escribir devuelve el valor de partida — la primera medición de `invalid-border`
dio «sin efecto» por eso, que es exactamente el motivo por el que el guard
congela. Con la congelación: invalid `oklch(0.9555 0.0207 13.86) → rgb(1,2,3)` ,
`horizontal-basis` 192px → 1234px, `disabled-opacity` 0.4 → 0.123, y las dos
de transición medidas SIN congelar (0.12s → 11.5s).
Sonda antes/después: **0 diffs en 3.540 valores** (19 nodos × 7 estados).
<!-- veredicto:end -->