Cierra el tramo C de F2b. El único block cuya fase 0 fue jurídica antes que
visual: las referencias shippean el aviso como markup, y el markup no puede
impedir las tres cosas que lo vuelven ilegal — un rechazo debilitado,
categorías premarcadas, y cerrar tratado como consentir.
Aquí son el tipo y el constructor. `essential: true` hace inescribible una UI
que ofrezca apagarlo; `initialConsent()` no admite semilla, así que una primera
pregunta no puede llegar marcada; `onDecision` es obligatoria, así que un aviso
que no informa de vuelta no se puede montar. Las cinco reglas están numeradas en
consent.ts y afirmadas por 8 tests, porque son justo lo que un refactor rompe en
silencio mientras todo sigue pintando bien.
Desviación de la ficha, y a favor: UNA llamada requerida `onDecision(consent,
via)` en vez de `onAcceptAll` + `onRejectAll`. Con dos callbacks el consumidor
podía pasar un no-op a «rechazar»; aquí el camino de rechazo lo renderiza el
block y el API no expone knob para degradarlo. Medido: las dos acciones tienen
idéntico relleno, tinta, borde, tamaño, peso y alto — 5.96:1 en claro, 8.79:1 en
oscuro.
Tres cosas se arreglaron por mirar, no por deducir. La barra era un `Card`
outline y midió 1.00:1 contra la página: se disolvía en ella, así que va al
plano `overlay` del sistema, el mismo que estampa cada superficie flotante del
canon. A 375 las tres acciones envolvían con «rechazar» en una fila y «aceptar»
en la siguiente, leyéndose como dos botones ajenos justo donde la pareja más
importa: ahora son un `Group`, y el markup lo dice. Y el panel devolvía el foco
a un nodo muerto — se devuelve aquí, un frame después de que la trampa se
desarme, con un pestillo para que el asentamiento del montaje no le robe el foco
a nadie al cargar.
Tres gaps de canon salieron al componerlo, todos en el README: `Button` acepta
`ref` y no lo reenvía (forma de A-94), `Switch` no tiene parte de etiqueta, y el
`Dialog` restaura el foco a un nodo muerto cuando su disparador se desmontó.
El instrumento mintió antes que el código, otra vez: el pane del navegador no
compone frames, así que la animación de salida no termina y un diálogo cerrado
sigue pintado — el foco medido allí era ficción. Y `fillStyle` no normaliza
oklch, así que todo color leído del estilo computado se volvió negro y dio
1.11:1 sobre texto perfectamente legible. Las cifras de esta ficha se miden por
píxel, en Chrome real.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>