El nudo, la bifurcación y la convergencia usaban 2.5 y 3.5 sueltos, así que
las tres se veían de pesos distintos puestas una al lado de otra.
Un test de contrato por ilustración exige ahora que todo trazo pertenezca a
{1.5, 2, 3}, de modo que la escala no se pueda romper en silencio más
adelante. SecuenciaClaridad queda fuera a propósito: resuelve en las barras
reales del ≡ y su grosor lo manda LINEAS_SIMBOLO.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
61 lines
2.8 KiB
TypeScript
61 lines
2.8 KiB
TypeScript
'use client';
|
|
|
|
import { motion } from 'framer-motion';
|
|
import { useEnVista } from '@/lib/motion';
|
|
|
|
// A shared trunk splitting at a marked decision point: one route climbs, gold
|
|
// and continuous; the other flattens, grey and dashed. It draws the section's
|
|
// own bifurcation — "sí es para ti / no es para ti" — without illustrating a
|
|
// judgement about the reader.
|
|
const TRONCO = 'M10 100 C 50 96, 80 84, 110 70';
|
|
const RUTA_SI = 'M110 70 C 145 58, 175 30, 210 18';
|
|
const RUTA_NO = 'M110 70 C 145 82, 175 92, 210 90';
|
|
|
|
export function IlustracionBifurcacion({ className = '' }: { className?: string }) {
|
|
const { ref, enVista, reduced } = useEnVista();
|
|
|
|
const punto = (
|
|
<>
|
|
<circle cx={110} cy={70} r={5} fill="currentColor" className="text-dorado" />
|
|
<circle cx={110} cy={70} r={9} fill="none" stroke="currentColor" className="text-dorado" strokeWidth={1} strokeOpacity={0.4} />
|
|
</>
|
|
);
|
|
|
|
// Plain <path> under reduced motion — motion.path would hide the drawing.
|
|
if (reduced) {
|
|
return (
|
|
<svg ref={ref} viewBox="0 0 220 120" className={className} aria-hidden="true" focusable="false">
|
|
<path d={TRONCO} fill="none" stroke="currentColor" className="text-azul-profundo" strokeWidth={2} strokeLinecap="round" />
|
|
<path d={RUTA_NO} fill="none" stroke="currentColor" className="text-gris-medio" strokeWidth={2} strokeLinecap="round" strokeDasharray="1 8" />
|
|
<path d={RUTA_SI} fill="none" stroke="currentColor" className="text-dorado" strokeWidth={3} strokeLinecap="round" />
|
|
{punto}
|
|
</svg>
|
|
);
|
|
}
|
|
|
|
const dibuja = (delay: number) => ({
|
|
initial: { pathLength: 0 },
|
|
animate: enVista ? { pathLength: 1 } : { pathLength: 0 },
|
|
transition: { duration: 1.1, delay, ease: [0.22, 1, 0.36, 1] as const },
|
|
});
|
|
|
|
// The "no" route is dashed, and a dashed stroke cannot share Framer Motion's
|
|
// pathLength reveal: pathLength drives `stroke-dasharray` itself and would
|
|
// overwrite the "1 8" dashes. It fades in by opacity instead, so the dashes
|
|
// it is drawn with are the dashes it keeps.
|
|
const punteada = {
|
|
initial: { opacity: 0 },
|
|
animate: enVista ? { opacity: 1 } : { opacity: 0 },
|
|
transition: { duration: 0.8, delay: 0.55, ease: [0.22, 1, 0.36, 1] as const },
|
|
};
|
|
|
|
return (
|
|
<svg ref={ref} viewBox="0 0 220 120" className={className} aria-hidden="true" focusable="false">
|
|
<motion.path d={TRONCO} fill="none" stroke="currentColor" className="text-azul-profundo" strokeWidth={2} strokeLinecap="round" {...dibuja(0)} />
|
|
<motion.path d={RUTA_NO} fill="none" stroke="currentColor" className="text-gris-medio" strokeWidth={2} strokeLinecap="round" strokeDasharray="1 8" {...punteada} />
|
|
<motion.path d={RUTA_SI} fill="none" stroke="currentColor" className="text-dorado" strokeWidth={3} strokeLinecap="round" {...dibuja(0.55)} />
|
|
{punto}
|
|
</svg>
|
|
);
|
|
}
|