diff --git a/docs/next-features.md b/docs/next-features.md index b881d2e3a..c9eabf20c 100644 --- a/docs/next-features.md +++ b/docs/next-features.md @@ -27,7 +27,7 @@ Detail lives in the linked doc, never copied here. > **Stage 2 CLOSED (2026-07-20) — no solver needed.** The 6 decisions were > locked (D1 band · D2 measured-pass · D3 flip-only · D4 opt-in · D5 runtime-first > · D6 now), then **execution disproved the premise**: the template morph does not -> *compute* text contrast, it **inherits** it (steps 11/12 copy the donor's L-curve +> _compute_ text contrast, it **inherits** it (steps 11/12 copy the donor's L-curve > verbatim; L-driven contrast is ~chroma-invariant under gamut-mapping), so any > scale generated from a §40-compliant donor library clears the ratified text > floors **by construction**. Verified on three banks — authored base, leave-one-out @@ -119,7 +119,7 @@ far, to seed its scope: verdict, 2026-07-07, audit B.1): segment height derives from the SIZE axis at the FIELD family level — `field` recipe declares `segment-height` with size-scoped declarations (`calc(var(--field-control-height-{k}) - - var(--space-2))`; the TSC `size:` scope axis exists, unused so far), and +var(--space-2))`; the TSC `size:` scope axis exists, unused so far), and the per-component copies die (each x-field today re-declares the whole `height-{xs..xl}` family the field recipe already has). **MANDATED by the B.1-(i) verdict**: date/time/color-field MUST incorporate the Field @@ -164,7 +164,7 @@ the vocabulary gained the alpha `surface`/`surface-hover` + `hover` slots. never a scissor; expression waits animation-finish after the hold, capped by an absolute `MAX_EXPRESSION_WAIT_MS`, never derived from the hold) is recorded in [`decisions/book-deviations.md`](./decisions/book-deviations.md) D.12 as a -candidate **editorial appendix** for the book (*Diseñando lo que ocurre*, +candidate **editorial appendix** for the book (_Diseñando lo que ocurre_, HOMOGENEIZADO edition) — the book gives qualitative regions and this is the materialization doctrine worth feeding back to the source. @@ -240,6 +240,14 @@ navigation tree); parity-floor = v1 scope policy; F2 = **14** site blocks (+banner · team · contact · content-section); distribution registered as §9; ⌘K stays app-land. +**F3 STARTED 2026-08-19** — `app-shell` shipped with a signed phase 0 (four +decisions: the block wires no services, two scroll models by prop, the top bar +inside the inset, generated bypass links) and a new canon component in front of +it, `SkipLink` (WCAG 2.4.1). It closes ledger row **A-95**, the one thing the +tier could not fix from inside any block: with the shell owning the page's +heights, an in-flow notice and a pinned header overlap by **0px** (measured; +before: 49px, with the hit test landing on the strip). + **Deps**: `scheduler` block gated on `chronos` landing; chat-room block explicitly NOT here (canon `chat-*` family, §7 above). @@ -282,7 +290,7 @@ same encoder: - **Codabar · MSI · Pharmacode** — the niche tail JsBarcode still ships. Pure table work: each is a symbology module + its vectors. -- **GS1-128 (FNC1 + Application Identifier parsing)** — a *profile* of Code 128, +- **GS1-128 (FNC1 + Application Identifier parsing)** — a _profile_ of Code 128, not a new encoder: the FNC1 code value plus an AI grammar so the HRI can print the bracketed form. The natural pair for a logistics-facing app, and the same shape the ISBN profile already established. diff --git a/docs/process/AUDIT-blocks-ledger.md b/docs/process/AUDIT-blocks-ledger.md index f6f9179fb..a9dc6b02e 100644 --- a/docs/process/AUDIT-blocks-ledger.md +++ b/docs/process/AUDIT-blocks-ledger.md @@ -138,7 +138,7 @@ Columna **or.** = de qué sección del documento viejo salió la fila (`C` confi | A-92 | `pricing` | doctrina | BAJA | F7 | Una restricción estructural del modelo de cascada (sólo los presets CSS participan del stagger) vive en un comentario del block y falta en §D.13 de la doctrina… | `docs/theming/motion.md` | CONFIRMADO | | A-93 | `stats-band` | doctrina | MEDIA | F7 | `Motion` no expone su momento «visto» (privado + `data-animation-pending`), así que un block no puede sincronizarse con el revelado sin violar B-6… | `src/uix/eidos/components/motion/motion.svelte` | ARREGLADO | | A-94 | `feature-grid · team · testimonials` | doctrina | MEDIA | F7 | Los tres declaran `= AutoGridProps` y ponen `{...rest}` antes de props fijadas: el consumidor tipa `align`/`width` y se descartan en silencio (A-28 ×3)… | `src/uix/blocks/testimonials/types.ts` | ARREGLADO | -| A-95 | `banner` | doctrina | MEDIA | F7 | Con `affix="top"` la tira fijada tapa la cabecera pegada y la navegación queda inalcanzable; la pieza que falta es la que posee las alturas de página (`app-shell`)… | `web/routes/blocks/banner/BannerSite.svelte` | CONFIRMADO | +| A-95 | `banner` | doctrina | MEDIA | F7 | Con `affix="top"` la tira fijada tapa la cabecera pegada y la navegación queda inalcanzable; la pieza que falta es la que posee las alturas de página (`app-shell`)… | `web/routes/blocks/banner/BannerSite.svelte` | ARREGLADO | | A-96 | `banner` | doctrina | BAJA | F7 | `affixOffset` es prop público sin control vivo en la demo, contra la regla «cada prop público, un control»… | `web/routes/blocks/banner/+page.svelte` | CONFIRMADO | | 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 | @@ -368,7 +368,7 @@ Los trece restantes, por filas vivas primero: `pricing` · `faq` · `site-header -### A-95 — CONFIRMADO · `banner` · doctrina · MEDIA +### A-95 — ARREGLADO · `banner` · doctrina · MEDIA **Mecanismo** — Con `affix="top"` la tira fijada TAPA la cabecera pegada, y la navegación del sitio queda inalcanzable mientras el aviso siga visible. Medido en `/blocks/banner/preview?affix=top` a 1280×700 con la página desplazada 800px: la tira ocupa `0..54` y el `
` del `site-header` `0..31` —se solapan—, y `document.elementFromPoint` en el centro del header devuelve LA TIRA. El apilamiento en sí es correcto y está firmado: `Affix` monta en el peldaño `--viewport-placement-z` = 150, «encima de un sticky header, debajo de menús y diálogos», y el escenario lo dice («las dos compiten por el mismo borde — por eso el aviso va por encima del cromo»). El escenario ya compensa con `padding-block-start: 3.5rem` en la página, pero eso empuja el CONTENIDO: un sticky con `top: 0` se sigue anclando donde está la tira. @@ -380,6 +380,26 @@ Los trece restantes, por filas vivas primero: `pricing` · `faq` · `site-header **Disposición** — **NO se arregla en `banner` ni en `site-header`**: la pieza que falta es la que POSEE las alturas de página y propaga los offsets, y en el plan del tier es el block `app-shell` (F3.1, sin construir). Hasta que exista, cualquier solución en el banner es un número acordado con otro nombre. Lo que sí procede ya, y es documental: que el README del block diga que `affix="top"` no está pensado para convivir con una cabecera pegada — para eso, hasta que haya shell, el app agrupa aviso y cabecera en un solo `Sticky` (⚠️ esa alternativa está RAZONADA, no medida). +**CERRADA 2026-08-19 — la pieza existe.** El block `app-shell` (F3.1) se +construyó y con él el solape desaparece por CONSTRUCCIÓN, no por compensación: +bajo `scroll="main"` el shell no fija nada. Medido en +`/blocks/app-shell/preview?scroll=main&banner=true` a 1280×720 con la tira +puesta: el aviso ocupa `[0, 54]`, la cabecera `[54, 85]`, **solape 0px**, y +`document.elementFromPoint` en el centro de la cabecera devuelve LA CABECERA. +El documento mide 720 = el viewport, así que tampoco hay página que se desplace +por debajo del cromo. + +Lo que lo resuelve no es un número mejor sino quitar la pregunta que el autor +hizo y que tumbó todas las propuestas anteriores («¿y si tenemos banners a +diferentes alturas?»): el aviso entra EN FLUJO como una fila de la rejilla, así +que su altura es la que sea — una línea, dos, o dos avisos — y la cabecera se +ancla debajo sin que nadie declare nada. + +⚠️ Sigue siendo cierto lo que la ficha decía del `Affix`: un aviso con +`affix="top"` FUERA de un shell sigue tapando una cabecera pegada, y eso no es +un defecto sino el apilamiento firmado. El README de `banner` sigue siendo el +sitio donde decirlo. + ### A-96 — CONFIRMADO · `banner` · doctrina · BAJA @@ -1979,6 +1999,16 @@ un block que no posee nada. **Evidencia** — `/blocks/landing`: `querySelectorAll('header,[role=banner]')` devuelve dos y, sin `aria-label` en la tira, uno queda anónimo en el árbol de accesibilidad. `src/uix/eidos/components/banner/banner.svelte:41`. +**Disposición (escrita 2026-08-19, con `app-shell` delante)** — Es del CANON y +sigue abierta: mientras `banner.svelte` estampe `role="banner"` después de los +rest props, ni un block ni una app pueden quitarlo. Lo que el shell aporta es +que la página deja de necesitar el apaño para OTRA cosa: sus regiones se nombran +solas, así que el único landmark sin nombre posible es el segundo `banner`. Dos +salidas, y no son excluyentes: (a) canon — estampar el `role` ANTES de los rest +props, que es la clase de precedencia «naming» donde el consumidor gana +(`reference_aria_two_class_precedence_a85`); (b) app — nombrar los dos, que es +lo único disponible hoy. Se decide en una sesión del canon, no del tier. + ### A-110 — CONFIRMADO · `feature-split` · doctrina · MEDIA **Mecanismo** — es el único block de sección sin parte `.Header`: `feature-grid`, `testimonials`, `faq` y `pricing` la tienen. Sus `Row` emiten `Title` a `level={2}` por defecto, así que una sección de tres filas aporta **tres `h2` hermanos** y la sección misma no tiene nombre. Un app puede componer el encabezado a mano como primer hijo (el root renderiza `{@render children()}` dentro de un `Stack`) y bajar las filas a `level={3}` —lo que hace la página compuesta—, pero eso es reconstruir a mano lo que el resto del tier declara. diff --git a/docs/process/CONTINUE-blocks.md b/docs/process/CONTINUE-blocks.md index 089c6e1d4..20711a82f 100644 --- a/docs/process/CONTINUE-blocks.md +++ b/docs/process/CONTINUE-blocks.md @@ -1,34 +1,81 @@ -# CONTINUE — tier blocks (handoff, act. 2026-08-18) +# CONTINUE — tier blocks (handoff, act. 2026-08-19) **Estado: F1 CERRADA (8/8) · F2 CERRADA EN UNIDADES (15/15) · saneamiento CERRADO ENTERO · fase 5 (guard endurecido) HECHA · fase 7 (contraste doctrinal) -CERRADA 15/15 · renombrado del eje de tamaño HECHO · A-99/A-98/A-93/A-68 -ARREGLADAS · F2b (ola de variedad) ✅ CERRADA ENTERA 2026-08-18, los cuatro -tramos — y con su tramo D queda cerrado también el cierre que F2 debía y no -cumplió: la página compuesta.** +CERRADA 15/15 · F2b (ola de variedad) CERRADA ENTERA con su página compuesta · +**F3 ABIERTA: F3.1 `app-shell` CONSTRUIDO Y VERIFICADO 2026-08-19**, con su +fase 0 firmada (Q1–Q4) y el canon `SkipLink` nacido delante de él.** -**18 blocks vivos**: site-header · hero · feature-grid · feature-split · pricing · +**19 blocks vivos**: site-header · hero · feature-grid · feature-split · pricing · testimonials · faq · stats-band · cta · newsletter · site-footer · banner · team · -contact · content-section · **logo-cloud** · **article-grid** · -**cookie-consent**. Más **una página compuesta**: `/blocks/landing`, con 14 de -ellos. +contact · content-section · logo-cloud · article-grid · cookie-consent · +**app-shell**. Más **una página compuesta**: `/blocks/landing`, con 14 de ellos. + +**A-95 CERRADA** (la única fila que estaba bloqueada por una pieza inexistente): +con `app-shell` el solape del aviso sobre la cabecera es **0px** y el hit-test +cae en la cabecera, medido. La ficha del ledger lleva las cifras. --- ## Por dónde entrar mañana -**Lo que TÚ dejaste pedido, y va primero: «repasar cada bloque».** Un repaso -block a block, con el tier ya completo y la página compuesta como banco de -pruebas. **No hay ficha escrita para ese repaso**: su forma se acuerda antes de -empezar — qué orden, qué se mira en cada uno, y si lo que salga se escribe en el -ledger o en el README de cada block. Pregunta antes de arrancar. - -Detrás, por orden: [§Qué queda, por orden](#qué-queda-por-orden) — las **24 filas -CONFIRMADO** del ledger (110 filas: 70 ARREGLADO · 24 CONFIRMADO · 13 REFUTADO · -3 DATO), de las que **5 nacieron el 2026-08-18** en la página compuesta. - -⚠️ Las cifras «96 filas / 64-19-13» que este handoff traía eran una foto vieja. -Las de arriba están contadas hoy sobre el fichero. +**Sigue pendiente lo que TÚ dejaste pedido: «repasar cada bloque»** — un repaso +block a block con el tier de sitio completo. **No hay ficha escrita**: su forma +se acuerda antes de empezar (qué orden, qué se mira, y si lo que salga va al +ledger o al README de cada block). Pregunta antes de arrancar. + +**Y ahora hay una segunda puerta, abierta ayer: F3 sigue.** El orden del plan es +`app-shell` (HECHO) → luego, por coste creciente, `error-page` → `user-menu` → +`notifications` → `settings` → `auth` → `dashboard` → `wizard` → `data-table` y +`kanban`. ⚠️ **Recomendación registrada, sin firmar por ti**: subir **`auth`** al +segundo puesto — es lo que a un producto real le falta de verdad, y su ficha ya +tiene anotado lo que hay que resolver en su fase 0 (cuatro vistas frente a las +seis del dominio; y dos hilos de canon abiertos que la esperan: `Form`/SIUM con +`progressive` no expone mensajes, y `ProofOfHuman` escribe su propio `status`). + +### Lo que dejó la sesión del `app-shell` (2026-08-19) + +Tres commits: `docs(blocks)` (la fase 0), `uix(skip-link)` (canon nuevo) y +`blocks(app-shell)`. + +- **Fase 0 firmada, en `PLAN-blocks.md` §F3.1** — Q1 el block NO cablea + servicios (la integración del ecosistema se demuestra en una app de + referencia, no dentro del block) · Q2 dos modelos de scroll por prop · Q3 la + cabecera dentro del inset (el provider del `Sidebar` ES la fila flex) · Q4 + canon `SkipLink` + uno por región montada. +- **`SkipLink` (canon)** — eidos-native, 1 parte, 0 eventos. Posee sus palabras + por ROL de landmark; peldaño propio de z (950, el más alto de la escalera + estática, porque un empate lo rompe el orden del DOM y este enlace es el + primer elemento). +- **Cuatro trampas de layout medidas**, todas escritas en el README del block: + `minHeight` es un suelo y no un techo · un grid que sólo declara filas tiene + una columna implícita `auto` que se encoge · `Box` declara + `flex-grow/shrink/basis` y pisa al `flex` de la receta de quien lo envuelve · + **un ancestro con `overflow` se lleva el `position: sticky` de dentro** (por + eso el shell pone su propia caja en vez de `Sidebar.Inset`). +- **Una avería del ARNÉS, no del block**: los previews del tier llevaban los 8px + de margen por defecto del navegador, así que NINGÚN block se enseñaba a + sangre (`x: 8, w: 1264` a 1280), contra la regla dura del tier — la página + compuesta incluida, cuyo README cita cifras a sangre. Arreglado en + `_lib/reset.css`. ⚠️ **Las medidas de anchura tomadas antes del 2026-08-19 + llevan ese sesgo.** +- **Gaps de canon que abrió, anotados en el README del block**: el eje `layout` + del `Sidebar` (provider ≠ fila) para una topbar a todo lo ancho, que pedirá + `docs-shell` · `Sidebar.Inset` debería dejar elegir si es contenedor de + scroll · el `Sidebar` no publica su ancho actual · F21 (los primitivos de + layout no cambian de elemento) obliga a dos declaraciones en línea sobre + `
` y `