<!DOCTYPE html>
<html lang="fr" class="scroll-smooth">
<head>
<!-- Google Tag Manager bootstrap -->
<script>
window.dataLayer = window.dataLayer || [];
window.hydrostopLoadGtm = window.hydrostopLoadGtm || function () {
if (window.hydrostopGtmLoaded || document.getElementById('hydrostop-gtm-script')) return;
window.hydrostopGtmLoaded = true;
window.dataLayer.push({ 'gtm.start': new Date().getTime(), event: 'gtm.js' });
var firstScript = document.getElementsByTagName('script')[0];
var gtmScript = document.createElement('script');
gtmScript.id = 'hydrostop-gtm-script';
gtmScript.async = true;
gtmScript.src = 'https://www.googletagmanager.com/gtm.js?id=GTM-P66M6B4L';
firstScript.parentNode.insertBefore(gtmScript, firstScript);
};
(function () {
var storedConsent = null;
try {
storedConsent = window.localStorage.getItem('hydrostop_cookie_consent');
} catch (error) {
storedConsent = null;
}
if (storedConsent === 'accepted') {
window.hydrostopLoadGtm();
}
})();
</script>
<!-- End Google Tag Manager bootstrap -->
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hydrostop | Rénovation de canalisations et tuyaux sans tranchée</title>
<meta name="description" content="Hydrostop rénove les canalisations sans tranchée en Île-de-France avec des caméras HD et des équipements parmi les plus performants du marché : diagnostic précis, chantier propre et remise en service rapide.">
<link rel="canonical" href="https://hydrostop-fluides.fr/" />
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "ProfessionalService",
"name": "Hydrostop",
"url": "https://hydrostop-fluides.fr/",
"telephone": "+33765778276",
"email": "hydrostop.contact@gmail.com",
"areaServed": ["Paris", "Boulogne-Billancourt", "Nanterre", "Saint-Denis", "Créteil", "Versailles", "Île-de-France"],
"serviceType": ["Chemisage de canalisation", "Rénovation de canalisations sans tranchée", "Inspection caméra HD", "Traitement d'infiltration"],
"address": {
"@type": "PostalAddress",
"addressCountry": "FR"
}
}
</script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="preconnect" href="https://unpkg.com" crossorigin>
<link rel="preconnect" href="https://cdn.tailwindcss.com" crossorigin>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/lucide@latest" defer></script>
<link rel="preload" as="style" href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap" rel="stylesheet" media="print" onload="this.media='all'">
<noscript><link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap" rel="stylesheet"></noscript>
<style>
:root {
--hydrostop-consent-bg: rgba(15, 41, 66, 0.98);
--hydrostop-consent-border: rgba(255, 255, 255, 0.12);
--hydrostop-consent-text: #ffffff;
--hydrostop-consent-muted: rgba(255, 255, 255, 0.72);
--hydrostop-consent-accent: #e91e8c;
--hydrostop-consent-accent-hover: #f24ca6;
}
.hydrostop-consent {
position: fixed;
left: 16px;
right: 16px;
bottom: 16px;
z-index: 1000;
display: none;
}
.hydrostop-consent.is-visible {
display: block;
}
.hydrostop-consent__card {
max-width: 880px;
margin: 0 auto;
padding: 24px;
border-radius: 18px;
border: 1px solid var(--hydrostop-consent-border);
background:
radial-gradient(circle at top left, rgba(233, 30, 140, 0.18), transparent 34%),
var(--hydrostop-consent-bg);
color: var(--hydrostop-consent-text);
box-shadow: 0 24px 80px rgba(2, 8, 23, 0.4);
backdrop-filter: blur(14px);
}
.hydrostop-consent__eyebrow {
display: inline-block;
margin: 0 0 12px;
color: var(--hydrostop-consent-accent);
font-size: 11px;
font-weight: 800;
letter-spacing: 0.28em;
text-transform: uppercase;
}
.hydrostop-consent__title {
margin: 0 0 10px;
font-size: 28px;
font-weight: 800;
line-height: 1.1;
}
.hydrostop-consent__text {
margin: 0;
max-width: 680px;
color: var(--hydrostop-consent-muted);
font-size: 15px;
line-height: 1.7;
}
.hydrostop-consent__actions {
display: flex;
flex-wrap: wrap;
gap: 12px;
margin-top: 22px;
}
.hydrostop-consent__button {
appearance: none;
border: 1px solid transparent;
border-radius: 999px;
padding: 13px 18px;
font: inherit;
font-size: 12px;
font-weight: 800;
letter-spacing: 0.18em;
text-transform: uppercase;
cursor: pointer;
transition: transform 0.2s ease, border-color 0.2s ease, background-color 0.2s ease, color 0.2s ease;
}
.hydrostop-consent__button:hover {
transform: translateY(-1px);
}
.hydrostop-consent__button:focus-visible,
.hydrostop-consent-manage:focus-visible {
outline: 2px solid #ffffff;
outline-offset: 2px;
}
.hydrostop-consent__button--primary {
background: var(--hydrostop-consent-accent);
color: #ffffff;
}
.hydrostop-consent__button--primary:hover {
background: var(--hydrostop-consent-accent-hover);
}
.hydrostop-consent__button--secondary {
background: transparent;
color: #ffffff;
border-color: rgba(255, 255, 255, 0.24);
}
.hydrostop-consent__button--secondary:hover {
border-color: rgba(255, 255, 255, 0.4);
background: rgba(255, 255, 255, 0.05);
}
.hydrostop-consent-manage {
position: fixed;
right: 16px;
bottom: 16px;
z-index: 999;
appearance: none;
border: 1px solid rgba(255, 255, 255, 0.14);
border-radius: 999px;
padding: 12px 16px;
background: #0f2942;
color: #ffffff;
font: inherit;
font-size: 11px;
font-weight: 800;
letter-spacing: 0.2em;
text-transform: uppercase;
cursor: pointer;
box-shadow: 0 18px 40px rgba(2, 8, 23, 0.24);
}
.hydrostop-consent-manage[hidden] {
display: none;
}
@media (max-width: 640px) {
.hydrostop-consent {
left: 12px;
right: 12px;
bottom: 12px;
}
.hydrostop-consent__card {
padding: 20px;
border-radius: 16px;
}
.hydrostop-consent__title {
font-size: 24px;
}
.hydrostop-consent__text {
font-size: 14px;
}
.hydrostop-consent__actions {
flex-direction: column;
}
.hydrostop-consent__button,
.hydrostop-consent-manage {
width: 100%;
text-align: center;
}
.hydrostop-consent-manage {
right: 12px;
bottom: 12px;
max-width: calc(100vw - 24px);
}
}
</style>
<script src="/src/consent-manager.js" defer></script>
<script>
tailwind.config = {
theme: {
extend: {
colors: {
navy: '#0F2942',
magenta: '#E91E8C',
'navy-light': '#1a3d5f',
},
fontFamily: {
sans: ['Inter', 'sans-serif'],
},
}
}
}
</script>
<style>
.reveal {
opacity: 0;
transform: translateY(30px);
transition: all 0.8s ease-out;
}
.reveal.active {
opacity: 1;
transform: translateY(0);
}
.service-card:hover .service-icon {
background-color: #E91E8C;
color: white;
transform: scale(1.1);
}
.nav-scrolled {
background: radial-gradient(circle at center, rgba(26, 61, 95, 0.96) 0%, rgba(10, 25, 41, 0.98) 100%) !important;
box-shadow: 0 4px 20px -5px rgba(0, 0, 0, 0.1);
height: 70px;
}
#navbar {
background: radial-gradient(circle at center, rgba(26, 61, 95, 0.9) 0%, rgba(10, 25, 41, 0.95) 100%) !important;
backdrop-filter: blur(14px);
}
#tunnel-container {
perspective: 1200px;
transform-style: preserve-3d;
overflow: hidden;
background: radial-gradient(circle at center, #1a3d5f 0%, #0a1929 100%);
}
.pipe-ring {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border-radius: 50%;
border: 14px solid rgba(35, 70, 100, 0.82);
transition: transform 0.1s linear, opacity 0.1s linear;
backface-visibility: hidden;
}
.pipe-ring::before {
content: '';
position: absolute;
inset: 16px;
border-radius: 50%;
border: 8px solid rgba(233, 30, 140, 0.94);
opacity: var(--lining-alpha, 0);
transform: scale(calc(0.97 + (var(--lining-alpha, 0) * 0.02)));
transition: opacity 0.12s linear, transform 0.12s linear;
}
.hero-text-content {
transition: opacity 0.5s ease, transform 0.5s ease;
}
.tunnel-step-label,
.tunnel-step-title {
width: 100%;
margin: 0;
text-align: center;
opacity: 1;
transform: translateY(0);
transition: opacity 0.34s ease, transform 0.34s cubic-bezier(0.22, 1, 0.36, 1);
will-change: opacity, transform;
}
.tunnel-step-label {
min-height: 1.5rem;
margin-bottom: 1rem;
}
.tunnel-step-title {
min-height: clamp(5rem, 11vw, 9rem);
}
.tunnel-step-line.is-hidden-up {
opacity: 0;
transform: translateY(-28px);
}
.tunnel-step-line.is-hidden-down {
opacity: 0;
transform: translateY(28px);
}
#hydrostop-map {
width: 100%;
height: 100%;
min-height: 420px;
}
.leaflet-container {
font-family: 'Inter', sans-serif;
}
.leaflet-control-attribution {
background: rgba(15, 41, 66, 0.9);
color: rgba(255, 255, 255, 0.8);
padding: 2px 8px;
border-radius: 999px;
margin: 0 10px 10px 0;
}
.leaflet-control-attribution a {
color: #ffffff;
}
</style>
</head>
<body class="bg-white text-slate-800 antialiased">
<!-- Navbar -->
<nav id="navbar" class="fixed w-full z-50 transition-all duration-300 h-24 flex items-center border-b border-white/10" style="background: radial-gradient(circle at center, rgba(26, 61, 95, 0.9) 0%, rgba(10, 25, 41, 0.95) 100%); backdrop-filter: blur(14px);">
<div class="max-w-7xl mx-auto px-6 w-full flex justify-between items-center">
<div class="flex items-center space-x-3">
<img src="/unnamed-96.webp" alt="Hydrostop" width="48" height="48" class="w-12 h-12 object-contain rounded-full shadow-lg" loading="eager" decoding="async">
<div class="leading-none">
<span class="block text-2xl font-extrabold tracking-tighter uppercase text-white transition-colors duration-300" id="nav-logo-text">
Hydro<span class="text-magenta">stop</span>
</span>
<span class="block text-[10px] font-black uppercase tracking-[0.28em] text-white/45 mt-1">Rénovation réseaux</span>
</div>
</div>
<div class="hidden md:flex items-center space-x-10">
<a href="#services" class="text-sm font-bold uppercase tracking-widest text-white/80 hover:text-magenta transition" id="nav-link-1">Solutions</a>
<a href="#why" class="text-sm font-bold uppercase tracking-widest text-white/80 hover:text-magenta transition" id="nav-link-2">Expertise</a>
<a href="#testimonials" class="text-sm font-bold uppercase tracking-widest text-white/80 hover:text-magenta transition" id="nav-link-3">Références</a>
<a href="#contact" class="px-7 py-3 bg-magenta text-white text-xs font-black uppercase tracking-widest rounded-sm hover:bg-white hover:text-navy transition-all duration-300 shadow-xl shadow-magenta/20">
Demander un diagnostic
</a>
</div>
<button class="md:hidden text-white" id="nav-toggle">
<i data-lucide="menu" class="w-8 h-8"></i>
</button>
</div>
</nav>
<section class="relative overflow-hidden bg-navy text-white pt-36 pb-20">
<div class="absolute inset-0 bg-[radial-gradient(circle_at_top_left,_rgba(233,30,140,0.24),_transparent_35%),radial-gradient(circle_at_bottom_right,_rgba(255,255,255,0.08),_transparent_26%)]"></div>
<div class="relative max-w-7xl mx-auto px-6 grid lg:grid-cols-[1.15fr_0.85fr] gap-12 items-start">
<div>
<p class="text-xs font-black uppercase tracking-[0.35em] text-magenta mb-5">Comment se passe le chemisage ?</p>
<h1 class="text-5xl md:text-7xl font-extrabold leading-[0.95] mb-7">
Comment se passe le
<span class="text-magenta">chemisage de canalisation</span> ?
</h1>
<p class="text-lg md:text-xl text-slate-300 leading-relaxed max-w-3xl">
On commence par un diagnostic caméra HD, puis on prépare le réseau, on pose la solution de chemisage adaptée et on contrôle le résultat. Une méthode claire, propre et maîtrisée pour rénover sans tout casser.
</p>
<div class="mt-9 flex flex-col sm:flex-row gap-4">
<a href="#hero-tunnel-section" class="inline-flex items-center justify-center px-8 py-4 bg-white text-navy font-black uppercase tracking-[0.2em] text-xs rounded-sm hover:bg-magenta hover:text-white transition">Voir les étapes</a>
<a href="#contact" class="inline-flex items-center justify-center px-8 py-4 border border-white/20 text-white font-black uppercase tracking-[0.2em] text-xs rounded-sm hover:bg-white/10 transition">Demander un diagnostic</a>
</div>
<p class="mt-6 text-sm text-white/60 leading-relaxed max-w-3xl">
Diagnostic caméra, préparation du réseau, pose du chemisage, contrôle final : chaque étape est pensée pour réduire la casse et accélérer la remise en service.
</p>
</div>
<div class="space-y-4">
<div class="grid grid-cols-2 gap-4">
<div class="bg-white/8 border border-white/10 rounded-sm p-6">
<p class="text-3xl font-extrabold text-white">48h</p>
<p class="mt-2 text-[11px] font-black uppercase tracking-[0.24em] text-white/55">Diagnostic initial</p>
</div>
<div class="bg-white/8 border border-white/10 rounded-sm p-6">
<p class="text-3xl font-extrabold text-white">10+</p>
<p class="mt-2 text-[11px] font-black uppercase tracking-[0.24em] text-white/55">Années terrain</p>
</div>
<div class="bg-white/8 border border-white/10 rounded-sm p-6">
<p class="text-3xl font-extrabold text-white">2500</p>
<p class="mt-2 text-[11px] font-black uppercase tracking-[0.24em] text-white/55">Interventions réseaux</p>
</div>
<div class="bg-white/8 border border-white/10 rounded-sm p-6">
<p class="text-3xl font-extrabold text-white">100m</p>
<p class="mt-2 text-[11px] font-black uppercase tracking-[0.24em] text-white/55">Chemisage continu</p>
</div>
</div>
<div class="bg-white text-navy rounded-sm p-8 shadow-2xl">
<p class="text-xs font-black uppercase tracking-[0.3em] text-magenta mb-4">Matériel haute performance</p>
<h2 class="text-2xl font-extrabold leading-tight mb-4">Des équipements haut de gamme pour décider juste, intervenir proprement et tenir dans le temps.</h2>
<ul class="space-y-3 text-sm text-slate-600 leading-relaxed">
<li class="flex gap-3"><i data-lucide="check" class="w-4 h-4 text-magenta flex-shrink-0 mt-1"></i><span>Caméras HD pour localiser exactement fissures, déboîtements, joints fatigués et contre-pentes.</span></li>
<li class="flex gap-3"><i data-lucide="check" class="w-4 h-4 text-magenta flex-shrink-0 mt-1"></i><span>Curage et préparation du réseau pour intervenir sur une base propre et fiabiliser la réparation.</span></li>
<li class="flex gap-3"><i data-lucide="check" class="w-4 h-4 text-magenta flex-shrink-0 mt-1"></i><span>Gaines, packers et résines techniques sélectionnés selon le diamètre, l'usage et le niveau d'exigence du chantier.</span></li>
<li class="flex gap-3"><i data-lucide="check" class="w-4 h-4 text-magenta flex-shrink-0 mt-1"></i><span>Compte-rendu clair avec images, constats et recommandations exploitables pour décider vite.</span></li>
</ul>
</div>
</div>
</div>
</section>
<!-- KPIs Section -->
<section class="py-24 bg-white border-b border-slate-200">
<div class="max-w-7xl mx-auto px-6">
<div class="max-w-3xl mb-12 reveal">
<h2 class="text-sm font-black text-magenta uppercase tracking-[0.3em] mb-4">Chiffres terrain</h2>
<h3 class="text-4xl md:text-5xl font-extrabold text-navy leading-tight">Des chiffres concrets, utiles au client et au chantier.</h3>
</div>
<div class="grid grid-cols-2 md:grid-cols-4 gap-px bg-slate-200 border border-slate-200 shadow-2xl overflow-hidden rounded-sm">
<div class="bg-white p-8 md:p-12 text-center reveal">
<i data-lucide="clock" class="w-8 h-8 text-magenta mx-auto mb-4"></i>
<div class="text-4xl font-extrabold text-navy mb-2">48h</div>
<div class="text-[10px] font-black uppercase tracking-widest text-slate-400">Diagnostic et retour initial</div>
</div>
<div class="bg-white p-8 md:p-12 text-center reveal delay-100">
<i data-lucide="award" class="w-8 h-8 text-magenta mx-auto mb-4"></i>
<div class="text-4xl font-extrabold text-navy mb-2">10+</div>
<div class="text-[10px] font-black uppercase tracking-widest text-slate-400">Années d'expertise réseaux</div>
</div>
<div class="bg-white p-8 md:p-12 text-center reveal delay-200">
<i data-lucide="hard-hat" class="w-8 h-8 text-magenta mx-auto mb-4"></i>
<div class="text-4xl font-extrabold text-navy mb-2">2500</div>
<div class="text-[10px] font-black uppercase tracking-widest text-slate-400">Interventions sur canalisations</div>
</div>
<div class="bg-white p-8 md:p-12 text-center reveal delay-300">
<i data-lucide="ruler" class="w-8 h-8 text-magenta mx-auto mb-4"></i>
<div class="text-4xl font-extrabold text-navy mb-2">100m</div>
<div class="text-[10px] font-black uppercase tracking-widest text-slate-400">Chemisage continu</div>
</div>
</div>
</div>
</section>
<!-- Hero Tunnel Section -->
<section id="hero-tunnel-section" class="relative h-[190vh] bg-navy">
<div class="sticky top-0 h-screen w-full flex items-center justify-center overflow-hidden">
<div id="tunnel-container" class="absolute inset-0 flex items-center justify-center"></div>
<div id="hero-main-content" class="relative z-40 max-w-4xl mx-auto px-6 text-center hero-text-content">
<p class="text-sm md:text-base font-semibold text-white/75 mb-5">
Les étapes du chemisage Hydrostop
</p>
<div class="inline-flex items-center gap-3 px-4 py-2 bg-magenta/10 border border-magenta/30 rounded-full mb-8">
<span class="w-2 h-2 bg-magenta rounded-full animate-pulse"></span>
<span class="text-xs font-bold text-magenta uppercase tracking-[0.2em]">On inspecte, on prépare, on chemise, on contrôle</span>
</div>
<h2 class="text-5xl md:text-8xl font-extrabold text-white leading-tight mb-8 drop-shadow-2xl">
Le chemisage, <br>
<span class="text-magenta">étape par étape</span>
</h2>
<p class="text-xl text-slate-300 mb-12 leading-relaxed max-w-2xl mx-auto">
Faites défiler pour voir comment Hydrostop passe du diagnostic caméra à la remise en service avec un chantier plus propre et plus léger.
</p>
<div class="flex flex-col sm:flex-row gap-5 justify-center">
<button id="hero-immersion-trigger" class="group flex items-center justify-center px-10 py-5 bg-white text-navy font-black rounded-sm hover:bg-magenta hover:text-white transition-all duration-500 uppercase tracking-widest text-sm shadow-2xl">
Voir les étapes
<i data-lucide="chevron-down" class="ml-2 w-4 h-4 group-hover:translate-y-1 transition"></i>
</button>
</div>
</div>
<div id="tunnel-step-overlay" class="absolute inset-0 z-40 flex flex-col items-center justify-center text-center max-w-xl mx-auto px-6 pointer-events-none opacity-0 transition-opacity duration-500">
<div id="tunnel-step-label" class="tunnel-step-line tunnel-step-label text-magenta font-black uppercase tracking-[0.3em] text-sm">Phase 1 : Diagnostic</div>
<h2 id="tunnel-step-title" class="tunnel-step-line tunnel-step-title text-4xl md:text-6xl font-extrabold text-white leading-tight">Passage caméra dans le réseau</h2>
</div>
<div id="tunnel-ui" class="absolute inset-0 pointer-events-none opacity-0 transition-opacity duration-700">
<div class="absolute left-10 top-1/2 -translate-y-1/2 w-1 h-32 bg-white/10 rounded-full overflow-hidden">
<div id="tunnel-progress-bar" class="w-full h-0 bg-magenta transition-all duration-100"></div>
</div>
<div class="absolute bottom-10 right-10 text-right">
<div class="text-magenta font-mono text-4xl font-black" id="depth-counter">0m</div>
<div class="text-white/40 text-[10px] font-bold uppercase tracking-widest">Avancee dans le réseau</div>
</div>
</div>
</div>
</section>
<!-- Services Section -->
<section id="services" class="py-32">
<div class="max-w-7xl mx-auto px-6">
<div class="flex flex-col md:flex-row justify-between items-end mb-20 reveal">
<div class="max-w-2xl">
<h2 class="text-sm font-black text-magenta uppercase tracking-[0.3em] mb-4">Nos pôles d'expertise</h2>
<h3 class="text-4xl md:text-5xl font-extrabold text-navy leading-tight">Des solutions claires pour rénover une canalisation sans refaire tout le bâtiment.</h3>
</div>
<p class="text-slate-500 max-w-sm mt-6 md:mt-0 italic">
Caméra HD, diagnostic fiable, matériel premium et choix de la bonne technique avant d'ouvrir le chantier.
</p>
</div>
<div class="grid md:grid-cols-3 gap-10">
<!-- Card 1 -->
<div id="chemisage-continu" class="group bg-slate-50 p-10 rounded-sm border-t-4 border-transparent hover:border-magenta hover:bg-white hover:shadow-2xl transition-all duration-500 reveal service-card">
<div class="service-icon w-14 h-14 bg-white text-navy rounded-sm flex items-center justify-center mb-8 shadow-sm transition-all duration-500">
<i data-lucide="layers" class="w-7 h-7"></i>
</div>
<h4 class="text-2xl font-bold text-navy mb-5">Rénovation complète par chemisage</h4>
<p class="text-slate-500 leading-relaxed mb-8">
On rénove l'intérieur de la canalisation avec une gaine structurelle polymérisée sur place, sans ouvrir tout le réseau.
</p>
<ul class="space-y-3 text-sm font-semibold text-navy-light">
<li class="flex items-center gap-2"><i data-lucide="check" class="w-4 h-4 text-magenta"></i> Étanchéité durable</li>
<li class="flex items-center gap-2"><i data-lucide="check" class="w-4 h-4 text-magenta"></i> Longueur jusqu'à 100m</li>
</ul>
<p class="mt-8 text-xs font-black uppercase tracking-[0.2em] text-slate-400">
Pages liées :
<a href="/chemisage-canalisation-paris/" class="text-navy hover:text-magenta transition">chemisage de canalisation à Paris</a> •
<a href="/chemisage-canalisation-versailles/" class="text-navy hover:text-magenta transition">chemisage de canalisation à Versailles</a> •
<a href="/chemisage-canalisation-boulogne-billancourt/" class="text-navy hover:text-magenta transition">chemisage de canalisation à Boulogne</a>
</p>
</div>
<!-- Card 2 -->
<div id="audit-robotise" class="group bg-slate-50 p-10 rounded-sm border-t-4 border-transparent hover:border-magenta hover:bg-white hover:shadow-2xl transition-all duration-500 reveal delay-100 service-card">
<div class="service-icon w-14 h-14 bg-white text-navy rounded-sm flex items-center justify-center mb-8 shadow-sm transition-all duration-500">
<i data-lucide="scan" class="w-7 h-7"></i>
</div>
<h4 class="text-2xl font-bold text-navy mb-5">Inspection caméra et diagnostic</h4>
<p class="text-slate-500 leading-relaxed mb-8">
Caméras haute définition et lecture terrain pour localiser exactement le défaut, éviter les travaux inutiles et engager la bonne solution du premier coup.
</p>
<ul class="space-y-3 text-sm font-semibold text-navy-light">
<li class="flex items-center gap-2"><i data-lucide="check" class="w-4 h-4 text-magenta"></i> Diagnostic caméra HD</li>
<li class="flex items-center gap-2"><i data-lucide="check" class="w-4 h-4 text-magenta"></i> Rapport utile pour suite de chantier</li>
</ul>
<p class="mt-8 text-xs font-black uppercase tracking-[0.2em] text-slate-400">
Pages liées :
<a href="/chemisage-canalisation-nanterre/" class="text-navy hover:text-magenta transition">chemisage de canalisation à Nanterre</a> •
<a href="/chemisage-canalisation-saint-denis/" class="text-navy hover:text-magenta transition">chemisage de canalisation à Saint-Denis</a> •
<a href="/chemisage-canalisation-creteil/" class="text-navy hover:text-magenta transition">chemisage de canalisation à Créteil</a>
</p>
</div>
<!-- Card 3 -->
<div id="reparation-ciblee" class="group bg-slate-50 p-10 rounded-sm border-t-4 border-transparent hover:border-magenta hover:bg-white hover:shadow-2xl transition-all duration-500 reveal delay-200 service-card">
<div class="service-icon w-14 h-14 bg-white text-navy rounded-sm flex items-center justify-center mb-8 shadow-sm transition-all duration-500">
<i data-lucide="pipette" class="text-navy w-7 h-7"></i>
</div>
<h4 class="text-2xl font-bold text-navy mb-5">Réparation localisée des tuyaux</h4>
<p class="text-slate-500 leading-relaxed mb-8">
Quand le problème est ponctuel, on vise uniquement la zone dégradée pour rétablir le service plus vite, contenir le budget et éviter une reprise lourde.
</p>
<ul class="space-y-3 text-sm font-semibold text-navy-light">
<li class="flex items-center gap-2"><i data-lucide="check" class="w-4 h-4 text-magenta"></i> Intervention rapide et propre</li>
<li class="flex items-center gap-2"><i data-lucide="check" class="w-4 h-4 text-magenta"></i> Évite une casse inutile</li>
</ul>
<p class="mt-8 text-xs font-black uppercase tracking-[0.2em] text-slate-400">
Pages liées :
<a href="/chemisage-canalisation-paris/" class="text-navy hover:text-magenta transition">chemisage de canalisation à Paris</a> •
<a href="/chemisage-canalisation-creteil/" class="text-navy hover:text-magenta transition">chemisage de canalisation à Créteil</a> •
<a href="/chemisage-canalisation-boulogne-billancourt/" class="text-navy hover:text-magenta transition">chemisage de canalisation à Boulogne</a>
</p>
</div>
</div>
<p class="mt-12 max-w-5xl text-sm text-slate-500 leading-relaxed reveal">
Les demandes les plus fréquentes concernent la
<a href="/chemisage-canalisation-paris/" class="font-bold text-navy hover:text-magenta transition">chemisage de canalisation à Paris</a>,
les
<a href="/chemisage-canalisation-boulogne-billancourt/" class="font-bold text-navy hover:text-magenta transition">chemisage de canalisation à Boulogne-Billancourt</a>,
le
<a href="/chemisage-canalisation-nanterre/" class="font-bold text-navy hover:text-magenta transition">chemisage de canalisation à Nanterre</a>,
les interventions sur
<a href="/chemisage-canalisation-saint-denis/" class="font-bold text-navy hover:text-magenta transition">chemisage de canalisation à Saint-Denis</a>,
les
<a href="/chemisage-canalisation-creteil/" class="font-bold text-navy hover:text-magenta transition">chemisage de canalisation à Créteil</a>
et les chantiers en
<a href="/chemisage-canalisation-versailles/" class="font-bold text-navy hover:text-magenta transition">chemisage de canalisation à Versailles</a>.
</p>
</div>
</section>
<!-- Why Us Section -->
<section id="why" class="py-32 bg-navy text-white overflow-hidden relative">
<div class="max-w-7xl mx-auto px-6 grid lg:grid-cols-2 gap-20 items-center relative z-10">
<div class="reveal">
<h2 class="text-sm font-black text-magenta uppercase tracking-[0.4em] mb-6">Pourquoi Hydrostop ?</h2>
<h3 class="text-4xl md:text-6xl font-extrabold mb-10 leading-tight">Un diagnostic caméra net, du matériel premium et des décisions techniques qui évitent les travaux inutiles.</h3>
<div class="space-y-10">
<div id="personnel-qualifie" class="flex gap-6">
<div class="flex-shrink-0 w-12 h-12 border border-magenta/50 flex items-center justify-center text-magenta">
<i data-lucide="hard-hat"></i>
</div>
<div>
<h4 class="text-xl font-bold mb-2">Techniciens réseaux de terrain</h4>
<p class="text-slate-400">Des techniciens habitués aux colonnes, collecteurs, tuyaux enterrés et réseaux techniques complexes, même en site occupé.</p>
</div>
</div>
<div id="intervention-non-intrusive" class="flex gap-6">
<div class="flex-shrink-0 w-12 h-12 border border-magenta/50 flex items-center justify-center text-magenta">
<i data-lucide="zap"></i>
</div>
<div>
<h4 class="text-xl font-bold mb-2">Matériel haut de gamme, décision plus juste</h4>
<p class="text-slate-400">Caméras HD, curage haute pression, packers, gaines et résines techniques pour intervenir juste du premier coup et limiter la casse.</p>
</div>
</div>
<div id="protection-assurance" class="flex gap-6">
<div class="flex-shrink-0 w-12 h-12 border border-magenta/50 flex items-center justify-center text-magenta">
<i data-lucide="shield"></i>
</div>
<div>
<h4 class="text-xl font-bold mb-2">Rapport clair et cadre rassurant</h4>
<p class="text-slate-400">Images, constats, recommandations et assurances pour aider un syndic, un gestionnaire ou un propriétaire à décider vite et sereinement.</p>
</div>
</div>
</div>
</div>
<div class="relative reveal delay-200">
<div class="absolute -top-10 -left-10 w-40 h-40 border-l-2 border-t-2 border-magenta opacity-30"></div>
<img src="src/p11_4636_lg-640.webp" alt="Ingénierie canalisation" width="640" height="400" loading="lazy" decoding="async" class="rounded-sm shadow-2xl grayscale hover:grayscale-0 transition duration-1000">
<div class="absolute -bottom-8 -right-8 bg-magenta p-10 shadow-2xl">
<div class="text-5xl font-black mb-1 italic tracking-tighter">10+</div>
<div class="text-xs font-bold uppercase tracking-widest opacity-80">Années de <br> longévité </div>
</div>
</div>
</div>
<div class="absolute inset-0 bg-[url('https://www.transparenttextures.com/patterns/carbon-fibre.png')] opacity-5"></div>
</section>
<!-- Testimonials Section -->
<section id="testimonials" class="py-32 bg-slate-50">
<div class="max-w-7xl mx-auto px-6">
<div class="text-center mb-20 reveal">
<h2 class="text-sm font-black text-magenta uppercase tracking-widest mb-4">Ils nous recommandent</h2>
<h3 class="text-4xl font-extrabold text-navy">Retours d'expérience</h3>
</div>
<div class="grid md:grid-cols-2 gap-10">
<div class="bg-white p-12 rounded-sm shadow-sm reveal">
<div class="flex gap-1 text-magenta mb-8">
<i data-lucide="star" class="w-5 h-5 fill-current"></i>
<i data-lucide="star" class="w-5 h-5 fill-current"></i>
<i data-lucide="star" class="w-5 h-5 fill-current"></i>
<i data-lucide="star" class="w-5 h-5 fill-current"></i>
<i data-lucide="star" class="w-5 h-5 fill-current"></i>
</div>
<p class="text-lg text-slate-600 italic mb-10 leading-relaxed">
"Ravi d'avoir fait appel à Hydrostop à Marne la Vallée Nous avions une fuite difficile à localiser dans une canalisation enterrée dans notre pavillon. Marco a su nous rassurer et expliquer clairement. [...] Merci à lui"
</p>
<div class="flex items-center gap-4">
<div>
<div class="font-black text-navy uppercase text-sm">Lionel G.</div>
<div class="text-xs text-slate-400 font-bold uppercase tracking-wider">Propriétaire d'un pavillon à Marne la Vallée</div>
</div>
</div>
</div>
<div class="bg-white p-12 rounded-sm shadow-sm reveal delay-100">
<div class="flex gap-1 text-magenta mb-8">
<i data-lucide="star" class="w-5 h-5 fill-current"></i>
<i data-lucide="star" class="w-5 h-5 fill-current"></i>
<i data-lucide="star" class="w-5 h-5 fill-current"></i>
<i data-lucide="star" class="w-5 h-5 fill-current"></i>
<i data-lucide="star" class="w-5 h-5 fill-current"></i>
</div>
<p class="text-lg text-slate-600 italic mb-10 leading-relaxed">
"Marco a été très professionel et réactif. Je l'ai contacté ce matin pour lui exposer mon problème de canalisation et il est intervenu dès l'après-midi. [...] Je recommande fortement ses services et ce technicien."
</p>
<div class="flex items-center gap-4">
<div>
<div class="font-black text-navy uppercase text-sm">Morgane P.</div>
<div class="text-xs text-slate-400 font-bold uppercase tracking-wider">Propriétaire d'un pavillion à Torcy</div>
</div>
</div>
</div>
</div>
</div>
</section>
<section id="zones" class="py-32 bg-white border-y border-slate-200">
<div class="max-w-7xl mx-auto px-6">
<div class="flex flex-col lg:flex-row lg:items-end lg:justify-between gap-10 mb-16 reveal">
<div class="max-w-3xl">
<h2 class="text-sm font-black text-magenta uppercase tracking-[0.3em] mb-4">Zones d'intervention</h2>
<h3 class="text-4xl md:text-5xl font-extrabold text-navy leading-tight">Accedez directement à la page la plus proche de votre chantier.</h3>
</div>
<p class="max-w-2xl text-slate-500 leading-relaxed">
Chaque page locale présente un contexte de chantier précis pour vous projeter plus rapidement dans votre projet.
</p>
</div>
<div class="grid md:grid-cols-2 xl:grid-cols-3 gap-8">
<article class="bg-slate-50 border border-slate-200 rounded-sm p-8 shadow-sm reveal">
<p class="text-xs font-black uppercase tracking-[0.3em] text-magenta mb-3">Référence urbaine</p>
<h4 class="text-2xl font-extrabold text-navy mb-4">Paris</h4>
<p class="text-slate-600 leading-relaxed mb-6">Pour les immeubles anciens, copropriétés denses et tuyaux enterrés en environnement urbain contraint.</p>
<div class="flex flex-wrap gap-3 text-xs font-black uppercase tracking-[0.18em]">
<a href="/chemisage-canalisation-paris/" class="px-4 py-3 bg-navy text-white rounded-sm hover:bg-magenta transition">Voir la page</a>
<a href="#chemisage-continu" class="px-4 py-3 border border-slate-300 text-navy rounded-sm hover:border-magenta hover:text-magenta transition">Voir la rénovation</a>
</div>
</article>
<article class="bg-slate-50 border border-slate-200 rounded-sm p-8 shadow-sm reveal delay-100">
<p class="text-xs font-black uppercase tracking-[0.3em] text-magenta mb-3">Résidentiel et tertiaire</p>
<h4 class="text-2xl font-extrabold text-navy mb-4">Boulogne-Billancourt</h4>
<p class="text-slate-600 leading-relaxed mb-6">Pour les résidences, bureaux et immeubles mixtes où l'activité du site doit rester fluide pendant l'intervention.</p>
<div class="flex flex-wrap gap-3 text-xs font-black uppercase tracking-[0.18em]">
<a href="/chemisage-canalisation-boulogne-billancourt/" class="px-4 py-3 bg-navy text-white rounded-sm hover:bg-magenta transition">Voir la page</a>
<a href="#reparation-ciblee" class="px-4 py-3 border border-slate-300 text-navy rounded-sm hover:border-magenta hover:text-magenta transition">Voir la réparation</a>
</div>
</article>
<article class="bg-slate-50 border border-slate-200 rounded-sm p-8 shadow-sm reveal delay-200">
<p class="text-xs font-black uppercase tracking-[0.3em] text-magenta mb-3">Sites mixtes</p>
<h4 class="text-2xl font-extrabold text-navy mb-4">Nanterre</h4>
<p class="text-slate-600 leading-relaxed mb-6">Pour les bâtiments mixtes, parkings et sous-sols techniques qui demandent un diagnostic précis avant travaux.</p>
<div class="flex flex-wrap gap-3 text-xs font-black uppercase tracking-[0.18em]">
<a href="/chemisage-canalisation-nanterre/" class="px-4 py-3 bg-navy text-white rounded-sm hover:bg-magenta transition">Voir la page</a>
<a href="#audit-robotise" class="px-4 py-3 border border-slate-300 text-navy rounded-sm hover:border-magenta hover:text-magenta transition">Voir le diagnostic</a>
</div>
</article>
<article class="bg-slate-50 border border-slate-200 rounded-sm p-8 shadow-sm reveal">
<p class="text-xs font-black uppercase tracking-[0.3em] text-magenta mb-3">Habitat collectif</p>
<h4 class="text-2xl font-extrabold text-navy mb-4">Saint-Denis</h4>
<p class="text-slate-600 leading-relaxed mb-6">Pour les résidences, ERP et réseaux très sollicités où la rapidité d'exécution compte autant que la fiabilité.</p>
<div class="flex flex-wrap gap-3 text-xs font-black uppercase tracking-[0.18em]">
<a href="/chemisage-canalisation-saint-denis/" class="px-4 py-3 bg-navy text-white rounded-sm hover:bg-magenta transition">Voir la page</a>
<a href="#audit-robotise" class="px-4 py-3 border border-slate-300 text-navy rounded-sm hover:border-magenta hover:text-magenta transition">Voir le diagnostic</a>
</div>
</article>
<article class="bg-slate-50 border border-slate-200 rounded-sm p-8 shadow-sm reveal delay-100">
<p class="text-xs font-black uppercase tracking-[0.3em] text-magenta mb-3">Réseaux pluviaux</p>
<h4 class="text-2xl font-extrabold text-navy mb-4">Créteil</h4>
<p class="text-slate-600 leading-relaxed mb-6">Pour les réseaux pluviaux, bâtiments publics et ensembles résidentiels avec contraintes d'accès ou de continuité.</p>
<div class="flex flex-wrap gap-3 text-xs font-black uppercase tracking-[0.18em]">
<a href="/chemisage-canalisation-creteil/" class="px-4 py-3 bg-navy text-white rounded-sm hover:bg-magenta transition">Voir la page</a>
<a href="#reparation-ciblee" class="px-4 py-3 border border-slate-300 text-navy rounded-sm hover:border-magenta hover:text-magenta transition">Voir la réparation</a>
</div>
</article>
<article class="bg-slate-50 border border-slate-200 rounded-sm p-8 shadow-sm reveal delay-200">
<p class="text-xs font-black uppercase tracking-[0.3em] text-magenta mb-3">Bâti sensible</p>
<h4 class="text-2xl font-extrabold text-navy mb-4">Versailles</h4>
<p class="text-slate-600 leading-relaxed mb-6">Pour les bâtiments anciens, résidences de standing et chantiers où les finitions doivent être préservées.</p>
<div class="flex flex-wrap gap-3 text-xs font-black uppercase tracking-[0.18em]">
<a href="/chemisage-canalisation-versailles/" class="px-4 py-3 bg-navy text-white rounded-sm hover:bg-magenta transition">Voir la page</a>
<a href="#chemisage-continu" class="px-4 py-3 border border-slate-300 text-navy rounded-sm hover:border-magenta hover:text-magenta transition">Voir la rénovation</a>
</div>
</article>
</div>
</div>
</section>
<!-- Contact Section -->
<section id="contact" class="py-32 bg-white">
<div class="max-w-7xl mx-auto px-6">
<div class="grid lg:grid-cols-3 gap-px bg-slate-200 shadow-2xl rounded-sm overflow-hidden">
<div class="lg:col-span-1 bg-navy p-12 text-white">
<h2 class="text-3xl font-extrabold mb-10 leading-tight">Parlez-nous de votre chantier</h2>
<div class="space-y-10">
<div class="flex gap-5">
<i data-lucide="map-pin" class="text-magenta flex-shrink-0"></i>
<div>
<div class="font-bold text-sm uppercase tracking-widest text-magenta mb-2">Nos zones d'interventions</div>
<p class="text-slate-400 leading-relaxed"><a href="/chemisage-canalisation-paris/" class="underline underline-offset-4 hover:text-white transition">Paris</a>, <a href="/chemisage-canalisation-boulogne-billancourt/" class="underline underline-offset-4 hover:text-white transition">Boulogne-Billancourt</a>, <a href="/chemisage-canalisation-nanterre/" class="underline underline-offset-4 hover:text-white transition">Nanterre</a>, <a href="/chemisage-canalisation-saint-denis/" class="underline underline-offset-4 hover:text-white transition">Saint-Denis</a>, <a href="/chemisage-canalisation-creteil/" class="underline underline-offset-4 hover:text-white transition">Créteil</a>, <a href="/chemisage-canalisation-versailles/" class="underline underline-offset-4 hover:text-white transition">Versailles</a>, et bien plus encore...<br> Île-de-France, France</p>
</div>
</div>
<div class="flex gap-5">
<i data-lucide="phone" class="text-magenta flex-shrink-0"></i>
<div>
<div class="font-bold text-sm uppercase tracking-widest text-magenta mb-2">Ligne Directe</div>
<p class="text-2xl font-black">07 65 77 82 76</p>
</div>
</div>
<div class="flex gap-5">
<i data-lucide="mail" class="text-magenta flex-shrink-0"></i>
<div>
<div class="font-bold text-sm uppercase tracking-widest text-magenta mb-2">Expertise</div>
<p class="text-slate-400">hydrostop.contact@gmail.com</p>
</div>
</div>
</div>
</div>
<div class="lg:col-span-2 bg-slate-50">
<div class="h-full flex flex-col">
<div class="flex flex-col md:flex-row md:items-center md:justify-between gap-4 px-8 py-6 bg-white border-b border-slate-200">
<div>
<p class="text-xs font-black uppercase tracking-[0.3em] text-magenta mb-2">Carte d'intervention</p>
<h3 class="text-2xl font-extrabold text-navy">Zone couverte autour de Paris et de l'Île-de-France</h3>
</div>
<a
href="https://www.openstreetmap.org/#map=9/48.8566/2.3522"
target="_blank"
rel="noopener noreferrer"
class="inline-flex items-center justify-center px-5 py-3 bg-navy text-white text-xs font-black uppercase tracking-[0.2em] rounded-sm hover:bg-magenta transition"
>
Ouvrir la carte
</a>
</div>
<div class="relative flex-1 min-h-[420px]">
<div
id="hydrostop-map"
role="img"
aria-label="Carte interactive Hydrostop autour de Paris et de l'Île-de-France avec un thème Voyager"
></div>
<div class="absolute left-4 right-4 bottom-4 md:left-6 md:right-auto md:max-w-md bg-white/95 backdrop-blur-sm border border-slate-200 shadow-xl rounded-sm p-5">
<p class="text-[11px] font-black uppercase tracking-[0.3em] text-magenta mb-2">Repère</p>
<p class="text-sm text-slate-600 leading-relaxed">
Les points roses couvrent les grandes villes d'Île-de-France, les 20 arrondissements de Paris et Croissy-Beaubourg pour visualiser rapidement notre maillage d'intervention.
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Footer -->
<footer class="bg-navy py-20 text-white border-t border-white/10">
<div class="max-w-7xl mx-auto px-6">
<div class="grid md:grid-cols-4 gap-12 mb-20">
<div class="col-span-1 md:col-span-1">
<a href="/" class="flex items-center space-x-3 mb-8">
<img src="/unnamed-96.webp" alt="Hydrostop" width="48" height="48" class="w-12 h-12 object-contain rounded-full shadow-lg" loading="lazy" decoding="async">
<div class="leading-none">
<span class="block text-xl font-extrabold tracking-tighter uppercase">Hydro<span class="text-magenta">stop</span></span>
<span class="block text-[9px] font-black uppercase tracking-[0.28em] text-white/45 mt-1">Rénovation réseaux</span>
</div>
</a>
<p class="text-slate-400 text-sm leading-relaxed">
Expert en rénovation de canalisations, tuyaux d'assainissement et réseaux pluviaux sans tranchée en Île-de-France.
</p>
</div>
<div>
<h4 class="text-xs font-black uppercase tracking-[0.3em] text-magenta mb-8">Solutions</h4>
<ul class="space-y-4 text-sm text-slate-400 font-bold uppercase tracking-widest">
<li><a href="#chemisage-continu" class="hover:text-white transition">Chemisage</a></li>
<li><a href="#audit-robotise" class="hover:text-white transition">Diagnostic caméra</a></li>
<li><a href="#reparation-ciblee" class="hover:text-white transition">Réparation localisée</a></li>
<li><a href="#services" class="hover:text-white transition">Expertise chantier</a></li>
</ul>
</div>
<div>
<h4 class="text-xs font-black uppercase tracking-[0.3em] text-magenta mb-8">Société</h4>
<ul class="space-y-4 text-sm text-slate-400 font-bold uppercase tracking-widest">
<li><a href="#why" class="hover:text-white transition">Notre Équipe</a></li>
<li><a href="#protection-assurance" class="hover:text-white transition">Garantie Décennale</a></li>
<li><a href="#personnel-qualifie" class="hover:text-white transition">Certifications</a></li>
<li><a href="#zones" class="hover:text-white transition">Zone IDF</a></li>
</ul>
</div>
<div>
<h4 class="text-xs font-black uppercase tracking-[0.3em] text-magenta mb-8">Légal</h4>
<ul class="space-y-4 text-sm text-slate-400 font-bold uppercase tracking-widest">
<li><a href="mentions-legales.html" class="hover:text-white transition">Mentions Légales</a></li>
<li><a href="mentions-legales.html#confidentialite" class="hover:text-white transition">Confidentialité</a></li>
<li><a href="mentions-legales.html#cgu" class="hover:text-white transition">CGU</a></li>
</ul>
</div>
</div>
<div class="pt-10 border-t border-white/5 flex flex-col md:flex-row justify-between items-center gap-6">
<p class="text-[10px] font-bold uppercase tracking-widest text-slate-500 italic">
Certification Hydrostop
</p>
<p class="text-[10px] font-bold uppercase tracking-widest text-slate-500">
© 2026 Hydrostop • Réalisé par AEOM.
</p>
</div>
</div>
</footer>
<script>
// Init Lucide Icons
const initLucideIcons = () => {
if (!window.lucide) return false;
window.lucide.createIcons();
return true;
};
if (!initLucideIcons()) {
document.addEventListener('DOMContentLoaded', () => {
initLucideIcons();
}, { once: true });
}
const loadExternalScript = (src) => new Promise((resolve, reject) => {
const existingScript = document.querySelector(`script[src="${src}"]`);
if (existingScript) {
if (existingScript.dataset.loaded === 'true') {
resolve();
return;
}
existingScript.addEventListener('load', resolve, { once: true });
existingScript.addEventListener('error', reject, { once: true });
return;
}
const script = document.createElement('script');
script.src = src;
script.async = true;
script.addEventListener('load', () => {
script.dataset.loaded = 'true';
resolve();
}, { once: true });
script.addEventListener('error', reject, { once: true });
document.body.appendChild(script);
});
const loadExternalStylesheet = (href) => new Promise((resolve, reject) => {
const existingStylesheet = document.querySelector(`link[href="${href}"]`);
if (existingStylesheet) {
resolve();
return;
}
const stylesheet = document.createElement('link');
stylesheet.rel = 'stylesheet';
stylesheet.href = href;
stylesheet.addEventListener('load', resolve, { once: true });
stylesheet.addEventListener('error', reject, { once: true });
document.head.appendChild(stylesheet);
});
// Themed map for the intervention area
const hydrostopMapNode = document.getElementById('hydrostop-map');
const initHydrostopMap = async () => {
if (!hydrostopMapNode || hydrostopMapNode.dataset.mapReady === 'true') return;
await Promise.all([
loadExternalStylesheet('https://unpkg.com/leaflet@1.9.4/dist/leaflet.css'),
loadExternalScript('https://unpkg.com/leaflet@1.9.4/dist/leaflet.js')
]);
if (!window.L) return;
hydrostopMapNode.dataset.mapReady = 'true';
const interventionCities = [
{ name: 'Boulogne-Billancourt', coords: [48.8397, 2.2399], type: 'city' },
{ name: 'Nanterre', coords: [48.8924, 2.2060], type: 'city' },
{ name: 'Saint-Denis', coords: [48.9362, 2.3574], type: 'city' },
{ name: 'Créteil', coords: [48.7904, 2.4556], type: 'city' },
{ name: 'Versailles', coords: [48.8049, 2.1204], type: 'city' },
{ name: 'Orly', coords: [48.7430, 2.4024], type: 'city' },
{ name: 'Torcy', coords: [48.8506, 2.6500], type: 'city' },
{ name: 'Noisiel', coords: [48.8452, 2.6249], type: 'city' },
{ name: 'Croissy-Beaubourg', coords: [48.8287, 2.6522], type: 'city' }
];
const parisArrondissements = [
{ name: 'Paris 1er', coords: [48.8625, 2.3363], type: 'arrondissement' },
{ name: 'Paris 2e', coords: [48.8683, 2.3440], type: 'arrondissement' },
{ name: 'Paris 3e', coords: [48.8636, 2.3613], type: 'arrondissement' },
{ name: 'Paris 4e', coords: [48.8543, 2.3570], type: 'arrondissement' },
{ name: 'Paris 5e', coords: [48.8448, 2.3500], type: 'arrondissement' },
{ name: 'Paris 6e', coords: [48.8494, 2.3320], type: 'arrondissement' },
{ name: 'Paris 7e', coords: [48.8562, 2.3126], type: 'arrondissement' },
{ name: 'Paris 8e', coords: [48.8721, 2.3126], type: 'arrondissement' },
{ name: 'Paris 9e', coords: [48.8760, 2.3379], type: 'arrondissement' },
{ name: 'Paris 10e', coords: [48.8761, 2.3590], type: 'arrondissement' },
{ name: 'Paris 11e', coords: [48.8586, 2.3780], type: 'arrondissement' },
{ name: 'Paris 12e', coords: [48.8409, 2.3870], type: 'arrondissement' },
{ name: 'Paris 13e', coords: [48.8282, 2.3622], type: 'arrondissement' },
{ name: 'Paris 14e', coords: [48.8323, 2.3266], type: 'arrondissement' },
{ name: 'Paris 15e', coords: [48.8412, 2.3003], type: 'arrondissement' },
{ name: 'Paris 16e', coords: [48.8623, 2.2712], type: 'arrondissement' },
{ name: 'Paris 17e', coords: [48.8873, 2.3077], type: 'arrondissement' },
{ name: 'Paris 18e', coords: [48.8926, 2.3444], type: 'arrondissement' },
{ name: 'Paris 19e', coords: [48.8870, 2.3840], type: 'arrondissement' },
{ name: 'Paris 20e', coords: [48.8635, 2.4016], type: 'arrondissement' }
];
const mapPoints = [...interventionCities, ...parisArrondissements];
const hydrostopMap = L.map(hydrostopMapNode, {
center: [48.8566, 2.3522],
zoom: 11,
scrollWheelZoom: false
});
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png', {
attribution: '© OpenStreetMap contributors © CARTO',
subdomains: 'abcd',
maxZoom: 20
}).addTo(hydrostopMap);
const cityMarkers = mapPoints.map((city) => (
L.circleMarker(city.coords, {
radius: city.type === 'arrondissement' ? 5 : 7,
color: '#ffffff',
weight: city.type === 'arrondissement' ? 1.5 : 2,
fillColor: '#E91E8C',
fillOpacity: 0.95
}).bindTooltip(city.name, {
direction: 'top',
offset: [0, -8],
opacity: 0.95
})
));
const interventionLayer = L.featureGroup(cityMarkers).addTo(hydrostopMap);
hydrostopMap.fitBounds(interventionLayer.getBounds(), {
padding: [30, 30],
maxZoom: 10
});
};
if (hydrostopMapNode) {
if (!('IntersectionObserver' in window)) {
window.addEventListener('load', () => {
initHydrostopMap().catch(() => {});
}, { once: true });
} else {
const mapObserver = new IntersectionObserver((entries, observer) => {
entries.forEach((entry) => {
if (!entry.isIntersecting) return;
observer.disconnect();
initHydrostopMap().catch(() => {});
});
}, { rootMargin: '320px 0px' });
mapObserver.observe(hydrostopMapNode);
}
}
// Tunnel hero
const tunnelContainer = document.getElementById('tunnel-container');
const heroTunnelSection = document.getElementById('hero-tunnel-section');
const postHeroSection = heroTunnelSection ? heroTunnelSection.nextElementSibling : null;
const heroMainContent = document.getElementById('hero-main-content');
const heroImmersionTrigger = document.getElementById('hero-immersion-trigger');
const tunnelUI = document.getElementById('tunnel-ui');
const tunnelStepOverlay = document.getElementById('tunnel-step-overlay');
const tunnelStepLabel = document.getElementById('tunnel-step-label');
const tunnelStepTitle = document.getElementById('tunnel-step-title');
const depthCounter = document.getElementById('depth-counter');
const tunnelProgressBar = document.getElementById('tunnel-progress-bar');
if (
tunnelContainer &&
heroTunnelSection &&
heroMainContent &&
heroImmersionTrigger &&
tunnelUI &&
tunnelStepOverlay &&
tunnelStepLabel &&
tunnelStepTitle &&
depthCounter &&
tunnelProgressBar
) {
const totalRings = 18;
const rings = [];
let targetTunnelProgress = 0;
let renderedTunnelProgress = 0;
let tunnelFrameId = null;
let tunnelStepFrameId = null;
let tunnelStepSwapTimeout = null;
let tunnelStepTimeout = null;
let immersionFrameId = null;
let immersionTimeoutId = null;
let displayedTunnelStepIndex = 0;
let queuedTunnelStepIndex = null;
let isTunnelStepTransitioning = false;
for (let i = 0; i < totalRings; i += 1) {
const ring = document.createElement('div');
ring.className = 'pipe-ring';
const size = 220 + (i * 56);
ring.style.width = `${size}px`;
ring.style.height = `${size}px`;
ring.style.zIndex = totalRings - i;
ring.style.setProperty('--lining-alpha', '0');
ring.style.transform = `translate(-50%, -50%) translateZ(${-i * 180}px)`;
tunnelContainer.appendChild(ring);
rings.push(ring);
}
const tunnelSteps = [
{ threshold: 0.08, label: 'Phase 1 : Diagnostic', title: 'Passage caméra dans le réseau' },
{ threshold: 0.2, label: 'Phase 2 : Préparation', title: 'Curage et préparation du tuyau' },
{ threshold: 0.36, label: 'Phase 3 : Rénovation', title: 'Pose du chemisage structurel' },
{ threshold: 0.54, label: 'Phase 4 : Contrôle', title: 'Validation et remise en service' }
];
const setVisibleStep = (stepIndex) => {
const step = tunnelSteps[stepIndex];
tunnelStepLabel.textContent = step.label;
tunnelStepTitle.textContent = step.title;
tunnelStepLabel.classList.remove('is-hidden-up', 'is-hidden-down');
tunnelStepTitle.classList.remove('is-hidden-up', 'is-hidden-down');
displayedTunnelStepIndex = stepIndex;
};
const animateStepChange = (stepIndex) => {
if (stepIndex === displayedTunnelStepIndex && !isTunnelStepTransitioning) return;
if (isTunnelStepTransitioning) {
queuedTunnelStepIndex = stepIndex;
return;
}
if (stepIndex === displayedTunnelStepIndex) return;
isTunnelStepTransitioning = true;
queuedTunnelStepIndex = null;
window.clearTimeout(tunnelStepSwapTimeout);
window.clearTimeout(tunnelStepTimeout);
tunnelStepSwapTimeout = null;
tunnelStepTimeout = null;
if (tunnelStepFrameId) {
window.cancelAnimationFrame(tunnelStepFrameId);
tunnelStepFrameId = null;
}
tunnelStepLabel.classList.remove('is-hidden-down');
tunnelStepTitle.classList.remove('is-hidden-down');
tunnelStepLabel.classList.add('is-hidden-up');
tunnelStepTitle.classList.add('is-hidden-up');
tunnelStepSwapTimeout = window.setTimeout(() => {
const step = tunnelSteps[stepIndex];
tunnelStepLabel.textContent = step.label;
tunnelStepTitle.textContent = step.title;
tunnelStepLabel.classList.remove('is-hidden-up');
tunnelStepTitle.classList.remove('is-hidden-up');
tunnelStepLabel.classList.add('is-hidden-down');
tunnelStepTitle.classList.add('is-hidden-down');
if (tunnelStepFrameId) {
window.cancelAnimationFrame(tunnelStepFrameId);
}
tunnelStepFrameId = window.requestAnimationFrame(() => {
tunnelStepFrameId = window.requestAnimationFrame(() => {
tunnelStepFrameId = null;
tunnelStepLabel.classList.remove('is-hidden-down');
tunnelStepTitle.classList.remove('is-hidden-down');
});
});
tunnelStepSwapTimeout = null;
tunnelStepTimeout = window.setTimeout(() => {
tunnelStepTimeout = null;
isTunnelStepTransitioning = false;
setVisibleStep(stepIndex);
if (queuedTunnelStepIndex !== null && queuedTunnelStepIndex !== displayedTunnelStepIndex) {
const nextQueuedStepIndex = queuedTunnelStepIndex;
queuedTunnelStepIndex = null;
animateStepChange(nextQueuedStepIndex);
} else {
queuedTunnelStepIndex = null;
}
}, 340);
}, 180);
};
setVisibleStep(0);
const getTunnelState = () => {
const rect = heroTunnelSection.getBoundingClientRect();
const scrollPercent = Math.max(0, Math.min(1, -rect.top / (rect.height - window.innerHeight)));
return { rect, scrollPercent };
};
const renderTunnel = (scrollPercent, rect) => {
if (scrollPercent < 0.08) {
const opacity = 1 - (scrollPercent * 11);
heroMainContent.style.opacity = Math.max(0, opacity);
heroMainContent.style.transform = `translateY(${-scrollPercent * 120}px) scale(${1 - scrollPercent * 0.65})`;
tunnelUI.style.opacity = 0;
} else {
heroMainContent.style.opacity = 0;
tunnelUI.style.opacity = 1;
}
if (rect.top <= window.innerHeight && rect.bottom >= 0) {
rings.forEach((ring, index) => {
const adjustedScroll = Math.max(0, scrollPercent - 0.02);
const zBase = -index * 180;
const zTravel = adjustedScroll * ((totalRings * 180) + 900);
const zFinal = zBase + zTravel;
const scale = Math.max(0, 1 + (zFinal / 500));
const opacity = zFinal > 300 ? 0 : (zFinal < -1500 ? 0 : 1);
const liningWave = ((scrollPercent - 0.24) * totalRings * 5.1) - index;
const liningProgress = Math.max(0, Math.min(1, liningWave / 3.2));
ring.style.transform = `translate(-50%, -50%) translateZ(${zFinal}px) scale(${scale})`;
ring.style.opacity = opacity;
ring.style.setProperty('--lining-alpha', liningProgress.toFixed(3));
});
depthCounter.innerText = `${Math.floor(scrollPercent * 60)}m`;
tunnelProgressBar.style.height = `${scrollPercent * 100}%`;
let currentStepIndex = 0;
tunnelSteps.forEach((step, index) => {
if (scrollPercent >= step.threshold) currentStepIndex = index;
});
if (scrollPercent > 0.08) {
tunnelStepOverlay.style.opacity = 1;
animateStepChange(currentStepIndex);
} else if (scrollPercent <= 0.08) {
if (tunnelStepFrameId) {
window.cancelAnimationFrame(tunnelStepFrameId);
tunnelStepFrameId = null;
}
window.clearTimeout(tunnelStepSwapTimeout);
window.clearTimeout(tunnelStepTimeout);
tunnelStepSwapTimeout = null;
tunnelStepTimeout = null;
queuedTunnelStepIndex = null;
isTunnelStepTransitioning = false;
setVisibleStep(0);
tunnelStepOverlay.style.opacity = 0;
}
}
};
const animateTunnel = () => {
renderedTunnelProgress += (targetTunnelProgress - renderedTunnelProgress) * 0.24;
if (Math.abs(targetTunnelProgress - renderedTunnelProgress) < 0.0025) {
renderedTunnelProgress = targetTunnelProgress;
}
const { rect } = getTunnelState();
renderTunnel(renderedTunnelProgress, rect);
if (Math.abs(targetTunnelProgress - renderedTunnelProgress) >= 0.0025) {
tunnelFrameId = window.requestAnimationFrame(animateTunnel);
} else {
tunnelFrameId = null;
}
};
const syncTunnelToScroll = () => {
const { scrollPercent } = getTunnelState();
targetTunnelProgress = scrollPercent;
if (!tunnelFrameId) {
tunnelFrameId = window.requestAnimationFrame(animateTunnel);
}
};
const stopImmersionScroll = () => {
if (immersionFrameId) {
window.cancelAnimationFrame(immersionFrameId);
immersionFrameId = null;
}
if (immersionTimeoutId) {
window.clearTimeout(immersionTimeoutId);
immersionTimeoutId = null;
}
};
const easeInOutCubic = (value) => {
if (value < 0.5) return 4 * value * value * value;
return 1 - Math.pow(-2 * value + 2, 3) / 2;
};
const animateViewportTo = (destinationY, duration, onComplete) => {
const startY = window.scrollY;
let startTime = null;
const stepScroll = (timestamp) => {
if (startTime === null) startTime = timestamp;
const elapsed = timestamp - startTime;
const progress = Math.min(1, elapsed / duration);
const easedProgress = easeInOutCubic(progress);
window.scrollTo({
top: startY + ((destinationY - startY) * easedProgress),
behavior: 'auto'
});
if (progress < 1) {
immersionFrameId = window.requestAnimationFrame(stepScroll);
} else {
immersionFrameId = null;
if (onComplete) onComplete();
}
};
immersionFrameId = window.requestAnimationFrame(stepScroll);
};
heroImmersionTrigger.addEventListener('click', () => {
stopImmersionScroll();
const heroTop = window.scrollY + heroTunnelSection.getBoundingClientRect().top;
const maxTravel = Math.max(0, heroTunnelSection.offsetHeight - window.innerHeight);
const currentProgress = getTunnelState().scrollPercent;
const autoplayStops = tunnelSteps
.map((step, index) => Math.min(step.threshold + (index === 0 ? 0.05 : 0.04), 0.62))
.filter((stop) => stop > currentProgress + 0.015);
if (!autoplayStops.length) {
autoplayStops.push(Math.min(0.62, currentProgress + 0.12));
}
const runImmersionStep = (index) => {
if (index >= autoplayStops.length) {
immersionFrameId = null;
if (postHeroSection) {
immersionTimeoutId = window.setTimeout(() => {
immersionTimeoutId = null;
const nextSectionTop = window.scrollY + postHeroSection.getBoundingClientRect().top - 24;
animateViewportTo(nextSectionTop, 1650);
}, 700);
} else {
immersionTimeoutId = null;
}
return;
}
const destinationY = heroTop + (maxTravel * autoplayStops[index]);
const distance = Math.abs(destinationY - window.scrollY);
const duration = Math.min(1700, Math.max(950, distance * 1.7));
animateViewportTo(destinationY, duration, () => {
immersionTimeoutId = window.setTimeout(() => {
immersionTimeoutId = null;
runImmersionStep(index + 1);
}, 950);
});
};
runImmersionStep(0);
});
window.addEventListener('wheel', stopImmersionScroll, { passive: true });
window.addEventListener('touchstart', stopImmersionScroll, { passive: true });
window.addEventListener('scroll', syncTunnelToScroll, { passive: true });
window.addEventListener('resize', syncTunnelToScroll);
syncTunnelToScroll();
}
// Reveal on scroll
const observerOptions = { threshold: 0.15 };
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) entry.target.classList.add('active');
});
}, observerOptions);
document.querySelectorAll('.reveal').forEach(el => observer.observe(el));
// Navbar interaction
const navbar = document.getElementById('navbar');
const logoText = document.getElementById('nav-logo-text');
const links = [
document.getElementById('nav-link-1'),
document.getElementById('nav-link-2'),
document.getElementById('nav-link-3')
];
const toggle = document.getElementById('nav-toggle');
const syncNavbarState = () => {
if (window.scrollY > 100) {
navbar.classList.add('nav-scrolled');
logoText.classList.replace('text-navy', 'text-white');
links.forEach(l => l.classList.replace('text-slate-600', 'text-white/80'));
toggle.classList.replace('text-navy', 'text-white');
} else {
navbar.classList.remove('nav-scrolled');
logoText.classList.replace('text-navy', 'text-white');
links.forEach(l => l.classList.replace('text-slate-600', 'text-white/80'));
toggle.classList.replace('text-navy', 'text-white');
}
};
window.addEventListener('scroll', syncNavbarState);
syncNavbarState();
</script>
</body>
</html>