Drops the cylinder+box airplane built last commit in favor of a CC-BY
3D commercial airliner from Poly by Google (188 KB GLB, 11.3k tris,
hosted in assets/airplane.glb). Loaded at runtime via three/addons
GLTFLoader; importmap extended to expose the addons subpath.
Bug worth noting: a naive setFromObject + position.sub(center) +
scale.setScalar pipeline leaves the model offset by -center after
scaling because position is in pre-scale units. Fix is to wrap the
model in a Group, apply the centering offset to the inner model,
then scale the outer Group — the whole transform stays consistent.
Attribution added in two places per CC-BY 3.0:
- HTML header comment with creator + source URL + license link
- JS file header in intro-scene.js
Tone-mapping bumped to ACES filmic for a slightly nicer render.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Restructure the page so the first 4 viewports of scroll drive a
Three.js scene composited on top of the Antananarivo parachute video.
What's there:
- Three.js (ESM, r158 via importmap) renders a low-poly cargo airliner
built from primitives: cylinder fuselage, cone nose, sphere cockpit
(dark glass + emissive), box wings/tail/fin, cylinder engines with
torus intakes, gold trim band, navy fin with gold logo box. No
external model file.
- Hemisphere + directional + ambient lights tuned for golden-hour fill.
- 14 cloud spheres scattered around the plane, slowly rotating.
- GSAP + ScrollTrigger drive a single progress value scrubbed against
scroll position. Inside the rAF loop, the camera arcs from rear-left
(-0.6 rad) to front-right (+1.1 rad), radius dipping mid-flight, and
the plane rolls slightly with scroll.
- Three act labels (Paris CDG / Vol cargo / Antananarivo) cross-fade at
20%/40%-60%/72% scroll positions via a chained gsap timeline.
- Gold CTA button stays opacity:0 + pointer-events:none until the last
~10% of scroll, then fades and scales in. Hover transform rebuilt
without the old mouse-parallax tilt (fights the scroll animation).
- Scroll hint pill (chevron + "Faites défiler") at the bottom of the
first viewport, fades out on first scroll event.
- prefers-reduced-motion shortcut: scroll stage hidden, CTA visible,
no animation. Page reverts to a static screen with the video bg.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The new index.html is a 3-act scroll-driven storytelling intro:
Act 1 (Tarmac at sunset)
Sunset gradient sky, mountain silhouettes, hangar, runway with
centerline lights. Inline SVG cargo plane (MVA-branded gold tail)
sits on the ground while box emojis cycle up a loading ramp.
Act 2 (Take-off at dusk)
Dusk sky, two parallax cloud layers and distant mountains. The
plane translates diagonally up-and-right with a slight tilt and
a glowing contrail, sized down progressively.
Act 3 (Arrival at night)
Deep navy night sky with twinkling stars, a glowing moon, and
the Madagascar coastline silhouette. A small plane fades in
descending toward the island, then a centered CTA block reveals:
"Bienvenue à bord" with the gold "Accéder au site" button that
routes to accueil.html (the real homepage).
Implementation:
- Pure CSS layered scenes; no library
- Scroll progress driven by a single CSS custom property --scroll
(0→1) updated via rAF, layers transform off it
- Mouse-move parallax on layers via --mx/--my (skipped on touch)
- Inline SVG plane reused across the 3 scenes
- All text is i18n-driven with a new `intro` section in FR/EN/MG
Architecture changes:
- index.html → new parallax intro
- accueil.html → former index.html content (full homepage)
- All nav/logo/footer links updated index.html → accueil.html across
the 8 existing pages
- Mobile-nav on accueil.html now also includes Service Commande
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Footer copyright bumped to 2026 across all 8 HTML pages and in the
three translation strings (FR/EN/MG) in translations.js.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
"Dépasser les dimensions autorisées" now has an asterisk pointing to
a small italic note below the dos/donts grid: "Nous contacter pour
tout colis volumineux." (FR/EN/MG).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
New page service-commande.html explaining the order-on-behalf service:
- 10% commission on total order amount
- 50% deposit + 50% on order validation
- Right to request 100% upfront for large orders
- Standard 70,000 Ar/kg shipping fee on top, paid on receipt
- 5-question FAQ
- CTA to contact / Messenger
Trilingual content (FR / EN / MG) added to translations.js with full
serviceCommande section + nav.serviceCommande key.
Menu link inserted right after "Tarifs" in main nav, mobile nav and
footer links across all pages: index, about, tarifs, contact,
guide-envoi, application, cgv, service-commande.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When a client tries to re-register with an existing email:
- The form still shows the on-screen "already registered" message
- HubSpot data is still untouched (no duplicate, ref number preserved)
- NEW: a welcome-back email is now sent via EmailJS reminding them
of their existing client reference number
- The internal MVA notification (Formspree) is preserved
Requires creating a new EmailJS template (id: template_welcome_back)
with variables: firstname, email, reference_client.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace the cramped map-container layout with a polished map-card
- Centered section header (h2 + gold-line + subtitle) above the card
- Navy gradient header inside the card with gold location icon
- Address displayed in the header alongside an "open in Google Maps" CTA
- Increased map height to 420px (320px on mobile)
- Soft shadow and gold-tinted border for premium feel
- Added mapSubtitle translation key (FR/EN/MG)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Ajout de data-i18n sur tous les éléments non traduits (tarifs, contact, guide,
application, accueil) et ajout des clés correspondantes en FR/EN/MG dans
translations.js : détails tarifaires, cartes livraison, stats accueil, sections
CTA, récapitulatif contact, footer CGV.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
"Sarany" est le terme correct pour désigner les tarifs/prix dans ce contexte.
Corrige : heroTitle tarifs, heroSubtitle tarifs, nav pricing, heroCtaSecondary,
et value3Desc (about).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
"Fandefasana" est la forme correcte (nominalisée) en malgache pour désigner
le transport/fret aérien. Corrige le titre hero et 5 autres occurrences dans
les textes descriptifs, sous-titres et footer.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Mise à jour de toutes les mentions du délai de livraison sur l'ensemble du site
(index, tarifs, contact) et dans les 3 langues (FR/EN/MG) pour indiquer clairement
que les 2 semaines sont comptées à compter de l'arrivée du colis au dépôt de Paris.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Ajout du SDK EmailJS (CDN) dans contact.html
- Initialisation EmailJS avec la clé publique dans form-handler.js
- Nouvelle fonction sendWelcomeEmail() : envoie au client son prénom,
numéro de référence et l'adresse de dépôt Paris (AEIC Forwarding, Orly)
- Appel automatique dans showSuccess() après inscription réussie
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Active WORKER_PROXY_URL pointant vers mva-hubspot-proxy.mvaglobalfret.workers.dev.
Le Worker interroge l'API CRM HubSpot côté serveur (contourne le CORS) et
retourne les données du contact si l'email est déjà enregistré.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Supprime HUBSPOT_SERVICE_KEY du code JS public (évite l'exposition du token)
- Remplace l'appel CORS-bloqué vers api.hubapi.com par un appel au proxy
Cloudflare Worker (WORKER_PROXY_URL, vide par défaut = sans blocage)
- Ajoute cloudflare-worker/hubspot-proxy.js : code complet du Worker à
déployer gratuitement depuis dash.cloudflare.com (sans CLI ni Node.js)
- Quand WORKER_PROXY_URL est renseigné, la détection doublon est active :
un client existant voit son message "déjà inscrit" sans re-soumission
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- generateRefNumber() basé sur timestamp : références jamais identiques
- checkExistingContact() : lecture HubSpot via clé de service (read-only)
- Si email déjà connu : affiche message 'déjà client' + référence existante,
AUCUNE soumission envoyée (référence existante jamais modifiée)
- Notification interne Formspree si tentative double inscription
- Traductions FR/EN/MG pour les nouveaux messages