F3.1 del tier, con su fase 0 firmada delante. El block que faltaba: el que
POSEE las regiones de una página de aplicación — sus landmarks, sus enlaces de
salto y sus alturas.
**A-95 se cierra por construcción, no compensando.** Bajo `scroll="main"` no
hay nada fijo: el aviso es una fila, el cromo es una fila y la página es la fila
que se desplaza. Medido con la tira puesta: aviso [0,54], cabecera [54,85],
**solape 0**, y el hit-test en el centro de la cabecera cae en la cabecera
(antes: 49px de solape y el clic en la tira). El eje `scroll` es el que Mantine
expone como `mode` y Atlassian como `isFixed` por slot; `body` existe porque
`docs-shell` lo necesitará para anclas y TOC.
Compone `Sidebar` (sus tres colapsos, su drawer móvil, sus dos landmarks),
`SkipLink`, `Sticky`, `Grid`/`Flex`/`Box`. Sin `.css`. Coordina tres booleanos
(`navOpen · asideOpen · mobile`) por contexto, sin máquina y sin palabras: nada
en un shell puede bloquearse, así que no hay frase que decir.
Medido en navegador (Playwright; 1280 y 375, claro y oscuro, LTR y RTL):
- landmarks por construcción — 1 banner · 1 main · 2 navigation NOMBRADOS ·
2 complementary NOMBRADOS · 1 contentinfo; encabezados 1-2-2-2-2 sin saltos.
- `scroll="main"`: documento 720 = viewport, el main scrollea dentro y la
cabecera se queda en 0 tras desplazar 900px. `scroll="body"`: el documento
scrollea y la cabecera SE PEGA (top 0 a 900px de scroll).
- teclado: los tres enlaces de salto son las tres primeras paradas y Enter deja
el foco en el `<main>`.
- 375: el raíl es drawer, devuelve el foco al trigger con Escape, el aside se
pliega y el documento no crece. RTL: sin desbordamiento horizontal, raíl a la
derecha, aside a la izquierda.
Cuatro averías que sólo aparecieron midiendo, y las cuatro son doctrina ahora:
1. `minHeight` es un SUELO, no un techo: con `100dvh` ahí el documento crecía
con el contenido. Es `height`.
2. Un grid que sólo declara filas tiene UNA columna implícita `auto`, que se
encoge a su contenido: la página salía en una tira de 32px al lado del raíl.
3. `Box` declara `flex-grow/shrink/basis`, así que pisa el `flex: 1 1 auto` de
la receta del inset. Quien está más abajo en el árbol tiene que PEDIR crecer.
4. Un ancestro con `overflow` se lleva el `position: sticky` de dentro. El
`overflow: auto` de `Sidebar.Inset` dejaba la barra sin pegar bajo `body`
mientras `data-stuck` decía que sí — el atributo dando la razón a una página
que no la tenía. Por eso el shell pone su propia caja: gap de canon anotado
(el inset debería dejar elegir si es contenedor de scroll).
**Y una avería del ARNÉS que este block destapó**: los 19 previews del tier
llevaban los 8px de margen por defecto del navegador, así que ningún block se
enseñaba a sangre — contra la regla dura del propio tier. Medido:
`x: 8, y: 8, w: 1264` en 1280, la página compuesta incluida, cuyo README cita
cifras a sangre. Invisible porque todos scrollean; deja de serlo con un shell
que llena el viewport. Arreglado en el reset del arnés.
De paso, en el canon `skip-link`: el enlace del panel complementario decía «Ir
a la barra lateral», que es como todo el mundo llama al raíl de NAVEGACIÓN. En
una página que tiene los dos, nombraba al que no era. Ahora «Ir al panel
lateral».
Guards: `blocks:check` verde con 19 blocks · `docs:check` 0/0 (638) ·
`svelte-check` 74, ninguno aquí.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>