<!-- ============================================================
  Sélecteur de véhicule Meovia — bloc autonome (CSS + HTML + JS)
  À coller tel quel dans la page du CMS.
  Réglages : attributs data-* de <div id="mvs"> ci-dessous.
============================================================ -->
<style>
#mvs{--mvs-accent:#0b5cad;--mvs-accent-dark:#084580;--mvs-navy:#0c2340;--mvs-bg:#f3f6fa;--mvs-line:#e2e8f0;--mvs-text:#18212d;--mvs-muted:#5f6d7e;--mvs-ok:#157347;--mvs-ok-bg:#e8f6ee;
  box-sizing:border-box;max-width:1100px;margin:24px auto;padding:0 12px;color:var(--mvs-text);font-size:15px;line-height:1.5}
#mvs *,#mvs *::before,#mvs *::after{box-sizing:border-box}
#mvs [hidden]{display:none!important}
#mvs .mvs-panel{background:#fff;border:1px solid var(--mvs-line);border-radius:18px;box-shadow:0 12px 36px rgba(12,35,64,.10);overflow:hidden}
#mvs .mvs-head{position:relative;display:flex;align-items:center;gap:16px;padding:24px 28px;color:#fff;background:radial-gradient(120% 160% at 0% 0%,#1b6fc7 0%,var(--mvs-accent) 35%,var(--mvs-navy) 100%)}
#mvs .mvs-head::after{content:"";position:absolute;right:-40px;top:-60px;width:220px;height:220px;border-radius:50%;background:rgba(255,255,255,.07);pointer-events:none}
#mvs .mvs-icon{flex:none;display:flex;align-items:center;justify-content:center;width:52px;height:52px;border-radius:14px;background:rgba(255,255,255,.16);box-shadow:inset 0 0 0 1px rgba(255,255,255,.25)}
#mvs .mvs-icon svg{width:30px;height:30px}
#mvs .mvs-title{margin:0;font-size:23px;font-weight:800;letter-spacing:-.01em;line-height:1.25;color:#fff}
#mvs .mvs-sub{margin:4px 0 0;color:rgba(255,255,255,.82);font-size:14px}
#mvs .mvs-form{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:14px;padding:22px 28px 26px}
#mvs .mvs-field{position:relative;display:flex;flex-direction:column;gap:6px;min-width:0}
#mvs .mvs-field label{display:flex;align-items:center;gap:8px;font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--mvs-muted)}
#mvs .mvs-num{display:inline-flex;align-items:center;justify-content:center;flex:none;width:22px;height:22px;border-radius:50%;background:var(--mvs-bg);color:var(--mvs-muted);box-shadow:inset 0 0 0 1px var(--mvs-line);font-size:12px;letter-spacing:0;transition:all .2s}
#mvs .mvs-field.mvs-active .mvs-num{background:var(--mvs-accent);color:#fff;box-shadow:none}
#mvs .mvs-field.mvs-done .mvs-num{background:var(--mvs-ok);color:#fff;box-shadow:none;font-size:0}
#mvs .mvs-field.mvs-done .mvs-num::before{content:"";width:5px;height:10px;margin-top:-2px;border:solid #fff;border-width:0 2px 2px 0;transform:rotate(45deg)}
#mvs select{width:100%;height:48px;padding:0 38px 0 14px;font:inherit;font-weight:500;color:var(--mvs-text);background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%230b5cad' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat right 14px center;border:1.5px solid #cdd6e1;border-radius:12px;appearance:none;-webkit-appearance:none;-moz-appearance:none;text-overflow:ellipsis;cursor:pointer;transition:border-color .15s,box-shadow .15s}
#mvs select:hover:not(:disabled){border-color:var(--mvs-accent)}
#mvs select:focus-visible,#mvs button:focus-visible,#mvs a:focus-visible,#mvs summary:focus-visible{outline:none;box-shadow:0 0 0 4px rgba(11,92,173,.22);border-color:var(--mvs-accent)}
#mvs select:disabled{background-color:var(--mvs-bg);color:#9aa6b4;border-color:var(--mvs-line);cursor:not-allowed}
#mvs .mvs-field.mvs-done select{border-color:#9fd2b5;background-color:#fbfffc}
#mvs .mvs-bar{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:14px 28px;background:var(--mvs-bg);border-top:1px solid var(--mvs-line)}
#mvs .mvs-chosen{margin:0;font-weight:700;overflow-wrap:anywhere}
#mvs .mvs-reset{flex:none;padding:9px 16px;font:inherit;font-size:14px;font-weight:600;color:var(--mvs-accent);background:#fff;border:1.5px solid var(--mvs-accent);border-radius:999px;cursor:pointer;transition:all .15s}
#mvs .mvs-reset:hover{background:var(--mvs-accent);color:#fff}
#mvs .mvs-status{margin:16px 0 0;padding:14px 18px;border-radius:12px;background:var(--mvs-bg);color:var(--mvs-muted)}
#mvs .mvs-status.mvs-error{background:#fdecea;color:#8a1f17}
#mvs .mvs-results{margin-top:20px;animation:mvs-in .35s ease both}
@keyframes mvs-in{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){#mvs .mvs-results{animation:none}#mvs *{transition:none!important}}
#mvs .mvs-summary{display:inline-flex;align-items:center;gap:8px;margin:0 0 4px;padding:6px 14px;border-radius:999px;background:var(--mvs-ok-bg);color:var(--mvs-ok);font-size:14px;font-weight:700}
#mvs .mvs-roof{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 10px;margin:22px 0 10px;font-size:17px;font-weight:800;letter-spacing:-.01em}
#mvs .mvs-roof small{padding:2px 10px;border-radius:999px;background:#e7f0fb;color:var(--mvs-accent-dark);font-size:13px;font-weight:600}
#mvs .mvs-group{margin:0 0 18px;background:#fff;border:1px solid var(--mvs-line);border-radius:16px;box-shadow:0 2px 10px rgba(12,35,64,.05);overflow:hidden}
#mvs .mvs-grouphead{margin:0;display:flex;align-items:center;gap:8px;padding:12px 20px;font-size:12px;font-weight:800;text-transform:uppercase;letter-spacing:.06em;color:var(--mvs-accent-dark);background:linear-gradient(90deg,#eaf2fb,var(--mvs-bg));border-bottom:1px solid var(--mvs-line)}
#mvs .mvs-fixed .mvs-grouphead{color:var(--mvs-muted);border-top:1px solid var(--mvs-line);background:var(--mvs-bg)}
#mvs .mvs-fixed .mvs-grouphead::before{content:"+";display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;border-radius:50%;background:var(--mvs-accent);color:#fff;font-size:14px;line-height:1}
#mvs .mvs-list{list-style:none;margin:0;padding:0}
#mvs .mvs-item{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:2px 16px;align-items:center;padding:14px 20px;border-top:1px solid var(--mvs-line);transition:background .15s}
#mvs .mvs-item:hover{background:#f8fbff}
#mvs .mvs-list>.mvs-item:first-child{border-top:0}
#mvs .mvs-name{font-size:16px;font-weight:700}
#mvs .mvs-desc{grid-column:1;color:var(--mvs-muted);font-size:14px}
#mvs .mvs-meta{grid-column:1;display:flex;flex-wrap:wrap;gap:6px;margin-top:6px}
#mvs .mvs-chip{padding:2px 10px;border-radius:999px;background:var(--mvs-bg);color:var(--mvs-muted);font-size:12px;font-weight:600;border:1px solid var(--mvs-line)}
#mvs .mvs-chip.mvs-load{background:var(--mvs-ok-bg);border-color:#bfe3cd;color:var(--mvs-ok)}
#mvs .mvs-link{grid-column:2;grid-row:1 / span 3;align-self:center;display:inline-flex;align-items:center;gap:6px;padding:10px 18px;border-radius:999px;background:var(--mvs-accent);color:#fff;font-size:14px;font-weight:700;text-align:center;text-decoration:none;white-space:nowrap;box-shadow:0 4px 12px rgba(11,92,173,.25);transition:transform .15s,background .15s,box-shadow .15s}
#mvs .mvs-link::after{content:"→";transition:transform .15s}
#mvs .mvs-link:hover{background:var(--mvs-accent-dark);color:#fff;transform:translateY(-1px)}
#mvs .mvs-link:hover::after{transform:translateX(3px)}
#mvs .mvs-fixed .mvs-link{background:#fff;color:var(--mvs-accent);border:1.5px solid var(--mvs-accent);box-shadow:none}
#mvs .mvs-fixed .mvs-link:hover{background:var(--mvs-accent);color:#fff}
#mvs .mvs-tips{padding:12px 20px;border-top:1px solid var(--mvs-line);font-size:14px;background:#fffdf6}
#mvs .mvs-tips summary{cursor:pointer;font-weight:700;color:#8a5a00}
#mvs .mvs-tips ul{margin:8px 0 0;padding-left:20px}
#mvs .mvs-tips li{margin:4px 0}
#mvs .mvs-empty{padding:22px;border:1.5px dashed #b9c2cc;border-radius:14px;color:var(--mvs-muted);background:#fff}
#mvs .mvs-foot{margin:20px 0 0;font-size:12px;color:var(--mvs-muted)}
@media (max-width:900px){#mvs .mvs-form{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:560px){
  #mvs{margin:12px auto;padding:0 8px}
  #mvs .mvs-head{padding:18px 16px;gap:12px}
  #mvs .mvs-icon{width:42px;height:42px;border-radius:12px}
  #mvs .mvs-icon svg{width:24px;height:24px}
  #mvs .mvs-title{font-size:18px}
  #mvs .mvs-form{grid-template-columns:1fr;padding:16px 16px 20px}
  #mvs .mvs-bar{flex-direction:column;align-items:stretch;padding:14px 16px}
  #mvs .mvs-item{grid-template-columns:1fr;padding:14px 16px}
  #mvs .mvs-link{grid-column:1;grid-row:auto;justify-content:center;margin-top:10px;width:100%;padding:12px 16px}
  #mvs .mvs-grouphead,#mvs .mvs-tips{padding-left:16px;padding-right:16px}
}
</style>

<div id="mvs"
     data-base="/pub/selecteur-voiture/"
     data-product-url="/?q={ref}"
     data-contact-url="/contact">
  <section class="mvs-panel" aria-labelledby="mvs-title">
    <div class="mvs-head">
      <span class="mvs-icon" aria-hidden="true"><svg viewBox="0 0 32 32" fill="none" stroke="#fff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 14l2.2-5.2A3 3 0 0 1 12 7h8a3 3 0 0 1 2.8 1.8L25 14"/><path d="M5 14h22a2 2 0 0 1 2 2v5a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1v-5a2 2 0 0 1 2-2z"/><circle cx="9" cy="22" r="2.5" fill="#0c2340"/><circle cx="23" cy="22" r="2.5" fill="#0c2340"/><path d="M9 4h14" stroke-width="2.4"/></svg></span>
      <div>
        <h2 class="mvs-title" id="mvs-title">Trouvez les accessoires compatibles avec votre véhicule</h2>
        <p class="mvs-sub">Barres de toit, pieds et kits de fixation compatibles. Sélectionnez votre voiture en 4 étapes.</p>
      </div>
    </div>
    <div class="mvs-form">
      <div class="mvs-field"><label for="mvs-make"><span class="mvs-num">1</span>Marque</label>
        <select id="mvs-make" disabled><option value="">Chargement…</option></select></div>
      <div class="mvs-field"><label for="mvs-model"><span class="mvs-num">2</span>Modèle</label>
        <select id="mvs-model" disabled><option value="">Choisissez d’abord la marque</option></select></div>
      <div class="mvs-field"><label for="mvs-year"><span class="mvs-num">3</span>Année</label>
        <select id="mvs-year" disabled><option value="">Choisissez d’abord le modèle</option></select></div>
      <div class="mvs-field"><label for="mvs-version"><span class="mvs-num">4</span>Version</label>
        <select id="mvs-version" disabled><option value="">Choisissez d’abord l’année</option></select></div>
    </div>
    <div class="mvs-bar" id="mvs-bar" hidden>
      <p class="mvs-chosen" id="mvs-chosen"></p>
      <button type="button" class="mvs-reset" id="mvs-reset">Changer de véhicule</button>
    </div>
  </section>
  <div id="mvs-live" aria-live="polite"></div>
  <p class="mvs-foot">Compatibilités fournies par Thule. Vérifiez toujours la notice et la charge maximale autorisée par le constructeur de votre véhicule.</p>
</div>

<script>
(function () {
  'use strict';
  var root = document.getElementById('mvs');
  if (!root || root.getAttribute('data-ready')) return;
  root.setAttribute('data-ready', '1');

  var CFG = {
    base: (root.getAttribute('data-base') || '/files/selecteur-voiture/').replace(/\/?$/, '/'),
    productUrl: root.getAttribute('data-product-url') || '/?q={ref}',
    contactUrl: root.getAttribute('data-contact-url') || '/contact',
    thisYear: new Date().getFullYear()
  };

  var KIND_HEAD = ['Barres de toit — au choix', 'Galeries complètes (barres + pieds) — au choix'];

  var $ = function (id) { return document.getElementById(id); };
  var selMake = $('mvs-make'), selModel = $('mvs-model'), selYear = $('mvs-year'), selVer = $('mvs-version');
  var live = $('mvs-live'), bar = $('mvs-bar'), chosen = $('mvs-chosen');

  var index = null, cache = {}, current = null, productMap = {}, state = { tab: null };

  function el(tag, cls, text) {
    var n = document.createElement(tag);
    if (cls) n.className = cls;
    if (text != null) n.textContent = text;
    return n;
  }
  function fill(select, placeholder, items, disabled) {
    select.innerHTML = '';
    var o = el('option', null, placeholder); o.value = ''; select.appendChild(o);
    items.forEach(function (it) { var op = el('option', null, it.label); op.value = it.value; select.appendChild(op); });
    select.disabled = !!disabled || !items.length;
  }
  function getJSON(url) {
    return fetch(url, { credentials: 'same-origin' }).then(function (r) {
      if (!r.ok) throw new Error(url + ' → ' + r.status);
      return r.json();
    });
  }
  function setStatus(msg, isError) {
    live.innerHTML = '';
    if (!msg) return;
    var p = el('p', 'mvs-status' + (isError ? ' mvs-error' : ''), msg);
    live.appendChild(p);
  }
  function cap(s) { return s ? s.charAt(0).toUpperCase() + s.slice(1) : s; }
  function yearsOf(v) { return { a: v.a, z: v.z || CFG.thisYear }; }

  /* état visuel des 4 étapes : validée (✓), en cours, à venir */
  function markSteps() {
    var sels = [selMake, selModel, selYear, selVer], active = false;
    sels.forEach(function (sel) {
      var f = sel.parentNode, done = sel.value !== '';
      f.classList.toggle('mvs-done', done);
      var isActive = !done && !sel.disabled && !active;
      f.classList.toggle('mvs-active', isActive);
      if (isActive) active = true;
    });
  }
  root.addEventListener('change', markSteps);
  new MutationObserver(markSteps).observe(root, { subtree: true, childList: true, attributes: true, attributeFilter: ['disabled'] });

  /* ---------- Étape 1 : marques ---------- */
  getJSON(CFG.base + 'index.json').then(function (data) {
    index = data;
    fill(selMake, 'Sélectionnez une marque', data.makes.map(function (m, i) { return { value: String(i), label: m.n }; }));
    getJSON(CFG.base + 'produits.json').then(function (m) { productMap = m || {}; }).catch(function () {});
  }).catch(function () {
    fill(selMake, 'Indisponible', [], true);
    setStatus('Le sélecteur est momentanément indisponible. Contactez-nous pour trouver les accessoires adaptés à votre véhicule.', true);
  });

  selMake.addEventListener('change', function () {
    resetFrom('model');
    if (selMake.value === '') return;
    var m = index.makes[+selMake.value];
    setStatus('Chargement des modèles…');
    var p = cache[m.f] ? Promise.resolve(cache[m.f]) : getJSON(CFG.base + m.f).then(function (d) { cache[m.f] = d; return d; });
    p.then(function (d) {
      current = d; setStatus('');
      fill(selModel, 'Sélectionnez un modèle', d.models.map(function (mo, i) { return { value: String(i), label: mo.n }; }));
    }).catch(function () { setStatus('Impossible de charger les données de cette marque. Réessayez plus tard.', true); });
  });

  /* ---------- Étape 2 : modèle → années ---------- */
  selModel.addEventListener('change', function () {
    resetFrom('year');
    if (selModel.value === '') return;
    var model = current.models[+selModel.value], set = {};
    model.v.forEach(function (v) {
      var y = yearsOf(v);
      for (var i = y.a; i <= y.z; i++) set[i] = 1;
    });
    var years = Object.keys(set).map(Number).sort(function (a, b) { return b - a; });
    fill(selYear, 'Sélectionnez une année', years.map(function (y) { return { value: String(y), label: String(y) }; }));
  });

  /* ---------- Étape 3 : année → versions ---------- */
  function vehicleLabel(v) {
    var parts = [];
    var base = [v.ty, v.do ? v.do.replace('-dr', ' portes') : null].filter(Boolean).join(' ');
    if (base) parts.push(base);
    if (v.ch) parts.push(v.ch);
    if (v.mi) parts.push(v.mi);
    parts.push(v.a + ' – ' + (v.z ? v.z : 'aujourd’hui'));
    if (v.mk) parts.push('marché ' + v.mk);
    return parts.join(' · ');
  }
  selYear.addEventListener('change', function () {
    resetFrom('version');
    if (selYear.value === '') return;
    var y = +selYear.value, model = current.models[+selModel.value];
    var vers = [];
    model.v.forEach(function (v, i) { var r = yearsOf(v); if (y >= r.a && y <= r.z) vers.push({ value: String(i), label: vehicleLabel(v) }); });
    fill(selVer, 'Sélectionnez une version', vers);
    if (vers.length === 1) { selVer.value = vers[0].value; showResults(); }
  });
  selVer.addEventListener('change', function () { if (selVer.value !== '') showResults(); else clearResults(); });

  function resetFrom(level) {
    clearResults();
    var steps = ['model', 'year', 'version'];
    var texts = { model: 'Choisissez d’abord la marque', year: 'Choisissez d’abord le modèle', version: 'Choisissez d’abord l’année' };
    var sels = { model: selModel, year: selYear, version: selVer };
    for (var i = steps.indexOf(level); i < steps.length; i++) fill(sels[steps[i]], texts[steps[i]], [], true);
  }
  function clearResults() { setStatus(''); bar.hidden = true; state.tab = null; }

  $('mvs-reset').addEventListener('click', function () {
    selMake.value = ''; resetFrom('model'); selMake.focus();
    window.scrollTo({ top: root.getBoundingClientRect().top + window.pageYOffset - 20, behavior: 'smooth' });
  });

  /* ---------- Étape 4 : résultats ---------- */
  function productLink(id, name) {
    if (productMap[id]) return productMap[id];
    return CFG.productUrl.replace('{ref}', encodeURIComponent(id)).replace('{name}', encodeURIComponent(name));
  }
  function itemRow(role, id, kg) {
    var p = current.p[id] || [id, ''];
    var li = el('li', 'mvs-item');
    li.appendChild(el('div', 'mvs-name', p[0]));
    if (p[1]) li.appendChild(el('div', 'mvs-desc', cap(p[1])));
    var meta = el('div', 'mvs-meta');
    if (role) meta.appendChild(el('span', 'mvs-chip', role));
    meta.appendChild(el('span', 'mvs-chip', 'Réf. ' + id));
    if (kg) meta.appendChild(el('span', 'mvs-chip mvs-load', 'Charge max. ' + kg + ' kg'));
    li.appendChild(meta);
    var a = el('a', 'mvs-link', 'Voir sur Meovia');
    a.href = productLink(id, p[0]);
    a.setAttribute('aria-label', 'Voir ' + p[0] + ' sur Meovia');
    li.appendChild(a);
    return li;
  }

  /* groupe = [toit, type(0 barres | 1 galerie), pieds, kit, [[réf barre, kg],…], [conseils], an début, an fin] */
  function renderGroup(g) {
    var box = el('section', 'mvs-group');
    box.appendChild(el('h4', 'mvs-grouphead', KIND_HEAD[g[1]]));
    var ul = el('ul', 'mvs-list');
    g[4].forEach(function (b) { ul.appendChild(itemRow(null, b[0], b[1])); });
    box.appendChild(ul);
    var fixed = [];
    if (g[2]) fixed.push(['Pieds', g[2]]);
    if (g[3]) fixed.push(['Kit de fixation', g[3]]);
    if (fixed.length) {
      var f = el('div', 'mvs-fixed');
      f.appendChild(el('h4', 'mvs-grouphead', 'À associer pour le montage'));
      var ul2 = el('ul', 'mvs-list');
      fixed.forEach(function (x) { ul2.appendChild(itemRow(x[0], x[1])); });
      f.appendChild(ul2); box.appendChild(f);
    }
    if (g[5] && g[5].length) {
      var d = el('details', 'mvs-tips'); d.appendChild(el('summary', null, 'Conseils de montage (' + g[5].length + ')'));
      var ul3 = el('ul');
      g[5].forEach(function (t) { ul3.appendChild(el('li', null, current.tips[t])); });
      d.appendChild(ul3); box.appendChild(d);
    }
    return box;
  }

  function showResults() {
    var model = current.models[+selModel.value], v = model.v[+selVer.value], y = +selYear.value;
    chosen.textContent = 'Votre véhicule : ' + current.make + ' ' + model.n + ' — ' + vehicleLabel(v).split(' · ')[0] + ' — ' + y;
    bar.hidden = false;
    live.innerHTML = '';

    var groups = v.g.filter(function (g) { return !(g[6] && y < g[6]) && !(g[7] && y > g[7]); });
    if (!groups.length) {
      var e = el('div', 'mvs-empty');
      e.appendChild(el('p', null, 'Aucune barre de toit Thule n’est référencée pour ce véhicule. '));
      var a = el('a', null, 'Contactez-nous'); a.href = CFG.contactUrl;
      e.appendChild(a); e.appendChild(document.createTextNode(' : nous vous conseillerons une solution adaptée.'));
      live.appendChild(e); return;
    }
    var roofs = [], by = {};
    groups.forEach(function (g) { if (!by[g[0]]) { by[g[0]] = []; roofs.push(g[0]); } by[g[0]].push(g); });
    var wrap = el('div', 'mvs-results');
    var seen = {};
    groups.forEach(function (g) { g[4].forEach(function (b) { seen[b[0]] = 1; }); });
    var n = Object.keys(seen).length;
    wrap.appendChild(el('p', 'mvs-summary', '✓ ' + n + (n > 1 ? ' barres de toit compatibles' : ' barre de toit compatible')));
    roofs.forEach(function (r) {
      var label = current.roofs[r];
      if (label) {
        var h = el('h3', 'mvs-roof'); h.appendChild(document.createTextNode('Votre toit : ')); h.appendChild(el('small', null, label));
        wrap.appendChild(h);
      }
      by[r].sort(function (a, b) { return a[1] - b[1]; }).forEach(function (g) { wrap.appendChild(renderGroup(g)); });
    });
    live.appendChild(wrap);
  }
})();
</script>