Motion · comportamiento de marca
El movimiento que se calla.
GFC mueve la interfaz como mueve el dato: con intención y sin ruido. El movimiento explica jerarquía, da feedback y guía la lectura — nunca decora. Rápido, discreto, sobrio. Y siempre con reduce-motion respetado.
DocumentoSub-manual movimiento
Hereda deManual de identidad v2.0
Curva basecubic-bezier(.2,0,0,1)
Micro / entrada160ms / 240ms
ImplementaCSS · Framer Motion · Lottie
Intro de marca · demo en vivo
Cinco reglas que el movimiento obedece.
1
Funcional, no decorativo. Cada animación tiene un trabajo: dar feedback, mostrar relación causa-efecto, orientar en el espacio o jerarquizar. Si no explica nada, se quita.
2
Rápido y discreto. Microinteracciones 160ms; entradas 240ms; lo más lento (página/logo) ≤ 640ms. El usuario nota el resultado, no la animación.
3
Sobrio. Easing estándar/decel; sin bounce ni elástico. La marca dice "el dato manda, el gráfico se calla" — el motion también.
4
Una entrada por vista. El movimiento llamativo (hero, logo) ocurre una vez; el resto es feedback breve. Nada que distraiga de la lectura del dato.
5
Accesible siempre. prefers-reduced-motion respetado, foco visible, y nunca comunicar solo con movimiento.
Jerarquía del movimiento
Instant 80flips de estado
Fast 160hover · botones
Base 240menús · reveal
Slow 420sección
Page 640logo · loader
Regla de oro de accesibilidad. Con prefers-reduced-motion: reduce se eliminan desplazamientos y parallax; queda a lo más un fade ≤ 200ms. Loaders y la intro de logo saltan al estado final. Ya está cableado en tokens.css.
Duración
--motion-instant80msFlips de estado (checkbox, toggle)
--motion-fast160msMicrointeracciones: hover, focus, botones
--motion-base240msDropdowns, acordeones, reveal al scroll
--motion-slow420msTransición de sección, expand grande
--motion-page640msIntro de logo, transición de página, loader
Distancia + secuencia
--motion-shift-sm8pxDesplazamiento corto de entrada
--motion-shift16pxEntrada estándar (fade + up)
--motion-stagger60msRetardo entre elementos en secuencia
Curvas (easing)
--ease-standardcubic-bezier(.2,0,0,1) · por defecto
--ease-outcubic-bezier(.16,1,.3,1) · entradas
--ease-incubic-bezier(.4,0,1,1) · salidas
--ease-inoutcubic-bezier(.65,0,.35,1) · continuo
demo en vivo
Comparativa de curvas · 3s loop
standard
out
in
in-out
Fuente única. Viven en manual/tokens.css + tokens.json (objeto motion). Ningún componente define duraciones o curvas propias.
Feedback inmediato, 160 ms.
Pasa el cursor / enfoca con teclado sobre los ejemplos — son reales.
hover real
Botones — elevación sutil
Hover: translateY(-2px) + sombra, --motion-fast. Sin cambio de tamaño brusco.
focus real
Formulario — estados y validación
Correo
Inmuebles a valuar
El campo no puede quedar vacío.
Foco: anillo teal 3px + borde, --motion-fast. Error en magenta + texto (nunca solo color).
hover real
Menú desplegable
Despliegue: fade + translateY(-6→0), --motion-base con --ease-out. Origen anclado al disparador.
hover/focus real
Enlace — subrayado desde el centro
Convertimos información dispersa en decisiones defendibles y reportes que se sostienen.
clic real
Toggle — flip de estado 240ms
Notificaciones de avalúo
El pulgar viaja con --ease-out; el fondo cambia en --motion-base.
Aparecer, no irrumpir.
Al entrar en viewport, los bloques hacen fade + desplazamiento corto hacia arriba. En listas, un stagger de 60ms da ritmo de lectura. Una sola vez por elemento — al re-scrollear no se repite.
Transformopacity 0→1 · translateY 16→0
Duración--motion-base (240ms)
Curva--ease-out
Stagger60ms entre hermanos
TriggerIntersectionObserver · once · ~15% visible
No bloquear contenido. El texto debe ser legible aunque el JS no corra (estado final = visible). El reveal es realce, no requisito.
demo en vivo · loop
Reveal con stagger
I
Avalúos
comerciales · fiscales · garantía
II
Cartografía
mapas de valor por zona
III
Consultoría
mercado · viabilidad · portafolio
Cada fila entra con 60ms de retraso sobre la anterior. En producción ocurre una vez al entrar en viewport.
Intro de marca
demo · loop
Intro / carga del sitio. El wordmark hace fade + scale .94→1 (--ease-out) y debajo se traza una línea teal de izquierda a derecha. Dura ≤ --motion-page (640ms) y ocurre una sola vez por sesión — no en cada navegación.
Alternativa sobria: solo el isotipo entra por scale + fade. Evitar "dibujar" trazo a trazo el logotipo completo — es lento y poco sobrio.
Loaders / pantallas de carga
Skeleton
Spinner = isotipo con anillo teal girando (900ms lineal) — para esperas cortas indeterminadas. Skeleton con shimmer para cargar listas/tarjetas: percibe más rápido y mantiene el layout estable.
Umbral. <1s: nada o skeleton. 1–3s: spinner de marca. >3s: barra de progreso con porcentaje. Nunca dejar pantalla muerta sin feedback.
Continuidad, no cortes.
Entre páginas (SPA / Next). Cross-fade + 8px de desplazamiento, --motion-slow. Salida --ease-in, entrada --ease-out. La barra de nav permanece fija (no parpadea).
Entre secciones (scroll). Cambios de fondo navy↔paper con transición de color ≤ --motion-slow; el contenido entra con el reveal de la §03.
Hero → contenido. Regla del sub-manual web: hero C (gradiente) cede a contenido A (editorial) al scrollear, sin salto brusco.
Elemento compartido. Opcional: una tarjeta de "caso" se expande a su página de detalle (shared layout). Solo si la librería lo hace fluido; si no, cross-fade.
Sin mareo. Nada de slides horizontales largos ni zoom dramático entre páginas. La transición orienta; no es el espectáculo.
esquema
Cross-fade entre páginas
/ servicios
→
/ casos
Nav fija arriba (no transiciona). Solo el cuerpo hace cross-fade + 8px. 420ms.
/* page transition · Next + Framer Motion */
<motion.main
initial={{ opacity: 0, y: 8 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -8 }}
transition={{ duration: 0.42,
ease: [.16, 1, .3, 1] }} />
Lottie donde aporta, no por decorar.
Lottie (JSON vectorial de After Effects vía Bodymovin) es el estándar para íconos e ilustraciones animadas ligeras. En GFC se usa con criterio editorial: refuerza un concepto o un estado, no rellena.
Cuándo SÍ
Estados de éxito/envío (check que se dibuja) · íconos de servicio en hero/feature al entrar en viewport (play once) · vacíos/onboarding · micro-celebración discreta tras enviar un formulario.
Cuándo NO
Loops infinitos que distraen junto a texto · sustituir íconos del sistema estático (cap. 07) en navegación · animaciones de stock genéricas que no son de marca.
Formato.json (Lottie) · .lottie (dotLottie) comprimido
Coloresnavy · teal · lima · magenta — paleta GFC, nunca stock
Trazolineal, esquinas vivas (coherente con íconos cap. 07)
Duraciónplay once 0.6–1.2s · loop solo si es ambiente
Peso< 50 KB por ícono · lazy-load
TriggeronVisible / hover / onSuccess — no autoplay masivo
<!-- lottie-player (web component) -->
<lottie-player
src="/motion/check-avaluo.json"
autoplay mode="normal"
speed="1"
style="width:64px;height:64px">
</lottie-player>
/* respetar reduce-motion: render del frame final */
Entregable aparte. Los archivos Lottie de marca (logo, set de íconos de servicio, check de éxito) se producen en una fase de assets — este sub-manual fija la spec, no los binarios.
El gradiente oficial deriva muy lento (≈9s, ease-in-out) — da vida sin robar atención. El texto editorial queda quieto y legible encima.
Jerarquía de opciones para el hero
1 · Gradiente en movimiento (recomendado). El gradiente C deriva lento. Ligero, on-brand, sin assets pesados.
2 · Dato en movimiento. Un KPI/contador que sube o un mapa de valor que se dibuja al cargar — coherente con "el dato manda".
3 · Video de fondo. Solo si hay material propio de calidad (cartografía, drone). Silenciado, en loop, < 6s, overlay duotone navy×teal, < 2.5 MB, con poster y pausa en reduce-motion.
Nunca: video de stock genérico, autoplay con sonido, o gradiente que parpadee. El hero vende, pero con la voz sobria de GFC.
Legibilidad primero. El texto del hero mantiene contraste AA sobre la zona más clara del gradiente/video (overlay si hace falta).
Stack sugerido (proyecto 02-web · Next/React)
CSS / tokensMicro, hover, reveal simple, loaders
Framer MotionTransiciones de página, layout compartido, orquestación
IntersectionObs.Reveal al scroll (once)
lottie-playerÍconos/ilustración animada
GSAP (opcional)Solo para secuencias complejas puntuales
/* base · todo desde tokens */
.btn { transition: transform var(--motion-fast)
var(--ease-standard); }
.btn:hover { transform: translateY(-2px); }
/* reveal al entrar en viewport */
.reveal { opacity:0; transform: translateY(var(--motion-shift)); }
.reveal.in { opacity:1; transform:none;
transition: all var(--motion-base) var(--ease-out); }
/* accesibilidad — innegociable */
@media (prefers-reduced-motion: reduce) {
* { animation-duration:.01ms !important;
transition-duration:.01ms !important; } }
Presupuesto de performance
Solo transform y opacity (compositor/GPU). Nunca animar width/height/top/left.
60 fps objetivo · sin jank en scroll · will-change con moderación.
Lottie lazy + <50KB · video hero <2.5MB con poster.
El movimiento no debe degradar LCP/CLS (Core Web Vitals).
Checklist pre-publicación
☐ Todas las duraciones/curvas vienen de tokens (cero valores sueltos).
☐ prefers-reduced-motion probado (desactiva shift/parallax/loops).
☐ Foco visible en todo lo interactivo (anillo 2px teal).
☐ Contenido legible sin JS (reveal degrada a visible).
☐ Sin bounce/elástico; intro de logo 1× por sesión.
☐ 60 fps en mobile; Lottie y video dentro de presupuesto.
Una sola fuente. Si una animación necesita un valor que no existe en tokens, primero se agrega el token en tokens.css — no se hardcodea en el componente.