KOPHI’S MUSIC est un label musical indépendant ivoirien, spécialisé dans l’Urban Gospel; un mouvement musical avant-gardiste qui fusionne les codes de la musique urbaine contemporaine avec des messages profondément ancrés dans la foi chrétienne.
Né d’une passion authentique et d’une vision claire, KOPHI’S MUSIC est la division musicale (artistique) de KOPHI’S GROUP SAS. Il incarne une nouvelle génération de producteurs et d’artistes qui revendiquent leur foi sans compromis sur la qualité artistique et l’authenticité urbaine.
Pop Urbaine – accessibilité, modernité et impact immédiat
Notre philosophie :
Une approche label indépendant (Indie) qui privilégie la liberté artistique
Un accompagnement personnalisé, à l’écoute de chaque artiste
Une ambition de production à standard mondial, depuis Abidjan
La conviction profonde que foi et excellence artistique peuvent coexister
La création d’œuvres qui inspirent, élèvent et transcendent les frontières
Notre Histoire et Notre Évolution
L’histoire de KOPHI’S MUSIC est celle d’une évolution organique, portée par la conviction et le travail acharné. Son parcours est un témoignage d’humilité, de persévérance et de croissance.
Notre Évolution
L’aventure commence dans le salon de son fondateur, Jean Philippe KOFFI alias Monsieur Kophi par la création d’un Home Studio baptisé CELS HOUSE.
Loin d’être un simple home studio, CELS HOUSE était un sanctuaire créatif. Son nom, acronyme de « Christ Est La Solution », en était le fondement théologique et visionnaire. Dans ce lieu, la musique était conçue comme un ministère et un témoignage, posant les bases de tout ce qui allait suivre. Cet esprit de mission et d’artisanat demeure notre cœur battant.
La vision grandit et descend littéralement au rez-de-chaussée.
Le home studio évolue pour devenir un studio professionnel situé au rez-de-chaussée de l’immeuble. Cette matérialisation marque un tournant et la naissance officielle de KOPHI’S MUSIC qui commence à produire et à publier ses premières œuvres, dont l’EP « Merci Seigneur » de Monsieur Kophi.
Cette période est marquée par des connexions stratégiques. La rencontre avec le beatmaker Schama Beats, puis avec Mdrick Oninni, n’est pas perçue comme un simple hasard professionnel, mais comme une synergie divine.
Cette synergie mène à la production de l’album « GOAT POUR CHRIST » de Mdrick Oninni, sorti en décembre 2024 dont la réédition est prévu pour 2025.
KOPHI’S MUSIC se structure officiellement en label musical, division de KOPHI’S GROUP, fruit de l’association entre Monsieur Kophi, son épouse, Schama Beats et Mdrick Oninni.
Nos Activités et Services
Chez KOPHI'S MUSIC, nous avons bâti un écosystème artistique complet et structuré, pensé pour accompagner chaque projet musical de sa genèse jusqu'à son rayonnement international. Que vous soyez artiste en quête de signature, producteur à la recherche d'un partenaire créatif, ou simplement un passionné souhaitant enregistrer votre musique dans un cadre professionnel, nous avons une solution taillée pour vous.
Développement et Production d'Artistes
Le cœur battant de KOPHI’S MUSIC, c’est ses artistes. Nous ne nous contentons pas de signer des talents; nous les accompagnons, les façonnons et les propulsons vers leur plein potentiel artistique et spirituel. Chaque artiste
signé chez nous bénéficie d’un suivi individualisé, d’une production musicale aux standards internationaux et d’une stratégie de carrière construite sur le long terme.
Détection & Signature de Talents
Identification d’artistes dont la vision, les valeurs et les objectifs s’alignent avec l’ADN du label
Processus de sélection rigoureux mais bienveillant, basé sur l’authenticité, le potentiel et l’engagement spirituel
Signature dans un cadre contractuel clair, équitable et transparent, respectueux des droits de l’artiste
Sessions d’échanges approfondies pour comprendre la vision de chaque artiste avant tout engagement
Production Musicale Complète
Composition et arrangements musicaux aux standards internationaux, couvrant tous les genres Urban Gospel (Hip-Hop, Afrobeat, Trap, RnB, Soul, Pop)
Direction artistique personnalisée pour affiner l’identité sonore de chaque artiste
Mixage et mastering professionnels pour une qualité sonore compétitive sur toutes les plateformes
Production de clips et contenus visuels en adéquation avec l’univers artistique de l’artiste
Développement de Carrière & Rayonnement
Stratégie de lancement et de promotion multicanale : streaming, réseaux sociaux, médias, radio
Distribution numérique sur toutes les grandes plateformes (Spotify, Apple Music, Boomplay, YouTube Music, Deezer…)
Construction de l’image de marque : identité visuelle, storytelling, communication digitale
Préparation aux performances scéniques : coaching vocal, mise en scène, gestion du trac
Suivi des performances et ajustement de la stratégie en fonction des résultats obtenus
Collaborations Créatives
Chez KOPHI’S MUSIC, nous croyons fermement que la créativité s’épanouit dans la rencontre. C’est pourquoi nous cultivons activement des partenariats artistiques ouverts, sincères et mutuellement enrichissants. Qu’il s’agisse d’un artiste solo, d’un collectif, d’un producteur indépendant ou d’un autre label, nous sommes convaincus que l’Urban Gospel africain grandit plus vite et plus loin lorsque ses acteurs unissent leurs forces.
Co-Productions & Featurings
Collaborations avec des artistes de la scène Urban Gospel locale, panafricaine et internationale
Featurings stratégiques pour maximiser la visibilité des artistes et enrichir le catalogue du label
Co-productions musicales avec des beatmakers et compositeurs partageant notre vision artistique et spirituelle
Compilations thématiques réunissant plusieurs artistes autour d’un message commun fort
Partenariats Stratégiques & Institutionnels
Partenariats avec des labels, maisons de disques et distributeurs africains et internationaux pour élargir notre réseau
Collaborations avec des églises, ministères et organisations chrétiennes pour ancrer notre musique dans les communautés de foi
Partenariats avec des médias spécialisés (radios chrétiennes, webzines musicaux, chaînes YouTube gospel) pour une diffusion ciblée
Collaborations avec des écoles de musique et structures de formation pour soutenir la relève artistique gospel
Événements & Projets Spéciaux
Organisation et participation à des concerts, showcases et festivals Urban Gospel en Côte d’Ivoire et à l’international
Sessions créatives collectives (camps d’écriture, sessions de production groupées) pour stimuler l’innovation artistique
Projets cross-border réunissant des artistes de différents pays d’Afrique francophone autour d’une vision commune
Le studio de KOPHI’S MUSIC est bien plus qu’un simple espace technique; c’est un sanctuaire de la création musicale. Conçu pour répondre aux exigences des productions contemporaines les plus ambitieuses, il est ouvert aussi bien aux artistes du label qu’aux artistes externes, producteurs indépendants et créatifs de tous horizons souhaitant donner vie à leurs projets dans des conditions optimales.
Services Proposés
Sessions d’enregistrement vocal et instrumental encadrées par des ingénieurs du son expérimentés
Production de beats et arrangements musicaux sur mesure selon votre style et votre vision
Mixage professionnel pour un rendu sonore puissant, clair et équilibré
Mastering final aux standards des plateformes de streaming internationales (Spotify, Apple Music, etc.)
Production de voix off, jingles et bandes sonores pour des projets audiovisuels et publicitaires
Accès & Tarification
Réservation de sessions flexibles : à l’heure, à la demi-journée ou à la journée complète
Tarifs adaptés à tous les profils : artistes émergents, producteurs confirmés, structures professionnelles
Forfaits spéciaux pour les projets complets (EP, album, mixtape) avec suivi de bout en bout
Tarifs préférentiels pour les ministères, associations chrétiennes et artistes gospel en développement
Chez KOPHI’S MUSIC, nous ne faisons pas que produire de la musique. Nous bâtissons un mouvement culturel et spirituel ancré dans la jeunesse africaine contemporaine. Notre vision s’articule autour de trois grandes ambitions :
Devenir la référence de l’Urban Gospel en Afrique francophone
Positionner KOPHI’S MUSIC comme le label Urban Gospel numéro 1 en Afrique francophone
Rayonner au-delà des frontières ivoiriennes vers le Sénégal, le Cameroun, le Congo, la France et la diaspora africaine
Être reconnu comme un label de référence mondiale dans la gospel music contemporaine
Créer une musique qui résonne avec la jeunesse
Proposer une musique moderne, authentique et spirituellement riche qui parle à la génération Z et aux milléniaux
Porter un message de foi fort et sans compromis, habillé dans les codes urbains actuels
Briser le cliché selon lequel la musique chrétienne ne peut pas être cool, urbaine et compétitive sur le plan artistique
Bâtir un écosystème durable pour l’Urban Gospel africain
Structurer une industrie musicale gospel professionnelle en Afrique francophone
Accompagner et former la prochaine génération d’artistes et producteurs engagés
Créer des ponts entre l’Afrique, l’Europe et la diaspora à travers la musique
KOPHI'S MUSIC - Un Seul Esprit, une diversité de Don pour un Seul et Même But!
Nous ne construisons pas seulement un label. Nous posons les fondations d'un mouvement.
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 });
}})();