feat(landing): brand "Rubis.pro" + corrections copy
- Brand : suffixe `sur l'ongle` → `.pro` (attaché, muted, non italique).
Propagé partout via `<Brand withSuffix>` — header/footer landing,
topbar/sidebar SPA, login/signup/onboarding. Renforce l'identification
brand requise par Google OAuth (gem seul jugé trop générique).
- Hero : dots groupés avec leur label (inline-flex) — ne se baladent plus
en début de ligne au flex wrap. Ajout d'un topbar mock "Rubis.pro ·
Tableau de bord" en haut de la carte hero pour identifier le mock comme
un vrai dashboard. `DSO` → `DSO*`.
- Stats : "Trois chiffres qui devraient vous fâcher" → "Trois chiffres
exorbitants". Sous-titre remplacé par "Et vous faites sûrement partie
intégrante de ces enquêtes." (plus direct, moins gratuit).
- Promise : "Votre temps vaut plus que ça" → "Votre temps est plus
précieux". Réécriture de l'amorce ("votre boîte / lundis soirs" →
"votre entreprise / journées"). Ajout d'une ligne italique "Parfois
moins, si votre plan par défaut est bien réglé".
- HowItWorks : Step 01 — suppression de "à la caisse" et de ", RIB"
(l'OCR ne lit pas le RIB en V1). Step 03 — "La machine fait le reste"
→ "L'algorithme fait le reste".
- Gamification : suppression de "Pas un PDF abscons" (jargon inutile) et
de "Et oui, on garde un classement amical" (le classement n'est pas en
V1). `DSO` → `DSO*`.
- Footnotes : ajout de la définition DSO (Days Sales Outstanding) sous
celle d'OCR.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
c3c9dbb408
commit
3052a7e909
@ -1,13 +1,19 @@
|
|||||||
export function Footnotes() {
|
export function Footnotes() {
|
||||||
return (
|
return (
|
||||||
<aside className="border-t border-line bg-cream">
|
<aside className="border-t border-line bg-cream">
|
||||||
<div className="max-w-[820px] mx-auto px-5 sm:px-8 py-8">
|
<div className="max-w-[820px] mx-auto px-5 sm:px-8 py-8 space-y-3">
|
||||||
<p className="text-[13.5px] text-ink-3 leading-relaxed">
|
<p className="text-[13.5px] text-ink-3 leading-relaxed">
|
||||||
<span className="text-rubis font-semibold mr-1.5">*</span>
|
<span className="text-rubis font-semibold mr-1.5">*</span>
|
||||||
<b className="text-ink-2">OCR</b> — pour <i>Optical Character Recognition</i>. La
|
<b className="text-ink-2">OCR</b> — pour <i>Optical Character Recognition</i>. La
|
||||||
reconnaissance automatique du texte sur un PDF ou une photo. La machine lit votre
|
reconnaissance automatique du texte sur un PDF ou une photo. La machine lit votre
|
||||||
facture par-dessus votre épaule, en somme.
|
facture par-dessus votre épaule, en somme.
|
||||||
</p>
|
</p>
|
||||||
|
<p className="text-[13.5px] text-ink-3 leading-relaxed">
|
||||||
|
<span className="text-rubis font-semibold mr-1.5">*</span>
|
||||||
|
<b className="text-ink-2">DSO</b> — pour <i>Days Sales Outstanding</i>. Le délai
|
||||||
|
moyen, en jours, entre l'émission d'une facture et son encaissement. Plus il est
|
||||||
|
bas, plus votre trésorerie respire.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -16,7 +16,7 @@ export function Gamification() {
|
|||||||
<p className="mt-5 max-w-[680px] mx-auto text-[17px] text-cream/85 leading-relaxed">
|
<p className="mt-5 max-w-[680px] mx-auto text-[17px] text-cream/85 leading-relaxed">
|
||||||
À chaque relance que Rubis envoie à votre place, vous gagnez un rubis. À la fin du
|
À chaque relance que Rubis envoie à votre place, vous gagnez un rubis. À la fin du
|
||||||
mois, vous voyez exactement combien d'heures vous avez récupérées. Pas un graphique
|
mois, vous voyez exactement combien d'heures vous avez récupérées. Pas un graphique
|
||||||
de DSO. Pas un PDF abscons. Du temps. Concret.
|
de DSO*. Du temps. Concret.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div className="mt-10 flex flex-col items-center gap-3">
|
<div className="mt-10 flex flex-col items-center gap-3">
|
||||||
@ -35,7 +35,7 @@ export function Gamification() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p className="mt-10 max-w-[460px] mx-auto text-[14px] text-cream/70">
|
<p className="mt-10 max-w-[460px] mx-auto text-[14px] text-cream/70">
|
||||||
Et oui, on garde un classement amical. Les meilleurs utilisateurs libèrent{" "}
|
Les meilleurs utilisateurs libèrent{" "}
|
||||||
<b className="text-cream">30 heures par mois</b>. Plus de quoi prendre un long
|
<b className="text-cream">30 heures par mois</b>. Plus de quoi prendre un long
|
||||||
week-end. Toutes les 4 semaines.
|
week-end. Toutes les 4 semaines.
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { Button, Eyebrow, Gem, cn } from "@rubis/ui";
|
import { Brand, Button, Eyebrow, Gem, cn } from "@rubis/ui";
|
||||||
import { Check } from "lucide-react";
|
import { Check } from "lucide-react";
|
||||||
|
|
||||||
const APP_URL = "https://app.rubis.pro";
|
const APP_URL = "https://app.rubis.pro";
|
||||||
@ -52,10 +52,14 @@ export function Hero() {
|
|||||||
<Check size={14} className="text-rubis" aria-hidden />
|
<Check size={14} className="text-rubis" aria-hidden />
|
||||||
30 jours gratuits puis Free 5 factures
|
30 jours gratuits puis Free 5 factures
|
||||||
</span>
|
</span>
|
||||||
<span aria-hidden className="size-[3px] rounded-full bg-ink-3" />
|
<span className="inline-flex items-center gap-3">
|
||||||
<span>Hébergement souverain</span>
|
<span aria-hidden className="size-[3px] rounded-full bg-ink-3" />
|
||||||
<span aria-hidden className="size-[3px] rounded-full bg-ink-3" />
|
Hébergement souverain
|
||||||
<span>Made in France 🇫🇷</span>
|
</span>
|
||||||
|
<span className="inline-flex items-center gap-3">
|
||||||
|
<span aria-hidden className="size-[3px] rounded-full bg-ink-3" />
|
||||||
|
Made in France 🇫🇷
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -68,22 +72,31 @@ export function Hero() {
|
|||||||
<div className="relative w-full max-w-[480px] mx-auto lg:ml-auto lg:mr-0">
|
<div className="relative w-full max-w-[480px] mx-auto lg:ml-auto lg:mr-0">
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"bg-white border border-line rounded-card shadow-card",
|
"bg-white border border-line rounded-card shadow-card overflow-hidden",
|
||||||
"p-6 sm:p-7 lg:p-8",
|
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{/* Hero rubis */}
|
{/* Topbar mock — identifie la carte comme un dashboard Rubis.pro,
|
||||||
<div className="flex items-center gap-4 pb-5 border-b border-line">
|
pas juste un widget de chiffres flottants. */}
|
||||||
<Gem size={56} glow />
|
<div className="flex items-center justify-between px-6 sm:px-7 lg:px-8 py-3.5 border-b border-line bg-cream/40">
|
||||||
<div>
|
<Brand withSuffix gemSize={18} />
|
||||||
<div className="font-display font-bold text-[32px] tracking-[-0.022em] leading-none text-ink">
|
<span className="text-[11px] uppercase tracking-[0.08em] font-semibold text-ink-3">
|
||||||
124 rubis
|
Tableau de bord
|
||||||
</div>
|
</span>
|
||||||
<div className="mt-1.5 text-[14px] text-ink-2">
|
</div>
|
||||||
≈ <b className="text-ink">24 h 48</b> que vous n'avez pas passées à relancer.
|
|
||||||
|
<div className="p-6 sm:p-7 lg:p-8">
|
||||||
|
{/* Hero rubis */}
|
||||||
|
<div className="flex items-center gap-4 pb-5 border-b border-line">
|
||||||
|
<Gem size={56} glow />
|
||||||
|
<div>
|
||||||
|
<div className="font-display font-bold text-[32px] tracking-[-0.022em] leading-none text-ink">
|
||||||
|
124 rubis
|
||||||
|
</div>
|
||||||
|
<div className="mt-1.5 text-[14px] text-ink-2">
|
||||||
|
≈ <b className="text-ink">24 h 48</b> que vous n'avez pas passées à relancer.
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* KPIs */}
|
{/* KPIs */}
|
||||||
<div className="grid grid-cols-2 gap-5 mt-5">
|
<div className="grid grid-cols-2 gap-5 mt-5">
|
||||||
@ -100,7 +113,7 @@ export function Hero() {
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div className="text-[10.5px] uppercase tracking-[0.06em] font-semibold text-ink-3">
|
<div className="text-[10.5px] uppercase tracking-[0.06em] font-semibold text-ink-3">
|
||||||
DSO
|
DSO*
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-1.5 font-display font-bold text-[22px] tracking-[-0.015em] text-ink tabular-nums">
|
<div className="mt-1.5 font-display font-bold text-[22px] tracking-[-0.015em] text-ink tabular-nums">
|
||||||
38 j
|
38 j
|
||||||
@ -135,6 +148,7 @@ export function Hero() {
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Badge flottant — relatif au wrapper carte (max-w 480) */}
|
{/* Badge flottant — relatif au wrapper carte (max-w 480) */}
|
||||||
|
|||||||
@ -17,7 +17,7 @@ export function HowItWorks() {
|
|||||||
<Step
|
<Step
|
||||||
num="01"
|
num="01"
|
||||||
title="Vous importez vos factures."
|
title="Vous importez vos factures."
|
||||||
body="PDF, photo prise depuis votre téléphone à la caisse, scan reçu par mail — peu importe. L'OCR* lit, extrait montant, client, échéance, RIB. Vous vérifiez. Vingt secondes par facture, montre en main."
|
body="PDF, photo prise depuis votre téléphone, scan reçu par mail — peu importe. L'OCR* lit, extrait montant, client, échéance. Vous vérifiez. Vingt secondes par facture, montre en main."
|
||||||
>
|
>
|
||||||
<DropzoneWidget />
|
<DropzoneWidget />
|
||||||
</Step>
|
</Step>
|
||||||
@ -47,7 +47,7 @@ export function HowItWorks() {
|
|||||||
Pendant que vous travaillez, Rubis envoie les emails au moment prévu, suit qui a
|
Pendant que vous travaillez, Rubis envoie les emails au moment prévu, suit qui a
|
||||||
ouvert, qui n'a pas répondu, et avant chaque relance vous demande discrètement par
|
ouvert, qui n'a pas répondu, et avant chaque relance vous demande discrètement par
|
||||||
email : « Cette facture a-t-elle été réglée ? ». Vous répondez en deux secondes.
|
email : « Cette facture a-t-elle été réglée ? ». Vous répondez en deux secondes.
|
||||||
La machine fait le reste.
|
L'algorithme fait le reste.
|
||||||
</p>
|
</p>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
|||||||
@ -7,14 +7,14 @@ export function Promise() {
|
|||||||
<div className="text-center max-w-[820px] mx-auto">
|
<div className="text-center max-w-[820px] mx-auto">
|
||||||
<Eyebrow>Notre conviction</Eyebrow>
|
<Eyebrow>Notre conviction</Eyebrow>
|
||||||
<blockquote className="mt-6 font-display font-bold text-ink leading-[1.05] tracking-[-0.03em] text-[40px] sm:text-[56px] lg:text-[64px]">
|
<blockquote className="mt-6 font-display font-bold text-ink leading-[1.05] tracking-[-0.03em] text-[40px] sm:text-[56px] lg:text-[64px]">
|
||||||
Votre temps vaut <em>plus que ça</em>.
|
Votre temps est <em>plus précieux</em>.
|
||||||
</blockquote>
|
</blockquote>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-14 grid lg:grid-cols-[1.4fr_1fr] gap-10 lg:gap-16 items-start max-w-[1080px] mx-auto">
|
<div className="mt-14 grid lg:grid-cols-[1.4fr_1fr] gap-10 lg:gap-16 items-start max-w-[1080px] mx-auto">
|
||||||
<div className="space-y-5 md:text-justify hyphens-auto">
|
<div className="space-y-5 md:text-justify hyphens-auto">
|
||||||
<p className="text-[17.5px] leading-relaxed text-ink-2">
|
<p className="text-[17.5px] leading-relaxed text-ink-2">
|
||||||
Vous n'avez pas créé votre boîte pour passer vos lundis soirs à rédiger des
|
Vous n'avez pas créé votre entreprise pour passer vos journées à rédiger des
|
||||||
relances polies. Pendant que vous écrivez "je me permets un petit rappel
|
relances polies. Pendant que vous écrivez "je me permets un petit rappel
|
||||||
concernant…", vous ne facturez pas, vous ne vendez pas, vous ne créez pas.
|
concernant…", vous ne facturez pas, vous ne vendez pas, vous ne créez pas.
|
||||||
</p>
|
</p>
|
||||||
@ -24,6 +24,9 @@ export function Promise() {
|
|||||||
<b className="text-ink">moins de 3</b>. Soit 5 heures de votre vie récupérées.
|
<b className="text-ink">moins de 3</b>. Soit 5 heures de votre vie récupérées.
|
||||||
Toutes les semaines. Pour toujours.
|
Toutes les semaines. Pour toujours.
|
||||||
</p>
|
</p>
|
||||||
|
<p className="text-[15px] leading-relaxed text-ink-3 italic">
|
||||||
|
Parfois moins, si votre plan par défaut est bien réglé.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="bg-cream-2 border border-line rounded-card p-7">
|
<div className="bg-cream-2 border border-line rounded-card p-7">
|
||||||
|
|||||||
@ -25,11 +25,10 @@ export function Stats() {
|
|||||||
<div className="text-center max-w-[640px] mx-auto mb-12">
|
<div className="text-center max-w-[640px] mx-auto mb-12">
|
||||||
<Eyebrow>L'état des paiements en France</Eyebrow>
|
<Eyebrow>L'état des paiements en France</Eyebrow>
|
||||||
<h2 className="mt-4 font-display font-bold text-ink leading-[1.1] tracking-[-0.025em] text-[34px] sm:text-[44px]">
|
<h2 className="mt-4 font-display font-bold text-ink leading-[1.1] tracking-[-0.025em] text-[34px] sm:text-[44px]">
|
||||||
Trois chiffres qui devraient vous fâcher.
|
Trois chiffres exorbitants.
|
||||||
</h2>
|
</h2>
|
||||||
<p className="mt-4 text-[17px] text-ink-2 leading-relaxed">
|
<p className="mt-4 text-[17px] text-ink-2 leading-relaxed">
|
||||||
Si vous lisez ça, vous avez probablement une facture impayée à l'heure où on parle.
|
Et vous faites sûrement partie intégrante de ces enquêtes.
|
||||||
Vous n'êtes pas un cas isolé.
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -2,8 +2,11 @@ import { cn } from "../lib/cn.js";
|
|||||||
import { Gem } from "./Gem.js";
|
import { Gem } from "./Gem.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lockup horizontal : ◆ + "Rubis" (+ optionnel "sur l'ongle" en suffixe italique muted).
|
* Lockup horizontal : ◆ + "Rubis" (+ optionnel suffixe ".pro" muted, attaché
|
||||||
* À utiliser dans les headers, le sidebar, les emails.
|
* au wordmark sans espace). À utiliser dans les headers, le sidebar, les
|
||||||
|
* emails. Le suffixe rend le mark identifiant (cf. exigence Google OAuth :
|
||||||
|
* un logo doit "identifier la marque de manière unique" — la gem seule
|
||||||
|
* est trop générique).
|
||||||
*
|
*
|
||||||
* Architecture : on s'appuie sur le composant <Gem/> SVG — pas de PNG, pas
|
* Architecture : on s'appuie sur le composant <Gem/> SVG — pas de PNG, pas
|
||||||
* de border externe. La pierre EST le logo. Plus rien ne casse à l'export
|
* de border externe. La pierre EST le logo. Plus rien ne casse à l'export
|
||||||
@ -13,7 +16,7 @@ import { Gem } from "./Gem.js";
|
|||||||
* Cf. /docs/marque.md §2 et le pattern de la landing.
|
* Cf. /docs/marque.md §2 et le pattern de la landing.
|
||||||
*/
|
*/
|
||||||
type BrandProps = {
|
type BrandProps = {
|
||||||
/** Affiche le suffixe "sur l'ongle" en italique muted. */
|
/** Affiche le suffixe ".pro" attaché au wordmark, en couleur muted. */
|
||||||
withSuffix?: boolean;
|
withSuffix?: boolean;
|
||||||
/**
|
/**
|
||||||
* Taille de la gem en pixels. Default 22 (lockup) ou 32 (onlyImage).
|
* Taille de la gem en pixels. Default 22 (lockup) ou 32 (onlyImage).
|
||||||
@ -54,16 +57,7 @@ export function Brand({
|
|||||||
<Gem size={resolvedSize} />
|
<Gem size={resolvedSize} />
|
||||||
<span className="leading-none">
|
<span className="leading-none">
|
||||||
Rubis
|
Rubis
|
||||||
{withSuffix && (
|
{withSuffix && <span className="text-ink-3">.pro</span>}
|
||||||
<span
|
|
||||||
className={cn(
|
|
||||||
"ml-1 font-display italic font-medium text-ink-3",
|
|
||||||
"text-[12.5px] tracking-[-0.005em]",
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
sur l'ongle
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user