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>
90 lines
5.2 KiB
TypeScript
90 lines
5.2 KiB
TypeScript
'use client';
|
|
import { useState } from 'react';
|
|
import { motion } from 'framer-motion';
|
|
import { Container } from '@/components/primitives/Container';
|
|
import { Antetitulo } from '@/components/primitives/Antetitulo';
|
|
import { TarjetaSpotlight } from '@/components/primitives/TarjetaSpotlight';
|
|
import { Resplandor } from '@/components/primitives/Resplandor';
|
|
import { Icono, type IconoNombre } from '@/components/primitives/Icono';
|
|
import { IlustracionConvergencia } from '@/components/primitives/IlustracionConvergencia';
|
|
import { disciplinas } from '@/lib/content';
|
|
import { fadeInUp, staggerContainer, viewportOnce, usePrefersReducedMotion, motionProps } from '@/lib/motion';
|
|
|
|
const ICONOS: IconoNombre[] = ['comunicacion', 'digital', 'experiencias'];
|
|
|
|
export function Disciplinas() {
|
|
const reduced = usePrefersReducedMotion();
|
|
// Which discipline the reader is pointing at, so its strand lights up in the
|
|
// drawing above. A pointer-only enhancement on purpose: it reveals nothing —
|
|
// all three cards and all three strands are fully there without it — so
|
|
// nobody loses anything by not having a mouse.
|
|
const [senalada, setSenalada] = useState<number | null>(null);
|
|
return (
|
|
// Azul profundo, no blanco: al mover esta sección delante de Proceso
|
|
// quedaba pegada a Dolores, que también es blanca, y las dos se fundían.
|
|
// Además rompe el tramo de seis secciones claras seguidas que había entre
|
|
// FraseAncla y Cierre, y le da a la página un latido oscuro a media altura.
|
|
<section className="bg-azul-profundo bg-hondo-navy text-white relative overflow-hidden">
|
|
<Resplandor className="-top-40 -right-32 w-[38rem] h-[38rem]" />
|
|
<Resplandor className="bottom-[-14rem] -left-40 w-[32rem] h-[32rem]" tono="frio" />
|
|
<Container className="relative py-16 md:py-24">
|
|
{/* Title and lead on the left, the drawing on the right at the same
|
|
height. The lead is the sentence this section exists for — Proceso
|
|
sits after it so it lands first — and it used to be small grey
|
|
text lost in the gap under the title, with the drawing floating
|
|
loose below. */}
|
|
<motion.div variants={fadeInUp} initial="hidden" whileInView="visible" viewport={viewportOnce} {...motionProps(reduced)}
|
|
className="md:flex md:items-end md:justify-between md:gap-12">
|
|
<div>
|
|
{/* sobre="oscuro": la sección es azul profundo, así que aquí el dorado
|
|
del manual se queda tal cual — 6,07:1. */}
|
|
<Antetitulo sobre="oscuro" as="p">
|
|
{disciplinas.eyebrow}
|
|
</Antetitulo>
|
|
<h2 className="mt-4 font-sans font-black text-seccion text-balance">{disciplinas.title}</h2>
|
|
<p className="mt-4 text-xl md:text-2xl font-semibold text-white/85">
|
|
{/* Two unbreakable halves, the dash closing the first. On a
|
|
phone the line used to break wherever it fell — before the
|
|
dash, or before «medios» — and left a stray fragment alone. */}
|
|
{(() => {
|
|
const [antes, despues] = disciplinas.lead.split(' — ');
|
|
if (!despues) return disciplinas.lead; // copy without a dash
|
|
return (
|
|
<>
|
|
<span className="whitespace-nowrap">{antes} —</span>{' '}
|
|
<span className="whitespace-nowrap">{despues}</span>
|
|
</>
|
|
);
|
|
})()}
|
|
</p>
|
|
</div>
|
|
<IlustracionConvergencia className="mt-8 md:mt-0 w-56 md:w-72 h-auto shrink-0" activa={senalada} />
|
|
</motion.div>
|
|
<motion.ul variants={staggerContainer} initial="hidden" whileInView="visible" viewport={viewportOnce} {...motionProps(reduced)}
|
|
className="mt-12 grid gap-6 md:grid-cols-3 list-none p-0">
|
|
{disciplinas.items.map((item, i) => (
|
|
<motion.li key={item.name} variants={fadeInUp}
|
|
onPointerEnter={() => setSenalada(i)}
|
|
onPointerLeave={() => setSenalada(null)}
|
|
// No lift: the cards are not links. What answers the pointer is
|
|
// the card's own strand lighting up in the drawing above, plus a
|
|
// gold edge so the reader sees which card that strand belongs to.
|
|
className="group">
|
|
{/* Tarjetas invertidas al pasar la sección a azul: `text-gris-medio`
|
|
se leía bien sobre navy, pero sobre blanco cae a ~2,3:1 y no
|
|
pasa contraste. La descripción va en azul rebajado. */}
|
|
<TarjetaSpotlight className="h-full rounded-xl bg-white text-azul-profundo p-7 shadow-tarjeta border-t-4 border-transparent transition-colors duration-200 group-hover:border-dorado motion-reduce:transition-none">
|
|
<div className="grid place-items-center w-14 h-14 rounded-full bg-dorado/15">
|
|
<Icono nombre={ICONOS[i]} className="w-7 h-7 text-dorado" />
|
|
</div>
|
|
<h3 className="mt-5 font-sans font-black text-2xl">{item.name}</h3>
|
|
<p className="mt-3 text-azul-profundo/75 leading-relaxed text-pretty">{item.desc}</p>
|
|
</TarjetaSpotlight>
|
|
</motion.li>
|
|
))}
|
|
</motion.ul>
|
|
</Container>
|
|
</section>
|
|
);
|
|
}
|