feat: reformula landing page e experiência mobile

This commit is contained in:
Felipe Coutinho
2026-03-20 18:35:12 +00:00
parent 33a5d6f5f0
commit 5b8d25d894
41 changed files with 692 additions and 453 deletions

View File

@@ -1,252 +1,38 @@
import {
RiBankCard2Line,
RiBarChartBoxLine,
RiCalendarLine,
RiCheckLine,
RiCodeSSlashLine,
RiDatabase2Line,
RiDeviceLine,
RiDownloadCloudLine,
RiEyeOffLine,
RiFileTextLine,
RiFlashlightLine,
RiGitBranchLine,
RiAndroidLine,
RiGithubFill,
RiInformationLine,
RiLayoutGridLine,
RiLineChartLine,
RiLockLine,
RiNotification3Line,
RiPercentLine,
RiPieChartLine,
RiRobot2Line,
RiShieldCheckLine,
RiSmartphoneLine,
RiStarLine,
RiTeamLine,
RiTimeLine,
RiWalletLine,
} from "@remixicon/react";
import { headers } from "next/headers";
import Image from "next/image";
import Link from "next/link";
import type { ComponentType } from "react";
import { AnimateOnScroll } from "@/features/landing/components/animate-on-scroll";
import { MobileNav } from "@/features/landing/components/mobile-nav";
import { ScreenshotTabs } from "@/features/landing/components/screenshot-tabs";
import { SetupTabs } from "@/features/landing/components/setup-tabs";
import {
companionBanks,
companionSteps,
extraFeatures,
getMetricsItems,
mainFeatures,
navbarActionClassName,
navLinks,
pwaHighlights,
stackItems,
whoIsItForItems,
} from "@/features/landing/constants";
import { landingImages } from "@/features/landing/images";
import { fetchGitHubStats } from "@/features/landing/queries";
import { AnimatedThemeToggler } from "@/shared/components/animated-theme-toggler";
import { Logo } from "@/shared/components/logo";
import {
Alert,
AlertDescription,
AlertTitle,
} from "@/shared/components/ui/alert";
import { Badge } from "@/shared/components/ui/badge";
import { Button } from "@/shared/components/ui/button";
import { Card, CardContent } from "@/shared/components/ui/card";
import { DotPattern } from "@/shared/components/ui/dot-pattern";
import { getOptionalUserSession } from "@/shared/lib/auth/server";
async function fetchGitHubStats() {
try {
const res = await fetch(
"https://api.github.com/repos/felipegcoutinho/openmonetis",
{ next: { revalidate: 3600 } },
);
if (!res.ok) return { stars: 200, forks: 60 };
const data = await res.json();
return {
stars: data.stargazers_count as number,
forks: data.forks_count as number,
};
} catch {
return { stars: 200, forks: 60 };
}
}
const navbarActionClassName =
"border-black/10 bg-transparent text-black/75 shadow-none hover:border-black/20 hover:bg-black/10 hover:text-black focus-visible:ring-black/20 data-[state=open]:bg-black/10 data-[state=open]:text-black";
type FeatureItem = {
icon: ComponentType<{ className?: string; style?: React.CSSProperties }>;
title: string;
description: string;
colorVar: string;
};
const mainFeatures: FeatureItem[] = [
{
icon: RiWalletLine,
title: "Contas e transações",
description:
"Registre suas contas bancárias, cartões e dinheiro. Adicione receitas, despesas e transferências. Organize por categorias. Extratos detalhados por conta.",
colorVar: "var(--data-9)",
},
{
icon: RiPercentLine,
title: "Parcelamentos avançados",
description:
"Controle completo de compras parceladas. Antecipe parcelas com cálculo automático de desconto. Veja análise consolidada de todas as parcelas em aberto.",
colorVar: "var(--data-4)",
},
{
icon: RiRobot2Line,
title: "Insights com IA",
description:
"Análises financeiras geradas por IA (Claude, GPT, Gemini). Insights personalizados sobre seus padrões de gastos e recomendações inteligentes.",
colorVar: "var(--data-8)",
},
{
icon: RiBarChartBoxLine,
title: "Relatórios e gráficos",
description:
"Dashboard com 20+ widgets interativos. Relatórios detalhados por categoria. Gráficos de evolução e comparativos. Exportação em PDF e Excel.",
colorVar: "var(--data-5)",
},
{
icon: RiBankCard2Line,
title: "Faturas de cartão",
description:
"Cadastre seus cartões e acompanhe as faturas por período. Veja o que ainda não foi fechado. Controle limites, vencimentos e fechamentos.",
colorVar: "var(--data-1)",
},
{
icon: RiTeamLine,
title: "Gestão colaborativa",
description:
"Compartilhe pagadores com permissões granulares (admin/viewer). Notificações automáticas por e-mail. Colabore em lançamentos compartilhados.",
colorVar: "var(--data-3)",
},
];
const extraFeatures: FeatureItem[] = [
{
icon: RiPieChartLine,
title: "Categorias e orçamentos",
description:
"Crie categorias personalizadas e defina orçamentos mensais com indicadores visuais.",
colorVar: "var(--data-7)",
},
{
icon: RiFileTextLine,
title: "Anotações e tarefas",
description:
"Notas de texto e listas de tarefas com checkboxes. Arquivamento para manter histórico.",
colorVar: "var(--data-6)",
},
{
icon: RiCalendarLine,
title: "Calendário financeiro",
description:
"Visualize transações em calendário mensal. Nunca perca prazos de pagamentos.",
colorVar: "var(--data-2)",
},
{
icon: RiDownloadCloudLine,
title: "Importação em massa",
description: "Lance múltiplos lançamentos de uma vez",
colorVar: "var(--data-9)",
},
{
icon: RiEyeOffLine,
title: "Modo privacidade",
description:
"Oculte valores sensíveis com um clique. Tema dark/light. Calculadora integrada.",
colorVar: "var(--data-4)",
},
{
icon: RiFlashlightLine,
title: "Performance otimizada",
description: "Sistema rápido e com alta performance",
colorVar: "var(--data-5)",
},
];
const screenshotSections = [
{
title: "Lançamentos",
description: "Registre e organize todas as suas transações financeiras",
lightSrc: "/images/preview-lancamentos-light.webp",
darkSrc: "/images/preview-lancamentos-dark.webp",
},
{
title: "Calendário",
description: "Visualize suas finanças no calendário mensal",
lightSrc: "/images/preview-calendario-light.webp",
darkSrc: "/images/preview-calendario-dark.webp",
},
{
title: "Cartões",
description: "Acompanhe faturas, limites e vencimentos dos seus cartões",
lightSrc: "/images/preview-cartao-light.webp",
darkSrc: "/images/preview-cartao-dark.webp",
},
];
const companionBanks = [
{ name: "Nubank", logo: "/logos/nubank.png" },
{ name: "Itaú", logo: "/logos/itau.png" },
{ name: "Inter", logo: "/logos/interpj.png" },
{ name: "Mercado Pago", logo: "/logos/mercadopago.png" },
{ name: "Outros", logo: null },
];
const stackItems = [
{
icon: RiCodeSSlashLine,
title: "Frontend",
subtitle: "Next.js 16, TypeScript, Tailwind CSS, shadcn/ui",
description: "Interface moderna e responsiva com React 19 e App Router",
colorVar: "var(--data-3)",
},
{
icon: RiDatabase2Line,
title: "Backend",
subtitle: "PostgreSQL 18, Drizzle ORM, Better Auth",
description: "Banco relacional robusto com type-safe ORM",
colorVar: "var(--data-9)",
},
{
icon: RiShieldCheckLine,
title: "Segurança",
subtitle: "Better Auth com OAuth (Google) e autenticação por email",
description: "Sessões seguras e proteção de rotas por middleware",
colorVar: "var(--data-1)",
},
{
icon: RiDeviceLine,
title: "Deploy",
subtitle:
"Docker com multi-stage build, health checks e volumes persistentes",
description: "Fácil de rodar localmente ou em qualquer servidor",
colorVar: "var(--data-5)",
},
];
const whoIsItForItems = [
{
icon: RiTimeLine,
title: "Tem disciplina de registrar gastos",
description:
"Não se importa em dedicar alguns minutos por dia ou semana para manter tudo atualizado",
colorVar: "var(--data-4)",
},
{
icon: RiLockLine,
title: "Quer controle total sobre seus dados",
description:
"Prefere hospedar seus próprios dados ao invés de depender de serviços terceiros",
colorVar: "var(--data-9)",
},
{
icon: RiLineChartLine,
title: "Gosta de entender exatamente onde o dinheiro vai",
description:
"Quer visualizar padrões de gastos e tomar decisões informadas",
colorVar: "var(--data-3)",
},
];
export default async function Page() {
const [session, headersList, githubStats] = await Promise.all([
getOptionalUserSession(),
@@ -259,6 +45,7 @@ export default async function Page() {
"",
).replace(/:\d+$/, "");
const isPublicDomain = !!(publicDomain && hostname === publicDomain);
const metricsItems = getMetricsItems(githubStats.stars, githubStats.forks);
return (
<div className="flex min-h-screen flex-col">
@@ -273,13 +60,7 @@ export default async function Page() {
{/* Center Navigation Links */}
<nav className="hidden md:flex items-center gap-1 absolute left-1/2 -translate-x-1/2">
{[
{ href: "#telas", label: "conheça as telas" },
{ href: "#funcionalidades", label: "funcionalidades" },
{ href: "#companion", label: "companion" },
{ href: "#stack", label: "stack" },
{ href: "#como-usar", label: "como usar" },
].map(({ href, label }) => (
{navLinks.map(({ href, label }) => (
<a
key={href}
href={href}
@@ -333,9 +114,8 @@ export default async function Page() {
</div>
</header>
{/* Hero Section — texto + preview integrado */}
{/* Hero Section */}
<section className="relative overflow-hidden pt-14 md:pt-20 lg:pt-24 pb-0">
{/* Background — DotPattern fade conectando com navbar */}
<div className="pointer-events-none absolute inset-x-0 top-0 h-80 overflow-hidden">
<DotPattern
width={20}
@@ -349,7 +129,6 @@ export default async function Page() {
</div>
<div className="max-w-8xl mx-auto px-4 relative">
{/* Texto */}
<div className="mx-auto flex max-w-3xl flex-col items-center text-center gap-5 md:gap-6 pb-10 md:pb-14">
<Badge variant="outline">
<RiGithubFill className="size-4 mr-1" />
@@ -397,7 +176,6 @@ export default async function Page() {
</div>
</div>
{/* Dashboard preview integrado ao hero */}
<div className="mx-auto max-w-6xl">
<div className="rounded-t-xl overflow-hidden border-x border-t bg-card">
<div className="flex items-center gap-1.5 px-3 h-8 border-b bg-muted/50">
@@ -407,7 +185,7 @@ export default async function Page() {
<div className="ml-2 flex-1 max-w-52 h-4 rounded bg-muted-foreground/10" />
</div>
<Image
src="/images/dashboard-preview-light.webp"
src={landingImages.hero.light}
alt="openmonetis Dashboard Preview"
width={1920}
height={1080}
@@ -415,7 +193,7 @@ export default async function Page() {
priority
/>
<Image
src="/images/dashboard-preview-dark.webp"
src={landingImages.hero.dark}
alt="openmonetis Dashboard Preview"
width={1920}
height={1080}
@@ -432,32 +210,7 @@ export default async function Page() {
<div className="max-w-8xl mx-auto px-4">
<div className="mx-auto max-w-4xl">
<div className="grid grid-cols-2 gap-4 md:grid-cols-4 md:gap-8">
{[
{
icon: RiLayoutGridLine,
value: "20+",
label: "Widgets no dashboard",
colorVar: "var(--data-9)",
},
{
icon: RiShieldCheckLine,
value: "100%",
label: "Self-hosted",
colorVar: "var(--data-1)",
},
{
icon: RiStarLine,
value: `${githubStats.stars}`,
label: "Stars no GitHub",
colorVar: "var(--data-4)",
},
{
icon: RiGitBranchLine,
value: `${githubStats.forks}`,
label: "Forks no GitHub",
colorVar: "var(--data-3)",
},
].map(({ icon: Icon, value, label, colorVar }) => (
{metricsItems.map(({ icon: Icon, value, label, colorVar }) => (
<div
key={label}
className="flex flex-col items-center text-center gap-1.5"
@@ -494,50 +247,17 @@ export default async function Page() {
</div>
</AnimateOnScroll>
<div className="space-y-10 md:space-y-14">
{screenshotSections.map((section) => (
<AnimateOnScroll key={section.title}>
<div className="mb-3 text-center">
<h3 className="font-semibold text-base md:text-lg">
{section.title}
</h3>
<p className="text-sm text-muted-foreground">
{section.description}
</p>
</div>
<div className="rounded-lg overflow-hidden border bg-card">
<div className="flex items-center gap-1.5 px-3 h-8 border-b bg-muted/50">
<div className="size-2.5 rounded-full bg-muted-foreground/20" />
<div className="size-2.5 rounded-full bg-muted-foreground/20" />
<div className="size-2.5 rounded-full bg-muted-foreground/20" />
<div className="ml-2 flex-1 max-w-52 h-4 rounded bg-muted-foreground/10" />
</div>
<Image
src={section.lightSrc}
alt={`Preview ${section.title}`}
width={1920}
height={1080}
className="w-full h-auto dark:hidden"
/>
<Image
src={section.darkSrc}
alt={`Preview ${section.title}`}
width={1920}
height={1080}
className="w-full h-auto hidden dark:block"
/>
</div>
</AnimateOnScroll>
))}
</div>
<AnimateOnScroll>
<ScreenshotTabs />
</AnimateOnScroll>
</div>
</div>
</section>
{/* Features Section */}
<section id="funcionalidades" className="py-12 md:py-24">
<section id="funcionalidades" className="py-12 md:py-24 bg-muted/40">
<div className="max-w-8xl mx-auto px-4">
<div className="mx-auto max-w-5xl">
<div className="mx-auto max-w-6xl">
<AnimateOnScroll>
<div className="text-center mb-8 md:mb-12">
<Badge variant="outline" className="mb-4">
@@ -553,7 +273,6 @@ export default async function Page() {
</div>
</AnimateOnScroll>
{/* Main Features - larger cards */}
<AnimateOnScroll>
<div className="grid gap-4 md:gap-6 sm:grid-cols-2 lg:grid-cols-3">
{mainFeatures.map((feature) => (
@@ -586,11 +305,10 @@ export default async function Page() {
</div>
</AnimateOnScroll>
{/* Extra Features - compact list */}
<AnimateOnScroll>
<div className="mt-8 md:mt-12">
<h3 className="text-lg font-semibold text-center mb-4 md:mb-6 text-muted-foreground">
E mais...
<h3 className="text-sm font-medium text-center mb-4 md:mb-6 text-muted-foreground">
Também inclui
</h3>
<div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
{extraFeatures.map((feature) => (
@@ -626,85 +344,141 @@ export default async function Page() {
</div>
</section>
{/* Companion Section */}
<section id="companion" className="py-12 md:py-24">
{/* Mobile Section */}
<section id="mobile" className="py-12 md:py-24">
<div className="max-w-8xl mx-auto px-4">
<div className="mx-auto max-w-5xl">
<div className="mx-auto max-w-6xl">
{/* Header */}
<AnimateOnScroll>
<div className="grid gap-8 md:gap-12 md:grid-cols-2 items-center">
{/* Text content */}
<div className="order-2 md:order-1">
<div className="text-center mb-12 md:mb-20">
<Badge variant="outline" className="mb-4">
<RiSmartphoneLine className="size-3.5 mr-1" />
Mobile
</Badge>
<h2 className="text-2xl sm:text-3xl md:text-4xl font-bold tracking-tight mb-3 md:mb-4">
Use o OpenMonetis no celular sem perder o fluxo
</h2>
<p className="text-base md:text-lg text-muted-foreground max-w-2xl mx-auto px-4 sm:px-0">
Instale como PWA para acesso rápido no dia a dia. No Android,
use o Companion para capturar notificações bancárias
automaticamente.
</p>
</div>
</AnimateOnScroll>
{/* PWA — imagem esquerda, texto direita */}
<AnimateOnScroll>
<div className="grid gap-10 lg:gap-16 lg:grid-cols-2 items-center mb-16 md:mb-24">
<div className="flex justify-center">
<div className="relative">
<div className="absolute inset-0 bg-primary/8 rounded-3xl blur-3xl scale-90" />
<Image
src={landingImages.pwa.light}
alt="Preview PWA"
width={390}
height={844}
className="relative h-auto w-56 md:w-64 rounded-3xl shadow-lg dark:hidden"
/>
<Image
src={landingImages.pwa.dark}
alt="Preview PWA"
width={390}
height={844}
className="relative h-auto w-56 md:w-64 rounded-3xl shadow-lg hidden dark:block"
/>
</div>
</div>
<div>
<Badge variant="outline" className="mb-4">
<RiSmartphoneLine className="size-3.5 mr-1" />
App Android
PWA instalável
</Badge>
<h2 className="text-2xl sm:text-3xl md:text-4xl font-bold tracking-tight mb-3 md:mb-4">
Capture automaticamente do seu celular
</h2>
<p className="text-base md:text-lg text-muted-foreground mb-6">
O OpenMonetis Companion captura notificações de apps
bancários e cria pré-lançamentos automaticamente para você
revisar.
<h3 className="text-2xl md:text-3xl font-bold tracking-tight mb-3">
Leve o OpenMonetis para a tela inicial
</h3>
<p className="text-muted-foreground mb-6 leading-relaxed">
Adicione à tela inicial e abra direto, como um app. Sem
depender de uma aba perdida no navegador. Funciona em
Android, iOS e desktop.
</p>
{/* Flow steps */}
<div className="space-y-3 mb-6">
{[
{
icon: RiNotification3Line,
title: "Notificação bancária chega",
subtitle: "O Companion intercepta automaticamente",
colorVar: "var(--data-1)",
},
{
icon: RiSmartphoneLine,
title: "Dados extraídos e enviados",
subtitle: "Valor, descrição e banco são identificados",
colorVar: "var(--data-4)",
},
{
icon: RiCheckLine,
title: "Revise e confirme no OpenMonetis",
subtitle:
"Pré-lançamentos ficam na inbox para sua aprovação",
colorVar: "var(--data-9)",
},
].map((step) => (
<div key={step.title} className="flex items-start gap-3">
<ul className="space-y-3">
{pwaHighlights.map((item) => (
<li key={item.title} className="flex items-start gap-3">
<div
className="flex h-8 w-8 shrink-0 items-center justify-center rounded-full"
className="mt-0.5 flex h-7 w-7 shrink-0 items-center justify-center rounded-md"
style={{
backgroundColor: `color-mix(in oklch, ${step.colorVar} 14%, transparent)`,
backgroundColor: `color-mix(in oklch, ${item.colorVar} 14%, transparent)`,
}}
>
<step.icon
className="size-4"
style={{ color: step.colorVar }}
<item.icon
className="size-[15px]"
style={{ color: item.colorVar }}
/>
</div>
<div>
<p className="text-sm font-medium">{step.title}</p>
<p className="text-xs text-muted-foreground">
{step.subtitle}
</p>
</div>
</div>
<p className="text-sm">
<span className="font-medium">{item.title}</span>
<span className="text-muted-foreground">
{" "}
{item.description}
</span>
</p>
</li>
))}
</div>
</ul>
</div>
</div>
</AnimateOnScroll>
{/* Supported banks */}
<div className="mb-6">
<p className="text-xs font-medium text-muted-foreground mb-2 uppercase tracking-wider">
Bancos suportados
{/* Companion — texto esquerda, imagem direita */}
<AnimateOnScroll>
<div className="grid gap-10 lg:gap-16 lg:grid-cols-2 items-center border-t pt-16 md:pt-24">
<div>
<div className="mb-4">
<Badge variant="outline">
<RiAndroidLine className="size-3.5 mr-1" />
Companion Android
</Badge>
</div>
<h3 className="text-2xl md:text-3xl font-bold tracking-tight mb-3">
Capture, envie e revise no mesmo fluxo
</h3>
<p className="text-muted-foreground mb-6 leading-relaxed">
O Companion captura notificações de apps bancários e cria
pré-lançamentos automaticamente para você revisar na inbox.
</p>
<ol className="space-y-3 mb-6">
{companionSteps.map((step, index) => (
<li key={step.title} className="flex items-start gap-3">
<span
className="mt-0.5 flex h-7 w-7 shrink-0 items-center justify-center rounded-full text-xs font-bold"
style={{
backgroundColor: `color-mix(in oklch, ${step.colorVar} 14%, transparent)`,
color: step.colorVar,
}}
>
{index + 1}
</span>
<p className="text-sm">
<span className="font-medium">{step.title}</span>
<span className="text-muted-foreground">
{" "}
{step.description}
</span>
</p>
</li>
))}
</ol>
<div>
<p className="text-xs font-medium text-muted-foreground uppercase tracking-wider mb-2">
Bancos testados
</p>
<div className="flex flex-wrap gap-2">
{companionBanks.map((bank) => (
<span
key={bank.name}
className="inline-flex items-center gap-1.5 rounded-full border bg-muted/50 py-1 text-xs font-medium"
className="inline-flex items-center gap-1.5 rounded-full border py-1 pr-3 text-xs font-medium"
style={{
paddingLeft: bank.logo ? "4px" : "12px",
paddingRight: "12px",
}}
>
{bank.logo && (
@@ -720,28 +494,32 @@ export default async function Page() {
</span>
))}
</div>
</div>
<Link
href="https://github.com/felipegcoutinho/openmonetis-companion"
target="_blank"
>
<Button variant="outline" className="gap-2">
<RiGithubFill className="size-4" />
<Link
href="https://github.com/felipegcoutinho/openmonetis-companion"
target="_blank"
className="mt-4 inline-flex items-center gap-1.5 text-xs font-medium text-muted-foreground hover:text-foreground transition-colors"
>
<RiGithubFill className="size-3.5" />
Ver no GitHub
</Button>
</Link>
</Link>
</div>
</div>
{/* Companion Screenshot */}
<div className="order-1 md:order-2 flex items-center justify-center">
<div className="w-full max-w-[220px] md:max-w-[260px]">
<div className="flex justify-center order-first lg:order-last">
<div className="relative">
<div className="absolute inset-0 bg-primary/8 rounded-3xl blur-3xl scale-90" />
<Image
src="/images/openmonetis_companion.webp"
alt="OpenMonetis Companion App"
width={1080}
height={2217}
className="w-full h-auto rounded-2xl"
src={landingImages.companion.light}
alt="Preview Companion"
width={390}
height={844}
className="relative h-auto w-56 md:w-64 rounded-3xl shadow-lg dark:hidden"
/>
<Image
src={landingImages.companion.dark}
alt="Preview Companion"
width={390}
height={844}
className="relative h-auto w-56 md:w-64 rounded-3xl shadow-lg hidden dark:block"
/>
</div>
</div>
@@ -752,19 +530,19 @@ export default async function Page() {
</section>
{/* Tech Stack Section */}
<section id="stack" className="py-12 md:py-24">
<section id="stack" className="py-12 md:py-24 bg-muted/40">
<div className="max-w-8xl mx-auto px-4">
<div className="mx-auto max-w-5xl">
<div className="mx-auto max-w-6xl">
<AnimateOnScroll>
<div className="text-center mb-8 md:mb-12">
<Badge variant="outline" className="mb-4">
Stack técnica
</Badge>
<h2 className="text-2xl sm:text-3xl md:text-4xl font-bold tracking-tight mb-3 md:mb-4">
Construído com tecnologias modernas
O que roda por baixo
</h2>
<p className="text-base md:text-lg text-muted-foreground max-w-2xl mx-auto px-4 sm:px-0">
Open source, self-hosted e fácil de customizar
Self-hosted, open source, type-safe do banco ao frontend
</p>
</div>
</AnimateOnScroll>
@@ -793,9 +571,6 @@ export default async function Page() {
<p className="text-sm text-muted-foreground mb-2 md:mb-3">
{item.subtitle}
</p>
<p className="text-xs text-muted-foreground">
{item.description}
</p>
</div>
</div>
</CardContent>
@@ -803,13 +578,6 @@ export default async function Page() {
))}
</div>
</AnimateOnScroll>
<div className="mt-6 md:mt-8 text-center">
<p className="text-sm text-muted-foreground">
Seus dados ficam no seu controle. Pode rodar localmente ou no
seu próprio servidor.
</p>
</div>
</div>
</div>
</section>
@@ -817,7 +585,7 @@ export default async function Page() {
{/* How to run Section */}
<section id="como-usar" className="py-12 md:py-24">
<div className="max-w-8xl mx-auto px-4">
<div className="mx-auto max-w-3xl">
<div className="mx-auto max-w-4xl">
<AnimateOnScroll>
<div className="text-center mb-8 md:mb-12">
<Badge variant="outline" className="mb-4">
@@ -850,19 +618,19 @@ export default async function Page() {
</section>
{/* Who is this for Section */}
<section className="py-12 md:py-24">
<section id="para-quem-e" className="py-12 md:py-24 bg-muted/40">
<div className="max-w-8xl mx-auto px-4">
<div className="mx-auto max-w-3xl">
<div className="mx-auto max-w-4xl">
<AnimateOnScroll>
<div className="text-center mb-8 md:mb-12">
<Badge variant="outline" className="mb-4">
Para quem é?
</Badge>
<h2 className="text-2xl sm:text-3xl md:text-4xl font-bold tracking-tight mb-3 md:mb-4">
Para quem funciona?
Feito para quem gosta de controle
</h2>
<p className="text-base md:text-lg text-muted-foreground px-4 sm:px-0">
O openmonetis funciona melhor se você:
O OpenMonetis não é para todo mundo.
</p>
</div>
</AnimateOnScroll>
@@ -896,19 +664,6 @@ export default async function Page() {
))}
</div>
</AnimateOnScroll>
<AnimateOnScroll>
<Alert className="mt-6 md:mt-8">
<RiInformationLine />
<AlertTitle>Não é para todo mundo</AlertTitle>
<AlertDescription>
Se você não se encaixa nisso, provavelmente vai abandonar
depois de uma semana. Tudo certo! Existem outras ferramentas
com sincronização automática que podem funcionar melhor pra
você.
</AlertDescription>
</Alert>
</AnimateOnScroll>
</div>
</div>
</section>
@@ -917,7 +672,7 @@ export default async function Page() {
<section className="py-12 md:py-24">
<div className="max-w-8xl mx-auto px-4">
<AnimateOnScroll>
<div className="mx-auto max-w-3xl rounded-2xl border bg-card px-6 py-12 md:py-16 text-center">
<div className="mx-auto max-w-4xl rounded-2xl border bg-card px-8 py-12 md:py-16 text-center">
<h2 className="text-2xl sm:text-3xl md:text-4xl font-bold tracking-tight mb-3 md:mb-4">
Pronto para testar?
</h2>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -51,7 +51,6 @@
--chart-9: var(--color-cyan-500);
--chart-10: var(--color-lime-500);
/* Data palette — análoga quente (hue 0120), família do primary */
--data-1: oklch(58% 0.22 18); /* vermelho-tijolo */
--data-2: oklch(64% 0.22 30); /* vermelho-laranja */
--data-3: oklch(69% 0.21 42); /* laranja (≈ primary) */
@@ -93,23 +92,23 @@
}
.dark {
--background: oklch(22% 0.004 55);
--background: oklch(18% 0.004 55);
--foreground: oklch(93% 0.008 80);
--card: oklch(25.5% 0.004 55);
--card: oklch(21.5% 0.004 55);
--card-foreground: var(--foreground);
--popover: oklch(28% 0.004 55);
--popover: oklch(24% 0.004 55);
--popover-foreground: var(--foreground);
--primary: oklch(72.069% 0.18335 44.069);
--primary-foreground: oklch(16% 0.004 60);
--secondary: oklch(29% 0.004 55);
--secondary: oklch(25% 0.004 55);
--secondary-foreground: var(--foreground);
--muted: oklch(32% 0.0035 55);
--muted: oklch(28% 0.0035 55);
--muted-foreground: oklch(73% 0.006 75);
--accent: oklch(33% 0.005 55);
--accent: oklch(29% 0.005 55);
--accent-foreground: var(--foreground);
--success: oklch(62% 0.16 150);
@@ -121,7 +120,7 @@
--destructive: oklch(62% 0.2 28);
--destructive-foreground: oklch(98% 0.005 30);
--border: oklch(35% 0.004 55);
--border: oklch(31% 0.004 55);
--input: var(--border);
--ring: var(--primary);
@@ -136,8 +135,6 @@
--chart-9: var(--color-cyan-500);
--chart-10: var(--color-lime-500);
/* Data palette — dark mode (ligeiramente mais vivos) */
/* Data palette dark — ligeiramente mais vivos para contrastar no fundo escuro */
--data-1: oklch(66% 0.22 18);
--data-2: oklch(72% 0.22 30);
--data-3: oklch(76% 0.21 42);
@@ -149,13 +146,13 @@
--data-9: oklch(69% 0.17 120);
--data-10: oklch(63% 0.15 10);
--sidebar: oklch(19.5% 0.004 55);
--sidebar: oklch(15.5% 0.004 55);
--sidebar-foreground: var(--foreground);
--sidebar-primary: var(--primary);
--sidebar-primary-foreground: var(--primary-foreground);
--sidebar-accent: oklch(30% 0.004 55);
--sidebar-accent: oklch(26% 0.004 55);
--sidebar-accent-foreground: var(--foreground);
--sidebar-border: oklch(34% 0.004 55);
--sidebar-border: oklch(30% 0.004 55);
--sidebar-ring: var(--primary);
--radius: 0.625rem;

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB