feat: homelab deployment - NPM + IONOS DNS + monitoring + NAS backup
- Restructured docker-compose for Nginx Proxy Manager (no custom nginx) - Added domain wordly.art configuration - Added Prometheus + Grafana monitoring stack with pre-configured dashboards - Added PostgreSQL backup script to NAS (daily/weekly/monthly rotation) - Added alert rules for backend, system, and Docker metrics - Updated deployment guide for NPM + IONOS DNS homelab setup - Added marketing plan document - PDF translator and watermark support - Enhanced middleware, routes, and translator modules Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -1,86 +0,0 @@
|
||||
import {
|
||||
Globe2,
|
||||
FileText,
|
||||
Zap,
|
||||
Shield,
|
||||
Brain,
|
||||
Server
|
||||
} from "lucide-react"
|
||||
|
||||
const features = [
|
||||
{
|
||||
icon: Globe2,
|
||||
title: "100+ Languages",
|
||||
description: "Translate between any language pair with high accuracy",
|
||||
color: "text-blue-400",
|
||||
},
|
||||
{
|
||||
icon: FileText,
|
||||
title: "Preserve Formatting",
|
||||
description: "All styles, fonts, colors, tables, and charts remain intact",
|
||||
color: "text-green-400",
|
||||
},
|
||||
{
|
||||
icon: Zap,
|
||||
title: "Lightning Fast",
|
||||
description: "Batch processing translates entire documents in seconds",
|
||||
color: "text-amber-400",
|
||||
},
|
||||
{
|
||||
icon: Shield,
|
||||
title: "Secure & Private",
|
||||
description: "Your documents are encrypted and never stored permanently",
|
||||
color: "text-purple-400",
|
||||
},
|
||||
{
|
||||
icon: Brain,
|
||||
title: "AI-Powered",
|
||||
description: "Advanced neural translation for natural, context-aware results",
|
||||
color: "text-teal-400",
|
||||
},
|
||||
{
|
||||
icon: Server,
|
||||
title: "Enterprise Ready",
|
||||
description: "API access, team management, and dedicated support",
|
||||
color: "text-orange-400",
|
||||
},
|
||||
]
|
||||
|
||||
export function FeaturesSection() {
|
||||
return (
|
||||
<section className="py-16 px-6">
|
||||
<div className="max-w-5xl mx-auto">
|
||||
<div className="text-center mb-12">
|
||||
<h2 className="text-2xl font-bold text-foreground mb-3">
|
||||
Everything You Need for Document Translation
|
||||
</h2>
|
||||
<p className="text-muted-foreground max-w-2xl mx-auto">
|
||||
Professional-grade translation with enterprise features, available to everyone.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{features.map((feature) => {
|
||||
const Icon = feature.icon
|
||||
return (
|
||||
<div
|
||||
key={feature.title}
|
||||
className="flex flex-col items-center text-center p-6 rounded-xl border border-border bg-card/50 hover:bg-card transition-colors"
|
||||
>
|
||||
<div className={`mb-4 ${feature.color}`}>
|
||||
<Icon className="size-8" />
|
||||
</div>
|
||||
<h3 className="text-base font-semibold text-foreground mb-2">
|
||||
{feature.title}
|
||||
</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{feature.description}
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
import Link from "next/link"
|
||||
import { FileSpreadsheet, FileText, Presentation } from "lucide-react"
|
||||
import { Button } from "@/components/ui/button"
|
||||
|
||||
export function HeroSection() {
|
||||
return (
|
||||
<section className="flex flex-col items-center gap-6 px-6 pt-16 pb-8 text-center md:pt-24 md:pb-12">
|
||||
<div className="flex items-center gap-2 rounded-full border border-border bg-card px-4 py-1.5 text-xs font-medium text-muted-foreground shadow-sm">
|
||||
<span className="inline-block size-1.5 rounded-full bg-green-500" />
|
||||
Now with Pro LLM Engine
|
||||
</div>
|
||||
|
||||
<h1 className="max-w-2xl text-balance text-4xl font-bold leading-tight tracking-tight text-foreground md:text-5xl lg:text-6xl">
|
||||
Translate Office Documents. Keep the Format Perfect.
|
||||
</h1>
|
||||
|
||||
<p className="max-w-xl text-pretty text-base leading-relaxed text-muted-foreground md:text-lg">
|
||||
Upload your Excel, Word, or PowerPoint files and get accurate translations with zero formatting loss.
|
||||
</p>
|
||||
|
||||
<div className="flex items-center gap-4 pt-2">
|
||||
<Button asChild size="lg">
|
||||
<Link href="/auth/register">Try Free</Link>
|
||||
</Button>
|
||||
<Button variant="outline" asChild size="lg">
|
||||
<Link href="/pricing">View Pricing</Link>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-6 pt-4">
|
||||
<div className="flex items-center gap-2 text-sm text-muted-foreground">
|
||||
<FileSpreadsheet className="size-4 text-green-500" />
|
||||
<span>.xlsx</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 text-sm text-muted-foreground">
|
||||
<FileText className="size-4 text-blue-500" />
|
||||
<span>.docx</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 text-sm text-muted-foreground">
|
||||
<Presentation className="size-4 text-orange-500" />
|
||||
<span>.pptx</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
@@ -76,7 +76,7 @@ export function HeroWordComparison() {
|
||||
</div>
|
||||
|
||||
<div className="relative p-2 sm:p-4 bg-[#1e1e1e]">
|
||||
<p className="mb-3 text-center text-xs text-slate-400 sm:text-left sm:px-1">
|
||||
<p className="mb-3 text-center text-xs text-slate-400 sm:text-start sm:px-1">
|
||||
{t("landing.heroDoc.caption")}
|
||||
</p>
|
||||
<div className="flex rounded-lg overflow-hidden border border-[#3c3c3c] shadow-inner min-h-[240px] sm:min-h-[300px]">
|
||||
@@ -86,7 +86,7 @@ export function HeroWordComparison() {
|
||||
{t("landing.heroDoc.badgeOriginal")}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex-1 p-3 sm:p-4 overflow-hidden bg-white text-left">
|
||||
<div className="flex-1 p-3 sm:p-4 overflow-hidden bg-white text-start">
|
||||
<article
|
||||
className="text-[11px] sm:text-xs leading-relaxed text-[#242424]"
|
||||
style={{
|
||||
@@ -108,7 +108,7 @@ export function HeroWordComparison() {
|
||||
{t("landing.heroDoc.badgeTranslated")}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex-1 p-3 sm:p-4 overflow-hidden bg-white text-left">
|
||||
<div className="flex-1 p-3 sm:p-4 overflow-hidden bg-white text-start">
|
||||
<article
|
||||
className="text-[11px] sm:text-xs leading-relaxed text-[#242424]"
|
||||
style={{
|
||||
|
||||
@@ -1,226 +1,355 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
import Link from "next/link";
|
||||
import { useTranslation } from "@/lib/i18n";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { LanguageSwitcher } from "@/components/ui/language-switcher";
|
||||
import { ThemeToggle } from "@/components/ui/theme-toggle";
|
||||
import { HeroWordComparison } from "@/components/landing/hero-word-comparison";
|
||||
import { useI18n } from "@/lib/i18n";
|
||||
import { API_BASE } from "@/lib/config";
|
||||
import {
|
||||
Table2,
|
||||
FileText,
|
||||
Table2,
|
||||
Presentation,
|
||||
Bot,
|
||||
Lock,
|
||||
Zap,
|
||||
FileSpreadsheet,
|
||||
Check,
|
||||
PlayCircle,
|
||||
ShieldCheck,
|
||||
Clock,
|
||||
Languages,
|
||||
Zap,
|
||||
Sparkles,
|
||||
ArrowRight,
|
||||
BadgeCheck,
|
||||
Eye,
|
||||
LayoutGrid,
|
||||
Bot,
|
||||
Brain,
|
||||
BookOpen,
|
||||
Upload,
|
||||
ArrowLeftRight,
|
||||
} from "lucide-react";
|
||||
|
||||
export function LandingPage() {
|
||||
const { t } = useTranslation();
|
||||
const [isYearly, setIsYearly] = useState(false);
|
||||
const { t } = useI18n();
|
||||
|
||||
const [prices, setPrices] = useState({
|
||||
starter: { monthly: 9, yearly: 86.40 },
|
||||
pro: { monthly: 19, yearly: 182.40 },
|
||||
business: { monthly: 49, yearly: 470.40 },
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
fetch(`${API_BASE}/api/v1/auth/plans`, { cache: "no-store" })
|
||||
.then((r) => (r.ok ? r.json() : null))
|
||||
.then((json) => {
|
||||
if (!json) return;
|
||||
const d = json.data ?? json;
|
||||
const plans = Array.isArray(d.plans) ? d.plans : [];
|
||||
const map: Record<string, { monthly: number; yearly: number }> = {};
|
||||
for (const p of plans) {
|
||||
if (p.id && typeof p.price_monthly === "number") {
|
||||
map[p.id] = {
|
||||
monthly: p.price_monthly,
|
||||
yearly: typeof p.price_yearly === "number" ? p.price_yearly : p.price_monthly * 12,
|
||||
};
|
||||
}
|
||||
}
|
||||
if (map.starter || map.pro || map.business) {
|
||||
setPrices((prev) => ({
|
||||
starter: map.starter || prev.starter,
|
||||
pro: map.pro || prev.pro,
|
||||
business: map.business || prev.business,
|
||||
}));
|
||||
}
|
||||
})
|
||||
.catch(() => {});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-background text-foreground font-sans">
|
||||
{/* Header */}
|
||||
{/* ── Header ── */}
|
||||
<header className="sticky top-0 z-50 w-full border-b border-border bg-background/80 backdrop-blur-md">
|
||||
<div className="mx-auto flex h-16 max-w-7xl items-center justify-between px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex items-center gap-4">
|
||||
<Link href="/" className="flex items-center gap-3">
|
||||
<div className="flex items-center justify-center rounded-lg bg-primary/10 p-1.5">
|
||||
<Languages className="h-5 w-5 text-primary" />
|
||||
</div>
|
||||
<span className="text-foreground text-lg font-bold tracking-tight">
|
||||
Office Translator
|
||||
</span>
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
<nav className="hidden md:flex items-center gap-8">
|
||||
<a
|
||||
className="text-muted-foreground hover:text-foreground text-sm font-medium transition-colors"
|
||||
href="#features"
|
||||
>
|
||||
{t("nav.features")}
|
||||
<a className="text-muted-foreground hover:text-foreground text-sm font-medium transition-colors" href="#why">
|
||||
{t("landing.nav.whyUs")}
|
||||
</a>
|
||||
<a
|
||||
className="text-muted-foreground hover:text-foreground text-sm font-medium transition-colors"
|
||||
href="#pricing"
|
||||
>
|
||||
{t("nav.pricing")}
|
||||
<a className="text-muted-foreground hover:text-foreground text-sm font-medium transition-colors" href="#formats">
|
||||
{t("landing.nav.formats")}
|
||||
</a>
|
||||
<a
|
||||
className="text-muted-foreground hover:text-foreground text-sm font-medium transition-colors"
|
||||
href="#enterprise"
|
||||
>
|
||||
{t("nav.enterprise")}
|
||||
<a className="text-muted-foreground hover:text-foreground text-sm font-medium transition-colors" href="#pricing">
|
||||
{t("landing.nav.pricing")}
|
||||
</a>
|
||||
</nav>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<LanguageSwitcher variant="button" />
|
||||
<LanguageSwitcher variant="select" />
|
||||
<ThemeToggle />
|
||||
<a
|
||||
className="hidden sm:inline-flex h-9 items-center justify-center rounded-lg px-4 text-sm font-medium text-muted-foreground transition-colors hover:text-foreground"
|
||||
href="/auth/login"
|
||||
>
|
||||
{t("common.login")}
|
||||
{t("landing.nav.login")}
|
||||
</a>
|
||||
<Button
|
||||
asChild
|
||||
className="bg-primary text-primary-foreground font-bold hover:bg-primary/90"
|
||||
>
|
||||
<Link href="/auth/register">{t("common.signup")}</Link>
|
||||
<Button asChild className="bg-primary text-primary-foreground font-bold hover:bg-primary/90">
|
||||
<Link href="/auth/register">{t("landing.nav.startFree")}</Link>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
{/* Hero Section */}
|
||||
<section className="relative pt-20 pb-32 overflow-hidden">
|
||||
{/* ── Hero ── */}
|
||||
<section className="relative pt-20 pb-28 overflow-hidden">
|
||||
<div className="absolute inset-0 -z-10 bg-[radial-gradient(ellipse_at_top,_var(--tw-gradient-stops))] from-primary/10 via-background to-background" />
|
||||
|
||||
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex flex-col lg:flex-row items-center gap-12 lg:gap-20">
|
||||
{/* Hero Text */}
|
||||
<div className="flex-1 text-center lg:text-left space-y-8">
|
||||
<h1 className="text-4xl font-extrabold tracking-tight text-foreground sm:text-5xl lg:text-6xl xl:text-7xl">
|
||||
{t("hero.title")}
|
||||
<br />
|
||||
<span className="text-transparent bg-clip-text bg-gradient-to-r from-primary to-emerald-400">
|
||||
{t("hero.titleHighlight")}
|
||||
</span>
|
||||
</h1>
|
||||
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 text-center">
|
||||
{/* Badge */}
|
||||
<div className="inline-flex items-center gap-2 rounded-full border border-primary/30 bg-primary/5 px-4 py-1.5 text-sm font-medium text-primary mb-8">
|
||||
<Sparkles className="h-4 w-4" />
|
||||
{t("landing.hero.badge")}
|
||||
</div>
|
||||
|
||||
<p className="mx-auto lg:mx-0 max-w-2xl text-lg text-muted-foreground">
|
||||
{t("hero.subtitle")}
|
||||
</p>
|
||||
<h1 className="text-4xl font-extrabold tracking-tight text-foreground sm:text-5xl lg:text-6xl xl:text-7xl mx-auto max-w-5xl">
|
||||
{t("landing.hero.title1")}
|
||||
<br />
|
||||
<span className="text-transparent bg-clip-text bg-gradient-to-r from-primary to-emerald-400">
|
||||
{t("landing.hero.title2")}
|
||||
</span>
|
||||
</h1>
|
||||
|
||||
<div className="flex flex-col sm:flex-row items-center justify-center lg:justify-start gap-4">
|
||||
<Button
|
||||
asChild
|
||||
size="lg"
|
||||
className="bg-primary text-primary-foreground font-bold hover:bg-primary/90"
|
||||
>
|
||||
<Link href="/auth/register">{t("hero.cta")}</Link>
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="lg"
|
||||
className="gap-2"
|
||||
>
|
||||
<PlayCircle className="h-5 w-5" />
|
||||
{t("hero.demoCta")}
|
||||
</Button>
|
||||
</div>
|
||||
<p className="mt-8 mx-auto max-w-2xl text-lg text-muted-foreground">
|
||||
{t("landing.hero.subtitle")}
|
||||
</p>
|
||||
|
||||
{/* Trust Badges */}
|
||||
<div className="pt-8 flex flex-wrap justify-center lg:justify-start gap-6">
|
||||
<div className="flex items-center gap-2 text-sm text-muted-foreground">
|
||||
<ShieldCheck className="h-5 w-5 text-primary" />
|
||||
<span>{t("hero.badge1")}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 text-sm text-muted-foreground">
|
||||
<Clock className="h-5 w-5 text-primary" />
|
||||
<span>{t("hero.badge2")}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-10 flex flex-col sm:flex-row items-center justify-center gap-4">
|
||||
<Button
|
||||
asChild
|
||||
size="lg"
|
||||
className="bg-primary text-primary-foreground font-bold hover:bg-primary/90 text-base px-8"
|
||||
>
|
||||
<Link href="/auth/register">
|
||||
{t("landing.hero.cta")}
|
||||
<ArrowRight className="ms-2 h-5 w-5" />
|
||||
</Link>
|
||||
</Button>
|
||||
<Button variant="outline" size="lg" className="text-base px-8" asChild>
|
||||
<Link href="#pricing">{t("landing.hero.seePlans")}</Link>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* Trust Badges */}
|
||||
<div className="mt-12 flex flex-wrap justify-center gap-8 text-sm text-muted-foreground">
|
||||
<div className="flex items-center gap-2">
|
||||
<ShieldCheck className="h-5 w-5 text-primary" />
|
||||
<span>{t("landing.trust.filesDeleted")}</span>
|
||||
</div>
|
||||
|
||||
{/* Hero Visual — Word EN | FR + illustrations */}
|
||||
<div className="flex-1 w-full max-w-lg lg:max-w-none relative">
|
||||
<HeroWordComparison />
|
||||
<div className="flex items-center gap-2">
|
||||
<BadgeCheck className="h-5 w-5 text-primary" />
|
||||
<span>{t("landing.trust.noBait")}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Eye className="h-5 w-5 text-primary" />
|
||||
<span>{t("landing.trust.preview")}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Format pills */}
|
||||
<div className="mt-10 flex flex-wrap justify-center gap-3">
|
||||
{[".DOCX", ".XLSX", ".PPTX", ".PDF"].map((fmt) => (
|
||||
<span
|
||||
key={fmt}
|
||||
className="inline-flex items-center rounded-full border border-border bg-card px-4 py-2 text-sm font-mono font-semibold text-foreground"
|
||||
>
|
||||
{fmt}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Features Grid */}
|
||||
<section className="py-24 bg-background relative" id="features">
|
||||
{/* ── How it works ── */}
|
||||
<section className="py-24 bg-background">
|
||||
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||
<div className="text-center mb-16">
|
||||
<h2 className="text-3xl font-bold tracking-tight text-foreground sm:text-4xl mb-4">
|
||||
{t("features.title")}
|
||||
<h2 className="text-3xl font-bold tracking-tight sm:text-4xl mb-4">
|
||||
{t("landing.howItWorks.title")}
|
||||
</h2>
|
||||
<p className="text-lg text-muted-foreground max-w-2xl mx-auto">
|
||||
{t("features.subtitle")}
|
||||
{t("landing.howItWorks.subtitle")}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-wrap justify-center gap-6">
|
||||
{/* Feature 1 - Excel */}
|
||||
<div className="w-full md:w-[calc(50%-12px)] lg:w-[calc(33.333%-16px)] group relative rounded-2xl border border-border bg-card p-8 hover:border-primary/50 transition-colors">
|
||||
<div className="mb-4 inline-flex h-12 w-12 items-center justify-center rounded-lg bg-primary/10 text-primary">
|
||||
<Table2 className="h-6 w-6" />
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-8 max-w-4xl mx-auto">
|
||||
{[
|
||||
{
|
||||
step: "1",
|
||||
icon: Upload,
|
||||
title: t("landing.howItWorks.step1.title"),
|
||||
desc: t("landing.howItWorks.step1.desc"),
|
||||
color: "text-blue-500",
|
||||
},
|
||||
{
|
||||
step: "2",
|
||||
icon: ArrowLeftRight,
|
||||
title: t("landing.howItWorks.step2.title"),
|
||||
desc: t("landing.howItWorks.step2.desc"),
|
||||
color: "text-primary",
|
||||
},
|
||||
{
|
||||
step: "3",
|
||||
icon: Check,
|
||||
title: t("landing.howItWorks.step3.title"),
|
||||
desc: t("landing.howItWorks.step3.desc"),
|
||||
color: "text-emerald-500",
|
||||
},
|
||||
].map((s, i) => (
|
||||
<div key={i} className="flex flex-col items-center text-center">
|
||||
<div className={`flex size-16 items-center justify-center rounded-2xl bg-muted/50 mb-4 ${s.color}`}>
|
||||
<s.icon className="size-7" />
|
||||
</div>
|
||||
<h3 className="text-lg font-bold mb-2">{s.title}</h3>
|
||||
<p className="text-sm text-muted-foreground max-w-xs">{s.desc}</p>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-foreground mb-2">
|
||||
{t("features.excel.title")}
|
||||
</h3>
|
||||
<p className="text-muted-foreground">{t("features.excel.description")}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Feature 2 - Word */}
|
||||
<div className="w-full md:w-[calc(50%-12px)] lg:w-[calc(33.333%-16px)] group relative rounded-2xl border border-border bg-card p-8 hover:border-primary/50 transition-colors">
|
||||
<div className="mb-4 inline-flex h-12 w-12 items-center justify-center rounded-lg bg-primary/10 text-primary">
|
||||
<FileText className="h-6 w-6" />
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-foreground mb-2">
|
||||
{t("features.word.title")}
|
||||
</h3>
|
||||
<p className="text-muted-foreground">{t("features.word.description")}</p>
|
||||
{/* ── AI Translation Engine ── */}
|
||||
<section className="py-24 bg-muted/30" id="ai-engine">
|
||||
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||
<div className="text-center mb-16">
|
||||
<div className="inline-flex items-center gap-2 rounded-full border border-primary/30 bg-primary/5 px-4 py-1.5 text-sm font-medium text-primary mb-6">
|
||||
<Brain className="h-4 w-4" />
|
||||
{t("landing.ai.badge")}
|
||||
</div>
|
||||
<h2 className="text-3xl font-bold tracking-tight sm:text-4xl mb-4">
|
||||
{t("landing.ai.title")}
|
||||
</h2>
|
||||
<p className="text-lg text-muted-foreground max-w-2xl mx-auto">
|
||||
{t("landing.ai.subtitle")}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Feature 3 - PowerPoint */}
|
||||
<div className="w-full md:w-[calc(50%-12px)] lg:w-[calc(33.333%-16px)] group relative rounded-2xl border border-border bg-card p-8 hover:border-primary/50 transition-colors">
|
||||
<div className="mb-4 inline-flex h-12 w-12 items-center justify-center rounded-lg bg-primary/10 text-primary">
|
||||
<Presentation className="h-6 w-6" />
|
||||
{/* Three pillars */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 max-w-5xl mx-auto mb-16">
|
||||
{[
|
||||
{ icon: Zap, title: t("landing.ai.context.title"), desc: t("landing.ai.context.desc"), color: "text-blue-500" },
|
||||
{ icon: BookOpen, title: t("landing.ai.glossary.title"), desc: t("landing.ai.glossary.desc"), color: "text-primary" },
|
||||
{ icon: Eye, title: t("landing.ai.vision.title"), desc: t("landing.ai.vision.desc"), color: "text-emerald-500" },
|
||||
].map((feature, i) => (
|
||||
<div key={i} className="group relative rounded-2xl border border-border bg-card p-8 hover:border-primary/50 transition-colors">
|
||||
<div className={`mb-4 inline-flex h-12 w-12 items-center justify-center rounded-lg bg-muted/50 ${feature.color}`}>
|
||||
<feature.icon className="h-6 w-6" />
|
||||
</div>
|
||||
<h3 className="text-xl font-bold mb-2">{feature.title}</h3>
|
||||
<p className="text-muted-foreground text-sm">{feature.desc}</p>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-foreground mb-2">
|
||||
{t("features.powerpoint.title")}
|
||||
</h3>
|
||||
<p className="text-muted-foreground">
|
||||
{t("features.powerpoint.description")}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Feature 4 - AI */}
|
||||
<div className="w-full md:w-[calc(50%-12px)] lg:w-[calc(33.333%-16px)] group relative rounded-2xl border border-border bg-card p-8 hover:border-primary/50 transition-colors">
|
||||
<div className="mb-4 inline-flex h-12 w-12 items-center justify-center rounded-lg bg-primary/10 text-primary">
|
||||
<Bot className="h-6 w-6" />
|
||||
{/* Comparison */}
|
||||
<div className="max-w-3xl mx-auto rounded-2xl border border-border bg-card p-8">
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
<div className="space-y-2">
|
||||
<p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">{t("landing.ai.comparison.source")}</p>
|
||||
<p className="text-sm text-foreground font-medium italic">“{t("landing.ai.comparison.sourceText")}”</p>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-foreground mb-2">
|
||||
{t("features.ai.title")}
|
||||
</h3>
|
||||
<p className="text-muted-foreground">{t("features.ai.description")}</p>
|
||||
</div>
|
||||
|
||||
{/* Feature 5 - Speed */}
|
||||
<div className="w-full md:w-[calc(50%-12px)] lg:w-[calc(33.333%-16px)] group relative rounded-2xl border border-border bg-card p-8 hover:border-primary/50 transition-colors">
|
||||
<div className="mb-4 inline-flex h-12 w-12 items-center justify-center rounded-lg bg-primary/10 text-primary">
|
||||
<Zap className="h-6 w-6" />
|
||||
<div className="space-y-2">
|
||||
<p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">{t("landing.ai.comparison.google")}</p>
|
||||
<p className="text-sm text-destructive/80">“{t("landing.ai.comparison.googleText")}”</p>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<p className="text-xs font-semibold uppercase tracking-wider text-primary">{t("landing.ai.comparison.ai")}</p>
|
||||
<p className="text-sm text-emerald-600 font-medium">“{t("landing.ai.comparison.aiText")}”</p>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-foreground mb-2">
|
||||
{t("features.speed.title")}
|
||||
</h3>
|
||||
<p className="text-muted-foreground">{t("features.speed.description")}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Pricing Section */}
|
||||
<section className="py-24 bg-muted/30" id="pricing">
|
||||
{/* ── Why Us — Format Preservation ── */}
|
||||
<section className="py-24 bg-muted/30" id="why">
|
||||
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||
<div className="text-center mb-16">
|
||||
<h2 className="text-3xl font-bold tracking-tight sm:text-4xl mb-4">
|
||||
{t("landing.why.title")}
|
||||
</h2>
|
||||
<p className="text-lg text-muted-foreground max-w-2xl mx-auto">
|
||||
{t("landing.why.subtitle")}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{[
|
||||
{
|
||||
icon: LayoutGrid,
|
||||
title: t("landing.why.smartart.title"),
|
||||
desc: t("landing.why.smartart.desc"),
|
||||
},
|
||||
{
|
||||
icon: FileText,
|
||||
title: t("landing.why.toc.title"),
|
||||
desc: t("landing.why.toc.desc"),
|
||||
},
|
||||
{
|
||||
icon: Table2,
|
||||
title: t("landing.why.charts.title"),
|
||||
desc: t("landing.why.charts.desc"),
|
||||
},
|
||||
{
|
||||
icon: Presentation,
|
||||
title: t("landing.why.shapes.title"),
|
||||
desc: t("landing.why.shapes.desc"),
|
||||
},
|
||||
{
|
||||
icon: FileSpreadsheet,
|
||||
title: t("landing.why.headers.title"),
|
||||
desc: t("landing.why.headers.desc"),
|
||||
},
|
||||
{
|
||||
icon: Zap,
|
||||
title: t("landing.why.languages.title"),
|
||||
desc: t("landing.why.languages.desc"),
|
||||
},
|
||||
].map((feature, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="group relative rounded-2xl border border-border bg-card p-8 hover:border-primary/50 transition-colors"
|
||||
>
|
||||
<div className="mb-4 inline-flex h-12 w-12 items-center justify-center rounded-lg bg-primary/10 text-primary">
|
||||
<feature.icon className="h-6 w-6" />
|
||||
</div>
|
||||
<h3 className="text-xl font-bold mb-2">{feature.title}</h3>
|
||||
<p className="text-muted-foreground">{feature.desc}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── Honest Pricing Comparison ── */}
|
||||
<section className="py-24 bg-background" id="pricing">
|
||||
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||
<div className="text-center mb-10">
|
||||
<h2 className="text-3xl font-bold tracking-tight text-foreground sm:text-4xl mb-4">
|
||||
{t("pricing.title")}
|
||||
<h2 className="text-3xl font-bold tracking-tight sm:text-4xl mb-4">
|
||||
{t("landing.pricing.title")}
|
||||
</h2>
|
||||
<p className="text-lg text-muted-foreground">{t("pricing.subtitle")}</p>
|
||||
<p className="text-lg text-muted-foreground max-w-2xl mx-auto">
|
||||
{t("landing.pricing.subtitle")}
|
||||
</p>
|
||||
|
||||
<div className="flex justify-center mt-8">
|
||||
<div className="inline-flex items-center gap-3 bg-card border border-border rounded-full p-1.5">
|
||||
@@ -228,21 +357,24 @@ export function LandingPage() {
|
||||
onClick={() => setIsYearly(false)}
|
||||
className={cn(
|
||||
"px-5 py-2 rounded-full text-sm font-medium transition-all",
|
||||
!isYearly ? "bg-primary text-primary-foreground shadow" : "text-muted-foreground hover:text-foreground"
|
||||
!isYearly ? "bg-primary text-primary-foreground shadow" : "text-muted-foreground"
|
||||
)}
|
||||
>
|
||||
{t("common.monthly")}
|
||||
{t("landing.pricing.monthly")}
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setIsYearly(true)}
|
||||
className={cn(
|
||||
"px-5 py-2 rounded-full text-sm font-medium transition-all flex items-center gap-2",
|
||||
isYearly ? "bg-primary text-primary-foreground shadow" : "text-muted-foreground hover:text-foreground"
|
||||
isYearly ? "bg-primary text-primary-foreground shadow" : "text-muted-foreground"
|
||||
)}
|
||||
>
|
||||
{t("common.yearly")}
|
||||
<span className={cn("text-xs px-1.5 py-0.5 rounded-full font-bold", isYearly ? "bg-background text-primary" : "bg-emerald-500/20 text-emerald-600 dark:text-emerald-400")}>
|
||||
{t("common.save20")}
|
||||
{t("landing.pricing.yearly")}
|
||||
<span className={cn(
|
||||
"text-xs px-1.5 py-0.5 rounded-full font-bold",
|
||||
isYearly ? "bg-background text-primary" : "bg-emerald-500/20 text-emerald-600"
|
||||
)}>
|
||||
-20%
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
@@ -250,140 +382,218 @@ export function LandingPage() {
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-8 max-w-5xl mx-auto">
|
||||
{/* Starter Plan */}
|
||||
{/* Starter */}
|
||||
<div className="rounded-2xl border border-border bg-card p-8 flex flex-col">
|
||||
<h3 className="text-xl font-semibold text-foreground">
|
||||
{t("pricing.starter.name")}
|
||||
</h3>
|
||||
<p className="mt-4 text-muted-foreground text-sm">
|
||||
{t("pricing.starter.description")}
|
||||
<h3 className="text-xl font-semibold">{t("landing.pricing.starter.title")}</h3>
|
||||
<p className="mt-2 text-muted-foreground text-sm">
|
||||
{t("landing.pricing.starter.desc")}
|
||||
</p>
|
||||
<div className="mt-6 mb-2">
|
||||
<span className="text-4xl font-bold text-foreground">
|
||||
{isYearly ? t("pricing.starter.priceYearly") : t("pricing.starter.priceMonthly")}
|
||||
<span className="text-4xl font-bold">
|
||||
€{isYearly ? prices.starter.yearly / 12 : prices.starter.monthly}
|
||||
</span>
|
||||
<span className="text-muted-foreground">/{t("common.month")}</span>
|
||||
<span className="text-muted-foreground">{t("landing.pricing.perMonth")}</span>
|
||||
</div>
|
||||
<div className="h-6 mb-4">
|
||||
{isYearly && (
|
||||
<span className="text-sm font-medium text-emerald-600 dark:text-emerald-400">
|
||||
{t("pricing.starter.billedYearly")}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<ul className="space-y-4 mb-8 flex-1">
|
||||
{[0, 1, 2, 3].map((i) => (
|
||||
<li key={i} className="flex items-center text-muted-foreground text-sm">
|
||||
<Check className="h-4 w-4 text-primary mr-2 shrink-0" />
|
||||
{t(`pricing.starter.features.${i}`)}
|
||||
{isYearly && (
|
||||
<span className="text-sm text-emerald-600 mb-4">€{prices.starter.yearly} {t("landing.pricing.billedYearly")}</span>
|
||||
)}
|
||||
<ul className="space-y-3 mb-8 flex-1 mt-4">
|
||||
{[
|
||||
t("landing.pricing.starter.f1"),
|
||||
t("landing.pricing.starter.f2"),
|
||||
t("landing.pricing.starter.f3"),
|
||||
t("landing.pricing.starter.f4"),
|
||||
].map((f, i) => (
|
||||
<li key={i} className="flex items-center text-sm text-muted-foreground">
|
||||
<Check className="h-4 w-4 text-primary me-2 shrink-0" />{f}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<Button asChild variant="outline">
|
||||
<Link href="/pricing?plan=starter">{t("common.signup")}</Link>
|
||||
<Button asChild variant="outline" className="w-full">
|
||||
<Link href="/pricing?plan=starter">{t("landing.pricing.starter.cta")}</Link>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* Pro Plan */}
|
||||
<div className="relative rounded-2xl border border-primary bg-card p-8 flex flex-col shadow-lg shadow-primary/10 scale-105 z-10">
|
||||
<div className="absolute -top-4 left-1/2 -translate-x-1/2 rounded-full bg-warning px-3 py-1 text-xs font-bold text-warning-foreground uppercase tracking-wide">
|
||||
{t("common.popular")}
|
||||
{/* Pro — Popular */}
|
||||
<div className="relative rounded-2xl border-2 border-primary bg-card p-8 flex flex-col shadow-lg shadow-primary/10 scale-105 z-10">
|
||||
<div className="absolute -top-4 left-1/2 -translate-x-1/2 rounded-full bg-primary px-4 py-1 text-xs font-bold text-primary-foreground uppercase tracking-wide">
|
||||
{t("landing.pricing.pro.badge")}
|
||||
</div>
|
||||
<h3 className="text-xl font-semibold text-foreground">
|
||||
{t("pricing.pro.name")}
|
||||
</h3>
|
||||
<p className="mt-4 text-muted-foreground text-sm">
|
||||
{t("pricing.pro.description")}
|
||||
<h3 className="text-xl font-semibold">{t("landing.pricing.pro.title")}</h3>
|
||||
<p className="mt-2 text-muted-foreground text-sm">
|
||||
{t("landing.pricing.pro.desc")}
|
||||
</p>
|
||||
<div className="mt-6 mb-2">
|
||||
<span className="text-4xl font-bold text-foreground">
|
||||
{isYearly ? t("pricing.pro.priceYearly") : t("pricing.pro.priceMonthly")}
|
||||
<span className="text-4xl font-bold">
|
||||
€{isYearly ? prices.pro.yearly / 12 : prices.pro.monthly}
|
||||
</span>
|
||||
<span className="text-muted-foreground">/{t("common.month")}</span>
|
||||
<span className="text-muted-foreground">{t("landing.pricing.perMonth")}</span>
|
||||
</div>
|
||||
<div className="h-6 mb-4">
|
||||
{isYearly && (
|
||||
<span className="text-sm font-medium text-emerald-600 dark:text-emerald-400">
|
||||
{t("pricing.pro.billedYearly")}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<ul className="space-y-4 mb-8 flex-1">
|
||||
{[0, 1, 2, 3].map((i) => (
|
||||
<li key={i} className="flex items-center text-foreground text-sm">
|
||||
<Check className="h-4 w-4 text-primary mr-2 shrink-0" />
|
||||
{t(`pricing.pro.features.${i}`)}
|
||||
{isYearly && (
|
||||
<span className="text-sm text-emerald-600 mb-4">€{prices.pro.yearly} {t("landing.pricing.billedYearly")}</span>
|
||||
)}
|
||||
<ul className="space-y-3 mb-8 flex-1 mt-4">
|
||||
{[
|
||||
t("landing.pricing.pro.f1"),
|
||||
t("landing.pricing.pro.f2"),
|
||||
t("landing.pricing.pro.f3"),
|
||||
t("landing.pricing.pro.f4"),
|
||||
t("landing.pricing.pro.f5"),
|
||||
t("landing.pricing.pro.f6"),
|
||||
].map((f, i) => (
|
||||
<li key={i} className="flex items-center text-sm text-foreground font-medium">
|
||||
<Check className="h-4 w-4 text-primary me-2 shrink-0" />{f}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<Button
|
||||
asChild
|
||||
className="bg-primary text-primary-foreground font-bold hover:bg-primary/90"
|
||||
>
|
||||
<Link href="/pricing?plan=pro">{t("common.tryPro")}</Link>
|
||||
<Button asChild className="w-full bg-primary text-primary-foreground font-bold hover:bg-primary/90">
|
||||
<Link href="/pricing?plan=pro">{t("landing.pricing.pro.cta")}</Link>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* Business Plan */}
|
||||
{/* Business */}
|
||||
<div className="rounded-2xl border border-border bg-card p-8 flex flex-col">
|
||||
<h3 className="text-xl font-semibold text-foreground">
|
||||
{t("pricing.business.name")}
|
||||
</h3>
|
||||
<p className="mt-4 text-muted-foreground text-sm">
|
||||
{t("pricing.business.description")}
|
||||
<h3 className="text-xl font-semibold">{t("landing.pricing.business.title")}</h3>
|
||||
<p className="mt-2 text-muted-foreground text-sm">
|
||||
{t("landing.pricing.business.desc")}
|
||||
</p>
|
||||
<div className="mt-6 mb-2">
|
||||
<span className="text-4xl font-bold text-foreground">
|
||||
{isYearly ? t("pricing.business.priceYearly") : t("pricing.business.priceMonthly")}
|
||||
<span className="text-4xl font-bold">
|
||||
€{isYearly ? prices.business.yearly / 12 : prices.business.monthly}
|
||||
</span>
|
||||
<span className="text-muted-foreground">/{t("common.month")}</span>
|
||||
<span className="text-muted-foreground">{t("landing.pricing.perMonth")}</span>
|
||||
</div>
|
||||
<div className="h-6 mb-4">
|
||||
{isYearly && (
|
||||
<span className="text-sm font-medium text-emerald-600 dark:text-emerald-400">
|
||||
{t("pricing.business.billedYearly")}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<ul className="space-y-4 mb-8 flex-1">
|
||||
{[0, 1, 2, 3].map((i) => (
|
||||
<li key={i} className="flex items-center text-muted-foreground text-sm">
|
||||
<Check className="h-4 w-4 text-primary mr-2 shrink-0" />
|
||||
{t(`pricing.business.features.${i}`)}
|
||||
{isYearly && (
|
||||
<span className="text-sm text-emerald-600 mb-4">€{prices.business.yearly} {t("landing.pricing.billedYearly")}</span>
|
||||
)}
|
||||
<ul className="space-y-3 mb-8 flex-1 mt-4">
|
||||
{[
|
||||
t("landing.pricing.business.f1"),
|
||||
t("landing.pricing.business.f2"),
|
||||
t("landing.pricing.business.f3"),
|
||||
t("landing.pricing.business.f4"),
|
||||
t("landing.pricing.business.f5"),
|
||||
t("landing.pricing.business.f6"),
|
||||
].map((f, i) => (
|
||||
<li key={i} className="flex items-center text-sm text-muted-foreground">
|
||||
<Check className="h-4 w-4 text-primary me-2 shrink-0" />{f}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<Button asChild variant="outline">
|
||||
<Link href="/pricing?plan=business">{t("common.tryPro")}</Link>
|
||||
<Button asChild variant="outline" className="w-full">
|
||||
<Link href="/pricing?plan=business">{t("landing.pricing.business.cta")}</Link>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Honest pricing callout */}
|
||||
<div className="mt-12 text-center">
|
||||
<div className="inline-flex items-center gap-2 rounded-full border border-emerald-500/30 bg-emerald-500/5 px-5 py-2.5 text-sm text-emerald-700 dark:text-emerald-400">
|
||||
<BadgeCheck className="h-5 w-5" />
|
||||
<span className="font-medium">{t("landing.pricing.honest")}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* CTA Section */}
|
||||
{/* ── Format Support ── */}
|
||||
<section className="py-24 bg-muted/30" id="formats">
|
||||
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||
<div className="text-center mb-16">
|
||||
<h2 className="text-3xl font-bold tracking-tight sm:text-4xl mb-4">
|
||||
{t("landing.formats.title")}
|
||||
</h2>
|
||||
<p className="text-lg text-muted-foreground max-w-2xl mx-auto">
|
||||
{t("landing.formats.subtitle")}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-8 max-w-4xl mx-auto">
|
||||
{[
|
||||
{
|
||||
format: t("landing.formats.word"),
|
||||
items: [
|
||||
t("landing.formats.word.f1"),
|
||||
t("landing.formats.word.f2"),
|
||||
t("landing.formats.word.f3"),
|
||||
t("landing.formats.word.f4"),
|
||||
t("landing.formats.word.f5"),
|
||||
t("landing.formats.word.f6"),
|
||||
t("landing.formats.word.f7"),
|
||||
],
|
||||
},
|
||||
{
|
||||
format: t("landing.formats.excel"),
|
||||
items: [
|
||||
t("landing.formats.excel.f1"),
|
||||
t("landing.formats.excel.f2"),
|
||||
t("landing.formats.excel.f3"),
|
||||
t("landing.formats.excel.f4"),
|
||||
t("landing.formats.excel.f5"),
|
||||
],
|
||||
},
|
||||
{
|
||||
format: t("landing.formats.powerpoint"),
|
||||
items: [
|
||||
t("landing.formats.powerpoint.f1"),
|
||||
t("landing.formats.powerpoint.f2"),
|
||||
t("landing.formats.powerpoint.f3"),
|
||||
t("landing.formats.powerpoint.f4"),
|
||||
t("landing.formats.powerpoint.f5"),
|
||||
],
|
||||
},
|
||||
{
|
||||
format: t("landing.formats.pdf"),
|
||||
items: [
|
||||
t("landing.formats.pdf.f1"),
|
||||
t("landing.formats.pdf.f2"),
|
||||
t("landing.formats.pdf.f3"),
|
||||
t("landing.formats.pdf.f4"),
|
||||
t("landing.formats.pdf.f5"),
|
||||
],
|
||||
},
|
||||
].map((fmt, i) => (
|
||||
<div key={i} className="rounded-2xl border border-border bg-card p-8">
|
||||
<h3 className="text-xl font-bold mb-4">{fmt.format}</h3>
|
||||
<ul className="space-y-2">
|
||||
{fmt.items.map((item, j) => (
|
||||
<li key={j} className="flex items-center text-sm text-muted-foreground">
|
||||
<Check className="h-4 w-4 text-primary me-2 shrink-0" />{item}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── CTA ── */}
|
||||
<section className="relative py-20 px-4 bg-background">
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-primary/5 to-transparent pointer-events-none" />
|
||||
<div className="mx-auto max-w-4xl rounded-3xl bg-card border border-border p-12 text-center shadow-2xl overflow-hidden relative">
|
||||
<div className="absolute top-0 left-0 w-full h-1 bg-gradient-to-r from-transparent via-primary to-transparent opacity-50" />
|
||||
<h2 className="text-3xl font-bold text-foreground mb-6">
|
||||
{t("cta.title")}
|
||||
<h2 className="text-3xl font-bold mb-6">
|
||||
{t("landing.cta.title")}
|
||||
</h2>
|
||||
<p className="text-muted-foreground mb-8 max-w-2xl mx-auto">
|
||||
{t("cta.subtitle")}
|
||||
{t("landing.cta.subtitle")}
|
||||
</p>
|
||||
<Button
|
||||
asChild
|
||||
size="lg"
|
||||
className="bg-primary text-primary-foreground font-bold hover:bg-primary/90"
|
||||
className="bg-primary text-primary-foreground font-bold hover:bg-primary/90 text-base px-8"
|
||||
>
|
||||
<Link href="/auth/register">{t("cta.button")}</Link>
|
||||
<Link href="/auth/register">
|
||||
{t("landing.cta.button")}
|
||||
<ArrowRight className="ms-2 h-5 w-5" />
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
{/* Footer */}
|
||||
{/* ── Footer ── */}
|
||||
<footer className="border-t border-border bg-background py-12">
|
||||
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex flex-col md:flex-row justify-between items-center gap-6">
|
||||
@@ -396,17 +606,13 @@ export function LandingPage() {
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex gap-6 text-sm text-muted-foreground">
|
||||
<a className="hover:text-foreground transition-colors" href="#">
|
||||
{t("footer.privacy")}
|
||||
</a>
|
||||
<a className="hover:text-foreground transition-colors" href="#">
|
||||
{t("footer.terms")}
|
||||
</a>
|
||||
<a className="hover:text-foreground transition-colors" href="#">
|
||||
{t("footer.contact")}
|
||||
</a>
|
||||
<a className="hover:text-foreground transition-colors" href="#">{t("landing.footer.privacy")}</a>
|
||||
<a className="hover:text-foreground transition-colors" href="#">{t("landing.footer.terms")}</a>
|
||||
<a className="hover:text-foreground transition-colors" href="#">{t("landing.footer.contact")}</a>
|
||||
</div>
|
||||
<div className="text-muted-foreground text-sm">
|
||||
© {new Date().getFullYear()} Office Translator
|
||||
</div>
|
||||
<div className="text-muted-foreground text-sm">{t("footer.copyright")}</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
Reference in New Issue
Block a user