diff --git a/components/layout/__tests__/Footer.test.tsx b/components/layout/__tests__/Footer.test.tsx
index 61fd4d1..aaba8b7 100644
--- a/components/layout/__tests__/Footer.test.tsx
+++ b/components/layout/__tests__/Footer.test.tsx
@@ -1,6 +1,7 @@
import { render, screen } from '@testing-library/react';
import { describe, it, expect } from 'vitest';
import { Footer } from '../Footer';
+import { creditosFotos } from '@/lib/content';
describe('', () => {
it('renders the tagline and the legal line', () => {
@@ -12,11 +13,19 @@ describe('', () => {
render();
expect(screen.queryByRole('heading', { level: 1 })).toBeNull();
});
- it('credits the stock photos per their CC BY-SA 4.0 licence', () => {
+ it('credits every reused photograph, with author, licence and modification notice', () => {
render();
- expect(screen.getAllByText(/CC BY-SA 4\.0/)).toHaveLength(2);
- expect(screen.getByText(/Golden Gate Bridge/)).toBeInTheDocument();
- expect(screen.getByText(/Monte Nardi/)).toBeInTheDocument();
- expect(screen.getAllByText(/modificada/).length).toBe(2);
+ // The licences these photographs carry require three things: naming the
+ // author, linking the licence, and saying the image was modified. This is
+ // the only place in the project where that obligation is enforced, so it
+ // counts against `creditosFotos` itself rather than a number typed here —
+ // adding a photograph without crediting it has to fail, and a hard-coded
+ // count only fails once someone remembers to update it.
+ for (const credito of creditosFotos) {
+ expect(credito.desc).toMatch(/—\s*\S/); // the author, after the em dash
+ expect(screen.getByText(credito.desc)).toHaveAttribute('href', credito.href);
+ expect(screen.getAllByText(credito.licencia).length).toBeGreaterThan(0);
+ }
+ expect(screen.getAllByText(/modificada/)).toHaveLength(creditosFotos.length);
});
});
diff --git a/components/sections/PuntosInflexion.tsx b/components/sections/PuntosInflexion.tsx
index 377cd75..60f363a 100644
--- a/components/sections/PuntosInflexion.tsx
+++ b/components/sections/PuntosInflexion.tsx
@@ -4,6 +4,7 @@ import { useEffect, useRef, useState } from 'react';
import { motion, useMotionValue, useMotionValueEvent, useSpring, useTransform } from 'framer-motion';
import { Container } from '@/components/primitives/Container';
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';
@@ -13,6 +14,24 @@ import { fadeInUp, staggerContainer, viewportOnce, usePrefersReducedMotion, moti
const items = puntosInflexion.items;
const TOTAL = items.length;
+// One photograph per inflection point, in the order the points are declared.
+// Asset wiring, not copy — `lib/content.ts` stays the source of truth for words
+// only. Every file is from Wikimedia Commons under a licence that allows reuse,
+// and every one is credited in `creditosFotos`; the footer renders that list.
+//
+// They are read through FondoFoto, which pushes them through
+// mix-blend-luminosity over the brand's navy→gold gradient, so no photograph
+// ever brings its own colour onto the page. Under the veils below they read as
+// texture, not as stock photography.
+const FOTOS = [
+ '/images/recorrido/crecer.jpg', // a mountain road with no visible end
+ '/images/recorrido/consolidarse.jpg', // a building still open to the weather
+ '/images/recorrido/rentabilidad.jpg', // the harvest: effort turned into result
+ '/images/recorrido/simplificar.jpg', // wires crossing a sky, lines multiplying
+ '/images/recorrido/expandirse.jpg', // a container port, new markets
+ '/images/recorrido/portafolio.jpg', // a whole city at once, nothing prioritised
+];
+
function Cabecera({ reduced }: { reduced: boolean }) {
return (
@@ -102,6 +121,8 @@ function Escenificado() {
const barra = useTransform(progreso, [0, 1], [0, 1]);
const fondoY = useTransform(progreso, [0, 1], [0, -140]);
+ // A slower drift than the dots, so the photograph sits behind them in depth.
+ const fotoY = useTransform(progreso, [0, 1], [0, -70]);
return (
@@ -112,20 +133,45 @@ function Escenificado() {
{/* One viewport of stage, six viewports of scroll to move through it. */}
-
-
-
+ {/* The photograph of whichever point is on screen, crossfading with
+ the beat. Only the active one is opaque; the rest sit at zero, so
+ the browser still holds them decoded and the swap costs nothing. */}
+ {items.map((item, i) => (
+
+
+
+
+
+ ))}
- {/* The frame itself turns over on the answer. The whole stage goes to
- azul-profundo, not a panel inside it — the answer is not a card on
- the reader's page, it is creeer's ground. */}
+ {/* "Respetando la capa azul y blanco": the photograph never carries
+ the frame, it only gives it grain. The light veil holds the
+ question legible in azul-profundo type; the navy veil takes the
+ whole stage over for the answer. Both are heavy on purpose —
+ anything thinner and the copy starts fighting the photograph. */}
+
+
+
+
+
{/* left-6 / md:left-12, not left-0: an absolutely positioned child
resolves against Container's padding box, so `left-0` lands on
diff --git a/lib/content.ts b/lib/content.ts
index cb8b10d..efe9659 100644
--- a/lib/content.ts
+++ b/lib/content.ts
@@ -181,9 +181,17 @@ export const footer = {
legal: '© 2026 creeer',
};
-// CC BY-SA 4.0 requires attribution + a link to the licence + noting the
-// image was modified (both got a navy/gold duotone treatment).
+// Every reused photograph is credited here and the footer renders the list.
+// CC BY-SA / CC BY require attribution + a link to the licence + noting the
+// image was modified — all of them get the navy/gold duotone treatment, and the
+// six in `recorrido` are additionally cropped and resized.
export const creditosFotos = [
{ desc: 'Foto: Golden Gate Bridge — Dietmar Rabich', href: 'https://commons.wikimedia.org/wiki/File:San_Francisco_(CA,_USA),_Golden_Gate_Bridge_--_2022_--_3023_(bw).jpg', licencia: 'CC BY-SA 4.0', licenciaHref: 'https://creativecommons.org/licenses/by-sa/4.0/' },
{ desc: 'Foto: amanecer, Monte Nardi — Tony 1212', href: 'https://commons.wikimedia.org/wiki/File:Sunrise_over_the_summit_of_Mount_Nardi_from_the_south.jpg', licencia: 'CC BY-SA 4.0', licenciaHref: 'https://creativecommons.org/licenses/by-sa/4.0/' },
+ { desc: 'Foto: montaña de Sheikh, Somalilandia — Abdifatah Y. Barwaaqo', href: 'https://commons.wikimedia.org/wiki/File:Sheikh_mountain,_Somaliland.jpg', licencia: 'dominio público', licenciaHref: 'https://commons.wikimedia.org/wiki/File:Sheikh_mountain,_Somaliland.jpg' },
+ { desc: 'Foto: edificio en construcción — PattayaPatrol', href: 'https://commons.wikimedia.org/wiki/File:DFC_1635_Unfinished_concrete_building_with_exposed_floors_and_metal_scaffolding_rising_along_its_side_green_safety_netting_hanging_from_the_structure.jpg', licencia: 'CC BY-SA 4.0', licenciaHref: 'https://creativecommons.org/licenses/by-sa/4.0/' },
+ { desc: 'Foto: cosechadora en el trigo — Michael Gäbler', href: 'https://commons.wikimedia.org/wiki/File:The_combine_Claas_Lexion_584_in_the_wheat_harvest.jpg', licencia: 'CC BY-SA 3.0', licenciaHref: 'https://creativecommons.org/licenses/by-sa/3.0/' },
+ { desc: 'Foto: pájaros sobre cables — Alex Martinez', href: 'https://commons.wikimedia.org/wiki/File:Birds_On_Wires_(Unsplash).jpg', licencia: 'CC0', licenciaHref: 'https://creativecommons.org/publicdomain/zero/1.0/' },
+ { desc: 'Foto: puerto de contenedores de Miami — James R. Tourtellotte', href: 'https://commons.wikimedia.org/wiki/File:Aerial_photograph_of_the_Port_of_Miami_Container_Port.jpg', licencia: 'dominio público', licenciaHref: 'https://commons.wikimedia.org/wiki/File:Aerial_photograph_of_the_Port_of_Miami_Container_Port.jpg' },
+ { desc: 'Foto: Cracovia desde el aire — Robin', href: 'https://commons.wikimedia.org/wiki/File:Aerial_photograph_of_Krak%C3%B3w.jpg', licencia: 'CC BY 2.0', licenciaHref: 'https://creativecommons.org/licenses/by/2.0/' },
];
diff --git a/public/images/recorrido/consolidarse.jpg b/public/images/recorrido/consolidarse.jpg
new file mode 100644
index 0000000..b127049
Binary files /dev/null and b/public/images/recorrido/consolidarse.jpg differ
diff --git a/public/images/recorrido/crecer.jpg b/public/images/recorrido/crecer.jpg
new file mode 100644
index 0000000..fa3e3a8
Binary files /dev/null and b/public/images/recorrido/crecer.jpg differ
diff --git a/public/images/recorrido/expandirse.jpg b/public/images/recorrido/expandirse.jpg
new file mode 100644
index 0000000..bcbf7a0
Binary files /dev/null and b/public/images/recorrido/expandirse.jpg differ
diff --git a/public/images/recorrido/portafolio.jpg b/public/images/recorrido/portafolio.jpg
new file mode 100644
index 0000000..1b0642b
Binary files /dev/null and b/public/images/recorrido/portafolio.jpg differ
diff --git a/public/images/recorrido/rentabilidad.jpg b/public/images/recorrido/rentabilidad.jpg
new file mode 100644
index 0000000..fdce5cf
Binary files /dev/null and b/public/images/recorrido/rentabilidad.jpg differ
diff --git a/public/images/recorrido/simplificar.jpg b/public/images/recorrido/simplificar.jpg
new file mode 100644
index 0000000..36ae693
Binary files /dev/null and b/public/images/recorrido/simplificar.jpg differ