Files
Creeer-Web/components/primitives/SecuenciaClaridad.tsx
T
erikghandClaude Opus 5.5 89e54a6e84 feat: rediseño «El documento» en curso, contacto real y enlaces externos
Primitivas y contenido del rediseño (escala tipográfica, Revelar,
MarcaSeccion, Seccion, Antetitulo, SimboloMarca, Resplandor, ClaridadHero,
sección Proceso de ocho etapas, lib/content.ts reestructurado en seis
secciones con alias para las viejas). Mecanismo y FormaTrabajar se retiran.

Encima, lo de esta sesión:
- recorrido: creeer vuelve a responder cada situación en vez de repetirla
  (el alias apuntaba respuesta a situacion); respuestas en plural. Créditos
  de las seis fotos de México.
- contacto: WhatsApp, email (con mailto:) y LinkedIn reales; iconos de las
  redes en el cierre y el footer (IconoRed, trazos de Simple Icons, CC0).
- enlaces: lo externo abre en otra pestaña con noopener y aviso para
  lectores de pantalla (lib/enlaces.ts); mailto y anclas se quedan.
- Proceso: las ocho tarjetas no aparecían nunca en móvil (amount 0.3 sobre
  una lista de ~3000px); ahora cada una se revela sola. El ≡ de la 08 ya no
  tapa un entregable, título equilibrado, etiqueta a 12px, sin elevar al
  hover lo que no es clicable.
- Disciplinas: la frase «No son la promesa — son los medios» gana peso y
  se agrupa con título e ilustración; sin cortes huérfanos en móvil.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 11:27:20 -06:00

183 lines
6.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client';
import { motion } from 'framer-motion';
import { useEnVista } from '@/lib/motion';
import { VIEWBOX_SIMBOLO, LINEAS_SIMBOLO } from '@/lib/simbolo';
// The manual's core metaphor, finally drawn: Complejidad → Enfoque → Claridad.
// Eighteen crossing lines converge in three groups; in the "completa" variant
// each group collapses onto one of the three bars of the ≡, so the mark is
// literally produced by the resolution of the tangle rather than placed next
// to it. The "hero" variant resolves the chaos into a skyline silhouette —
// structure emerging from disorder, what creeer builds for its clients.
// FraseAncla pays off the full ≡ resolution further down the page.
type Variant = 'completa' | 'hero';
// Scattered start positions. Hand-placed rather than random so the tangle is
// identical on every render and between server and client.
const DISPERSAS = [
{ x1: 2, y1: 8, x2: 40, y2: 3, barra: 0 },
{ x1: 20, y1: 2, x2: 61, y2: 24, barra: 0 },
{ x1: 6, y1: 22, x2: 52, y2: 6, barra: 0 },
{ x1: 34, y1: 5, x2: 12, y2: 27, barra: 0 },
{ x1: 48, y1: 2, x2: 58, y2: 30, barra: 0 },
{ x1: 3, y1: 15, x2: 46, y2: 19, barra: 0 },
{ x1: 5, y1: 30, x2: 60, y2: 26, barra: 1 },
{ x1: 14, y1: 40, x2: 55, y2: 20, barra: 1 },
{ x1: 2, y1: 26, x2: 38, y2: 44, barra: 1 },
{ x1: 44, y1: 22, x2: 18, y2: 41, barra: 1 },
{ x1: 30, y1: 18, x2: 62, y2: 40, barra: 1 },
{ x1: 8, y1: 36, x2: 50, y2: 33, barra: 1 },
{ x1: 4, y1: 44, x2: 47, y2: 58, barra: 2 },
{ x1: 24, y1: 62, x2: 60, y2: 42, barra: 2 },
{ x1: 10, y1: 56, x2: 56, y2: 50, barra: 2 },
{ x1: 40, y1: 61, x2: 14, y2: 46, barra: 2 },
{ x1: 2, y1: 50, x2: 44, y2: 62, barra: 2 },
{ x1: 33, y1: 44, x2: 62, y2: 57, barra: 2 },
];
// One line per group survives to become a bar of the ≡; the rest fade as they
// converge — many/disordered becomes few/aligned, per the manual.
const SOBREVIVE = [0, 6, 12];
// Skyline destination for the hero variant. Eighteen lines form a city
// silhouette: vertical segments are building walls, horizontal segments
// are rooftops and the ground line. The skyline reads left to right as
// buildings of increasing height — chaos becoming structure, the visual
// promise of what creeer delivers.
//
// ViewBox: 64×64. Ground at y=58. Tallest building peaks at y=10.
//
// ┌──┐
// ┌──┐ │ │ ┌─┐
// │ │ │ │ │ │┌──┐
// ┌─┤ │ │ │ │ ││ │
// │ │ │ │ │ │ ││ │
// └─┴──┴─┴──┴─┴─┴┴──┘
//
const SKYLINE = [
// Building 1 (left, medium) — x: 4–14, top: 28
{ x1: 4, y1: 58, x2: 4, y2: 28 }, // 0: left wall
{ x1: 4, y1: 28, x2: 14, y2: 28 }, // 1: rooftop
{ x1: 14, y1: 28, x2: 14, y2: 58 }, // 2: right wall
// Building 2 (tall) — x: 18–30, top: 12
{ x1: 18, y1: 58, x2: 18, y2: 12 }, // 3: left wall
{ x1: 18, y1: 12, x2: 30, y2: 12 }, // 4: rooftop
{ x1: 30, y1: 12, x2: 30, y2: 58 }, // 5: right wall
// Building 3 (short) — x: 34–40, top: 32
{ x1: 34, y1: 58, x2: 34, y2: 32 }, // 6: left wall
{ x1: 34, y1: 32, x2: 40, y2: 32 }, // 7: rooftop
{ x1: 40, y1: 32, x2: 40, y2: 58 }, // 8: right wall
// Building 4 (medium-tall) — x: 42–54, top: 20
{ x1: 42, y1: 58, x2: 42, y2: 20 }, // 9: left wall
{ x1: 42, y1: 20, x2: 54, y2: 20 }, // 10: rooftop
{ x1: 54, y1: 20, x2: 54, y2: 58 }, // 11: right wall
// Small tower on building 1 — x: 7–11, top: 22
{ x1: 7, y1: 28, x2: 7, y2: 22 }, // 12: left wall
{ x1: 7, y1: 22, x2: 11, y2: 22 }, // 13: rooftop
{ x1: 11, y1: 22, x2: 11, y2: 28 }, // 14: right wall
// Ground line segments
{ x1: 2, y1: 58, x2: 30, y2: 58 }, // 15: ground left
{ x1: 30, y1: 58, x2: 56, y2: 58 }, // 16: ground right
// Antenna on tallest building — a small vertical detail
{ x1: 24, y1: 12, x2: 24, y2: 6 }, // 17: antenna
];
const EASE = [0.22, 1, 0.36, 1] as const;
export function SecuenciaClaridad({
variant = 'completa',
className = '',
}: {
variant?: Variant;
className?: string;
}) {
const { ref, enVista, reduced } = useEnVista(0.35);
const completa = variant === 'completa';
// Where each line ends up. In "completa" the survivors land exactly on the
// symbol's own coordinates; in "hero" the lines form a skyline silhouette.
const destino = (i: number) => {
if (!completa) {
// Hero variant: lines converge into the skyline shape.
const s = SKYLINE[i];
return {
x1: s.x1,
y1: s.y1,
x2: s.x2,
y2: s.y2,
opacity: i === 17 ? 0.7 : 0.85, // antenna slightly dimmer
};
}
// Completa variant: survivors land on the ≡ bars.
const { barra } = DISPERSAS[i];
const linea = LINEAS_SIMBOLO[barra];
const sobrevive = SOBREVIVE.includes(i);
return {
x1: linea.x1,
y1: linea.y1,
x2: linea.x2,
y2: linea.y2,
opacity: sobrevive ? 1 : 0,
};
};
const grosor = (i: number) =>
completa && SOBREVIVE.includes(i) ? LINEAS_SIMBOLO[DISPERSAS[i].barra].grosor : 1.5;
// Reduced motion renders plain <line> elements: motion.line would apply its
// own dash scaffolding and leave the drawing invisible.
if (reduced) {
return (
<svg ref={ref} viewBox={VIEWBOX_SIMBOLO} className={className} aria-hidden="true" focusable="false">
{DISPERSAS.map((_, i) => {
const d = destino(i);
const visible = completa ? SOBREVIVE.includes(i) : true;
return (
<line
key={i}
{...(completa && SOBREVIVE.includes(i) ? { 'data-resolucion': true } : {})}
x1={d.x1}
y1={d.y1}
x2={d.x2}
y2={d.y2}
stroke="currentColor"
strokeWidth={grosor(i)}
strokeLinecap="round"
opacity={visible ? d.opacity : 0}
/>
);
})}
</svg>
);
}
return (
<svg ref={ref} viewBox={VIEWBOX_SIMBOLO} className={className} aria-hidden="true" focusable="false">
{DISPERSAS.map(({ barra: _barra, ...inicio }, i) => {
const d = destino(i);
const reposo = { ...inicio, opacity: 0.55, strokeWidth: 1.5 };
return (
<motion.line
key={i}
{...(completa && SOBREVIVE.includes(i) ? { 'data-resolucion': true } : {})}
stroke="currentColor"
strokeLinecap="round"
initial={reposo}
animate={enVista ? { ...d, strokeWidth: grosor(i) } : reposo}
transition={{ duration: 1.2, delay: 0.25 + (i % 6) * 0.05, ease: EASE }}
/>
);
})}
</svg>
);
}