From 331912cf234daf5cf289c304adb166bc17207981 Mon Sep 17 00:00:00 2001 From: dev Date: Tue, 18 Aug 2026 03:56:39 +0200 Subject: [PATCH] =?UTF-8?q?blocks(background):=20seis=20fondos,=20y=20el?= =?UTF-8?q?=20que=20parec=C3=ADa=20mejor=20era=20el=20que=20no=20se=20pod?= =?UTF-8?q?=C3=ADa=20leer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit F5 de PLAN-background.md: los seis blocks de D-BG.10 (2) reciben `Background.*`. El hero cayó en F2 y la página compuesta ya existía — no había que construirla, había que verificarla con la decoración puesta. La forma es uniforme y tiene un solo desvío: cada block gana un prop `decor` que monta `` como HIJA de su `Section`, la misma composición que el hero ya probó. El desvío es `cta`, donde la decoración va dentro del PANEL, que es donde está el ojo. **Dos hallazgos que sólo la medición podía dar.** Dentro del panel sólido del `cta`, las dos tramas TINTADAS hunden el titular bajo AA: `glow` lleva la copia blanca de 5,18:1 a **3,06:1** y `mesh` a **2,27:1**. Pintan un lavado claro anclado en `50% 0%` — exactamente donde se asienta el titular. Las de línea toman la tinta de regla, oscurecen, y la copia sube a **14,35:1** mientras la textura sigue leyéndose a 3,19:1 contra el panel. Por eso el default es `rings`, que además irradia del mismo anclaje superior que usaba el glow. Las tintadas se ofrecen igual: el app decide, pero ya con el número delante, en el tipo y en el README. Y una trama tintada dentro del panel era invisible por construcción: `--_background-tint` cae en `--color-primary-solid`, que es EL MISMO valor que pinta el panel — un halo del color del panel sobre el color del panel. El block pasa ahora `color="var(--color-content-on-solid)"`, el token que ya usa para su propia copia; medido después, el tinte resuelve a `#ffffff`. **Los defaults, y por qué dos están apagados.** `cta` `rings` · `stats-band` `grid`, porque una banda de cifras se lee como medida y la rejilla es la trama que lo dice sin decorar por decorar · `testimonials` y `feature-split` `glow`. `site-footer` y `banner` reciben la capacidad APAGADA: la columna B del plan de calidad no pide acabado en ninguno de los dos, y encenderlo por nuestra cuenta sería inventar un aspecto que nadie pidió. **Un desvío de alcance, declarado.** La columna B pedía «`Backdrop` alterno» POR FILA en `feature-split`; se resuelve en la SECCIÓN. Una banda por fila obligaría a cada `Row` a poseer el estado de alternancia, y eso es coordinación — un block que coordina deja de ser un block que no posee nada. Medido en Chrome sobre la página compuesta real: cinco pilas, los cinco anfitriones adoptados (`position: relative` + `isolation: isolate`) sin que ningún block los posicione; la copia mide 15,88:1 sobre las secciones decoradas y 5,18:1 sobre el panel del cta — AA en todas. Sobre lienzo oscuro, medido aparte: 17,06 → 13,23:1 con `glow` y 12,37:1 con `grid`/`dots`. Ledger: seis filas nuevas, A-100…A-105, cada una con su mecanismo y su evidencia. Gates: `blocks:check` 0/18 · `rtl:check` 0/180 · `docs:check` 0/0 en 634 docs · 434/435 (el fallo es el `skin-media-player` de siempre) · `check` 0 errores propios · prettier limpio. Co-Authored-By: Claude Opus 5 --- docs/process/AUDIT-blocks-ledger.md | 63 +++++++++++++++++++ docs/process/PLAN-background.md | 51 +++++++++++++++ src/uix/blocks/banner/README.md | 5 ++ src/uix/blocks/banner/banner.svelte | 9 +++ src/uix/blocks/banner/types.ts | 10 +++ src/uix/blocks/cta/README.md | 11 ++++ src/uix/blocks/cta/cta.svelte | 28 +++++++++ src/uix/blocks/cta/types.ts | 19 ++++++ src/uix/blocks/feature-split/README.md | 6 ++ .../blocks/feature-split/feature-split.svelte | 12 ++++ src/uix/blocks/feature-split/types.ts | 11 ++++ src/uix/blocks/site-footer/README.md | 5 ++ src/uix/blocks/site-footer/site-footer.svelte | 12 ++++ src/uix/blocks/site-footer/types.ts | 11 ++++ src/uix/blocks/stats-band/README.md | 7 +++ src/uix/blocks/stats-band/stats-band.svelte | 12 ++++ src/uix/blocks/stats-band/types.ts | 11 ++++ src/uix/blocks/testimonials/README.md | 7 +++ .../blocks/testimonials/testimonials.svelte | 12 ++++ src/uix/blocks/testimonials/types.ts | 11 ++++ 20 files changed, 313 insertions(+) diff --git a/docs/process/AUDIT-blocks-ledger.md b/docs/process/AUDIT-blocks-ledger.md index 762b990cd..ae409f90d 100644 --- a/docs/process/AUDIT-blocks-ledger.md +++ b/docs/process/AUDIT-blocks-ledger.md @@ -143,6 +143,12 @@ Columna **or.** = de qué sección del documento viejo salió la fila (`C` confi | A-97 | `feature-grid + 6 blocks` | percepcion | MEDIA | F7 | El texto `color="muted"` mide 3,70:1 en claro — bajo AA de cuerpo — en 8 sitios de 7 blocks; el hallazgo estaba enterrado en la ficha de A-70, que es REFUTADO… | `src/uix/blocks/feature-grid/feature-grid-item-text.svelte` | REFUTADO | | A-98 | `hero` | percepcion | MEDIA | F7 | Las acciones no apilan en móvil: `Group` es row/nowrap y a 375px los dos botones ocupan 315 de 327px. Síntoma de [A-99]; cae sin tocar el block… | `src/uix/blocks/hero/hero.svelte` | ARREGLADO | | A-99 | `Group` (canon) | doctrina | MEDIA | F7 | `Group` no aplica NINGUNO de los dos defaults de action row que su README promete (`wrap: wrap` y `align: center`): nunca se los pasa a `Flex`, y el recipe no puede suplirlos… | `src/uix/eidos/components/group/group.svelte` | ARREGLADO | +| A-100 | `cta` | percepcion | ALTA | F5-bg | Dentro del panel sólido, las dos tramas TINTADAS hunden el titular blanco bajo AA: `glow` 5,18 → 3,06:1 y `mesh` → 2,27:1. Las de línea oscurecen y suben la copia a 14,35:1 | `src/uix/blocks/cta/cta.svelte` | ARREGLADO | +| A-101 | `cta` | doctrina | MEDIA | F5-bg | Un `glow` tintado con el acento del propio panel resuelve EXACTAMENTE al fondo del panel: el halo es invisible por construcción. El acento debe viajar como tinta on-solid | `src/uix/blocks/cta/cta.svelte` | ARREGLADO | +| A-102 | `stats-band` | percepcion | BAJA | F5-bg | Sin decoración de sección (columna B: «reveal + Backdrop»); el reveal ya estaba, el fondo no | `src/uix/blocks/stats-band/stats-band.svelte` | ARREGLADO | +| A-103 | `testimonials` | percepcion | BAJA | F5-bg | Sin decoración de sección; el halo detrás de las citas es el acabado que las referencias pintan a mano | `src/uix/blocks/testimonials/testimonials.svelte` | ARREGLADO | +| A-104 | `feature-split` | percepcion | BAJA | F5-bg | Columna B pedía «`Backdrop` alterno» por fila; se resuelve en la SECCIÓN — una banda por fila obligaría a cada `Row` a poseer estado de alternancia | `src/uix/blocks/feature-split/feature-split.svelte` | ARREGLADO | +| A-105 | `site-footer + banner` | doctrina | BAJA | F5-bg | Ambos ganan la capacidad de decoración APAGADA por defecto: la columna B no pide acabado en ninguno, y encenderlo sería inventar un aspecto que nadie pidió | `src/uix/blocks/site-footer/site-footer.svelte` | ARREGLADO | ## Reparto @@ -1881,3 +1887,60 @@ LÍNEA BASE sin biografía: todas las tarjetas 195px, desviación 0px — es dec **Mecanismo** — `ContactVerification` es ahora `ProofOfHumanStatus` importado del canon, no una copia de las mismas cuatro palabras. **Evidencia** — `contact/state.ts`. + +### A-100 — ARREGLADO · `cta` · percepcion · ALTA + +**Reclamación** — la decoración del panel, encendida sin medir, deja el titular +bajo AA. + +**Mecanismo** — el panel es `Surface variant='solid'` con la copia en tinta +on-solid (blanca). `glow` y `mesh` son las dos tramas que pintan con el TINTE, y +lo hacen sobre un área grande anclada en `50% 0%` — exactamente donde se asienta +el titular. El lavado claro sube la luminancia del fondo bajo la copia. + +**Evidencia** — medido en Chrome sobre panel `primary` (`142,78,198`) con tinta +`#ffffff`: llano **5,18:1** · con `glow` **3,06:1** · con `mesh` **2,27:1** · +con cualquiera de línea (`grid`/`dots`/`lines`/`rings`) **14,35:1** · con +`vignette` **9,89:1**. La textura de línea sigue siendo visible: la regla mide +3,19:1 contra el panel, que es el registro de una decoración. + +**Arreglo** — el default pasa a `rings`, que irradia del mismo anclaje superior +que usaba el glow. Las tintadas se siguen ofreciendo, con el número escrito en +el tipo y en el README: el app decide, pero informado. + +### A-101 — ARREGLADO · `cta` · doctrina · MEDIA + +**Reclamación** — la trama tintada dentro del panel es invisible. + +**Mecanismo** — `--_background-tint` cae por defecto en `--color-primary-solid`, +que es el MISMO valor que pinta el panel cuando `color='primary'`: un halo del +color del panel sobre el color del panel. + +**Evidencia** — medido: `--_background-tint` resolvía a +`oklch(0.5556 0.1829 305.86)`, idéntico al `background-color` del panel. + +**Arreglo** — el block pasa `color="var(--color-content-on-solid)"`, el mismo +token que ya usa para la tinta de su copia; medido después, el tinte resuelve a +`#ffffff`. + +### A-102 · A-103 · A-104 · A-105 — ARREGLADO · decoración de sección · F5 + +**Reclamación** — la columna B del plan de calidad pedía acabado de fondo en +`stats-band` (con reveal, que ya estaba), `testimonials` y `feature-split`; y +`site-footer` / `banner` no tenían la capacidad siquiera. + +**Mecanismo** — los cuatro primeros montan `` como +HIJA de su `Section`: la sección se vuelve anfitriona por la regla de foundation +(`:where(:has(> [data-background]))`), así que la banda sangra a todo el ancho +detrás de la medida y ningún block gana una caja. `site-footer` y `banner` la +reciben APAGADA: la columna B no pide acabado en ninguno de los dos. + +**Evidencia** — medido en Chrome, copia sobre el lienzo de página (`10,10,11`, +tinta `238,238,238`): llano **17,06:1**; con `glow` **13,23:1**; con `grid` / +`dots` **12,37:1**. Los cinco anfitriones computan `position: relative` + +`isolation: isolate` sin que ningún block los posicione. + +**Nota de alcance** — `feature-split` resuelve la alternancia en la sección y no +por fila a propósito: una banda por fila obligaría a cada `Row` a poseer el +estado de alternancia, que es coordinación, y un block que coordina deja de ser +un block que no posee nada. diff --git a/docs/process/PLAN-background.md b/docs/process/PLAN-background.md index 9b50c106e..53a8c15ba 100644 --- a/docs/process/PLAN-background.md +++ b/docs/process/PLAN-background.md @@ -742,6 +742,57 @@ componente pisaba y un `aria-pressed` inerte. Gates: audit **PASS 0** · eidos-lint invalid 0 · rtl 0/180 · docs 0/0 en 634 · blocks 0/18 · smoke PASS · 441/442 · `check` 0 propios · prettier limpio. +### 7.octies F5 ejecutada (2026-08-18) — rollout al tier + +Los seis blocks de D-BG.10 (2) reciben `Background.*`. El (1) —el hero— aterrizó +en F2, y el (3) —la página compuesta— **ya existía** (`/blocks/landing`): no +había que construirla, había que verificarla con la decoración puesta, y eso es +lo que se hizo. + +**La forma, uniforme y con un solo desvío**: cada block gana un prop `decor` que +monta `` como HIJA de su `Section` — la misma que el hero ya +probó. El desvío es `cta`, donde la decoración va dentro del PANEL (`Surface`), +que es donde está el ojo. + +**Dos hallazgos que sólo la medición podía dar, y que habría shippeado a ciegas:** + +1. **Dentro del panel sólido del `cta`, las dos tramas TINTADAS hunden el titular + bajo AA**: `glow` lleva la copia blanca de 5,18:1 a **3,06:1** y `mesh` a + **2,27:1**, porque pintan un lavado claro anclado en `50% 0%` — exactamente + donde se asienta el titular. Las de línea toman la tinta de regla, oscurecen, + y la copia sube a **14,35:1** mientras la textura sigue leyéndose a 3,19:1 + contra el panel. El default es `rings`, que irradia del mismo anclaje que + usaba el glow. Las tintadas se ofrecen igual, con el número en el tipo. +2. **Una trama tintada dentro del panel es invisible por construcción**: + `--_background-tint` cae en `--color-primary-solid`, que es EL MISMO valor que + pinta el panel — un halo del color del panel sobre el color del panel. El + block pasa `color="var(--color-content-on-solid)"`, el token que ya usa para + su copia; medido después, el tinte resuelve a `#ffffff`. + +**Los defaults, y por qué dos están apagados.** `cta` `rings` · `stats-band` +`grid` (una banda de cifras se lee como medida) · `testimonials` y +`feature-split` `glow`. `site-footer` y `banner` reciben la capacidad **APAGADA**: +la columna B del plan de calidad no pide acabado en ninguno de los dos, y +encenderlo por nuestra cuenta sería inventar un aspecto que nadie pidió. + +**Un desvío de alcance, declarado**: la columna B pedía «`Backdrop` alterno» POR +FILA en `feature-split`; se resuelve en la SECCIÓN. Una banda por fila obligaría +a cada `Row` a poseer el estado de alternancia, que es coordinación — y un block +que coordina deja de ser un block que no posee nada. + +**Medido en Chrome sobre la página compuesta real** (`/blocks/landing`): cinco +pilas, los cinco anfitriones adoptados (`position: relative` + `isolation: +isolate`) sin que ningún block los posicione; la copia en modo claro mide +15,88:1 sobre las secciones decoradas y 5,18:1 sobre el panel del cta — AA en +todas. Sobre lienzo oscuro, medido aparte: 17,06 → 13,23:1 con `glow` y +12,37:1 con `grid`/`dots`. + +Ledger: seis filas nuevas, **A-100…A-105**, con su mecanismo y su evidencia. + +Gates: `blocks:check` 0/18 · `rtl:check` 0/180 · `docs:check` 0/0 en 634 · +434/435 (el fallo es el `skin-media-player` de siempre) · `check` 0 errores +propios · prettier limpio. + ### F1.5 — correcciones de supervisión (para el agente, ANTES del commit de F1) | # | Qué | Cómo (exacto) | Gate | diff --git a/src/uix/blocks/banner/README.md b/src/uix/blocks/banner/README.md index 09976a118..95d55698a 100644 --- a/src/uix/blocks/banner/README.md +++ b/src/uix/blocks/banner/README.md @@ -57,6 +57,11 @@ here can be blocked, so there is no state to derive and no state to explain. ## Decisions +- **La decoración existe pero está APAGADA por defecto** (2026-08-18): un aviso de + página mide dos líneas y su trabajo es leerse; la columna B no pide acabado aquí. + La capacidad se ofrece porque una tira de marketing a veces la quiere — el block + no lo decide por el app. + **2026-07-30 — reference floor** (dossier: Tailwind Plus «Banners» 13 · Untitled UI 16 · Flowbite 5 — the most-shipped category of the whole dossier): diff --git a/src/uix/blocks/banner/banner.svelte b/src/uix/blocks/banner/banner.svelte index 921cc1a09..8fc2cf4ae 100644 --- a/src/uix/blocks/banner/banner.svelte +++ b/src/uix/blocks/banner/banner.svelte @@ -27,9 +27,11 @@ import { Banner } from '$uix/eidos/components/banner'; import { Container } from '$uix/eidos/components/container'; import { Wrap } from '$uix/eidos/components/wrap'; + import { Background } from '$uix/eidos/components/background'; import type { SiteBannerProps } from './types'; let { + decor = 'none', containerSize = 'xl', affix, affixOffset = '0px', @@ -55,6 +57,13 @@ {#snippet strip()} + {#if decor !== 'none'} + + + + + {/if} + {#if decor !== 'none'} + + + + {/if} {#if centered} {@render copy()} diff --git a/src/uix/blocks/cta/types.ts b/src/uix/blocks/cta/types.ts index e34033dae..3e7b17002 100644 --- a/src/uix/blocks/cta/types.ts +++ b/src/uix/blocks/cta/types.ts @@ -5,6 +5,7 @@ import type { SectionSize } from '$uix/eidos/components/section'; import type { HeadingLevel } from '$uix/eidos/components/heading'; import type { SurfaceProps } from '$uix/eidos/components/surface'; import type { ComponentColorProp } from '$uix/eidos/lib/types'; +import type { BackgroundPatternKind } from '$uix/eidos/components/background'; /** How the panel arranges its copy and its actions. */ export type CtaLayout = 'center' | 'justified' | 'split'; @@ -26,6 +27,24 @@ export type CtaProps = Omit, 'children' | 'title'> & * @default 'center' */ layout?: CtaLayout; + /** + * The decoration INSIDE the panel — `rings` (default) · every other + * `Background.Pattern` treatment · `none`. + * + * **The two tinted treatments cost legibility here, measured.** Over the + * solid panel `glow` and `mesh` paint a light wash exactly where the title + * sits: white copy falls from 5.18:1 to **3.06:1** and **2.27:1**, under AA. + * The line patterns (`grid` · `dots` · `lines` · `rings`) take the dark rule + * token, so they darken the panel — the copy rises to 14.35:1 and the texture + * still reads at 3.19:1. They are offered anyway; the app owns the call, and + * now it owns the number too. + * + * Their accent is the ON-SOLID ink, not the panel's colour: a glow tinted + * with the accent resolves to exactly the panel's background — a halo of the + * panel colour over the panel colour, which is nothing. + * @default 'rings' + */ + decor?: BackgroundPatternKind | 'none'; /** * Panel accent — the full colour system (role · intent · any of the 33 donor * scales · a raw CSS value). The panel is always the SOLID canvas: measured diff --git a/src/uix/blocks/feature-split/README.md b/src/uix/blocks/feature-split/README.md index 5db6f6a93..cf27a7fde 100644 --- a/src/uix/blocks/feature-split/README.md +++ b/src/uix/blocks/feature-split/README.md @@ -51,6 +51,12 @@ explain. ## Decisions +- **La decoración es `glow` por defecto** (2026-08-18), HIJA de la `Section`. + Columna B pedía «`Backdrop` alterno» por fila; se resuelve en la SECCIÓN y no + por fila a propósito: una banda por fila obligaría a cada `Row` a ser anfitriona + y a alternar su propio fondo, que es la clase de estado que un block no debe + poseer. Medido: la copia pasa de 17,06:1 a 13,23:1 en el peor punto. + **2026-07-23 — reference floor** (dossier §P1: Tailwind Plus «Features 15» · Untitled UI «Features 42» · Flowbite; the #1 gap): diff --git a/src/uix/blocks/feature-split/feature-split.svelte b/src/uix/blocks/feature-split/feature-split.svelte index 72116a2b9..88413c28f 100644 --- a/src/uix/blocks/feature-split/feature-split.svelte +++ b/src/uix/blocks/feature-split/feature-split.svelte @@ -12,9 +12,11 @@ import { Section } from '$uix/eidos/components/section'; import { Container } from '$uix/eidos/components/container'; import { Stack } from '$uix/eidos/components/stack'; + import { Background } from '$uix/eidos/components/background'; import type { FeatureSplitProps } from './types'; let { + decor = 'glow', containerSize = 'lg', sectionSize = 'xl', gap = 12, @@ -25,6 +27,16 @@
+ {#if decor !== 'none'} + + + + + {/if} {@render children?.()} diff --git a/src/uix/blocks/feature-split/types.ts b/src/uix/blocks/feature-split/types.ts index 585f9ea99..e37cefb49 100644 --- a/src/uix/blocks/feature-split/types.ts +++ b/src/uix/blocks/feature-split/types.ts @@ -7,8 +7,19 @@ import type { HeadingProps } from '$uix/eidos/components/heading'; import type { TextProps } from '$uix/eidos/components/text'; import type { GroupProps } from '$uix/eidos/components/group'; import type { ComponentColorProp } from '$uix/eidos/lib/types'; +import type { BackgroundPatternKind } from '$uix/eidos/components/background'; export type FeatureSplitProps = Omit, 'children'> & { + /** + * Section decoration — `glow` (default) · every other `Background.Pattern` + * treatment · `none`. A CHILD of the `Section`, not a wrapper around it: the + * section becomes the host through the foundation's own rule, so the band + * bleeds full-width behind the measure and the block gains no extra box. + * Reduced motion, forced colours and `prefers-contrast` are the component's + * responsibility, not the block's. + * @default 'glow' + */ + decor?: BackgroundPatternKind | 'none'; /** Content measure. Passed straight to `Container`. @default 'lg' */ containerSize?: ContainerSize; /** Block-axis padding. Passed straight to `Section`. @default 'xl' */ diff --git a/src/uix/blocks/site-footer/README.md b/src/uix/blocks/site-footer/README.md index 50fab79b9..e1621fd38 100644 --- a/src/uix/blocks/site-footer/README.md +++ b/src/uix/blocks/site-footer/README.md @@ -46,6 +46,11 @@ No state, no shape, no words. ## Decisions +- **La decoración existe pero está APAGADA por defecto** (2026-08-18): la columna + B del plan de calidad no pide acabado para el pie, y encenderlo por nuestra + cuenta sería inventar un aspecto que nadie pidió. La capacidad está para el app + que la quiera. Medido con `dots`: la copia pasa de 17,06:1 a 12,37:1. + **2026-07-30 — reference floor** (dossier: Tailwind Plus «Footers» 7 · Untitled UI 40 · Flowbite): diff --git a/src/uix/blocks/site-footer/site-footer.svelte b/src/uix/blocks/site-footer/site-footer.svelte index 25005b99c..b38dc44d4 100644 --- a/src/uix/blocks/site-footer/site-footer.svelte +++ b/src/uix/blocks/site-footer/site-footer.svelte @@ -25,9 +25,11 @@ import { AutoGrid } from '$uix/eidos/components/auto-grid'; import { Separator } from '$uix/eidos/components/separator'; import { Motion } from '$uix/eidos/components/motion'; + import { Background } from '$uix/eidos/components/background'; import type { SiteFooterProps } from './types'; let { + decor = 'none', // `lg`, the same measure `hero` / `cta` / `newsletter` default to. A footer // wider than every other section of the page reads as misaligned — verified // by composing it under a `lg` section. @@ -46,6 +48,16 @@