Segunda fila de la ola F2b, y la que existía para comprobar una sospecha. El
README llevaba desde julio diciendo que el plan único «ya lo cubre el layout»,
diferido por eso. La ficha exigía medirlo antes de darlo por gratis, y no lo
cubría.
La causa está en la lista de pistas, no en cuántos planes hay: la fila es
repeat(auto-fill, minmax(17rem, 1fr)), y auto-fill RESERVA toda pista que quepa,
la ocupe alguien o no. Medido a 1280 sobre 992px de fila, un plan solo daba una
tarjeta de 315px pegada al borde inicial con 677px de vacío al lado; fijar
columns a 1 solo cambiaba eso por una tarjeta de 992px, que es un cartel. Meterlo
en un Container sm tampoco: a 640px vuelven a caber dos pistas.
Lo que faltaba era un tope sobre la FILA, y la parte no lo dejaba pasar: sus
props están cerradas a propósito desde A-94, porque el envoltorio esparce el
resto antes de las props que fija y un width del consumidor tipaba y se
descartaba en silencio. Así que se abre nombrando: maxWidth entra en el tipo y
viaja explícito al AutoGrid, que es exactamente lo que A-94 dejó dicho — el tipo
dice lo que la parte honra. El marginX auto va con él sin condición: sin tope la
fila ya llena la medida y auto no resuelve a nada.
El número lo pone la app. Un block que horneara uno estaría decidiendo cuánto
mide un plan; la demo pasa 28rem para uno y 44rem para dos, que es lo que las
referencias le dan a cada arreglo, y gana un control vivo de recuento que también
viaja en la URL de la vista previa.
Medido después: un plan 448px centrado, dos planes 704px en dos pistas de 340
centradas, y tres planes 992px idénticos a antes — el tope es opt-in y no toca el
caso que ya existía. A 375 es inerte, porque allí una sola pista ya toma el
ancho.
Queda anotada la lección en el README y en el handoff, porque no es de este
block: una fila «diferida» puede ser una medición equivocada y no un
aplazamiento. Nadie había mirado pricing con menos de tres planes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
| **V1** | `pricing` | tabla comparativa features×planes | **`Pricing.Compare`** (parte, por el término 4). **Tanda propia con fase 0**: dos decisiones de diseño que la ficha no puede prejuzgar — (a) **quién declara las columnas** si `.Plans` y `.Compare` conviven (doble declaración de planes) y (b) **qué pasa en móvil** (las refs colapsan a lista-por-plan o a scroll) | **alto** |
| **V2** | `testimonials` | cita única en spotlight | **`layout="grid" \| "spotlight"`**. ⚠️ No es «misma anatomía» exacta: gana un slot `logo`, pierde la `Card` y `Items` pasa a un solo protagonista. Aun así `layout`, con el precedente de `hero layout="background"`, que también redefine partes. El hermano se reabre SÓLO si un día pide rotación / carousel | medio |
| **V3** | `faq` | lista estática 2/3 columnas | **`layout="accordion" \| "list"`**, con `.List` conmutando entre `Accordion` y una rejilla de Q&A siempre abiertas. **El punto fino es el TIPO**: hoy `FaqListProps = AccordionProps`, y bajo `list` no aplican ni esas props ni `value`/`disabled` de `.Item` → unión discriminada, jamás superficie descartada en silencio (A-94) | medio |
| **V4** | `hero` | `form-in-hero` | ✅ **HECHA 2026-08-17.** Slot `form`, el app compone `Form` + `Field` + `Form.Submit` entero (el hero NO toma el handle: tomarlo lo convertiría en un block que coordina). Aterriza en el sitio del CTA — tras la descripción, antes de `actions` — con medida propia `sm`; los dos conviven si llegan los dos. Detalle y medidas: README del block §«The sign-up slot» | bajo |
| **V5** | `cta` | split-with-media | tercer **`layout="split"`** + slot `media` (el nombre que ya usa `hero`); el `Mockup` existe. Es suelo: el dossier la lista | bajo |
| **V8** | `pricing` | single-price | **PRIMERO SE MIDE.** «Un solo `.Plan` y el layout ya lo sostiene» es una asunción sin verificar: en rejilla fluida un plan solo o se estira al container o se queda en su pista, y ninguna de las dos es la card centrada de las referencias — además `PricingPlansProps` es un `Pick` cerrado sin salida. Si no lo sostiene, deja de ser ~0 y vuelve como decisión | ~0 → ? |
| **V1** | `pricing` | tabla comparativa features×planes | **`Pricing.Compare`** (parte, por el término 4). **Tanda propia con fase 0**: dos decisiones de diseño que la ficha no puede prejuzgar — (a) **quién declara las columnas** si `.Plans` y `.Compare` conviven (doble declaración de planes) y (b) **qué pasa en móvil** (las refs colapsan a lista-por-plan o a scroll) | **alto** |
| **V2** | `testimonials` | cita única en spotlight | **`layout="grid" \| "spotlight"`**. ⚠️ No es «misma anatomía» exacta: gana un slot `logo`, pierde la `Card` y `Items` pasa a un solo protagonista. Aun así `layout`, con el precedente de `hero layout="background"`, que también redefine partes. El hermano se reabre SÓLO si un día pide rotación / carousel | medio |
| **V3** | `faq` | lista estática 2/3 columnas | **`layout="accordion" \| "list"`**, con `.List` conmutando entre `Accordion` y una rejilla de Q&A siempre abiertas. **El punto fino es el TIPO**: hoy `FaqListProps = AccordionProps`, y bajo `list` no aplican ni esas props ni `value`/`disabled` de `.Item` → unión discriminada, jamás superficie descartada en silencio (A-94) | medio |
| **V4** | `hero` | `form-in-hero` | ✅ **HECHA 2026-08-17.** Slot `form`, el app compone `Form` + `Field` + `Form.Submit` entero (el hero NO toma el handle: tomarlo lo convertiría en un block que coordina). Aterriza en el sitio del CTA — tras la descripción, antes de `actions` — con medida propia `sm`; los dos conviven si llegan los dos. Detalle y medidas: README del block §«The sign-up slot» | bajo |
| **V5** | `cta` | split-with-media | tercer **`layout="split"`** + slot `media` (el nombre que ya usa `hero`); el `Mockup` existe. Es suelo: el dossier la lista | bajo |
| **V8** | `pricing` | single-price | ✅ **HECHA 2026-08-17 — y NO era gratis.** Medido: la fila es `auto-fill`, así que RESERVA las pistas que caben aunque nadie las ocupe → un plan solo daba 315px pegados al borde con 677px de vacío, y `columns={1}` lo cambiaba por una card de 992px. Resuelto con **`.Plans maxWidth`** (tope de fila, centrado, reenviado nombrado por A-94); el número lo pone el app. Detalle: README del block §«The row cap» | ~0 → bajo |
**Fuera de la ola, a F5 con disparador** — el dossier declara `stats-band`
**«Paridad OK»**, así que estas dos son _adoptables_, no suelo, y meterlas aquí
@ -2110,3 +2110,19 @@ type="button">` es una pista de MIME falsa) — el morfo lo declara
tampoco normaliza oklch aquí → medía NEGRO contra todo); la señal de que la
sonda es honesta es que la etiqueta del submit sale a 5.18:1, la cifra que el
repo ya documenta para `primary`.
- 2026-08-17 — **F2b · V8 `single-price` HECHA, y la ficha acertó al exigir que
se midiera ANTES**: «un solo `.Plan` y el layout ya lo sostiene» —la
disposición que el README del block llevaba desde julio— era falsa. La fila es
`repeat(auto-fill, minmax(17rem, 1fr))` y **`auto-fill` reserva toda pista que
quepa**, la ocupe alguien o no: medido a 1280 sobre 992px de fila, un plan solo
daba una card de 315px pegada al borde con 677px de vacío al lado, y
`columns={1}` sólo cambiaba eso por una card de 992px. Ninguna de las dos es la
card centrada de las referencias. Resuelto abriendo `.Plans` a **`maxWidth`**
(tope de la FILA, con `marginX="auto"` incondicional para centrarla),
reenviado NOMBRADO al `AutoGrid` — nunca por `{...rest}`, que es justo lo que
A-94 dejó dicho. El número lo pone el app: la demo pasa `28rem` para un plan y
`44rem` para dos. Medido después: 448px centrados con uno, 704px (dos pistas de 340) con dos, y **992px idénticos con tres** — el tope es opt-in y no toca el
caso que ya existía; a 375 es inerte. Control vivo nuevo en la demo (nº de
planes) y en la URL del preview. ⚠️ Lección que se queda: **una fila
«diferida» puede ser una medición equivocada, no un aplazamiento** — nadie
| `.Switch` | `ToggleGroup` | writes the period; reads it back to stay in sync |
| `.Plans` | `AutoGrid` + `data-stagger` | fluid row of equal-height plan cards; the stagger rhythm is structural. `maxWidth` caps and centres the row for short plan counts (V8) |
| `.Plan` | `Motion` (`trigger="viewport"`) wrapping a `Card` (outline) | IS the reveal (direct child of the staggered row); `featured` → accent colour; `badge` chip |
| **Feature-comparison table** (features × plans matrix) | **scope-approval pending** — the dossier's recurring pricing gap. It is a table, not a row of cards, so likely a sibling (`pricing-table`) or a `.Compare` sub-block — a user decision, not a silent add |
| **Single-price variant** (one plan, centered) | **deferred** — one `.Plan` in `.Plans`; the layout already handles it |
| **Single-price variant** (one plan, centered) | **SHIPPED 2026-08-17** (F2b · V8) — as `.Plans maxWidth`. The old disposition here («the layout already handles it») was WRONG and is kept visible on purpose; see «The row cap» below |
| **Per-period savings note** ("2 meses gratis") | **app-land** — the app puts it in the `annualLabel` or a `.PlanDescription` |
| **Elevation on the featured plan** | **canon candidate** — `Card` exposes no elevation prop, and a block paints nothing of its own. Marking the recommended tier by depth (not just colour) needs the prop in `Card`; until then `featured` is colour only |
### The row cap (`.Plans maxWidth`) — 2026-08-17, plan F2b · V8
This row existed in the Gaps table as «deferred — one `.Plan` in `.Plans`; the
layout already handles it». **It did not.** Measured before touching anything,