250 lines
8.5 KiB
TypeScript
250 lines
8.5 KiB
TypeScript
"use client";
|
|
|
|
import Link from "next/link";
|
|
import { motion, type Variants, useReducedMotion } from "framer-motion";
|
|
import { serviceHubLinks } from "@/lib/site-content";
|
|
import { Section } from "./Section";
|
|
import { DrawLine } from "./animations/DrawLine";
|
|
import MagneticButton from "./cinematic/MagneticButton";
|
|
|
|
interface Tier {
|
|
id: string;
|
|
badge: string;
|
|
level: string;
|
|
title: string;
|
|
tagline: string;
|
|
description: string;
|
|
deliverables: string[];
|
|
pricing: string;
|
|
pricingNote: string;
|
|
featured?: boolean;
|
|
ctaLabel: string;
|
|
ctaHref: string;
|
|
}
|
|
|
|
const TIERS: Tier[] = [
|
|
{
|
|
id: "discovery",
|
|
badge: "Entrada / Baixo Risco",
|
|
level: "01",
|
|
title: "Auditoria & Diagnostico Tecnico",
|
|
tagline: "Fotografia clara do problema antes de qualquer comprometimento.",
|
|
description:
|
|
"Analise profunda de arquitetura, performance ou seguranca com entrega de um plano de acao executavel. Ideal para quem precisa de direcao antes de contratar execucao.",
|
|
deliverables: [
|
|
"Relatorio de gargalos e divida tecnica",
|
|
"Mapeamento de riscos e dependencias",
|
|
"Sugestao de stack e cronograma de mitigacao",
|
|
"Plano de acao priorizado",
|
|
],
|
|
pricing: "Valor Fixo",
|
|
pricingNote: "Contrato unico. Entrega em ate 5 dias uteis.",
|
|
featured: false,
|
|
ctaLabel: "Solicitar diagnostico",
|
|
ctaHref: "#contact",
|
|
},
|
|
{
|
|
id: "cycles",
|
|
badge: "Mais Escolhido",
|
|
level: "02",
|
|
title: "Ciclos de Engenharia",
|
|
tagline: "Capacidade produtiva garantida. Entrega a cada 2 semanas.",
|
|
description:
|
|
"Desenvolvimento continuo com a previsibilidade de orcamento do escopo fechado e a agilidade de sprints. Milestones claros, sem amarras de contrato longo.",
|
|
deliverables: [
|
|
"Features em producao a cada ciclo",
|
|
"Refatoracao iterativa com rastreabilidade",
|
|
"Documentacao tecnica atualizada",
|
|
"Capacidade de pivotar prioridades no inicio de cada sprint",
|
|
],
|
|
pricing: "Fixo por Ciclo",
|
|
pricingNote: "Assinatura quinzenal ou mensal. Cancele a qualquer ciclo.",
|
|
featured: true,
|
|
ctaLabel: "Iniciar ciclo de engenharia",
|
|
ctaHref: "#contact",
|
|
},
|
|
{
|
|
id: "fractional",
|
|
badge: "Premium / High-Ticket",
|
|
level: "03",
|
|
title: "Fractional Tech Lead",
|
|
tagline: "Lideranca tecnica senior. Sem o custo de um CTO full-time.",
|
|
description:
|
|
"Direcao arquitetural, gestao de risco e sustentacao de operacoes criticas. Para empresas que precisam de decisoes de alto impacto com responsabilidade continua.",
|
|
deliverables: [
|
|
"SLA prioritario Zero-Risk",
|
|
"Code review e lideranca do time interno",
|
|
"Decisoes de infra: Cloud, VPS, CI/CD",
|
|
"Consultoria estrategica recorrente",
|
|
],
|
|
pricing: "Retainer Mensal",
|
|
pricingNote: "Renovacao mensal. Vagas limitadas.",
|
|
featured: false,
|
|
ctaLabel: "Agendar conversa estrategica",
|
|
ctaHref: "#contact",
|
|
},
|
|
];
|
|
|
|
function TierCard({ tier }: Readonly<{ tier: Tier }>) {
|
|
const shouldReduceMotion = useReducedMotion();
|
|
|
|
return (
|
|
<motion.article
|
|
className={`ds-card relative flex h-full min-w-0 flex-col overflow-hidden outline-none max-md:w-full max-md:max-w-none max-md:px-sp-5 max-md:py-sp-5 ${
|
|
tier.featured ? "border-[var(--slash)] shadow-sm" : ""
|
|
}`}
|
|
style={{
|
|
borderWidth: tier.featured ? "2px" : "1px",
|
|
}}
|
|
whileHover={
|
|
shouldReduceMotion
|
|
? undefined
|
|
: {
|
|
y: -4,
|
|
boxShadow: "0 24px 50px rgba(0, 0, 0, 0.08)",
|
|
}
|
|
}
|
|
whileTap={shouldReduceMotion ? undefined : { scale: 0.99 }}
|
|
transition={{ type: "spring", stiffness: 180, damping: 18 }}
|
|
>
|
|
<div className="flex min-w-0 items-start justify-between gap-sp-4">
|
|
<span className="ds-kicker max-md:text-[10px] max-md:leading-[1.6]">
|
|
{tier.badge}
|
|
</span>
|
|
<span className="text-[11px] tracking-[0.08em] text-[var(--meta)]">
|
|
{tier.level}
|
|
</span>
|
|
</div>
|
|
|
|
<DrawLine delay={0.04} />
|
|
|
|
<div className="mt-sp-4 min-w-0">
|
|
<h3 className="ds-card-title !mt-0 text-balance !text-[clamp(22px,5vw,28px)] !leading-[1.02] !tracking-[-0.035em] [overflow-wrap:break-word] [word-break:normal]">
|
|
{tier.title}
|
|
</h3>
|
|
<p className="mt-sp-2 text-[12px] leading-[1.7] text-[var(--meta)] md:text-[11px]">
|
|
{tier.tagline}
|
|
</p>
|
|
</div>
|
|
|
|
<p className="ds-copy !mt-sp-4 !text-[13px] !leading-[1.75] [overflow-wrap:break-word] [word-break:normal] md:!text-[12px]">
|
|
{tier.description}
|
|
</p>
|
|
|
|
<ul className="ds-list !mt-sp-5 !pl-[1.15rem] !text-[13px] !leading-[1.75] [overflow-wrap:break-word] [word-break:normal] md:!text-[12px]">
|
|
{tier.deliverables.map((deliverable) => (
|
|
<li key={deliverable} className="pl-sp-1">
|
|
{deliverable}
|
|
</li>
|
|
))}
|
|
</ul>
|
|
|
|
<div className="mt-sp-6 space-y-sp-2 border-t border-[var(--border)] pt-sp-5">
|
|
<div className="font-display text-[clamp(17px,4.6vw,18px)] font-extrabold leading-none tracking-tight">
|
|
{tier.pricing}
|
|
</div>
|
|
<div className="text-[12px] leading-[1.7] text-[var(--meta)]">
|
|
{tier.pricingNote}
|
|
</div>
|
|
</div>
|
|
|
|
<MagneticButton
|
|
as="a"
|
|
href={tier.ctaHref}
|
|
className={`ds-link mt-sp-6 min-h-[50px] w-full justify-center px-sp-4 py-sp-3 text-center text-[11px] leading-none ${
|
|
tier.featured ? "ds-link-accent" : "ds-link-muted"
|
|
}`}
|
|
strength={0.25}
|
|
>
|
|
{tier.ctaLabel}
|
|
</MagneticButton>
|
|
</motion.article>
|
|
);
|
|
}
|
|
|
|
export function WorkModalities() {
|
|
const shouldReduceMotion = useReducedMotion();
|
|
|
|
const containerVariants: Variants = {
|
|
hidden: {},
|
|
visible: {
|
|
transition: {
|
|
delayChildren: 0.08,
|
|
staggerChildren: 0.08,
|
|
},
|
|
},
|
|
};
|
|
|
|
const itemVariants: Variants = {
|
|
hidden: shouldReduceMotion
|
|
? { opacity: 0 }
|
|
: { opacity: 0, y: 20, clipPath: "inset(100% 0 0 0)" },
|
|
visible: {
|
|
opacity: 1,
|
|
y: 0,
|
|
clipPath: "inset(0% 0 0 0)",
|
|
transition: shouldReduceMotion
|
|
? { duration: 0.25 }
|
|
: { duration: 0.75, ease: [0.16, 1, 0.3, 1] },
|
|
},
|
|
};
|
|
|
|
return (
|
|
<Section
|
|
id="modalities"
|
|
eyebrow="Working models"
|
|
title="Servicos de engenharia de software e consultoria tecnica."
|
|
description="Formatos de contratacao para arquitetura de software, integracoes criticas, produtos conectados e evolucao de sistemas em producao."
|
|
disableChildrenAnimation
|
|
>
|
|
<div className="mb-sp-8 ds-card bg-[rgba(10,10,10,0.02)]">
|
|
<div className="flex flex-col gap-sp-4 lg:flex-row lg:items-end lg:justify-between">
|
|
<div className="max-w-[760px]">
|
|
<div className="ds-kicker">Paginas de servico</div>
|
|
<h3 className="ds-card-title !mt-sp-3">Especialidades organizadas por intencao de busca</h3>
|
|
<p className="ds-copy !mt-sp-3 max-w-[62ch]">
|
|
Se voce chegou buscando uma stack, um tipo de consultoria ou um contexto tecnico especifico,
|
|
aqui esta o caminho mais direto para a pagina certa.
|
|
</p>
|
|
</div>
|
|
<MagneticButton as="a" href="/servicos" className="ds-link ds-link-accent" strength={0.2}>
|
|
Ver hub de servicos
|
|
</MagneticButton>
|
|
</div>
|
|
|
|
<div className="mt-sp-6 grid gap-sp-3 md:grid-cols-2 xl:grid-cols-3">
|
|
{serviceHubLinks.map((service) => (
|
|
<Link
|
|
key={service.href}
|
|
href={service.href}
|
|
className="rounded-[8px] border border-[var(--border)] bg-white/70 px-sp-4 py-sp-4 transition-colors duration-200 hover:border-[var(--slash)] hover:bg-white"
|
|
>
|
|
<div className="text-[12px] font-semibold tracking-[0.02em] text-[var(--ink)]">
|
|
{service.label}
|
|
</div>
|
|
<div className="mt-sp-2 text-[12px] leading-6 text-[var(--meta)]">
|
|
{service.description}
|
|
</div>
|
|
</Link>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
<motion.div
|
|
className="grid grid-cols-1 gap-sp-4 md:grid-cols-2 md:gap-sp-5 lg:grid-cols-3 lg:gap-sp-6"
|
|
initial="hidden"
|
|
whileInView="visible"
|
|
viewport={{ once: true, amount: 0.2 }}
|
|
variants={containerVariants}
|
|
>
|
|
{TIERS.map((tier) => (
|
|
<motion.div key={tier.id} variants={itemVariants} className="min-w-0">
|
|
<TierCard tier={tier} />
|
|
</motion.div>
|
|
))}
|
|
</motion.div>
|
|
</Section>
|
|
);
|
|
}
|
|
|