refactor(recorrido): fuera la cabecera; el escenario abre la sección
Con el recorrido en segundo lugar, esa franja clara quedaba como una lasca entre el azul del hero y el escenario oscuro. Se va: la sección arranca directamente en la secuencia anclada, y su fondo pasa a azul para que cualquier costura sea oscura. Quitarla dejaba la sección sin ningún encabezado, que en una pieza de 5.400px es un agujero en el esquema del documento — para un lector de pantalla las seis parejas colgarían de nada. El rótulo «¿Te reconoces?», que ya estaba en el escenario, pasa a ser el <h2>. Hay una prueba que exige que exista y que sea h2. Actualizado también el comentario de orden en page.tsx, que describía una disposición que ya no es la del archivo. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
d4bff33e47
commit
e0ce0d3b22
3 files changed
+23
-46
No files matched your search
+5
-13
@@ -24,23 +24,15 @@ export default function Home() {
|
||||
<>
|
||||
<script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }} />
|
||||
<Header />
|
||||
{/* Order matters more since PuntosInflexion became the pinned sequence.
|
||||
It no longer only names the six inflection points — it answers each
|
||||
one in creeer's voice, six times over, across six screens. Put third,
|
||||
as it was, the reader got the whole solution before Dolores had given
|
||||
them a reason to care and before Mecanismo explained the method, and
|
||||
the pain landed after the answer.
|
||||
|
||||
Dolores now comes first: short, in the client's own words, the ache.
|
||||
Then the recorrido answers it point by point. Then Mecanismo, which
|
||||
stops reading as repetition and starts reading as the method behind
|
||||
the answers the reader just heard — and it keeps creeer's navy ground
|
||||
straight out of the sequence's last frame. */}
|
||||
{/* El recorrido va en segundo lugar por decisión de la dueña: el lector
|
||||
entra por el gancho y cae directo en la secuencia anclada, que plantea
|
||||
seis situaciones y las contesta. FraseAncla y Dolores llegan después,
|
||||
y Mecanismo cierra explicando el método detrás de esas respuestas. */}
|
||||
<main>
|
||||
<Hero variant="editorial" /> {/* dueña puede cambiar a "hormozi" */}
|
||||
<PuntosInflexion />
|
||||
<FraseAncla />
|
||||
<Dolores />
|
||||
<PuntosInflexion />
|
||||
<Mecanismo />
|
||||
<Disciplinas />
|
||||
<ParaQuien />
|
||||
|
||||
@@ -7,7 +7,6 @@ import { FondoPuntos } from '@/components/primitives/FondoPuntos';
|
||||
import { FondoFoto } from '@/components/primitives/FondoFoto';
|
||||
import { ParDialogo } from '@/components/primitives/ParDialogo';
|
||||
import { EscenaDialogo } from '@/components/primitives/EscenaDialogo';
|
||||
import { IlustracionInflexion } from '@/components/primitives/IlustracionInflexion';
|
||||
import { puntosInflexion } from '@/lib/content';
|
||||
import { fadeInUp, staggerContainer, viewportOnce, usePrefersReducedMotion, motionProps } from '@/lib/motion';
|
||||
|
||||
@@ -32,23 +31,6 @@ const FOTOS = [
|
||||
'/images/recorrido/portafolio.jpg', // a skyline of towers, every one of them a front
|
||||
];
|
||||
|
||||
function Cabecera({ reduced }: { reduced: boolean }) {
|
||||
return (
|
||||
<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)}
|
||||
className="text-xs tracking-[0.3em] uppercase font-black text-dorado">{puntosInflexion.eyebrow}</motion.p>
|
||||
<motion.h2 variants={fadeInUp} initial="hidden" whileInView="visible" viewport={viewportOnce} {...motionProps(reduced)}
|
||||
className="mt-4 font-sans font-black text-seccion text-azul-profundo max-w-3xl">{puntosInflexion.title}</motion.h2>
|
||||
</div>
|
||||
<motion.div variants={fadeInUp} initial="hidden" whileInView="visible" viewport={viewportOnce} {...motionProps(reduced)}
|
||||
className="mt-8 md:mt-0 shrink-0">
|
||||
<IlustracionInflexion className="w-56 md:w-72 h-auto mx-auto" />
|
||||
</motion.div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Reduced motion, and the server's first paint, get the whole conversation laid
|
||||
// out at once. A pinned section that advances on scroll is exactly the thing
|
||||
// someone asking for less movement is asking to be spared, and hiding five
|
||||
@@ -58,8 +40,7 @@ function Estatica() {
|
||||
<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-16 md:py-24">
|
||||
<Cabecera reduced />
|
||||
<p className="mt-14 text-xs tracking-[0.3em] uppercase font-black text-dorado">{puntosInflexion.lead}</p>
|
||||
<h2 className="text-xs tracking-[0.3em] uppercase font-black text-dorado">{puntosInflexion.lead}</h2>
|
||||
<ul className="mt-8 list-none p-0 flex flex-col gap-16 md:gap-24">
|
||||
{items.map((item, i) => (
|
||||
<ParDialogo key={item.name} n={i + 1} {...item} activo reducido onActivar={() => {}} />
|
||||
@@ -142,15 +123,10 @@ function Escenificado() {
|
||||
const fotoY = useTransform(progreso, [0, 1], [0, -70]);
|
||||
|
||||
return (
|
||||
<section className="bg-gris-claro relative">
|
||||
{/* The pinned stage starts the instant this container ends, so without a
|
||||
bottom the dark ground began three pixels under the last line of the
|
||||
title and the intro read as a squeezed strip between two dark blocks
|
||||
rather than as the section's opening. */}
|
||||
<Container className="relative pt-16 pb-16 md:pt-24 md:pb-24">
|
||||
<Cabecera reduced={false} />
|
||||
</Container>
|
||||
|
||||
// Navy, not gris-claro: with no header block left there is no light strip
|
||||
// to show, and any seam at the section's edges should be dark like the
|
||||
// stage itself.
|
||||
<section className="bg-azul-profundo relative">
|
||||
{/* One viewport of stage, six viewports of scroll to move through it. */}
|
||||
<div ref={contenedor} className="relative" style={{ height: `${TOTAL * 100}vh` }}>
|
||||
<div data-escena={activo} data-tiempo={tiempo} className="sticky top-0 h-screen overflow-hidden bg-azul-profundo">
|
||||
@@ -205,9 +181,13 @@ function Escenificado() {
|
||||
resolves against Container's padding box, so `left-0` lands on
|
||||
the inside of the border and ignores the px-6 the rest of the
|
||||
page is aligned to. On a phone that clipped the first glyph. */}
|
||||
<p className="absolute top-24 left-6 md:left-12 text-xs tracking-[0.3em] uppercase font-black text-dorado md:top-28">
|
||||
{/* The section's only heading now. Losing the header block cost
|
||||
the recorrido its <h2>, and a section this size with no heading
|
||||
at all is a hole in the document outline — for a screen reader
|
||||
the six exchanges would hang off nothing. */}
|
||||
<h2 className="absolute top-24 left-6 md:left-12 text-xs tracking-[0.3em] uppercase font-black text-dorado md:top-28">
|
||||
{puntosInflexion.lead}
|
||||
</p>
|
||||
</h2>
|
||||
|
||||
{/* The rail. Where you are in the conversation, and how much is
|
||||
left — a pinned section without it feels like a page that
|
||||
|
||||
@@ -4,9 +4,14 @@ import { PuntosInflexion } from '../PuntosInflexion';
|
||||
import { puntosInflexion } from '@/lib/content';
|
||||
|
||||
describe('<PuntosInflexion />', () => {
|
||||
it('renders the section title', () => {
|
||||
it('still has a heading after losing its header block', () => {
|
||||
render(<PuntosInflexion />);
|
||||
expect(screen.getByText(/llegan a un punto de inflexión/i)).toBeInTheDocument();
|
||||
// The eyebrow and the deck's title used to sit in a light strip above the
|
||||
// pinned stage; with them gone the lead carries the heading level. A
|
||||
// section this long with no heading at all is a hole in the outline —
|
||||
// for a screen reader the six exchanges would hang off nothing.
|
||||
const encabezado = screen.getByRole('heading', { name: /te reconoces/i });
|
||||
expect(encabezado.tagName).toBe('H2');
|
||||
});
|
||||
|
||||
it('labels both halves of every exchange with its inflection point', () => {
|
||||
|
||||
Reference in new issue
Block a user