.my-devis-v2 {
--my-color: #20b5bd;
--my-dark: #06485b;
max-width: 760px;
margin: 24px auto;
padding: 28px;
background: #fff;
border: 1px solid #e4ecee;
border-radius: 24px;
box-shadow: 0 12px 40px #06485b12;
color: var(--my-dark);
}
.my-devis-v2 *,
.my-devis-v2 *::before {
box-sizing: border-box;
}
.my-devis-v2 [hidden] {
display: none !important;
}
.my-devis-v2 h3 {
font-size: 24px;
text-align: center;
margin: 24px 0;
}
.my-devis-v2 .wpcf7-radio {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 12px;
}
.my-devis-v2 .wpcf7-list-item {
margin: 0;
min-width: 0;
}
.my-devis-v2 .wpcf7-list-item label {
position: relative;
display: block;
height: 100%;
cursor: pointer;
}
.my-devis-v2 input[type="radio"] {
position: absolute;
width: 1px;
height: 1px;
opacity: 0;
}
.my-devis-v2 .wpcf7-list-item-label {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 10px;
height: 100%;
min-height: 135px;
padding: 18px 12px;
border: 2px solid #e4e8ec;
border-radius: 18px;
background: #f8fafb;
text-align: center;
font-size: 17px;
line-height: 1.35;
}
.my-devis-v2 .wpcf7-list-item-label::before,
.my-devis-v2 .wpcf7-list-item-label::after {
content: none;
}
.my-devis-v2 .my-icon {
display: block;
font-size: 34px;
line-height: 1.2;
}
.my-devis-v2 input:checked + .wpcf7-list-item-label {
border-color: var(--my-color);
background: #eafafb;
box-shadow: 0 5px 16px #20b5bd20;
}
.my-devis-v2 input:focus-visible + .wpcf7-list-item-label {
outline: 3px solid var(--my-dark);
outline-offset: 3px;
}
.my-devis-v2 .my-progress {
height: 7px;
background: #edf1f3;
border-radius: 20px;
overflow: hidden;
}
.my-devis-v2 .my-progress span {
display: block;
height: 100%;
background: var(--my-color);
transition: width .2s;
}
.my-devis-v2 .my-count {
margin: 10px 0;
text-align: center;
font-size: 14px;
}
.my-devis-v2 .my-nav {
display: flex;
justify-content: space-between;
gap: 12px;
margin-top: 24px;
}
.my-devis-v2 .my-nav button,
.my-devis-v2 input[type="submit"] {
padding: 14px 22px;
border: 0;
border-radius: 12px;
background: var(--my-dark);
color: #fff;
font: inherit;
font-weight: 600;
cursor: pointer;
}
.my-devis-v2 .my-nav .my-next {
margin-left: auto;
background: var(--my-color);
}
.my-devis-v2 .my-devis-step > label,
.my-devis-v2 .my-name-row label {
display: block;
margin: 14px 0;
}
.my-devis-v2 .my-name-row {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 14px;
}
.my-devis-v2 input[type="text"],
.my-devis-v2 input[type="email"],
.my-devis-v2 input[type="tel"] {
width: 100%;
margin-top: 6px;
padding: 13px;
border: 1px solid #cddcde;
border-radius: 10px;
background: #fff;
font: inherit;
}
.my-devis-v2 input[type="file"] {
display: block;
width: 100%;
margin-top: 10px;
font: inherit;
}
.my-devis-v2 .my-error {
color: #b42318;
text-align: center;
}
@media (max-width: 600px) {
.my-devis-v2 { padding: 18px 12px; }
.my-devis-v2 h3 { font-size: 21px; }
.my-devis-v2 .wpcf7-list-item-label {
font-size: 15px;
min-height: 125px;
padding: 14px 8px;
}
}(function () {
function init() {
document.querySelectorAll(".my-devis-v2").forEach(function (box) {
if (box.dataset.myV2Ready) return;const steps = Array.from(
box.querySelectorAll(".my-devis-step")
);
const form = box.closest("form");
if (!form || steps.length !== 8) return;box.dataset.myV2Ready = "1";
let current = 0;
let timer;const branches = {
"Toiture": [
"Démoussage de toiture",
"Nettoyage de toiture",
"Hydrofuge de toiture",
"Réparation de couverture",
"Pose de couverture neuve",
"Autre demande pour la toiture"
],
"Façade": [
"Démoussage de façade",
"Nettoyage de façade",
"Hydrofuge de façade",
"Autre demande pour la façade"
],
"Isolation": [
"Isolation des combles aménagés",
"Isolation des combles perdus"
]
};const icons = [
["🏠","🧱","🌡️","🏢","☀️","🪵","🔆","🌧️",
"🪟","🌳","🏭","📦","💧","🧹","🔧"],
["🌿","🧹","💧","🔧","🏠","❓",
"🌿","🧹","💧","❓","🏠","🪵","✓"],
["🏠","🏢","🏪","🏭"],
["📏","📐","🏡","🏭"],
["✅","🪜","🏗️","❓"],
["⚡","📅","🗓️","🕒"],
["📍","📍","📍","📍"]
];steps.forEach(function (step, index) {
const heading = step.querySelector("h3");
if (heading) heading.tabIndex = -1;step.querySelectorAll(
".wpcf7-list-item-label"
).forEach(function (label, n) {
const icon = document.createElement("span");
icon.className = "my-icon";
icon.setAttribute("aria-hidden", "true");
icon.textContent = (icons[index] || [])[n] || "✓";
label.prepend(icon);
});
});const header = document.createElement("div");
header.innerHTML =
'
' +
'
';
box.prepend(header);const error = document.createElement("p");
error.className = "my-error";
error.setAttribute("role", "alert");
box.append(error);const nav = document.createElement("div");
nav.className = "my-nav";
nav.innerHTML =
'
← Retour ' +
'
Continuer → ';
box.append(nav);const back = nav.querySelector(".my-back");
const next = nav.querySelector(".my-next");function category() {
const selected = steps[0].querySelector(
'input[type="radio"]:checked'
);
return selected ? selected.value : "";
}function route() {
return branches[category()]
? [0,1,2,3,4,5,6,7]
: [0,2,3,4,5,6,7];
}function configure() {
const allowed = branches[category()];
steps[1].querySelectorAll(
'input[type="radio"]'
).forEach(function (input) {
const visible = !!allowed && allowed.includes(input.value);
input.closest(".wpcf7-list-item").hidden = !visible;if (allowed) {
if (!visible) input.checked = false;
} else {
input.checked = input.value === "Sans précision";
}
});const heading = steps[1].querySelector("h3");
heading.textContent = category() === "Isolation"
? "Quels combles souhaitez-vous isoler ?"
: category() === "Façade"
? "Quelle prestation pour votre façade ?"
: "Quelle prestation pour votre toiture ?";
}function show(index, focus) {
clearTimeout(timer);
current = index;
const path = route();
const position = path.indexOf(current);steps.forEach(function (step, n) {
step.hidden = n !== current;
});
back.hidden = current === 0;
next.hidden = current === 7;
error.textContent = "";header.querySelector(".my-count").textContent =
"Étape " + (position + 1) + " sur " + path.length;
header.querySelector(".my-progress span").style.width =
((position + 1) / path.length * 100) + "%";if (focus) {
const heading = steps[current].querySelector("h3");
if (heading) {
heading.focus({preventScroll: true});
heading.scrollIntoView({
behavior: "smooth", block: "center"
});
}
}
}function advance() {
if (current === 7) return;
if (!steps[current].querySelector(
'input[type="radio"]:checked'
)) {
error.textContent = "Choisissez une réponse pour continuer.";
return;
}
if (current === 0) configure();
const path = route();
show(path[path.indexOf(current) + 1], true);
}back.addEventListener("click", function () {
const path = route();
const position = path.indexOf(current);
show(path[Math.max(0, position - 1)], true);
});
next.addEventListener("click", advance);box.addEventListener("change", function (event) {
if (event.target.name === "travaux") {
configure();
}
});box.addEventListener("click", function (event) {
if (!event.target.matches('input[type="radio"]')) return;
const index = steps.indexOf(
event.target.closest(".my-devis-step")
);
if (index !== current) return;
clearTimeout(timer);
timer = setTimeout(advance, 200);
});form.addEventListener("submit", function (event) {
configure();
const missing = route().find(function (index) {
return index !== 7 && !steps[index].querySelector(
'input[type="radio"]:checked'
);
});
if (missing !== undefined || current !== 7) {
event.preventDefault();
event.stopImmediatePropagation();
show(missing !== undefined ? missing : current, true);
error.textContent = "Répondez aux questions avant l’envoi.";
}
}, true);const wrapper = form.closest(".wpcf7");
if (wrapper) {
wrapper.addEventListener("wpcf7invalid", function () {
setTimeout(function () {
const invalid = box.querySelector(".wpcf7-not-valid");
if (!invalid) return;
const index = steps.indexOf(
invalid.closest(".my-devis-step")
);
if (route().includes(index)) show(index, true);
}, 0);
});
}configure();
show(0, false);
});
}init();
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", init);
}let attempts = 0;
const loading = setInterval(function () {
init();
if (++attempts >= 30) clearInterval(loading);
}, 500);
})();