feat(secciones): puntos de inflexión y dolores, con gráfico en toda la página
Dos secciones nuevas tomadas del deck de la dueña, verbatim y sin reescribir: los 6 puntos de inflexión y los 4 dolores en primera persona. El resto de las secciones incorpora la capa gráfica: fondos de puntos, duotono sobre foto en Mecanismo y Cómo empezar, pantalla partida sí/no en Para quién, y pasos conectados con línea de progreso. Las fotos son CC BY-SA 4.0 y llevan crédito en el footer, como exige la licencia al haberlas modificado. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
5b400cb161
commit
69b4069525
25 files changed
+592
-120
No files matched your search
@@ -2,26 +2,78 @@
|
||||
|
||||
import { motion } from 'framer-motion';
|
||||
import { Container } from '@/components/primitives/Container';
|
||||
import { FondoFoto } from '@/components/primitives/FondoFoto';
|
||||
import { Icono, type IconoNombre } from '@/components/primitives/Icono';
|
||||
import { mecanismo } from '@/lib/content';
|
||||
import { fadeInUp, staggerContainer, viewportOnce, usePrefersReducedMotion, motionProps } from '@/lib/motion';
|
||||
import { fadeInUp, staggerContainer, viewportOnce, usePrefersReducedMotion, motionProps, useAutoStep } from '@/lib/motion';
|
||||
|
||||
const ICONOS: IconoNombre[] = ['inmersion', 'desafiar', 'estrategia'];
|
||||
|
||||
export function Mecanismo() {
|
||||
const reduced = usePrefersReducedMotion();
|
||||
const { active, setActive, hoverProps } = useAutoStep(mecanismo.steps.length, 3200);
|
||||
return (
|
||||
<section className="bg-azul-profundo text-white">
|
||||
<Container className="py-24 md:py-32">
|
||||
<section id="mecanismo" className="bg-azul-profundo text-white scroll-mt-24 relative overflow-hidden">
|
||||
{/* Foto: Golden Gate Bridge, Dietmar Rabich, CC BY-SA 4.0, modificada (duotono) — créditos en el footer */}
|
||||
<FondoFoto src="/images/mecanismo-bg.jpg" className="inset-0 opacity-25" wash="bg-azul-profundo/80" />
|
||||
<Container className="relative py-24 md:py-32">
|
||||
<motion.p variants={fadeInUp} initial="hidden" whileInView="visible" viewport={viewportOnce} {...motionProps(reduced)}
|
||||
className="text-xs tracking-[0.3em] uppercase font-semibold text-dorado">{mecanismo.eyebrow}</motion.p>
|
||||
className="text-xs tracking-[0.3em] uppercase font-black text-dorado">{mecanismo.eyebrow}</motion.p>
|
||||
<motion.h2 variants={fadeInUp} initial="hidden" whileInView="visible" viewport={viewportOnce} {...motionProps(reduced)}
|
||||
className="mt-4 font-sans font-bold text-3xl md:text-5xl">{mecanismo.title}</motion.h2>
|
||||
<motion.ol variants={staggerContainer} initial="hidden" whileInView="visible" viewport={viewportOnce} {...motionProps(reduced)}
|
||||
className="mt-4 font-sans font-black text-4xl md:text-6xl tracking-tight">{mecanismo.title}</motion.h2>
|
||||
|
||||
{/* Conector de pasos: avanza solo cada ~3s (se pausa con hover o si el
|
||||
usuario elige un paso), y adelanta la línea de progreso — el mismo
|
||||
lenguaje de "proceso conectado" de en-ti.com. */}
|
||||
<div {...hoverProps} className="mt-14 hidden md:flex items-center" role="tablist" aria-label="Pasos del mecanismo">
|
||||
{mecanismo.steps.map((step, i) => (
|
||||
<div key={step.n} className="flex items-center flex-1 last:flex-none">
|
||||
<button
|
||||
type="button"
|
||||
role="tab"
|
||||
aria-selected={active === i}
|
||||
aria-label={`Paso ${step.n}: ${step.name}`}
|
||||
onClick={() => setActive(i)}
|
||||
onMouseEnter={() => setActive(i)}
|
||||
className={`shrink-0 grid place-items-center w-14 h-14 rounded-full border-2 font-sans font-black text-lg transition-colors duration-300 ${
|
||||
active === i ? 'bg-dorado border-dorado text-azul-profundo' : 'border-white/25 text-white/60 hover:border-dorado/60 hover:text-white'
|
||||
}`}
|
||||
>
|
||||
{step.n}
|
||||
</button>
|
||||
{i < mecanismo.steps.length - 1 && (
|
||||
<div className="flex-1 h-px mx-2 bg-white/15 relative overflow-hidden">
|
||||
<motion.div
|
||||
className="absolute inset-y-0 left-0 w-full origin-left bg-dorado motion-reduce:transition-none"
|
||||
initial={false}
|
||||
animate={{ scaleX: active > i ? 1 : 0 }}
|
||||
transition={{ duration: 0.4, ease: 'easeOut' }}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<motion.ol variants={staggerContainer} initial="hidden" whileInView="visible" viewport={viewportOnce} {...motionProps(reduced)} {...hoverProps}
|
||||
className="mt-12 grid gap-10 md:grid-cols-3">
|
||||
{mecanismo.steps.map((step) => (
|
||||
<motion.li key={step.n} variants={fadeInUp}
|
||||
className="border-t border-dorado/30 pt-6 transition-all duration-300 ease-out hover:-translate-y-1.5 hover:border-dorado/70 motion-reduce:transform-none motion-reduce:transition-none">
|
||||
<div className="font-sans font-black text-5xl md:text-6xl text-dorado leading-none">{step.n}</div>
|
||||
<h3 className="mt-4 font-sans font-bold text-xl">{step.name}</h3>
|
||||
<p className="mt-3 text-gris-medio leading-relaxed">{step.desc}</p>
|
||||
{mecanismo.steps.map((step, i) => (
|
||||
<motion.li key={step.n} variants={fadeInUp}>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setActive(i)}
|
||||
aria-pressed={active === i}
|
||||
className={`w-full text-left border-t pt-6 transition-all duration-300 ease-out hover:-translate-y-1.5 motion-reduce:transform-none motion-reduce:transition-none ${
|
||||
active === i ? 'border-dorado md:-translate-y-1.5' : 'border-dorado/30 md:opacity-40'
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="font-sans font-black text-5xl md:text-6xl text-dorado leading-none">{step.n}</div>
|
||||
<Icono nombre={ICONOS[i]} className="w-10 h-10 md:w-12 md:h-12 text-white/70" />
|
||||
</div>
|
||||
<h3 className="mt-4 font-sans font-bold text-xl">{step.name}</h3>
|
||||
<p className="mt-3 text-gris-medio leading-relaxed">{step.desc}</p>
|
||||
</button>
|
||||
</motion.li>
|
||||
))}
|
||||
</motion.ol>
|
||||
|
||||
Reference in new issue
Block a user