<!-- ============================================================
Carrousel des évènements – Comité Régional de Boxe de Normandie
À coller dans un bloc « HTML personnalisé » de WordPress.
Pour ajouter un évènement : voir la liste EVENEMENTS dans le .
============================================================ -->
.bn-carousel{--per:3;--bn-navy:#01297a;--bn-pink:#e8365d;--bn-pink-soft:#ff7a98;--bn-text:#4a5578;--bn-line:#dfe3ee;--bn-soft:#f1f4fb;max-width:1100px;margin:0 auto;padding:24px 14px;background:var(--bn-navy);border-radius:16px;font-family:inherit;font-size:16px;line-height:1.4}
.bn-carousel *{box-sizing:border-box}
.bn-carousel .bn-heading{margin:0 0 22px;text-align:center;color:#fff;font-weight:800;font-size:28px;line-height:1.2}
.bn-viewport{overflow:hidden;padding:6px 0 10px}
.bn-track{display:flex;transition:transform .5s cubic-bezier(.4,0,.2,1)}
/* Nombre de cartes visibles : 3 ordinateur, 2 tablette, 1 téléphone */
@media(max-width:1000px){.bn-carousel{--per:2}}
@media(max-width:700px){.bn-carousel{--per:1}}
.bn-slide{flex:0 0 calc(100% / var(--per));padding:0 10px}
/* Toutes les cartes ont EXACTEMENT la même structure et les mêmes hauteurs */
.bn-card{background:#fff;color:var(--bn-navy);border-radius:14px;overflow:hidden;display:flex;flex-direction:column;box-shadow:0 4px 14px rgba(0,0,0,.25)}
/* Image : cadre carré, jamais plus grand que prévu */
.bn-media{position:relative;flex:none;width:100%;aspect-ratio:1/1;overflow:hidden;background:var(--bn-soft);display:flex;align-items:center;justify-content:center;border-bottom:1px solid var(--bn-line)}
.bn-carousel .bn-media img{position:absolute;top:0;left:0;width:100%;height:100%;max-width:none;margin:0;object-fit:contain;display:block}
.bn-glove{font-size:76px;line-height:1}
.bn-state{position:absolute;top:12px;left:12px;z-index:1;font-size:14px;line-height:1.4;background:var(--bn-navy);color:#fff;border-radius:99px;padding:3px 12px}
/* Texte : 4 zones à hauteur fixe, toujours dans le même ordre */
.bn-body{flex:none;height:270px;padding:16px 18px;display:grid;grid-template-rows:56px 52px 44px 1fr;row-gap:8px;overflow:hidden}
.bn-when{display:flex;align-items:center;gap:12px;margin:0;height:56px}
.bn-day{font-size:48px;font-weight:800;line-height:1;color:var(--bn-pink)}
.bn-when-txt{display:flex;flex-direction:column;font-size:15px;line-height:21px;color:var(--bn-text)}
.bn-when-txt strong{color:var(--bn-navy);font-size:17px;line-height:23px;font-weight:700}
.bn-carousel .bn-title{margin:0;padding:0;height:52px;color:var(--bn-navy);font-size:20px;line-height:26px;font-weight:800;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.bn-lieu{margin:0;padding:0;height:44px;color:var(--bn-text);font-size:15px;line-height:21px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.bn-actions{display:flex;align-items:flex-end}
.bn-carousel a.bn-btn{display:inline-block;background:var(--bn-pink);color:#fff;text-decoration:none;font-size:16px;font-weight:700;padding:10px 20px;border-radius:8px;line-height:20px}
.bn-carousel a.bn-btn:hover{background:var(--bn-navy);color:#fff}
.bn-controls{display:flex;align-items:center;justify-content:center;gap:18px;margin-top:14px}
.bn-nav{width:44px;height:44px;border:2px solid #fff;border-radius:50%;background:transparent;color:#fff;font-size:30px;line-height:1;cursor:pointer;padding:0 0 4px;display:flex;align-items:center;justify-content:center}
.bn-nav:hover{background:var(--bn-pink);border-color:var(--bn-pink);color:#fff}
.bn-dots{display:flex;gap:8px;align-items:center}
.bn-dot{width:11px;height:11px;border-radius:50%;border:0;padding:0;background:rgba(255,255,255,.35);cursor:pointer}
.bn-dot[aria-current="true"]{background:var(--bn-pink-soft);width:28px;border-radius:99px}
.bn-carousel button:focus-visible,.bn-carousel a:focus-visible{outline:3px solid #fff;outline-offset:2px}
@media(prefers-reduced-motion:reduce){.bn-track{transition:none}}
(function () {
/* ===================== À MODIFIER ===================== */
var TITRE = "Les prochains évènements du comité"; // "" = pas de titre
var PLUS_RECENT_D_ABORD = true; // true = du plus récent au plus ancien (28 nov, 21 nov…) ; false = du plus ancien au plus récent
var MASQUER_PASSES = false; // true = les évènements passés disparaissent
var DELAI = 6000; // défilement automatique en ms (0 = désactivé)
// Pour ajouter un évènement : copiez un bloc { ... }, collez-le dans la liste
// et changez les textes. La date s'écrit AAAA-MM-JJ. L'ordre dans la liste
// n'a pas d'importance : le carrousel trie tout seul par date.
// (Deux évènements le même jour : l'ordre de la liste est respecté.)
// Laissez "" pour image / lien / heure si vous n'en avez pas.
// Format d'image conseillé : carré, 1080 x 1080 pixels.
var EVENEMENTS = [
{
titre: "Formation des Dirigeants M3",
date: "2026-11-21",
heure: "",
lieu: "Maison des Sports, Hérouville-Saint-Clair",
image: "https://boxenormandie.fr/wp-content/uploads/2026/11/Copie-de-Sans-titre10.svg",
lien: ""
},
{
titre: "Championnat Normandie Élites",
date: "2026-11-21",
heure: "19h00",
lieu: "Gymnase Robert Gossart, Condé-en-Normandie",
image: "https://boxenormandie.fr/wp-content/uploads/2026/11/Copie-de-Sans-titre7.svg",
lien: "https://boxenormandie.fr/championnat-normandie-elites-boxe-conde-en-normandie/"
},
{
titre: "½ Finales CR Élites",
date: "2026-11-28",
heure: "",
lieu: "Salle Multisport, Lisieux",
image: "",
lien: ""
},
{
titre: "La Nuit des Combattants",
date: "2026-10-31",
heure: "",
lieu: "Hall Saint-Exupéry, Rouen",
image: "https://boxenormandie.fr/wp-content/uploads/2026/11/Copie-de-Sans-titre8.svg",
lien: "https://boxenormandie.fr/nuit-des-combattants-rouen-2026/"
},
{
titre: "Boxing Tour Normand, étape d'Hérouville-Saint-Clair",
date: "2026-09-06",
heure: "",
lieu: "Collège Saint-Michel, Hérouville-Saint-Clair",
image: "https://boxenormandie.fr/wp-content/uploads/2026/11/Copie-de-Sans-titre9.svg",
lien: "https://boxenormandie.fr/boxing-tour-normand-herouville-saint-clair/"
}
];
/* =================== FIN DES MODIFICATIONS =================== */
var root = document.getElementById("bn-carousel");
if (!root) return;
var track = root.querySelector(".bn-track");
var dotsBox = root.querySelector(".bn-dots");
var controls = root.querySelector(".bn-controls");
var heading = root.querySelector(".bn-heading");
if (TITRE) heading.textContent = TITRE; else heading.style.display = "none";
var today = new Date(); today.setHours(0, 0, 0, 0);
var list = EVENEMENTS.map(function (e, n) {
var d = new Date(e.date + "T12:00:00");
return { e: e, d: d, n: n, passe: d < today };
}).filter(function (x) {
return !isNaN(x.d) && !(MASQUER_PASSES && x.passe);
}).sort(function (a, b) {
var diff = PLUS_RECENT_D_ABORD ? b.d - a.d : a.d - b.d;
return diff || (a.n - b.n);
});
if (!list.length) { root.style.display = "none"; return; }
function el(tag, cls, txt) {
var n = document.createElement(tag);
if (cls) n.className = cls;
if (txt) n.textContent = txt;
return n;
}
var slides = [], dots = [], idx = 0, timer = null;
list.forEach(function (x, i) {
var e = x.e;
var s = el("div", "bn-slide");
s.setAttribute("role", "group");
s.setAttribute("aria-roledescription", "diapositive");
s.setAttribute("aria-label", (i + 1) + " sur " + list.length);
var card = el("article", "bn-card");
var m = el("div", "bn-media");
if (e.image) {
var im = el("img"); im.src = e.image; im.alt = "Affiche : " + e.titre; im.loading = "lazy";
m.appendChild(im);
} else {
m.appendChild(el("span", "bn-glove", "\uD83E\uDD4A"));
}
if (x.passe) m.appendChild(el("span", "bn-state", "Terminé"));
var b = el("div", "bn-body");
var when = el("p", "bn-when");
when.appendChild(el("span", "bn-day", String(x.d.getDate())));
var wt = el("span", "bn-when-txt");
var mois = x.d.toLocaleDateString("fr-FR", { month: "long", year: "numeric" });
var jour = x.d.toLocaleDateString("fr-FR", { weekday: "long" });
wt.appendChild(el("strong", "", mois));
wt.appendChild(el("span", "", jour.charAt(0).toUpperCase() + jour.slice(1) + (e.heure ? " à " + e.heure : "")));
when.appendChild(wt);
b.appendChild(when);
b.appendChild(el("h3", "bn-title", e.titre));
b.appendChild(el("p", "bn-lieu", e.lieu || ""));
var act = el("div", "bn-actions");
if (e.lien) {
var a = el("a", "bn-btn", "En savoir plus");
a.href = e.lien;
act.appendChild(a);
}
b.appendChild(act);
card.appendChild(m); card.appendChild(b);
s.appendChild(card);
track.appendChild(s); slides.push(s);
});
function perView() {
return parseInt(getComputedStyle(root).getPropertyValue("--per"), 10) || 1;
}
function maxIdx() { return Math.max(0, list.length - perView()); }
function buildDots() {
dotsBox.innerHTML = ""; dots = [];
for (var i = 0; i mx ? 0 : (n = idx && i 0 && maxIdx() > 0 && !reduit && !timer) timer = setInterval(function () { go(idx + 1); }, DELAI);
}
function stop() { clearInterval(timer); timer = null; }
function restart() { stop(); start(); }
root.querySelector(".bn-prev").addEventListener("click", function () { go(idx - 1); restart(); });
root.querySelector(".bn-next").addEventListener("click", function () { go(idx + 1); restart(); });
root.addEventListener("mouseenter", stop);
root.addEventListener("mouseleave", start);
root.addEventListener("focusin", stop);
root.addEventListener("focusout", start);
root.addEventListener("keydown", function (ev) {
if (ev.key === "ArrowLeft") go(idx - 1);
if (ev.key === "ArrowRight") go(idx + 1);
});
var x0 = null;
root.addEventListener("touchstart", function (ev) { x0 = ev.touches[0].clientX; }, { passive: true });
root.addEventListener("touchend", function (ev) {
if (x0 === null) return;
var dx = ev.changedTouches[0].clientX - x0;
if (Math.abs(dx) > 50) { go(idx + (dx < 0 ? 1 : -1)); restart(); }
x0 = null;
});
var rt;
window.addEventListener("resize", function () {
clearTimeout(rt);
rt = setTimeout(function () { buildDots(); go(Math.min(idx, maxIdx())); restart(); }, 150);
});
buildDots();
go(0);
start();
})();