feat(ui): vague 4 — la zone de dépôt répond, l'or devient lisible, tarifs binaires, avant/après réel
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2m58s

Zone de dépôt : le contour s'allume en doré et la carte s'agrandit
quand on la survole avec un fichier (l'information existait, elle
n'était jamais affichée).

Or lisible : nouveau jeton « or encre » (#8B6F47) pour les textes,
l'or clair reste aux traits, fonds et au mode sombre ; 52 textes dorés
convertis, pastille comprises ; plus aucun texte sous 10 px
(8,5 px → 11 px dans le sélecteur de moteurs).

Tarifs : le choix redevient binaire — les trois abonnements payants en
grandes cartes, le gratuit en ligne discrète au-dessus, le sur mesure
en ligne dorée dessous. Le tableau comparatif complet reste dessous.

Accueil : le mur de six cartes génériques est remplacé par un vrai
avant/après — une page « Cahier des charges — Traitement d'air » à
côté de sa traduction anglaise, structure identique au mot près
(terme technique en gras des deux côtés), sceau « Même mise en page,
mot pour mot » entre les deux, et trois preuves précises (SmartArt
reconstruits, séries de graphiques traduites, tables des matières
régénérées) à la place des promesses vagues.
This commit is contained in:
2026-08-30 23:27:53 +02:00
parent 9d5b5ce9c3
commit 3f45ccdf50
14 changed files with 286 additions and 86 deletions

View File

@@ -272,7 +272,7 @@ export function GlossarySelector({ sourceLang, targetLang, isPro, mode, glossary
>
<div className="flex justify-between items-center">
<div className="flex items-center gap-2">
<BookOpen size={14} className="text-brand-accent shrink-0" />
<BookOpen size={14} className="text-brand-goldink dark:text-brand-accent shrink-0" />
<span className="text-xs font-black uppercase tracking-[0.1em] text-brand-dark dark:text-white truncate">
{t('translate.glossary.title') || 'Glossaire & Terminologie'}
</span>
@@ -403,7 +403,7 @@ export function GlossarySelector({ sourceLang, targetLang, isPro, mode, glossary
onClick={() => setFilterByLang(!filterByLang)}
className={cn(
"text-[10px] font-bold px-2 py-0.5 rounded transition-colors cursor-pointer",
filterByLang ? "bg-brand-accent/10 text-brand-accent" : "bg-brand-dark/10 dark:bg-white/10 text-brand-dark/50 dark:text-white/50"
filterByLang ? "bg-brand-accent/10 text-brand-goldink dark:text-brand-accent" : "bg-brand-dark/10 dark:bg-white/10 text-brand-dark/50 dark:text-white/50"
)}
>
{filterByLang ? t('translate.glossary.active') || 'Actif' : t('translate.glossary.inactive') || 'Inactif'}
@@ -431,7 +431,7 @@ export function GlossarySelector({ sourceLang, targetLang, isPro, mode, glossary
className={cn(
"w-full text-left px-2.5 py-2 rounded-lg transition-colors flex items-center justify-between cursor-pointer",
isSelected
? 'bg-brand-accent/5 text-brand-accent'
? 'bg-brand-accent/5 text-brand-goldink dark:text-brand-accent'
: 'hover:bg-brand-muted dark:hover:bg-white/5 text-brand-dark/70 dark:text-white/70'
)}
>
@@ -441,7 +441,7 @@ export function GlossarySelector({ sourceLang, targetLang, isPro, mode, glossary
{flag} {g.target_language === 'multi' ? `🌐 ${t('translate.glossary.multilingual') || 'MULTILINGUE'}` : getFlag(g.target_language || targetLang)} {g.terms_count} {t('translate.glossary.terms') || 'termes'}
</span>
</div>
{isSelected && <Check size={12} className="text-brand-accent shrink-0" />}
{isSelected && <Check size={12} className="text-brand-goldink dark:text-brand-accent shrink-0" />}
</button>
);
})}
@@ -480,7 +480,7 @@ export function GlossarySelector({ sourceLang, targetLang, isPro, mode, glossary
className={cn(
"w-full text-left px-2.5 py-2 rounded-lg transition-colors flex items-center justify-between cursor-pointer",
isAlreadySelected
? 'bg-brand-accent/5 text-brand-accent'
? 'bg-brand-accent/5 text-brand-goldink dark:text-brand-accent'
: 'hover:bg-brand-muted dark:hover:bg-white/5 text-brand-dark/70 dark:text-white/70'
)}
>
@@ -493,9 +493,9 @@ export function GlossarySelector({ sourceLang, targetLang, isPro, mode, glossary
</span>
</div>
{isImporting ? (
<Loader2 size={12} className="animate-spin text-brand-accent shrink-0" />
<Loader2 size={12} className="animate-spin text-brand-goldink dark:text-brand-accent shrink-0" />
) : isAlreadySelected ? (
<Check size={12} className="text-brand-accent shrink-0" />
<Check size={12} className="text-brand-goldink dark:text-brand-accent shrink-0" />
) : null}
</button>
);
@@ -547,7 +547,7 @@ export function GlossarySelector({ sourceLang, targetLang, isPro, mode, glossary
{isLoadingDetail ? (
<div className="flex items-center justify-center py-3 gap-1.5 text-xs text-brand-dark/40 dark:text-white/30 font-light">
<Loader2 size={12} className="animate-spin text-brand-accent" /> {t('translate.glossary.loading') || 'Chargement...'}
<Loader2 size={12} className="animate-spin text-brand-goldink dark:text-brand-accent" /> {t('translate.glossary.loading') || 'Chargement...'}
</div>
) : selectedGlossaryDetail?.terms && selectedGlossaryDetail.terms.length > 0 ? (
<div className="grid grid-cols-1 gap-1 max-h-[120px] overflow-y-auto pr-1">

View File

@@ -112,7 +112,7 @@ function Combobox({
)}
>
<span className="truncate normal-case">{label || placeholder}</span>
<ChevronDown className={cn('size-3.5 shrink-0 text-brand-accent transition-transform ms-2', open && 'rotate-180')} />
<ChevronDown className={cn('size-3.5 shrink-0 text-brand-goldink dark:text-brand-accent transition-transform ms-2', open && 'rotate-180')} />
</button>
{open && (
<div
@@ -145,12 +145,12 @@ function Combobox({
className={cn(
'flex w-full items-center justify-between rounded-lg px-2.5 py-2 text-xs font-bold uppercase tracking-wider transition-colors cursor-pointer',
value === lang.code
? 'bg-brand-accent/10 text-brand-accent'
? 'bg-brand-accent/10 text-brand-goldink dark:text-brand-accent'
: 'text-brand-dark/70 dark:text-white/70 hover:bg-brand-muted dark:hover:bg-white/5'
)}
>
<span className="truncate">{lang.name}</span>
{value === lang.code && <Check className="size-3.5 text-brand-accent shrink-0" />}
{value === lang.code && <Check className="size-3.5 text-brand-goldink dark:text-brand-accent shrink-0" />}
</button>
))}
</div>
@@ -213,7 +213,7 @@ export default function LanguageSelector({
className={cn(
'flex size-7 items-center justify-center rounded-xl transition-all cursor-pointer',
canSwap
? 'text-brand-dark/50 dark:text-white/50 hover:text-brand-accent hover:bg-brand-muted/50 dark:hover:bg-white/5'
? 'text-brand-dark/50 dark:text-white/50 hover:text-brand-goldink dark:text-brand-accent hover:bg-brand-muted/50 dark:hover:bg-white/5'
: 'cursor-not-allowed opacity-30'
)}
title={t('langSelector.swap')}

View File

@@ -70,7 +70,7 @@ const LLM_THEMES_FACTORY = (t: (k: string) => string): Record<string, CardTheme>
const makeDefaultLlmTheme = (t: (k: string) => string): CardTheme => ({
badge: t('providerTheme.default.badge'),
subBadge: t('providerTheme.default.subBadge'),
accentClass: 'border-brand-accent/30 text-brand-accent bg-brand-accent/5',
accentClass: 'border-brand-accent/30 text-brand-goldink dark:text-brand-accent bg-brand-accent/5',
glowClass: 'from-brand-accent/10 to-transparent',
descriptionOverride: t('providerTheme.default.desc')
});
@@ -118,7 +118,7 @@ export function ProviderSelector({
if (isLoadingProviders) {
return (
<div className="flex items-center gap-2 text-sm text-brand-dark/50 dark:text-white/40 py-4">
<Loader2 className="size-4 animate-spin text-brand-accent" />
<Loader2 className="size-4 animate-spin text-brand-goldink dark:text-brand-accent" />
<span>{t('dashboard.translate.provider.loading')}</span>
</div>
);
@@ -152,7 +152,7 @@ export function ProviderSelector({
<div className="flex items-center justify-between">
<span className={cn(
"text-[10px] font-black uppercase tracking-tight truncate flex-1",
isSelected ? 'text-brand-accent' : 'text-brand-dark/60 dark:text-white/60'
isSelected ? 'text-brand-goldink dark:text-brand-accent' : 'text-brand-dark/60 dark:text-white/60'
)}>
{t('providerSelector.standard')}
</span>
@@ -188,7 +188,7 @@ export function ProviderSelector({
<div className="flex items-center justify-between mb-0.5">
<span className={cn(
"text-[9px] font-black uppercase tracking-tight truncate flex-1",
isSelected ? 'text-brand-accent' : 'text-brand-dark/40 dark:text-white/40'
isSelected ? 'text-brand-goldink dark:text-brand-accent' : 'text-brand-dark/40 dark:text-white/40'
)}>
{theme.badge}
</span>
@@ -198,7 +198,7 @@ export function ProviderSelector({
<span className="text-xs font-bold text-brand-dark dark:text-white block leading-none mb-0.5 truncate">
{displayLabel}
</span>
<span className="text-[8.5px] text-brand-dark/40 dark:text-white/45 uppercase font-bold block leading-none truncate">
<span className="text-[11px] text-brand-dark/40 dark:text-white/45 uppercase font-bold block leading-none truncate">
{theme.subBadge}
</span>
</button>
@@ -238,7 +238,7 @@ export function ProviderSelector({
: 'text-brand-dark/50 dark:text-white/40 hover:text-brand-dark dark:hover:text-white'
)}
>
<Sparkles className={cn("size-3", activeTab === 'llm' ? 'text-brand-accent' : 'text-brand-dark/35 dark:text-white/30')} />
<Sparkles className={cn("size-3", activeTab === 'llm' ? 'text-brand-goldink dark:text-brand-accent' : 'text-brand-dark/35 dark:text-white/30')} />
{t('dashboard.translate.provider.tabLLM')}
{!isPro && <Lock className="size-2.5 opacity-60 ml-0.5" />}
</button>
@@ -279,7 +279,7 @@ export function ProviderSelector({
<p className="text-[10px] text-brand-dark/60 dark:text-white/60 leading-normal font-light">
<span className="font-bold text-brand-dark dark:text-white">{meta?.labelOverride || activeP.label} : </span>
{meta?.descriptionOverride || activeP.description}
<span className="block mt-1 font-bold text-brand-accent">{t('providerSelector.costOne')}</span>
<span className="block mt-1 font-bold text-brand-goldink dark:text-brand-accent">{t('providerSelector.costOne')}</span>
</p>
) : null;
})()
@@ -291,7 +291,7 @@ export function ProviderSelector({
<p className="text-[10px] text-brand-dark/60 dark:text-white/60 leading-normal font-light">
<span className="font-bold text-brand-dark dark:text-white">{activeP.label} : </span>
{theme.descriptionOverride} <span className="opacity-50 text-[9px] font-mono">({activeP.model || 'default'})</span>
<span className="block mt-1 font-bold text-brand-accent">
<span className="block mt-1 font-bold text-brand-goldink dark:text-brand-accent">
{activeP.id === 'openrouter_premium' ? t('providerSelector.costFive') : t('providerSelector.costOne')}
</span>
</p>
@@ -305,7 +305,7 @@ export function ProviderSelector({
{/* Pro upgrade banner when llm is active and user is not pro */}
{!isPro && activeTab === 'llm' && (
<div className="p-3.5 rounded-xl border border-brand-accent/20 bg-brand-accent/[0.02] dark:bg-brand-accent/[0.01] text-center flex flex-col items-center gap-1.5">
<Sparkles className="size-3.5 text-brand-accent animate-pulse" />
<Sparkles className="size-3.5 text-brand-goldink dark:text-brand-accent animate-pulse" />
<span className="text-[11px] font-bold text-brand-dark dark:text-white leading-none">
{t('dashboard.translate.provider.llmDivider')}
</span>

View File

@@ -358,7 +358,10 @@ export default function TranslatePage() {
{/* ── UPLOAD STATE: Editorial Dropzone ──────────────── */}
{showUpload && (
<div
className="relative bg-white border-2 border-dashed border-brand-accent/15 dark:border-white/10 rounded-[32px] p-12 flex flex-col items-center justify-center text-center group cursor-pointer hover:border-brand-accent/40 dark:hover:border-brand-accent/40 hover:bg-brand-muted/10 dark:hover:bg-brand-muted/5 transition-all shadow-editorial dark:bg-[#141414] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-accent/60 focus-visible:border-brand-accent/60"
className={cn(
'relative bg-white border-2 border-dashed border-brand-accent/15 dark:border-white/10 rounded-[32px] p-12 flex flex-col items-center justify-center text-center group cursor-pointer hover:border-brand-accent/40 dark:hover:border-brand-accent/40 hover:bg-brand-muted/10 dark:hover:bg-brand-muted/5 transition-all shadow-editorial dark:bg-[#141414] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-accent/60 focus-visible:border-brand-accent/60',
upload.isDragOver && 'border-brand-accent bg-brand-accent/10 scale-[1.01] shadow-lg'
)}
role="button"
tabIndex={0}
aria-label={t('translate.upload.ariaDropzone')}
@@ -378,7 +381,7 @@ export default function TranslatePage() {
{t('translate.upload.nativeFormat')}
</div>
<div className="w-16 h-16 bg-brand-muted dark:bg-white/5 rounded-2xl flex items-center justify-center text-brand-accent group-hover:scale-105 group-hover:bg-brand-dark dark:group-hover:bg-brand-accent group-hover:text-white dark:group-hover:text-brand-dark transition-all duration-300 mb-6 shadow-sm">
<div className="w-16 h-16 bg-brand-muted dark:bg-white/5 rounded-2xl flex items-center justify-center text-brand-goldink dark:text-brand-accent group-hover:scale-105 group-hover:bg-brand-dark dark:group-hover:bg-brand-accent group-hover:text-white dark:group-hover:text-brand-dark transition-all duration-300 mb-6 shadow-sm">
<Upload size={24} />
</div>
@@ -444,7 +447,7 @@ export default function TranslatePage() {
<button
onClick={handleDownloadAll}
disabled={!batch.items.some((i) => i.status === 'completed' && i.jobId)}
className="rounded-xl border border-brand-accent/30 px-4 py-2 text-[10px] font-bold uppercase tracking-wider text-brand-accent transition-colors hover:bg-brand-accent/10 disabled:opacity-40"
className="rounded-xl border border-brand-accent/30 px-4 py-2 text-[10px] font-bold uppercase tracking-wider text-brand-goldink dark:text-brand-accent transition-colors hover:bg-brand-accent/10 disabled:opacity-40"
>
<Download size={11} className="mr-1 inline" /> {t('translate.batch.downloadAll')}
</button>
@@ -465,7 +468,7 @@ export default function TranslatePage() {
className="flex items-center gap-3 rounded-2xl border border-black/5 bg-brand-muted/30 px-4 py-3 dark:border-white/5 dark:bg-white/5"
>
{item.status === 'processing' ? (
<Loader2 className="size-4 shrink-0 animate-spin text-brand-accent" />
<Loader2 className="size-4 shrink-0 animate-spin text-brand-goldink dark:text-brand-accent" />
) : item.status === 'completed' ? (
<CheckCircle2 className="size-4 shrink-0 text-emerald-500" />
) : item.status === 'failed' ? (
@@ -501,7 +504,7 @@ export default function TranslatePage() {
</button>
<Link
href={`/dashboard/reviews/${item.jobId}`}
className="rounded-lg border border-brand-accent/25 px-2.5 py-1.5 text-[10px] font-bold uppercase tracking-wider text-brand-accent"
className="rounded-lg border border-brand-accent/25 px-2.5 py-1.5 text-[10px] font-bold uppercase tracking-wider text-brand-goldink dark:text-brand-accent"
>
{t('translate.recent.review')}
</Link>
@@ -531,7 +534,7 @@ export default function TranslatePage() {
{recentJobs.slice(0, 6).map((job) => (
<li key={job.jobId} className="flex items-center justify-between gap-3 py-3">
<span className="flex min-w-0 items-center gap-2.5 text-xs font-semibold text-brand-dark dark:text-white">
<FileText className="size-3.5 shrink-0 text-brand-accent" />
<FileText className="size-3.5 shrink-0 text-brand-goldink dark:text-brand-accent" />
<span className="truncate">{job.fileName || job.jobId}</span>
</span>
<span className="flex shrink-0 items-center gap-1.5">
@@ -544,7 +547,7 @@ export default function TranslatePage() {
</button>
<Link
href={`/dashboard/reviews/${job.jobId}`}
className="rounded-lg px-3 py-1.5 text-[10px] font-bold uppercase tracking-wider text-brand-accent border border-brand-accent/25 hover:bg-brand-accent/10 transition-colors"
className="rounded-lg px-3 py-1.5 text-[10px] font-bold uppercase tracking-wider text-brand-goldink dark:text-brand-accent border border-brand-accent/25 hover:bg-brand-accent/10 transition-colors"
>
{t('translate.recent.review')}
</Link>
@@ -608,9 +611,9 @@ export default function TranslatePage() {
{submit.isSubmitting ? (
<><Loader2 className="size-4 animate-spin" /> {t('translate.submit')}</>
) : upload.files.length > 1 ? (
<>{t('translate.startBatch', { count: upload.files.length })} <ArrowRight size={13} className="text-brand-accent" /></>
<>{t('translate.startBatch', { count: upload.files.length })} <ArrowRight size={13} className="text-brand-goldink dark:text-brand-accent" /></>
) : (
<>{t('translate.startTranslation')} <ArrowRight size={13} className={upload.files.length > 0 ? 'text-brand-accent' : 'opacity-20'} /></>
<>{t('translate.startTranslation')} <ArrowRight size={13} className={upload.files.length > 0 ? 'text-brand-goldink dark:text-brand-accent' : 'opacity-20'} /></>
)}
</button>
@@ -623,10 +626,10 @@ export default function TranslatePage() {
<div className="flex justify-between gap-4 text-[11px] font-semibold uppercase tracking-[0.06em] text-brand-dark/55 dark:text-white/55 border-t border-black/5 dark:border-white/5 pt-4">
<span className="flex items-center gap-1.5">
<ShieldCheck size={13} className="text-brand-accent" /> {t('landing.translate.zeroRetention') || 'Rétention Zéro'}
<ShieldCheck size={13} className="text-brand-goldink dark:text-brand-accent" /> {t('landing.translate.zeroRetention') || 'Rétention Zéro'}
</span>
<span className="flex items-center gap-1.5">
<Clock size={13} className="text-brand-accent" /> {t('landing.translate.filesDeleted') || 'Fichiers supprimés post-traitement'}
<Clock size={13} className="text-brand-goldink dark:text-brand-accent" /> {t('landing.translate.filesDeleted') || 'Fichiers supprimés post-traitement'}
</span>
</div>
</div>
@@ -636,7 +639,7 @@ export default function TranslatePage() {
{showProcessing && (
<div className="editorial-card p-12 h-full border-none shadow-editorial bg-white dark:bg-[#141414] space-y-12">
<div className="flex items-center gap-6">
<div className="w-16 h-16 bg-brand-muted dark:bg-white/5 rounded-2xl flex items-center justify-center text-brand-accent border border-brand-accent/10 animate-pulse">
<div className="w-16 h-16 bg-brand-muted dark:bg-white/5 rounded-2xl flex items-center justify-center text-brand-goldink dark:text-brand-accent border border-brand-accent/10 animate-pulse">
<Activity size={32} />
</div>
<div className="text-left">
@@ -718,7 +721,7 @@ export default function TranslatePage() {
</button>
<Link
href={`/dashboard/reviews/${submit.jobId}`}
className="mb-6 flex items-center gap-2 rounded-2xl border border-brand-accent/30 px-6 py-3 text-xs font-bold uppercase tracking-[0.15em] text-brand-accent transition-colors hover:bg-brand-accent/10"
className="mb-6 flex items-center gap-2 rounded-2xl border border-brand-accent/30 px-6 py-3 text-xs font-bold uppercase tracking-[0.15em] text-brand-goldink dark:text-brand-accent transition-colors hover:bg-brand-accent/10"
>
<Search size={14} />
{t('translate.reviewCta')}
@@ -810,7 +813,7 @@ export default function TranslatePage() {
<span className={cn(
"inline-flex items-center gap-1.5 px-3 py-1.5 rounded-full text-[10px] font-bold uppercase tracking-[0.1em]",
config.mode === 'llm'
? "bg-brand-accent/10 text-brand-accent border border-brand-accent/20"
? "bg-brand-accent/10 text-brand-goldink dark:text-brand-accent border border-brand-accent/20"
: "bg-brand-muted/50 text-brand-dark/50 dark:bg-white/5 dark:text-white/50 border border-transparent"
)}>
{config.mode === 'llm' ? (
@@ -831,7 +834,7 @@ export default function TranslatePage() {
{config.mode === 'llm' && !!systemPrompt?.trim() && (
<Link
href="/dashboard/glossaries"
className="flex items-center gap-2 rounded-xl border border-brand-accent/25 bg-brand-accent/5 px-3 py-2 text-[10px] font-bold uppercase tracking-wider text-brand-accent transition-colors hover:bg-brand-accent/10"
className="flex items-center gap-2 rounded-xl border border-brand-accent/25 bg-brand-accent/5 px-3 py-2 text-[10px] font-bold uppercase tracking-wider text-brand-goldink dark:text-brand-accent transition-colors hover:bg-brand-accent/10"
>
<FileText className="size-3.5 shrink-0" />
{t('translate.contextActive')}
@@ -856,7 +859,7 @@ export default function TranslatePage() {
<div className="bg-brand-muted/30 dark:bg-white/[0.02] border border-black/[0.03] dark:border-white/[0.03] p-4 rounded-xl space-y-3">
<div className="flex justify-between items-center">
<div className="flex items-center gap-2">
<ImageIcon className="size-3.5 text-brand-accent shrink-0" />
<ImageIcon className="size-3.5 text-brand-goldink dark:text-brand-accent shrink-0" />
<span className="text-[10px] font-black uppercase tracking-[0.1em] text-brand-dark dark:text-white">
{t('dashboard.translate.translateImages') || "Traduire les images"}
</span>
@@ -905,7 +908,7 @@ export default function TranslatePage() {
)}
>
<div className="flex items-center gap-2 text-[10px] font-bold uppercase tracking-tight text-brand-dark dark:text-white">
<FileText className="size-3.5 text-brand-accent" />
<FileText className="size-3.5 text-brand-goldink dark:text-brand-accent" />
{t('dashboard.translate.pdfMode.preserveLayout') || 'Mise en page'}
</div>
<p className="mt-1.5 text-[10px] text-brand-dark/50 dark:text-white/50 font-medium leading-relaxed">
@@ -924,7 +927,7 @@ export default function TranslatePage() {
)}
>
<div className="flex items-center gap-2 text-[10px] font-bold uppercase tracking-tight text-brand-dark dark:text-white">
<Languages className="size-3.5 text-brand-accent" />
<Languages className="size-3.5 text-brand-goldink dark:text-brand-accent" />
{t('translate.textOnly')}
</div>
<p className="mt-1.5 text-[10px] text-brand-dark/50 dark:text-white/50 font-medium leading-relaxed">
@@ -950,7 +953,7 @@ export default function TranslatePage() {
{/* File summary */}
{(submit.fileName || upload.file?.name) && (
<div className="p-4 bg-brand-muted dark:bg-white/5 rounded-2xl mb-8 flex items-center gap-4 border border-black/5 dark:border-white/5">
<div className="w-10 h-10 bg-white dark:bg-[#1a1a1a] rounded-xl flex items-center justify-center text-brand-accent shadow-sm">
<div className="w-10 h-10 bg-white dark:bg-[#1a1a1a] rounded-xl flex items-center justify-center text-brand-goldink dark:text-brand-accent shadow-sm">
{(() => {
const name = submit.fileName || upload.file?.name || '';
const ext = name.split('.').pop()?.toLowerCase() ?? '';
@@ -977,7 +980,7 @@ export default function TranslatePage() {
</div>
<div className="flex justify-between items-center text-[11px] font-semibold uppercase tracking-[0.15em] text-brand-dark/50 dark:text-white/50">
<span>{t('translate.monitor.target')}</span>
<span className="text-brand-accent normal-case">{tgtLangName}</span>
<span className="text-brand-goldink dark:text-brand-accent normal-case">{tgtLangName}</span>
</div>
{currentProvider && (
<div className="flex justify-between items-center text-[11px] font-semibold uppercase tracking-[0.15em] text-brand-dark/50 dark:text-white/50">
@@ -1019,7 +1022,7 @@ export default function TranslatePage() {
</div>
<div className="flex justify-between items-center text-[11px] font-semibold uppercase tracking-[0.15em] text-brand-dark/50 dark:text-white/50">
<span>{t('translate.monitor.target')}</span>
<span className="text-brand-accent normal-case">{tgtLangName}</span>
<span className="text-brand-goldink dark:text-brand-accent normal-case">{tgtLangName}</span>
</div>
{currentProvider && (
<div className="flex justify-between items-center text-[11px] font-semibold uppercase tracking-[0.15em] text-brand-dark/50 dark:text-white/50">
@@ -1032,7 +1035,7 @@ export default function TranslatePage() {
<div className="pt-6 border-t border-black/5 dark:border-white/5 text-left">
<div className="flex justify-between items-center text-[11px] font-semibold text-brand-dark/50 dark:text-white/50">
<span className="flex items-center gap-1.5">
<ShieldCheck size={13} className="text-brand-accent" /> {t('landing.translate.zeroRetention') || 'Rétention Zéro'}
<ShieldCheck size={13} className="text-brand-goldink dark:text-brand-accent" /> {t('landing.translate.zeroRetention') || 'Rétention Zéro'}
</span>
</div>
</div>
@@ -1057,7 +1060,7 @@ export default function TranslatePage() {
{submit.isSubmitting ? (
<><Loader2 className="size-4 animate-spin" /> {t('translate.submit')}</>
) : (
<>{t('translate.startTranslation')} <ArrowRight size={13} className={upload.file ? 'text-brand-accent' : 'opacity-20'} /></>
<>{t('translate.startTranslation')} <ArrowRight size={13} className={upload.file ? 'text-brand-goldink dark:text-brand-accent' : 'opacity-20'} /></>
)}
</button>
</div>
@@ -1095,7 +1098,7 @@ function FileStrip({ file, onRemove, onReplace, t }: { file: File; onRemove: ()
function StatBox({ icon, value, label }: { icon: React.ReactNode; value: string; label: string }) {
return (
<div className="p-6 bg-brand-muted/30 rounded-3xl text-center border border-transparent hover:border-brand-accent/10 transition-all dark:bg-white/5 dark:border-white/5">
<div className="text-brand-accent flex justify-center mb-4">{icon}</div>
<div className="text-brand-goldink dark:text-brand-accent flex justify-center mb-4">{icon}</div>
<p className="text-sm font-black text-brand-dark mb-1 uppercase tracking-tight dark:text-white">{value}</p>
<p className="text-[10px] font-black text-brand-dark/50 uppercase tracking-[0.12em] dark:text-white/50">{label}</p>
</div>