/* global React */
/* ═══════════════════════════════════════════════════════════════════════════
AUREA · BACK INTO LOVE, destaque do AI Creative Studio
Proposta local (site-agent 2026-09-11). Não está em produção.
Fica entre o Hero e as "Quatro frentes".
Pela ordem em que aparecem:
1. making of, em grande: explica o processo e é a peça principal
2. slider chroma vs composite: prova o método num plano só
3. cartão para o clipe completo no YouTube
═══════════════════════════════════════════════════════════════════════════ */
const AUREA_MEDIA = window.BOLDER_AUREA_MEDIA || "/assets/aurea/";
const AUREA_YT = "https://www.youtube.com/watch?v=F4CdL1BeYkk";
function aureaPlay(v) { const p = v && v.play(); if (p && p.catch) p.catch(() => {}); }
/* Toca só quando está à vista. Vídeos a correr fora do ecrã gastam bateria e
dados a quem nunca os vê. */
function useTocaQuandoVisivel(refs) {
React.useEffect(() => {
const alvo = refs[0].current;
if (!alvo) return;
const io = new IntersectionObserver(([e]) => {
refs.forEach((r) => { const v = r.current; if (!v) return; e.isIntersecting ? aureaPlay(v) : v.pause(); });
}, { threshold: 0.2 });
io.observe(alvo);
return () => io.disconnect();
}, []); // eslint-disable-line react-hooks/exhaustive-deps
}
function AureaMakingOf() {
const v = React.useRef(null);
const [comSom, setComSom] = React.useState(false);
const comSomRef = React.useRef(false);
// Enquanto ninguém carrega, passa em silêncio e em loop, como antevisão.
// Depois de carregar, é o vídeo a sério: do início, com som e controlos.
React.useEffect(() => {
const el = v.current; if (!el) return;
const io = new IntersectionObserver(([e]) => {
if (comSomRef.current) { if (!e.isIntersecting && !el.paused) el.pause(); return; }
e.isIntersecting ? aureaPlay(el) : el.pause();
}, { threshold: 0.25 });
io.observe(el);
return () => io.disconnect();
}, []);
const verComSom = () => {
const el = v.current; if (!el) return;
comSomRef.current = true; setComSom(true);
el.loop = false; el.muted = false; el.controls = true; el.currentTime = 0;
aureaPlay(el);
};
return (
Making of · 1:11Do chroma à personagem
{!comSom && (
)}
);
}
function AureaSlider() {
const caixa = React.useRef(null);
const chroma = React.useRef(null); // relógio mestre
const comp = React.useRef(null); // segue o chroma
const arrastar = React.useRef(false);
const [pos, setPos] = React.useState(50);
const [tocado, setTocado] = React.useState(false);
useTocaQuandoVisivel([chroma, comp]);
// Os dois ficheiros têm 440 frames exactos. O composite corrige-se ao chroma
// sempre que derrapa mais de frame e meio, senão a costura mostraria dois
// instantes diferentes e o efeito desfazia-se.
React.useEffect(() => {
let raf;
const passo = () => {
const a = chroma.current, b = comp.current;
if (a && b && !a.paused && Math.abs(b.currentTime - a.currentTime) > 1.5 / 24) {
b.currentTime = a.currentTime;
}
raf = requestAnimationFrame(passo);
};
raf = requestAnimationFrame(passo);
return () => cancelAnimationFrame(raf);
}, []);
// Enquanto ninguém mexe, a pega oscila devagar. É o que diz que aquilo se arrasta.
React.useEffect(() => {
if (tocado || window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
let raf; const t0 = performance.now();
const osc = (t) => { setPos(50 + Math.sin((t - t0) / 2200) * 24); raf = requestAnimationFrame(osc); };
raf = requestAnimationFrame(osc);
return () => cancelAnimationFrame(raf);
}, [tocado]);
const mover = (x) => {
const r = caixa.current.getBoundingClientRect();
setPos(Math.max(0, Math.min(100, ((x - r.left) / r.width) * 100)));
};
const onDown = (e) => { setTocado(true); arrastar.current = true; caixa.current.setPointerCapture(e.pointerId); mover(e.clientX); };
const onMove = (e) => {
if (!arrastar.current) return;
// Rato sem botão carregado: o pointerup perdeu-se algures, larga a pega.
if (e.pointerType === "mouse" && e.buttons === 0) { arrastar.current = false; return; }
mover(e.clientX);
};
const onUp = () => { arrastar.current = false; };
const onKey = (e) => {
const d = e.shiftKey ? 10 : 2;
if (e.key === "ArrowLeft") { setTocado(true); setPos((p) => Math.max(0, p - d)); e.preventDefault(); }
if (e.key === "ArrowRight") { setTocado(true); setPos((p) => Math.min(100, p + d)); e.preventDefault(); }
};
return (
);
}
function AureaDestaque() {
return (
Novo · Videoclipe híbrido · 2026
Aurea. Back Into Love
Os playbacks foram filmados em chroma, em estúdio. O ambiente e a história foram
gerados em IA. A personagem fora dos playbacks nasceu de mais de 300 fotografias dela.