fix(home): oferta leva ao formulário, ofertas logo depois da vitrine
O botão das ofertas rola até o contato com o tipo marcado e não quebra mais as âncoras; ofertas com o que você recebe e primeiro passo, logo depois da vitrine; bloco de IA fora da home; cartão largo da SEV no hero do celular; separador da faixa de clientes só entre itens; favicon de 13 para 1,8 KB; pré-carregamento só no hover e nunca de /#... fora da home; X do menu e cabeçalho opaco; WhatsApp com "o case"; /ia com 3 passos e modelo de relatório ilustrativo; Sobre alinhado ao currículo; CSP Report-Only com os domínios do Ads.
This commit is contained in:
1 parent
fc44a69fb3
commit
9e2d65a926
51 files changed
+1730
-420
No files matched your search
+113
-6
@@ -5,6 +5,7 @@ import {
|
||||
primaryButton,
|
||||
textLinkDark,
|
||||
} from "@/app/components/button-styles";
|
||||
import HoverPrefetchLink from "@/app/components/HoverPrefetchLink";
|
||||
import WhatsAppLink from "@/app/components/WhatsAppLink";
|
||||
import { safeJsonLd } from "@/lib/jsonld";
|
||||
import { buildBreadcrumbList, buildPageSocialMetadata } from "@/lib/seo";
|
||||
@@ -53,6 +54,51 @@ const DELIVERABLES = [
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* Como a revisão anda, em três passos, no cartão do hero. Só o que o resto da página já diz: a conversa pelo WhatsApp
|
||||
* (sem enviar senhas), o teste e a separação do que aproveitar do que refazer, e o orçamento por escrito. Sem prazo e
|
||||
* sem preço: isso se combina na conversa.
|
||||
*/
|
||||
const STEPS = [
|
||||
{
|
||||
title: "Conversa pelo WhatsApp",
|
||||
description:
|
||||
"Você conta o que o app faz e o que ele precisa fazer. Não envie senhas nem acessos por mensagem.",
|
||||
},
|
||||
{
|
||||
title: "Teste e avaliação",
|
||||
description:
|
||||
"Testo se uma pessoa consegue ver ou alterar os dados de outra e separo o que dá para aproveitar do que é melhor refazer.",
|
||||
},
|
||||
{
|
||||
title: "Relatório e orçamento",
|
||||
description:
|
||||
"Você recebe o que precisa de correção e o orçamento por escrito para pôr o app em produção.",
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* Três achados de EXEMPLO do relatório, para mostrar como ele é organizado: a falha, a gravidade e a correção sugerida.
|
||||
* São ilustrativos: não são de nenhum cliente nem de um app real, e a página os rotula assim.
|
||||
*/
|
||||
const REPORT_EXAMPLES = [
|
||||
{
|
||||
flaw: "Um usuário consegue abrir os dados de outro trocando o número no endereço da página.",
|
||||
severity: "Alta",
|
||||
fix: "Conferir no servidor se cada registro pertence a quem está logado e testar com contas de empresas diferentes.",
|
||||
},
|
||||
{
|
||||
flaw: "A chave de acesso ao banco de dados está no código que o navegador baixa.",
|
||||
severity: "Alta",
|
||||
fix: "Levar a chave para o servidor, trocar a que ficou exposta e liberar no banco só o que cada perfil precisa.",
|
||||
},
|
||||
{
|
||||
flaw: "Não há cópia de segurança com restauração testada.",
|
||||
severity: "Média",
|
||||
fix: "Ligar as cópias automáticas, separar o banco de testes do de produção e ensaiar a restauração.",
|
||||
},
|
||||
];
|
||||
|
||||
const RESPONSIBILITIES = [
|
||||
{
|
||||
title: "Quem pode acessar cada dado?",
|
||||
@@ -161,24 +207,27 @@ export default function AiPage() {
|
||||
>
|
||||
Pedir a revisão do meu app
|
||||
</WhatsAppLink>
|
||||
{/* Segue na própria página: os cases do portfólio não são revisões de app feito com IA. */}
|
||||
<a href="#ia-receber" className={textLinkDark}>
|
||||
Ver como a revisão funciona
|
||||
</a>
|
||||
{/* Link secundário para os cases: mostram como eu entrego, não são revisões de app feito com IA. */}
|
||||
<HoverPrefetchLink href="/cases" className={textLinkDark}>
|
||||
Ver projetos entregues
|
||||
</HoverPrefetchLink>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
data-testid="ia-review-card"
|
||||
data-testid="ia-steps-card"
|
||||
className="min-w-0 border border-white/15 bg-white/[0.04] p-sp-6 sm:p-sp-8"
|
||||
>
|
||||
<p className="font-display text-xl font-semibold leading-7 text-white">
|
||||
O que você recebe
|
||||
Como funciona em 3 passos
|
||||
</p>
|
||||
<ol className="mt-sp-5 flex flex-col">
|
||||
{DELIVERABLES.map((item, index) => (
|
||||
{STEPS.map((step, index) => (
|
||||
<li
|
||||
key={item.title}
|
||||
key={step.title}
|
||||
className="flex items-start gap-sp-4 border-t border-white/12 py-sp-4 first:border-t-0 first:pt-0 last:pb-0"
|
||||
>
|
||||
<span
|
||||
@@ -188,7 +237,10 @@ export default function AiPage() {
|
||||
{String(index + 1).padStart(2, "0")}
|
||||
</span>
|
||||
<span className="min-w-0 font-display text-base leading-6 text-white/90">
|
||||
{item.title}
|
||||
<strong className="font-semibold text-white">
|
||||
{step.title}.
|
||||
</strong>{" "}
|
||||
{step.description}
|
||||
</span>
|
||||
</li>
|
||||
))}
|
||||
@@ -230,6 +282,61 @@ export default function AiPage() {
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section
|
||||
id="ia-modelo"
|
||||
className="ds-section"
|
||||
aria-labelledby="ia-modelo-title"
|
||||
>
|
||||
<div className="ds-section-shell">
|
||||
<h2 id="ia-modelo-title" className="ds-section-title max-w-[26ch]">
|
||||
Modelo do relatório
|
||||
</h2>
|
||||
<p className="ds-copy max-w-[65ch]">
|
||||
Cada falha encontrada entra no relatório com a gravidade e a
|
||||
correção sugerida. Os três achados abaixo são{" "}
|
||||
<strong>exemplos ilustrativos</strong> de como ele é organizado: não
|
||||
são de nenhum cliente nem de um app real.
|
||||
</p>
|
||||
<ol className="mt-sp-8 grid gap-sp-6 lg:grid-cols-3">
|
||||
{REPORT_EXAMPLES.map((example, index) => (
|
||||
<li key={example.flaw} className="flex">
|
||||
<article className="ds-card w-full">
|
||||
<p className="ds-kicker">
|
||||
Exemplo ilustrativo {String(index + 1).padStart(2, "0")}
|
||||
</p>
|
||||
<dl className="mt-sp-4 flex flex-col gap-sp-4">
|
||||
<div>
|
||||
<dt className="font-display text-[15px] font-semibold leading-6 text-[var(--ink)]">
|
||||
Falha
|
||||
</dt>
|
||||
<dd className="font-display text-[15px] leading-6 text-[var(--ink-80)]">
|
||||
{example.flaw}
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt className="font-display text-[15px] font-semibold leading-6 text-[var(--ink)]">
|
||||
Gravidade
|
||||
</dt>
|
||||
<dd className="font-display text-[15px] leading-6 text-[var(--ink-80)]">
|
||||
{example.severity}
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt className="font-display text-[15px] font-semibold leading-6 text-[var(--ink)]">
|
||||
Correção sugerida
|
||||
</dt>
|
||||
<dd className="font-display text-[15px] leading-6 text-[var(--ink-80)]">
|
||||
{example.fix}
|
||||
</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</article>
|
||||
</li>
|
||||
))}
|
||||
</ol>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="ds-section" aria-labelledby="ia-contratar-title">
|
||||
<div className="ds-section-shell">
|
||||
<h2 id="ia-contratar-title" className="ds-section-title max-w-[26ch]">
|
||||
|
||||
Reference in new issue
Block a user