- Introduced DrawLine component for drawing animations. - Added LazyRevealImage component for lazy loading images with reveal animations. - Implemented TextDiffuseReveal for animated text reveals with staggered effects. - Created TopProgressBar for a dynamic loading indicator. - Added PointCloud mock for testing animations. - Developed useReducedMotion hook to handle user preferences for reduced motion. - Centralized animation configurations in config.ts for easier management. - Defined animation variants in variants.ts for consistent animation effects. - Established AnimationProvider to supply global animation settings. - Created tests for AnimationProvider and useReducedMotion hook. - Added SVG assets for branding and UI elements. - Documented frontend review plan and hero circuit board animation plan.
213 lines
6.5 KiB
TypeScript
213 lines
6.5 KiB
TypeScript
"use client";
|
|
|
|
import { motion, type Variants, useReducedMotion } from "framer-motion";
|
|
import { Section } from "./Section";
|
|
import { DrawLine } from "./animations/DrawLine";
|
|
|
|
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
|
|
tabIndex={0}
|
|
className={`ds-card h-full relative outline-none ${
|
|
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 justify-between items-start">
|
|
<span className="ds-kicker">{tier.badge}</span>
|
|
<span className="font-display text-[11px] font-extrabold tracking-widest text-[var(--meta)]">
|
|
{tier.level}
|
|
</span>
|
|
</div>
|
|
|
|
<DrawLine delay={0.04} />
|
|
|
|
<div className="mt-sp-4">
|
|
<h3 className="ds-card-title">{tier.title}</h3>
|
|
<p className="mt-sp-2 text-[11px] font-medium leading-relaxed text-[var(--meta)]">
|
|
{tier.tagline}
|
|
</p>
|
|
</div>
|
|
|
|
<p className="ds-copy">{tier.description}</p>
|
|
|
|
<ul className="ds-list">
|
|
{tier.deliverables.map((deliverable) => (
|
|
<li key={deliverable}>{deliverable}</li>
|
|
))}
|
|
</ul>
|
|
|
|
<div className="mt-sp-6 border-t border-[var(--border)] pt-sp-4">
|
|
<div className="font-display text-[clamp(14px,1.5vw,18px)] font-extrabold tracking-tight">
|
|
{tier.pricing}
|
|
</div>
|
|
<div className="mt-1 text-[10px] tracking-widest text-[var(--meta)] uppercase">
|
|
{tier.pricingNote}
|
|
</div>
|
|
</div>
|
|
|
|
<motion.a
|
|
href={tier.ctaHref}
|
|
className={`ds-link mt-sp-6 justify-center w-full ${
|
|
tier.featured ? "ds-link-accent" : "ds-link-muted"
|
|
}`}
|
|
whileHover={shouldReduceMotion ? undefined : { scale: 1.02 }}
|
|
whileTap={shouldReduceMotion ? undefined : { scale: 0.98 }}
|
|
transition={{ type: "spring", stiffness: 260, damping: 20 }}
|
|
>
|
|
{tier.ctaLabel}
|
|
{" ->"}
|
|
</motion.a>
|
|
</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="CONTRACT_PROTOCOLS.sys"
|
|
title="Engenharia sob demanda. Previsibilidade de entrega sem overhead."
|
|
description="Tres niveis de contratacao desenhados como uma esteira de valor, do diagnostico rapido a parceria estrategica de longo prazo."
|
|
disableChildrenAnimation
|
|
>
|
|
<motion.div
|
|
style={{
|
|
display: "grid",
|
|
gridTemplateColumns: "repeat(3, minmax(0, 1fr))",
|
|
gap: "var(--sp-6)",
|
|
}}
|
|
className="max-md:grid-cols-1 max-md:!flex max-md:!flex-col"
|
|
initial="hidden"
|
|
whileInView="visible"
|
|
viewport={{ once: true, amount: 0.2 }}
|
|
variants={containerVariants}
|
|
>
|
|
{TIERS.map((tier) => (
|
|
<motion.div key={tier.id} variants={itemVariants}>
|
|
<TierCard tier={tier} />
|
|
</motion.div>
|
|
))}
|
|
</motion.div>
|
|
</Section>
|
|
);
|
|
}
|