{"id":2016,"date":"2026-04-17T16:46:54","date_gmt":"2026-04-17T14:46:54","guid":{"rendered":"https:\/\/labienveillance.fr\/?page_id=2016"},"modified":"2026-04-21T16:43:48","modified_gmt":"2026-04-21T14:43:48","slug":"elementor-2016","status":"publish","type":"page","link":"https:\/\/labienveillance.fr\/?page_id=2016","title":{"rendered":"Devis estimatif monte escalier"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"2016\" class=\"elementor elementor-2016\">\n\t\t\t\t<div class=\"elementor-element elementor-element-585e435 e-flex e-con-boxed wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no e-con e-parent\" data-id=\"585e435\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-55d6b59 elementor-widget elementor-widget-html\" data-id=\"55d6b59\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<div id=\"jlmLiteAppRoot\"><\/div>\r\n\r\n<script>\r\n(function () {\r\n  var root = document.getElementById(\"jlmLiteAppRoot\");\r\n  if (!root) return;\r\n\r\n  var ADMIN_CODE = \"Loli424720\";\r\n\r\n  function clone(o) {\r\n    return JSON.parse(JSON.stringify(o));\r\n  }\r\n\r\n  function escapeHtml(s) {\r\n    return String(s == null ? \"\" : s)\r\n      .replace(\/&\/g, \"&amp;\")\r\n      .replace(\/<\/g, \"&lt;\")\r\n      .replace(\/>\/g, \"&gt;\")\r\n      .replace(\/\"\/g, \"&quot;\");\r\n  }\r\n\r\n  function deepMerge(target, source) {\r\n    Object.keys(source || {}).forEach(function (key) {\r\n      if (source[key] && typeof source[key] === \"object\" && !Array.isArray(source[key])) {\r\n        if (!target[key] || typeof target[key] !== \"object\") target[key] = {};\r\n        deepMerge(target[key], source[key]);\r\n      } else {\r\n        target[key] = source[key];\r\n      }\r\n    });\r\n    return target;\r\n  }\r\n\r\n  var DEF = {\r\n    companyLine: \"La Bienveillance \u2014 Devis estimatif\",\r\n    contactUrl: \"#contact\",\r\n    contactLabel: \"CONTACTEZ-NOUS\",\r\n    comments: {\r\n      home: \"\",\r\n      type: \"\",\r\n      brand: \"\",\r\n      depart: \"\",\r\n      obstacle: \"\",\r\n      rail: \"\",\r\n      longueur: \"\",\r\n      arrivee: \"\",\r\n      pivot: \"\",\r\n      recap: \"\",\r\n      garanties: \"\",\r\n      aides: \"\",\r\n      price: \"\"\r\n    },\r\n    prices: {\r\n      includedMeters: 5,\r\n      up: {\r\n        droit: { base: 3500, mo: 650, railSup: 350, railRelevable: 680, extPlus: 300, pivotElec: 0 },\r\n        courbe: { base: 7900, mo: 900, railSup: 300, courbe: 280, railRelevable: 750, pivotElec: 0 }\r\n      },\r\n      acorn: {\r\n        droit: { base: 3200, mo: 650, railSup: 350, railRelevable: 600, extPlus: 300, pivotElec: 600 },\r\n        courbe: { base: 5700, mo: 750, railSup: 350, courbe: 450, railRelevable: 600, pivotElec: 600 }\r\n      }\r\n    },\r\n    images: {\r\n      logo: { url: \"https:\/\/laseptiemecom.wpcomstaging.com\/wp-content\/uploads\/2026\/03\/logomakr-0c1pju.png\" },\r\n      type_droit: { url: \"https:\/\/laseptiemecom.wpcomstaging.com\/wp-content\/uploads\/2026\/03\/escalier-droit.jpg\" },\r\n      type_90: { url: \"https:\/\/laseptiemecom.wpcomstaging.com\/wp-content\/uploads\/2026\/03\/escalier-90.jpg\" },\r\n      type_180: { url: \"https:\/\/laseptiemecom.wpcomstaging.com\/wp-content\/uploads\/2026\/03\/escalier-180c2b0.jpg\" },\r\n      type_ext: { url: \"https:\/\/laseptiemecom.wpcomstaging.com\/wp-content\/uploads\/2026\/03\/serenite-monte-escalier-monte-escaliers7-390x380-1.jpeg\" },\r\n      marque_up: { url: \"https:\/\/laseptiemecom.wpcomstaging.com\/wp-content\/uploads\/2026\/03\/camscanner-23-02-2026-15.20_1.jpg\" },\r\n      marque_acorn: { url: \"https:\/\/laseptiemecom.wpcomstaging.com\/wp-content\/uploads\/2026\/03\/0abcd33b-7191-4d4f-81fe-5097d415b3cc_image1.png\" },\r\n      depart_std: { url: \"https:\/\/laseptiemecom.wpcomstaging.com\/wp-content\/uploads\/2026\/03\/whatsapp-image-2026-03-04-at-14.44.17.jpeg\" },\r\n      depart_rall: { url: \"https:\/\/laseptiemecom.wpcomstaging.com\/wp-content\/uploads\/2026\/03\/whatsapp-image-2026-03-04-at-14.45.07.jpeg\" },\r\n      depart_p90: { url: \"https:\/\/laseptiemecom.wpcomstaging.com\/wp-content\/uploads\/2026\/03\/whatsapp-image-2026-03-04-at-15.20.00.jpeg\" },\r\n      depart_p180: { url: \"https:\/\/laseptiemecom.wpcomstaging.com\/wp-content\/uploads\/2026\/03\/whatsapp-image-2024-11-17-a-15.19.52_789038bb.jpg\" },\r\n      obstacle_ex1: { url: \"https:\/\/laseptiemecom.wpcomstaging.com\/wp-content\/uploads\/2026\/03\/whatsapp-image-2025-07-23-at-16.55.59-1-768x1024-1.jpeg\" },\r\n      obstacle_ex2: { url: \"https:\/\/laseptiemecom.wpcomstaging.com\/wp-content\/uploads\/2026\/03\/WhatsApp-Image-2026-02-02-at-15.22.57.jpeg\" },\r\n      obstacle_yes: { url: \"https:\/\/laseptiemecom.wpcomstaging.com\/wp-content\/uploads\/2026\/03\/IMG_4902.jpeg\" },\r\n      obstacle_no: { url: \"https:\/\/laseptiemecom.wpcomstaging.com\/wp-content\/uploads\/2026\/03\/whatsapp-image-2024-11-17-a-15.19.52_38b0d7f8.jpg\" },\r\n      rail_1: { url: \"https:\/\/laseptiemecom.wpcomstaging.com\/wp-content\/uploads\/2026\/03\/WhatsApp-Image-2026-02-02-at-15.22.57.jpeg\" },\r\n      rail_2: { url: \"https:\/\/laseptiemecom.wpcomstaging.com\/wp-content\/uploads\/2026\/03\/IMG_4902.jpeg\" },\r\n      rail_yes: { url: \"https:\/\/laseptiemecom.wpcomstaging.com\/wp-content\/uploads\/2026\/03\/whatsapp-image-2026-03-04-at-14.54.44.jpeg\" },\r\n      rail_no: { url: \"https:\/\/laseptiemecom.wpcomstaging.com\/wp-content\/uploads\/2026\/03\/whatsapp-image-2024-11-17-a-15.19.52_38b0d7f8.jpg\" },\r\n      arr_nez: { url: \"https:\/\/laseptiemecom.wpcomstaging.com\/wp-content\/uploads\/2026\/03\/WhatsApp-Image-2026-03-04-at-14.51.48.jpeg\" },\r\n      arr_prol: { url: \"https:\/\/laseptiemecom.wpcomstaging.com\/wp-content\/uploads\/2026\/03\/whatsapp-image-2026-03-01-at-08.10.01.jpeg\" },\r\n      arr_90: { url: \"https:\/\/laseptiemecom.wpcomstaging.com\/wp-content\/uploads\/2026\/03\/whatsapp-image-2026-03-01-at-08.08.50.jpeg\" },\r\n      arr_180: { url: \"https:\/\/laseptiemecom.wpcomstaging.com\/wp-content\/uploads\/2026\/03\/whatsapp-image-2024-11-17-a-15.19.53_562a3c5e-1.jpg\" },\r\n      pivot_manuel: { url: \"https:\/\/laseptiemecom.wpcomstaging.com\/wp-content\/uploads\/2026\/03\/whatsapp-image-2026-03-04-at-15.21.03.jpeg\" },\r\n      pivot_elec: { url: \"https:\/\/laseptiemecom.wpcomstaging.com\/wp-content\/uploads\/2026\/03\/whatsapp-image-2026-03-04-at-14.51.48.jpeg\" },\r\n      garanties_photo: { url: \"https:\/\/laseptiemecom.wpcomstaging.com\/wp-content\/uploads\/2026\/03\/whatsapp-image-2026-03-01-at-08.11.43.jpeg\" },\r\n      aides_photo: { url: \"https:\/\/laseptiemecom.wpcomstaging.com\/wp-content\/uploads\/2026\/03\/whatsapp-image-2026-03-01-at-08.16.15.jpeg\" }\r\n    }\r\n  };\r\n\r\n  var cfg = clone(DEF);\r\n  var adminUnlocked = false;\r\n  var app = null;\r\n\r\n  var state = {\r\n    step: 0,\r\n    msg: \"\",\r\n    showAlert: false,\r\n    type: \"\",\r\n    brand: \"\",\r\n    depart: \"\",\r\n    obstacle: \"\",\r\n    railChoice: \"\",\r\n    nbMarches: 17,\r\n    longueur: 5.1,\r\n    arrivee: \"\",\r\n    pivotMode: \"\"\r\n  };\r\n\r\n  function getLongueurEstimee() {\r\n    return Number((Number(state.nbMarches || 0) * 0.30).toFixed(2));\r\n  }\r\n\r\n  function syncLongueur() {\r\n    state.nbMarches = Math.max(1, Math.round(Number(state.nbMarches || 0)));\r\n    state.longueur = getLongueurEstimee();\r\n  }\r\n\r\n  async function wpLoadConfig() {\r\n    try {\r\n      let r = await fetch(\"\/wp-admin\/admin-ajax.php?action=jlm_get_config\", {\r\n        credentials: \"same-origin\"\r\n      });\r\n      let j = await r.json();\r\n      if (j && j.success && j.data && typeof j.data === \"object\") {\r\n        cfg = deepMerge(clone(DEF), j.data);\r\n      } else {\r\n        cfg = clone(DEF);\r\n      }\r\n    } catch (e) {\r\n      alert(\"Erreur chargement configuration\");\r\n      cfg = clone(DEF);\r\n    }\r\n  }\r\n\r\n  async function wpSaveConfig() {\r\n    try {\r\n      let r = await fetch(\"\/wp-admin\/admin-ajax.php?action=jlm_save_config\", {\r\n        method: \"POST\",\r\n        credentials: \"same-origin\",\r\n        headers: {\r\n          \"Content-Type\": \"application\/json\"\r\n        },\r\n        body: JSON.stringify(cfg)\r\n      });\r\n\r\n      let j = await r.json();\r\n\r\n      if (j && j.success) {\r\n        return true;\r\n      } else {\r\n        alert(\"Erreur : \" + (j && j.data ? j.data : \"sauvegarde impossible\"));\r\n        return false;\r\n      }\r\n    } catch (e) {\r\n      alert(\"Erreur serveur\");\r\n      return false;\r\n    }\r\n  }\r\n\r\n  function getImg(key) {\r\n    return cfg.images[key] ? cfg.images[key].url : \"\";\r\n  }\r\n\r\n  function setImageUrl(key, val) {\r\n    if (!cfg.images[key]) cfg.images[key] = { url: \"\" };\r\n    cfg.images[key].url = String(val || \"\").trim();\r\n  }\r\n\r\n  function isStraightFamily() {\r\n    return state.type === \"droit\" || state.type === \"exterieur\";\r\n  }\r\n\r\n  function isCurvedFamily() {\r\n    return state.type === \"courbe90\" || state.type === \"courbe180\";\r\n  }\r\n\r\n  function isUP() {\r\n    return state.brand === \"UP\";\r\n  }\r\n\r\n  function isACORN() {\r\n    return state.brand === \"ACORN\";\r\n  }\r\n\r\n  function hasRailRelevable() {\r\n    return state.railChoice === \"oui\";\r\n  }\r\n\r\n  function normalizeState() {\r\n    syncLongueur();\r\n\r\n    if (isStraightFamily()) {\r\n      state.depart = \"standard\";\r\n      state.arrivee = \"nez\";\r\n      state.obstacle = \"\";\r\n      if (isUP()) {\r\n        state.pivotMode = \"electrique\";\r\n      } else if (!state.pivotMode) {\r\n        state.pivotMode = \"manuel\";\r\n      }\r\n    } else {\r\n      if (isUP() && state.arrivee === \"nez\") {\r\n        state.pivotMode = \"electrique\";\r\n      } else if (state.arrivee !== \"nez\") {\r\n        state.pivotMode = \"\";\r\n      }\r\n    }\r\n  }\r\n\r\n  function typeCurveCount() {\r\n    if (state.type === \"courbe90\") return 1;\r\n    if (state.type === \"courbe180\") return 2;\r\n    return 0;\r\n  }\r\n\r\n  function departCurveCount() {\r\n    if (state.depart === \"p90\") return 1;\r\n    if (state.depart === \"p180\") return 2;\r\n    return 0;\r\n  }\r\n\r\n  function arriveeCurveCount() {\r\n    if (state.arrivee === \"p90\") return 1;\r\n    if (state.arrivee === \"p180\") return 2;\r\n    return 0;\r\n  }\r\n\r\n  function totalCurveCount() {\r\n    return typeCurveCount() + departCurveCount() + arriveeCurveCount();\r\n  }\r\n\r\n  function extraMeters() {\r\n    syncLongueur();\r\n\r\n    var longueur = Number(state.longueur || 0);\r\n\r\n    if (state.brand === \"ACORN\" && (state.type === \"courbe90\" || state.type === \"courbe180\")) {\r\n      return longueur;\r\n    }\r\n\r\n    var inc = Number(cfg.prices.includedMeters || 5);\r\n    return Math.max(0, Math.ceil(longueur - inc));\r\n  }\r\n\r\n  function needsPivotChoice() {\r\n    return state.arrivee === \"nez\" && isACORN();\r\n  }\r\n\r\n  function steps() {\r\n    normalizeState();\r\n    var s = [\"home\", \"type\", \"brand\", \"depart\"];\r\n\r\n    if (isCurvedFamily() && state.depart === \"standard\") {\r\n      s.push(\"obstacle\");\r\n      if (state.obstacle === \"oui\") s.push(\"rail\");\r\n    }\r\n\r\n    if (isStraightFamily()) s.push(\"rail\");\r\n    if (isCurvedFamily() && state.depart !== \"standard\") s.push(\"rail\");\r\n\r\n    s.push(\"longueur\", \"arrivee\");\r\n\r\n    if (needsPivotChoice()) s.push(\"pivot\");\r\n\r\n    s.push(\"recap\", \"garanties\", \"aides\", \"price\");\r\n    return s;\r\n  }\r\n\r\n  function pricingProfile() {\r\n    if (isUP()) return isCurvedFamily() ? cfg.prices.up.courbe : cfg.prices.up.droit;\r\n    return isCurvedFamily() ? cfg.prices.acorn.courbe : cfg.prices.acorn.droit;\r\n  }\r\n\r\n  function calcPriceBreakdown() {\r\n    normalizeState();\r\n\r\n    var p = pricingProfile();\r\n    var extraM = extraMeters();\r\n    var curves = totalCurveCount();\r\n\r\n    var base = Number(p.base || 0);\r\n    var mo = Number(p.mo || 0);\r\n    var railSup = extraM * Number(p.railSup || 0);\r\n    var curveCost = isCurvedFamily() ? curves * Number(p.courbe || 0) : 0;\r\n    var railRelevable = hasRailRelevable() ? Number(p.railRelevable || 0) : 0;\r\n    var pivotElec = state.pivotMode === \"electrique\" ? Number(p.pivotElec || 0) : 0;\r\n    var extPlus = state.type === \"exterieur\" ? Number(p.extPlus || 0) : 0;\r\n\r\n    return {\r\n      total: base + mo + railSup + curveCost + railRelevable + pivotElec + extPlus,\r\n      curves: curves,\r\n      extraMeters: extraM\r\n    };\r\n  }\r\n\r\n  function money(n) {\r\n    return Number(n || 0).toString().replace(\/\\B(?=(\\d{3})+(?!\\d))\/g, \" \") + \" \u20ac\";\r\n  }\r\n\r\n  function showComment(key) {\r\n    var t = (cfg.comments[key] || \"\").trim();\r\n    if (!t) return \"\";\r\n\r\n    return (\r\n      '<div class=\"commentWrap\">' +\r\n        '<button type=\"button\" class=\"commentToggle\" data-comment-open=\"' + escapeHtml(key) + '\">' +\r\n          '<span class=\"commentToggleIcon\">\u2726<\/span> Conseils' +\r\n        '<\/button>' +\r\n      '<\/div>'\r\n    );\r\n  }\r\n\r\n  function renderCommentModal() {\r\n    return (\r\n      '<div class=\"commentModalOverlay\" id=\"commentModalOverlay\">' +\r\n        '<div class=\"commentModal\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"commentModalTitle\">' +\r\n          '<div class=\"commentModalGlow\"><\/div>' +\r\n          '<div class=\"commentModalHead\">' +\r\n            '<div class=\"commentModalTitleWrap\">' +\r\n              '<div class=\"commentModalEyebrow\">La Bienveillance<\/div>' +\r\n              '<div class=\"commentModalTitle\" id=\"commentModalTitle\">Conseils<\/div>' +\r\n            '<\/div>' +\r\n            '<button type=\"button\" class=\"commentModalX\" data-comment-close=\"1\" aria-label=\"Fermer\">\u00d7<\/button>' +\r\n          '<\/div>' +\r\n          '<div class=\"commentModalBody\" id=\"commentModalBody\"><\/div>' +\r\n          '<div class=\"commentModalActions\">' +\r\n            '<button type=\"button\" class=\"btn pri\" data-comment-close=\"1\">Fermer<\/button>' +\r\n          '<\/div>' +\r\n        '<\/div>' +\r\n      '<\/div>'\r\n    );\r\n  }\r\n\r\n  function openCommentModal(key) {\r\n    var txt = (cfg.comments[key] || \"\").trim();\r\n    if (!txt) return;\r\n\r\n    var overlay = document.getElementById(\"commentModalOverlay\");\r\n    var body = document.getElementById(\"commentModalBody\");\r\n    if (!overlay || !body) return;\r\n\r\n    body.innerHTML = escapeHtml(txt).replace(\/\\n\/g, \"<br>\");\r\n    overlay.classList.add(\"show\");\r\n    document.body.classList.add(\"jlmNoScroll\");\r\n  }\r\n\r\n  function closeCommentModal() {\r\n    var overlay = document.getElementById(\"commentModalOverlay\");\r\n    var body = document.getElementById(\"commentModalBody\");\r\n    if (overlay) overlay.classList.remove(\"show\");\r\n    if (body) body.innerHTML = \"\";\r\n    document.body.classList.remove(\"jlmNoScroll\");\r\n  }\r\n\r\n  function choice(key, label, img, selected) {\r\n    return (\r\n      '<div class=\"choice ' + (selected ? \"sel\" : \"\") + '\" data-choice=\"' + escapeHtml(key) + '\">' +\r\n        '<div class=\"media\"><img decoding=\"async\" src=\"' + escapeHtml(img) + '\" alt=\"' + escapeHtml(label) + '\"><\/div>' +\r\n        '<div class=\"label\">' + escapeHtml(label) + \"<\/div>\" +\r\n      \"<\/div>\"\r\n    );\r\n  }\r\n\r\n  function validate(page) {\r\n    if (page === \"type\" && !state.type) return \"MERCI DE CHOISIR UN TYPE D\u2019ESCALIER AVANT DE CONTINUER\";\r\n    if (page === \"brand\" && !state.brand) return \"MERCI DE CHOISIR UNE MARQUE AVANT DE CONTINUER\";\r\n    if (page === \"depart\" && !state.depart) return \"MERCI DE CHOISIR UN D\u00c9PART AVANT DE CONTINUER\";\r\n    if (page === \"obstacle\" && !state.obstacle) return \"MERCI D\u2019INDIQUER OUI OU NON POUR L\u2019OBSTACLE\";\r\n    if (page === \"rail\" && !state.railChoice) return \"MERCI D\u2019INDIQUER OUI OU NON POUR LE RAIL RELEVABLE\";\r\n    if (page === \"longueur\" && !state.nbMarches) return \"MERCI D\u2019INDIQUER LE NOMBRE DE MARCHES\";\r\n    if (page === \"arrivee\" && !state.arrivee) return \"MERCI DE CHOISIR UNE ARRIV\u00c9E AVANT DE CONTINUER\";\r\n    if (page === \"pivot\" && !state.pivotMode) return \"MERCI DE CHOISIR LE TYPE DE SI\u00c8GE PIVOTANT\";\r\n    return \"\";\r\n  }\r\n\r\n  function recapMaterial() {\r\n    normalizeState();\r\n    var b = calcPriceBreakdown();\r\n\r\n    var typeMap = {\r\n      droit: \"Escalier droit\",\r\n      courbe90: \"Escalier courbe 90\u00b0\",\r\n      courbe180: \"Escalier courbe 180\u00b0\",\r\n      exterieur: \"Escalier ext\u00e9rieur\"\r\n    };\r\n    var departMap = {\r\n      standard: \"D\u00e9part standard\",\r\n      rallonge: \"D\u00e9part rallong\u00e9\",\r\n      p90: \"D\u00e9part parking 90\u00b0\",\r\n      p180: \"D\u00e9part parking 180\u00b0\"\r\n    };\r\n    var arriveeMap = {\r\n      nez: \"Arriv\u00e9e nez de marche - si\u00e8ge pivotant\",\r\n      prolonge: \"Arriv\u00e9e prolong\u00e9e\",\r\n      p90: \"Arriv\u00e9e parking 90\u00b0\",\r\n      p180: \"Arriv\u00e9e parking 180\u00b0\"\r\n    };\r\n\r\n    var out = [];\r\n    if (state.type) out.push(typeMap[state.type] || state.type);\r\n    if (state.brand) out.push(\"Marque : \" + (state.brand === \"UP\" ? \"UP Stairlift\" : \"ACORN\"));\r\n    if (state.depart) out.push(departMap[state.depart] || state.depart);\r\n    if (isCurvedFamily() && state.depart === \"standard\") out.push(\"Obstacle au d\u00e9part : \" + (state.obstacle === \"oui\" ? \"Oui\" : \"Non\"));\r\n    out.push(\"Rail relevable : \" + (state.railChoice === \"oui\" ? \"Oui\" : \"Non\"));\r\n    out.push(\"Nombre de marches : \" + Number(state.nbMarches || 0));\r\n    out.push(\"Longueur estim\u00e9e : \" + Number(state.longueur || 0).toFixed(2) + \" m\");\r\n    if (state.arrivee) out.push(arriveeMap[state.arrivee] || state.arrivee);\r\n    if (state.arrivee === \"nez\") {\r\n      if (isUP()) out.push(\"Pivot \u00e9lectrique : inclus\");\r\n      else out.push(\"Pivot : \" + (state.pivotMode === \"electrique\" ? \"\u00c9lectrique\" : \"Manuel\"));\r\n    }\r\n    if (isCurvedFamily()) out.push(\"Nombre total de courbes \u00e0 90\u00b0 : \" + b.curves);\r\n    out.push(\"M\u00e8tres factur\u00e9s : \" + b.extraMeters);\r\n    return out;\r\n  }\r\n\r\n  function renderImageField(key, label) {\r\n    return (\r\n      '<div class=\"hr\"><\/div>' +\r\n      '<label class=\"lbl\">' + escapeHtml(label) + ' \u2014 URL<\/label>' +\r\n      '<input class=\"inp\" id=\"img_' + escapeHtml(key) + '\" value=\"' + escapeHtml((cfg.images[key] || {}).url || \"\") + '\">'\r\n    );\r\n  }\r\n\r\n  function renderPage() {\r\n    normalizeState();\r\n    var id = steps()[state.step];\r\n    var breakdown = calcPriceBreakdown();\r\n\r\n    if (id === \"home\") {\r\n      return '<div class=\"card\"><div class=\"h1\">BONJOUR<\/div><div class=\"txt\">Bienvenue.<br><br>En quelques \u00e9tapes simples, obtenez une estimation claire et rassurante de votre monte-escalier.<br><br>Visite technique gratuite et absolument sans engagement.<\/div>' + showComment(\"home\") + '<\/div>';\r\n    }\r\n\r\n    if (id === \"type\") {\r\n      return '<div class=\"card\"><div class=\"h2\">TYPE D\u2019ESCALIER<\/div><div class=\"txt\">Cliquez sur une image pour choisir.<\/div><div class=\"grid\">' +\r\n        choice(\"droit\", \"Droit\", getImg(\"type_droit\"), state.type === \"droit\") +\r\n        choice(\"courbe90\", \"Courbe 90\u00b0\", getImg(\"type_90\"), state.type === \"courbe90\") +\r\n        choice(\"courbe180\", \"Courbe 180\u00b0\", getImg(\"type_180\"), state.type === \"courbe180\") +\r\n        choice(\"exterieur\", \"Ext\u00e9rieur\", getImg(\"type_ext\"), state.type === \"exterieur\") +\r\n        '<\/div>' + showComment(\"type\") + '<\/div>';\r\n    }\r\n\r\n    if (id === \"brand\") {\r\n      return '<div class=\"card\"><div class=\"h2\">MARQUE<\/div><div class=\"txt\">Cliquez sur une image pour choisir.<\/div><div class=\"grid\">' +\r\n        choice(\"UP\", \"UP Stairlift\", getImg(\"marque_up\"), state.brand === \"UP\") +\r\n        choice(\"ACORN\", \"ACORN\", getImg(\"marque_acorn\"), state.brand === \"ACORN\") +\r\n        '<\/div>' + showComment(\"brand\") + '<\/div>';\r\n    }\r\n\r\n    if (id === \"depart\") {\r\n      if (isStraightFamily()) {\r\n        return '<div class=\"card\"><div class=\"h2\">D\u00c9PART<\/div><div class=\"txt\">Pour cette configuration, le d\u00e9part est uniquement standard.<\/div><div class=\"grid\">' +\r\n          choice(\"standard\", \"Standard\", getImg(\"depart_std\"), true) +\r\n          '<\/div>' + showComment(\"depart\") + '<\/div>';\r\n      }\r\n      return '<div class=\"card\"><div class=\"h2\">D\u00c9PART<\/div><div class=\"txt\">Cliquez sur une image pour choisir.<\/div><div class=\"grid\">' +\r\n        choice(\"standard\", \"Standard\", getImg(\"depart_std\"), state.depart === \"standard\") +\r\n        choice(\"rallonge\", \"Rallong\u00e9\", getImg(\"depart_rall\"), state.depart === \"rallonge\") +\r\n        choice(\"p90\", \"Parking 90\u00b0\", getImg(\"depart_p90\"), state.depart === \"p90\") +\r\n        choice(\"p180\", \"Parking 180\u00b0\", getImg(\"depart_p180\"), state.depart === \"p180\") +\r\n        '<\/div>' + showComment(\"depart\") + '<\/div>';\r\n    }\r\n\r\n    if (id === \"obstacle\") {\r\n      return '<div class=\"card\"><div class=\"h2\">OBSTACLE AU D\u00c9PART<\/div><div class=\"txt\">Exemples ci-dessous, puis cliquez sur OUI ou NON.<\/div><div class=\"grid\">' +\r\n        '<div class=\"fixedCard\"><div class=\"media\"><img decoding=\"async\" src=\"' + escapeHtml(getImg(\"obstacle_ex1\")) + '\" alt=\"\"><\/div><div class=\"label\">Exemple<\/div><\/div>' +\r\n        '<div class=\"fixedCard\"><div class=\"media\"><img decoding=\"async\" src=\"' + escapeHtml(getImg(\"obstacle_ex2\")) + '\" alt=\"\"><\/div><div class=\"label\">Exemple<\/div><\/div>' +\r\n        '<\/div><div class=\"grid\">' +\r\n        choice(\"oui\", \"OUI\", getImg(\"obstacle_yes\"), state.obstacle === \"oui\") +\r\n        choice(\"non\", \"NON\", getImg(\"obstacle_no\"), state.obstacle === \"non\") +\r\n        '<\/div>' + showComment(\"obstacle\") + '<\/div>';\r\n    }\r\n\r\n    if (id === \"rail\") {\r\n      return '<div class=\"card\"><div class=\"h2\">RAIL RELEVABLE<\/div><div class=\"txt\">Voici deux exemples d\u2019obstacle. Puis cliquez sur OUI ou NON.<\/div><div class=\"grid\">' +\r\n        '<div class=\"fixedCard\"><div class=\"media\"><img decoding=\"async\" src=\"' + escapeHtml(getImg(\"rail_1\")) + '\" alt=\"\"><\/div><div class=\"label\">Exemple obstacle<\/div><\/div>' +\r\n        '<div class=\"fixedCard\"><div class=\"media\"><img decoding=\"async\" src=\"' + escapeHtml(getImg(\"rail_2\")) + '\" alt=\"\"><\/div><div class=\"label\">Exemple obstacle<\/div><\/div>' +\r\n        '<\/div><div class=\"grid\">' +\r\n        choice(\"rail_oui\", \"OUI\", getImg(\"rail_yes\"), state.railChoice === \"oui\") +\r\n        choice(\"rail_non\", \"NON\", getImg(\"rail_no\"), state.railChoice === \"non\") +\r\n        '<\/div>' + showComment(\"rail\") + '<\/div>';\r\n    }\r\n\r\n    if (id === \"longueur\") {\r\n      return '<div class=\"card\">' +\r\n        '<div class=\"h2\">NOMBRE DE MARCHES<\/div>' +\r\n        '<div class=\"measure\">' +\r\n          '<div class=\"bigVal\">' + Number(state.nbMarches || 0) + ' marches<\/div>' +\r\n          '<div class=\"measureSub\">' + Number(state.longueur || 0).toFixed(2) + ' m<\/div>' +\r\n          '<div class=\"measureRow\">' +\r\n            '<button class=\"arr\" data-act=\"minusMarches\">\u2212<\/button>' +\r\n            '<input class=\"range\" type=\"range\" min=\"1\" max=\"30\" step=\"1\" value=\"' + Number(state.nbMarches || 1) + '\" data-act=\"rangeMarches\">' +\r\n            '<button class=\"arr\" data-act=\"plusMarches\">+<\/button>' +\r\n          '<\/div>' +\r\n        '<\/div>' +\r\n        showComment(\"longueur\") +\r\n      '<\/div>';\r\n    }\r\n\r\n    if (id === \"arrivee\") {\r\n      if (isStraightFamily()) {\r\n        return '<div class=\"card\"><div class=\"h2\">ARRIV\u00c9E<\/div><div class=\"txt\">Pour cette configuration, l\u2019arriv\u00e9e est uniquement nez de marche.<\/div><div class=\"grid\">' +\r\n          choice(\"nez\", \"Nez de marche - si\u00e8ge pivotant\", getImg(\"arr_nez\"), true) +\r\n          '<\/div>' + showComment(\"arrivee\") + '<\/div>';\r\n      }\r\n      return '<div class=\"card\"><div class=\"h2\">ARRIV\u00c9E<\/div><div class=\"txt\">Cliquez sur une image pour choisir.<\/div><div class=\"grid\">' +\r\n        choice(\"nez\", \"Nez de marche - si\u00e8ge pivotant\", getImg(\"arr_nez\"), state.arrivee === \"nez\") +\r\n        choice(\"prolonge\", \"Prolong\u00e9e\", getImg(\"arr_prol\"), state.arrivee === \"prolonge\") +\r\n        choice(\"p90\", \"Parking 90\u00b0\", getImg(\"arr_90\"), state.arrivee === \"p90\") +\r\n        choice(\"p180\", \"Parking 180\u00b0\", getImg(\"arr_180\"), state.arrivee === \"p180\") +\r\n        '<\/div>' + showComment(\"arrivee\") + '<\/div>';\r\n    }\r\n\r\n    if (id === \"pivot\") {\r\n      return '<div class=\"card\"><div class=\"h2\">SI\u00c8GE PIVOTANT<\/div><div class=\"txt\">Choisissez manuel ou \u00e9lectrique.<\/div><div class=\"grid\">' +\r\n        choice(\"manuel\", \"Manuel\", getImg(\"pivot_manuel\"), state.pivotMode === \"manuel\") +\r\n        choice(\"electrique\", \"\u00c9lectrique\", getImg(\"pivot_elec\"), state.pivotMode === \"electrique\") +\r\n        '<\/div>' + showComment(\"pivot\") + '<\/div>';\r\n    }\r\n\r\n    if (id === \"recap\") {\r\n      var lines = recapMaterial();\r\n      return '<div class=\"card\"><div class=\"h2\">R\u00c9CAPITULATIF UNIQUEMENT MAT\u00c9RIEL<\/div><div class=\"recap\"><ul>' +\r\n        lines.map(function (x) { return \"<li>\" + escapeHtml(x) + \"<\/li>\"; }).join(\"\") +\r\n        '<\/ul><\/div>' + showComment(\"recap\") + '<\/div>';\r\n    }\r\n\r\n    if (id === \"garanties\") {\r\n      return '<div class=\"card\"><div class=\"h2\">GARANTIES<\/div><div class=\"guaranteePhoto\"><img decoding=\"async\" src=\"' + escapeHtml(getImg(\"garanties_photo\")) + '\" alt=\"Garanties\"><\/div><div class=\"guaranteeBig\">GARANTIE 4 ANS PI\u00c8CES, MAIN D\u2019\u0152UVRE ET D\u00c9PLACEMENT<br><br>2 VISITES TECHNIQUES COMPRISES DANS LE PRIX<\/div>' + showComment(\"garanties\") + '<\/div>';\r\n    }\r\n\r\n    if (id === \"aides\") {\r\n      return '<div class=\"card\"><div class=\"h2\">LES AIDES ET AUTRES POSSIBILIT\u00c9S<\/div><div class=\"guaranteePhoto\"><img decoding=\"async\" src=\"' + escapeHtml(getImg(\"aides_photo\")) + '\" alt=\"Aides et autres possibilit\u00e9s\"><\/div><div class=\"txt\">Certaines aides peuvent \u00eatre \u00e9tudi\u00e9es selon votre situation.<br><br>Des solutions de financement peuvent \u00e9galement \u00eatre envisag\u00e9es.<br><br>Un conseiller pourra vous orienter lors de la visite technique gratuite et sans engagement.<\/div>' + showComment(\"aides\") + '<\/div>';\r\n    }\r\n\r\n    if (id === \"price\") {\r\n      return '<div class=\"card\"><div class=\"h2\">VOTRE PRIX FINAL TTC POS\u00c9<\/div><div class=\"price\"><div class=\"big\">' + money(breakdown.total) + '<\/div><div style=\"font-size:13px;color:rgba(255,255,255,.75);margin-top:6px\">Estimation TTC pos\u00e9e<\/div><\/div><div class=\"txt\" style=\"margin-top:14px\">Ce prix est une estimation. Il sera confirm\u00e9 lors de la visite technique gratuite, sans engagement.<\/div>' + showComment(\"price\") + '<div class=\"nav\" style=\"margin-top:14px\"><a class=\"btn pri\" href=\"' + escapeHtml(cfg.contactUrl) + '\">' + escapeHtml(cfg.contactLabel) + '<\/a><\/div><\/div>';\r\n    }\r\n\r\n    return '<div class=\"card\"><div class=\"txt\">Page inconnue.<\/div><\/div>';\r\n  }\r\n\r\n  function renderBO() {\r\n    if (!adminUnlocked) return \"\";\r\n\r\n    return (\r\n      '<div class=\"boOverlay\" id=\"boOverlay\">' +\r\n        '<div class=\"bo\">' +\r\n          '<div class=\"boHead\"><strong>Back Office complet WordPress<\/strong><button class=\"btn\" data-act=\"closeBo\">Fermer<\/button><\/div>' +\r\n          '<div class=\"boBody\">' +\r\n\r\n            '<fieldset class=\"fs\"><legend>Global<\/legend>' +\r\n              '<label class=\"lbl\">Ligne d\u2019en-t\u00eate<\/label><input class=\"inp\" id=\"boCompanyLine\" value=\"' + escapeHtml(cfg.companyLine) + '\">' +\r\n              '<label class=\"lbl\" style=\"margin-top:10px\">URL bouton contact<\/label><input class=\"inp\" id=\"boContactUrl\" value=\"' + escapeHtml(cfg.contactUrl) + '\">' +\r\n              '<label class=\"lbl\" style=\"margin-top:10px\">Texte bouton contact<\/label><input class=\"inp\" id=\"boContactLabel\" value=\"' + escapeHtml(cfg.contactLabel) + '\">' +\r\n              '<div class=\"hr\"><\/div>' +\r\n              '<label class=\"lbl\">Logo \u2014 URL<\/label><input class=\"inp\" id=\"boLogo\" value=\"' + escapeHtml((cfg.images.logo || {}).url || \"\") + '\">' +\r\n            '<\/fieldset>' +\r\n\r\n            '<fieldset class=\"fs\"><legend>Prix<\/legend>' +\r\n              '<div class=\"row2\"><div><label class=\"lbl\">M\u00e8tres inclus standard<\/label><input class=\"num\" id=\"boIncludedMeters\" type=\"number\" value=\"' + cfg.prices.includedMeters + '\"><\/div><div><\/div><\/div>' +\r\n\r\n              '<div class=\"hr\"><\/div><div class=\"lbl\" style=\"font-weight:700;\">UP droit \/ ext\u00e9rieur<\/div>' +\r\n              '<div class=\"row2\"><div><label class=\"lbl\">Base<\/label><input class=\"num\" id=\"boUpDroitBase\" type=\"number\" value=\"' + cfg.prices.up.droit.base + '\"><\/div><div><label class=\"lbl\">Main d\u2019\u0153uvre<\/label><input class=\"num\" id=\"boUpDroitMo\" type=\"number\" value=\"' + cfg.prices.up.droit.mo + '\"><\/div><\/div>' +\r\n              '<div class=\"row2\" style=\"margin-top:10px\"><div><label class=\"lbl\">Rail sup \/ m<\/label><input class=\"num\" id=\"boUpDroitRailSup\" type=\"number\" value=\"' + cfg.prices.up.droit.railSup + '\"><\/div><div><label class=\"lbl\">Rail relevable<\/label><input class=\"num\" id=\"boUpDroitRailRel\" type=\"number\" value=\"' + cfg.prices.up.droit.railRelevable + '\"><\/div><\/div>' +\r\n              '<div class=\"row2\" style=\"margin-top:10px\"><div><label class=\"lbl\">Plus-value ext\u00e9rieur<\/label><input class=\"num\" id=\"boUpDroitExtPlus\" type=\"number\" value=\"' + cfg.prices.up.droit.extPlus + '\"><\/div><div><label class=\"lbl\">Pivot \u00e9lectrique<\/label><input class=\"num\" id=\"boUpDroitPivot\" type=\"number\" value=\"' + cfg.prices.up.droit.pivotElec + '\"><\/div><\/div>' +\r\n\r\n              '<div class=\"hr\"><\/div><div class=\"lbl\" style=\"font-weight:700;\">UP courbe<\/div>' +\r\n              '<div class=\"row2\"><div><label class=\"lbl\">Base<\/label><input class=\"num\" id=\"boUpCourbeBase\" type=\"number\" value=\"' + cfg.prices.up.courbe.base + '\"><\/div><div><label class=\"lbl\">Main d\u2019\u0153uvre<\/label><input class=\"num\" id=\"boUpCourbeMo\" type=\"number\" value=\"' + cfg.prices.up.courbe.mo + '\"><\/div><\/div>' +\r\n              '<div class=\"row2\" style=\"margin-top:10px\"><div><label class=\"lbl\">Rail sup \/ m<\/label><input class=\"num\" id=\"boUpCourbeRailSup\" type=\"number\" value=\"' + cfg.prices.up.courbe.railSup + '\"><\/div><div><label class=\"lbl\">Valeur par courbe<\/label><input class=\"num\" id=\"boUpCourbeCourbe\" type=\"number\" value=\"' + cfg.prices.up.courbe.courbe + '\"><\/div><\/div>' +\r\n              '<div class=\"row2\" style=\"margin-top:10px\"><div><label class=\"lbl\">Rail relevable<\/label><input class=\"num\" id=\"boUpCourbeRailRel\" type=\"number\" value=\"' + cfg.prices.up.courbe.railRelevable + '\"><\/div><div><label class=\"lbl\">Pivot \u00e9lectrique<\/label><input class=\"num\" id=\"boUpCourbePivot\" type=\"number\" value=\"' + cfg.prices.up.courbe.pivotElec + '\"><\/div><\/div>' +\r\n\r\n              '<div class=\"hr\"><\/div><div class=\"lbl\" style=\"font-weight:700;\">ACORN droit \/ ext\u00e9rieur<\/div>' +\r\n              '<div class=\"row2\"><div><label class=\"lbl\">Base<\/label><input class=\"num\" id=\"boAcornDroitBase\" type=\"number\" value=\"' + cfg.prices.acorn.droit.base + '\"><\/div><div><label class=\"lbl\">Main d\u2019\u0153uvre<\/label><input class=\"num\" id=\"boAcornDroitMo\" type=\"number\" value=\"' + cfg.prices.acorn.droit.mo + '\"><\/div><\/div>' +\r\n              '<div class=\"row2\" style=\"margin-top:10px\"><div><label class=\"lbl\">Rail sup \/ m<\/label><input class=\"num\" id=\"boAcornDroitRailSup\" type=\"number\" value=\"' + cfg.prices.acorn.droit.railSup + '\"><\/div><div><label class=\"lbl\">Rail relevable<\/label><input class=\"num\" id=\"boAcornDroitRailRel\" type=\"number\" value=\"' + cfg.prices.acorn.droit.railRelevable + '\"><\/div><\/div>' +\r\n              '<div class=\"row2\" style=\"margin-top:10px\"><div><label class=\"lbl\">Plus-value ext\u00e9rieur<\/label><input class=\"num\" id=\"boAcornDroitExtPlus\" type=\"number\" value=\"' + cfg.prices.acorn.droit.extPlus + '\"><\/div><div><label class=\"lbl\">Pivot \u00e9lectrique<\/label><input class=\"num\" id=\"boAcornDroitPivot\" type=\"number\" value=\"' + cfg.prices.acorn.droit.pivotElec + '\"><\/div><\/div>' +\r\n\r\n              '<div class=\"hr\"><\/div><div class=\"lbl\" style=\"font-weight:700;\">ACORN courbe<\/div>' +\r\n              '<div class=\"row2\"><div><label class=\"lbl\">Base<\/label><input class=\"num\" id=\"boAcornCourbeBase\" type=\"number\" value=\"' + cfg.prices.acorn.courbe.base + '\"><\/div><div><label class=\"lbl\">Main d\u2019\u0153uvre<\/label><input class=\"num\" id=\"boAcornCourbeMo\" type=\"number\" value=\"' + cfg.prices.acorn.courbe.mo + '\"><\/div><\/div>' +\r\n              '<div class=\"row2\" style=\"margin-top:10px\"><div><label class=\"lbl\">Rail sup \/ m<\/label><input class=\"num\" id=\"boAcornCourbeRailSup\" type=\"number\" value=\"' + cfg.prices.acorn.courbe.railSup + '\"><\/div><div><label class=\"lbl\">Valeur par courbe<\/label><input class=\"num\" id=\"boAcornCourbeCourbe\" type=\"number\" value=\"' + cfg.prices.acorn.courbe.courbe + '\"><\/div><\/div>' +\r\n              '<div class=\"row2\" style=\"margin-top:10px\"><div><label class=\"lbl\">Rail relevable<\/label><input class=\"num\" id=\"boAcornCourbeRailRel\" type=\"number\" value=\"' + cfg.prices.acorn.courbe.railRelevable + '\"><\/div><div><label class=\"lbl\">Pivot \u00e9lectrique<\/label><input class=\"num\" id=\"boAcornCourbePivot\" type=\"number\" value=\"' + cfg.prices.acorn.courbe.pivotElec + '\"><\/div><\/div>' +\r\n            '<\/fieldset>' +\r\n\r\n            '<fieldset class=\"fs\"><legend>Commentaires<\/legend>' +\r\n              '<label class=\"lbl\">Accueil<\/label><textarea class=\"ta\" id=\"boHome\">' + escapeHtml(cfg.comments.home) + '<\/textarea>' +\r\n              '<label class=\"lbl\" style=\"margin-top:10px\">Type<\/label><textarea class=\"ta\" id=\"boType\">' + escapeHtml(cfg.comments.type) + '<\/textarea>' +\r\n              '<label class=\"lbl\" style=\"margin-top:10px\">Marque<\/label><textarea class=\"ta\" id=\"boBrand\">' + escapeHtml(cfg.comments.brand) + '<\/textarea>' +\r\n              '<label class=\"lbl\" style=\"margin-top:10px\">D\u00e9part<\/label><textarea class=\"ta\" id=\"boDepart\">' + escapeHtml(cfg.comments.depart) + '<\/textarea>' +\r\n              '<label class=\"lbl\" style=\"margin-top:10px\">Obstacle<\/label><textarea class=\"ta\" id=\"boObstacle\">' + escapeHtml(cfg.comments.obstacle) + '<\/textarea>' +\r\n              '<label class=\"lbl\" style=\"margin-top:10px\">Rail<\/label><textarea class=\"ta\" id=\"boRail\">' + escapeHtml(cfg.comments.rail) + '<\/textarea>' +\r\n              '<label class=\"lbl\" style=\"margin-top:10px\">Longueur<\/label><textarea class=\"ta\" id=\"boLongueur\">' + escapeHtml(cfg.comments.longueur) + '<\/textarea>' +\r\n              '<label class=\"lbl\" style=\"margin-top:10px\">Arriv\u00e9e<\/label><textarea class=\"ta\" id=\"boArrivee\">' + escapeHtml(cfg.comments.arrivee) + '<\/textarea>' +\r\n              '<label class=\"lbl\" style=\"margin-top:10px\">Pivot<\/label><textarea class=\"ta\" id=\"boPivot\">' + escapeHtml(cfg.comments.pivot) + '<\/textarea>' +\r\n              '<label class=\"lbl\" style=\"margin-top:10px\">R\u00e9capitulatif<\/label><textarea class=\"ta\" id=\"boRecap\">' + escapeHtml(cfg.comments.recap) + '<\/textarea>' +\r\n              '<label class=\"lbl\" style=\"margin-top:10px\">Garanties<\/label><textarea class=\"ta\" id=\"boGaranties\">' + escapeHtml(cfg.comments.garanties) + '<\/textarea>' +\r\n              '<label class=\"lbl\" style=\"margin-top:10px\">Aides<\/label><textarea class=\"ta\" id=\"boAides\">' + escapeHtml(cfg.comments.aides) + '<\/textarea>' +\r\n              '<label class=\"lbl\" style=\"margin-top:10px\">Prix final<\/label><textarea class=\"ta\" id=\"boPrice\">' + escapeHtml(cfg.comments.price) + '<\/textarea>' +\r\n            '<\/fieldset>' +\r\n\r\n            '<fieldset class=\"fs\"><legend>URLs images<\/legend>' +\r\n              renderImageField(\"type_droit\", \"Type droit\") +\r\n              renderImageField(\"type_90\", \"Type courbe 90\u00b0\") +\r\n              renderImageField(\"type_180\", \"Type courbe 180\u00b0\") +\r\n              renderImageField(\"type_ext\", \"Type ext\u00e9rieur\") +\r\n              renderImageField(\"marque_up\", \"Marque UP\") +\r\n              renderImageField(\"marque_acorn\", \"Marque ACORN\") +\r\n              renderImageField(\"depart_std\", \"D\u00e9part standard\") +\r\n              renderImageField(\"depart_rall\", \"D\u00e9part rallong\u00e9\") +\r\n              renderImageField(\"depart_p90\", \"D\u00e9part parking 90\u00b0\") +\r\n              renderImageField(\"depart_p180\", \"D\u00e9part parking 180\u00b0\") +\r\n              renderImageField(\"obstacle_ex1\", \"Obstacle exemple 1\") +\r\n              renderImageField(\"obstacle_ex2\", \"Obstacle exemple 2\") +\r\n              renderImageField(\"obstacle_yes\", \"Obstacle oui\") +\r\n              renderImageField(\"obstacle_no\", \"Obstacle non\") +\r\n              renderImageField(\"rail_1\", \"Rail exemple 1\") +\r\n              renderImageField(\"rail_2\", \"Rail exemple 2\") +\r\n              renderImageField(\"rail_yes\", \"Rail oui cliquable\") +\r\n              renderImageField(\"rail_no\", \"Rail non cliquable\") +\r\n              renderImageField(\"arr_nez\", \"Arriv\u00e9e nez\") +\r\n              renderImageField(\"arr_prol\", \"Arriv\u00e9e prolong\u00e9e\") +\r\n              renderImageField(\"arr_90\", \"Arriv\u00e9e 90\u00b0\") +\r\n              renderImageField(\"arr_180\", \"Arriv\u00e9e 180\u00b0\") +\r\n              renderImageField(\"pivot_manuel\", \"Pivot manuel\") +\r\n              renderImageField(\"pivot_elec\", \"Pivot \u00e9lectrique\") +\r\n              renderImageField(\"garanties_photo\", \"Garanties image\") +\r\n              renderImageField(\"aides_photo\", \"Aides image\") +\r\n            '<\/fieldset>' +\r\n\r\n          '<\/div>' +\r\n          '<div class=\"boActions\">' +\r\n            '<button class=\"btn\" data-act=\"closeBo\">Fermer<\/button>' +\r\n            '<button class=\"btn pri\" data-act=\"saveBo\">Enregistrer<\/button>' +\r\n          '<\/div>' +\r\n        '<\/div>' +\r\n      '<\/div>'\r\n    );\r\n  }\r\n\r\n  function saveBOToCfg() {\r\n    cfg.companyLine = app.querySelector(\"#boCompanyLine\").value;\r\n    cfg.contactUrl = app.querySelector(\"#boContactUrl\").value;\r\n    cfg.contactLabel = app.querySelector(\"#boContactLabel\").value;\r\n\r\n    cfg.prices.includedMeters = Number(app.querySelector(\"#boIncludedMeters\").value || 5);\r\n\r\n    cfg.prices.up.droit.base = Number(app.querySelector(\"#boUpDroitBase\").value || 0);\r\n    cfg.prices.up.droit.mo = Number(app.querySelector(\"#boUpDroitMo\").value || 0);\r\n    cfg.prices.up.droit.railSup = Number(app.querySelector(\"#boUpDroitRailSup\").value || 0);\r\n    cfg.prices.up.droit.railRelevable = Number(app.querySelector(\"#boUpDroitRailRel\").value || 0);\r\n    cfg.prices.up.droit.extPlus = Number(app.querySelector(\"#boUpDroitExtPlus\").value || 0);\r\n    cfg.prices.up.droit.pivotElec = Number(app.querySelector(\"#boUpDroitPivot\").value || 0);\r\n\r\n    cfg.prices.up.courbe.base = Number(app.querySelector(\"#boUpCourbeBase\").value || 0);\r\n    cfg.prices.up.courbe.mo = Number(app.querySelector(\"#boUpCourbeMo\").value || 0);\r\n    cfg.prices.up.courbe.railSup = Number(app.querySelector(\"#boUpCourbeRailSup\").value || 0);\r\n    cfg.prices.up.courbe.courbe = Number(app.querySelector(\"#boUpCourbeCourbe\").value || 0);\r\n    cfg.prices.up.courbe.railRelevable = Number(app.querySelector(\"#boUpCourbeRailRel\").value || 0);\r\n    cfg.prices.up.courbe.pivotElec = Number(app.querySelector(\"#boUpCourbePivot\").value || 0);\r\n\r\n    cfg.prices.acorn.droit.base = Number(app.querySelector(\"#boAcornDroitBase\").value || 0);\r\n    cfg.prices.acorn.droit.mo = Number(app.querySelector(\"#boAcornDroitMo\").value || 0);\r\n    cfg.prices.acorn.droit.railSup = Number(app.querySelector(\"#boAcornDroitRailSup\").value || 0);\r\n    cfg.prices.acorn.droit.railRelevable = Number(app.querySelector(\"#boAcornDroitRailRel\").value || 0);\r\n    cfg.prices.acorn.droit.extPlus = Number(app.querySelector(\"#boAcornDroitExtPlus\").value || 0);\r\n    cfg.prices.acorn.droit.pivotElec = Number(app.querySelector(\"#boAcornDroitPivot\").value || 0);\r\n\r\n    cfg.prices.acorn.courbe.base = Number(app.querySelector(\"#boAcornCourbeBase\").value || 0);\r\n    cfg.prices.acorn.courbe.mo = Number(app.querySelector(\"#boAcornCourbeMo\").value || 0);\r\n    cfg.prices.acorn.courbe.railSup = Number(app.querySelector(\"#boAcornCourbeRailSup\").value || 0);\r\n    cfg.prices.acorn.courbe.courbe = Number(app.querySelector(\"#boAcornCourbeCourbe\").value || 0);\r\n    cfg.prices.acorn.courbe.railRelevable = Number(app.querySelector(\"#boAcornCourbeRailRel\").value || 0);\r\n    cfg.prices.acorn.courbe.pivotElec = Number(app.querySelector(\"#boAcornCourbePivot\").value || 0);\r\n\r\n    cfg.comments.home = app.querySelector(\"#boHome\").value;\r\n    cfg.comments.type = app.querySelector(\"#boType\").value;\r\n    cfg.comments.brand = app.querySelector(\"#boBrand\").value;\r\n    cfg.comments.depart = app.querySelector(\"#boDepart\").value;\r\n    cfg.comments.obstacle = app.querySelector(\"#boObstacle\").value;\r\n    cfg.comments.rail = app.querySelector(\"#boRail\").value;\r\n    cfg.comments.longueur = app.querySelector(\"#boLongueur\").value;\r\n    cfg.comments.arrivee = app.querySelector(\"#boArrivee\").value;\r\n    cfg.comments.pivot = app.querySelector(\"#boPivot\").value;\r\n    cfg.comments.recap = app.querySelector(\"#boRecap\").value;\r\n    cfg.comments.garanties = app.querySelector(\"#boGaranties\").value;\r\n    cfg.comments.aides = app.querySelector(\"#boAides\").value;\r\n    cfg.comments.price = app.querySelector(\"#boPrice\").value;\r\n\r\n    setImageUrl(\"logo\", app.querySelector(\"#boLogo\").value);\r\n    setImageUrl(\"type_droit\", app.querySelector(\"#img_type_droit\").value);\r\n    setImageUrl(\"type_90\", app.querySelector(\"#img_type_90\").value);\r\n    setImageUrl(\"type_180\", app.querySelector(\"#img_type_180\").value);\r\n    setImageUrl(\"type_ext\", app.querySelector(\"#img_type_ext\").value);\r\n    setImageUrl(\"marque_up\", app.querySelector(\"#img_marque_up\").value);\r\n    setImageUrl(\"marque_acorn\", app.querySelector(\"#img_marque_acorn\").value);\r\n    setImageUrl(\"depart_std\", app.querySelector(\"#img_depart_std\").value);\r\n    setImageUrl(\"depart_rall\", app.querySelector(\"#img_depart_rall\").value);\r\n    setImageUrl(\"depart_p90\", app.querySelector(\"#img_depart_p90\").value);\r\n    setImageUrl(\"depart_p180\", app.querySelector(\"#img_depart_p180\").value);\r\n    setImageUrl(\"obstacle_ex1\", app.querySelector(\"#img_obstacle_ex1\").value);\r\n    setImageUrl(\"obstacle_ex2\", app.querySelector(\"#img_obstacle_ex2\").value);\r\n    setImageUrl(\"obstacle_yes\", app.querySelector(\"#img_obstacle_yes\").value);\r\n    setImageUrl(\"obstacle_no\", app.querySelector(\"#img_obstacle_no\").value);\r\n    setImageUrl(\"rail_1\", app.querySelector(\"#img_rail_1\").value);\r\n    setImageUrl(\"rail_2\", app.querySelector(\"#img_rail_2\").value);\r\n    setImageUrl(\"rail_yes\", app.querySelector(\"#img_rail_yes\").value);\r\n    setImageUrl(\"rail_no\", app.querySelector(\"#img_rail_no\").value);\r\n    setImageUrl(\"arr_nez\", app.querySelector(\"#img_arr_nez\").value);\r\n    setImageUrl(\"arr_prol\", app.querySelector(\"#img_arr_prol\").value);\r\n    setImageUrl(\"arr_90\", app.querySelector(\"#img_arr_90\").value);\r\n    setImageUrl(\"arr_180\", app.querySelector(\"#img_arr_180\").value);\r\n    setImageUrl(\"pivot_manuel\", app.querySelector(\"#img_pivot_manuel\").value);\r\n    setImageUrl(\"pivot_elec\", app.querySelector(\"#img_pivot_elec\").value);\r\n    setImageUrl(\"garanties_photo\", app.querySelector(\"#img_garanties_photo\").value);\r\n    setImageUrl(\"aides_photo\", app.querySelector(\"#img_aides_photo\").value);\r\n  }\r\n\r\n  function render() {\r\n    normalizeState();\r\n    var ids = steps();\r\n    if (state.step > ids.length - 1) state.step = ids.length - 1;\r\n    var current = ids[state.step];\r\n    var progress = Math.round(((state.step + 1) \/ ids.length) * 100);\r\n\r\n    app.innerHTML =\r\n      '<div class=\"top\">' +\r\n        '<div class=\"brand\">' +\r\n          '<div class=\"logo\"><img decoding=\"async\" src=\"' + escapeHtml(getImg(\"logo\")) + '\" alt=\"Logo\"><\/div>' +\r\n          '<div><div class=\"small\">' + escapeHtml(cfg.companyLine) + '<\/div><\/div>' +\r\n        '<\/div>' +\r\n        '<div class=\"progress\"><div class=\"pill\">' + (state.step + 1) + ' \/ ' + ids.length + '<\/div><div class=\"bar\"><i style=\"width:' + progress + '%\"><\/i><\/div><\/div>' +\r\n      '<\/div>' +\r\n\r\n      '<div class=\"alertBand ' + (state.showAlert ? 'show' : '') + '\">' + escapeHtml(state.msg || 'MERCI DE FAIRE UN CHOIX AVANT DE CONTINUER') + '<\/div>' +\r\n\r\n      renderPage() +\r\n\r\n      '<div class=\"nav\">' +\r\n        '<button class=\"btn reset\" data-act=\"reset\">R\u00c9INITIALISER<\/button>' +\r\n        '<button class=\"btn\" data-act=\"prev\" ' + (state.step === 0 ? 'disabled' : '') + '>RETOUR<\/button>' +\r\n        '<button class=\"btn pri\" data-act=\"next\">' + (current === 'price' ? 'TERMINER' : 'SUIVANT') + '<\/button>' +\r\n      '<\/div>' +\r\n\r\n      renderBO() +\r\n      renderCommentModal();\r\n\r\n    app.querySelectorAll(\".choice[data-choice]\").forEach(function (el) {\r\n      el.addEventListener(\"click\", function () {\r\n        var k = el.getAttribute(\"data-choice\");\r\n\r\n        if (current === \"type\") {\r\n          state.type = k;\r\n          state.depart = \"\";\r\n          state.obstacle = \"\";\r\n          state.railChoice = \"\";\r\n          state.arrivee = \"\";\r\n          state.pivotMode = \"\";\r\n        }\r\n\r\n        if (current === \"brand\") {\r\n          state.brand = k;\r\n          state.depart = \"\";\r\n          state.obstacle = \"\";\r\n          state.railChoice = \"\";\r\n          state.arrivee = \"\";\r\n          state.pivotMode = \"\";\r\n        }\r\n\r\n        if (current === \"depart\") {\r\n          state.depart = k;\r\n          state.obstacle = \"\";\r\n          state.railChoice = \"\";\r\n        }\r\n\r\n        if (current === \"obstacle\") {\r\n          state.obstacle = k;\r\n          state.railChoice = \"\";\r\n        }\r\n\r\n        if (current === \"rail\") {\r\n          state.railChoice = (k === \"rail_oui\") ? \"oui\" : \"non\";\r\n        }\r\n\r\n        if (current === \"arrivee\") {\r\n          state.arrivee = k;\r\n          state.pivotMode = \"\";\r\n        }\r\n\r\n        if (current === \"pivot\") {\r\n          state.pivotMode = k;\r\n        }\r\n\r\n        state.msg = \"\";\r\n        state.showAlert = false;\r\n        render();\r\n      });\r\n    });\r\n\r\n    app.querySelectorAll('[data-act=\"reset\"]').forEach(function (btn) {\r\n      btn.addEventListener(\"click\", function () {\r\n        if (window.confirm(\"Voulez-vous vraiment r\u00e9initialiser le configurateur ?\")) {\r\n          state = {\r\n            step: 0,\r\n            msg: \"\",\r\n            showAlert: false,\r\n            type: \"\",\r\n            brand: \"\",\r\n            depart: \"\",\r\n            obstacle: \"\",\r\n            railChoice: \"\",\r\n            nbMarches: 17,\r\n            longueur: 5.1,\r\n            arrivee: \"\",\r\n            pivotMode: \"\"\r\n          };\r\n          closeCommentModal();\r\n          render();\r\n        }\r\n      });\r\n    });\r\n\r\n    app.querySelectorAll('[data-act=\"next\"]').forEach(function (btn) {\r\n      btn.addEventListener(\"click\", function () {\r\n        var currentStep = steps()[state.step];\r\n        var err = validate(currentStep);\r\n        if (err) {\r\n          state.msg = err;\r\n          state.showAlert = true;\r\n          render();\r\n          return;\r\n        }\r\n        if (state.step < steps().length - 1) {\r\n          closeCommentModal();\r\n          state.step++;\r\n          state.msg = \"\";\r\n          state.showAlert = false;\r\n          render();\r\n        }\r\n      });\r\n    });\r\n\r\n    app.querySelectorAll('[data-act=\"prev\"]').forEach(function (btn) {\r\n      btn.addEventListener(\"click\", function () {\r\n        if (state.step > 0) {\r\n          closeCommentModal();\r\n          state.step--;\r\n          state.msg = \"\";\r\n          state.showAlert = false;\r\n          render();\r\n        }\r\n      });\r\n    });\r\n\r\n    app.querySelectorAll('[data-act=\"minusMarches\"]').forEach(function (btn) {\r\n      btn.addEventListener(\"click\", function () {\r\n        state.nbMarches = Math.max(1, Number(state.nbMarches || 1) - 1);\r\n        syncLongueur();\r\n        render();\r\n      });\r\n    });\r\n\r\n    app.querySelectorAll('[data-act=\"plusMarches\"]').forEach(function (btn) {\r\n      btn.addEventListener(\"click\", function () {\r\n        state.nbMarches = Math.min(30, Number(state.nbMarches || 1) + 1);\r\n        syncLongueur();\r\n        render();\r\n      });\r\n    });\r\n\r\n    app.querySelectorAll('[data-act=\"rangeMarches\"]').forEach(function (r) {\r\n      r.addEventListener(\"input\", function () {\r\n        state.nbMarches = Number(r.value);\r\n        syncLongueur();\r\n        render();\r\n      });\r\n    });\r\n\r\n    app.querySelectorAll(\"[data-comment-open]\").forEach(function (btn) {\r\n      btn.addEventListener(\"click\", function () {\r\n        var key = btn.getAttribute(\"data-comment-open\");\r\n        openCommentModal(key);\r\n      });\r\n    });\r\n\r\n    app.querySelectorAll(\"[data-comment-close]\").forEach(function (btn) {\r\n      btn.addEventListener(\"click\", function () {\r\n        closeCommentModal();\r\n      });\r\n    });\r\n\r\n    var modalOverlay = document.getElementById(\"commentModalOverlay\");\r\n    if (modalOverlay) {\r\n      modalOverlay.addEventListener(\"click\", function (e) {\r\n        if (e.target === modalOverlay) {\r\n          closeCommentModal();\r\n        }\r\n      });\r\n    }\r\n\r\n    app.querySelectorAll('[data-act=\"closeBo\"]').forEach(function (btn) {\r\n      btn.addEventListener(\"click\", function () {\r\n        var bo = document.getElementById(\"boOverlay\");\r\n        if (bo) bo.classList.remove(\"show\");\r\n      });\r\n    });\r\n\r\n    app.querySelectorAll('[data-act=\"saveBo\"]').forEach(function (btn) {\r\n      btn.addEventListener(\"click\", async function () {\r\n        saveBOToCfg();\r\n        var ok = await wpSaveConfig();\r\n        if (!ok) return;\r\n        var bo = document.getElementById(\"boOverlay\");\r\n        if (bo) bo.classList.remove(\"show\");\r\n        render();\r\n        alert(\"Configuration enregistr\u00e9e dans WordPress.\");\r\n      });\r\n    });\r\n  }\r\n\r\n  var styleNode = document.createElement(\"style\");\r\n  styleNode.textContent = `\r\n:root{\r\n  --bg:#071327;\r\n  --bg2:#050C19;\r\n  --card:rgba(255,255,255,.06);\r\n  --bd:rgba(255,255,255,.14);\r\n  --txt:#fff;\r\n  --muted:rgba(255,255,255,.78);\r\n  --orange:#F97316;\r\n  --orange2:#EA580C;\r\n  --danger1:#DC2626;\r\n  --danger2:#F97316;\r\n}\r\nbody.jlmNoScroll{overflow:hidden}\r\n#jlmLiteAppRoot *{box-sizing:border-box}\r\n#jlmLiteAppRoot{\r\n  font-family:Arial,Helvetica,sans-serif;\r\n  color:var(--txt);\r\n  background:\r\n    radial-gradient(1200px 560px at 15% 0%, rgba(249,115,22,.18), transparent 60%),\r\n    radial-gradient(1000px 700px at 85% 10%, rgba(59,130,246,.12), transparent 60%),\r\n    linear-gradient(180deg, var(--bg), var(--bg2) 58%, #040A14);\r\n  border-radius:20px;\r\n  padding:14px 10px 18px;\r\n  overflow:hidden;\r\n}\r\n#jlmLiteAppRoot .app{width:100%;max-width:1120px;margin:0 auto}\r\n#jlmLiteAppRoot .top{display:flex;align-items:center;justify-content:space-between;gap:6px;padding:0 2px 2px;margin-bottom:4px}\r\n#jlmLiteAppRoot .brand{display:flex;align-items:center;gap:8px;min-width:0}\r\n#jlmLiteAppRoot .logo{width:138px;height:138px;border-radius:18px;border:1px solid rgba(255,255,255,.14);background:rgba(255,255,255,.05);display:flex;align-items:center;justify-content:center;overflow:hidden;flex:0 0 auto}\r\n#jlmLiteAppRoot .logo img{width:100%;height:100%;object-fit:contain;display:block}\r\n#jlmLiteAppRoot .small{font-size:9px;color:var(--muted);line-height:1.05;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\r\n#jlmLiteAppRoot .progress{display:flex;align-items:center;gap:5px;min-width:120px;flex:0 1 220px}\r\n#jlmLiteAppRoot .pill{font-size:9px;padding:3px 6px;border-radius:999px;border:1px solid rgba(255,255,255,.10);background:rgba(255,255,255,.04)}\r\n#jlmLiteAppRoot .bar{height:5px;flex:1;border-radius:999px;border:1px solid rgba(255,255,255,.10);background:rgba(255,255,255,.04);overflow:hidden}\r\n#jlmLiteAppRoot .bar i{display:block;height:100%;width:0%;background:linear-gradient(90deg,var(--orange),#FDBA74)}\r\n#jlmLiteAppRoot .alertBand{display:none;width:100%;margin:0 0 10px;padding:14px 18px;border-radius:18px;background:linear-gradient(90deg,var(--danger1),var(--danger2));color:#fff;font-size:18px;font-weight:800;text-align:center;box-shadow:0 18px 40px rgba(0,0,0,.24)}\r\n#jlmLiteAppRoot .alertBand.show{display:block}\r\n#jlmLiteAppRoot .card{background:linear-gradient(180deg, rgba(255,255,255,.06), rgba(255,255,255,.035));border:1px solid var(--bd);border-radius:24px;padding:18px 16px;box-shadow:0 20px 50px rgba(0,0,0,.28)}\r\n#jlmLiteAppRoot .h1,#jlmLiteAppRoot .h2{text-align:center;margin:2px 0 10px}\r\n#jlmLiteAppRoot .h1{font-size:34px}\r\n#jlmLiteAppRoot .h2{font-size:25px}\r\n#jlmLiteAppRoot .txt{max-width:980px;margin:0 auto;text-align:center;line-height:1.7;font-size:16px;color:rgba(255,255,255,.94)}\r\n#jlmLiteAppRoot .grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;margin-top:14px}\r\n#jlmLiteAppRoot .choice,#jlmLiteAppRoot .fixedCard{border-radius:22px;border:1px solid rgba(255,255,255,.12);background:linear-gradient(180deg, rgba(255,255,255,.06), rgba(255,255,255,.035));overflow:hidden;box-shadow:0 10px 24px rgba(0,0,0,.14)}\r\n#jlmLiteAppRoot .choice{cursor:pointer;transition:transform .18s ease,border-color .18s ease,box-shadow .18s ease;position:relative}\r\n#jlmLiteAppRoot .choice:hover{transform:translateY(-4px);border-color:rgba(249,115,22,.55);box-shadow:0 16px 34px rgba(0,0,0,.22)}\r\n#jlmLiteAppRoot .choice.sel{border-color:rgba(249,115,22,.92);box-shadow:0 0 0 2px rgba(249,115,22,.22) inset,0 16px 34px rgba(0,0,0,.22)}\r\n#jlmLiteAppRoot .choice.sel:after{content:\"\u2713\";position:absolute;top:10px;right:12px;width:34px;height:34px;border-radius:999px;display:flex;align-items:center;justify-content:center;background:linear-gradient(180deg,var(--orange),var(--orange2));color:#fff;font-weight:900;font-size:18px}\r\n#jlmLiteAppRoot .media{aspect-ratio:1\/1;background:rgba(255,255,255,.03);display:flex;align-items:center;justify-content:center}\r\n#jlmLiteAppRoot .media img{width:100%;height:100%;object-fit:contain;display:block;background:rgba(255,255,255,.03)}\r\n#jlmLiteAppRoot .label{padding:12px 12px 14px;text-align:center;font-size:15px;font-weight:700}\r\n#jlmLiteAppRoot .measure{max-width:980px;margin:10px auto 0;text-align:center}\r\n#jlmLiteAppRoot .measureRow{display:flex;align-items:center;justify-content:center;gap:10px;flex-wrap:wrap;margin-top:12px}\r\n#jlmLiteAppRoot .measureSub{font-size:28px;font-weight:800;margin-top:10px;color:rgba(255,255,255,.94)}\r\n#jlmLiteAppRoot .arr{width:58px;height:46px;border-radius:16px;border:1px solid rgba(255,255,255,.16);background:rgba(255,255,255,.06);color:#fff;font-size:22px;cursor:pointer}\r\n#jlmLiteAppRoot .range{width:min(680px,92vw);accent-color:var(--orange)}\r\n#jlmLiteAppRoot .bigVal{font-size:32px;font-weight:800;margin-top:6px}\r\n#jlmLiteAppRoot .recap{max-width:980px;margin:16px auto 0;border-radius:20px;background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.16);padding:16px;text-align:center}\r\n#jlmLiteAppRoot .recap ul{display:inline-block;text-align:left;line-height:1.7;margin:0;padding-left:18px}\r\n#jlmLiteAppRoot .guaranteePhoto{max-width:980px;margin:10px auto 0;border-radius:20px;border:1px solid rgba(255,255,255,.14);overflow:hidden;background:rgba(255,255,255,.05);display:flex;align-items:center;justify-content:center}\r\n#jlmLiteAppRoot .guaranteePhoto img{width:100%;display:block;aspect-ratio:16\/7;object-fit:contain;background:rgba(255,255,255,.03)}\r\n#jlmLiteAppRoot .guaranteeBig{max-width:980px;margin:16px auto 0;text-align:center;font-size:30px;line-height:1.45;font-weight:900}\r\n#jlmLiteAppRoot .price{text-align:center;margin-top:12px}\r\n#jlmLiteAppRoot .price .big{font-size:52px;font-weight:900}\r\n#jlmLiteAppRoot .commentWrap{max-width:980px;margin:18px auto 0;text-align:center}\r\n#jlmLiteAppRoot .commentToggle{\r\n  appearance:none;\r\n  border:1px solid rgba(249,115,22,.48);\r\n  background:linear-gradient(180deg, rgba(249,115,22,.22), rgba(234,88,12,.16)), rgba(255,255,255,.06);\r\n  color:#fff;border-radius:999px;padding:11px 18px;font-size:14px;font-weight:700;cursor:pointer;\r\n  transition:transform .18s ease, box-shadow .18s ease, border-color .18s ease;\r\n  box-shadow:0 10px 30px rgba(0,0,0,.16), inset 0 1px 0 rgba(255,255,255,.08);\r\n}\r\n#jlmLiteAppRoot .commentToggle:hover{\r\n  transform:translateY(-2px);\r\n  border-color:rgba(249,115,22,.72);\r\n  box-shadow:0 14px 34px rgba(0,0,0,.22), 0 0 0 1px rgba(249,115,22,.10) inset;\r\n}\r\n#jlmLiteAppRoot .commentToggleIcon{margin-right:8px;opacity:.95}\r\n#jlmLiteAppRoot .commentModalOverlay{\r\n  position:fixed;inset:0;background:rgba(2, 8, 18, .64);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);\r\n  display:none;align-items:center;justify-content:center;padding:22px;z-index:1000000;\r\n}\r\n#jlmLiteAppRoot .commentModalOverlay.show{display:flex;animation:jlmFadeIn .22s ease}\r\n#jlmLiteAppRoot .commentModal{\r\n  position:relative;width:min(760px, 100%);max-height:min(84vh, 820px);overflow:auto;border-radius:28px;\r\n  border:1px solid rgba(255,255,255,.14);\r\n  background:radial-gradient(900px 320px at 0% 0%, rgba(249,115,22,.16), transparent 55%), radial-gradient(700px 280px at 100% 0%, rgba(59,130,246,.10), transparent 58%), linear-gradient(180deg, rgba(11,18,32,.96), rgba(8,16,29,.98));\r\n  box-shadow:0 30px 80px rgba(0,0,0,.46), 0 0 0 1px rgba(255,255,255,.03) inset;\r\n  animation:jlmPopIn .24s ease;\r\n}\r\n#jlmLiteAppRoot .commentModalGlow{\r\n  position:absolute;inset:auto -20% -35% -20%;height:200px;background:radial-gradient(circle, rgba(249,115,22,.12), transparent 65%);pointer-events:none;\r\n}\r\n#jlmLiteAppRoot .commentModalHead{\r\n  position:relative;display:flex;align-items:flex-start;justify-content:space-between;gap:12px;padding:18px 20px 16px;border-bottom:1px solid rgba(255,255,255,.10);\r\n}\r\n#jlmLiteAppRoot .commentModalEyebrow{font-size:11px;letter-spacing:.18em;text-transform:uppercase;color:rgba(255,255,255,.62);margin-bottom:6px}\r\n#jlmLiteAppRoot .commentModalTitle{font-size:28px;font-weight:900;line-height:1.1}\r\n#jlmLiteAppRoot .commentModalX{\r\n  appearance:none;border:1px solid rgba(255,255,255,.14);background:rgba(255,255,255,.06);color:#fff;width:44px;height:44px;border-radius:999px;\r\n  font-size:26px;line-height:1;cursor:pointer;transition:transform .18s ease, background .18s ease, border-color .18s ease;flex:0 0 auto;\r\n}\r\n#jlmLiteAppRoot .commentModalX:hover{transform:scale(1.04);background:rgba(255,255,255,.10);border-color:rgba(255,255,255,.24)}\r\n#jlmLiteAppRoot .commentModalBody{position:relative;padding:24px 22px 12px;color:#fff;text-align:center;font-weight:700;line-height:1.9;font-size:18px}\r\n#jlmLiteAppRoot .commentModalActions{padding:0 22px 22px;display:flex;justify-content:center}\r\n@keyframes jlmFadeIn{from{opacity:0}to{opacity:1}}\r\n@keyframes jlmPopIn{from{opacity:0;transform:translateY(14px) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}\r\n#jlmLiteAppRoot .nav{display:flex;gap:12px;justify-content:center;align-items:center;flex-wrap:wrap;margin-top:18px}\r\n#jlmLiteAppRoot .btn{appearance:none;border:1px solid rgba(255,255,255,.16);background:rgba(255,255,255,.06);color:#fff;border-radius:999px;padding:12px 18px;font-size:14px;font-weight:700;cursor:pointer;min-width:150px;text-decoration:none}\r\n#jlmLiteAppRoot .btn.pri{background:linear-gradient(180deg,var(--orange),var(--orange2));border-color:rgba(249,115,22,.65)}\r\n#jlmLiteAppRoot .btn.reset{margin-right:26px;background:rgba(255,255,255,.04)}\r\n#jlmLiteAppRoot .boOverlay{position:fixed;inset:0;background:rgba(0,0,0,.62);display:none;z-index:999999}\r\n#jlmLiteAppRoot .boOverlay.show{display:block}\r\n#jlmLiteAppRoot .bo{position:absolute;inset:5%;background:#0B1220;border:1px solid rgba(255,255,255,.14);border-radius:22px;overflow:hidden;display:flex;flex-direction:column;box-shadow:0 24px 60px rgba(0,0,0,.35)}\r\n#jlmLiteAppRoot .boHead{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:12px 14px;border-bottom:1px solid rgba(255,255,255,.10);background:rgba(255,255,255,.04)}\r\n#jlmLiteAppRoot .boBody{overflow:auto;padding:14px}\r\n#jlmLiteAppRoot .fs{border:1px solid rgba(255,255,255,.14);border-radius:18px;padding:12px;margin-bottom:12px;background:rgba(255,255,255,.03)}\r\n#jlmLiteAppRoot .fs legend{padding:0 8px;color:rgba(255,255,255,.86);font-size:13px;font-weight:700}\r\n#jlmLiteAppRoot .lbl{display:block;font-size:12px;color:rgba(255,255,255,.78);margin-bottom:6px;text-align:left}\r\n#jlmLiteAppRoot .inp,#jlmLiteAppRoot .ta,#jlmLiteAppRoot .num{width:100%;border-radius:12px;border:1px solid rgba(255,255,255,.16);background:rgba(255,255,255,.06);color:#fff;padding:10px;outline:none}\r\n#jlmLiteAppRoot .ta{min-height:82px;resize:vertical}\r\n#jlmLiteAppRoot .boActions{display:flex;gap:10px;justify-content:flex-end;flex-wrap:wrap;padding:12px 14px;border-top:1px solid rgba(255,255,255,.10);background:rgba(255,255,255,.03)}\r\n#jlmLiteAppRoot .row2{display:grid;grid-template-columns:1fr 1fr;gap:10px}\r\n#jlmLiteAppRoot .hr{height:1px;background:rgba(255,255,255,.10);margin:10px 0}\r\n@media (max-width:700px){\r\n  #jlmLiteAppRoot .row2{grid-template-columns:1fr}\r\n}\r\n@media (max-width:560px){\r\n  #jlmLiteAppRoot .grid{grid-template-columns:1fr}\r\n  #jlmLiteAppRoot .logo{width:108px;height:108px}\r\n  #jlmLiteAppRoot .alertBand{font-size:16px}\r\n  #jlmLiteAppRoot .guaranteeBig{font-size:22px}\r\n  #jlmLiteAppRoot .commentModalTitle{font-size:23px}\r\n  #jlmLiteAppRoot .commentModalBody{font-size:16px;line-height:1.8}\r\n  #jlmLiteAppRoot .commentModalHead{padding:16px}\r\n  #jlmLiteAppRoot .commentModalBody{padding:20px 16px 10px}\r\n  #jlmLiteAppRoot .commentModalActions{padding:0 16px 18px}\r\n}\r\n`;\r\n  root.appendChild(styleNode);\r\n\r\n  app = document.createElement(\"div\");\r\n  app.className = \"app\";\r\n  root.appendChild(app);\r\n\r\n  function hotkey(e) {\r\n    var isA = (e.code === \"KeyA\") || (String(e.key || \"\").toLowerCase() === \"a\");\r\n\r\n    if (e.ctrlKey && e.altKey && isA) {\r\n      e.preventDefault();\r\n      e.stopPropagation();\r\n\r\n      if (!adminUnlocked) {\r\n        var code = window.prompt(\"Entrez le code d\u2019acc\u00e8s au Back Office :\");\r\n        if (code === null) return;\r\n\r\n        code = String(code || \"\").trim();\r\n\r\n        if (code !== ADMIN_CODE) {\r\n          alert(\"Code incorrect.\");\r\n          return;\r\n        }\r\n\r\n        adminUnlocked = true;\r\n        render();\r\n        var boOpen = document.getElementById(\"boOverlay\");\r\n        if (boOpen) boOpen.classList.add(\"show\");\r\n        return;\r\n      }\r\n\r\n      var bo = document.getElementById(\"boOverlay\");\r\n      if (bo) bo.classList.toggle(\"show\");\r\n    }\r\n\r\n    if (e.key === \"Escape\") {\r\n      var bo2 = document.getElementById(\"boOverlay\");\r\n      if (bo2 && bo2.classList.contains(\"show\")) {\r\n        bo2.classList.remove(\"show\");\r\n        e.preventDefault();\r\n        e.stopPropagation();\r\n        return;\r\n      }\r\n\r\n      var commentOverlay = document.getElementById(\"commentModalOverlay\");\r\n      if (commentOverlay && commentOverlay.classList.contains(\"show\")) {\r\n        closeCommentModal();\r\n        e.preventDefault();\r\n        e.stopPropagation();\r\n      }\r\n    }\r\n  }\r\n\r\n  window.addEventListener(\"keydown\", hotkey, true);\r\n  document.addEventListener(\"keydown\", hotkey, true);\r\n\r\n  wpLoadConfig().then(function () {\r\n    syncLongueur();\r\n    render();\r\n  });\r\n})();\r\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-0f3fc0b e-flex e-con-boxed wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no e-con e-parent\" data-id=\"0f3fc0b\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-3b58784 e-flex e-con-boxed wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no e-con e-parent\" data-id=\"3b58784\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-2016","page","type-page","status-publish","hentry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.1.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Devis estimatif monte escalier - Bien vieillir chez soi<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/labienveillance.fr\/?page_id=2016\" \/>\n<meta property=\"og:locale\" content=\"fr_FR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Devis estimatif monte escalier - Bien vieillir chez soi\" \/>\n<meta property=\"og:url\" content=\"https:\/\/labienveillance.fr\/?page_id=2016\" \/>\n<meta property=\"og:site_name\" content=\"Bien vieillir chez soi\" \/>\n<meta property=\"article:modified_time\" content=\"2026-04-21T14:43:48+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Dur\u00e9e de lecture estim\u00e9e\" \/>\n\t<meta name=\"twitter:data1\" content=\"19 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/labienveillance.fr\/?page_id=2016\",\"url\":\"https:\/\/labienveillance.fr\/?page_id=2016\",\"name\":\"Devis estimatif monte escalier - Bien vieillir chez soi\",\"isPartOf\":{\"@id\":\"https:\/\/labienveillance.fr\/#website\"},\"datePublished\":\"2026-04-17T14:46:54+00:00\",\"dateModified\":\"2026-04-21T14:43:48+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/labienveillance.fr\/?page_id=2016#breadcrumb\"},\"inLanguage\":\"fr-FR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/labienveillance.fr\/?page_id=2016\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/labienveillance.fr\/?page_id=2016#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Accueil\",\"item\":\"https:\/\/labienveillance.fr\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Devis estimatif monte escalier\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/labienveillance.fr\/#website\",\"url\":\"https:\/\/labienveillance.fr\/\",\"name\":\"Bien vieillir chez soi\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/labienveillance.fr\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/labienveillance.fr\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"fr-FR\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/labienveillance.fr\/#organization\",\"name\":\"Bien vieillir chez soi\",\"url\":\"https:\/\/labienveillance.fr\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"fr-FR\",\"@id\":\"https:\/\/labienveillance.fr\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/labienveillance.fr\/wp-content\/uploads\/2025\/09\/LogoMakr-0C1PJU-1.png\",\"contentUrl\":\"https:\/\/labienveillance.fr\/wp-content\/uploads\/2025\/09\/LogoMakr-0C1PJU-1.png\",\"width\":199,\"height\":110,\"caption\":\"Bien vieillir chez soi\"},\"image\":{\"@id\":\"https:\/\/labienveillance.fr\/#\/schema\/logo\/image\/\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Devis estimatif monte escalier - Bien vieillir chez soi","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/labienveillance.fr\/?page_id=2016","og_locale":"fr_FR","og_type":"article","og_title":"Devis estimatif monte escalier - Bien vieillir chez soi","og_url":"https:\/\/labienveillance.fr\/?page_id=2016","og_site_name":"Bien vieillir chez soi","article_modified_time":"2026-04-21T14:43:48+00:00","twitter_card":"summary_large_image","twitter_misc":{"Dur\u00e9e de lecture estim\u00e9e":"19 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/labienveillance.fr\/?page_id=2016","url":"https:\/\/labienveillance.fr\/?page_id=2016","name":"Devis estimatif monte escalier - Bien vieillir chez soi","isPartOf":{"@id":"https:\/\/labienveillance.fr\/#website"},"datePublished":"2026-04-17T14:46:54+00:00","dateModified":"2026-04-21T14:43:48+00:00","breadcrumb":{"@id":"https:\/\/labienveillance.fr\/?page_id=2016#breadcrumb"},"inLanguage":"fr-FR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/labienveillance.fr\/?page_id=2016"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/labienveillance.fr\/?page_id=2016#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Accueil","item":"https:\/\/labienveillance.fr\/"},{"@type":"ListItem","position":2,"name":"Devis estimatif monte escalier"}]},{"@type":"WebSite","@id":"https:\/\/labienveillance.fr\/#website","url":"https:\/\/labienveillance.fr\/","name":"Bien vieillir chez soi","description":"","publisher":{"@id":"https:\/\/labienveillance.fr\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/labienveillance.fr\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"fr-FR"},{"@type":"Organization","@id":"https:\/\/labienveillance.fr\/#organization","name":"Bien vieillir chez soi","url":"https:\/\/labienveillance.fr\/","logo":{"@type":"ImageObject","inLanguage":"fr-FR","@id":"https:\/\/labienveillance.fr\/#\/schema\/logo\/image\/","url":"https:\/\/labienveillance.fr\/wp-content\/uploads\/2025\/09\/LogoMakr-0C1PJU-1.png","contentUrl":"https:\/\/labienveillance.fr\/wp-content\/uploads\/2025\/09\/LogoMakr-0C1PJU-1.png","width":199,"height":110,"caption":"Bien vieillir chez soi"},"image":{"@id":"https:\/\/labienveillance.fr\/#\/schema\/logo\/image\/"}}]}},"_links":{"self":[{"href":"https:\/\/labienveillance.fr\/index.php?rest_route=\/wp\/v2\/pages\/2016","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/labienveillance.fr\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/labienveillance.fr\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/labienveillance.fr\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/labienveillance.fr\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2016"}],"version-history":[{"count":13,"href":"https:\/\/labienveillance.fr\/index.php?rest_route=\/wp\/v2\/pages\/2016\/revisions"}],"predecessor-version":[{"id":2322,"href":"https:\/\/labienveillance.fr\/index.php?rest_route=\/wp\/v2\/pages\/2016\/revisions\/2322"}],"wp:attachment":[{"href":"https:\/\/labienveillance.fr\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2016"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}