feat: rewrite all dashboard views with editorial design
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 1m29s

Translate page: editorial dropzone (rounded-[40px]), config panel,
progress stepper, download button, Momento promo banner.
Profile page: pill tabs, dark subscription card, usage bars, language grid.
Context page: preset grid (rounded-[32px]), instruction/glossary textareas.
API keys page: editorial-card with production key display.
Glossaries page: editorial-card grid with hover lift.
Pricing page: 5-column grid, colored headers, plan badges.

All pages use editorial design system: accent-pill, editorial-card,
premium-button, brand colors, dark mode support.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-16 12:54:29 +02:00
parent c2e9617045
commit 3938adf10c
7 changed files with 1506 additions and 993 deletions

View File

@@ -4,14 +4,13 @@ import { useState, useEffect } from "react";
import Link from "next/link";
import { useRouter, useSearchParams } from "next/navigation";
import {
Check, X, Zap, Building2, Crown, Sparkles, ArrowRight, ArrowLeft,
Star, Shield, Rocket, Users, Headphones, Lock, Globe,
Clock, ChevronDown, ChevronUp, Cpu, BarChart3, Infinity,
FileText, Layers, Brain, BadgeCheck, Gauge
Check, CheckCircle2, X, Zap, Building2, Crown, Sparkles, ArrowRight,
ArrowLeft, ChevronLeft, Star, Shield, Rocket, Users, Headphones, Lock,
Globe, Clock, ChevronDown, ChevronUp, Cpu, BarChart3, Infinity,
FileText, Layers, Brain, BadgeCheck, Gauge, Activity,
} from "lucide-react";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { cn } from "@/lib/utils";
import { API_BASE } from "@/lib/config";
import { ANNUAL_DISCOUNT_PERCENT } from "@/lib/pricing";
@@ -200,41 +199,41 @@ const STATIC_CREDITS: CreditPackage[] = [
];
/* ─────────────────────────────────────────────
Visual config by plan
Visual config by plan — editorial design
───────────────────────────────────────────── */
const PLAN_ICONS: Record<string, any> = {
free: Sparkles,
free: Star,
starter: Zap,
pro: Crown,
business: Building2,
enterprise: Rocket,
business: Globe,
enterprise: Shield,
};
const PLAN_COLORS: Record<string, { gradient: string; border: string; badge: string; button: string }> = {
free: { gradient: "from-slate-600 to-slate-700", border: "border-slate-700/50", badge: "bg-slate-700", button: "bg-slate-700 hover:bg-slate-600" },
starter: { gradient: "from-blue-600 to-blue-700", border: "border-blue-700/50", badge: "bg-blue-600", button: "bg-blue-600 hover:bg-blue-500" },
pro: { gradient: "from-violet-600 to-violet-700", border: "border-violet-500/60",badge: "bg-violet-600", button: "bg-violet-600 hover:bg-violet-500" },
business: { gradient: "from-emerald-600 to-emerald-700",border:"border-emerald-700/50",badge:"bg-emerald-600", button: "bg-emerald-600 hover:bg-emerald-500" },
enterprise: { gradient: "from-amber-600 to-amber-700", border: "border-amber-700/50", badge: "bg-amber-600", button: "bg-amber-600 hover:bg-amber-500" },
const PLAN_COLORS: Record<string, { header: string; iconColor: string; nameColor: string }> = {
free: { header: "bg-muted", iconColor: "text-foreground/20", nameColor: "text-foreground/40" },
starter: { header: "bg-foreground", iconColor: "text-white/20", nameColor: "text-white/50" },
pro: { header: "bg-accent", iconColor: "text-white/30", nameColor: "text-white/50" },
business: { header: "bg-foreground", iconColor: "text-accent/40", nameColor: "text-white/50" },
enterprise: { header: "bg-[#252525]", iconColor: "text-white/10", nameColor: "text-white/50" },
};
/** Avoids flash of static prices before the API responds on refresh. */
function PricingDataSkeleton() {
return (
<>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-5 gap-5">
<div className="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-5 gap-6">
{Array.from({ length: 5 }).map((_, i) => (
<div
key={i}
className="rounded-2xl border border-border/40 bg-card overflow-hidden animate-pulse"
className="rounded-[24px] border border-black/[0.08] bg-white overflow-hidden animate-pulse"
>
<div className="h-28 bg-muted/60" />
<div className="p-5 space-y-3">
<div className="h-48 bg-muted/60" />
<div className="p-8 space-y-3">
<div className="h-4 bg-muted rounded w-3/4" />
<div className="h-4 bg-muted rounded w-1/2" />
<div className="h-4 bg-muted rounded w-full" />
<div className="h-4 bg-muted rounded w-5/6" />
<div className="h-9 bg-muted rounded-lg mt-4" />
<div className="h-10 bg-muted rounded-2xl mt-4" />
</div>
</div>
))}
@@ -404,27 +403,28 @@ export default function PricingPage() {
return (
<div className="min-h-screen bg-background text-foreground">
{/* ── Top navigation ── */}
<div className="sticky top-0 z-40 border-b border-border/60 bg-background/85 backdrop-blur">
<div className="max-w-7xl mx-auto px-4 py-3 flex items-center justify-between gap-3">
{/* ── Top navigation — breadcrumb bar ── */}
<div className="max-w-[1400px] mx-auto px-4 pt-4">
<div className="flex justify-between items-center mb-20">
<button
onClick={() => router.back()}
className="inline-flex items-center gap-2 text-sm text-muted-foreground hover:text-foreground transition-colors"
className="flex items-center gap-3 text-[10px] font-black uppercase tracking-[0.4em] text-foreground/30 hover:text-foreground transition-all group"
>
<ArrowLeft className="w-4 h-4" />
<ChevronLeft size={16} className="group-hover:-translate-x-1 transition-transform" />
{t('pricing.nav.back')}
</button>
<div className="flex items-center gap-2">
<div className="flex gap-2 p-1.5 bg-muted rounded-full border border-black/5 shadow-inner">
<Link
href={isLoggedIn ? "/dashboard" : "/"}
className="px-3 py-1.5 rounded-lg text-sm bg-secondary hover:bg-secondary/80 text-secondary-foreground transition-colors"
className="px-6 py-2 rounded-full text-[9px] font-black uppercase tracking-widest text-foreground/40 hover:text-foreground transition-all"
>
{isLoggedIn ? "Dashboard" : t('pricing.nav.home')}
Dashboard
</Link>
{isLoggedIn && (
<Link
href="/dashboard/profile"
className="px-3 py-1.5 rounded-lg text-sm bg-accent/80 hover:bg-accent text-accent-foreground transition-colors"
className="px-6 py-2 bg-white rounded-full text-[9px] font-black uppercase tracking-widest text-foreground shadow-sm border border-black/5"
>
{t('pricing.nav.mySubscription')}
</Link>
@@ -438,185 +438,238 @@ export default function PricingPage() {
<div className={cn(
"fixed top-4 left-1/2 -translate-x-1/2 z-50 flex items-start gap-3 px-5 py-4 rounded-2xl shadow-2xl border max-w-lg w-full mx-4 backdrop-blur-sm",
toastMsg.type === 'ok'
? "bg-success/10 border-success/30 text-success"
: "bg-destructive/10 border-destructive/30 text-destructive"
? "bg-emerald-50 border-emerald-200 text-emerald-700 dark:bg-emerald-950/50 dark:border-emerald-800 dark:text-emerald-300"
: "bg-red-50 border-red-200 text-red-700 dark:bg-red-950/50 dark:border-red-800 dark:text-red-300"
)}>
<span className="text-lg">{toastMsg.type === 'ok' ? '✓' : '✕'}</span>
<p className="text-sm flex-1">{toastMsg.text}</p>
<button onClick={() => setToastMsg(null)} className="text-muted-foreground hover:text-foreground text-lg leading-none"></button>
<button onClick={() => setToastMsg(null)} className="text-muted-foreground hover:text-foreground text-lg leading-none">&times;</button>
</div>
)}
{/* ── Header ── */}
<div className="max-w-7xl mx-auto px-4 pt-20 pb-12 text-center">
<div className="inline-flex items-center gap-2 px-4 py-1.5 rounded-full bg-accent/10 border border-accent/20 text-accent text-sm font-medium mb-6">
<Cpu className="w-4 h-4" />
{t('pricing.header.badge')}
</div>
<h1 className="text-5xl md:text-6xl font-bold tracking-tight mb-4 bg-gradient-to-r from-foreground via-accent/80 to-accent bg-clip-text text-transparent">
{t('pricing.header.title')}
<div className="max-w-[1400px] mx-auto px-4 text-center mb-20">
<span className="inline-flex items-center gap-2 px-4 py-1.5 rounded-full border border-black/5 mb-6">
<div className="w-2 h-2 bg-accent rounded-full animate-pulse" />
<span className="text-[10px] font-black tracking-[0.3em] opacity-40">{t('pricing.header.badge')}</span>
</span>
<h1 className="text-5xl md:text-7xl font-black uppercase tracking-tighter mb-6 leading-none">
{t('pricing.header.title').split(' ').slice(0, -2).join(' ')}{" "}
<span className="text-accent">
{t('pricing.header.title').split(' ').slice(-2).join(' ')}
</span>
</h1>
<p className="text-xl text-muted-foreground max-w-2xl mx-auto mb-8">
<p className="text-foreground/40 font-medium text-xl max-w-2xl mx-auto leading-relaxed">
{t('pricing.header.subtitle')}
</p>
</div>
{/* Monthly / Yearly toggle */}
<div className="inline-flex items-center gap-3 bg-muted/60 border border-border/50 rounded-full p-1.5">
{/* ── Monthly / Yearly toggle ── */}
<div className="flex items-center justify-center gap-10 mb-20">
<div className="flex p-1 bg-muted rounded-full border border-black/5 shadow-inner px-2">
<button
onClick={() => setIsYearly(false)}
className={cn(
"px-5 py-2 rounded-full text-sm font-medium transition-all",
!isYearly ? "bg-foreground text-background shadow" : "text-muted-foreground hover:text-foreground"
)}
className={`px-8 py-3 rounded-full text-[10px] font-black uppercase tracking-widest transition-all ${!isYearly ? 'bg-foreground text-white shadow-xl' : 'text-foreground/60 hover:text-foreground'}`}
>
{t('pricing.billing.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-foreground text-background shadow" : "text-muted-foreground hover:text-foreground"
)}
className={`px-8 py-3 rounded-full text-[10px] font-black uppercase tracking-widest transition-all ${isYearly ? 'bg-foreground text-white shadow-xl' : 'text-foreground/60 hover:text-foreground'}`}
>
{t('pricing.billing.yearly')}
<span className="bg-success text-success-foreground text-xs px-1.5 py-0.5 rounded-full">
{annualDiscountPercent} %
</span>
<span className={`ml-2 transition-colors ${isYearly ? 'text-accent' : 'text-accent/60'}`}>&minus;{annualDiscountPercent} %</span>
</button>
</div>
</div>
{/* ── Plan cards (+ comparison + credits): skeleton until API responds to avoid stale price flash ── */}
<div className="max-w-7xl mx-auto px-4 pb-20">
{/* ── Plan cards (skeleton until API responds) ── */}
<div className="max-w-[1400px] mx-auto px-4 pb-20">
{!pricingLoaded ? (
<PricingDataSkeleton />
) : (
<>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-5 gap-5">
<div className="grid md:grid-cols-3 lg:grid-cols-5 gap-6 items-stretch">
{plans.map((plan) => {
const Icon = PLAN_ICONS[plan.id] ?? Sparkles;
const colors = PLAN_COLORS[plan.id] ?? PLAN_COLORS.starter;
const price = displayPrice(plan);
const isCurrent = currentPlan === plan.id;
const isEnterprise = plan.id === "enterprise";
const isFree = plan.id === "free";
return (
<div
key={plan.id}
className={cn(
"relative flex flex-col rounded-2xl border bg-card backdrop-blur transition-all duration-300",
"hover:scale-[1.02] hover:shadow-2xl",
colors.border,
plan.popular && "ring-2 ring-violet-500/50 shadow-violet-500/20 shadow-xl"
"flex flex-col bg-white dark:bg-card rounded-[24px] border border-black/[0.08] dark:border-border/40 overflow-hidden transition-all duration-500 hover:shadow-[0_20px_50px_rgba(0,0,0,0.08)] hover:-translate-y-2 group",
plan.popular && "border-accent/30 ring-4 ring-accent/5"
)}
>
{/* Popular badge */}
{plan.badge && (
<div className={cn(
"absolute -top-3 left-1/2 -translate-x-1/2 px-3 py-1 rounded-full text-xs font-bold text-white",
colors.badge
)}>
{t(plan.badge)}
</div>
)}
{isCurrent && (
<div className="absolute -top-3 right-4 px-3 py-1 rounded-full text-xs font-bold bg-emerald-600 text-white flex items-center gap-1">
<BadgeCheck className="w-3 h-3" /> {t('pricing.card.myPlan')}
</div>
)}
{/* Header */}
<div className={cn("p-5 rounded-t-2xl bg-gradient-to-br", colors.gradient)}>
<div className="flex items-center gap-2 mb-3">
<div className="p-1.5 bg-white/10 rounded-lg">
<Icon className="w-5 h-5 text-white" />
{/* ── Header section ── */}
<div className={cn("p-8 text-white relative h-48 flex flex-col justify-end", colors.header)}>
{/* Badges for popular/current plan */}
{plan.popular && (
<div className="absolute top-0 right-0 p-3 flex gap-2">
{plan.badge && (
<span className="bg-foreground/20 backdrop-blur-md text-white text-[8px] font-black uppercase tracking-widest px-3 py-1 rounded-full border border-white/20 shadow-lg">
{t(plan.badge)}
</span>
)}
{isCurrent && (
<span className="bg-foreground/40 backdrop-blur-md text-white text-[8px] font-black uppercase tracking-widest px-3 py-1 rounded-full border border-white/20 shadow-lg flex items-center gap-1">
<div className="w-1.5 h-1.5 bg-accent rounded-full animate-pulse" /> {t('pricing.card.myPlan')}
</span>
)}
</div>
<span className="font-bold text-white">{t(plan.name)}</span>
</div>
{isEnterprise ? (
<div className="text-3xl font-bold text-white">{t('pricing.card.onRequest')}</div>
) : price === 0 ? (
<div className="text-3xl font-bold text-white">{t('pricing.card.free')}</div>
) : (
<div className="flex items-end gap-1">
<span className="text-3xl font-bold text-white">{price} </span>
<span className="text-white/70 text-sm pb-1">{t('pricing.card.perMonth')}</span>
)}
{plan.badge && !plan.popular && (
<div className="absolute top-0 right-0 p-3">
<span className="bg-white/10 backdrop-blur-md text-white text-[8px] font-black uppercase tracking-widest px-3 py-1 rounded-full border border-white/10">
{t(plan.badge)}
</span>
</div>
)}
{/* "My Plan" badge for current non-popular plan */}
{isCurrent && !plan.popular && (
<div className="absolute top-0 right-0 p-3">
<span className="bg-foreground/40 backdrop-blur-md text-white text-[8px] font-black uppercase tracking-widest px-3 py-1 rounded-full border border-white/20 shadow-lg flex items-center gap-1">
<div className="w-1.5 h-1.5 bg-accent rounded-full animate-pulse" /> {t('pricing.card.myPlan')}
</span>
</div>
)}
{/* Icon + plan name */}
<div className="flex items-center gap-3 mb-4">
<Icon size={20} className={colors.iconColor} />
<span className={cn("text-sm font-black uppercase tracking-widest", isFree ? "text-foreground/40" : colors.nameColor)}>
{t(plan.name)}
</span>
</div>
{/* Price */}
<div className="flex items-baseline gap-2">
{isEnterprise ? (
<h3 className={cn("text-3xl font-black uppercase tracking-tighter", isFree ? "text-foreground" : "text-white")}>
{t('pricing.card.onRequest')}
</h3>
) : price === 0 ? (
<h3 className="text-3xl font-black uppercase tracking-tighter text-foreground">
{t('pricing.card.free')}
</h3>
) : (
<>
<h3 className="text-3xl font-black uppercase tracking-tighter text-white">{price} &euro;</h3>
<span className="text-[10px] font-bold uppercase tracking-widest text-white/40">{t('pricing.card.perMonth')}</span>
</>
)}
</div>
{/* Yearly billing note */}
{isYearly && plan.price_yearly > 0 && (
<div className="text-white/70 text-xs mt-1">
<div className="text-white/70 text-[10px] mt-1">
{t('pricing.card.billedYearly', { price: plan.price_yearly.toFixed(2) })}
</div>
)}
<p className="text-white/60 text-xs mt-2">{t(plan.description || '')}</p>
{/* Description */}
<p className={cn("text-[10px] font-medium uppercase mt-3 tracking-widest leading-relaxed", isFree ? "text-foreground/40" : "text-white/60")}>
{t(plan.description || '')}
</p>
</div>
{/* Features */}
<div className="flex-1 p-5 space-y-2.5">
{/* Key stats */}
<div className="grid grid-cols-1 gap-2 mb-3">
<Stat
icon={<FileText className="w-3.5 h-3.5" />}
label={t('pricing.card.documents')}
value={plan.docs_per_month === -1 ? t('pricing.card.unlimited') : `${plan.docs_per_month} ${t('pricing.card.perMonthStat')}`}
/>
<Stat
icon={<Layers className="w-3.5 h-3.5" />}
label={t('pricing.card.pagesMax')}
value={plan.max_pages_per_doc === -1 ? t('pricing.card.unlimited') : `${plan.max_pages_per_doc} ${t('pricing.card.perDoc')}`}
/>
{/* ── Content section ── */}
<div className="p-8 flex-1 flex flex-col">
{/* Metrics */}
<div className="space-y-2 mb-10">
<div className="flex justify-between items-center py-2 border-b border-black/[0.03] dark:border-border/20">
<div className="flex items-center gap-2">
<FileText size={12} className="text-foreground/20" />
<span className="text-[9px] font-black uppercase tracking-widest text-foreground/40">{t('pricing.card.documents')}</span>
</div>
<span className="text-[10px] font-black uppercase text-foreground">
{plan.docs_per_month === -1 ? t('pricing.card.unlimited') : `${plan.docs_per_month} ${t('pricing.card.perMonthStat')}`}
</span>
</div>
<div className="flex justify-between items-center py-2 border-b border-black/[0.03] dark:border-border/20">
<div className="flex items-center gap-2">
<Layers size={12} className="text-foreground/20" />
<span className="text-[9px] font-black uppercase tracking-widest text-foreground/40">{t('pricing.card.pagesMax')}</span>
</div>
<span className="text-[10px] font-black uppercase text-foreground">
{plan.max_pages_per_doc === -1 ? t('pricing.card.unlimited') : `${plan.max_pages_per_doc} ${t('pricing.card.perDoc')}`}
</span>
</div>
{plan.ai_translation && (
<Stat
icon={<Brain className="w-3.5 h-3.5 text-violet-400" />}
label={t('pricing.card.aiTranslation')}
value={
plan.ai_tier === "essential" ? t('pricing.card.aiEssential') :
plan.ai_tier === "premium" ? t('pricing.card.aiEssentialPremium') : t('pricing.card.aiCustom')
}
highlight
/>
<div className={cn(
"flex justify-between items-center py-3 px-3 rounded-lg mt-2",
plan.ai_tier === "essential" ? "bg-accent/5" :
plan.ai_tier === "premium" ? "bg-foreground/5" :
"bg-black/5 dark:bg-border/20"
)}>
<div className="flex items-center gap-2">
<Activity size={12} className={
plan.ai_tier === "essential" ? "text-accent/40" :
"text-foreground/20"
} />
<span className={cn(
"text-[9px] font-black uppercase tracking-widest",
plan.ai_tier === "essential" ? "text-accent/60" :
"text-foreground/40"
)}>{t('pricing.card.aiTranslation')}</span>
</div>
<span className={cn(
"text-[9px] font-black uppercase",
plan.ai_tier === "essential" ? "text-accent" :
plan.ai_tier === "premium" ? "text-foreground" :
"text-foreground"
)}>
{plan.ai_tier === "essential" ? t('pricing.card.aiEssential') :
plan.ai_tier === "premium" ? t('pricing.card.aiEssentialPremium') :
t('pricing.card.aiCustom')}
</span>
</div>
)}
</div>
<div className="border-t border-border/40 pt-3 space-y-2">
{/* Features list */}
<ul className="space-y-4 mb-12 flex-1">
{plan.features.map((feat, i) => (
<div key={i} className="flex items-start gap-2">
<Check className="w-4 h-4 text-emerald-500 flex-shrink-0 mt-0.5" />
<span className="text-muted-foreground text-xs leading-snug">{t(feat)}</span>
</div>
<li key={i} className="flex items-start gap-3">
<div className="w-4 h-4 rounded-full bg-accent/10 flex items-center justify-center shrink-0 mt-0.5">
<CheckCircle2 size={10} className="text-accent" />
</div>
<span className="text-[10px] font-bold text-foreground/60 leading-normal">{t(feat)}</span>
</li>
))}
</div>
</div>
</ul>
{/* CTA */}
<div className="p-5 pt-0">
{/* CTA */}
{isCurrent ? (
<Button
variant="outline"
className="w-full border-success/50 text-success hover:bg-success/10"
onClick={() => router.push("/dashboard/profile")}
<Link
href="/dashboard/profile"
className="w-full py-4 rounded-2xl text-[11px] font-black uppercase tracking-widest transition-all flex items-center justify-center gap-3 border shadow-sm hover:shadow-xl active:scale-95 bg-muted text-foreground border-black/5 hover:bg-foreground hover:text-white"
>
<BadgeCheck className="w-4 h-4 me-1" /> {t('pricing.card.managePlan')}
</Button>
) : plan.id === "free" && !currentPlan ? (
<Button
variant="outline"
className="w-full border-border text-muted-foreground hover:bg-muted/30"
onClick={() => router.push("/auth/register")}
{t('pricing.card.managePlan')}
<ArrowRight size={14} className="opacity-40" />
</Link>
) : isFree && !currentPlan ? (
<Link
href="/auth/register"
className="w-full py-4 rounded-2xl text-[11px] font-black uppercase tracking-widest transition-all flex items-center justify-center gap-3 border shadow-sm hover:shadow-xl active:scale-95 bg-foreground text-white border-transparent hover:bg-accent"
>
{t('pricing.card.startFree')}
</Button>
<ArrowRight size={14} className="opacity-40" />
</Link>
) : (
<button
onClick={() => handleSubscribe(plan.id)}
disabled={loadingPlanId !== null}
className={cn(
"w-full py-2.5 px-4 rounded-xl text-sm font-semibold text-white transition-all flex items-center justify-center gap-2",
colors.button,
"w-full py-4 rounded-2xl text-[11px] font-black uppercase tracking-widest transition-all flex items-center justify-center gap-3 border shadow-sm hover:shadow-xl active:scale-95",
plan.popular
? "bg-muted text-foreground border-black/5 hover:bg-foreground hover:text-white"
: "bg-foreground text-white border-transparent hover:bg-accent",
loadingPlanId !== null && "opacity-70 cursor-not-allowed"
)}
>
@@ -631,7 +684,7 @@ export default function PricingPage() {
) : (
<>
{isEnterprise ? t('pricing.card.contactUs') : t('pricing.card.choosePlan')}
<ArrowRight className="w-4 h-4" />
<ArrowRight size={14} className="opacity-40" />
</>
)}
</button>
@@ -719,7 +772,7 @@ export default function PricingPage() {
)}
<div className="text-2xl font-bold text-foreground">{pkg.credits}</div>
<div className="text-muted-foreground text-xs mb-3">{t('pricing.credits.unit')}</div>
<div className="text-xl font-bold text-foreground">{pkg.price} </div>
<div className="text-xl font-bold text-foreground">{pkg.price} &euro;</div>
<div className="text-muted-foreground text-xs">{(pkg.price_per_credit * 100).toFixed(0)} {t('pricing.credits.centsPerCredit')}</div>
<button className="mt-3 w-full py-1.5 rounded-lg bg-muted hover:bg-muted/80 text-foreground text-xs transition-all">
{t('pricing.credits.buy')}
@@ -766,7 +819,7 @@ export default function PricingPage() {
<div className="flex flex-wrap gap-2 text-xs">
<span className="px-2 py-1 bg-muted rounded">{t('pricing.aiModels.essential.context')}</span>
<span className="px-2 py-1 bg-muted rounded">$0.25/$0.38 per 1M</span>
<span className="px-2 py-1 bg-success/10 text-success rounded">{t('pricing.aiModels.essential.value')}</span>
<span className="px-2 py-1 bg-emerald-500/10 text-emerald-600 dark:text-emerald-400 rounded">{t('pricing.aiModels.essential.value')}</span>
</div>
</div>
<div className="p-5 rounded-xl bg-card border border-accent/30">
@@ -840,17 +893,3 @@ export default function PricingPage() {
</div>
);
}
/* ── Sub-components ── */
function Stat({ icon, label, value, highlight }: { icon: React.ReactNode; label: string; value: string; highlight?: boolean }) {
return (
<div className={cn(
"flex items-center gap-2 px-3 py-2 rounded-lg text-xs",
highlight ? "bg-accent/10 border border-accent/20" : "bg-muted/40 border border-border/30"
)}>
<span className={highlight ? "text-accent" : "text-muted-foreground"}>{icon}</span>
<span className="text-muted-foreground">{label} :</span>
<span className={cn("font-medium ml-auto", highlight ? "text-accent" : "text-foreground")}>{value}</span>
</div>
);
}