Las dos puertas de Mogos son hoy la misma pantalla sin marca: un formulario centrado sobre fondo blanco, sin tarjeta, con el isotipo flotando arriba a la derecha. Lo único que cambia entre el cliente y el admin es el título. La primera pantalla que ve un cliente de Mogos no dice nada de Mogos. Acá entra la aurora — el par celeste y lima sobre marino — y con ella el momento que ya existe en el link-in-bio: la placa «Importamos futuro», disparada al iniciar sesión.
No hay una decisión de diseño que revertir: hay una ausencia. Las dos apps
renderizan un max-w-md centrado sobre bg-background, el isotipo de 36×32
absolutamente posicionado arriba a la derecha, y nada más. Sin tarjeta, sin degradado, sin
ilustración, sin el wordmark. El admin ni siquiera declara type="email" en su campo de
correo, y muestra el mensaje crudo de Supabase sin traducir.
El momento del login tampoco existe: el botón se deshabilita, su texto se reemplaza por un spinner y la pantalla salta. La marca ya tiene una coreografía que la gente reconoce —la del link-in-bio, con la marca completa, el punto rojo que cae y la regla degradada— y no se usa justamente donde se abre la relación.
El cliente dice «Ingresa tu correo» (tú) y el admin dice
«Ingrese su correo» (usted). No es una decisión: es que
login/page.tsx, (auth)/layout.tsx, lib/auth/actions.ts y los
esquemas están duplicados en las dos apps y derivaron por separado. El shell aurora es la excusa
para consolidarlos.
La escena viene de las puertas de Amedi y se traduce a los cuatro colores del manual. Es una sola
receta: fondo --grad-hero en marino, dos halos radiales a la deriva —
celeste arriba a la derecha, lima abajo a la izquierda — con recorridos de 12 s y
16 s desfasados para que nunca coincidan, y el barco del manual como isotipo gigante al 7 % de
opacidad. Nada de esto es color nuevo: el degradado y el movimiento son la marca según el
propio manual.
Con la misma escena en las dos apps, un administrador que abre las dos pestañas no distingue cuál es cuál hasta leer el título. El cliente entra por el día y mira la noche (formulario claro + panel aurora); el admin es la única puerta full-noche. La diferencia se lee de reojo, y las dos siguen siendo obviamente Mogos.
Formulario claro a la izquierda —donde ya viven el registro de dos pasos y el OAuth— y panel aurora a la derecha cargando el eslogan. El wordmark real reemplaza al isotipo suelto de la esquina, la regla degradada firma el arranque, y el botón primario es marino: el color ancla sobre superficie clara.
El panel colapsa y la aurora se queda como acento del header: una banda de ~180 px con los halos, el wordmark en blanco y el eslogan; el formulario, debajo, en claro. Es el mismo comportamiento que hoy tiene la foto en el split de Amedi — el panel no se apila entero, se reduce. La placa sí ocupa la pantalla completa, igual que en escritorio.
La única puerta full-noche: la aurora ocupa toda la ventana y el formulario vive en una tarjeta de
vidrio (backdrop-filter sobre marino al 55 %). Sin OAuth, sin registro y sin enlace de
vuelta — porque el admin no los tiene. El botón primario cambia a celeste: sobre
marino, es el color que el manual asigna a los highlights, y es el que aguanta el contraste.
Es exactamente la coreografía que ya corre al cargar el link-in-bio, movida de la carga a la acción. Cuatro tiempos en 1.1 s: la marca completa entra con spring, el punto rojo cae desde arriba, la regla degradada se dibuja de izquierda a derecha y el eslogan aparece en Oswald. Todos los easings y duraciones salen de los tokens del sistema.
--ease-spring desde el 72 %.--grad-marca se dibuja con scaleX desde la izquierda.La decisión que importa no es la coreografía, es cuándo se dispara. La placa entra con el clic, en paralelo con la petición, y tiene un piso de 1.4 s. Así la latencia de la red se esconde detrás de la marca en vez de sumarse a ella: el tiempo percibido es 1.4 s, no 300 ms + 1.4 s.
Solo donde se abre una sesión: el login de las dos puertas, el regreso de
Google, el último paso del registro y activate.
Ni en olvidé-contraseña, ni al pedir un OTP, ni en el logout. Ahí el botón conserva su spinner: la placa no es un indicador de carga de uso general.
Un usuario que entra tres veces al día ve la placa tres veces. Por eso el piso son 1.4 s y no los 2.2 s del splash del link-in-bio, que solo se ve una vez.
Con OAuth el navegador se va: signInWithOAuth redirige a Google y cualquier animación
lanzada en el clic la corta la navegación. Así que la placa no va en la salida, va en el
regreso — en /auth/callback, mientras se intercambia el código por la sesión.
Que es justo donde hoy hay una pantalla en blanco de la que nadie se ocupó.
El formulario se atenúa al 42 % y el botón de Google queda aria-busy con su
spinner. Nada de celebrar todavía: el usuario aún no se ha autenticado y puede cancelar en la
pantalla de Google.
Hoy los botones de OAuth no tienen ningún estado y les falta
type="button", así que un Enter en el formulario los puede disparar.
/auth/callback pinta la placa mientras corre el intercambio de código. Si el
intercambio falla, la placa se retira y se vuelve a /login con el error — mismo
contrato que el camino de contraseña.
Efecto colateral: se acaba el flash blanco del regreso de Google, que hoy es la parte más rota del flujo.
Lleva aria-hidden. El estado real viaja por un aria-live="polite":
«Iniciando sesión…» y luego el destino o el error. Un lector de pantalla nunca oye hablar de
una placa.
Con prefers-reduced-motion no hay placa y la aurora no deriva: se navega directo
y el botón conserva el spinner que ya existe. La puerta sigue completa sin una sola
animación.
«El correo o la contraseña no coinciden. Revísalos e intenta de nuevo.» — bajo el campo, con el borde en rojo y el foco devuelto al correo. Reemplaza el mensaje crudo de Supabase que el admin muestra hoy sin traducir.
Verificado sobre las superficies reales, no token contra token: texto sobre el panel aurora y
sobre la tarjeta de vidrio. El botón celeste del admin lleva tinta marino, no blanca — sobre
#AAE4F3 el blanco no llega a AA.
La placa se retira en pageshow, como ya hace el transit del link-in-bio. Sin eso,
volver con el botón de atrás desde /account revive la página desde el bfcache
con la placa puesta y la puerta queda tapada.
Las otras nueve rutas no se redibujan: heredan el shell de su puerta. Esto es lo que cambia en cada una, y se puede implementar de a una.
| Ruta | App | Qué hereda · qué cambia | Placa |
|---|---|---|---|
| /login | client | El split completo: formulario claro + panel aurora. Es la pieza de esta propuesta. | Sí |
| /login | admin | Noche completa con tarjeta de vidrio. Botón celeste. Se traduce el error de Supabase y se arregla el type="email". | Sí |
| /register | client | El mismo split. Los dos pasos viven en el lado claro con un indicador de progreso sobre la regla degradada. | Al cerrar el paso 2 |
| /forgot-password | ambas | Solo retinte del shell. Un campo, un botón, y la confirmación en el mismo lugar en vez de otra pantalla. | No |
| /reset-password | ambas | Retinte + los requisitos de contraseña como lista que se va marcando, no como bloque de texto. | No |
| /verify-otp | client | Retinte + el código en cajitas (una por dígito) con avance y pegado automáticos. | No |
| /verify-whatsapp-otp | client | Igual que el anterior; cambia el texto de ayuda y el plate del icono a WhatsApp. | No |
| /activate | client | Retinte. Es la puerta de los usuarios migrados de v1: el copy explica por qué se les pide activar. | Sí |
| /complete-profile | client | Retinte. Ya hay sesión, así que no lleva placa: es un formulario, no una puerta. | No |
| /auth/callback | ambas | Deja de ser una pantalla en blanco: es donde vive la placa del regreso de Google. | Sí |
Las dos apps duplican (auth)/layout.tsx, login/page.tsx,
lib/auth/actions.ts, password-fields.tsx y los esquemas de Zod.
Implementar el shell dos veces sería repetir el error. La propuesta asume un solo
AuroraShell en packages/ui, parametrizado por puerta
(split o noche) — que es también lo que hace barato retintar las nueve
rutas restantes.
Una puerta bonita puede convertirse en una puerta lenta. Estos son los límites que la propuesta se pone a sí misma.
Ni Supabase, ni las server actions, ni el guardia de returnTo, ni el
window.location.assign del admin. Es una capa de presentación: si se quita, el
login sigue funcionando igual.
Hoy existe con className="hidden". O se implementa o se borra — no se dibuja un
botón apagado en la puerta principal.
Turnstile es el ship de Confianza y llega por su propia ruta. Meterlo en esta pieza mezcla dos decisiones que se validan distinto.
El logout es instantáneo. La placa dice «entraste», no «te fuiste»: usarla en los dos sentidos la vacía de significado.