feat: landing page completa de RyNext con React, Tailwind v4 y Vite

This commit is contained in:
NolbertoChagala committed 2026-08-04 19:01:54 -05:00
commit e261394133
31 files changed
+16562

No files matched your search

+67
View File
@@ -0,0 +1,67 @@
import { X, Mail } from 'lucide-react';
import type { ModalProps } from '../types';
const supportEmail = '[email protected]';
const mailToHref = `mailto:${supportEmail}?subject=${encodeURIComponent('Consulta RyNext')}&body=${encodeURIComponent('Hola RyNext,\n\nQuiero agendar una conversación sobre un proyecto.\n\nGracias.')}`;
export const ContactModal = ({ isOpen, onClose, isNavyBg }: ModalProps) => {
if (!isOpen) return null;
return (
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/60 backdrop-blur-sm animate-fadeIn">
<div
className={`relative w-full max-w-md rounded-2xl border p-8 shadow-2xl transition-all ${
isNavyBg
? 'border-white/20 bg-brand-navy text-white'
: 'border-gray-200 bg-white text-brand-black'
}`}
>
<button
onClick={onClose}
className="absolute right-4 top-4 cursor-pointer text-gray-400 transition-colors hover:text-brand-blue"
aria-label="Cerrar modal"
>
<X size={24} />
</button>
<div className="text-center">
<div className="mx-auto mb-4 flex h-12 w-12 items-center justify-center rounded-full bg-brand-blue/20 text-brand-blue">
<Mail size={24} />
</div>
<h3 className="mb-2 text-2xl font-bold">Ponte en Contacto</h3>
<p className={`mb-6 text-sm ${isNavyBg ? 'text-slate-300' : 'text-gray-600'}`}>
Puedes escribirnos directamente a nuestro correo oficial de atención y tu cliente de correo se abrirá automáticamente.
</p>
<div className={`mb-6 rounded-xl border p-4 ${isNavyBg ? 'border-brand-blue/30 bg-brand-blue/10' : 'border-brand-blue/30 bg-brand-blue/5'}`}>
<p className="mb-1 text-xs font-semibold tracking-[0.08em] text-brand-blue">
Correo electrónico
</p>
<a
href={mailToHref}
className="block font-mono text-base font-medium underline decoration-brand-blue/50 underline-offset-4"
aria-label="Enviar correo a soporte de RyNext"
>
{supportEmail}
</a>
</div>
<div className="grid gap-3 sm:grid-cols-2">
<a
href={mailToHref}
className="inline-flex cursor-pointer items-center justify-center rounded-xl bg-brand-blue px-4 py-3 text-sm font-bold text-white transition hover:bg-brand-blue/90"
>
Enviar correo
</a>
<button
onClick={onClose}
className="cursor-pointer rounded-xl border border-brand-navy/15 bg-white px-4 py-3 text-sm font-bold text-brand-navy transition hover:border-brand-blue hover:text-brand-blue"
>
Entendido
</button>
</div>
</div>
</div>
</div>
);
};
+28
View File
@@ -0,0 +1,28 @@
import { ArrowRight } from 'lucide-react';
import type { ThemeProps } from '../types';
export const CtaBanner = ({ onOpenContact }: ThemeProps & { onOpenContact: () => void }) => {
return (
<section className="relative overflow-hidden bg-[linear-gradient(135deg,#001f5b,#0d2d78_50%,#005596)] px-6 py-24 text-white md:px-12">
<div className="absolute -left-10 top-0 h-60 w-60 rounded-full bg-brand-red/20 blur-[120px]" />
<div className="absolute bottom-0 right-0 h-72 w-72 rounded-full bg-white/10 blur-[120px]" />
<div className="absolute inset-x-0 top-0 h-16 rounded-b-[100%] bg-white/5" />
<div className="relative z-10 mx-auto max-w-5xl space-y-8 text-center">
<h2 className="text-3xl font-black leading-tight tracking-tight font-display sm:text-6xl">
¿Listo para dejar de construir con ruido y empezar con dirección?
</h2>
<p className="mx-auto max-w-2xl text-lg font-normal text-sky-100 sm:text-xl">
Agenda una conversación técnica con RyNext para revisar tu proyecto, tu stack y la ruta de evolución ideal.
</p>
<button
onClick={onOpenContact}
className="inline-flex cursor-pointer items-center gap-3 rounded-xl bg-white px-9 py-4 text-base font-bold text-brand-navy shadow-xl transition hover:scale-[1.03] hover:bg-gray-100"
>
<span>Agendar</span>
<ArrowRight size={18} />
</button>
</div>
</section>
);
};
+95
View File
@@ -0,0 +1,95 @@
import type { ThemeProps } from '../types';
export const Footer = ({ isNavyBg }: ThemeProps) => {
const isDark = isNavyBg;
return (
<footer className={`border-t px-6 py-14 md:px-12 transition-colors duration-500 ${
isDark
? 'border-white/10 bg-[linear-gradient(135deg,#001f5b,#0a2b78)] text-white'
: 'border-brand-navy/10 bg-white text-brand-black'
}`}>
<div className={`mx-auto grid max-w-7xl gap-8 text-sm md:grid-cols-5 ${isDark ? 'text-white' : 'text-brand-navy'}`}>
<div className="md:col-span-2">
<div className="mb-4 flex items-center gap-3">
<img
src={isDark ? '/icons/Logo_blanco.svg' : '/icons/Logo_negro.svg'}
alt="RyNext logo"
className="h-9 w-auto object-contain"
/>
<div className="flex items-center">
<span className={`font-display text-xl font-extrabold tracking-tight ${
isDark ? 'text-white' : 'text-brand-black'
}`}>
Ry<span className="text-brand-red">Next</span>
</span>
<span className={`ml-2 text-xs font-semibold ${isDark ? 'text-slate-300' : 'text-brand-navy/75'}`}>
— Software Studio
</span>
</div>
</div>
<p className={`max-w-md text-[13px] leading-6 ${isDark ? 'text-slate-200' : 'text-brand-navy/75'}`}>
Diseñamos productos y plataformas con foco en velocidad, estabilidad y crecimiento real de negocio.
</p>
<div className="mt-4 grid gap-2 sm:grid-cols-2">
<div className={`rounded-xl border px-3 py-2 ${isDark ? 'border-white/10 bg-white/5' : 'border-brand-navy/10 bg-[#001f5b]/5'}`}>
<p className="text-[11px] font-semibold tracking-[0.08em] text-sky-500">Operación</p>
<p className={`mt-1 text-[13px] ${isDark ? 'text-slate-200' : 'text-brand-navy/80'}`}>MX • LATAM • remoto</p>
</div>
<div className={`rounded-xl border px-3 py-2 ${isDark ? 'border-white/10 bg-white/5' : 'border-brand-navy/10 bg-[#001f5b]/5'}`}>
<p className="text-[11px] font-semibold tracking-[0.08em] text-sky-500">Entrega</p>
<p className={`mt-1 text-[13px] ${isDark ? 'text-slate-200' : 'text-brand-navy/80'}`}>Sprints • roadmap • support</p>
</div>
</div>
</div>
{/* Columna Servicios */}
<div>
<p className="mb-3 text-[11px] font-semibold tracking-[0.08em] text-sky-500">Servicios</p>
<ul className={`space-y-2 text-[13px] ${isDark ? 'text-slate-200' : 'text-brand-navy/80'}`}>
<li>Software a medida</li>
<li>Plataformas web</li>
<li>Integraciones y APIs</li>
<li>Arquitectura cloud</li>
</ul>
</div>
{/* Columna Contacto */}
<div>
<p className="mb-3 text-[11px] font-semibold tracking-[0.08em] text-sky-500">Contacto</p>
<ul className={`space-y-2 text-[13px] ${isDark ? 'text-slate-200' : 'text-brand-navy/80'}`}>
<li>
<a href="mailto:[email protected]?subject=Consulta%20RyNext" className="underline decoration-current/40 underline-offset-4 transition hover:text-brand-blue">
soporte@rynext.com.mx
</a>
</li>
<li>Cancún, Quintana Roo, México</li>
<li>Reserva de proyecto en 48h</li>
</ul>
</div>
{/* Columna Horario */}
<div>
<p className="mb-3 text-[11px] font-semibold tracking-[0.08em] text-sky-500">Horario</p>
<ul className={`space-y-2 text-[13px] ${isDark ? 'text-slate-200' : 'text-brand-navy/80'}`}>
<li>Lun–Vie 9:00–18:00</li>
<li>Reuniones por agenda</li>
<li>Soporte de proyecto</li>
<li>Consultoría técnica</li>
</ul>
</div>
</div>
{/* Copyright */}
<div className={`mx-auto mt-8 flex max-w-7xl flex-col items-center justify-between gap-4 border-t pt-6 text-[13px] sm:flex-row ${isDark ? 'border-white/10' : 'border-brand-navy/10'}`}>
<div className={isDark ? 'text-slate-200' : 'text-brand-navy/80'}>
© {new Date().getFullYear()} RyNext. Todos los derechos reservados.
</div>
</div>
</footer>
);
};
+108
View File
@@ -0,0 +1,108 @@
import { motion } from 'framer-motion';
import { ArrowRight, CheckCircle2, Shield } from 'lucide-react';
import type { HeroProps } from '../types';
export const Hero = ({ isNavyBg, onOpenContact }: HeroProps) => {
return (
<section className={`section-wave relative flex min-h-screen items-center overflow-hidden px-6 pb-24 pt-36 md:px-12 transition-colors duration-500 ${
isNavyBg ? 'bg-[#081b46] text-white' : 'bg-[#f4f9ff] text-brand-black'
}`}>
<div className={`absolute inset-x-0 top-0 h-44 ${
isNavyBg
? 'bg-[radial-gradient(circle_at_top_left,rgba(0,119,194,0.24),transparent_34%),radial-gradient(circle_at_top_right,rgba(229,9,20,0.16),transparent_30%)]'
: 'bg-[radial-gradient(circle_at_top_left,rgba(0,119,194,0.20),transparent_34%),radial-gradient(circle_at_top_right,rgba(229,9,20,0.10),transparent_30%)]'
}`} />
<div className="mx-auto grid w-full max-w-7xl grid-cols-1 items-center gap-12 lg:grid-cols-12 lg:gap-10">
<motion.div
initial={{ opacity: 0, y: 30 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.7 }}
className="space-y-8 lg:col-span-12"
>
<div className="space-y-4">
{/* Título uniforme de un solo color */}
<h1 className={`text-hero-dacodes max-w-5xl font-display transition-colors duration-500 ${
isNavyBg ? 'text-white' : 'text-[#001f5b]'
}`}>
Diseñamos software
<span className="block">
que mantiene el negocio en marcha.
</span>
</h1>
<p className={`max-w-2xl text-lg leading-relaxed sm:text-xl ${
isNavyBg ? 'text-slate-200' : 'text-gray-700'
}`}>
RyNext combina arquitectura, producto y operación para lanzar plataformas que se entiendan bien, corran rápido y puedan crecer sin romperse.
</p>
</div>
<div className="flex flex-wrap items-center gap-4 pt-2">
<button
onClick={onOpenContact}
className="group inline-flex items-center gap-3 bg-brand-red px-8 py-4 text-base font-bold text-white shadow-lg shadow-red-500/20 transition hover:scale-[1.02] hover:bg-[#b60014]"
>
<span>Agendar</span>
<ArrowRight size={18} className="transition group-hover:translate-x-1" />
</button>
<a
href="#servicios"
className={`border px-8 py-4 text-base font-semibold transition hover:scale-[1.02] ${
isNavyBg
? 'border-white/20 bg-white/5 text-white hover:bg-white/10'
: 'border-brand-navy/15 bg-white text-brand-navy hover:border-brand-blue hover:text-brand-blue'
}`}
>
Ver servicios
</a>
</div>
<div className="grid gap-4 pt-4 lg:grid-cols-3">
<div className={`rounded-[18px] border-[1.5px] p-4 ${
isNavyBg
? 'border-white/15 bg-white/5 shadow-[0_8px_30px_rgba(0,0,0,0.18)]'
: 'border-brand-navy/15 bg-white shadow-[0_10px_30px_rgba(0,31,91,0.08)]'
}`}>
<div className="mb-2 flex items-center gap-2">
<CheckCircle2 size={16} className="text-brand-blue" />
<span className={`text-sm font-semibold ${isNavyBg ? 'text-white' : 'text-brand-navy'}`}>Time to value</span>
</div>
<p className={`text-sm ${isNavyBg ? 'text-slate-200' : 'text-gray-700'}`}>
Entregas visibles desde las primeras semanas con objetivos claros.
</p>
</div>
<div className={`rounded-[18px] border-[1.5px] p-4 ${
isNavyBg
? 'border-white/15 bg-white/5 shadow-[0_8px_30px_rgba(0,0,0,0.18)]'
: 'border-brand-navy/15 bg-white shadow-[0_10px_30px_rgba(0,31,91,0.08)]'
}`}>
<div className="mb-2 flex items-center gap-2">
<CheckCircle2 size={16} className="text-brand-red" />
<span className={`text-sm font-semibold ${isNavyBg ? 'text-white' : 'text-brand-navy'}`}>Sistemas seguros</span>
</div>
<p className={`text-sm ${isNavyBg ? 'text-slate-200' : 'text-gray-700'}`}>
Infraestructura preparada para escalar con confianza y control.
</p>
</div>
<div className={`rounded-[18px] border-[1.5px] p-4 ${
isNavyBg
? 'border-white/15 bg-white/5 shadow-[0_8px_30px_rgba(0,0,0,0.18)]'
: 'border-brand-navy/15 bg-white shadow-[0_10px_30px_rgba(0,31,91,0.08)]'
}`}>
<div className="mb-2 flex items-center gap-2">
<Shield size={16} className="text-brand-blue" />
<span className={`text-sm font-semibold ${isNavyBg ? 'text-white' : 'text-brand-navy'}`}>Operación estable</span>
</div>
<p className={`text-sm ${isNavyBg ? 'text-slate-200' : 'text-gray-700'}`}>
Alianzas con dirección técnica, roadmap claro y sostenibilidad real.
</p>
</div>
</div>
</motion.div>
</div>
</section>
);
};
+67
View File
@@ -0,0 +1,67 @@
import { Sun, Moon, ArrowRight } from 'lucide-react';
import type { NavbarProps } from '../types';
export const Navbar = ({ isNavyBg, setIsNavyBg, onOpenContact }: NavbarProps) => {
return (
<header className="fixed top-0 left-0 right-0 z-50 w-full">
<div className={`w-full border-b backdrop-blur-md transition-all duration-500 ${
isNavyBg
? 'border-white/10 bg-[#001f5b]/95 text-white shadow-lg shadow-black/10'
: 'border-brand-navy/10 bg-white/95 text-brand-black shadow-sm'
}`}>
<div className="mx-auto flex max-w-7xl items-center justify-between px-6 py-4 md:px-12">
{/* Identidad / Logo */}
<div className="flex items-center gap-3">
<img
src={isNavyBg ? '/icons/Logo_blanco.svg' : '/icons/Logo_negro.svg'}
alt="RyNext logo"
className="h-10 w-auto object-contain"
/>
<span className={`font-display text-2xl font-extrabold tracking-tight ${
isNavyBg ? 'text-white' : 'text-brand-black'
}`}>
Ry<span className="text-brand-red">Next</span>
</span>
</div>
{/* Menú y Acciones (Sin 'Stack') */}
<div className="flex items-center gap-4 sm:gap-6">
<a href="#servicios" className="hidden text-sm font-semibold transition-colors hover:text-brand-red sm:block">
Servicios
</a>
<a href="#metodo" className="hidden text-sm font-semibold transition-colors hover:text-brand-red sm:block">
Método
</a>
<a href="#conveniencia" className="hidden text-sm font-semibold transition-colors hover:text-brand-red sm:block">
Conveniencia
</a>
{/* Switch de Fondo */}
<button
onClick={() => setIsNavyBg((prev) => !prev)}
className={`flex cursor-pointer items-center gap-2 rounded-lg border px-3 py-2 text-xs font-semibold transition-all ${
isNavyBg
? 'border-white/20 bg-white/5 text-white hover:bg-white/10'
: 'border-brand-navy/10 bg-[#001f5b]/5 text-brand-navy hover:bg-[#001f5b]/10'
}`}
>
{isNavyBg ? <Sun size={15} className="text-amber-400" /> : <Moon size={15} className="text-brand-navy" />}
<span className="hidden md:inline">{isNavyBg ? 'Fondo blanco' : 'Fondo azul'}</span>
</button>
{/* Botón CTA */}
<button
onClick={onOpenContact}
className="inline-flex cursor-pointer items-center gap-2 rounded-lg bg-brand-red px-5 py-2.5 text-sm font-bold text-white shadow-md shadow-red-500/20 transition hover:scale-[1.02] hover:bg-[#b60014]"
>
<span>Agendar</span>
<ArrowRight size={16} />
</button>
</div>
</div>
</div>
</header>
);
};
+155
View File
@@ -0,0 +1,155 @@
import { motion } from 'framer-motion';
import { ArrowRight, Building2, Layers3, ShieldCheck } from 'lucide-react';
import type { ThemeProps } from '../types';
const comparisonRows = [
{
criterion: 'Adaptación al negocio',
saas: 'Configuración limitada y procesos estándar.',
ry: 'Plataforma diseñada para tus reglas y operaciones.',
},
{
criterion: 'Propiedad y evolución',
saas: 'Depende del proveedor y de su roadmap.',
ry: 'Roadmap compartido con autonomía técnica real.',
},
{
criterion: 'Integraciones',
saas: 'APIs restringidas y costos extra por conectividad.',
ry: 'Arquitectura abierta para sistemas, ERPs y herramientas.',
},
{
criterion: 'Soporte y continuidad',
saas: 'Respuesta general, soporte tipo ticket.',
ry: 'Equipo senior con acompañamiento directo y operación.',
},
];
const proofCards = [
{
title: 'Diseño de experiencia',
description: 'UX orientada a adopción, claridad y flujo de trabajo real.',
icon: Layers3,
},
{
title: 'Arquitectura robusta',
description: 'Infraestructura, seguridad y escalabilidad definida desde el inicio.',
icon: ShieldCheck,
},
{
title: 'Equipo senior detrás',
description: 'Product owner, ingeniería y operación trabajando con criterio empresarial.',
icon: Building2,
},
];
export const PlatformAdvantage = ({ isNavyBg }: ThemeProps) => {
return (
<section id="conveniencia" className={`section-wave border-t border-current/10 px-6 py-28 md:px-12 transition-colors duration-500 ${
isNavyBg ? 'bg-[#071b49] text-white' : 'bg-[#f7fbff] text-brand-black'
}`}>
<div className="mx-auto max-w-7xl">
<div className="mb-14 flex flex-col gap-6 lg:flex-row lg:items-end lg:justify-between">
<div className="max-w-3xl">
<span className={`mb-3 block text-xs font-semibold tracking-[0.08em] ${
isNavyBg ? 'text-sky-200' : 'text-brand-blue'
}`}>
Conveniencia RyNext
</span>
<h2 className="text-section-title">
Detrás de cada plataforma hay un equipo senior, una arquitectura clara y una ruta con sentido.
</h2>
</div>
<p className={`max-w-xl text-base leading-relaxed ${isNavyBg ? 'text-slate-200' : 'text-gray-600'}`}>
Un sistema no solo se construye para operar: se diseña para sostener negocio, seguridad, adopción y evolución continua.
</p>
</div>
<div className={`overflow-hidden rounded-[22px] border ${isNavyBg ? 'border-white/10 bg-white/5' : 'border-brand-navy/10 bg-white'}`}>
<div className={`grid grid-cols-1 border-b text-sm font-semibold md:grid-cols-[1.1fr_0.95fr_0.95fr] ${isNavyBg ? 'border-white/10 text-sky-100' : 'border-brand-navy/10 text-brand-navy'}`}>
<div className="px-5 py-4">Criterio</div>
<div className="px-5 py-4 border-t md:border-t-0 md:border-l">Licencia SaaS</div>
<div className="px-5 py-4 border-t md:border-t-0 md:border-l">RyNext software</div>
</div>
{comparisonRows.map((row, index) => (
<div key={row.criterion} className={`grid grid-cols-1 md:grid-cols-[1.1fr_0.95fr_0.95fr] ${isNavyBg ? 'text-slate-200' : 'text-brand-navy/80'}`}>
<div className={`px-5 py-4 border-b font-semibold ${isNavyBg ? 'border-white/10 text-white' : 'border-brand-navy/10 text-brand-navy'}`}>
{row.criterion}
</div>
<div className={`px-5 py-4 border-b md:border-l ${isNavyBg ? 'border-white/10' : 'border-brand-navy/10'}`}>
{row.saas}
</div>
<div className={`px-5 py-4 border-b md:border-l ${isNavyBg ? 'border-white/10' : 'border-brand-navy/10'}`}>
{row.ry}
</div>
{index === comparisonRows.length - 1 && (
<div className={`md:col-span-3 px-5 py-4 text-xs tracking-[0.08em] ${isNavyBg ? 'text-sky-100' : 'text-brand-navy'}`}>
Resultado: menos fricción, más control y más valor real.
</div>
)}
</div>
))}
</div>
<div className="mt-8 grid gap-4 lg:grid-cols-3">
{proofCards.map((card, index) => {
const Icon = card.icon;
return (
<motion.article
key={card.title}
initial={{ opacity: 0, y: 24 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: index * 0.08 }}
className={`rounded-[18px] border p-5 ${isNavyBg
? 'border-white/10 bg-white/5 shadow-[0_10px_30px_rgba(0,0,0,0.16)]'
: 'border-brand-navy/10 bg-white shadow-[0_10px_30px_rgba(0,31,91,0.08)]'}`}
>
<div className="mb-4 flex items-center gap-3">
<div className={`rounded-xl p-3 ${isNavyBg ? 'bg-white/10 text-white' : 'bg-brand-blue/10 text-brand-blue'}`}>
<Icon size={18} />
</div>
<span className={`text-[10px] font-semibold tracking-[0.08em] ${isNavyBg ? 'text-sky-200' : 'text-brand-blue'}`}>
Capacidad real
</span>
</div>
<h3 className="mb-2 text-xl font-bold font-display">{card.title}</h3>
<p className={`text-sm leading-relaxed ${isNavyBg ? 'text-slate-200' : 'text-gray-600'}`}>{card.description}</p>
</motion.article>
);
})}
</div>
<div className={`mt-8 grid gap-4 rounded-[20px] border p-5 lg:grid-cols-[1.1fr_0.9fr] ${isNavyBg ? 'border-white/10 bg-white/5' : 'border-brand-navy/10 bg-white'}`}>
<div>
<p className={`mb-3 text-[10px] font-semibold tracking-[0.08em] ${isNavyBg ? 'text-sky-200' : 'text-brand-blue'}`}>
Visión operativa
</p>
<h3 className="mb-3 text-2xl font-bold font-display">Una plataforma respaldada por una operación empresarial madura.</h3>
<p className={`max-w-2xl text-sm leading-relaxed ${isNavyBg ? 'text-slate-200' : 'text-gray-600'}`}>
No entregamos simplemente una solución “bonita”. Dejanos una base técnica diseñada para crecer, sostener usuarios, automatizar procesos y poner a tu negocio en una ruta clara.
</p>
</div>
<div className={`rounded-[18px] border p-4 ${isNavyBg ? 'border-white/10 bg-[#081b46]' : 'border-brand-navy/10 bg-[#001f5b]/5'}`}>
<div className="mb-3 flex items-center justify-between">
<span className={`text-[10px] font-semibold tracking-[0.08em] ${isNavyBg ? 'text-sky-200' : 'text-brand-blue'}`}>Resumen ejecutivo</span>
<ArrowRight size={16} className={isNavyBg ? 'text-sky-200' : 'text-brand-blue'} />
</div>
<div className="space-y-3 text-sm">
<div className={`rounded-xl border px-3 py-2 ${isNavyBg ? 'border-white/10 bg-white/5 text-slate-200' : 'border-brand-navy/10 bg-white text-brand-navy'}`}>
<strong className="font-bold">Sin bloqueo del proveedor</strong>
<div className="mt-1">Tu roadmap y evolución no dependen de una licencia estándar.</div>
</div>
<div className={`rounded-xl border px-3 py-2 ${isNavyBg ? 'border-white/10 bg-white/5 text-slate-200' : 'border-brand-navy/10 bg-white text-brand-navy'}`}>
<strong className="font-bold">Equipo con criterio</strong>
<div className="mt-1">Diseño, ingeniería, integración y soporte en una sola visión.</div>
</div>
</div>
</div>
</div>
</div>
</section>
);
};
+51
View File
@@ -0,0 +1,51 @@
import { motion } from 'framer-motion';
import type { ThemeProps } from '../types';
const steps = [
{ step: '01', title: 'Diagnóstico y mapa de valor', desc: 'Auditamos tu stack actual, objetivos de negocio y fricción operativa para definir una ruta técnica precisa.' },
{ step: '02', title: 'Diseño de solución', desc: 'Estructuramos arquitectura, alcance, experiencia y entregables con una visión clara, realista y escalable.' },
{ step: '03', title: 'Construcción con control', desc: 'Desarrollamos en sprints con entregables medibles, calidad técnica y coordinación constante con tu equipo.' },
{ step: '04', title: 'Entrega y evolución', desc: 'Publicamos en la nube, transferimos conocimiento y dejamos una plataforma lista para crecer con seguridad.' },
];
export const Process = ({ isNavyBg }: ThemeProps) => {
return (
<section id="metodo" className={`section-wave border-t border-current/10 px-6 py-28 md:px-12 ${
isNavyBg ? 'bg-[#0a2b7a] text-white' : 'bg-[#f7fbff] text-brand-black'
}`}>
<div className="mx-auto max-w-7xl">
<div className="mb-16">
<span className={`mb-3 block text-xs font-semibold tracking-[0.08em] ${
isNavyBg ? 'text-sky-200' : 'text-brand-blue'
}`}>
Método RyNext
</span>
<h2 className="max-w-3xl text-section-title">
Un proceso que mantiene foco, velocidad y resultados concretos.
</h2>
</div>
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-4">
{steps.map((item, index) => (
<motion.div
key={item.step}
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: index * 0.1 }}
className={`rounded-[16px] border p-6 ${
isNavyBg
? 'border-white/10 bg-white/5'
: 'border-gray-200 bg-white shadow-sm'
}`}
>
<div className={`mb-4 text-4xl font-black ${isNavyBg ? 'text-sky-200' : 'text-brand-blue'}`}>{item.step}</div>
<h3 className="mb-3 text-xl font-bold font-display">{item.title}</h3>
<p className={`text-sm leading-relaxed ${isNavyBg ? 'text-slate-200' : 'text-gray-600'}`}>{item.desc}</p>
</motion.div>
))}
</div>
</div>
</section>
);
};
+64
View File
@@ -0,0 +1,64 @@
import { motion } from 'framer-motion';
import { ArrowUpRight } from 'lucide-react';
import type { ThemeProps } from '../types';
import { servicesData } from '../data/servicesData';
export const Services = ({ isNavyBg }: ThemeProps) => {
return (
<section id="servicios" className={`section-wave border-t border-current/10 px-6 py-28 md:px-12 transition-colors duration-500 ${
isNavyBg ? 'bg-[#0a2b7a] text-white' : 'bg-[#f7fbff] text-brand-black'
}`}>
<div className="mx-auto max-w-7xl">
<div className="mb-16 flex flex-col justify-between gap-8 md:flex-row md:items-end">
<div>
<span className={`mb-3 block text-xs font-semibold tracking-[0.08em] ${
isNavyBg ? 'text-sky-200' : 'text-brand-blue'
}`}>
Servicios RyNext
</span>
<h2 className="max-w-2xl text-section-title">
Soluciones que conectan producto, infraestructura y crecimiento.
</h2>
</div>
<p className={`max-w-xl text-base leading-relaxed ${isNavyBg ? 'text-slate-200' : 'text-gray-600'}`}>
No trabajamos con plantillas. Diseñamos ecosistemas de tecnología a medida para que tu operación gane velocidad, claridad y control.
</p>
</div>
<div className="grid gap-5 md:grid-cols-2">
{servicesData.map((service, index) => {
const Icon = service.icon;
return (
<motion.article
key={service.id}
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, margin: '-40px' }}
transition={{ duration: 0.5, delay: index * 0.08 }}
className={`group rounded-[16px] border p-6 transition-all duration-300 hover:-translate-y-1 ${
isNavyBg
? 'border-white/10 bg-white/5 hover:border-brand-blue/50 hover:bg-white/10'
: 'border-gray-200 bg-white hover:border-brand-blue/40 hover:shadow-xl'
}`}
>
<div className="mb-5 flex items-center justify-between">
<div className="flex items-center gap-4">
<span className={`text-sm font-semibold ${isNavyBg ? 'text-sky-200' : 'text-brand-blue'}`}>0{service.id}</span>
<div className={`rounded-xl p-3 ${isNavyBg ? 'bg-white/10 text-white' : 'bg-brand-blue/10 text-brand-blue'}`}>
<Icon size={20} />
</div>
</div>
<ArrowUpRight size={18} className={`opacity-70 transition ${isNavyBg ? 'text-sky-200' : 'text-brand-blue'} group-hover:translate-x-0.5 group-hover:-translate-y-0.5`} />
</div>
<h3 className="mb-3 text-2xl font-bold font-display">{service.title}</h3>
<p className={`max-w-lg text-sm leading-relaxed ${isNavyBg ? 'text-slate-200' : 'text-gray-600'}`}>{service.description}</p>
</motion.article>
);
})}
</div>
</div>
</section>
);
};