Espace Artiste

Blessing-K2

URBAN GOSPEL - HIP-HOP / RAP

Blessing K2 est un rappeur, chanteur et compositeur ivoirien évoluant dans le rap gospel. Fils de pasteur, il se distingue par des textes satiriques orientés vers l'éveil des consciences chrétiennes.

Blessing-K2

Blessing-K2

URBAN GOSPEL - HIP-HOP / RAP

Qui est Blessing K2 ?

Blessing K2 est un rappeur, chanteur et compositeur ivoirien, figure montante du rap gospel en Côte d’Ivoire. Artiste atypique et profondément engagé, il se distingue par un flow percutant et des textes satiriques qui tranchent avec les codes habituels de la musique chrétienne. Là où d’autres louent, lui interpelle, questionne et bouscule.

Sa marque de fabrique ? Une parole directe tournée vers l’éveil des consciences, notamment au sein des assemblées chrétiennes. Comme il aime lui-même le résumer : « Moi je rap pas, moi je prêche. »


Origines et parcours spirituel

Fils de pasteur, Blessing K2 a grandi dans un environnement profondément ancré dans la foi chrétienne. C’est ce terreau familial et spirituel qui forge son regard critique sur les réalités de l’Église contemporaine. Loin de s’en détourner, il choisit d’en faire le cœur de son art : dénoncer les dérives, nommer les maux, réveiller les endormis.

Son appartenance au Collectif 120 — un rassemblement de jeunes rappeurs chrétiens ivoiriens fondé officiellement le 5 mai 2019 — illustre aussi sa volonté de s’inscrire dans une dynamique collective au service de l’évangélisation par la musique urbaine.


Discographie et titres marquants

Blessing K2 démarre sa carrière musicale en 2018 avec un premier titre qui fait immédiatement parler de lui dans le milieu gospel ivoirien :

    • « Jésus n’est pas ton camarade » (2018) – Le titre de lancement qui pose les bases de son identité artistique. Un message clair, sans compromis : la foi n’est pas une affaire de convenance. Produit par Maranatha Production et réalisé par Andy Shakur, ce clip circule largement sur les plateformes chrétiennes.
    • « Dieu Faut Sciencer » (2022) – Un second titre qui confirme son style et renforce sa présence dans la scène rap gospel ivoirienne. L’expression — un mélange de français et de nouchi — signifie littéralement qu’il faut comprendreanalyser Dieu avec sérieux.
    • « Le Sang de Jésus » (2021) – Un titre plus contemplatif, disponible sur les grandes plateformes de streaming.
    • « On est dans quoi ? » (2024) – Une interrogation satirique sur l’état de la chrétienté, fidèle à son registre.
    • « Le Bilan Gospel » (2025) – Sa dernière production en date, qui confirme son évolution artistique.

Collaboration avec Kophi’s Music

En novembre 2025, Blessing K2 franchit une nouvelle étape dans sa carrière en signant une collaboration avec Kophi’s Music, label et structure spécialisé dans la distribution musicale. Ce partenariat lui ouvre des portes pour une diffusion plus large de ses productions sur les plateformes nationales et internationales, consolidant ainsi sa visibilité dans l’écosystème de la musique gospel africaine.


Style et positionnement artistique

Blessing K2 évolue dans la catégorie du rap gospel ivoire, une scène en plein essor portée par des artistes comme KS Bloom, Iron Le Rappeur ou encore les membres du Collectif 120. Mais son positionnement est unique : là où beaucoup optent pour la louange ou l’encouragement spirituel, lui choisit la satire et la dénonciation prophétique.

Ses textes s’attaquent aux faux-semblants de la vie d’église, à la superficialité de la foi, aux contradictions visibles dans les assemblées chrétiennes. Un positionnement courageux qui lui vaut autant d’admirateurs que de remises en question — et c’est précisément ce qu’il recherche.

Retrouvez Blessing K2 sur ses réseaux officiels :


« Moi je rap pas, moi je prêche. » — Blessing K2


Retour en haut
) * ============================================================ * * SPEC TIMING (synchronisé avec le CSS) : * DISPLAY_MS = 5000ms — durée totale d'affichage par slide * TRANSITION_MS = 1200ms — durée du crossfade CSS ease-in-out * OVERLAP_MS = 3800ms — délai avant déclenchement du crossfade * (DISPLAY − TRANSITION = 3800ms) * * FONCTIONNEMENT : * t = 0 → slide N devient is-active * Ken Burns scale(1.0 → 1.08) démarre * t = 3800ms → crossfadeTo() déclenché : * slide N → is-leaving (opacity 1→0 / 1200ms) * slide N+1 → is-active (opacity 0→1 / 1200ms) * Ken Burns de N+1 démarre * t = 5000ms → crossfade terminé, slide N+1 pleinement visible * t = 5000ms → prochain cycle démarre (boucle) * * RÈGLES : * • Pas de pause au survol de la souris * • Couleur accent propagée via CSS var(--accent) par slide * • Labels en français (SUIVANT, Mettre en pause, etc.) * ============================================================ */(function () { 'use strict';/* ───────────────────────────────────────────────────────── CONSTANTES DE TIMING — synchronisées avec le CSS ───────────────────────────────────────────────────────── */ const DISPLAY_MS = 5000; // Affichage total par slide const TRANSITION_MS = 1200; // Durée du crossfade CSS const OVERLAP_MS = DISPLAY_MS - TRANSITION_MS; // 3800ms : déclenchement anticipé/* ───────────────────────────────────────────────────────── INIT D'UN SLIDER ───────────────────────────────────────────────────────── */ function initKMSlider(wrapper) {/* ── Config ── */ const id = wrapper.id; const slidesData = (window.kmSliderData && window.kmSliderData[id]) || []; const auto = wrapper.dataset.auto !== 'false'; const total = parseInt(wrapper.dataset.total) || 0;if (total < 1) return;/* ── Éléments DOM ── */ const slides = wrapper.querySelectorAll('.km-slide'); const dots = wrapper.querySelectorAll('.km-dot'); const counter = wrapper.querySelector('.km-counter__current'); const progressFill = wrapper.querySelector('.km-progress-fill'); const nextTitle = wrapper.querySelector(`#${id}-next-title`); const btnPrev = wrapper.querySelector('.km-nav--prev'); const btnNext = wrapper.querySelector('.km-nav--next'); const btnPlay = wrapper.querySelector('.km-play-pause');if (!slides.length) return;/* ── État ── */ let current = 0; let isPlaying = auto; let overlapTimer = null; // Timer OVERLAP_MS → déclenche le crossfade let cleanTimer = null; // Timer TRANSITION_MS → nettoie is-leaving/* ── Utilitaires ── */ const pad = n => String(n).padStart(2, '0'); const mod = (n, m) => ((n % m) + m) % m; const getData = i => slidesData[i] || {};/* ─────────────────────────────────────────────────────── MISE À JOUR UI Compteur · Dots · Titre SUIVANT · Couleur accent ─────────────────────────────────────────────────────── */ function updateUI(index) {// Compteur numérique if (counter) counter.textContent = pad(index + 1);// Dots : classe active + aria dots.forEach((d, i) => { d.classList.toggle('is-active', i === index); d.setAttribute('aria-selected', i === index ? 'true' : 'false'); });// Titre SUIVANT : micro fade-out → mise à jour → fade-in const nextIdx = mod(index + 1, total); if (nextTitle) { nextTitle.classList.add('is-updating'); setTimeout(() => { nextTitle.textContent = getData(nextIdx).titre || ''; nextTitle.classList.remove('is-updating'); }, 300); }// Couleur accent : propagée à tous les éléments via var(--accent) const accent = getData(index).couleur || '#E63946'; wrapper.style.setProperty('--accent', accent); }/* ─────────────────────────────────────────────────────── BARRE DE PROGRESSION Se remplit sur DISPLAY_MS (5000ms) en continu. ─────────────────────────────────────────────────────── */ function startProgress() { if (!progressFill) return; progressFill.style.transition = 'none'; progressFill.style.width = '0%'; void progressFill.offsetWidth; // Force reflow progressFill.style.transition = `width ${DISPLAY_MS}ms linear`; progressFill.style.width = '100%'; }function stopProgress() { if (!progressFill) return; const computed = parseFloat(getComputedStyle(progressFill).width); const parent = progressFill.parentElement; const pct = parent ? (computed / parent.offsetWidth) * 100 : 0; progressFill.style.transition = 'none'; progressFill.style.width = pct + '%'; }function resetProgress() { if (!progressFill) return; progressFill.style.transition = 'none'; progressFill.style.width = '0%'; }/* ─────────────────────────────────────────────────────── CROSSFADE — cœur de la transition ─────────────────────────────────────────────────────── Appelé à t = OVERLAP_MS (3800ms) après le début d'affichage. • Slide sortant → is-leaving : opacity 1→0 sur 1200ms • Slide entrant → is-active : opacity 0→1 sur 1200ms Ken Burns scale(1→1.08) sur 5000ms ─────────────────────────────────────────────────────── */ function crossfadeTo(nextIndex) { const prev = current; current = mod(nextIndex, total);const slideOut = slides[prev]; const slideIn = slides[current];// Slide sortant : amorce le fondu sortant CSS slideOut.classList.remove('is-active'); slideOut.classList.add('is-leaving'); slideOut.setAttribute('aria-hidden', 'true');// Slide entrant : amorce le fondu entrant + Ken Burns CSS slideIn.classList.add('is-active'); slideIn.setAttribute('aria-hidden', 'false');// Mise à jour interface updateUI(current);// Nettoyage du slide sortant après fin du crossfade clearTimeout(cleanTimer); cleanTimer = setTimeout(() => { slideOut.classList.remove('is-leaving'); }, TRANSITION_MS + 50); // +50ms de marge de sécurité// Planifier le prochain crossfade si autoplay actif if (isPlaying) scheduleNext(); }/* ─────────────────────────────────────────────────────── AUTOPLAY — timer précis OVERLAP ─────────────────────────────────────────────────────── Le crossfade est déclenché à OVERLAP_MS (3800ms) pour que la transition se termine exactement à DISPLAY_MS (5000ms). ─────────────────────────────────────────────────────── */ function scheduleNext() { clearTimeout(overlapTimer); if (!isPlaying) return; overlapTimer = setTimeout(() => { crossfadeTo(current + 1); }, OVERLAP_MS); }function cancelAutoplay() { clearTimeout(overlapTimer); }/* ─────────────────────────────────────────────────────── NAVIGATION MANUELLE Déclenche le crossfade immédiatement, repart sur un cycle complet de DISPLAY_MS. ─────────────────────────────────────────────────────── */ function goTo(index) { const target = mod(index, total); if (target === current) return;cancelAutoplay(); resetProgress(); crossfadeTo(target);if (isPlaying) startProgress(); }const nextSlide = () => goTo(current + 1); const prevSlide = () => goTo(current - 1);/* ─────────────────────────────────────────────────────── LECTURE / PAUSE ─────────────────────────────────────────────────────── */ function play() { isPlaying = true; if (btnPlay) { btnPlay.classList.remove('is-paused'); btnPlay.setAttribute('aria-label', 'Mettre en pause'); } scheduleNext(); startProgress(); }function pause() { isPlaying = false; cancelAutoplay(); if (btnPlay) { btnPlay.classList.add('is-paused'); btnPlay.setAttribute('aria-label', 'Reprendre la lecture'); } stopProgress(); }/* ─────────────────────────────────────────────────────── ÉVÉNEMENTS ─────────────────────────────────────────────────────── */// Flèches if (btnPrev) btnPrev.addEventListener('click', prevSlide); if (btnNext) btnNext.addEventListener('click', nextSlide);// Lecture / Pause if (btnPlay) { btnPlay.addEventListener('click', () => isPlaying ? pause() : play()); }// Points de navigation dots.forEach(dot => { dot.addEventListener('click', () => { const i = parseInt(dot.dataset.goto, 10); if (!isNaN(i) && i !== current) goTo(i); }); });// PAS de pause au survol — comportement intentionnel// Swipe tactile let txStart = 0, tyStart = 0; wrapper.addEventListener('touchstart', e => { txStart = e.touches[0].clientX; tyStart = e.touches[0].clientY; }, { passive: true });wrapper.addEventListener('touchend', e => { const dx = txStart - e.changedTouches[0].clientX; const dy = tyStart - e.changedTouches[0].clientY; if (Math.abs(dx) > Math.abs(dy) && Math.abs(dx) > 40) { dx > 0 ? nextSlide() : prevSlide(); } }, { passive: true });// Navigation clavier wrapper.setAttribute('tabindex', '0'); wrapper.addEventListener('keydown', e => { switch (e.key) { case 'ArrowRight': nextSlide(); break; case 'ArrowLeft': prevSlide(); break; case ' ': e.preventDefault(); isPlaying ? pause() : play(); break; } });/* ─────────────────────────────────────────────────────── INITIALISATION ─────────────────────────────────────────────────────── */ (function init() {// Le slide 0 est déjà is-active dans le HTML (via PHP) if (counter) counter.textContent = pad(1);dots.forEach((d, i) => { d.classList.toggle('is-active', i === 0); d.setAttribute('aria-selected', i === 0 ? 'true' : 'false'); });// Titre SUIVANT : slide index 1 if (nextTitle) { nextTitle.textContent = getData(mod(1, total)).titre || ''; }// Couleur accent initiale wrapper.style.setProperty('--accent', getData(0).couleur || '#E63946');// prefers-reduced-motion → pas d'autoplay if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) { return; }// Démarrage de l'autoplay if (isPlaying) { scheduleNext(); // Premier crossfade à OVERLAP_MS (3800ms) startProgress(); // Barre de progression sur DISPLAY_MS (5000ms) } })(); }/* ───────────────────────────────────────────────────────── BOOTSTRAP — Initialise tous les sliders de la page ───────────────────────────────────────────────────────── */ function boot() { document.querySelectorAll('.km-hero-slider').forEach(initKMSlider); }if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', boot); } else { boot(); }})();) * * CORRECTIONS v11 vs v10 : * 1. Throbber : exclut explicitement #kpm-cta-artiste du listener * (sécurité supplémentaire, target="_blank" suffit déjà). * 2. Aucune autre logique modifiée (rétrocompatible v10). * ════════════════════════════════════════════════════════════════ */ (function () { 'use strict';document.readyState === 'loading' ? document.addEventListener('DOMContentLoaded', init) : init();function init() { injectPageLoader(); initCompactOnScroll(); initProgressBar(); initDynamicColors(); initMegaMenu(); initArtistePageActive(); initActualitesPageActive(); initBurgerMenu(); initThrobberLoader(); }/* ══════════════════════════════════════════════════════════════ UTILITAIRES COULEUR ══════════════════════════════════════════════════════════════ */ function hexToRgb(hex) { var c = (hex || '').replace('#', ''); if (c.length === 3) c = c[0]+c[0]+c[1]+c[1]+c[2]+c[2]; var m = /^([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(c); return m ? { r:parseInt(m[1],16), g:parseInt(m[2],16), b:parseInt(m[3],16) } : null; }function tintLogoImage(img, hexColor) { if (!img || img.tagName !== 'IMG') return; var rgb = hexToRgb(hexColor); if (!rgb) return; if (!img.dataset.originalSrc) img.dataset.originalSrc = img.src; var t = new Image(); t.crossOrigin = 'anonymous'; t.onload = function() { try { var cv = document.createElement('canvas'); cv.width = t.naturalWidth || 100; cv.height = t.naturalHeight || 100; var ctx = cv.getContext('2d'); ctx.drawImage(t,0,0); var id = ctx.getImageData(0,0,cv.width,cv.height), d = id.data; for (var i=0; i10) { var l=(d[i]*.299+d[i+1]*.587+d[i+2]*.114)/255; d[i]=Math.round(rgb.r*l); d[i+1]=Math.round(rgb.g*l); d[i+2]=Math.round(rgb.b*l); } } ctx.putImageData(id,0,0); img.src = cv.toDataURL('image/png'); img.style.filter='none'; } catch(e) { applyLogoFilterFallback(img, hexColor); } }; t.onerror = function() { applyLogoFilterFallback(img, hexColor); }; t.src = img.dataset.originalSrc; }function applyLogoFilterFallback(img, hex) { var rgb = hexToRgb(hex); if (!rgb) { img.style.filter='brightness(0) invert(1)'; return; } var r=rgb.r/255,g=rgb.g/255,b=rgb.b/255, mx=Math.max(r,g,b),mn=Math.min(r,g,b),h=0,s=0,l=(mx+mn)/2; if (mx!==mn){var d=mx-mn; s=l>.5?d/(2-mx-mn):d/(mx+mn); if(mx===r) h=((g-b)/d+(g THRESHOLD; if (sc===isCompact) return; isCompact=sc; header.classList.toggle('kpm-compact',isCompact); applyState(isCompact); }, {passive:true});window.addEventListener('resize', function() { H_NORMAL = window.matchMedia('(max-width:600px)').matches ? 56 : window.matchMedia('(max-width:868px)').matches ? 60 : window.matchMedia('(max-width:1024px)').matches ? 64 : 72; if (!isCompact) applyState(false); }, {passive:true});applyState(false); }/* ══════════════════════════════════════════════════════════════ 2. BARRE DE PROGRESSION ══════════════════════════════════════════════════════════════ */ function initProgressBar() { var bar = document.getElementById('kpm-progress')||document.querySelector('.kpm-progress-bar'); if (!bar) return; window.addEventListener('scroll', function() { var s=document.documentElement.scrollTop||document.body.scrollTop; var t=document.documentElement.scrollHeight-document.documentElement.clientHeight; bar.style.width = t>0 ? (s/t*100)+'%' : '0%'; }, {passive:true}); }/* ══════════════════════════════════════════════════════════════ 3. COULEURS DYNAMIQUES ══════════════════════════════════════════════════════════════ */ function initDynamicColors() { var menuLinks = document.querySelectorAll('.kpm-menu > li > a[data-color]'); var logo = document.getElementById('kpm-logo-svg')||document.getElementById('kpm-logo-text'); var bar = document.getElementById('kpm-progress')||document.querySelector('.kpm-progress-bar'); if (!menuLinks.length) return;var activeLink = null; var initItem = document.querySelector('.kpm-menu > li.current-menu-item > a[data-color]'); if (initItem && !document.body.classList.contains('single-nos-artistes') && !document.body.classList.contains('kpm-is-actualites')) { activeLink = initItem; colorItem(initItem, initItem.getAttribute('data-color')||'#6621c3'); applyLogoColor(logo, initItem.getAttribute('data-logo-color')||initItem.getAttribute('data-color')||'#6621c3'); if (bar) bar.style.background = initItem.getAttribute('data-color')||'#6621c3'; }menuLinks.forEach(function(link) { var mc = link.getAttribute('data-color')||'#6621c3'; var lc = link.getAttribute('data-logo-color')||mc; var li = link.closest('li');link.addEventListener('mouseenter', function() { colorItem(link,mc); }); link.addEventListener('mouseleave', function() { var act = (link===activeLink)||(li&&(li.classList.contains('current-menu-item')||li.classList.contains('nos-artistes-actif'))); act ? colorItem(link,mc) : resetItem(link); }); link.addEventListener('click', function() { if (link.classList.contains('kpm-menu-trigger')) return; menuLinks.forEach(function(l2){ var l2li=l2.closest('li'); if(l2li) l2li.classList.remove('current-menu-item'); if(l2!==link) resetItem(l2); }); li&&li.classList.add('current-menu-item'); activeLink=link; colorItem(link,mc); applyLogoColor(logo,lc); if (bar) bar.style.background=mc; }); }); }/* ══════════════════════════════════════════════════════════════ 4. PAGES ARTISTE — item "Nos Artistes" actif ══════════════════════════════════════════════════════════════ */ function initArtistePageActive() { if (!document.body.classList.contains('single-nos-artistes')) return; var trigger = document.querySelector('.kpm-menu-trigger'); var logo = document.getElementById('kpm-logo-svg')||document.getElementById('kpm-logo-text'); var bar = document.getElementById('kpm-progress')||document.querySelector('.kpm-progress-bar'); if (!trigger) return; var mc=trigger.getAttribute('data-color')||'#c0392b'; var lc=trigger.getAttribute('data-logo-color')||mc; var li=trigger.closest('li'); if (li) { li.classList.add('nos-artistes-actif','current-menu-item'); } colorItem(trigger,mc); applyLogoColor(logo,lc); if (bar) bar.style.background=mc; }/* ══════════════════════════════════════════════════════════════ 5. PAGES ACTUALITÉS — item "Actualités" actif ══════════════════════════════════════════════════════════════ */ function initActualitesPageActive() { if (!document.body.classList.contains('kpm-is-actualites')) return;var logo = document.getElementById('kpm-logo-svg')||document.getElementById('kpm-logo-text'); var bar = document.getElementById('kpm-progress')||document.querySelector('.kpm-progress-bar');var actuLink = null; var menuLinks = document.querySelectorAll('.kpm-menu > li > a[data-color]'); menuLinks.forEach(function(link) { var label = (link.querySelector('.menu-label')||link).textContent.toLowerCase().trim(); if (label.indexOf('actu') !== -1 || label.indexOf('news') !== -1 || label.indexOf('blog') !== -1) { actuLink = link; } });if (!actuLink) return;var mc = actuLink.getAttribute('data-color') || '#6621c3'; var lc = actuLink.getAttribute('data-logo-color') || mc; var li = actuLink.closest('li');if (li) li.classList.add('current-menu-item', 'kpm-actualites-actif'); colorItem(actuLink, mc); applyLogoColor(logo, lc); if (bar) bar.style.background = mc; }/* ══════════════════════════════════════════════════════════════ 6. MÉGA MENU ══════════════════════════════════════════════════════════════ */ function initMegaMenu() { var trigger = document.querySelector('.kpm-menu-trigger'); var dropdown = document.querySelector('.has-megamenu .aa-dropdown'); var btnBack = dropdown ? dropdown.querySelector('.aa-dropdown-back') : null; var logo = document.getElementById('kpm-logo-svg')||document.getElementById('kpm-logo-text'); var bar = document.getElementById('kpm-progress')||document.querySelector('.kpm-progress-bar'); if (!trigger || !dropdown) return;var isOpen = false; var mc = trigger.getAttribute('data-color') || '#6621c3'; var lc = trigger.getAttribute('data-logo-color') || mc; var li = trigger.closest('li');function open() { isOpen = true; dropdown.classList.add('is-open'); dropdown.setAttribute('aria-hidden','false'); trigger.setAttribute('aria-expanded','true'); colorItem(trigger,mc); applyLogoColor(logo,lc); if (bar) bar.style.background = mc; if (!isMobileNav()) { dropdown.querySelectorAll('.aa-drop-card').forEach(function(c,i){ c.style.animationDelay = (i*.04)+'s'; }); } }function close() { isOpen = false; dropdown.classList.remove('is-open'); dropdown.setAttribute('aria-hidden','true'); trigger.setAttribute('aria-expanded','false'); if (!document.body.classList.contains('single-nos-artistes') && li && !li.classList.contains('current-menu-item')) { resetItem(trigger); } }trigger.addEventListener('click', function(e) { e.preventDefault(); e.stopPropagation(); isOpen ? close() : open(); });if (btnBack) { btnBack.addEventListener('click', function(e) { e.stopPropagation(); close(); trigger.focus(); }); }document.addEventListener('click', function(e) { if (!isOpen || isMobileNav()) return; if (!dropdown.contains(e.target) && !trigger.contains(e.target)) close(); });document.addEventListener('keydown', function(e) { if (e.key==='Escape' && isOpen) close(); });dropdown.addEventListener('wheel', function(e) { if (isMobileNav()) return; var grid = dropdown.querySelector('.aa-dropdown-grid'); if (grid && !dropdown.classList.contains('aa-dropdown-grid--wrap')) { e.preventDefault(); grid.scrollLeft += e.deltaY; } }, {passive:false}); }/* ══════════════════════════════════════════════════════════════ 7. BURGER MENU ══════════════════════════════════════════════════════════════ */ function initBurgerMenu() { var burger = document.getElementById('kpm-burger'); var nav = document.getElementById('kpm-nav'); var overlay = document.getElementById('kpm-overlay'); var dropdown = document.querySelector('.has-megamenu .aa-dropdown'); if (!burger || !nav || !overlay) return; var isOpen = false;function openNav() { isOpen = true; burger.classList.add('is-active'); burger.setAttribute('aria-expanded','true'); nav.classList.add('is-active'); overlay.classList.add('is-active'); overlay.setAttribute('aria-hidden','false'); document.body.style.overflow = 'hidden'; }function closeNav() { isOpen = false; if (dropdown && dropdown.classList.contains('is-open')) { dropdown.classList.remove('is-open'); dropdown.setAttribute('aria-hidden','true'); var trig = document.querySelector('.kpm-menu-trigger'); if (trig) trig.setAttribute('aria-expanded','false'); } burger.classList.remove('is-active'); burger.setAttribute('aria-expanded','false'); nav.classList.remove('is-active'); overlay.classList.remove('is-active'); overlay.setAttribute('aria-hidden','true'); document.body.style.overflow = ''; }burger.addEventListener('click', function() { isOpen ? closeNav() : openNav(); }); overlay.addEventListener('click', closeNav);nav.querySelectorAll('.kpm-menu a').forEach(function(l) { l.addEventListener('click', function() { if (l.classList.contains('kpm-menu-trigger')) return; if (isOpen) setTimeout(closeNav, 250); }); });document.addEventListener('keydown', function(e) { if (e.key==='Escape' && isOpen) closeNav(); }); }/* ══════════════════════════════════════════════════════════════ 8. THROBBER LOADER ══════════════════════════════════════════════════════════════ v11 : exclut #kpm-cta-artiste (target="_blank" suffit déjà, mais on sécurise avec un check explicite sur l'id). ══════════════════════════════════════════════════════════════ */ function initThrobberLoader() { var logo = document.getElementById('kpm-logo-svg')||document.getElementById('kpm-logo-text'); var overlay = document.getElementById('kpm-page-loader'); var iconEl = document.getElementById('kpm-loader-icon');if (logo && logo.tagName==='IMG' && iconEl && iconEl.tagName==='IMG') { iconEl.src = logo.dataset.originalSrc || logo.src; }var isLoading=false, kickT=null, stopT=null, safeT=null;function clearClasses(el) { if (!el) return; el.classList.remove('kpm-throbber-kick','kpm-throbbing','kpm-throbber-stop'); }function startThrobber() { if (isLoading) return; isLoading=true; clearTimeout(kickT); clearTimeout(stopT); clearTimeout(safeT); overlay && overlay.classList.add('kpm-loader-active'); overlay && overlay.classList.remove('kpm-loader-exit'); [logo, iconEl].forEach(function(el){ clearClasses(el); el&&el.classList.add('kpm-throbber-kick'); }); kickT = setTimeout(function() { if (!isLoading) return; [logo, iconEl].forEach(function(el){ clearClasses(el); el&&el.classList.add('kpm-throbbing'); }); }, 600); safeT = setTimeout(stopThrobber, 8000); }function stopThrobber() { if (!isLoading) return; isLoading=false; clearTimeout(kickT); clearTimeout(safeT); [logo, iconEl].forEach(function(el){ clearClasses(el); el&&el.classList.add('kpm-throbber-stop'); }); if (overlay) { overlay.classList.remove('kpm-loader-active'); overlay.classList.add('kpm-loader-exit'); } stopT = setTimeout(function() { [logo, iconEl].forEach(function(el){ clearClasses(el); }); overlay&&overlay.classList.remove('kpm-loader-exit'); }, 600); }document.querySelectorAll('.kpm-menu a').forEach(function(link) { link.addEventListener('click', function() { if (link.classList.contains('kpm-menu-trigger')) return; if (link.target==='_blank') return; /* v11 : sécurité supplémentaire — ne jamais throbber sur le CTA artiste */ if (link.id === 'kpm-cta-artiste') return; startThrobber(); window.addEventListener('beforeunload', stopThrobber, {once:true}); }); });window.addEventListener('load', function() { if (isLoading) stopThrobber(); }); window.addEventListener('pageshow', function() { if (isLoading) stopThrobber(); }); window.addEventListener('popstate', function() { if (isLoading) stopThrobber(); }); }})();) * * Comportement style Reach Records : * → Clic "Nos Artistes" = dropdown s'ouvre SOUS le header * → La page en dessous reste visible * → L'URL passe à /nos-artistes/ via pushState * → Clic en dehors / Échap / ✕ = ferme * → Clic sur une image = navigue vers l'artiste * ================================================================ */ (function () { 'use strict';document.readyState === 'loading' ? document.addEventListener('DOMContentLoaded', init) : init();function init() { var trigger = document.querySelector('.rr-menu-trigger, .aa-nav-trigger'); var dropdown = document.getElementById('aa-dropdown');if (!trigger || !dropdown) return;var btnClose = dropdown.querySelector('.aa-dropdown-close'); var archiveUrl = trigger.getAttribute('href') || '/nos-artistes/'; var urlOrigin = window.location.href; var isOpen = false; var histPushed = false;/* ── Hauteur du header → positionne le dropdown ── */ function updateHeaderHeight() { var header = document.querySelector( '#masthead, .main-header-bar, .ast-primary-header-bar, .site-header, header' ); if (header) { var h = Math.round(header.getBoundingClientRect().height); document.documentElement.style.setProperty('--rr-header-h', h + 'px'); dropdown.style.top = h + 'px'; } } updateHeaderHeight(); window.addEventListener('resize', updateHeaderHeight, { passive: true });/* ── OUVRIR ── */ function open() { if (isOpen) return; isOpen = true;dropdown.classList.add('is-open'); dropdown.setAttribute('aria-hidden', 'false'); trigger.classList.add('is-active'); trigger.setAttribute('aria-expanded', 'true');/* URL → /nos-artistes/ sans rechargement */ if (window.history && window.history.pushState) { urlOrigin = window.location.href; window.history.pushState({ aaMenu: true }, 'Nos Artistes', archiveUrl); histPushed = true; }/* Animation cascade des cartes */ var cartes = dropdown.querySelectorAll('.aa-drop-card'); cartes.forEach(function (c, i) { c.classList.remove('rr-animate'); c.style.animationDelay = (i * 0.04) + 's'; void c.offsetWidth; // force reflow c.classList.add('rr-animate'); });/* Focus accessibilité */ var first = dropdown.querySelector('.aa-drop-card'); if (first) setTimeout(function () { first.focus(); }, 60); }/* ── FERMER ── */ function close(opts) { opts = opts || {}; if (!isOpen) return; isOpen = false;dropdown.classList.remove('is-open'); dropdown.setAttribute('aria-hidden', 'true'); trigger.classList.remove('is-active'); trigger.setAttribute('aria-expanded', 'false');/* Remet l'URL d'origine */ if (!opts.noHistory && histPushed && window.history && window.history.pushState) { window.history.pushState({ aaMenu: false }, document.title, urlOrigin); histPushed = false; }/* Reset animations */ dropdown.querySelectorAll('.aa-drop-card').forEach(function (c) { c.classList.remove('rr-animate'); c.style.animationDelay = ''; });trigger.focus(); }/* ── Clic sur le trigger ── */ trigger.addEventListener('click', function (e) { e.preventDefault(); e.stopPropagation();if (isOpen) { /* 2e clic → naviguer vers la page archive */ close({ noHistory: true }); window.location.href = archiveUrl; } else { open(); } });/* ── Bouton ✕ ── */ if (btnClose) { btnClose.addEventListener('click', function (e) { e.stopPropagation(); close(); }); }/* ── Clic en dehors ── */ document.addEventListener('click', function (e) { if (!isOpen) return; if (!dropdown.contains(e.target) && !trigger.contains(e.target)) close(); });/* ── Touche Échap ── */ document.addEventListener('keydown', function (e) { if (e.key === 'Escape' && isOpen) close(); });/* ── Navigation clavier dans le dropdown ── */ dropdown.addEventListener('keydown', function (e) { var liens = Array.from(dropdown.querySelectorAll('.aa-drop-card')); var idx = liens.indexOf(document.activeElement); if (idx === -1) return; var next; switch (e.key) { case 'ArrowRight': case 'ArrowDown': next = liens[(idx + 1) % liens.length]; break; case 'ArrowLeft': case 'ArrowUp': next = liens[(idx - 1 + liens.length) % liens.length]; break; case 'Home': next = liens[0]; break; case 'End': next = liens[liens.length - 1]; break; default: return; } if (next) { e.preventDefault(); next.focus(); } });/* ── Bouton Précédent du navigateur ── */ window.addEventListener('popstate', function () { if (isOpen) { isOpen = false; dropdown.classList.remove('is-open'); dropdown.setAttribute('aria-hidden', 'true'); trigger.classList.remove('is-active'); trigger.setAttribute('aria-expanded', 'false'); histPushed = false; dropdown.querySelectorAll('.aa-drop-card').forEach(function (c) { c.classList.remove('rr-animate'); }); } });/* ── Scroll horizontal dans le dropdown (tactile) ── */ dropdown.addEventListener('wheel', function (e) { var grid = dropdown.querySelector('.aa-dropdown-grid'); if (grid && !dropdown.classList.contains('aa-dropdown-grid--wrap')) { e.preventDefault(); grid.scrollLeft += e.deltaY; } }, { passive: false }); }})();