// SALVO — Part 2: Science, Product, Athletes, Pricing, Form, CTA, Footer, App
const { useState, useEffect, useRef, useCallback } = React;
// ===== SCIENCE HORIZONTAL SCROLL =====
const ScienceSection = () => {
const outerRef = useRef(null);
const trackRef = useRef(null);
const [progress, setProgress] = useState(0);
const [activePanel, setActivePanel] = useState(0);
const isMobile = window.innerWidth < 768;
useEffect(() => {
if (isMobile) return;
const handleScroll = () => {
const outer = outerRef.current;
if (!outer) return;
const rect = outer.getBoundingClientRect();
const scrolled = -rect.top;
const total = rect.height - window.innerHeight;
const p = Math.max(0, Math.min(1, scrolled / total));
setProgress(p);
setActivePanel(Math.min(3, Math.floor(p * 4)));
if (trackRef.current) {
const maxTranslate = -(trackRef.current.scrollWidth - window.innerWidth);
trackRef.current.style.transform = `translateX(${p * maxTranslate}px)`;
}
};
window.addEventListener('scroll', handleScroll, { passive: true });
return () => window.removeEventListener('scroll', handleScroll);
}, []);
const panels = [
{
tag: "01 — L'ancien modèle",
title: "L'ANCIEN MODÈLE\nA ÉCHOUÉ",
body: "Depuis 30 ans, la science du sport vous a dit que les crampes viennent de la déshydratation et des déficits électrolytiques. C'est faux.",
stat: "Niveaux d'électrolytes identiques entre athlètes qui crampent et ceux qui ne crampent pas.",
source: "Schwellnus et al., 2008",
visual: (
{/* Two bar charts side by side */}
{[['Crampes', 142], ['Pas de crampes', 138]].map(([label, val], i) => {
const [ref, inView] = useInView();
return (
);
})}
Aucune différence significative (p=0.82)
),
},
{
tag: "02 — Le vrai mécanisme",
title: "LES CRAMPES\nVIENNENT DES NERFS",
body: "Les crampes d'effort ne viennent pas du muscle. Elles viennent d'un motoneurone α en état d'hyperexcitabilité — un neurone qui tire sans s'arrêter.",
stat: "Le muscle reçoit un signal continu. Il se contracte. Il ne peut pas s'arrêter.",
source: "Schwellnus, 2009 — Altered Neuromuscular Control Hypothesis",
visual: (
{/* Neuron impulse visual */}
{Array.from({ length: 12 }).map((_, i) => (
))}
Motoneurone α — hyperexcitabilité
),
},
{
tag: "03 — La solution TRP",
title: "LES CANAUX TRP\nCOUPENT LE SIGNAL",
body: "Activés en bouche, les agonistes TRP envoient un signal inhibiteur via le nerf vague. Le motoneurone se calme. La crampe cède en 60-90 secondes.",
stat: "3 agonistes TRP. Un signal. Zéro compromis.",
source: "MacAuley & Best, 2007 — Bean & Strichartz, MIT",
visual: (
{[
{ name: 'Capsaïcine', sub: 'Piment', color: '#FF6B35' },
{ name: 'Gingérols', sub: 'Gingembre', color: '#FF8C5A' },
{ name: 'Cinnam.', sub: 'Cannelle', color: '#FFA875' },
].map((ing, i) => {
const [ref, inView] = useInView();
return (
);
})}
),
},
{
tag: "04 — La validation",
title: "VALIDATION :\n$86.4M D'IPO NASDAQ",
body: "Flex Pharma a levé $86.4M en IPO sur le Nasdaq avec Hotshot — basé sur le même mécanisme TRP. Prouvé. Breveté. SALVO va plus loin : double action électrolytique.",
stat: "SALVO = mécanisme TRP + 900mg sodium. Hotshot n'a pas de sodium. Nous, oui.",
source: "Flex Pharma IPO 2015 — NASDAQ: FLKS",
visual: (
{[
{ label: 'IPO Nasdaq', val: '$86.4M' },
{ label: 'Mécanisme TRP', val: 'Breveté' },
{ label: 'Double action', val: 'SALVO only' },
].map((item, i) => (
))}
Flex Pharma prouve le mécanisme. SALVO va plus loin.
),
},
];
if (isMobile) {
return (
La science
Le mécanisme TRP
{panels.map((p, i) => (
{p.tag}
{p.visual}
{p.title}
{p.body}
{p.stat}
— {p.source}
))}
);
}
return (
{/* Header */}
La science
Le mécanisme TRP
{/* Progress dots */}
{panels.map((_, i) => (
))}
{/* Track */}
{panels.map((p, i) => (
{p.tag}
{p.visual}
{p.title}
{p.body}
{p.stat}
— {p.source}
))}
{/* Progress bar */}
{/* Scroll cue */}
0.95 ? 0 : 0.5, transition: 'opacity 0.3s' }}>
Continuez à défiler →
);
};
// ===== PRODUCT SECTION =====
const ProductSection = () => {
const [ref, inView] = useInView();
const sachetRef = useRef(null);
const [angle, setAngle] = useState(0);
useEffect(() => {
let raf;
let start = null;
const animate = (ts) => {
if (!start) start = ts;
const elapsed = ts - start;
setAngle((elapsed / 15000) * 360);
raf = requestAnimationFrame(animate);
};
raf = requestAnimationFrame(animate);
return () => cancelAnimationFrame(raf);
}, []);
const specs = [
{ label: '30 ML', sub: 'Format shot', pos: { top: '8%', right: '-10%' } },
{ label: 'TRP × 3', sub: 'Capsaïcine · Gingérols · Cinnam.', pos: { top: '32%', right: '-18%' } },
{ label: '900MG', sub: 'Sodium', pos: { bottom: '22%', right: '-14%' } },
{ label: '200MG', sub: 'Potassium', pos: { bottom: '8%', left: '-12%' } },
{ label: 'ZÉRO SUCRE', sub: 'Formule pure', pos: { top: '32%', left: '-18%' } },
{ label: '60-90s', sub: 'Onset TRP', pos: { top: '8%', left: '-10%' } },
];
return (
Produit
Anatomie d'unshot SALVO
{/* Sachet + floating specs */}
{/* Specs */}
{specs.map((spec, i) => (
{spec.label}
{spec.sub}
{/* Connector line */}
))}
{/* Sachet SVG */}
{/* Body */}
{/* Top crimp */}
{/* Tear notch */}
{/* Horizontal seal lines */}
{/* Center logo area */}
{/* Brand text */}
SALVO
{/* Tagline */}
FIRE WHEN READY
{/* Shot details */}
ANTI-CRAMPE · 30ML
{/* Shine */}
);
};
// ===== ATHLETES SECTION =====
const AthletesSection = () => {
const communities = ['HYROX', 'UTMB', 'IRONMAN', 'Tour de France Amateur', 'Tennis Pro Circuit', 'CrossFit Open', 'Triathlon France', 'Trail Blanc'];
const testimonials = [
{ name: 'Laurent M.', sport: 'Trail Ultra', text: 'Au km 72 de l\'UTMB, la crampe habituelle. J\'ai pris SALVO. 90 secondes plus tard, j\'avançais encore.', placeholder: true },
{ name: 'Sarah K.', sport: 'HYROX', text: 'La chaleur du platform fait tout. J\'ai arrêté de cramper dans les sleds. Rien d\'autre n\'avait marché.', placeholder: true },
{ name: 'Pierre D.', sport: 'Triathlon Ironman', text: 'Le vélo et la course enchaînés — mes mollets lâchaient toujours à T2. Plus depuis SALVO.', placeholder: true },
];
return (
Communauté
Built with athletes
{/* Marquee */}
{[...communities, ...communities].map((c, i) => (
{c} ·
))}
{/* Testimonials */}
{testimonials.map((t, i) => (
{ e.currentTarget.style.borderColor = 'rgba(255,107,53,0.3)'; e.currentTarget.style.transform = 'translateY(-4px)'; e.currentTarget.style.boxShadow = '0 12px 40px rgba(0,0,0,0.3)'; }}
onMouseLeave={e => { e.currentTarget.style.borderColor = 'var(--border)'; e.currentTarget.style.transform = 'translateY(0)'; e.currentTarget.style.boxShadow = 'none'; }}
>
"{t.text}"
{t.placeholder && (
Testimonial early athletes program
)}
))}
);
};
// ===== PRICING SECTION =====
const PricingSection = ({ onSelect }) => {
const packs = [
{ name: 'Découverte', shots: 6, price: 19, per: '3.17', desc: 'Testez le mécanisme TRP avant votre prochaine course.', cta: 'Sélectionner' },
{ name: 'Abonnement', shots: 18, price: 49, per: '2.72', desc: 'Le pack de l\'athlète régulier. Renouvelable. Annulable.', cta: 'Sélectionner', featured: true },
{ name: 'Équipe', shots: 36, price: 89, per: '2.47', desc: 'Pour les clubs, les staffs, les athlètes qui ne transigent pas.', cta: 'Sélectionner' },
];
return (
Pré-commande
Choisissez votre pack
{packs.map((pack, i) => (
{
if (!pack.featured) {
e.currentTarget.style.borderColor = 'rgba(255,107,53,0.3)';
e.currentTarget.style.transform = 'translateY(-4px)';
e.currentTarget.style.boxShadow = '0 16px 48px rgba(0,0,0,0.3)';
} else {
e.currentTarget.style.boxShadow = '0 0 64px rgba(255,107,53,0.18)';
}
}}
onMouseLeave={e => {
if (!pack.featured) {
e.currentTarget.style.borderColor = 'var(--border)';
e.currentTarget.style.transform = 'scale(1)';
e.currentTarget.style.boxShadow = 'none';
} else {
e.currentTarget.style.boxShadow = '0 0 48px rgba(255,107,53,0.1)';
}
}}
>
{pack.featured && (
Le plus populaire
)}
{pack.name}
{pack.shots} shots
€{pack.price}
€{pack.per}/shot
{pack.desc}
onSelect(pack.name)}
style={{ width: '100%', justifyContent: 'center', padding: '13px 0' }}
>
{pack.cta}
))}
);
};
// ===== FORM SECTION =====
const FormSection = ({ selectedPack, setSelectedPack }) => {
const [form, setForm] = useState({ prenom: '', nom: '', email: '', pack: selectedPack || 'Abonnement', sport: '', pays: '', postal: '' });
const [errors, setErrors] = useState({});
const [loading, setLoading] = useState(false);
const [success, setSuccess] = useState(false);
useEffect(() => {
if (selectedPack) setForm(f => ({ ...f, pack: selectedPack }));
}, [selectedPack]);
const validate = () => {
const e = {};
if (!form.prenom.trim()) e.prenom = 'Requis';
if (!form.nom.trim()) e.nom = 'Requis';
if (!form.email.match(/^[^\s@]+@[^\s@]+\.[^\s@]+$/)) e.email = 'Email invalide';
if (!form.sport) e.sport = 'Requis';
if (!form.pays.trim()) e.pays = 'Requis';
return e;
};
const handleSubmit = (e) => {
e.preventDefault();
const errs = validate();
if (Object.keys(errs).length > 0) { setErrors(errs); return; }
setErrors({});
setLoading(true);
setTimeout(() => { setLoading(false); setSuccess(true); }, 1800);
};
const Field = ({ label, id, type = 'text', value, onChange, error, children }) => (
{label}
{children || (
e.target.style.borderColor = 'rgba(255,107,53,0.4)'}
onBlur={e => e.target.style.borderColor = error ? 'rgba(255,107,53,0.4)' : 'var(--border)'}
/>
)}
{error && {error} }
);
const selectStyle = { background: 'var(--bg)', border: '1px solid var(--border)', color: 'var(--white)', fontFamily: "'IBM Plex Sans', sans-serif", fontSize: 15, padding: '12px 14px', outline: 'none', width: '100%', fontWeight: 300, cursor: 'pointer' };
return (
{success && (
Vous êtes dansla première salve.
Confirmation envoyée à {form.email}. Livraison prévue Q4 2026.
setSuccess(false)} variant="ghost">Retour à la page
)}
Réservation
Rejoignez la première salve
);
};
// ===== CTA BANNER =====
const CTABanner = ({ onReserve }) => {
const [ref, inView] = useInView();
return (
{/* Line trace animation */}
La première salveest ouverte.
250 athlètes fondateurs · Early bird €15
Réserver ma place →
);
};
// ===== FOOTER =====
const Footer = () => {
const cols = [
{ title: 'Produit', links: ['Le shot SALVO', 'La science TRP', 'Dosage & utilisation', 'FAQ'] },
{ title: 'Science', links: ['Mécanisme neuromusculaire', 'Agonistes TRP', 'Électrolytes', 'Études cliniques'] },
{ title: 'Entreprise', links: ['Notre mission', 'Équipe', 'Presse', 'Contact'] },
];
return (
{/* Brand col */}
SALVO
Le premier shot anti-crampe européen à double action. Conçu pour le 1 sur 7.
Fire When Ready.
{cols.map((col, i) => (
))}
© 2026 SALVO. Tous droits réservés.
* « 1 athlète d'endurance sur 7 » — Estimation basée sur la prévalence des crampes d'effort récurrentes (Kantarowski 1990, Schwellnus 2008, Maughan & Shirreffs 2019). Les taux varient selon le sport, les conditions et le profil individuel.
);
};
// ===== APP =====
const App = () => {
const [showLoader, setShowLoader] = useState(() => !sessionStorage.getItem('salvo_loaded'));
const [selectedPack, setSelectedPack] = useState(null);
const handleLoaderDone = () => {
sessionStorage.setItem('salvo_loaded', '1');
setShowLoader(false);
};
const scrollToForm = (pack) => {
if (pack) setSelectedPack(pack);
const el = document.getElementById('preorder');
if (el) window.scrollTo({ top: el.offsetTop - 80, behavior: 'smooth' });
};
return (
{showLoader &&
}
scrollToForm()} />
scrollToForm()} />
scrollToForm(pack)} />
scrollToForm()} />
);
};
ReactDOM.createRoot(document.getElementById('root')).render( );