perf(movimento): sem tela vazia, passagens em CSS e vitrine leve
Projetos sobem sobre o palco do hero e o celular tem hero de uma tela sem mergulho; passagens com animation-timeline em CSS, sem GSAP nem motion; troca da vitrine sem texto duplicado; moldura de celular só com pôster e scrub reencodado em 960 px (9,4 para 5,2 MB); 3D monta na primeira interação e para quando parado; transição entre páginas do mesmo segmento; foco em anel duplo; texto de 15 px no celular; código morto removido.
This commit is contained in:
1 parent
10f170abf4
commit
318a764190
77 files changed
+4293
-4951
No files matched your search
@@ -1,30 +1,5 @@
|
||||
/** Contas puras da vitrine (sem DOM), separadas para serem testadas uma a uma. */
|
||||
|
||||
export interface CardCandidate {
|
||||
id: string;
|
||||
visible: boolean;
|
||||
/** Distância do centro do card ao centro da tela, em pixels. */
|
||||
distance: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Qual card toca: o que está sob o mouse (se visível); senão o visível mais perto do centro da tela.
|
||||
* Empate fica com o primeiro da lista (ordem do DOM: esquerda antes de direita).
|
||||
*/
|
||||
export function pickActiveCard(
|
||||
candidates: CardCandidate[],
|
||||
hoveredId: string | null,
|
||||
): string | null {
|
||||
const visible = candidates.filter((candidate) => candidate.visible);
|
||||
if (hoveredId && visible.some((candidate) => candidate.id === hoveredId))
|
||||
return hoveredId;
|
||||
let best: CardCandidate | null = null;
|
||||
for (const candidate of visible) {
|
||||
if (!best || candidate.distance < best.distance - 0.5) best = candidate;
|
||||
}
|
||||
return best?.id ?? null;
|
||||
}
|
||||
|
||||
export interface ReelPosition {
|
||||
/** Projeto em cena. */
|
||||
index: number;
|
||||
|
||||
Reference in new issue
Block a user