From c1a5e79c63c3c0eef008ce59b3caedd4acb37cd1 Mon Sep 17 00:00:00 2001 From: erikgh Date: Mon, 3 Aug 2026 11:14:57 -0600 Subject: [PATCH] feat(recorrido): los seis puntos dejan de ser tarjetas y pasan a contestar MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cada punto de inflexión enuncia ahora la situación en segunda persona y creeer responde qué hace al respecto. 01 y 05 son los dos intercambios que la dueña improvisó en la llamada del 31/jul, redactados. El test de segunda persona cazó cuatro situaciones impersonales que yo había escrito ("El esfuerzo dejó de traducirse en resultado" no interpela a nadie). Se corrigió el copy, no el test. Co-Authored-By: Claude Opus 5 --- components/sections/PuntosInflexion.tsx | 42 ++++------------ .../__tests__/PuntosInflexion.test.tsx | 44 ++++++++++++++-- lib/content.ts | 50 ++++++++++++++++--- 3 files changed, 93 insertions(+), 43 deletions(-) diff --git a/components/sections/PuntosInflexion.tsx b/components/sections/PuntosInflexion.tsx index 05bbf5e..139f68e 100644 --- a/components/sections/PuntosInflexion.tsx +++ b/components/sections/PuntosInflexion.tsx @@ -3,27 +3,11 @@ import { motion } from 'framer-motion'; import { Container } from '@/components/primitives/Container'; import { FondoPuntos } from '@/components/primitives/FondoPuntos'; -import { Carrusel } from '@/components/primitives/Carrusel'; -import { TarjetaSpotlight } from '@/components/primitives/TarjetaSpotlight'; +import { ParDialogo } from '@/components/primitives/ParDialogo'; import { IlustracionInflexion } from '@/components/primitives/IlustracionInflexion'; import { puntosInflexion } from '@/lib/content'; import { fadeInUp, staggerContainer, viewportOnce, usePrefersReducedMotion, motionProps } from '@/lib/motion'; -function Tarjeta({ n, name, desc }: { n: number; name: string; desc: string }) { - return ( - - {/* 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. */} - -

{name}

-

{desc}

-
- ); -} - export function PuntosInflexion() { const reduced = usePrefersReducedMotion(); return ( @@ -43,22 +27,18 @@ export function PuntosInflexion() { - {/* Swipeable carousel on mobile ("01 / 06" counter, as on en-ti.com); fixed grid from md up. */} -
- )} - slideClassName="pr-4" - /> -
+ {puntosInflexion.lead} + + {/* The conversation. One
  • per exchange, read top to bottom — no + carousel at any breakpoint, because "te bajas" is the whole shape + the dueña asked for. The stagger reaches ParDialogo's two halves + through React context, so each pair arrives in two beats: the + situation, then the answer. */} + className="mt-8 list-none p-0 flex flex-col gap-12 md:gap-16"> {puntosInflexion.items.map((item, i) => ( - - - + ))} diff --git a/components/sections/__tests__/PuntosInflexion.test.tsx b/components/sections/__tests__/PuntosInflexion.test.tsx index 31ff628..4c1edfe 100644 --- a/components/sections/__tests__/PuntosInflexion.test.tsx +++ b/components/sections/__tests__/PuntosInflexion.test.tsx @@ -1,22 +1,58 @@ import { render, screen } from '@testing-library/react'; import { describe, it, expect } from 'vitest'; import { PuntosInflexion } from '../PuntosInflexion'; +import { puntosInflexion } from '@/lib/content'; describe('', () => { it('renders the section title', () => { render(); expect(screen.getByText(/llegan a un punto de inflexión/i)).toBeInTheDocument(); }); + it('renders the six inflection points from the dueña deck', () => { render(); - // Each point renders twice in the markup — once in the mobile carousel, - // once in the desktop grid — with CSS `hidden`/`md:` toggling which one - // is actually visible at a given breakpoint. + // Each point now renders once, not twice: the mobile carousel is gone and + // the conversation stacks vertically at every breakpoint. for (const name of ['Crecer', 'Consolidarse', 'Recuperar rentabilidad', 'Simplificar', 'Expandirse', 'Replantear el portafolio']) { - expect(screen.getAllByText(name).length).toBeGreaterThanOrEqual(1); + expect(screen.getByText(new RegExp(name))).toBeInTheDocument(); } expect(screen.getAllByRole('listitem')).toHaveLength(6); }); + + it('answers every situation instead of only naming it', () => { + render(); + // The whole point of the section, and the one thing that would silently + // regress back into the old mute grid: six situations, six answers, each + // spoken by creeer. + expect(screen.getAllByLabelText('creeer')).toHaveLength(6); + for (const { respuesta } of puntosInflexion.items) { + expect(screen.getByText(respuesta)).toBeInTheDocument(); + } + }); + + it('states each situation in the second person, as the dueña reads them', () => { + // Her own phrasing in the 31/jul call: "estás atrapado en tu compañía", + // "creciste muy rápido pero quieres expandirte". The deck's infinitives + // ("Dar el siguiente salto") would put the reader outside their own story. + // + // Only real second-person markers count here. The first draft of this + // pattern also accepted `dejó|volvió|abiertos|mismo`, which let four + // impersonal lines through — "El esfuerzo dejó de traducirse en resultado" + // never addresses anyone. That was the test being bent to fit the copy. + for (const { situacion } of puntosInflexion.items) { + expect(situacion).toMatch(/\b(tu|tus|te|ti|tienes|vas|sabes|quieres|puedes|demostraste|construiste|creciste)\b/i); + } + }); + + it('keeps the situations about the business, not about how it feels', () => { + // `dolores` is four sections down and owns the feelings, in the client's + // own first-person words. If a situation starts saying "siento" or "estoy + // agotado", the two sections collapse into each other. + for (const { situacion } of puntosInflexion.items) { + expect(situacion).not.toMatch(/\b(siento|me siento|estoy|agotad|frustrad|harto)\b/i); + } + }); + it('does NOT introduce scarcity', () => { const { container } = render(); expect(container.textContent).not.toMatch(/cupos|cohorte|generación fundadora/i); diff --git a/lib/content.ts b/lib/content.ts index 450ccb3..cb8b10d 100644 --- a/lib/content.ts +++ b/lib/content.ts @@ -32,18 +32,52 @@ export const fraseAncla = { }, }; -// The six inflection points, verbatim from the dueña's deck -// "Rumbo Estratégico · Propuesta Socio" (slide 2). +// The six inflection points, from the dueña's deck "Rumbo Estratégico · +// Propuesta Socio" (slide 2). The deck states each one in the infinitive +// ("Dar el siguiente salto sin saber por dónde"); here it is stated in the +// second person, the way she reads them aloud herself — "estás atrapado en tu +// compañía", "creciste muy rápido pero quieres expandirte" (call of 31/jul, +// 6:01–7:15). `respuesta` is new copy and still needs her sign-off; 01 and 05 +// are the two exchanges she improvised on that call, written out. +// +// `situacion` describes the state of the business. It must not drift into how +// the reader feels — that is `dolores`, one section down, in the client's own +// first-person words, and the two would collapse into each other. export const puntosInflexion = { eyebrow: 'el contexto', title: 'Todos los negocios consolidados llegan a un punto de inflexión', + lead: '¿Te reconoces?', items: [ - { name: 'Crecer', desc: 'Dar el siguiente salto sin saber por dónde.' }, - { name: 'Consolidarse', desc: 'Ordenar lo construido antes de escalar.' }, - { name: 'Recuperar rentabilidad', desc: 'El esfuerzo ya no se traduce en resultado.' }, - { name: 'Simplificar', desc: 'Demasiada complejidad operativa.' }, - { name: 'Expandirse', desc: 'Nuevos mercados, mismo mapa de decisión.' }, - { name: 'Replantear el portafolio', desc: 'Qué seguir, qué dejar ir.' }, + { + name: 'Crecer', + situacion: 'Ya demostraste que sabes crecer. El siguiente salto no tiene mapa.', + respuesta: 'Me sumerjo hasta entender tu empresa desde dentro. Sales sabiendo por dónde, no intentándolo por todos lados a la vez.', + }, + { + name: 'Consolidarse', + situacion: 'Construiste rápido. Escalar así multiplicaría el desorden.', + respuesta: 'Ordenamos lo que ya existe antes de ponerle más peso encima. Escalas sobre algo que aguanta.', + }, + { + name: 'Recuperar rentabilidad', + situacion: 'Tu esfuerzo dejó de traducirse en resultado.', + respuesta: 'Cuestiono lo que todos dan por hecho en tu operación. El margen no siempre está en vender más.', + }, + { + name: 'Simplificar', + situacion: 'Tu operación se volvió más compleja que tu negocio.', + respuesta: 'Separo lo que solo tú puedes decidir de lo que la empresa debería resolver sin ti.', + }, + { + name: 'Expandirse', + situacion: 'Vas a mercados nuevos con el mismo mapa de decisión.', + respuesta: 'Reviso tu proceso y ubico la oportunidad real antes de mover una ficha. Expandirte deja de ser una apuesta.', + }, + { + name: 'Replantear el portafolio', + situacion: 'Tienes varios frentes abiertos y ninguno con su lugar claro.', + respuesta: 'Construimos, juntos, el criterio para decidir qué sigue y qué se deja ir. Por escrito, no en tu cabeza.', + }, ], };