perf(movimento): sem tempo morto, vídeos regravados e 3D sem React Three Fiber

Legenda do mergulho até Projetos cobrir a cena; transição de página sem blur e com fundo escuro; foco no conteúdo ao trocar de página; listas com marcador e dois pesos de título; vídeos da SEV e da SC Plus regravados sem quadros brancos; scrub a 12-15 fps (-30%); vitrine com uma parada de Tab e setas, contador no celular e CSS sob demanda; âncoras num módulo só (fragment-nav); FramePulse com setInterval; CSS morto removido.
This commit is contained in:
Evandro Fonseca Junior committed 2026-10-14 17:01:37 -03:00
1 parent f8545cd442
commit 6ac87824f3
68 files changed
+5735 -3300

No files matched your search

@@ -0,0 +1,54 @@
import { readFileSync } from "node:fs";
import { join } from "node:path";
import { HERO_TAIL_SCREENS } from "./HeroField";
/*
* O mergulho do hero é uma conta que vive em dois lugares: o CSS (altura do hero e margem de Projetos) e o
* HeroField (de onde o progresso --hero-p sai). Se um mudar sem o outro, o progresso acaba antes ou depois de
* Projetos começar a subir e volta o tempo morto (ou a tela vazia) no fim do mergulho.
*/
const css = readFileSync(join(__dirname, "../../globals.css"), "utf8");
function diveBlock() {
const start = css.indexOf(".hero[data-dive] {");
expect(start).toBeGreaterThan(-1);
return css.slice(start, start + 6000);
}
describe("hero dive (globals.css <-> HeroField)", () => {
it("the hero is HERO_TAIL_SCREENS screens taller than the dive", () => {
const height = /height: calc\((\d+)svh \+ var\(--hero-dive\)\)/.exec(
diveBlock(),
);
expect(height).not.toBeNull();
expect(Number(height?.[1]) / 100).toBe(HERO_TAIL_SCREENS);
});
it("Projects rises over the stage by the tail minus the pinned stage (one screen)", () => {
const margin = /margin-top: -(\d+)svh/.exec(diveBlock());
expect(margin).not.toBeNull();
expect(Number(margin?.[1]) / 100).toBeCloseTo(HERO_TAIL_SCREENS - 1);
});
it("the last caption stays on stage until Projects covers it (its end is past the end of the dive)", () => {
const last =
/li:nth-child\(3\) \{\s*--from: ([\d.]+);\s*--to: ([\d.]+);/.exec(
diveBlock(),
);
expect(last).not.toBeNull();
expect(Number(last?.[2])).toBeGreaterThan(1);
});
it("each caption starts before the previous one is gone far enough that the gap between them is short", () => {
const ranges = [
...diveBlock().matchAll(
/li:nth-child\((\d)\) \{\s*--from: ([\d.]+);\s*--to: ([\d.]+);/g,
),
].map((match) => [Number(match[2]), Number(match[3])]);
expect(ranges).toHaveLength(3);
for (let i = 1; i < ranges.length; i++) {
// sem texto entre uma legenda e a seguinte: no máximo 0,1 de progresso (~100 px de rolagem)
expect(ranges[i][0] - ranges[i - 1][1]).toBeLessThanOrEqual(0.1);
}
});
});