blocks(tramo B): las cinco primeras matrices de equivalencia

El entregable central de la ola, y el que responde a la pregunta que la abrió: no
competir en número de dumps, sino demostrar variante a variante qué composición
nuestra logra cada una de las suyas — y sacar a la luz, con nombre, lo que no
alcanzamos.

Cada block gana una sección de equivalencias con cinco columnas: la variante de la
referencia, quién la shippea, la receta exacta, dónde se ha visto, y su estado. La
regla que gobierna la tabla es que una receta que no se ha visto en el navegador
no entra: la columna de demostración es la prueba, no la promesa.

Y la primera tabla ya justificó el tramo. El hero declaraba desde julio, en sus
gaps, que el mockup de móvil estaba HECHO — y la demo sólo había enseñado nunca el
cromo de navegador. El primitivo ofrece tres, así que se añadió el control, se
midió el cromo de teléfono a trescientos veinte y sólo entonces se escribió la
fila. Una receta declarada no es una receta demostrada, que es exactamente lo que
este tramo existe para separar.

Van cinco de quince: hero, pricing, cta, testimonials y faq, que son los que esta
sesión ha trabajado y cuyas recetas están medidas. Entre las filas quedan nueve
gaps con nombre —desde la elevación estática que Card no tiene hasta el carrusel
de citas— y dos «no se ofrece» con su motivo: un carrusel en la apertura es
movimiento automático sin control de pausa, y filtrar preguntas es estado de datos
del app.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
alpha-0.1-background
dev 2 months ago
parent e7677d6d87
commit 00489be263

@ -80,6 +80,25 @@ PrimeBlocks «CTA 12» · Untitled UI):
layout, colour, finish and direction, and the device widths served from
`preview/`. Mini-page in `CtaSite.svelte`, shared by both surfaces.
## Equivalencias
_La matriz del tramo B: cada variante que las referencias shippean, frente a la
composición nuestra que la logra. Del dossier (P6.1): no competir en número de
dumps, sino **demostrar la equivalencia una a una** — y sacar a la luz lo que no
alcanzamos, con nombre. **Una receta que no se ha visto en el navegador NO entra
en esta tabla**: la columna «Demostrada en» es la prueba, no la promesa._
| Variante de la referencia | Refs | Receta | Demostrada en | Estado |
| -------------------------------- | --------------------- | ----------------------------------------------------------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------- |
| Panel centrado | TW · Prime · Untitled | `layout="center"` | control `layout` | cubierta |
| Copy a un lado, acciones al otro | TW («justified») | `layout="justified"` | control `layout` | cubierta |
| Panel con captura al lado | TW · Prime | `layout="split"` + slot `media` con `<Mockup>` | control `layout: split` | cubierta (V5) |
| Panel a sangre (borde a borde) | TW · Flowbite | `containerSize="full"` (el block suelta el canalón con él) | control `container: full` | cubierta |
| Acabado con degradado | Untitled | `gradient` (por defecto) sobre el `Surface` sólido del sistema | control `acabado` | cubierta |
| CTA que navega y parece botón | todas | el `child` de `Button` entrega el contenido ya pintado a un `<a>` | `CtaSite` | cubierta |
| Panel apagado con borde | TW («light panel») | — | — | gap: `quiet-bounded-panel` (`Surface soft` no acota —0.002 L del fondo— y `Card outline` no acepta degradado) |
| CTA descartable / pegajoso | Flowbite | — | — | no se ofrece: eso es el block `banner`, no este |
## Gaps
| Gap | Disposition |

@ -96,6 +96,23 @@ container 768, answers hidden until pressed. List → no accordion, **0 triggers
pressing**. At 375 it collapses to one column and keeps both. The accordion
arrangement is unchanged.
## Equivalencias
_La matriz del tramo B: cada variante que las referencias shippean, frente a la
composición nuestra que la logra. Del dossier (P6.1): no competir en número de
dumps, sino **demostrar la equivalencia una a una** — y sacar a la luz lo que no
alcanzamos, con nombre. **Una receta que no se ha visto en el navegador NO entra
en esta tabla**: la columna «Demostrada en» es la prueba, no la promesa._
| Variante de la referencia | Refs | Receta | Demostrada en | Estado |
| ------------------------------------------- | ------------------------------ | ------------------------------------------------------------ | ---------------- | ------------------------------------------------------------------------------------ |
| Acordeón de una columna | TW (1 de 7) · Flowbite | `.List` (por defecto) — el `Accordion` del canon entero | control `layout` | cubierta |
| Lista estática de 2/3 columnas | TW (6 de 7) · Untitled · Prime | `.List layout="list"` — pregunta como `h3`, respuesta debajo | control `layout` | cubierta (V3) |
| Cola «¿Aún tienes dudas?» con CTA a soporte | TW · Untitled | la app la compone tras el block (`Text` + `Link`) | `FaqSite` | cubierta |
| Acordeón con varias abiertas a la vez | Flowbite | `.List type="multiple"` — el API del `Accordion` atraviesa | — | gap: `faq-multiple-demo` (la receta existe; falta enseñarla) |
| FAQ agrupada por categorías | Untitled | varios `<Faq>` con su `.Header`, o `.List` por grupo | — | gap: `faq-grouped` (composición del app; sin demostrar) |
| Buscador sobre las preguntas | Prime | — | — | no se ofrece: filtrar preguntas es estado de datos del app, y el block no lo inventa |
## Gaps
| Gap | Disposition |

@ -106,6 +106,36 @@ of the five props, and the device widths served from `preview/` as their own
document. The mini-page lives in `HeroSite.svelte` and is shared by both
surfaces.
## Equivalencias
_La matriz del tramo B: cada variante que las referencias shippean, frente a la
composición nuestra que la logra. Su razón de ser está en el dossier (P6.1): no
competir en número de dumps, sino **demostrar la equivalencia una a una** — y
sacar a la luz lo que de verdad no alcanzamos, con nombre, en vez de dejarlo en
la sensación de que «ellos tienen más»._
**Regla dura**: una receta que no se ha visto en el navegador NO entra en esta
tabla. La columna «Demostrada en» es la prueba, no una promesa.
| Variante de la referencia | Refs | Receta | Demostrada en | Estado |
| ------------------------------- | ------------------------------------------------ | ---------------------------------------------------------------------------------- | ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| Hero centrado (copy + acciones) | TW · Flowbite · Untitled | `layout="center"` | control `layout` | cubierta |
| Hero partido con captura | TW · Flowbite · Untitled · Prime | `layout="split"` + `media` con `<Mockup chrome="browser">` | controles `layout` + `tipo de media: panel` | cubierta |
| Hero con mockup de móvil | Flowbite («phone-mockup + app-store») · Untitled | `layout="split"` + `media` con `<Mockup chrome="phone">` | control `tipo de media: móvil` | cubierta |
| Hero con vídeo | Flowbite · TW | `media` con `MediaPlayer` DECORATIVO (mudo, en línea, sin controles) | controles `tipo de media: vídeo` + `bucle del vídeo` | cubierta |
| Hero con imagen/vídeo de fondo | TW · Untitled | `layout="background"` + slot `backdrop`; el block pone el velo y la tinta on-solid | control `layout: background` | cubierta |
| Alta por correo en el hero | Flowbite («sign-up-in-hero») · TW | slot `form`; la app compone `Form` + `Field` + `Form.Submit` | control `form` | cubierta |
| Tira de logos bajo las acciones | TW · Untitled | slot `children` (se renderiza al final de la copy) | `HeroSite` (la banda «Con la confianza de…») | cubierta |
| Chip de anuncio sobre el título | TW · Untitled | slot `eyebrow` con un `Badge` | control `eyebrow` | cubierta |
| Hero con buscador / datepicker | Flowbite («search-bar + datepicker») | slot `form`: la app compone el control que quiera, no sólo un correo | — | gap: `hero-search-demo` (la receta es la misma que el alta; falta enseñarla) |
| Hero con carrusel | Flowbite («carousel») | — | — | no se ofrece: un carrusel en la apertura es contenido que se mueve solo sin control de pausa (WCAG 2.2.2) y el bloque no lo va a normalizar |
**Lo que esta tabla destapó** (2026-08-17): la fila del mockup de móvil llevaba
declarada «HECHA» en los Gaps desde julio y **la demo nunca la había enseñado** —
`Mockup` ofrece `plain | browser | phone` y aquí sólo se veía `browser`. Se añadió
el control y se midió (`data-chrome="phone"`, 320px) antes de escribir la fila.
Ese es el trabajo del tramo: una receta declarada no es una receta demostrada.
## Gaps
| Gap | Disposition |

@ -101,6 +101,27 @@ Untitled UI «Pricing 22» · Flowbite):
the middle), the live monthly/annual toggle switching every price. Mini-page in
`PricingSite.svelte`, shared by both surfaces.
## Equivalencias
_La matriz del tramo B: cada variante que las referencias shippean, frente a la
composición nuestra que la logra. Del dossier (P6.1): no competir en número de
dumps, sino **demostrar la equivalencia una a una** — y sacar a la luz lo que no
alcanzamos, con nombre. **Una receta que no se ha visto en el navegador NO entra
en esta tabla**: la columna «Demostrada en» es la prueba, no la promesa._
| Variante de la referencia | Refs | Receta | Demostrada en | Estado |
| --------------------------------------------- | ------------------------ | ------------------------------------------------------------------- | ----------------------------------- | ---------------------------------------------------------------------------------------------- |
| Fila de planes con uno destacado | TW · Untitled · Flowbite | `.Plans` + `.Plan featured` | por defecto en la demo | cubierta |
| Conmutador mensual / anual | TW · Untitled · Prime | `.Switch` + `.PlanPrice` con `monthly`/`annual` | el propio control del block | cubierta |
| Tabla comparativa características × planes | TW · Untitled · Prime | `.Compare` con el `createTable` de la app; convive con las tarjetas | control `tabla comparativa` | cubierta (V1) |
| Precio único centrado | TW · Untitled | un `.Plan` + `.Plans maxWidth="28rem"` | control `planes: 1` | cubierta (V8) |
| Dos planes | TW | dos `.Plan` + `.Plans maxWidth="44rem"` | control `planes: 2` | cubierta (V8) |
| Nota de ahorro anual | TW · Flowbite | la app la pone en `annualLabel` («Anual (−20 %)») | `PricingSite` | cubierta |
| Tarjeta que responde al puntero | Untitled | `.Plan lift` (eleva sin volverse control) | control `realce al puntero` | cubierta |
| Plan actual no elegible (upgrade / downgrade) | — **ninguna** | `.Plan state="current"` + `.PlanReason` + `aria-describedby` | control `escenario: cambio de plan` | **superación**: las refs shippean markup estático y no pueden expresar el estado del visitante |
| Elevación permanente del plan recomendado | TW · Untitled | — | — | gap: `card-static-elevation` (`Card` no expone elevación estática; `featured` es sólo color) |
| Precios por región / divisa | Prime | la app compone `FormatNumber` en los snippets del precio | — | gap: `pricing-currency-demo` (la receta existe; falta enseñarla) |
## Gaps
| Gap | Disposition |

@ -85,6 +85,24 @@ container 1024, stagger present. Spotlight → **0 cards**, one quote at **28px*
centred in a `<p>`, container **768**, author centred, no stagger. At 375 the
quote lands at 24px. The grid arrangement is byte-identical to before.
## Equivalencias
_La matriz del tramo B: cada variante que las referencias shippean, frente a la
composición nuestra que la logra. Del dossier (P6.1): no competir en número de
dumps, sino **demostrar la equivalencia una a una** — y sacar a la luz lo que no
alcanzamos, con nombre. **Una receta que no se ha visto en el navegador NO entra
en esta tabla**: la columna «Demostrada en» es la prueba, no la promesa._
| Variante de la referencia | Refs | Receta | Demostrada en | Estado |
| ----------------------------------- | ------------------------------------------ | ---------------------------------------------------------------------- | --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| Rejilla de citas en tarjeta | TW (2 de 8) · Prime | `layout="grid"` (por defecto) | control `layout` | cubierta |
| Cita única en spotlight | TW (mayoría) · Untitled · Flowbite · Prime | `layout="spotlight"` — sin tarjeta, cita a `xl` centrada, autor debajo | control `layout` | cubierta (V2) |
| Logo del cliente sobre la cita | TW · Untitled | slot `logo` en `.Item` | `TestimonialsSite` (con `layout="spotlight"`) | cubierta (V2) |
| Avatar + nombre + cargo | todas | `.Author` con el slot `avatar` (la app compone `Avatar`) | `TestimonialsSite` | cubierta |
| Cita con logo de empresa en tarjeta | Untitled | el mismo slot `logo` bajo `layout="grid"` | — | gap: `testimonial-logo-grid-demo` (la receta ya funciona; falta enseñarla en grid) |
| Carrusel de citas | Flowbite · Prime | — | — | gap: `testimonials-carousel` (el `Carousel` del canon existe; es otra disposición y entra cuando una demo la pida) |
| Vídeo-testimonio | Untitled | — | — | gap: `testimonial-video` (cabría en `.Item` componiendo `MediaPlayer`; sin demostrar) |
## Gaps
| Gap | Disposition |

@ -20,7 +20,7 @@
let container = $state<'sm' | 'md' | 'lg' | 'xl' | 'full'>('lg');
let size = $state<'sm' | 'md' | 'lg' | 'xl'>('xl');
let withMedia = $state(true);
let mediaKind = $state<'dashboard' | 'video'>('dashboard');
let mediaKind = $state<'dashboard' | 'video' | 'phone'>('dashboard');
let withEyebrow = $state(true);
let withForm = $state(false);
let videoLoop = $state(true);
@ -129,6 +129,7 @@
>
<ToggleGroup.Item value="dashboard">panel</ToggleGroup.Item>
<ToggleGroup.Item value="video">vídeo</ToggleGroup.Item>
<ToggleGroup.Item value="phone">móvil</ToggleGroup.Item>
</ToggleGroup>
</Group>

@ -37,7 +37,7 @@
type SectionSize = 'sm' | 'md' | 'lg' | 'xl';
type Layout = 'center' | 'split' | 'background';
type Decor = 'glow' | 'mesh' | 'grid' | 'dots' | 'none';
type MediaKind = 'dashboard' | 'video';
type MediaKind = 'dashboard' | 'video' | 'phone';
let {
layout = 'split' as Layout,
@ -198,6 +198,30 @@
/>
</MediaPlayer>
</Mockup>
{:else if mediaKind === 'phone'}
<!-- El mismo primitivo con el otro cromo: bisel de teléfono y notch. La receta
de «hero con mockup de móvil» estaba declarada como HECHA desde julio y no
se había enseñado nunca — el tramo B existe justamente para eso. -->
<Box width="100%" maxWidth="20rem" marginX="auto">
<Mockup chrome="phone">
<Box padding={4}>
<Stack gap={4}>
<Text size="sm" weight="medium">Cohorte de hoy</Text>
<Grid columns={4} gap={2} align="end">
{#each bars.slice(0, 4) as h, i (i)}
<Surface
variant="solid"
color={i === 2 ? 'primary' : 'neutral'}
rounded
height={h}
/>
{/each}
</Grid>
<Surface variant="solid" color="neutral" rounded height="0.5rem" />
</Stack>
</Box>
</Mockup>
</Box>
{:else}
<!-- Dogfoods the canon `Mockup`: the browser chrome (dots + URL) is the
primitive's, so the faux dashboard inside is just the content. -->

@ -18,7 +18,9 @@
const withEyebrow = $derived(params.get('eyebrow') !== 'false');
const withForm = $derived(params.get('form') === 'true');
const videoLoop = $derived(params.get('loop') !== 'false');
const mediaKind = $derived((params.get('kind') ?? 'dashboard') as 'dashboard' | 'video');
const mediaKind = $derived(
(params.get('kind') ?? 'dashboard') as 'dashboard' | 'video' | 'phone'
);
const decor = $derived(
(params.get('decor') ?? 'glow') as 'glow' | 'mesh' | 'grid' | 'dots' | 'none'
);

Loading…
Cancel
Save

Powered by TurnKey Linux.