`lib/types.ts` ya tenia `Position`, la rejilla 3x3 FISICA, con su idioma
`Extract<Position, …>` y sus consumidores (Dialog, Drawer, Toast). Lo que no
tenia nombre era la otra: la LOGICA, escrita a mano cinco veces —
`AffixPlacement`, `FabPlacement`, `MenuDialPlacement`, `OnionPlacement` y las
cuatro esquinas de `AvatarBadgePosition`—, coincidiendo por mantenimiento manual
y no por contrato. Anadir una zona a una no llegaba a las otras cuatro.
Ahora hay `LOGICAL_POSITIONS` / `LogicalPosition` junto a `POSITIONS` /
`Position`, y las cinco estrechan desde ella. Ambas pasan a ser consts para que
`docs:vocabularies` las genere: eran las unicas props visuales compartidas que
faltaban en `docs/canon/vocabularies.md`, que ya listaba tamanos, variantes,
paletas, arquetipos y el vocabulario sema entero.
NO son dos grafias de lo mismo, y por eso ninguna sustituye a la otra: son dos
COMPORTAMIENTOS. `top-left` es la izquierda de la pantalla y no espeja nunca;
`top-start` sigue la direccion de lectura — medido hoy, de `left: 0` a
`right: 0` en RTL. La regla de eleccion queda escrita en los dos typedoc y en el
canon generado: ¿tiene que voltearse para un lector de derecha a izquierda? Una
tira fijada en `bottom-end` va en el borde de salida en ambas direcciones; un
panel que se abre a la derecha fisica porque ahi hay sitio, no.
Con eso se cierra EID-3, que el audit de julio dejo asentado como excepcion pero
marcado «placement fisico — pendiente de doctrina explicita». La doctrina ya no
esta pendiente: son dos rejillas nombradas con la regla de cuando usar cada una.
Sin cambio de comportamiento: las uniones resultantes tienen los mismos miembros
(`MenuDialPlacement` = la rejilla + `static`; `FabPlacement` = las cuatro
esquinas + `static`; `OnionPlacement` y `AffixPlacement` = la rejilla entera;
`AvatarBadgePosition` = las cuatro esquinas).
check 69 = base intacta · docs:check 0/627 · component:audit los cinco PASS ·
layer:check 0/3 · rtl 0/178 · smoke 311/311.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>