// ============= GOOGLE ADS TAG (injection automatique) =============
(function() {
if (window.__ticoqueGtagInjected) return;
window.__ticoqueGtagInjected = true;
var s = document.createElement('script');
s.async = true;
s.src = 'https://www.googletagmanager.com/gtag/js?id=AW-18145448272';
document.head.appendChild(s);
window.dataLayer = window.dataLayer || [];
window.gtag = function() { dataLayer.push(arguments); };
gtag('js', new Date());
gtag('config', 'AW-18145448272');
})();
// ====================================================================
// SIMULATOR TICOQUE V16 — Projet Complet Piscine + Aménagement
// Décisions validées 4 voix (Seb + Claude Chat + ChatGPT + Code) le 03/05/2026
// Tarifs V3 catalogue 2026 + ajout DP-S180 + photo H1600 corrigée + dim+longueur
// + Margelles auto + Plage 5 procédés + Avantage progressif 500/1000/1500 €
// ====================================================================
// ============= CATALOG PISCINES =============
var TICOQUE_CATALOG = {
spas: [
{ref:'SPA-01', nom:'Demoiselle', dim:'2,10×1,84×0,62m', surface:'3,9 m²', perimetre:8.7, prix:3453, photo:'ticoque-spa_demoiselle_01_clean.jpg'},
{ref:'SPA-02', nom:'Anémone', dim:'⌀1,80×1,00m', surface:'2,5 m²', perimetre:7.9, prix:3942, photo:'ticoque-spa_anemone_01_clean.jpg'},
{ref:'SPA-03', nom:'Galet', dim:'2,20×2,20×0,90m', surface:'4,8 m²', perimetre:9.7, prix:4574, photo:'ticoque-spa_galet_01_clean.jpg'}
],
petites: [
{ref:'FPS-01', nom:'Picot', dim:'3,00×2,00×1,00m', surface:'6,0 m²', perimetre:11.0, prix:9900, photo:'ticoque_picot_01_clean.jpg'},
{ref:'FPS-02', nom:'Sirima', dim:'3,60×2,15×1,00m', surface:'7,7 m²', perimetre:12.7, prix:10500, photo:'ticoque_sirima_03_clean.jpg'},
{ref:'FPS-03', nom:'Baliste', dim:'3,20×2,00×1,20m', surface:'6,4 m²', perimetre:11.4, prix:11900, photo:'ticoque_baliste_02_clean_branded.jpg', badge:'Best-seller'},
{ref:'FPS-04', nom:'Tang', dim:'3,60×2,15×1,40m', surface:'9,7 m²', perimetre:12.7, prix:12900, photo:'ticoque_tang_02_clean.jpg'}
],
design: [
{ref:'DSP-01', nom:'Capucin', dim:'5,40×2,20×1,40m', surface:'11,9 m²', perimetre:16.7, prix:16900, photo:'capucin-1.jpg'},
{ref:'DSP-02', nom:'Bourgeois', dim:'5,80×2,20×1,20m', surface:'12,8 m²', perimetre:17.6, prix:16900, photo:'bourgeois-1.jpg'},
{ref:'DSP-02C', nom:'Bourgeois Sport', dim:'5,64×2,20×1-1,3m', surface:'12,4 m²', perimetre:17.2, prix:17900, photo:'bourgeois-sport-1.jpg'},
{ref:'DSP-03', nom:'Perroquet', dim:'6,00×2,00×1,20m', surface:'12,0 m²', perimetre:17.6, prix:16900, photo:'perroquet-1.jpg'},
{ref:'DSP-04', nom:'Bécune', dim:'6,00×2,45×1,45m', surface:'14,7 m²', perimetre:18.6, prix:17900, photo:'becune-1.jpg'},
{ref:'DSP-05', nom:'Empereur', dim:'7,00×2,30×1,40m', surface:'16,1 m²', perimetre:20.5, prix:19500, photo:'empereur-1.jpg'}
],
modulaires: [
{ref:'MSP-04', nom:'Mérou', dim:'6,00×3,00×1,50m', surface:'18,0 m²', perimetre:18.0, prix:20900, photo:'ticoque_merou_02_clean.jpg', badge:'Best-seller'},
{ref:'MSP-01', nom:'Carangue', dim:'8,00×4,00×1,60m', surface:'32,0 m²', perimetre:26.4, prix:26900, photo:'ticoque_carangue_03_clean.jpg'},
{ref:'MSP-02', nom:'Wahoo', dim:'8,00×4,00×1,60m', surface:'32,0 m²', perimetre:26.4, prix:28900, photo:'ticoque_wahoo_01_clean.jpg'},
{ref:'MSP-03', nom:'Bonite', dim:'8,00×4,00×1,60m', surface:'32,0 m²', perimetre:26.4, prix:29900, photo:'ticoque_bonite_01_clean_nologo.jpg'},
{ref:'MSP-05', nom:'Thazard', dim:'8,00×4,00×1,60m', surface:'32,0 m²', perimetre:26.4, prix:32900, photo:'tc-3d-real-msp05.jpg'},
{ref:'MSP-06', nom:'Marlin', dim:'9,00×6,00×1,60m', surface:'54,0 m²', perimetre:30.0, prix:49900, photo:'ticoque_marlin_02_clean.jpg', badge:'Exclusivité 974'}
],
toboggans: [
{ref:'DP-S178', nom:'T-1,8 Compact', dim:'H 1,78 m · L 2,80 m', emprise:'1,55x2,07m', prix:5990, photo:'toboggan-02-1_branded.jpg'},
{ref:'DP-S180', nom:'T-1,8 Grand', dim:'H 1,80 m · L 8,00 m', emprise:'8,60x3,50m', prix:10534, photo:'ticoque_toboggan_s180_clean.png'},
{ref:'DP-H1000', nom:'T-1,0 Famille', dim:'H 1,00 m · L 8,00 m', emprise:'5,00x5,00m', prix:10190, photo:'TiCoque_Toboggan_T-10-Famille_H1000_01-scaled.png'},
{ref:'DP-H1600', nom:'T-1,6 Parcours', dim:'H 1,60 m · L 6,00 m', emprise:'5,70x3,40m', prix:11546, photo:'ticoque_toboggan_h1600_clean.png'},
{ref:'DP-H120', nom:'T-1,2 XL', dim:'H 1,20 m · L 10,50 m', emprise:'4,60x7,40m', prix:12044, photo:'ticoque_toboggan_dp-h120_01_clean.jpg'},
{ref:'DP-CS200', nom:'T-2,0 Sensation', dim:'H 2,00 m · L 18,00 m', emprise:'3,60x2,90m', prix:14069, photo:'ticoque_toboggan_dp-cs200_01_clean.jpg', badge:'Nouveau'},
{ref:'DP-H230', nom:'T-2,3 Pro', dim:'H 2,30 m · L 14,60 m', emprise:'7,60x4,50m', prix:19109, photo:'ticoque_toboggan_h230_02_clean.jpg', badge:'Top de gamme'},
{ref:'DP-H220', nom:'T-2,2 Sport', dim:'H 2,20 m · L 16,50 m', emprise:'6,50x4,50m', prix:19522, photo:'ticoque_toboggan_h220_01_clean.jpg'}
]
};
// ============= TARIFS ARE =============
var ARE_PLAGE_PRICES = {imprime:120, cire:170, enduit:110, gazon:100, ndp:130};
var ARE_PLAGE_NAMES = {
imprime:'Béton imprimé sol',
cire:'Béton ciré extérieur',
enduit:'Enduit projeté / sol décoratif',
gazon:'Gazon synthétique',
ndp:'À définir au RDV'
};
var ARE_MARGELLE_PRICE_ML = 100; // €/ml posé
var PACK_OFFER_END = '2026-06-30';
// ============= PHOTOS BASE URL =============
var PHOTO_BASE_URL = 'https://ti-coque.re/wp-content/uploads/2026/04/';
var PHOTO_BASE_URL_2026_05 = 'https://ti-coque.re/wp-content/uploads/2026/05/';
function photoUrl(filename) {
if (!filename) return '';
// URL complete deja fournie
if (filename.indexOf('http') === 0) return filename;
// Photos uploaded in May (toboggan-h1600, s180, becune, empereur)
if (filename.indexOf('h1600_clean.png') >= 0 || filename.indexOf('s180_clean.png') >= 0
|| filename === 'becune-1.jpg' || filename === 'empereur-1.jpg') {
return PHOTO_BASE_URL_2026_05 + filename;
}
return PHOTO_BASE_URL + filename;
}
// ============= STATE =============
var state = {
selectedPiscine: null,
selectedToboggan: null,
margelles: 'rdv', // 'oui' | 'non' | 'rdv'
plage: 'rdv', // 'oui' | 'non' | 'rdv'
procede: null, // 'imprime' | 'cire' | 'enduit' | 'gazon' | 'ndp'
surface: null, // number (m²) | 'ndp'
surfaceNdp: false
};
// ============= RENDER MODELES =============
function renderModels(catKey, containerId, isToboggan) {
var container = document.getElementById(containerId);
if (!container) return;
var items = TICOQUE_CATALOG[catKey];
if (!items) return;
container.innerHTML = '';
items.forEach(function(item) {
var card = document.createElement('div');
card.className = 'tc-model';
card.dataset.ref = item.ref;
var hasPhoto = item.photo && item.photo.length > 0;
var photoStyle = hasPhoto
? 'background:url(\'' + photoUrl(item.photo) + '\') center/cover no-repeat;'
: 'background:linear-gradient(135deg,var(--navy),var(--navy-deep));';
var badgeHtml = item.badge ? '' + item.badge + '' : '';
var dimHtml = isToboggan
? '
' + item.dim + ' · emprise ' + item.emprise + '
'
: '' + item.dim + ' · ' + item.surface + '
';
card.innerHTML =
'' +
'' + item.nom + ' ' + badgeHtml + '
' +
dimHtml +
'' + item.ref + '
' +
'' + item.prix.toLocaleString('fr-FR') + ' € TTC
';
card.addEventListener('click', function() {
if (isToboggan) {
if (card.classList.contains('selected')) {
card.classList.remove('selected');
state.selectedToboggan = null;
} else {
var allCards = container.querySelectorAll('.tc-model');
allCards.forEach(function(c) { c.classList.remove('selected'); });
card.classList.add('selected');
state.selectedToboggan = item;
}
} else {
// Piscine : single select across all piscine grids
var allPiscineCards = document.querySelectorAll('#models-spas .tc-model, #models-petites .tc-model, #models-design .tc-model, #models-modulaires .tc-model');
allPiscineCards.forEach(function(c) { c.classList.remove('selected'); });
card.classList.add('selected');
state.selectedPiscine = item;
// Update margelles preview
updateMargelleAuto();
}
updateTotals();
});
container.appendChild(card);
});
}
// ============= MARGELLES + PLAGE HANDLERS =============
function updateMargelleAuto() {
if (!state.selectedPiscine) return;
var ml = state.selectedPiscine.perimetre;
var prix = ml * ARE_MARGELLE_PRICE_ML;
var metaEl = document.getElementById('marg-auto-meta');
var priceEl = document.getElementById('marg-auto-price');
if (metaEl) metaEl.textContent = ml.toFixed(1) + ' ml × 100 €/ml posé (périmètre × 1,10)';
if (priceEl) priceEl.textContent = prix.toLocaleString('fr-FR') + ' €';
}
function setupChoiceGroup(name, defaultValue, onChange) {
var btns = document.querySelectorAll('[data-' + name + ']');
btns.forEach(function(btn) {
btn.addEventListener('click', function() {
btns.forEach(function(b) { b.classList.remove('selected'); });
btn.classList.add('selected');
var val = btn.dataset[name.replace(/-/g, '')] || btn.getAttribute('data-' + name);
if (onChange) onChange(val);
updateTotals();
});
if (btn.getAttribute('data-' + name) === defaultValue) {
btn.classList.add('selected');
}
});
}
// ============= CALCULS =============
function calcSubtotalTicoque() {
var t = 0;
if (state.selectedPiscine) t += state.selectedPiscine.prix;
if (state.selectedToboggan) t += state.selectedToboggan.prix;
return t;
}
function calcSubtotalAre() {
var t = 0;
if (state.margelles === 'oui' && state.selectedPiscine) {
t += state.selectedPiscine.perimetre * ARE_MARGELLE_PRICE_ML;
}
if (state.plage === 'oui' && state.procede && state.surface && state.surface !== 'ndp') {
var surf = parseFloat(state.surface);
if (!isNaN(surf) && surf > 0) {
t += surf * ARE_PLAGE_PRICES[state.procede];
}
}
return t;
}
function calcAvantage() {
// Verrou : margelles + plage (avec procédé + surface valide) requis
if (state.margelles !== 'oui') return 0;
if (state.plage !== 'oui') return 0;
if (!state.procede) return 0;
if (!state.surface || state.surface === 'ndp') return 0;
var surf = parseFloat(state.surface);
if (isNaN(surf) || surf <= 0) return 0;
var totalProjet = calcSubtotalTicoque() + calcSubtotalAre();
if (totalProjet >= 30000) return 1500;
if (totalProjet >= 20000) return 1000;
if (totalProjet >= 15000) return 500;
return 0;
}
function calcTotal() {
return calcSubtotalTicoque() + calcSubtotalAre() - calcAvantage();
}
// ============= UPDATE TOTALS + RECAP =============
function updateTotals() {
var subtotal = calcSubtotalTicoque() + calcSubtotalAre();
var avantage = calcAvantage();
var total = subtotal - avantage;
var formattedTotal = total > 0 ? total.toLocaleString('fr-FR') + ' €' : '—';
['step2-total', 'step3-total'].forEach(function(id) {
var el = document.getElementById(id);
if (el) el.innerHTML = formattedTotal + ' TTC clé en main';
});
// Recap text
var recap = '';
if (state.selectedPiscine) recap += state.selectedPiscine.nom + ' (' + state.selectedPiscine.ref + ')';
if (state.selectedToboggan) recap += (recap ? ' + ' : '') + 'toboggan ' + state.selectedToboggan.nom;
if (state.margelles === 'oui') recap += (recap ? ' + ' : '') + 'margelles';
if (state.plage === 'oui' && state.procede && state.surface && state.surface !== 'ndp') {
recap += (recap ? ' + ' : '') + ARE_PLAGE_NAMES[state.procede].toLowerCase();
}
if (!recap) recap = 'Sélectionnez vos produits';
['step2-recap', 'step3-recap'].forEach(function(id) {
var el = document.getElementById(id);
if (el) el.textContent = recap;
});
// Detail récap 3 lignes (sous-total / avantage / total)
var subEl = document.getElementById('recap-subtotal');
var avRow = document.getElementById('recap-avantage-row');
var avVal = document.getElementById('recap-avantage-value');
var totalNetEl = document.getElementById('recap-total-net');
var palierBadge = document.getElementById('recap-palier-badge');
if (subEl) subEl.textContent = subtotal > 0 ? subtotal.toLocaleString('fr-FR') + ' €' : '—';
if (avRow) avRow.style.display = avantage > 0 ? '' : 'none';
if (avVal) avVal.textContent = '−' + avantage.toLocaleString('fr-FR') + ' €';
if (totalNetEl) totalNetEl.textContent = total > 0 ? total.toLocaleString('fr-FR') + ' € TTC' : '—';
if (palierBadge) {
if (avantage === 500) palierBadge.textContent = 'Palier 15-20 k€';
else if (avantage === 1000) palierBadge.textContent = 'Palier 20-30 k€';
else if (avantage === 1500) palierBadge.textContent = 'Palier > 30 k€';
else palierBadge.textContent = '';
palierBadge.style.display = avantage > 0 ? '' : 'none';
}
// Message contextuel d'incitation Avantage Projet Complet
var incitEl = document.getElementById('avantage-incitation');
if (incitEl) {
var hasPiscine = !!state.selectedPiscine;
var hasMarg = state.margelles === 'oui';
var hasPlage = state.plage === 'oui' && state.procede && state.surface && state.surface !== 'ndp';
if (hasPiscine && hasMarg && hasPlage && avantage > 0) {
incitEl.style.display = '';
incitEl.className = 'tc-incitation tc-incitation-active';
incitEl.innerHTML = '✓ Avantage Projet Complet : −' + avantage.toLocaleString('fr-FR') + ' € activé. Déduit de la facture aménagement (Atelier Roche & Eau).';
} else if (hasPiscine && hasMarg && !hasPlage) {
incitEl.style.display = '';
incitEl.className = 'tc-incitation tc-incitation-hint';
incitEl.innerHTML = '💡 Ajoutez une plage décorative ou gazon synthétique pour activer l\'Avantage Projet Complet (jusqu\'à 1 500 € sur la facture aménagement).';
} else if (hasPiscine && !hasMarg && hasPlage) {
incitEl.style.display = '';
incitEl.className = 'tc-incitation tc-incitation-hint';
incitEl.innerHTML = '💡 Ajoutez des margelles pour activer l\'Avantage Projet Complet (jusqu\'à 1 500 € sur la facture aménagement).';
} else if (hasPiscine && !hasMarg && !hasPlage) {
incitEl.style.display = '';
incitEl.className = 'tc-incitation tc-incitation-hint';
incitEl.innerHTML = '💡 Ajoutez margelles + plage décorative ou gazon synthétique pour bénéficier de l\'Avantage Projet Complet (jusqu\'à 1 500 € sur la facture aménagement).';
} else {
incitEl.style.display = 'none';
}
}
}
// ============= NAVIGATION ÉTAPES =============
function goStep(n) {
['step-1','step-2','step-3','step-final'].forEach(function(id, i) {
var el = document.getElementById(id);
if (!el) return;
if (i === n - 1 || (n === 4 && id === 'step-final')) {
el.classList.remove('hidden');
} else {
el.classList.add('hidden');
}
});
['ps-1','ps-2','ps-3'].forEach(function(id, i) {
var el = document.getElementById(id);
if (!el) return;
el.classList.toggle('done', i < n - 1);
el.classList.toggle('active', i === n - 1);
});
window.scrollTo({top: 0, behavior: 'smooth'});
}
window.goStep = goStep;
// ============= ENVOI DEVIS =============
function submitDevis() {
var prenom = document.getElementById('c-prenom').value.trim();
var nom = document.getElementById('c-nom').value.trim();
var email = document.getElementById('c-email').value.trim();
var tel = document.getElementById('c-tel').value.trim();
var rgpd = document.getElementById('c-rgpd').checked;
var honeypot = document.getElementById('c-website').value;
if (!prenom || !nom || !email || !tel) {
alert('Merci de remplir tous les champs obligatoires.');
return;
}
if (!rgpd) {
alert('Merci de cocher la case d\'acceptation RGPD.');
return;
}
// Build lines for plugin
var lines = [];
if (state.selectedPiscine) {
lines.push({
type: 'piscine-coque',
title: 'Piscine ' + state.selectedPiscine.nom + ' · ' + state.selectedPiscine.ref,
detail: 'Coque polyester ' + state.selectedPiscine.dim + ' · ' + state.selectedPiscine.surface +
' · TTC clé en main posée par Ti-Coque · Garantie 10 ans coque + 1 an INARYO.',
qty: 1,
pu: state.selectedPiscine.prix,
total: state.selectedPiscine.prix,
photo: state.selectedPiscine.photo ? photoUrl(state.selectedPiscine.photo) : ''
});
}
if (state.selectedToboggan) {
lines.push({
type: 'toboggan',
title: 'Toboggan ' + state.selectedToboggan.nom + ' · ' + state.selectedToboggan.ref,
detail: 'Toboggan aquatique · ' + state.selectedToboggan.dim + ' · emprise ' + state.selectedToboggan.emprise + ' · TTC clé en main posé par Ti-Coque.',
qty: 1,
pu: state.selectedToboggan.prix,
total: state.selectedToboggan.prix,
photo: state.selectedToboggan.photo ? photoUrl(state.selectedToboggan.photo) : ''
});
}
if (state.margelles === 'oui' && state.selectedPiscine) {
var ml = state.selectedPiscine.perimetre;
var pmar = ml * ARE_MARGELLE_PRICE_ML;
lines.push({
type: 'are-margelles',
title: 'Margelles posées · ' + ml.toFixed(1) + ' ml',
detail: 'Margelle de base, fourni-posé par Atelier Roche & Eau. Calcul auto périmètre × 1,10 (coupes). Mesure définitive au RDV technique.',
qty: ml,
pu: ARE_MARGELLE_PRICE_ML,
total: pmar,
photo: ''
});
}
if (state.plage === 'oui' && state.procede) {
var procedeName = ARE_PLAGE_NAMES[state.procede];
var prixM2 = ARE_PLAGE_PRICES[state.procede];
if (state.surface === 'ndp' || !state.surface) {
lines.push({
type: 'are-plage',
title: 'Plage ' + procedeName + ' · surface à définir',
detail: 'Posée par Atelier Roche & Eau. Surface définitive et chiffrage au RDV technique. Tarif indicatif : ' + prixM2 + ' €/m².',
qty: 1, pu: 0, total: 0, photo: ''
});
} else {
var surf = parseFloat(state.surface);
var pp = surf * prixM2;
lines.push({
type: 'are-plage',
title: 'Plage ' + procedeName + ' · ' + surf + ' m²',
detail: surf + ' m² fourni-posé par Atelier Roche & Eau au tarif ' + prixM2 + ' €/m². Surface définitive à confirmer au RDV technique.',
qty: surf,
pu: prixM2,
total: pp,
photo: ''
});
}
}
var subtotalAre = calcSubtotalAre();
var avantage = calcAvantage();
var totalHT_real = (calcTotal() / 1.085);
var devisNum = 'TC-' + Date.now().toString(36).toUpperCase();
// Construct projets label
var projets = '';
if (state.selectedPiscine) projets += state.selectedPiscine.nom;
if (state.selectedToboggan) projets += (projets ? ' + ' : '') + state.selectedToboggan.nom;
if (state.margelles === 'oui') projets += (projets ? ' + ' : '') + 'margelles';
if (state.plage === 'oui') projets += (projets ? ' + ' : '') + 'plage';
var projInfo = {
commune: document.getElementById('proj-commune') ? document.getElementById('proj-commune').value : '',
acces: document.getElementById('proj-acces') ? document.getElementById('proj-acces').value : '',
delai: document.getElementById('proj-delai') ? document.getElementById('proj-delai').value : '',
budget: document.getElementById('proj-budget') ? document.getElementById('proj-budget').value : '',
message: document.getElementById('proj-message') ? document.getElementById('proj-message').value : ''
};
var apiPayload = {
devisNum: devisNum,
client: {prenom: prenom, nom: nom, email: email, tel: tel},
projets: projets,
totalHT: totalHT_real,
lines: lines,
source: window.location.hostname,
_projectInfo: projInfo,
_isTTC: true,
_pack: {
avantage: avantage,
subtotalTicoque: calcSubtotalTicoque(),
subtotalAre: subtotalAre,
total: calcTotal(),
offerEnd: PACK_OFFER_END,
hasMargelles: state.margelles === 'oui',
hasPlage: state.plage === 'oui',
procede: state.procede,
surface: state.surface,
avantageEligible: (state.margelles === 'oui' && state.plage === 'oui' && state.procede && state.surface && state.surface !== 'ndp')
},
_honeypot: honeypot
};
// GA4 tracking
if (typeof gtag === 'function') {
try {
gtag('event', 'complete_simulator', {
pack_selected: apiPayload._pack.avantageEligible,
pack_components: (state.selectedPiscine ? 'piscine_' : '') +
(state.selectedToboggan ? 'toboggan_' : '') +
(state.margelles === 'oui' ? 'margelles_' : '') +
(state.plage === 'oui' ? 'plage' : '').replace(/_$/, ''),
tier_avantage: avantage,
total_value_eur: Math.round(calcTotal()),
selected_model: state.selectedPiscine ? state.selectedPiscine.ref : 'none',
procede_plage: state.procede || 'none'
});
} catch(e) {}
}
// Submit to plugin endpoint
var endpoint = window.location.origin + '/wp-json/inaryo/v1/devis';
fetch(endpoint, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(apiPayload)
}).then(function(r) {
return r.json();
}).then(function(d) {
if (d.success) {
// Google Ads conversion tracking
if (typeof gtag === 'function') {
gtag('event', 'conversion', {
'send_to': 'AW-18145448272/T9v7CJnDp6kcENCitsxD',
'value': 50.0,
'currency': 'EUR',
'transaction_id': devisNum
});
}
var devisNumEl = document.getElementById('devis-num');
if (devisNumEl) devisNumEl.textContent = devisNum;
goStep(4);
} else {
alert('Erreur lors de l\'envoi : ' + (d.error || 'inconnu') + '. Merci de nous contacter directement à contact@ti-coque.re');
}
}).catch(function(e) {
alert('Erreur réseau : ' + e.message + '. Merci de nous contacter directement à contact@ti-coque.re');
});
}
window.submitDevis = submitDevis;
// ============= INIT =============
function initSimulator() {
renderModels('spas', 'models-spas');
renderModels('petites', 'models-petites');
renderModels('design', 'models-design');
renderModels('modulaires', 'models-modulaires');
renderModels('toboggans', 'models-toboggans', true);
setupChoiceGroup('marg', 'rdv', function(v) { state.margelles = v; });
setupChoiceGroup('plage', 'rdv', function(v) {
state.plage = v;
var details = document.getElementById('plage-details');
if (details) details.style.display = (v === 'oui') ? 'block' : 'none';
});
setupChoiceGroup('procede', null, function(v) { state.procede = v; });
// Surface input
var surfaceInput = document.getElementById('surface-input');
var ndpLink = document.getElementById('surface-ndp-link');
var ndpActive = document.getElementById('surface-ndp-active');
var ndpCancel = document.getElementById('surface-ndp-cancel');
if (surfaceInput) {
surfaceInput.addEventListener('input', function() {
var v = parseFloat(surfaceInput.value);
if (!isNaN(v) && v > 0) {
state.surface = String(Math.round(v));
state.surfaceNdp = false;
} else {
state.surface = null;
}
updateTotals();
});
}
if (ndpLink) {
ndpLink.addEventListener('click', function(e) {
e.preventDefault();
state.surface = 'ndp';
state.surfaceNdp = true;
if (surfaceInput) surfaceInput.value = '';
ndpLink.style.display = 'none';
if (ndpActive) ndpActive.style.display = 'block';
updateTotals();
});
}
if (ndpCancel) {
ndpCancel.addEventListener('click', function(e) {
e.preventDefault();
state.surface = null;
state.surfaceNdp = false;
if (ndpLink) ndpLink.style.display = 'inline';
if (ndpActive) ndpActive.style.display = 'none';
if (surfaceInput) surfaceInput.focus();
updateTotals();
});
}
updateTotals();
// GA4 — start_simulator quand on ouvre la page
if (typeof gtag === 'function') {
try {
gtag('event', 'start_simulator', {
pack_offer_active: new Date() < new Date(PACK_OFFER_END)
});
} catch(e) {}
}
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initSimulator);
} else {
setTimeout(initSimulator, 50);
}