Files
evandro c7d09d63d4
CI / audit (push) Successful in 10m38s
CI / verify (push) Successful in 13m10s
CI / deploy (push) Successful in 1m50s
CI / e2e (push) Successful in 18m48s
feat(site): blocos 3D da marca, novas ofertas e hero mais abrangente
Hero e movimento
- cena 3D em tempo real com os blocos da marca (kit feito no Blender, 3d/blocos.py):
  marca, tela, integrações e dados; segue a rolagem, tem vida em repouso, reage ao
  cursor e, parada no topo, passa sozinha pelos estados com legenda
- três níveis de aparelho (full, lite, static); sem WebGL fica o pôster
- título novo: "Sites e sistemas sob medida para o jeito que a sua empresa trabalha."
- faixa de clientes com o ramo, linha do primeiro passo, hero alinhado às seções
- rótulos digitados, entrada dos blocos, cortina de blocos entre páginas e capa
  compartilhada entre a lista de cases e o case

Ofertas
- atendimento no WhatsApp com IA e nota fiscal para a reforma tributária
  (páginas de serviço, cartões da home, formulário e aviso com data de validade)
- página /ia atualizada, com fontes
- peças 3D em loop nos cartões e topos de página (3d/pecas.py)

Design
- hover por papel (bloco nos botões, barra nos links), rótulos sem caixa alta
- um destino por rótulo: "Falar sobre meu projeto" leva ao formulário,
  "Chamar no WhatsApp" abre o WhatsApp
- logo montado em blocos, 404 redesenhado, grades sem célula vazia
- ícones do PWA e manifesto novos

Specs em specs/, contexto de design em DESIGN.md e PRODUCT.md.
2026-11-10 03:48:25 -03:00

107 lines
3.1 KiB
TypeScript

import "@testing-library/jest-dom";
if (typeof global.ResizeObserver === "undefined") {
class ResizeObserver {
observe() {}
unobserve() {}
disconnect() {}
}
global.ResizeObserver = ResizeObserver as typeof global.ResizeObserver;
}
// Mock IntersectionObserver if not available in JSDOM
if (typeof global.IntersectionObserver === "undefined") {
class IntersectionObserver {
root: Element | Document | null = null;
rootMargin: string = "";
thresholds: ReadonlyArray<number> = [];
private callback: IntersectionObserverCallback;
private elements: Set<Element> = new Set();
constructor(
callback: IntersectionObserverCallback,
options?: IntersectionObserverInit,
) {
this.callback = callback;
this.root = options?.root || null;
this.rootMargin = options?.rootMargin || "";
const threshold = options?.threshold ?? 0;
this.thresholds = Array.isArray(threshold) ? threshold : [threshold];
}
observe(target: Element) {
this.elements.add(target);
setTimeout(() => {
this.callback(
[
{
target,
isIntersecting: true,
intersectionRatio: 1,
boundingClientRect: target.getBoundingClientRect(),
intersectionRect: target.getBoundingClientRect(),
rootBounds:
this.root instanceof Element
? this.root.getBoundingClientRect()
: null,
time: Date.now(),
} as IntersectionObserverEntry,
],
this,
);
}, 0);
}
unobserve(target: Element) {
this.elements.delete(target);
}
disconnect() {
this.elements.clear();
}
takeRecords(): IntersectionObserverEntry[] {
return [];
}
}
global.IntersectionObserver =
IntersectionObserver as typeof global.IntersectionObserver;
}
// Mock PointerEvent if not available in JSDOM
if (typeof global.PointerEvent === "undefined") {
class PointerEvent extends MouseEvent {
pointerId: number;
pointerType: string;
isPrimary: boolean;
constructor(type: string, params: PointerEventInit = {}) {
super(type, params);
this.pointerId = params.pointerId || 0;
this.pointerType = params.pointerType || "mouse";
this.isPrimary = params.isPrimary || false;
}
}
global.PointerEvent = PointerEvent as typeof global.PointerEvent;
}
// Mock window.matchMedia
Object.defineProperty(window, "matchMedia", {
writable: true,
value: jest.fn().mockImplementation((query) => ({
matches: false,
media: query,
onchange: null,
addListener: jest.fn(),
removeListener: jest.fn(),
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
dispatchEvent: jest.fn(),
})),
});
// O React estável do Jest não exporta <ViewTransition> (só o canary do Next): aqui ele só repassa os filhos.
// Testes que conferem as props dele trocam este dublê pelo seu (jest.mock("react")).
const actualReact = jest.requireActual("react");
actualReact.ViewTransition ??= ({ children }: { children?: unknown }) =>
children;