Blessing K2 – Rappeur Gospel Ivoirien | Biographie
Aller au contenu
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 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 comprendre , analyser 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
Retrouvez Blessing-K2 sur
)
* ============================================================
*
* 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 });
}})();