feat(home): ofertas que vendem o título, WhatsApp no hero e menu do celular acessível

Três ofertas (site que traz pedidos pelo WhatsApp, sistema para tirar a operação da planilha, revisão de sistema existente) com miniatura e formulário com o tipo escolhido; botão principal do hero abre o WhatsApp; moldura da SEV no hero do celular; menu fecha ao navegar, Esc, foco preso incluindo a barra de cookies e espaço para ela; CinematicHome como componente de servidor com ilha cliente; /ia com H1 de oferta e cartão do que você recebe; botão flutuante em aside com transform; AVIF antes de WebP; copy sem repetir contato direto.
This commit is contained in:
Evandro Fonseca Junior committed 2026-10-14 17:01:36 -03:00
1 parent de6af74a0c
commit f8545cd442
44 files changed
+2286 -571

No files matched your search

+19 -2
View File
@@ -2,7 +2,7 @@ import { render, screen, within } from "@testing-library/react";
import HomeFaq, { FAQ_ITEMS } from "./HomeFaq";
describe("HomeFaq", () => {
it("shows the four questions the site already backs up, closed by default", () => {
it("shows the five questions the site already backs up, closed by default", () => {
const { container } = render(<HomeFaq />);
expect(
@@ -13,6 +13,7 @@ describe("HomeFaq", () => {
);
expect(summaries).toEqual([
"Como começa um projeto?",
"Quanto custa?",
"Você atende fora de Santa Catarina?",
"Dá para continuar um sistema que já existe ou que foi feito com IA?",
"O que preciso ter para começar?",
@@ -54,7 +55,23 @@ describe("HomeFaq", () => {
// ...e fora da página
expect(screen.queryByText(unanswered)).toBeNull();
}
expect(container.querySelectorAll("details")).toHaveLength(4);
expect(container.querySelectorAll("details")).toHaveLength(5);
});
it("answers 'Quanto custa?' with the owner's sentence only: no value, no deadline, and no promise that the first talk is free", () => {
render(<HomeFaq />);
const details = screen
.getByText("Quanto custa?")
.closest("details") as HTMLElement;
expect(
within(details).getByText(
"Depois da primeira conversa você recebe escopo, valor e prazo por escrito, antes de qualquer compromisso.",
),
).toBeInTheDocument();
expect(details.textContent).not.toMatch(
/R\$|\d|grátis|gratuit|sem custo|sem compromisso/i,
);
});
it("starts showing a prepared question as soon as it gets an answer", () => {