refactor(ilustraciones): grosores unificados a la escala 1.5/2/3

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>
This commit is contained in:
erikghandClaude Opus 5 committed 2026-07-31 15:32:10 -06:00
1 parent 2296fa4868
commit 29837022ce
6 files changed
+26 -5

No files matched your search

@@ -25,7 +25,7 @@ export function IlustracionBifurcacion({ className = '' }: { className?: string
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.5} strokeLinecap="round" />
<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}
@@ -51,7 +51,7 @@ export function IlustracionBifurcacion({ className = '' }: { className?: string
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.5} strokeLinecap="round" {...dibuja(0)} />
<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}
@@ -23,7 +23,7 @@ export function IlustracionConvergencia({ className = '' }: { className?: string
{HEBRAS.map((d) => (
<path key={d} d={d} fill="none" stroke="currentColor" className="text-gris-medio" strokeWidth={2} strokeLinecap="round" />
))}
<path d={ESTRATEGIA} fill="none" stroke="currentColor" className="text-dorado" strokeWidth={3.5} strokeLinecap="round" />
<path d={ESTRATEGIA} fill="none" stroke="currentColor" className="text-dorado" strokeWidth={3} strokeLinecap="round" />
</svg>
);
}
@@ -39,7 +39,7 @@ export function IlustracionConvergencia({ className = '' }: { className?: string
{HEBRAS.map((d, i) => (
<motion.path key={d} d={d} fill="none" stroke="currentColor" className="text-gris-medio" strokeWidth={2} strokeLinecap="round" {...dibuja(i * 0.12)} />
))}
<motion.path d={ESTRATEGIA} fill="none" stroke="currentColor" className="text-dorado" strokeWidth={3.5} strokeLinecap="round" {...dibuja(0.7)} />
<motion.path d={ESTRATEGIA} fill="none" stroke="currentColor" className="text-dorado" strokeWidth={3} strokeLinecap="round" {...dibuja(0.7)} />
</svg>
);
}
+1 -1
View File
@@ -8,7 +8,7 @@ import { useEnVista } from '@/lib/motion';
// going anywhere. The strands draw themselves in sequence, which reads as the
// knot tightening rather than as decoration appearing.
const HEBRAS = [
{ d: 'M30 90 C 60 20, 130 20, 140 70 C 148 112, 78 118, 70 78 C 63 44, 120 38, 150 66', ancho: 2.5 },
{ d: 'M30 90 C 60 20, 130 20, 140 70 C 148 112, 78 118, 70 78 C 63 44, 120 38, 150 66', ancho: 3 },
{ d: 'M20 60 C 70 110, 120 110, 160 60', ancho: 2 },
{ d: 'M40 110 C 80 40, 110 130, 155 95', ancho: 2 },
{ d: 'M25 40 C 90 70, 100 100, 165 40', ancho: 1.5 },
@@ -31,4 +31,11 @@ describe('<IlustracionBifurcacion />', () => {
const { container } = render(<IlustracionBifurcacion />);
expect(container.querySelectorAll('circle').length).toBeGreaterThanOrEqual(1);
});
it('keeps every stroke within the shared line-art scale', () => {
const { container } = render(<IlustracionBifurcacion />);
const anchos = Array.from(container.querySelectorAll('path')).map((p) => p.getAttribute('stroke-width'));
expect(anchos.length).toBeGreaterThan(0);
anchos.forEach((a) => expect(['1.5', '2', '3']).toContain(a));
});
});
@@ -14,4 +14,11 @@ describe('<IlustracionConvergencia />', () => {
const { container } = render(<IlustracionConvergencia />);
expect(container.querySelectorAll('path')).toHaveLength(4);
});
it('keeps every stroke within the shared line-art scale', () => {
const { container } = render(<IlustracionConvergencia />);
const anchos = Array.from(container.querySelectorAll('path')).map((p) => p.getAttribute('stroke-width'));
expect(anchos.length).toBeGreaterThan(0);
anchos.forEach((a) => expect(['1.5', '2', '3']).toContain(a));
});
});
@@ -20,6 +20,13 @@ describe('<IlustracionNudo />', () => {
expect(container.querySelectorAll('path').length).toBeGreaterThanOrEqual(3);
});
it('keeps every stroke within the shared line-art scale', () => {
const { container } = render(<IlustracionNudo />);
const anchos = Array.from(container.querySelectorAll('path')).map((p) => p.getAttribute('stroke-width'));
expect(anchos.length).toBeGreaterThan(0);
anchos.forEach((a) => expect(['1.5', '2', '3']).toContain(a));
});
it('renders plain, fully-visible strands under reduced motion instead of motion.path\'s dash scaffolding', () => {
// Force the reduced-motion branch. motion.path applies stroke-dasharray/
// stroke-dashoffset even with no explicit initial/animate resolution,