feat(diseño): los diez arreglos de la revisión visual

Revisada la página con Chromium a 1440x900 y 390x844 en nueve alturas de
scroll, y verificado cada cambio contra capturas nuevas.

- El ≡ deja de leerse como icono de menú. lib/simbolo.ts se anunciaba como
  single source of truth pero no coincidía con Wordmark.tsx, que traza la
  marca con las proporciones medidas del Manual: barra de largo 5.919× su
  grosor, hueco de 2×, extremos de píldora. Ahora se derivan de ahí. De
  paso, las líneas se meten medio grosor por cada extremo: el remate
  redondo alargaba el trazo un grosor entero sobre la barra que debía
  reproducir.
- Banda: 12px en escritorio y 7px en móvil vía CSS (14px era el 3,6% de
  una pantalla de 390px y partía los párrafos), opacidad al 18%, y muelle
  de 90/30 a 210/40 — sobreamortiguado tardaba ~2s en asentar y la punta
  se arrastraba a media pantalla. El punto suelto que aparecía centrado
  arriba al cargar era el remate redondo pintándose en el origen con
  longitud cero: ahora la opacidad sigue al avance.
- Ritmo vertical un 25-30% más apretado en las diez secciones. La página
  pasa de 8.061 a 7.457px sin tocar contenido.
- Números 01-06: de marca de agua de 48px al 6% (que chocaba con títulos
  y reglas) a índice dorado sentado sobre la regla.
- Hero: los dos CTA al mismo ancho en móvil, el patrón de puntos fuera
  del logotipo, y la secuencia visible en todos los tamaños — oculta bajo
  lg dejaba el hero del móvil sin ninguna pieza gráfica. La convergencia
  de la variante "hero" se cierra más para que se lea como líneas
  buscando su eje y no como un garabato tachado.
- Estratega: fuera la retícula de puntos del retrato, que parecía el
  recuadro de imagen rota del navegador; la etiqueta del 30+ cabía en
  menos de lo que mide "construyendo" y salía en tres líneas.
- El nudo de Dolores, más pequeño y con algo más de contraste.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
erikghandClaude Opus 5 committed 2026-07-31 16:34:07 -06:00
1 parent 174fcb855a
commit fa86605b39
15 files changed
+135 -52

No files matched your search

+1 -1
View File
@@ -13,7 +13,7 @@ export function Cierre() {
return (
<section id="contacto" className="bg-azul-profundo text-white scroll-mt-24 relative overflow-hidden">
<FondoPuntos className="top-12 -left-16 w-72 md:w-[30rem] text-dorado/25" distance={36} />
<Container className="relative py-24 md:py-32 text-center">
<Container className="relative py-16 md:py-24 text-center">
<motion.div variants={staggerContainer} initial="hidden" whileInView="visible" viewport={viewportOnce} {...motionProps(reduced)}
className="flex flex-col items-center">
<motion.div variants={fadeInUp}><Wordmark size="lg" onDark showTagline /></motion.div>
+1 -1
View File
@@ -19,7 +19,7 @@ export function ComoEmpezar() {
const desplazamiento = useTransform(scrollYProgress, [0, 1], [20, -20]);
return (
<section className="bg-white">
<Container className="py-24 md:py-32 grid gap-12 md:grid-cols-[1fr_auto] md:items-center">
<Container className="py-16 md:py-24 grid gap-12 md:grid-cols-[1fr_auto] md:items-center">
<motion.div variants={staggerContainer} initial="hidden" whileInView="visible" viewport={viewportOnce} {...motionProps(reduced)}>
<motion.p variants={fadeInUp} className="text-xs tracking-[0.3em] uppercase font-black text-dorado">{comoEmpezar.eyebrow}</motion.p>
<motion.h2 variants={fadeInUp} className="mt-4 font-sans font-black text-seccion text-azul-profundo max-w-xl">{comoEmpezar.title}</motion.h2>
+1 -1
View File
@@ -13,7 +13,7 @@ export function Disciplinas() {
const reduced = usePrefersReducedMotion();
return (
<section className="bg-white">
<Container className="py-24 md:py-32">
<Container className="py-16 md:py-24">
<motion.p variants={fadeInUp} initial="hidden" whileInView="visible" viewport={viewportOnce} {...motionProps(reduced)}
className="text-xs tracking-[0.3em] uppercase font-black text-dorado">{disciplinas.eyebrow}</motion.p>
<motion.h2 variants={fadeInUp} initial="hidden" whileInView="visible" viewport={viewportOnce} {...motionProps(reduced)}
+5 -2
View File
@@ -11,8 +11,11 @@ export function Dolores() {
const reduced = usePrefersReducedMotion();
return (
<section className="bg-white relative overflow-hidden">
<IlustracionNudo className="pointer-events-none select-none absolute top-0 left-1/2 -translate-x-1/2 w-64 md:w-[28rem] text-azul-profundo/[0.08]" />
<Container className="relative py-24 md:py-32">
{/* Smaller and a touch stronger than it was: sprawling at 8% across the
whole title it read as a smudge over the headline rather than as a
knot. Stays centred so the conductor thread runs through it. */}
<IlustracionNudo className="pointer-events-none select-none absolute top-0 left-1/2 -translate-x-1/2 w-56 md:w-80 text-azul-profundo/[0.11]" />
<Container className="relative py-16 md:py-24">
<motion.p variants={fadeInUp} initial="hidden" whileInView="visible" viewport={viewportOnce} {...motionProps(reduced)}
className="text-xs tracking-[0.3em] uppercase font-black text-dorado">{dolores.eyebrow}</motion.p>
<motion.h2 variants={fadeInUp} initial="hidden" whileInView="visible" viewport={viewportOnce} {...motionProps(reduced)}
+10 -5
View File
@@ -1,7 +1,6 @@
'use client';
import { motion } from 'framer-motion';
import { Container } from '@/components/primitives/Container';
import { PatronPuntos } from '@/components/primitives/PatronPuntos';
import { Wordmark } from '@/components/primitives/Wordmark';
import { ContadorNumero } from '@/components/primitives/ContadorNumero';
import { MarcoRetrato } from '@/components/primitives/MarcoRetrato';
@@ -12,16 +11,20 @@ export function Estratega() {
const reduced = usePrefersReducedMotion();
return (
<section className="bg-gris-claro">
<Container className="py-24 md:py-32">
<Container className="py-16 md:py-24">
<motion.div variants={staggerContainer} initial="hidden" whileInView="visible" viewport={viewportOnce} {...motionProps(reduced)}
className="grid gap-12 md:grid-cols-[auto_1fr] md:items-center">
{/* TODO dueña: real portrait. The frame is built to take it as-is —
drop an <Image fill /> in place of the placeholder below. */}
<motion.div variants={fadeInUp}>
<MarcoRetrato>
{/* Reads as a brand plate, not as a broken image. The dot grid
that used to sit behind the wordmark looked like the
checkerboard a browser shows for a picture that failed to
load; the ≡ alone, meanwhile, reads as a hamburger menu once
it stands by itself in a circle. The wordmark is neither. */}
<div className="w-full h-full bg-azul-profundo grid place-items-center" role="img" aria-label="Retrato de la estratega — pendiente">
<PatronPuntos rows={4} cols={7} className="absolute inset-0 m-auto w-[150%] h-auto text-white/15" />
<span className="relative"><Wordmark size="sm" onDark /></span>
<Wordmark size="md" onDark />
</div>
</MarcoRetrato>
</motion.div>
@@ -32,7 +35,9 @@ export function Estratega() {
<motion.h2 variants={fadeInUp} className="mt-4 font-sans font-black text-seccion text-azul-profundo">{estratega.title}</motion.h2>
<motion.div variants={fadeInUp} className="mt-6 flex items-baseline gap-3">
<ContadorNumero hasta={30} sufijo="+" className="font-sans font-black text-5xl md:text-6xl text-dorado leading-none" />
<p className="text-xs uppercase tracking-[0.2em] text-gris-medio font-semibold max-w-[8rem] leading-tight">años construyendo marcas</p>
{/* 8rem was narrower than the word "construyendo" itself, which
broke the label into three ragged lines beside the number. */}
<p className="text-xs uppercase tracking-[0.14em] text-gris-medio font-semibold max-w-[12rem] leading-snug">años construyendo marcas</p>
</motion.div>
<motion.p variants={fadeInUp} className="mt-6 text-lg text-gris-medio leading-relaxed max-w-2xl">{estratega.bio}</motion.p>
<motion.blockquote variants={fadeInUp} className="mt-6 font-sans italic text-xl md:text-2xl text-azul-profundo border-l-4 border-dorado pl-4">
+1 -1
View File
@@ -11,7 +11,7 @@ export function FraseAncla() {
const reduced = usePrefersReducedMotion();
return (
<section className="bg-azul-profundo relative overflow-hidden">
<Container className="relative py-28 md:py-40 text-center max-w-5xl">
<Container className="relative py-20 md:py-28 text-center max-w-5xl">
<motion.div variants={fadeInUp} initial="hidden" whileInView="visible" viewport={viewportOnce} {...motionProps(reduced)}
className="flex justify-center">
{/* Payoff for the tension the hero leaves open: here the lines do
+17 -9
View File
@@ -23,10 +23,13 @@ export function Hero({ variant = 'editorial' }: { variant?: Variant }) {
return (
<section className="bg-white relative overflow-hidden">
<FondoPuntos className="top-24 -right-16 w-72 md:w-[28rem] text-azul-profundo/10" interactivo />
{/* Kept clear of the wordmark on narrow screens: at 390px the md field
reached back across the logotype and the tagline, so the pattern read
as collision rather than texture. */}
<FondoPuntos className="top-80 -right-20 w-56 md:top-24 md:-right-16 md:w-[28rem] text-azul-profundo/10" interactivo />
<FondoPuntos className="bottom-16 -left-20 w-64 md:w-96 text-dorado/20" distance={28} rows={2} />
<Container className="relative min-h-[88vh] flex items-center py-24">
<div className="grid gap-14 lg:grid-cols-[1.1fr_0.9fr] lg:items-center w-full">
<Container className="relative min-h-[80vh] lg:min-h-[88vh] flex items-center py-16 md:py-24">
<div className="grid gap-8 lg:gap-14 lg:grid-cols-[1.1fr_0.9fr] lg:items-center w-full">
<motion.div variants={staggerContainer} initial="hidden" animate="visible" {...motionProps(reduced)}
className="min-w-0 flex flex-col items-center text-center lg:items-start lg:text-left">
<motion.div variants={fadeInUp}><Wordmark size="xl" showTagline /></motion.div>
@@ -44,16 +47,21 @@ export function Hero({ variant = 'editorial' }: { variant?: Variant }) {
]}
/>
</motion.h1>
<motion.div variants={fadeInUp} className="mt-10 flex flex-col md:flex-row items-center gap-4">
<CTA href="#contacto" label={hero.cta} variant="light" className="md:whitespace-nowrap" />
<CTA href="#mecanismo" label={hero.ctaSecundario} variant="ghost" className="md:whitespace-nowrap" />
{/* Full width while stacked: at their natural widths the two CTAs
came out ragged and unequal, which read as an accident rather
than as hierarchy. */}
<motion.div variants={fadeInUp} className="mt-10 w-full flex flex-col md:flex-row items-stretch md:items-center md:w-auto gap-4">
<CTA href="#contacto" label={hero.cta} variant="light" className="text-center md:whitespace-nowrap" />
<CTA href="#mecanismo" label={hero.ctaSecundario} variant="ghost" className="text-center md:whitespace-nowrap" />
</motion.div>
</motion.div>
{/* Complexity → focus, left unresolved: the hero poses the tension
and FraseAncla pays it off by resolving into the ≡. */}
and FraseAncla pays it off by resolving into the ≡. Shown on every
breakpoint — hidden below lg it left the phone hero with no piece
of the brand's own graphic language at all. */}
<motion.div variants={fadeInUp} initial="hidden" animate="visible" {...motionProps(reduced)}
className="hidden lg:block min-w-0">
<SecuenciaClaridad variant="hero" className="w-full max-w-md mx-auto text-azul-profundo" />
className="min-w-0">
<SecuenciaClaridad variant="hero" className="w-32 lg:w-full max-w-md mx-auto text-azul-profundo" />
</motion.div>
</div>
</Container>
+1 -1
View File
@@ -24,7 +24,7 @@ export function Mecanismo() {
>
<FondoFoto src="/images/mecanismo-bg.jpg" className="inset-0 opacity-25" wash="bg-azul-profundo/80" />
</motion.div>
<Container className="relative py-24 md:py-32">
<Container className="relative py-16 md:py-24">
<motion.p variants={fadeInUp} initial="hidden" whileInView="visible" viewport={viewportOnce} {...motionProps(reduced)}
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)}
+1 -1
View File
@@ -10,7 +10,7 @@ export function ParaQuien() {
const reduced = usePrefersReducedMotion();
return (
<section className="bg-white relative overflow-hidden">
<Container className="relative pt-24 md:pt-32 pb-12 md:pb-16 md:flex md:items-center md:justify-between md:gap-12">
<Container className="relative pt-16 md:pt-24 pb-8 md:pb-12 md:flex md:items-center md:justify-between md:gap-12">
<motion.h2 variants={fadeInUp} initial="hidden" whileInView="visible" viewport={viewportOnce} {...motionProps(reduced)}
className="font-sans font-black text-seccion text-azul-profundo max-w-3xl">{paraQuien.title}</motion.h2>
<motion.div variants={fadeInUp} initial="hidden" whileInView="visible" viewport={viewportOnce} {...motionProps(reduced)}
+5 -2
View File
@@ -12,7 +12,10 @@ import { fadeInUp, staggerContainer, viewportOnce, usePrefersReducedMotion, moti
function Tarjeta({ n, name, desc }: { n: number; name: string; desc: string }) {
return (
<TarjetaSpotlight className="relative h-full rounded-md border-t-2 border-dorado pt-5 pl-1 pr-1 pb-1 overflow-visible">
<span aria-hidden="true" className="pointer-events-none absolute -top-2 right-0 font-sans font-black text-5xl text-azul-profundo/[0.06] leading-none select-none">
{/* An index, not a watermark. At 48px and 6% opacity these collided with
the titles and with the gold rule while carrying no contrast of their
own; sat on the rule they encode the sequence and stay out of the way. */}
<span aria-hidden="true" className="pointer-events-none absolute -top-1.5 right-0 bg-gris-claro pl-2 font-sans font-black text-xs tracking-[0.2em] text-dorado leading-none select-none">
{String(n).padStart(2, '0')}
</span>
<h3 className="relative font-sans font-bold text-xl text-azul-profundo">{name}</h3>
@@ -26,7 +29,7 @@ export function PuntosInflexion() {
return (
<section className="bg-gris-claro relative overflow-hidden">
<FondoPuntos className="-bottom-6 -right-12 w-80 md:w-[32rem] text-azul-profundo/10" distance={32} />
<Container className="relative py-24 md:py-32">
<Container className="relative py-16 md:py-24">
<div className="flex flex-col md:flex-row md:items-center md:justify-between md:gap-12">
<div>
<motion.p variants={fadeInUp} initial="hidden" whileInView="visible" viewport={viewportOnce} {...motionProps(reduced)}