import Image from "next/image"; import { getShowcaseAssets } from "@/lib/project-showcase"; import { generalFirstStep, type ServiceOffer, serviceOffers, } from "@/lib/site-content"; import { primaryButton, textLink } from "./button-styles"; import ContactOfferLink from "./ContactOfferLink"; import { FiscalNotice } from "./FiscalNotice"; import { isFiscalNoticeActive } from "./fiscal-notice"; import "./conversion.css"; import HoverPrefetchLink from "./HoverPrefetchLink"; import { OfferVideo } from "./OfferVideo"; import { Reveal } from "./Reveal"; import { Section } from "./Section"; import { WhatsAppMark } from "./WhatsAppMark"; /** O que só a home diz de cada oferta; o nome e "O que você recebe" vêm de `serviceOffers`, a fonte única que /servicos também usa. */ interface OfferExtras { description: string; ctaLabel: string; /** Case cujo pôster ilustra a oferta; sem ele, o cartão traz um vídeo ou uma ilustração própria (ver OfferArt). */ poster?: { id: string; title: string }; moreLabel: string; moreHref: string; } /** Ofertas com cartão na home; a da nota fiscal entra na faixa datada acima dos cartões (FiscalNotice). */ type HomeOfferId = Exclude; /** * Os textos da home para as quatro ofertas, na ordem de `serviceOffers`. Cada texto só diz o que o case, a página de /ia * ou a página da oferta citados já sustentam; sem prazo nem preço. Só o site tem foto: a Lavação 047 é um site de * catálogo e tabela de preços, o que o texto descreve. O sistema, o atendimento no WhatsApp e a revisão trazem uma peça * 3D em vídeo (OfferVideo); por cima, o atendimento tem o selo do aplicativo e a revisão, um recorte do relatório. */ const OFFER_EXTRAS: Record = { site: { description: "O cliente vê o que você oferece e vai para a conversa no WhatsApp, como na Lavação 047.", ctaLabel: "Começar pelo site", poster: { id: "lavacao-047", title: "Lavação 047" }, moreLabel: "Ver case Lavação 047", moreHref: "/cases/lavacao-047", }, sistema: { description: "Pedidos, estoque e rotinas que hoje vivem em planilhas e mensagens passam para um painel próprio, feito para a sua equipe. Um exemplo é a SEV Moda Íntima, com cadastro de peças, pedidos e estoque por tamanho.", ctaLabel: "Começar pelo sistema", moreLabel: "Ver case SEV Moda Íntima", moreHref: "/cases/sev-modaintima", }, whatsapp: { description: "Para quem atende e vende pelo WhatsApp e quer responder na hora sem deixar a IA inventar preço ou prazo.", ctaLabel: "Começar pelo atendimento", moreLabel: "Ver como funciona o atendimento", moreHref: "/servicos/atendimento-whatsapp-ia", }, revisao: { description: "Para quem já tem um sistema, como um app feito no Lovable, no Bolt ou no Replit, e quer saber se ele está pronto para receber clientes.", ctaLabel: "Começar pela revisão", moreLabel: "Ver como funciona a revisão", moreHref: "/ia", }, }; const homeOffers = serviceOffers.flatMap((offer) => offer.id === "fiscal" ? [] : [{ offer, extras: OFFER_EXTRAS[offer.id] }], ); const PROCESS = [ { title: "Entender a operação", description: "Quem usa, qual problema precisa resolver e quais dados e ferramentas já existem.", }, { title: "Definir a entrega", description: "Escopo, arquitetura, riscos, investimento e critérios de aceite antes de desenvolver.", }, { title: "Construir e validar", description: "Entregas por etapa, demonstrações e testes dos fluxos, das permissões e das integrações.", }, { title: "Publicar e dar continuidade", description: "Implantação, documentação e condições de manutenção combinadas para a operação.", }, ]; /** * Três achados do "Modelo do relatório" de /ia (#ia-modelo), em versão curta para caber no cartão: a falha, em poucas * palavras, e a gravidade. Como lá, são exemplos ilustrativos: não são de nenhum cliente nem de um app real. */ const REPORT_EXCERPT = [ { finding: "Dados expostos", severity: "Alta" }, { finding: "Chave exposta", severity: "Alta" }, { finding: "Sem backup", severity: "Média" }, ] as const; /** O mesmo tamanho nos dois selos: a gravidade fica no texto, não só na cor ou no enchimento. */ const SEVERITY_BADGE = "inline-flex min-w-14 shrink-0 items-center justify-center border border-[var(--ink)] px-2 font-display text-[18px] @[29rem]:text-[15px] leading-6"; /** * Recorte do "Modelo do relatório" de /ia junto do vídeo da revisão: três linhas de achado, cada uma com o selo da * gravidade, e a legenda "Exemplo ilustrativo", em 18 px. A peça 3D (a janela e a lupa) ocupa a metade esquerda do * quadro, então numa caixa larga (528 px ou mais) o recorte fica por cima da metade direita, centrado na vertical. Numa * caixa mais estreita (celular, e as duas colunas logo acima de 1024 px) ele não cabe ao lado da janela sem cobri-la: * desce para baixo do quadro, no mesmo fundo escuro. A largura vem da caixa (container query), não da tela. */ /* * Onde o trecho do relatório fica: ao lado da janela quando o quadro tem 29rem ou mais (a janela do vídeo acaba em 51% * da largura); embaixo do vídeo quando o cartão ocupa a linha inteira e é estreito (celular); fora da tela entre 1024 * e 1279 px, em que os cartões já estão lado a lado mas o quadro é estreito demais e empilhar desalinharia os títulos. */ function ReviewArt() { return (
); } /** Classes do quadro da mídia, iguais nos quatro cartões: a foto ou o vídeo ocupam o quadro inteiro. */ const MEDIA_FRAME = "relative aspect-[16/10] md:aspect-[21/9] lg:aspect-[16/10]"; /** Foto do case, quando há um; senão o vídeo da oferta, com o que vai junto dele. O quadro tem o mesmo tamanho em todos. */ function OfferArt({ offer, extras, }: Readonly<{ offer: ServiceOffer; extras: OfferExtras }>) { const poster = extras.poster ? getShowcaseAssets(extras.poster.id, "desktop") : null; if (poster && extras.poster) { return (
{`Site
); } return ( <>
{offer.id === "whatsapp" ? ( // de que aplicativo se trata; decorativo como o vídeo, porque o título do cartão já diz WhatsApp ) : null}
{offer.id === "revisao" ? : null} ); } /** Um único estilo de cartão para as quatro ofertas: foto ou vídeo, título com altura mínima, texto, o que você recebe, botão e link. */ function OfferCard({ offer, extras, }: Readonly<{ offer: ServiceOffer; extras: OfferExtras }>) { return (
{/* min-h de 3 linhas no desktop: os títulos de 2 e 3 linhas terminam na mesma altura e os textos se alinham */}

{offer.name}

{extras.description}

O que você recebe

    {offer.deliverables.map((item) => (
  • {item}
  • ))}
{/* mt-auto: com cartões de alturas diferentes, o botão e o link descem juntos até o pé do cartão */} {extras.ctaLabel} {extras.moreLabel}
); } export function WorkModalities() { const fiscal = serviceOffers.find(({ id }) => id === "fiscal"); return (
{/* a faixa só existe até 31/03/2027: o servidor a deixa de fora depois disso, e FiscalNotice confere a data no navegador */} {fiscal && isFiscalNoticeActive(new Date()) ? ( ) : null}
{homeOffers.map(({ offer, extras }, index) => ( ))}
{/* Uma vez só, depois dos cartões: o primeiro passo é o mesmo para qualquer oferta (uma conversa e, depois dela, escopo e proposta por escrito, sem prazo nem preço); a página de cada oferta diz o que se entende na conversa. */}

Primeiro passo

{generalFirstStep}

Ver todos os serviços {/* Lista compacta: o título e a descrição de cada etapa numa linha só, sem a grade de quatro cartões. */}

Como eu trabalho

Você acompanha as decisões e valida cada etapa. Prazo e investimento dependem do escopo, das integrações e dos riscos identificados.

    {PROCESS.map((step, index) => (
  1. {String(index + 1).padStart(2, "0")}

    {step.title}. {" "} {step.description}

  2. ))}
); }