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:
ordinarthur 2026-05-10 14:48:17 +02:00
parent c3c9dbb408
commit 3052a7e909
7 changed files with 57 additions and 41 deletions

View File

@ -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>
); );

View File

@ -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>

View File

@ -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) */}

View File

@ -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 é réglée ? ». Vous répondez en deux secondes. email : « Cette facture a-t-elle é réglée ? ». Vous répondez en deux secondes.
La machine fait le reste. L'algorithme fait le reste.
</p> </p>
} }
> >

View File

@ -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">

View File

@ -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 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>

View File

@ -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&apos;ongle
</span>
)}
</span> </span>
</span> </span>
); );