feat(hero): hero redesenhada, titulo visivel no HTML (LCP) e cena 3D so depois do idle

- titulo fluido (clamp ate 88px) com destaque em 'sob medida', eyebrow mono, seta no CTA e brilho de fundo
- numeros reais na hero (anos de experiencia, projetos publicados, demos online) calculados em app/page.tsx a partir dos dados do portfolio
- remove o opacity:0 inicial do motion: o texto nasce visivel; a entrada anima so a posicao (CSS)
- HeroSystem monta a cena Three.js via requestIdleCallback (timeout 2,5s), depois de pintar e hidratar o essencial
- capas decorativas (sem captura) escondidas no celular

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
This commit is contained in:
Evandro Fonseca JuniorandClaude Sonnet 5.5 committed 2026-10-04 23:48:19 -03:00
1 parent 35a950a9b1
commit 23aeaa2fda
5 files changed
+140 -28

No files matched your search

+27 -2
View File
@@ -88,11 +88,36 @@ export default function HeroSystem() {
}
}
}
setCanRender(supported);
mountScene(supported);
};
// A cena 3D (Three.js) so entra depois que a pagina ficou ociosa: titulo, imagem e botoes pintam e hidratam primeiro.
let idle: number | undefined;
let timer: ReturnType<typeof setTimeout> | undefined;
const cancelPending = () => {
if (idle !== undefined) window.cancelIdleCallback?.(idle);
if (timer !== undefined) clearTimeout(timer);
idle = timer = undefined;
};
const mountScene = (value: boolean) => {
cancelPending();
if (!value) {
setCanRender(false);
return;
}
if (typeof window.requestIdleCallback === "function") {
idle = window.requestIdleCallback(() => setCanRender(true), {
timeout: 2500,
});
} else {
timer = setTimeout(() => setCanRender(true), 1200);
}
};
updateCapability();
preference.addEventListener("change", updateCapability);
return () => preference.removeEventListener("change", updateCapability);
return () => {
cancelPending();
preference.removeEventListener("change", updateCapability);
};
}, []);
useEffect(() => {