Observatoire CFO · MGP
Orbite de carrière de Marine
Visualisation dynamique du Modèle Gravitationnel des Parcours. Cette page accueille la nouvelle expérience MGP de l’Observatoire CFO.
Portrait MGP
Marine
Trajectoire & impulsions
Évolution de la masse ; les marqueurs signalent des ruptures statistiques, sans inférer de causalité.
Radar des forces
Composition documentée de la dynamique actuelle.
Matrice Masse × Momentum
Position relative de l’artiste dans le panel CFO.
Carte gravitationnelle
Lecture spatiale du panel : les masses les plus fortes sont rapprochées du centre.
.cfo-mgp-receptacle{max-width:1180px;margin:0 auto;font-family:Open Sans,Arial,sans-serif;color:#263746}.cfo-mgp-receptacle__intro{background:#fff;border:1px solid #dbe4e8;border-top:3px solid #a68150;border-radius:16px;box-shadow:0 7px 20px rgba(16,47,67,.07);padding:24px 26px;margin-bottom:16px}.cfo-mgp-receptacle__kicker{margin:0 0 6px;color:#a68150;font-size:.68rem;font-weight:800;letter-spacing:.1em;text-transform:uppercase}.cfo-mgp-receptacle__intro h1{margin:0 0 8px!important;color:#102f43!important;font-size:1.55rem!important}.cfo-mgp-receptacle__intro p:last-child{margin:0;color:#75848c;font-size:.82rem}.cfo-mgp-stage{min-height:700px;background:#f4f7f8;border:1px solid #dbe4e8;border-radius:18px;box-shadow:0 8px 24px rgba(16,47,67,.07);padding:18px}.cfo-mgp-stage__placeholder{min-height:660px;border:1px dashed #c9d4d9;border-radius:14px;background:#fff;display:flex;align-items:center;justify-content:center;flex-direction:column;color:#75848c}.cfo-mgp-stage__placeholder strong{color:#102f43;font-size:1rem;margin-bottom:5px}
.cfo-mgp__block–trajectory{position:relative!important;overflow:visible!important}
.cfo-mgp__block–trajectory .cfo-mgp-event-tooltip{position:absolute;z-index:80;min-width:220px;max-width:310px;padding:12px 14px;background:rgba(255,255,255,.98);border:1px solid #dbe4e8;border-radius:12px;box-shadow:0 10px 28px rgba(16,47,67,.16);color:#263746;font-family:Open Sans,Arial,sans-serif;pointer-events:none;opacity:0;transform:translateY(5px);transition:opacity .12s ease,transform .12s ease}
.cfo-mgp__block–trajectory .cfo-mgp-event-tooltip.is-visible{opacity:1;transform:translateY(0)}
.cfo-mgp-event-tooltip__date{display:block;color:#102f43;font-size:.74rem;font-weight:800;margin-bottom:6px}
.cfo-mgp-event-tooltip__type{display:inline-flex;align-items:center;gap:5px;border-radius:999px;padding:4px 8px;font-size:.58rem;font-weight:800;letter-spacing:.04em;text-transform:uppercase;margin-bottom:7px}
.cfo-mgp-event-tooltip__type.is-positive{background:#eaf5ee;color:#25734f}.cfo-mgp-event-tooltip__type.is-negative{background:#faecec;color:#a7242b}.cfo-mgp-event-tooltip__type.is-neutral{background:#eef3f5;color:#526771}
.cfo-mgp-event-tooltip__title{display:block;color:#102f43;font-size:.72rem;font-weight:800;line-height:1.3;margin-bottom:4px}
.cfo-mgp-event-tooltip__meta{display:block;color:#75848c;font-size:.62rem;line-height:1.4}.cfo-mgp-event-tooltip__more{display:block;margin-top:6px;padding-top:6px;border-top:1px solid #edf1f3;color:#667982;font-size:.59rem}
.cfo-mgp__block–trajectory svg .cfo-mgp-event-active{filter:drop-shadow(0 0 5px rgba(16,47,67,.32));transform:scale(1.18);transform-box:fill-box;transform-origin:center;transition:transform .1s ease}
.cfo-mgp__block–trajectory svg .cfo-mgp-event-hit{fill:transparent!important;stroke:transparent!important;cursor:pointer;pointer-events:all}
(function(){const root=document.querySelector(‘.cfo-mgp__block–trajectory’);if(!root)return;const fmt=d=>{try{return new Intl.DateTimeFormat(‘fr-FR’,{day:’2-digit’,month:’long’,year:’numeric’}).format(new Date(String(d).slice(0,10)+’T00:00:00′))}catch(_){return d||’—’}};const esc=s=>String(s?? »).replace(/[& »‘]/g,c=>({‘&’:’&’, »:’>’,' »‘:’"’, »‘ »:’'’}[c]));const tip=document.createElement(‘div’);tip.className=’cfo-mgp-event-tooltip’;root.appendChild(tip);const documentedEvents=[{date:’2026-06-14′,title:’RTL2 Pop-Rock Live · spéciale ODP’,kind:’Radio / live’,url:’https://radio-podcast.fr/podcast/rtl2/2122/le-drive-rtl2/eric-jean-jean’},{date:’2026-07-12′,title:’Marine · Les Nuits d’Istres’,kind:’Concert’,url:’https://www.istres.fr/index.php?cHash=558c63558e2b3d32ae3090303356b31b&id=362&tx_news_pi1%5Baction%5D=detail&tx_news_pi1%5Bcontroller%5D=News&tx_news_pi1%5Bnews%5D=11882′},{date:’2026-07-13′,title:’NRJ Music Tour · Toulouse’,kind:’Concert / média’,url:’https://www.nrj.fr/concerts/nrj-music-tour-toulouse-2026-71366682′},{date:’2026-07-13′,title:’Duo surprise Marine × Pierre de Maere’,kind:’Live / collaboration’,url:’https://www.nrj.fr/artistes/marine/actus/pierre-de-maere-et-marine-duo-surprise-au-nrj-music-tour-a-toulouse-71366850′},{date:’2026-07-20′,title:’Retour média · NRJ Music Tour Toulouse’,kind:’Média’,url:’https://www.nrj.fr/actus/nrj-music-tour/retour-en-images-sur-le-nrj-music-tour-de-toulouse-2026-71366868′}];let impulses=[];fetch(‘/wp-json/cfo-mgp/v1/snapshot?artist=marine&days=365′,{credentials:’same-origin’}).then(r=>r.json()).then(d=>{impulses=(Array.isArray(d.impulses)?d.impulses:[]).slice().sort((a,b)=>String(a.date).localeCompare(String(b.date)));bind()}).catch(()=>bind());function polarity(im){const dir=String(im?.direction|| »).toLowerCase();const mag=Number(im?.magnitude||0);if(dir.includes(‘neg’)||mag0)return[‘Positif’,’is-positive’];return[‘Neutre’,’is-neutral’]}function show(ev,im,marker){const same=impulses.filter(x=>String(x.date)===String(im?.date));const [lab,cls]=polarity(im);const desc=im?.description||im?.label||im?.event||’Rupture statistique détectée sur la trajectoire.’;const mag=Number(im?.magnitude);const idate=new Date(String(im?.date).slice(0,10)+’T00:00:00′);const near=documentedEvents.map(e=>{const d=Math.round((new Date(e.date+’T00:00:00′)-idate)/86400000);return Object.assign({},e,{delta:d,abs:Math.abs(d)})}).filter(e=>e.absa.abs-b.abs)[0];const assoc=near?’Événement associé
‘+esc(near.title)+’ · ‘+esc(near.kind)+’ · ‘+(near.delta===0?’même jour’:(near.delta>0?’J+’+near.delta:’J’+near.delta))+(near.url?’ · source ↗‘: »)+’
Association temporelle · causalité non établie‘:’Aucun événement documenté associé dans une fenêtre de ±3 jours.‘;tip.innerHTML=’‘+esc(fmt(im?.date))+’Signal ‘+lab+’‘+esc(desc)+’‘+assoc+(same.length>1?’‘+same.length+’ événements détectés à cette date‘: »);marker.classList.add(‘cfo-mgp-event-active’);tip.classList.add(‘is-visible’);move(ev)}function hide(marker){marker.classList.remove(‘cfo-mgp-event-active’);tip.classList.remove(‘is-visible’)}function move(ev){const rr=root.getBoundingClientRect();let x=ev.clientX-rr.left+14,y=ev.clientY-rr.top+14;const w=tip.offsetWidth||260,h=tip.offsetHeight||120;if(x+w>rr.width-8)x=Math.max(8,ev.clientX-rr.left-w-14);if(y+h>rr.height-8)y=Math.max(8,ev.clientY-rr.top-h-14);tip.style.left=x+’px’;tip.style.top=y+’px’}function bind(){const chart=root.querySelector(‘[data-chart= »trajectory »]’);if(!chart)return retry();const svg=chart.querySelector(‘svg’);if(!svg)return retry();let circles=[…svg.querySelectorAll(‘circle’)].filter(c=>{const r=parseFloat(c.getAttribute(‘r’)||’0′);const fill=(c.getAttribute(‘fill’)||getComputedStyle(c).fill|| »).toLowerCase();return r>=5&&!fill.includes(‘255, 255, 255’)&&!fill.includes(‘#fff’)&&!fill.includes(‘white’)});circles.sort((a,b)=>(parseFloat(a.getAttribute(‘cx’))||a.getBoundingClientRect().left)-(parseFloat(b.getAttribute(‘cx’))||b.getBoundingClientRect().left));if(impulses.length&&circles.length>impulses.length)circles=circles.slice(0,impulses.length);circles.forEach((marker,i)=>{if(marker.dataset.cfoHoverBound)return;marker.dataset.cfoHoverBound=’1′;const group=marker.closest(‘g’);const nativeTitle=marker.querySelector(‘title’)||(group?group.querySelector(‘title’):null)||(marker.parentElement?marker.parentElement.querySelector(‘title’):null);const nativeText=nativeTitle?nativeTitle.textContent: »;const dm=nativeText.match(/(20\d{2}-\d{2}-\d{2})/);const nativeDate=dm?dm[1]: »;const fill=(marker.getAttribute(‘fill’)||getComputedStyle(marker).fill|| »).toLowerCase();const rgb=fill.match(/rgba?\((\d+)[, ]+(\d+)[, ]+(\d+)/i);const rr=rgb?+rgb[1]:0,gg=rgb?+rgb[2]:0,bb=rgb?+rgb[3]:0;const isRed=rr>gg*1.15&&rr>bb*1.15;const isGreen=gg>rr*1.05&&gg>bb*.9;let im=nativeDate&&impulses.find(x=>String(x.date)===nativeDate);if(!im){const pool=isRed?impulses.filter(x=>String(x.direction|| »).toLowerCase().includes(‘neg’)):isGreen?impulses.filter(x=>String(x.direction|| »).toLowerCase().includes(‘pos’)):impulses;im=pool[Math.min(i,pool.length-1)]||impulses[i]}im=im||{date:nativeDate,magnitude:null,direction:isRed?’negative’:(isGreen?’positive’: »),description:’Événement MGP’};if(nativeTitle)nativeTitle.remove();const hit=marker.cloneNode(false);hit.removeAttribute(‘style’);hit.classList.add(‘cfo-mgp-event-hit’);const r=parseFloat(marker.getAttribute(‘r’)||’6′);hit.setAttribute(‘r’,String(r+10));marker.parentNode.insertBefore(hit,marker.nextSibling);hit.addEventListener(‘pointerenter’,e=>show(e,im,marker));hit.addEventListener(‘pointermove’,move);hit.addEventListener(‘pointerleave’,()=>hide(marker));hit.addEventListener(‘focus’,e=>show(e,im,marker));hit.addEventListener(‘blur’,()=>hide(marker))})}let tries=0;function retry(){if(tries++<80)setTimeout(bind,250)}setTimeout(bind,300)})();