Files
Creeer-Web/components/sections/Disciplinas.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

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>
);
}