/* Alliance Boréale — champ d'étoiles + constellation. Vanilla JS, aucune dépendance. Désactivé si l'utilisateur préfère moins d'animation. La métaphore : chaque artisan est une étoile ; reliés, ils forment la constellation. */ (function () { "use strict"; /* ---- Menu mobile ---- */ var nav = document.querySelector(".site-nav"); var toggle = document.querySelector(".nav-toggle"); if (nav && toggle) { toggle.addEventListener("click", function () { var open = nav.classList.toggle("open"); toggle.setAttribute("aria-expanded", open ? "true" : "false"); }); } /* ---- Constellation ---- */ var canvas = document.getElementById("constellation"); if (!canvas) return; var reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches; var ctx = canvas.getContext("2d"); var stars = []; var w = 0, h = 0, dpr = Math.min(window.devicePixelRatio || 1, 2); var LINK_DIST = 130; function resize() { w = canvas.clientWidth; h = canvas.clientHeight; canvas.width = w * dpr; canvas.height = h * dpr; ctx.setTransform(dpr, 0, 0, dpr, 0, 0); seed(); } function seed() { var count = Math.round((w * h) / 14000); count = Math.max(40, Math.min(160, count)); stars = []; for (var i = 0; i < count; i++) { stars.push({ x: Math.random() * w, y: Math.random() * h, r: Math.random() * 1.3 + 0.4, vx: (Math.random() - 0.5) * 0.12, vy: (Math.random() - 0.5) * 0.12, tw: Math.random() * Math.PI * 2 }); } } function draw() { ctx.clearRect(0, 0, w, h); // liens de constellation for (var i = 0; i < stars.length; i++) { for (var j = i + 1; j < stars.length; j++) { var dx = stars[i].x - stars[j].x; var dy = stars[i].y - stars[j].y; var d = Math.sqrt(dx * dx + dy * dy); if (d < LINK_DIST) { var a = (1 - d / LINK_DIST) * 0.22; ctx.strokeStyle = "rgba(120, 200, 255," + a + ")"; ctx.lineWidth = 1; ctx.beginPath(); ctx.moveTo(stars[i].x, stars[i].y); ctx.lineTo(stars[j].x, stars[j].y); ctx.stroke(); } } } // étoiles for (var k = 0; k < stars.length; k++) { var s = stars[k]; s.tw += 0.02; var glow = 0.6 + Math.sin(s.tw) * 0.4; ctx.beginPath(); ctx.arc(s.x, s.y, s.r, 0, Math.PI * 2); ctx.fillStyle = "rgba(255,255,255," + glow + ")"; ctx.shadowColor = "rgba(160,220,255,0.9)"; ctx.shadowBlur = 6; ctx.fill(); ctx.shadowBlur = 0; if (!reduce) { s.x += s.vx; s.y += s.vy; if (s.x < 0 || s.x > w) s.vx *= -1; if (s.y < 0 || s.y > h) s.vy *= -1; } } if (!reduce) requestAnimationFrame(draw); } window.addEventListener("resize", resize); resize(); draw(); // un rendu statique si reduce, sinon animé })();