La Nutrition 100% Naturelle pour
l’Ultra-Trail
Fini le hasard. Notre algorithme crée votre pack nutrition sportive (gels, barres, boissons) adapté à votre distance et votre terrain pour des efforts longs sans troubles digestifs.
Approuvé par la communauté
Générez votre Pack Nutrition Sportive Personnalisé par IA
En ultra-endurance, la digestibilité est primordiale. Notre algorithme analyse votre métabolisme d’effort pour composer le pack de ravitaillement idéal en 30 secondes, associant glucides et électrolytes.
Notre algorithme nutritionnel pour coureurs d’endurance
Réponds au questionnaire
Dis-nous ton objectif, ta distance, ton niveau et tes préférences alimentaires.
Reçois ton pack
On te recommande le pack nutritionnel idéal adapté à ton profil de coureur.
Suis ton protocole
Un plan de consommation clair, jour par jour, pour optimiser ta préparation.
L’Avis de la Communauté Trail Vital
Découvrez pourquoi des centaines de coureurs d’ultra-marathon nous font confiance pour leur plan d’hydratation et d’énergie naturelle sans maux de ventre.
« Premier 80km terminé sans aucun problème digestif. Le pack m’a enlevé une charge mentale énorme avant la course. Je recommande à 100% ! »
Sophie B.
Finisher SaintéLyon
« Les gommes sont incroyables et l’hydratation au top. C’est la première fois que j’arrive à la ligne d’arrivée d’un ultra avec de l’énergie à revendre. »
Marc T.
Finisher UTMB
« Concept génial. J’ai rempli le quiz, reçu ma boîte 3 jours après. Les textures hydrogel sont passées toutes seules sous 35 degrés. »
Julien R.
Finisher Templiers
Questions Fréquentes sur notre Nutrition d’Épreuve
Quand vais-je recevoir mon pack mensuel ?
Puis-je modifier mes préférences en cours de préparation ?
L’abonnement est-il remboursable ou avec engagement ?
Prêt à battre votre record ?
Rejoignez des milliers de trailers qui s’alimentent mieux.
Commencer mon plan
Trail Vital – Pack Personnalisé
Créer mon pack menu

● #1 Choix naturel pour les Ultra-Trailers
La Nutrition 100% Naturelle pour
l’Ultra-Trail
Fini le hasard. Notre algorithme crée votre pack nutrition sportive (gels, barres, boissons) adapté à votre distance et votre terrain pour des efforts longs sans troubles digestifs.
Commencer mon plan arrow_forward forum Avis communautaires
+2k
starstarstarstarstar
Approuvé par la communauté
bolt Intelligence Artificielle
Générez votre Pack Nutrition Sportive Personnalisé par IA
En ultra-endurance, la digestibilité est primordiale. Notre algorithme analyse votre métabolisme d’effort pour composer le pack de ravitaillement idéal en 30 secondes, associant glucides et électrolytes.
Générer mon pack arrow_forward
check
Analyse Complète
Métabolisme & Profil
<section class="py-32 relative overflow-hidden bg-slate-50 dark:bg-slate-900/50" id="protocol">
<div class="container mx-auto px-4 relative z-10">
<div class="text-center mb-24">
<span class="text-secondary font-bold uppercase tracking-widest text-xs mb-4 block">Simple &
Efficace</span>
<h2 class="text-4xl md:text-5xl font-black text-slate-900 dark:text-white tracking-tight">Notre algorithme nutritionnel pour coureurs d'endurance</h2>
</div>
<div class="grid grid-cols-1 md:grid-cols-3 gap-16 relative">
<div
class="hidden md:block absolute top-16 left-[16%] right-[16%] h-0.5 bg-gradient-to-r from-gray-200 via-primary/20 to-gray-200 dark:from-gray-700 dark:via-primary/20 dark:to-gray-700 z-0 border-t border-dashed border-gray-300">
</div>
<div class="relative z-10 flex flex-col items-center text-center group">
<div
class="w-32 h-32 rounded-3xl bg-white dark:bg-gray-800 flex items-center justify-center mb-10 shadow-lg shadow-gray-200/50 dark:shadow-none border border-gray-100 dark:border-gray-700 group-hover:-translate-y-2 transition-transform duration-500 relative">
<div
class="absolute -top-3 -right-3 bg-primary text-white text-sm font-bold w-8 h-8 rounded-full flex items-center justify-center shadow-md">
1</div>
<div
class="absolute inset-0 bg-primary/5 rounded-3xl transform rotate-6 group-hover:rotate-12 transition-transform duration-500 z-[-1]">
</div>
<span class="material-symbols-outlined text-5xl text-primary bg-clip-text">assignment</span>
</div>
<h3 class="text-2xl font-bold mb-4 text-slate-900 dark:text-white">Réponds au questionnaire</h3>
<p class="text-slate-500 dark:text-slate-400 leading-relaxed max-w-xs mx-auto">
Dis-nous ton objectif, ta distance, ton niveau et tes préférences alimentaires.
</p>
</div>
<div class="relative z-10 flex flex-col items-center text-center group">
<div
class="w-32 h-32 rounded-3xl bg-white dark:bg-gray-800 flex items-center justify-center mb-10 shadow-lg shadow-gray-200/50 dark:shadow-none border border-gray-100 dark:border-gray-700 group-hover:-translate-y-2 transition-transform duration-500 relative">
<div
class="absolute -top-3 -right-3 bg-primary text-white text-sm font-bold w-8 h-8 rounded-full flex items-center justify-center shadow-md">
2</div>
<div
class="absolute inset-0 bg-primary/5 rounded-3xl transform rotate-6 group-hover:rotate-12 transition-transform duration-500 z-[-1]">
</div>
<span class="material-symbols-outlined text-5xl text-primary shadow-glow">inventory_2</span>
</div>
<h3 class="text-2xl font-bold mb-4 text-slate-900 dark:text-white">Reçois ton pack</h3>
<p class="text-slate-500 dark:text-slate-400 leading-relaxed max-w-xs mx-auto">
On te recommande le pack nutritionnel idéal adapté à ton profil de coureur.
</p>
</div>
<div class="relative z-10 flex flex-col items-center text-center group">
<div
class="w-32 h-32 rounded-3xl bg-white dark:bg-gray-800 flex items-center justify-center mb-10 shadow-lg shadow-gray-200/50 dark:shadow-none border border-gray-100 dark:border-gray-700 group-hover:-translate-y-2 transition-transform duration-500 relative">
<div
class="absolute -top-3 -right-3 bg-primary text-white text-sm font-bold w-8 h-8 rounded-full flex items-center justify-center shadow-md">
3</div>
<div
class="absolute inset-0 bg-primary/5 rounded-3xl transform rotate-6 group-hover:rotate-12 transition-transform duration-500 z-[-1]">
</div>
<span class="material-symbols-outlined text-5xl text-primary">event_available</span>
</div>
<h3 class="text-2xl font-bold mb-4 text-slate-900 dark:text-white">Suis ton protocole</h3>
<p class="text-slate-500 dark:text-slate-400 leading-relaxed max-w-xs mx-auto">
Un plan de consommation clair, jour par jour, pour optimiser ta préparation.
</p>
</div>
</div>
</div>
</section>
<!-- Testimonials Section -->
<section class="py-32 bg-background-light dark:bg-background-dark relative" id="testimonials">
<div class="container mx-auto px-4">
<div class="text-center mb-20 max-w-3xl mx-auto">
<span class="text-primary font-bold uppercase tracking-widest text-xs mb-4 block">Ils ont passé le cap</span>
<h2 class="text-4xl md:text-5xl font-black mb-6 text-slate-900 dark:text-white tracking-tight">
L'Avis de la Communauté Trail Vital</h2>
<p class="text-slate-600 dark:text-slate-400 text-lg">Découvrez pourquoi des centaines de coureurs d'ultra-marathon nous font confiance pour leur plan d'hydratation et d'énergie naturelle sans maux de ventre.</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-3 gap-8">
<!-- Testimonial 1 -->
<div class="glass-panel p-10 rounded-3xl shadow-lg border border-gray-100 dark:border-gray-700 relative">
<span class="quote-icon">"</span>
<div class="flex text-yellow-400 text-sm mb-6">
<span class="material-icons text-lg">star</span><span class="material-icons text-lg">star</span><span class="material-icons text-lg">star</span><span class="material-icons text-lg">star</span><span class="material-icons text-lg">star</span>
</div>
<p class="text-slate-700 dark:text-slate-300 mb-8 italic text-lg leading-relaxed">"Premier 80km terminé sans aucun problème digestif. Le pack m'a enlevé une charge mentale énorme avant la course. Je recommande à 100% !"</p>
<div class="flex items-center gap-4 mt-auto">
<img src="https://i.pravatar.cc/150?u=4" alt="Sophie B." class="w-14 h-14 rounded-full border-2 border-primary/20">
<div>
<p class="font-bold text-slate-900 dark:text-white">Sophie B.</p>
<p class="text-xs text-slate-500 font-medium">Finisher SaintéLyon</p>
</div>
</div>
</div>
<!-- Testimonial 2 -->
<div class="glass-panel p-10 rounded-3xl shadow-xl shadow-primary/5 border border-primary/10 relative transform md:-translate-y-6">
<span class="quote-icon">"</span>
<div class="flex text-yellow-400 text-sm mb-6">
<span class="material-icons text-lg">star</span><span class="material-icons text-lg">star</span><span class="material-icons text-lg">star</span><span class="material-icons text-lg">star</span><span class="material-icons text-lg">star</span>
</div>
<p class="text-slate-700 dark:text-slate-300 mb-8 italic text-lg leading-relaxed">"Les gommes sont incroyables et l'hydratation au top. C'est la première fois que j'arrive à la ligne d'arrivée d'un ultra avec de l'énergie à revendre."</p>
<div class="flex items-center gap-4 mt-auto">
<img src="https://i.pravatar.cc/150?u=5" alt="Marc T." class="w-14 h-14 rounded-full border-2 border-primary/20">
<div>
<p class="font-bold text-slate-900 dark:text-white">Marc T.</p>
<p class="text-xs text-slate-500 font-medium">Finisher UTMB</p>
</div>
</div>
</div>
<!-- Testimonial 3 -->
<div class="glass-panel p-10 rounded-3xl shadow-lg border border-gray-100 dark:border-gray-700 relative">
<span class="quote-icon">"</span>
<div class="flex text-yellow-400 text-sm mb-6">
<span class="material-icons text-lg">star</span><span class="material-icons text-lg">star</span><span class="material-icons text-lg">star</span><span class="material-icons text-lg">star</span><span class="material-icons text-lg">star</span>
</div>
<p class="text-slate-700 dark:text-slate-300 mb-8 italic text-lg leading-relaxed">"Concept génial. J'ai rempli le quiz, reçu ma boîte 3 jours après. Les textures hydrogel sont passées toutes seules sous 35 degrés."</p>
<div class="flex items-center gap-4 mt-auto">
<img src="https://i.pravatar.cc/150?u=6" alt="Julien R." class="w-14 h-14 rounded-full border-2 border-primary/20">
<div>
<p class="font-bold text-slate-900 dark:text-white">Julien R.</p>
<p class="text-xs text-slate-500 font-medium">Finisher Templiers</p>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- FAQ Section -->
<section class="py-24 bg-white dark:bg-gray-800" id="faq">
<div class="container mx-auto px-4 max-w-3xl">
<div class="text-center mb-16">
<h2 class="text-3xl md:text-5xl font-black text-slate-900 dark:text-white tracking-tight mb-4">Questions Fréquentes sur notre Nutrition d'Épreuve</h2>
</div>
<div class="space-y-4">
<details class="group bg-slate-50 dark:bg-slate-900/50 rounded-2xl border border-gray-100 dark:border-gray-700 shadow-sm transition-all duration-300 [&_summary::-webkit-details-marker]:hidden">
<summary class="flex items-center justify-between p-6 font-bold text-slate-900 dark:text-white cursor-pointer list-none select-none">
Quand vais-je recevoir mon pack mensuel ?
<span class="transition group-open:rotate-180 material-icons text-primary bg-primary/10 rounded-full p-1">expand_more</span>
</summary>
<div class="p-6 pt-0 text-slate-600 dark:text-slate-400 leading-relaxed border-t border-gray-100 dark:border-gray-700 mt-2">
Vos packs sont expédiés pour que vous les receviez toujours 5 jours avant le début de votre nouveau mois d'entraînement. Pour le mois 1, l'expédition se fait sous 24h après votre commande.
</div>
</details>
<details class="group bg-slate-50 dark:bg-slate-900/50 rounded-2xl border border-gray-100 dark:border-gray-700 shadow-sm transition-all duration-300 [&_summary::-webkit-details-marker]:hidden">
<summary class="flex items-center justify-between p-6 font-bold text-slate-900 dark:text-white cursor-pointer list-none select-none">
Puis-je modifier mes préférences en cours de préparation ?
<span class="transition group-open:rotate-180 material-icons text-primary bg-primary/10 rounded-full p-1">expand_more</span>
</summary>
<div class="p-6 pt-0 text-slate-600 dark:text-slate-400 leading-relaxed border-t border-gray-100 dark:border-gray-700 mt-2">
Oui, absolument. Si un produit ne vous convient pas lors du "Mois 1 - Phase de test", vous pouvez mettre à jour votre profil depuis votre espace client. Le prochain pack sera ajusté (changement de parfum, texture, ou retrait d'un allergène).
</div>
</details>
<details class="group bg-slate-50 dark:bg-slate-900/50 rounded-2xl border border-gray-100 dark:border-gray-700 shadow-sm transition-all duration-300 [&_summary::-webkit-details-marker]:hidden">
<summary class="flex items-center justify-between p-6 font-bold text-slate-900 dark:text-white cursor-pointer list-none select-none">
L'abonnement est-il remboursable ou avec engagement ?
<span class="transition group-open:rotate-180 material-icons text-primary bg-primary/10 rounded-full p-1">expand_more</span>
</summary>
<div class="p-6 pt-0 text-slate-600 dark:text-slate-400 leading-relaxed border-t border-gray-100 dark:border-gray-700 mt-2">
Notre programme est sans engagement. Vous pouvez l'annuler à tout moment en un clic. Cependant, les packs déjà expédiés et alimentaires ne sont pas remboursables pour des raisons d'hygiène.
</div>
</details>
</div>
</div>
</section>
<!-- Final CTA Section -->
<section class="py-24 bg-[#E86E0A] bg-gradient-to-br from-[#E86E0A] to-[#D56000] relative overflow-hidden flex flex-col items-center justify-center text-center">
<!-- Pattern background -->
<div class="absolute inset-0 opacity-[0.12]" style="background-image: url('data:image/svg+xml,%3Csvg width=\'60\' height=\'60\' viewBox=\'0 0 60 60\' xmlns=\'http://www.w3.org/2000/svg\'%3E%3Cpath d=\'M16 11h-2v4h-4v2h4v4h2v-4h4v-2h-4v-4z\' fill=\'%23ffffff\'/%3E%3Cpath d=\'M41 15h8v2h-8z\' fill=\'%23ffffff\'/%3E%3Cpath d=\'M11 45h8v2h-8z\' fill=\'%23ffffff\'/%3E%3Cpath d=\'M46 41h-2v4h-4v2h4v4h2v-4h4v-2h-4v-4z\' fill=\'%23ffffff\'/%3E%3C/svg%3E'); background-size: 60px 60px;"></div>
<div class="container mx-auto px-4 relative z-10">
<h2 class="text-4xl md:text-6xl font-black text-white mb-6 drop-shadow-sm tracking-tight">Prêt à battre votre record ?</h2>
<p class="text-white/90 text-lg md:text-xl font-medium mb-10 max-w-2xl mx-auto">Rejoignez des milliers de trailers qui s'alimentent mieux.</p>
<a href="#" onclick="showView('quiz'); return false;" class="inline-block bg-white text-[#E86E0A] hover:bg-gray-50 text-lg md:text-xl font-bold py-4 px-10 rounded-full shadow-lg hover:shadow-xl transition-all transform hover:-translate-y-1">
Commencer mon plan
</a>
</div>
</section>
</main></div>
<div id="view-quiz" style="display:none;"><main class="pt-32 pb-20 container mx-auto px-4 max-w-2xl">
<div class="bg-white dark:bg-gray-800 rounded-3xl p-8 shadow-2xl border border-gray-100 dark:border-gray-700">
<form id="nutrition-quiz">
<!-- Step 1: Biometrics & Training -->
<div id="step-1" class="step">
<h2 class="text-3xl font-black mb-6 text-slate-900 dark:text-white">Parlez-nous de vous</h2>
<div class="space-y-6">
<div>
<label class="block text-sm font-bold text-slate-700 dark:text-slate-300 mb-2">Poids
(kg)</label>
<input type="number" name="weight_kg" value="75" required
class="w-full bg-gray-50 dark:bg-gray-900 border-none ring-1 ring-gray-200 dark:ring-gray-700 rounded-xl p-4 focus:ring-2 focus:ring-primary">
</div>
<div>
<label class="block text-sm font-bold text-slate-700 dark:text-slate-300 mb-2">Genre</label>
<select name="gender"
class="w-full bg-gray-50 dark:bg-gray-900 border-none ring-1 ring-gray-200 dark:ring-gray-700 rounded-xl p-4 focus:ring-2 focus:ring-primary appearance-none">
<option value="male">Homme</option>
<option value="female">Femme</option>
</select>
</div>
<div>
<label class="block text-sm font-bold text-slate-700 dark:text-slate-300 mb-2">Nombre de
séances par semaine</label>
<input type="number" name="sessions_per_week" value="4" required
class="w-full bg-gray-50 dark:bg-gray-900 border-none ring-1 ring-gray-200 dark:ring-gray-700 rounded-xl p-4 focus:ring-2 focus:ring-primary">
</div>
<div>
<label class="block text-sm font-bold text-slate-700 dark:text-slate-300 mb-2">Durée moyenne
sortie longue (heures)</label>
<input type="number" step="0.5" name="average_long_run_hours" value="2.5" required
class="w-full bg-gray-50 dark:bg-gray-900 border-none ring-1 ring-gray-200 dark:ring-gray-700 rounded-xl p-4 focus:ring-2 focus:ring-primary">
</div>
</div>
</div>
<!-- Step 2: Preferences & Sensitivity -->
<div id="step-2" class="step hidden">
<h2 class="text-3xl font-black mb-6 text-slate-900 dark:text-white">Vos habitudes</h2>
<div class="space-y-6">
<div>
<label class="block text-sm font-bold text-slate-700 dark:text-slate-300 mb-2">Taux de
sudation</label>
<select name="sweat_rate_level"
class="w-full bg-gray-50 dark:bg-gray-900 border-none ring-1 ring-gray-200 dark:ring-gray-700 rounded-xl p-4 focus:ring-2 focus:ring-primary appearance-none">
<option value="1">Faible</option>
<option value="2">Moyen</option>
<option value="3" selected>Élevé (Traces de sel)</option>
</select>
</div>
<div>
<label class="block text-sm font-bold text-slate-700 dark:text-slate-300 mb-2">Sensibilité
digestive</label>
<select name="digestive_sensitivity"
class="w-full bg-gray-50 dark:bg-gray-900 border-none ring-1 ring-gray-200 dark:ring-gray-700 rounded-xl p-4 focus:ring-2 focus:ring-primary appearance-none">
<option value="low">Faible</option>
<option value="medium">Moyenne</option>
<option value="high" selected>Élevée (Estomac sensible)</option>
</select>
</div>
<div>
<label class="block text-sm font-bold text-slate-700 dark:text-slate-300 mb-2">Goût
préféré</label>
<select name="flavor_preference"
class="w-full bg-gray-50 dark:bg-gray-900 border-none ring-1 ring-gray-200 dark:ring-gray-700 rounded-xl p-4 focus:ring-2 focus:ring-primary appearance-none">
<option value="fruity" selected>Fruité</option>
<option value="neutral">Neutre</option>
<option value="salty">Salé</option>
</select>
</div>
</div>
</div>
<!-- Step 3: Race Goals -->
<div id="step-3" class="step hidden">
<h2 class="text-3xl font-black mb-6 text-slate-900 dark:text-white">Votre prochain objectif</h2>
<div class="space-y-6">
<div>
<label class="block text-sm font-bold text-slate-700 dark:text-slate-300 mb-2">Nom de la
course</label>
<input type="text" name="race_name" value="UTMB CCC" required
class="w-full bg-gray-50 dark:bg-gray-900 border-none ring-1 ring-gray-200 dark:ring-gray-700 rounded-xl p-4 focus:ring-2 focus:ring-primary">
</div>
<div>
<label class="block text-sm font-bold text-slate-700 dark:text-slate-300 mb-2">Distance
(km)</label>
<input type="number" name="distance_km" value="100" required
class="w-full bg-gray-50 dark:bg-gray-900 border-none ring-1 ring-gray-200 dark:ring-gray-700 rounded-xl p-4 focus:ring-2 focus:ring-primary">
</div>
<div>
<label class="block text-sm font-bold text-slate-700 dark:text-slate-300 mb-2">Dénivelé
positif (m)</label>
<input type="number" name="elevation_gain_m" value="6100" required
class="w-full bg-gray-50 dark:bg-gray-900 border-none ring-1 ring-gray-200 dark:ring-gray-700 rounded-xl p-4 focus:ring-2 focus:ring-primary">
</div>
<div>
<label class="block text-sm font-bold text-slate-700 dark:text-slate-300 mb-2">Date de la
course</label>
<input type="date" name="race_date" required
class="w-full bg-gray-50 dark:bg-gray-900 border-none ring-1 ring-gray-200 dark:ring-gray-700 rounded-xl p-4 focus:ring-2 focus:ring-primary">
</div>
<div>
<label class="block text-sm font-bold text-slate-700 dark:text-slate-300 mb-2">Temps estimé
(heures)</label>
<input type="number" step="1" name="estimated_time_hours" value="15" required
class="w-full bg-gray-50 dark:bg-gray-900 border-none ring-1 ring-gray-200 dark:ring-gray-700 rounded-xl p-4 focus:ring-2 focus:ring-primary">
</div>
</div>
</div>
<!-- Navigation -->
<div class="mt-12 flex justify-between gap-4">
<button type="button" id="prev-btn"
class="hidden flex-1 bg-gray-100 dark:bg-gray-700 text-slate-700 dark:text-slate-300 font-bold py-4 rounded-xl transition-all">Précédent</button>
<button type="button" id="next-btn"
class="flex-1 bg-primary hover:bg-primary-dark text-white font-bold py-4 rounded-xl shadow-lg transition-all">Suivant</button>
<button type="submit" id="submit-btn"
class="hidden flex-1 bg-slate-900 dark:bg-white text-white dark:text-slate-900 font-bold py-4 rounded-xl shadow-lg transition-all">Voir
mon pack</button>
</div>
</form>
</div>
</main></div>
<div id="view-results" style="display:none;"><main class="pt-32 pb-20 container mx-auto px-4 max-w-5xl">
<div id="results-content">
<!-- Results will be injected here -->
<div class="flex items-center justify-center h-64">
<p class="text-xl animate-pulse">Calcul de votre pack idéal...</p>
</div>
</div>
</main></div>
<footer class="bg-navy-dark text-white pt-24 pb-12 border-t border-white/5 relative overflow-hidden">
<div class="absolute top-0 left-0 w-full h-1 bg-gradient-to-r from-primary via-orange-400 to-primary/50"></div>
<div class="container mx-auto px-4 relative z-10">
<div class="grid grid-cols-1 md:grid-cols-4 gap-12 mb-16">
<div class="col-span-1 md:col-span-1">
<a class="flex items-center gap-3 mb-6" href="#" onclick="showView('home'); return false;">
<div class="w-10 h-10 rounded-full bg-primary flex items-center justify-center text-white">
<span class="material-icons text-xl">terrain</span>
</div>
<span class="font-extrabold text-2xl tracking-tight text-white">Trail<span
class="text-primary">Vital</span></span>
</a>
<p class="text-slate-400 text-sm leading-relaxed mb-6">
L'excellence de la nutrition sportive naturelle pour les coureurs d'ultra-distance. Conçu par
des passionnés, validé par la science.
</p>
<div class="flex gap-4">
<a href="https://www.strava.com/" target="_blank"
class="w-10 h-10 rounded-full bg-white/5 flex items-center justify-center hover:bg-primary transition-colors border border-white/10 group">
<!-- Strava Icon -->
<svg class="w-5 h-5 fill-current text-white group-hover:text-white transition-colors" viewBox="0 0 24 24">
<path d="M15.387 17.944l-2.089-4.116h-3.065L15.387 24l5.15-10.172h-3.066m-7.008-5.599l2.836 5.598h4.172L10.463 0l-7 13.828h4.169"/>
</svg>
</a>
<a href="#"
class="w-10 h-10 rounded-full bg-white/5 flex items-center justify-center hover:bg-primary transition-colors border border-white/10">
<!-- Instagram Icon -->
<svg class="w-5 h-5 fill-current" viewBox="0 0 24 24">
<path
d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948 0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98-1.281-.059-1.69-.073-4.949-.073zm0 5.838c-3.403 0-6.162 2.759-6.162 6.162s2.759 6.163 6.162 6.163 6.162-2.759 6.162-6.163c0-3.403-2.759-6.162-6.162-6.162zm0 10.162c-2.209 0-4-1.79-4-4 0-2.209 1.791-4 4-4s4 1.791 4 4c0 2.21-1.791 4-4 4zm6.406-11.845c-.796 0-1.441.645-1.441 1.44s.645 1.44 1.441 1.44c.795 0 1.439-.645 1.439-1.44s-.644-1.44-1.439-1.44z" />
</svg>
</a>
</div>
</div>
<div class="col-span-1">
<h3 class="text-white font-bold mb-6">Navigation</h3>
<ul class="space-y-4">
<li><a href="concept.html"
class="text-slate-400 hover:text-primary transition-colors text-sm">Comment ça
marche</a></li>
<li><a href="explore.html"
class="text-slate-400 hover:text-primary transition-colors text-sm">Explorer</a></li>
<li><a href="#" onclick="showView('quiz'); return false;"
class="text-slate-400 hover:text-primary transition-colors text-sm">Créer mon pack</a>
</li>
<li><a href="#" class="text-slate-400 hover:text-primary transition-colors text-sm">Science &
Nutrition</a></li>
</ul>
</div>
<div class="col-span-1">
<h3 class="text-white font-bold mb-6">Aide & Support</h3>
<ul class="space-y-4">
<li><a href="#" class="text-slate-400 hover:text-primary transition-colors text-sm">FAQ</a></li>
<li><a href="#"
class="text-slate-400 hover:text-primary transition-colors text-sm">Livraison</a></li>
<li><a href="#" class="text-slate-400 hover:text-primary transition-colors text-sm">Retours</a>
</li>
<li><a href="#" class="text-slate-400 hover:text-primary transition-colors text-sm">Contact</a>
</li>
</ul>
</div>
<div class="col-span-1">
<h3 class="text-white font-bold mb-6">Newsletter</h3>
<p class="text-slate-400 text-sm mb-6">Recevez nos conseils nutritionnels et nos offres exclusives.
</p>
<div class="relative">
<input type="email" placeholder="votre@email.com"
class="w-full bg-white/5 border border-white/10 rounded-xl py-3 px-4 text-white text-sm focus:outline-none focus:ring-2 focus:ring-primary/50 transition-all">
<button
class="absolute right-2 top-2 bg-primary hover:bg-primary-dark text-white p-1.5 rounded-lg transition-colors">
<span class="material-icons text-sm">send</span>
</button>
</div>
</div>
</div>
<div
class="pt-8 border-t border-white/5 flex flex-col md:flex-row justify-between items-center gap-6 text-xs text-slate-500 font-medium">
<div class="flex items-center gap-8">
<p>© 2024 Trail Vital Nutrition. Fait avec passion dans les Alpes.</p>
</div>
<div class="flex gap-8">
<a href="#" class="hover:text-primary transition-colors">Politique de confidentialité</a>
<a href="#" class="hover:text-primary transition-colors">CGV</a>
<a href="#" class="hover:text-primary transition-colors">Mentions légales</a>
</div>
</div>
</div>
</footer>
<script>
// CORE ALGORITHM
const CATALOG = [
// Hydration
{
id: "prod_001",
name: "Poudre Iso Menthe Salée",
type: "drink_mix",
category: "hydration",
macros: { carbs_g: 35, sodium_mg: 500, magnesium_mg: 50 },
attributes: { texture: "liquid", taste_profile: "salty", digestibility_score: 10 },
stock_unit: "sachet_500ml",
price: 2.50
},
{
id: "prod_001b",
name: "Poudre Iso Fraise",
type: "drink_mix",
category: "hydration",
macros: { carbs_g: 35, sodium_mg: 300, magnesium_mg: 50 },
attributes: { texture: "liquid", taste_profile: "fruity", digestibility_score: 10 },
stock_unit: "sachet_500ml",
price: 2.50
},
{
id: "prod_001c",
name: "Poudre Iso Neutre",
type: "drink_mix",
category: "hydration",
macros: { carbs_g: 35, sodium_mg: 400, magnesium_mg: 50 },
attributes: { texture: "liquid", taste_profile: "neutral", digestibility_score: 10 },
stock_unit: "sachet_500ml",
price: 2.50
},
// Gels
{
id: "prod_002a",
name: "Gel Hydro Pomme",
type: "gel",
category: "energy",
macros: { carbs_g: 25, sodium_mg: 20 },
attributes: { texture: "hydrogel", taste_profile: "fruity", caffeine: false, digestibility_score: 9 },
stock_unit: "unité",
price: 3.00
},
{
id: "prod_002b",
name: "Gel Hydro Neutre",
type: "gel",
category: "energy",
macros: { carbs_g: 25, sodium_mg: 20 },
attributes: { texture: "hydrogel", taste_profile: "neutral", caffeine: false, digestibility_score: 9 },
stock_unit: "unité",
price: 3.00
},
{
id: "prod_002c",
name: "Purée Patate Douce / Sel",
type: "gel",
category: "energy",
macros: { carbs_g: 20, sodium_mg: 200 },
attributes: { texture: "puree", taste_profile: "salty", caffeine: false, digestibility_score: 10 },
stock_unit: "gourde",
price: 3.50
},
// Salts
{
id: "prod_003",
name: "Salt Caps High Sodium",
type: "salt_tab",
category: "electrolytes",
macros: { carbs_g: 0, sodium_mg: 250 },
attributes: { texture: "capsule", taste_profile: "neutral", digestibility_score: 10 },
stock_unit: "gélule",
price: 0.50
},
// Bars
{
id: "prod_004a",
name: "Barre Avoine Banane",
type: "bar",
category: "energy",
macros: { carbs_g: 40, sodium_mg: 50 },
attributes: { texture: "solid", taste_profile: "fruity", digestibility_score: 5 },
stock_unit: "unité",
price: 2.80
},
{
id: "prod_004b",
name: "Barre Amande Vanille",
type: "bar",
category: "energy",
macros: { carbs_g: 40, sodium_mg: 100 },
attributes: { texture: "solid", taste_profile: "neutral", digestibility_score: 5 },
stock_unit: "unité",
price: 2.80
},
{
id: "prod_004c",
name: "Barre Cacahuète Salée",
type: "bar",
category: "energy",
macros: { carbs_g: 35, sodium_mg: 300 },
attributes: { texture: "solid", taste_profile: "salty", digestibility_score: 5 },
stock_unit: "unité",
price: 2.80
},
// Recovery
{
id: "prod_005",
name: "Mix de Récupération Choco",
type: "drink_mix",
category: "recovery",
macros: { carbs_g: 45, protein_g: 20, sodium_mg: 300 },
attributes: { texture: "liquid", taste_profile: "neutral", digestibility_score: 8 },
stock_unit: "sachet_portion",
price: 3.50
}
];
function calculateDurationInMonths(startDate, raceDate) {
const start = new Date(startDate);
const end = new Date(raceDate);
// Difference based on calendar months
let months = (end.getFullYear() - start.getFullYear()) * 12;
months -= start.getMonth();
months += end.getMonth();
// Total months including current and destination
return Math.max(1, months + 1);
}
function generatePreparationPlan(userData) {
const { questionnaire_answers, race_goals } = userData;
const today = new Date().toISOString().split(‘T’)[0];
const duration = calculateDurationInMonths(today, race_goals.race_date);
const plan = {
plan_id: `plan_${Date.now()}`,
user_id: "user_999", // Placeholder
goal_id: race_goals.race_name,
status: "actif",
start_date: today,
duration_months: duration,
monthly_deliveries: []
};
for (let i = 1; i <= duration; i++) {
let phase = "";
let objective = "";
if (i === duration) {
phase = "affutage_et_jour_j";
objective = "Affûtage et Jour J";
} else if (i === 1 && duration > 1) {
phase = "decouverte_et_tests";
objective = "Découverte et tests digestifs";
} else {
phase = "volume_et_intensite";
objective = "Intensification de l'entraînement";
}
const deliveryDate = new Date();
deliveryDate.setMonth(deliveryDate.getMonth() + (i - 1));
plan.monthly_deliveries.push({
month_index: i,
delivery_date: deliveryDate.toISOString().split('T')[0],
phase: phase,
objective: objective,
pack: generatePackForPhase(phase, userData),
status: i === 1 ? "livré" : "programmé"
});
}
return plan;
}
function generatePackForPhase(phase, userData) {
const { questionnaire_answers, race_goals } = userData;
const contents = [];
// User preference fallback logic
const tastePref = questionnaire_answers.taste_preference || "neutral";
// Helper to find best matching product
const findBestMatch = (type) => {
const matchesType = CATALOG.filter(p => p.type === type);
// Try to match specific preferred taste
let match = matchesType.find(p => p.attributes.taste_profile === tastePref);
// If preferred taste not in catalog for this type, fallback to neutral, then anything
if (!match) match = matchesType.find(p => p.attributes.taste_profile === "neutral");
if (!match && matchesType.length > 0) match = matchesType[0];
return match;
};
// Replace hardcoded lookups with preference-based helper
const isoDrink = findBestMatch("drink_mix");
const gel = findBestMatch("gel");
const bar = findBestMatch("bar");
const saltTab = findBestMatch("salt_tab");
if (phase === "decouverte_et_tests") {
// Variety focused
if (isoDrink) contents.push({ product: isoDrink, total_quantity: 4, instruction: "Boisson : TESTER les saveurs" });
if (gel) contents.push({ product: gel, total_quantity: 4, instruction: "Gel : TESTER la texture hydrogel" });
if (bar) contents.push({ product: bar, total_quantity: 4, instruction: "Barre : TESTER la digestion à l'arrêt" });
if (saltTab) contents.push({ product: saltTab, total_quantity: 5, instruction: "Sels : TESTER en cas de forte chaleur" });
}
else if (phase === "volume_et_intensite") {
// Performance focused, consistent base
if (isoDrink) contents.push({ product: isoDrink, total_quantity: 12, instruction: "Base hydratation sorties longues" });
if (gel) contents.push({ product: gel, total_quantity: 12, instruction: "Énergie : Entraînement 60g glucides/h" });
// Remove bars if sensitivity is high, otherwise keep as regular fuel
if (questionnaire_answers.digestive_sensitivity !== "high" && bar) {
contents.push({ product: bar, total_quantity: 6, instruction: "Solide : Pour le plaisir des sorties calmes" });
}
}
else if (phase === "affutage_et_jour_j") {
// Race Pack + Tapering
const hours = race_goals.estimated_time_hours;
if (isoDrink) contents.push({ product: isoDrink, total_quantity: Math.ceil(hours), instruction: "COURSE : 1 sachet par heure" });
if (gel) contents.push({ product: gel, total_quantity: Math.ceil(hours * 1.5), instruction: "COURSE : 1 à 2 gels par heure" });
// Special Race Day items
contents.push({
product: { name: "Maltodextrine de Recharge", type: "recharge", macros: { carbs_g: 50 }, price: 4.50 },
total_quantity: 3,
instruction: "J-3 à J-1 : Augmenter les réserves de glycogène"
});
contents.push({
product: { name: "Gâteau Sport Vitalité", type: "petit_dej", macros: { carbs_g: 65 }, price: 6.00 },
total_quantity: 1,
instruction: "H-3 avant départ : Énergie stable"
});
}
return { contents };
}
function calculatePackPrice(pack) {
let total = 0;
if (pack && pack.contents) {
for (const item of pack.contents) {
if (item.product && typeof item.product.price === ‘number’) {
total += item.product.price * item.total_quantity;
}
}
}
return total;
}
// Keep the old function for compatibility if needed, but point it to the new logic
function calculateRecommendation(userData) {
const plan = generatePreparationPlan(userData);
// Return the final month pack for « backward compatibility » in the UI if needed
// The old function returned targets and contents from the last month.
// The new instruction removes targets and returns the whole plan.
// I will remove the targets and contents from the return object as per the new instruction.
return { plan };
}
</script>
<script>
// VIEW CONTROLLER
function showView(viewId) {
document.getElementById('view-home').style.display = 'none';
document.getElementById('view-quiz').style.display = 'none';
document.getElementById('view-results').style.display = 'none';
document.getElementById('view-' + viewId).style.display = 'block';
window.scrollTo(0, 0);
if (viewId === 'results') {
renderResults();
}
}
</script>
<script>
// QUIZ LOGIC
(function() {
const form = document.getElementById('nutrition-quiz');
const steps = document.querySelectorAll('.step');
const prevBtn = document.getElementById('prev-btn');
const nextBtn = document.getElementById('next-btn');
const submitBtn = document.getElementById('submit-btn');
let currentStep = 0;
nextBtn.addEventListener('click', () => {
steps[currentStep].classList.add('hidden');
currentStep++;
steps[currentStep].classList.remove('hidden');
updateButtons();
});
prevBtn.addEventListener('click', () => {
steps[currentStep].classList.add('hidden');
currentStep--;
steps[currentStep].classList.remove('hidden');
updateButtons();
});
function updateButtons() {
prevBtn.classList.toggle('hidden', currentStep === 0);
nextBtn.classList.toggle('hidden', currentStep === steps.length - 1);
submitBtn.classList.toggle('hidden', currentStep !== steps.length - 1);
}
form.addEventListener('submit', (e) => {
e.preventDefault();
const formData = new FormData(form);
const data = Object.fromEntries(formData.entries());
// Structure data to match expected profile/goal formats
const payload = {
biometrics: {
weight_kg: parseFloat(data.weight_kg),
gender: data.gender
},
questionnaire_answers: {
sweat_rate_level: parseInt(data.sweat_rate_level),
digestive_sensitivity: data.digestive_sensitivity,
flavor_preference: data.flavor_preference
},
training_volume: {
sessions_per_week: parseInt(data.sessions_per_week),
average_long_run_hours: parseFloat(data.average_long_run_hours)
},
race_goals: {
race_name: data.race_name,
distance_km: parseInt(data.distance_km),
elevation_gain_m: parseInt(data.elevation_gain_m),
race_date: data.race_date,
estimated_time_hours: parseInt(data.estimated_time_hours)
}
};
localStorage.setItem('trail_vital_user_selection', JSON.stringify(payload));
showView('results');
});
})();
</script>
<script>
// RESULTS LOGIC
function renderResults() {
const userData = JSON.parse(localStorage.getItem('trail_vital_user_selection'));
if (!userData) {
showView('home');
return;
}
const result = calculateRecommendation(userData);
const plan = result.plan;
const resultsContainer = document.getElementById('results-content');
// Helper to format date
const formatDate = (dateStr) => {
const date = new Date(dateStr);
return date.toLocaleDateString('fr-FR', { month: 'long', year: 'numeric' });
};
let html = `
<div class="grid lg:grid-cols-4 gap-8">
<!-- Sidebar: User Info & Goals -->
<div class="lg:col-span-1">
<div class="summary-card p-8 rounded-3xl text-white shadow-2xl sticky top-32">
<h2 class="text-2xl font-black mb-6">Objectif</h2>
<div class="space-y-4 mb-10">
<div class="flex justify-between border-b border-white/10 pb-2">
<span class="opacity-70">Course</span>
<span class="font-bold text-right">${userData.race_goals.race_name}</span>
</div>
<div class="flex justify-between border-b border-white/10 pb-2">
<span class="opacity-70">Date</span>
<span class="font-bold text-right">${new Date(userData.race_goals.race_date).toLocaleDateString('fr-FR')}</span>
</div>
<div class="flex justify-between border-b border-white/10 pb-2">
<span class="opacity-70">Distance</span>
<span class="font-bold text-right">${userData.race_goals.distance_km} km</span>
</div>
<div class="flex justify-between border-b border-white/10 pb-2">
<span class="opacity-70">Plan</span>
<span class="font-bold text-right">${plan.duration_months} mois</span>
</div>
</div>
<div class="bg-white/5 p-4 rounded-2xl">
<h3 class="text-sm font-bold opacity-70 mb-2 uppercase">Statut Prépa</h3>
<div class="flex items-center gap-3">
<div class="w-3 h-3 rounded-full bg-secondary animate-pulse"></div>
<span class="font-bold">Plan Actif</span>
</div>
</div>
</div>
</div>
<!-- Main Content: Roadmap -->
<div class="lg:col-span-3 space-y-12">
<header>
<h1 class="text-4xl md:text-5xl font-black text-slate-900 dark:text-white mb-4">Votre <span class="text-primary">Plan de Préparation</span></h1>
<p class="text-slate-500 text-lg">Nous avons découpé votre préparation en ${plan.duration_months} mois d'accompagnement sur-mesure.</p>
</header>
<div class="space-y-16">
${plan.monthly_deliveries.map((delivery, index) => `
<section class="relative pl-8 md:pl-0">
<!-- Timeline Line -->
${index !== plan.monthly_deliveries.length - 1 ? '<div class="absolute left-0 md:left-1/2 top-10 bottom-0 w-1 bg-gray-100 dark:bg-gray-800 -translate-x-1/2 hidden md:block"></div>' : ''}
<div class="flex flex-col md:flex-row items-start gap-8">
<div class="md:w-1/2 md:text-right">
<div class="inline-block px-4 py-1 rounded-full bg-primary/10 text-primary font-bold text-sm mb-2 uppercase">
Mois ${delivery.month_index} - ${formatDate(delivery.delivery_date)}
</div>
<h2 class="text-3xl font-black text-slate-900 dark:text-white mb-2">${delivery.objective}</h2>
<p class="text-slate-500 italic mb-8">Phase : ${delivery.phase.replace(/_/g, ' ')}</p>
<!-- Image of the Box -->
<div class="hidden md:block rounded-2xl overflow-hidden shadow-xl border border-gray-100 dark:border-gray-700 max-w-xs ml-auto transform transition hover:-translate-y-1 hover:shadow-2xl">
<img src="box_mockup.png" alt="Box Trail Vital Mensuelle avec produits" class="w-full h-auto object-cover hover:scale-105 transition-transform duration-700"/>
</div>
</div>
<div class="hidden md:flex flex-shrink-0 w-12 h-12 rounded-full bg-primary items-center justify-center text-white z-10 border-4 border-white dark:border-gray-900 shadow-xl">
<span class="material-icons text-sm">${delivery.phase === 'affutage_et_jour_j' ? 'flag' : 'directions_run'}</span>
</div>
<div class="md:w-1/2 w-full">
<div class="bg-white dark:bg-gray-800 p-6 rounded-3xl shadow-xl border border-gray-100 dark:border-gray-700">
<h4 class="font-bold text-slate-900 dark:text-white mb-4 flex items-center gap-2">
<span class="material-icons text-primary">shopping_bag</span>
Pack Mensuel
</h4>
<div class="space-y-4">
${delivery.pack.contents.map(item => `
<div class="flex items-center justify-between py-2 border-b border-gray-50 dark:border-gray-700 last:border-0">
<div>
<p class="font-bold text-slate-800 dark:text-slate-200">${item.product.name}</p>
<p class="text-xs text-slate-500">${item.instruction}</p>
</div>
<div class="text-primary font-black">x${item.total_quantity}</div>
</div>
`).join('')}
</div>
${delivery.phase === 'affutage_et_jour_j' ? `
<div class="mt-6 p-4 bg-orange-50 dark:bg-orange-950/20 rounded-2xl border border-orange-100 dark:border-orange-900/40">
<p class="text-xs font-bold text-orange-600 dark:text-orange-400 uppercase mb-1">Inclus : Kit Jour J</p>
<p class="text-sm text-slate-600 dark:text-slate-400">Optimisé pour vos ${userData.race_goals.estimated_time_hours}h d'effort.</p>
</div>
` : ''}
</div>
</div>
</div>
</section>
`).join('')}
</div>
<div class="bg-slate-900 text-white p-10 rounded-[2.5rem] shadow-2xl relative overflow-hidden">
<div class="relative z-10">
<h3 class="text-3xl font-black mb-4">Prêt à démarrer l'aventure ?</h3>
<p class="text-slate-400 mb-8 max-w-lg">Recevez des produits adaptés à votre progression. Sans engagement, modifiable à tout moment.</p>
<button id="checkout-btn" class="bg-primary hover:bg-primary-dark text-white text-xl font-bold px-10 py-5 rounded-2xl shadow-lg transition-all transform hover:-translate-y-1">
Voir le prix et commander
</button>
</div>
<div class="absolute -right-20 -bottom-20 w-80 h-80 bg-primary/20 rounded-full blur-3xl"></div>
</div>
</div>
</div>
`;
resultsContainer.innerHTML = html;
document.getElementById('checkout-btn').addEventListener('click', () => {
alert('Redirection vers WooCommerce WordPress Checkout...');
});
}
</script>
