diff --git a/src/uix/eidos/codex_audit.md b/src/uix/eidos/codex_audit.md
new file mode 100644
index 000000000..217cdbce6
--- /dev/null
+++ b/src/uix/eidos/codex_audit.md
@@ -0,0 +1,388 @@
+# Auditoria Codex de Eidos / UIX demos
+
+Fecha: 2026-05-23
+Rama auditada: `active-uix`
+Ambito principal: `src/uix/eidos/components/*` y demos publicas en
+`web/routes/uix/components/*`
+
+## Resumen ejecutivo
+
+El ecosistema Eidos/UIX ya tiene una base visual y documental amplia: todas las
+83 demos publicas bajo `web/routes/uix/components` cargan, renderizan `canvas`,
+`stage` y seis tabs de documentacion; no se detectaron errores de consola en la
+pasada Playwright de escritorio. Tambien hay coherencia visual general: stage
+comun, trace strip, controles agrupados, tokens Eidos, props visuales
+homogeneas y un patron compound bastante estable.
+
+Pero el resultado no puede considerarse cerrado. La auditoria automatica del
+repo marca 12 componentes como `NEEDS-WORK`, hay demos que incumplen el contrato
+obligatorio de snippets, existen gaps de Sema/playback en componentes
+interactivos y el shell `/uix` no es usable en viewport movil: todas las rutas
+auditadas desbordan horizontalmente a 390px por un problema del marco de docs.
+
+El area de mayor riesgo sigue siendo la familia de pickers/calendarios. Han
+mejorado respecto a los fallos anteriores: hay controles visibles para
+min/max, minDays/maxDays, modal/inline, footer por composicion, clear/cancel/close
+y numberOfMonths. Aun asi, DatePicker, DateRangePicker, Tooltip, MonthGrid y
+YearGrid no cumplen del todo el contrato de playback Sema/demo y necesitan tests
+funcionales especificos para apertura, seleccion, cierre, limites y navegacion.
+
+## Evidencia usada
+
+Comandos y recorridos ejecutados:
+
+- `npm run component:audit`
+- Recorrido Playwright desktop `1440x1000` sobre las 83 demos publicas.
+- Recorrido Playwright mobile `390x844` para detectar overflow del shell.
+- Capturas del stage de todas las demos en `tmp/uix-audit/screens/*.png`.
+- Hojas de contacto visuales en:
+ - `tmp/uix-audit/contact-sheet-1.png`
+ - `tmp/uix-audit/contact-sheet-2.png`
+ - `tmp/uix-audit/contact-sheet-3.png`
+- Resumen estructural en `tmp/uix-audit/quick-summary.json`.
+- Reporte canonico generado en `tmp/component-audit.md`.
+
+Nota: habia cambios previos en `src/uix/soma/components/carousel/*`. Esta
+auditoria observa el estado actual sin revertir ni tocar esos cambios.
+
+## Resultado cuantitativo
+
+### `npm run component:audit`
+
+| Metrica | Resultado |
+| --- | ---: |
+| Componentes auditados por contrato | 92 |
+| PASS | 80 |
+| NEEDS-WORK | 12 |
+| BROKEN | 0 |
+
+### Recorrido visual/funcional Playwright
+
+| Metrica | Resultado |
+| --- | ---: |
+| Demos publicas recorridas | 83 |
+| Rutas con error HTTP/consola | 0 |
+| Demos sin `data-uix-canvas-inner` | 0 |
+| Demos sin `data-uix-stage` | 0 |
+| Demos sin seis tabs declaradas | 0 |
+| Overflow desktop | 0 |
+| Overflow mobile | 83 |
+| Demos con menos de 2 bloques de snippet en Live | 5 |
+
+El dato de overflow mobile es sistemico: los valores se repiten en todas las
+rutas, por lo que apunta al shell `/uix` y no a un componente concreto.
+
+## Hallazgos P1
+
+### P1.1 — 12 componentes no pasan el auditor canonico
+
+Estos componentes no deberian declararse cerrados:
+
+| Componente | Errores principales |
+| --- | --- |
+| `alert-dialog` | Falta selector root `[data-alert-dialog]` en recipe. |
+| `button` | Verbo Sema `action` invalido, mismatch `commit.action`, falta README. |
+| `carousel` | Falta README y falta `somaSnippet` en demo. |
+| `command` | Falta README, no hay `:focus-visible`, falta APG, tipografia literal. |
+| `grid-list` | Falta README, color raw `#fff`, falta `somaSnippet`, readonly sin estilo. |
+| `link-preview` | Falta README, tipografia literal. |
+| `listbox` | Falta README, readonly sin estilo, tipografia literal. |
+| `menubar` | Falta README, tipografia literal. |
+| `navigation-menu` | Falta README, falta `somaSnippet`, falta APG. |
+| `range-calendar` | Falta README, falta `somaSnippet`, readonly sin estilo. |
+| `search-field` | No hay `:focus-visible`, falta APG, readonly sin estilo. |
+| `time-range-field` | Falta README, falta `somaSnippet`, readonly/invalid sin estilo. |
+
+Accion: cerrar primero estos 12 antes de seguir ampliando componentes. El
+script ya da la lista exacta de reglas incumplidas.
+
+### P1.2 — El shell `/uix` no es responsive en mobile
+
+En viewport `390x844`, todas las demos desbordan horizontalmente. El overflow
+detectado es practicamente constante (`+495` a `+529px`), lo que indica un
+problema del layout documental: rail/sidebar/canvas con anchura minima fija o
+grid no colapsado.
+
+Impacto:
+
+- No se puede auditar mobile por componente con fiabilidad.
+- Los overlays, popovers y pickers quedan condicionados por un marco que ya
+ esta roto.
+- La web de docs no cumple un minimo de consumo movil.
+
+Accion:
+
+- Revisar `web/routes/uix/+layout@.svelte` y `web/routes/uix/uix.css`.
+- Definir breakpoint real para ocultar/convertir sidebar en drawer.
+- Asegurar que `data-uix-canvas-inner`, tabs, stage y tablas no fuerzan
+ `min-width` por encima del viewport.
+- Repetir auditoria mobile tras corregir el shell.
+
+### P1.3 — Demos con contrato Live incompleto: falta `somaSnippet`
+
+El contrato de `DEMO_AUTHORING_GUIDE.md` exige snippets Soma y Eidos en Live.
+Faltan en:
+
+- `carousel`
+- `grid-list`
+- `navigation-menu`
+- `range-calendar`
+- `time-range-field`
+
+Impacto:
+
+- La demo no enseña el contrato headless real.
+- El consumidor ve la capa Eidos pero no la composicion Soma equivalente.
+- Rompe la promesa de separacion por capas del ecosistema.
+
+Accion: añadir `somaSnippet` reactivo y comprobar que refleja los controles
+visibles del stage.
+
+### P1.4 — Gaps de Sema/playback en componentes interactivos
+
+Varias demos interactivas no tienen playback Sema normalizado con
+`data-uix-play` o el auditor avisa que no hay `uix.events.emit(...)`.
+
+Casos relevantes:
+
+- `date-picker`: PASS con warning `D-4.3`; no hay `uix.events.emit(...)`.
+- `date-range-picker`: PASS con warning `D-4.3`; no hay `uix.events.emit(...)`.
+- `tooltip`: PASS con warning `D-4.3`; no hay playback claro.
+- `month-grid` y `year-grid`: eventos `nav-step` no siguen la forma
+ `{verb}-X` o `{family}-X`; el play usa chip/boton no estandar.
+- `button`: usa verbo Sema invalido `action`.
+- `alert-dialog`: aparece como pasivo aunque la demo muestra acciones de
+ dialogo heredadas; hay que aclarar si el evento pertenece al wrapper o al
+ compuesto.
+
+Impacto:
+
+- El usuario no puede verificar eventos desde la tab Sema de forma uniforme.
+- La documentacion vuelve ambiguo que eventos son propios, heredados o
+ compuestos.
+- Se rompe la trazabilidad Morfo -> Soma -> Sema -> Eidos.
+
+Accion:
+
+- Normalizar todos los botones de playback a `data-uix-play`.
+- Para componentes compuestos, documentar y listar eventos heredados sin decir
+ que la superficie es 0 si el stage permite acciones visibles.
+- Corregir nombres de eventos que no respetan el vocabulario Sema.
+
+### P1.5 — Pickers y calendarios siguen siendo zona de alto riesgo
+
+Estado visual observado:
+
+- `calendar` renderiza uno/dos meses con heading centrado y trace funcional.
+- `range-calendar` renderiza seleccion y rango, pero falla auditor por README y
+ `somaSnippet`.
+- `date-picker` muestra field + popover + calendar + footer de acciones.
+- `date-range-picker` muestra dos inputs, dos meses, footer y controles de
+ limites/rango.
+- `time-picker` y `time-range-picker` muestran popover con sliders y footer.
+
+Riesgos abiertos:
+
+- DatePicker/DateRangePicker no tienen playback Sema normalizado.
+- La apertura por trigger necesita test E2E estable; en una pasada automatizada
+ el selector `data-date-picker-trigger` no dejo el provider en `open`, aunque
+ la captura visual previa si lo muestra abierto.
+- RangePicker debe tener regresiones automatizadas para:
+ - seleccionar start sin desplazar al mes siguiente de forma inesperada,
+ - seleccionar end sin auto-navegar,
+ - deseleccionar solo endpoint afectado,
+ - mantener start/end con colores diferenciados,
+ - respetar `minValue`, `maxValue`, `minDays`, `maxDays`,
+ - validar min/max invalidos y surfacing via UI/logger,
+ - clear sin cierre accidental,
+ - cancel revirtiendo snapshot de apertura,
+ - modal bloqueando outside click y manteniendo escape/cierre compuesto.
+
+Accion: crear suite Playwright especifica para `calendar`, `range-calendar`,
+`date-picker`, `date-range-picker`, `time-picker` y `time-range-picker`.
+
+## Hallazgos P2
+
+### P2.1 — Warnings de CSS/token contract
+
+Hay warnings que no rompen render, pero indican drift con Eidos:
+
+- Literales tipograficos en `command`, `link-preview`, `listbox`, `menubar`,
+ `code-block`, `field`, `kbd`, `combobox`, `time-range-picker`.
+- Raw color en `grid-list` (`#fff`).
+- Estados declarados pero no estilados: `readonly`, `invalid`, segun
+ componente.
+- `:focus-visible` ausente en `command` y `search-field`.
+
+Accion:
+
+- Sustituir literales por tokens o justificar con comentario `/* literal: ... */`.
+- Eliminar raw color.
+- Estilar `readonly`/`invalid` donde Morfo los declara.
+- Añadir focus ring visible a componentes interactivos.
+
+### P2.2 — Demos con controles presentes pero valor pedagogico desigual
+
+La plantilla se aplica de forma amplia, pero no siempre con el mismo nivel de
+claridad:
+
+- Componentes complejos (`file-upload`, `stepper`, `listbox`, `grid-list`,
+ `range-calendar`, `date-range-picker`) quedan comprimidos en un stage pequeno.
+- Algunas demos muestran mucho estado en trace, pero el stage no evidencia de
+ un vistazo que cambio produjo cada control.
+- Los controles de segmentos en `date-range-picker` existen, pero necesitan
+ copy y ejemplo visual mas directo para que se entienda por que start/end
+ segments importan si el usuario tambien elige fechas en calendario.
+- `pagedNavigation` existe como control, pero deberia acompañarse de estado
+ observable: mes actual antes/despues, step esperado y diferencia cuando hay
+ dos meses.
+
+Accion:
+
+- Para componentes compuestos, ampliar el stage o usar escenarios separados
+ dentro de Live.
+- Añadir microestado visible cuando un control no modifica visualmente de forma
+ obvia el componente.
+- Evitar controles que solo cambian el snippet o una prop interna sin evidencia
+ visual inmediata.
+
+### P2.3 — Componentes pasivos con 0 eventos necesitan justificacion visible
+
+El ecosistema ya acepta componentes pasivos, pero cada demo debe justificarlo.
+Se ven casos correctos en varias paginas, pero hay que revisar que el README de
+cada componente pasivo lo deje explicitamente cerrado.
+
+Watchlist:
+
+- `avatar`
+- `breadcrumb`
+- `field`
+- `meter`
+- `progress`
+- `tooltip`
+- `time-range-field`
+
+Accion: cada README debe explicar si el componente es pasivo, estructural o si
+sus acciones pertenecen a otro componente compuesto.
+
+## Coherencia visual del ecosistema
+
+### Lo que esta bien
+
+- La shell de demo es consistente: header, meta pills, stage, trace y seis tabs.
+- El lenguaje visual Eidos es reconocible: superficies limpias, bordes suaves,
+ tokens de color, foco morado/primary, estados discretos.
+- Los componentes compound respetan en general la forma root + hijos attached.
+- El trace strip ayuda a ver eventos y estado en componentes interactivos.
+- La mayoria de componentes tienen controles suficientes para explorar size,
+ variant, color, estado y comportamiento.
+- No hay rutas rotas ni errores de consola en desktop.
+
+### Lo que baja el nivel
+
+- El layout movil de docs esta roto.
+- La auditoria canonica aun marca 12 componentes como no cerrados.
+- Hay demos que no cumplen la plantilla obligatoria.
+- Falta una politica cerrada para eventos compuestos/heredados.
+- Algunos componentes grandes se ven mas como prueba tecnica que como demo
+ pedagogica de producto.
+- La capa visual depende demasiado de que el usuario sepa interpretar trace y
+ controles; en varios casos el stage deberia explicar por si mismo el cambio.
+
+## Inventario de demos publicas auditadas
+
+Renderizan sin error y con stage:
+
+`accordion`, `alert-dialog`, `aspect-ratio`, `auto-grid`, `avatar`, `banner`,
+`box`, `breadcrumb`, `button`, `calendar`, `carousel`, `checkbox`, `code`,
+`code-block`, `collapsible`, `color-field`, `color-picker`, `combobox`,
+`command`, `container`, `context-menu`, `date-field`, `date-picker`,
+`date-range-field`, `date-range-picker`, `dialog`, `display`, `drawer`,
+`dropdown-menu`, `editable`, `field`, `file-upload`, `flex`, `float`, `form`,
+`grid`, `grid-list`, `group`, `heading`, `highlight`, `icon`, `kbd`, `link`,
+`link-preview`, `listbox`, `mark`, `menubar`, `meter`, `month-grid`,
+`navigation-menu`, `number-field`, `pagination`, `pin-input`, `popover`,
+`progress`, `radio-group`, `range-calendar`, `rating-group`, `scroll-area`,
+`search-field`, `section`, `select`, `separator`, `slider`, `splitter`,
+`stack`, `stepper`, `switch`, `tabs`, `tag-group`, `tags-input`, `text`,
+`time-field`, `time-picker`, `time-range-field`, `time-range-picker`, `toast`,
+`toggle`, `toggle-group`, `toolbar`, `tooltip`, `wrap`, `year-grid`.
+
+## Componentes/contratos sin demo publica en `/uix/components`
+
+El auditor de contratos ve componentes que no tienen demo publica Eidos:
+
+- `announce`
+- `clipboard`
+- `drag-drop`
+- `feed`
+- `table`
+- `tree-grid`
+- `tree-view`
+- `virtual-grid`
+- `virtual-list`
+
+Esto puede ser correcto si son headless, internos, pendientes o no publicos,
+pero debe constar explicitamente en el mapa de componentes de la web.
+
+Tambien existen piezas Eidos internas sin demo publica directa:
+
+- `_layout`
+- `picker-shell`
+- `svg`
+
+`svg` ya esta documentado como helper interno; `picker-shell` deberia quedar
+marcado como interno en README/indice para evitar que parezca una omision.
+
+## Matriz de saneamiento recomendada
+
+### Fase 1 — Bloqueantes de contrato
+
+1. Corregir los 12 `NEEDS-WORK` del `component:audit`.
+2. Añadir READMEs faltantes.
+3. Añadir `somaSnippet` en las cinco demos incompletas.
+4. Corregir `button` Sema verb y eventos `nav-step`.
+5. Añadir `:focus-visible` en `command` y `search-field`.
+6. Eliminar raw color y literales tipograficos no justificados.
+
+### Fase 2 — Shell de docs
+
+1. Hacer responsive `web/routes/uix`.
+2. Repetir auditoria mobile.
+3. Asegurar que tablas, snippets y stages se desplazan internamente sin romper
+ el viewport.
+
+### Fase 3 — Semantica y demos
+
+1. Normalizar `data-uix-play` y `uix.events.emit(...)`.
+2. Documentar eventos heredados en componentes compuestos.
+3. Revisar todos los componentes marcados como 0 eventos.
+4. Convertir los controles no evidentes en cambios observables.
+
+### Fase 4 — Pickers/calendarios
+
+1. Tests E2E para DatePicker y DateRangePicker.
+2. Tests E2E para Calendar y RangeCalendar.
+3. Tests E2E para TimePicker y TimeRangePicker.
+4. Casos obligatorios: uno/dos meses, modal/no-modal, min/max, minDays/maxDays,
+ clear, cancel, close, seleccion/deseleccion parcial, navegacion paged y
+ granularidad `date/month/year` o `hour/minute/second`.
+
+### Fase 5 — Visual QA repetible
+
+1. Mantener un script de capturas del stage por componente.
+2. Generar hoja de contacto por batch.
+3. Comparar desktop y mobile tras cada tanda.
+4. No declarar cerrado un componente compuesto sin captura abierta de su
+ overlay/popup/menu.
+
+## Veredicto
+
+Eidos/UIX esta en una fase avanzada de cobertura, pero todavia no en una fase
+cerrada de calidad. La base visual es coherente y la arquitectura por capas se
+ve en las demos, pero los gaps actuales son de contrato, demo y semantica, no
+solo de CSS.
+
+El siguiente trabajo correcto no es crear mas componentes: es cerrar los 12
+`NEEDS-WORK`, arreglar el shell mobile, normalizar Sema/playback y blindar los
+pickers con pruebas visuales y funcionales especificas.
diff --git a/src/uix/eidos/components/carousel/carousel-context.ts b/src/uix/eidos/components/carousel/carousel-context.ts
index 2a9064fb7..09ba9a57c 100644
--- a/src/uix/eidos/components/carousel/carousel-context.ts
+++ b/src/uix/eidos/components/carousel/carousel-context.ts
@@ -1,15 +1,17 @@
import { getContext, setContext } from 'svelte';
import type { CarouselColor, CarouselSize, CarouselVariant } from './types';
+import type { Orientation } from '$soma/components/carousel';
/**
* Eidos-only context: visual concerns shared from the Provider down to
- * sub-parts (prev/next triggers consume `size`, indicators consume
- * `size` + `color`).
+ * sub-parts (prev/next triggers consume `size` + `orientation` so their
+ * chevron rotates correctly; indicators consume `size` + `color`).
*/
export type CarouselEidosContext = {
size: CarouselSize;
variant: CarouselVariant;
color: CarouselColor;
+ orientation: Orientation;
};
const KEY = Symbol('eidos:carousel');
diff --git a/src/uix/eidos/components/carousel/carousel-next-trigger.svelte b/src/uix/eidos/components/carousel/carousel-next-trigger.svelte
index fadfa9b51..fe77be667 100644
--- a/src/uix/eidos/components/carousel/carousel-next-trigger.svelte
+++ b/src/uix/eidos/components/carousel/carousel-next-trigger.svelte
@@ -24,10 +24,12 @@
const carousel = getCarouselEidosContext();
const resolvedSize = $derived(size ?? carousel?.size ?? 'md');
+ // In vertical orientation `next` means "go down" — chevron mirrors.
+ const chevronDir = $derived(carousel?.orientation === 'vertical' ? 'down' : 'right');
{#snippet defaultIcon()}
-
+
{/snippet}
diff --git a/src/uix/eidos/components/carousel/carousel-prev-trigger.svelte b/src/uix/eidos/components/carousel/carousel-prev-trigger.svelte
index c408e0d60..ad321858f 100644
--- a/src/uix/eidos/components/carousel/carousel-prev-trigger.svelte
+++ b/src/uix/eidos/components/carousel/carousel-prev-trigger.svelte
@@ -29,10 +29,12 @@
const carousel = getCarouselEidosContext();
const resolvedSize = $derived(size ?? carousel?.size ?? 'md');
+ // In vertical orientation `prev` means "go up" — chevron mirrors.
+ const chevronDir = $derived(carousel?.orientation === 'vertical' ? 'up' : 'left');
{#snippet defaultIcon()}
-
+
{/snippet}
diff --git a/src/uix/eidos/components/carousel/carousel.svelte b/src/uix/eidos/components/carousel/carousel.svelte
index 8e8633655..cc3b55e49 100644
--- a/src/uix/eidos/components/carousel/carousel.svelte
+++ b/src/uix/eidos/components/carousel/carousel.svelte
@@ -17,6 +17,7 @@
block = true,
verticalBlockSize,
value = $bindable(0),
+ orientation = 'horizontal',
style,
children: bodyContent,
...rest
@@ -45,6 +46,9 @@
},
get color() {
return color;
+ },
+ get orientation() {
+ return orientation;
}
});
@@ -52,6 +56,7 @@