/* womans-day wow-pack — feminine / beauty edition * petals · golden sparkles · 3D torus-knot rose · sparkle cursor trail * soft shimmer (no glitch) · heart confetti · floral ripple * cream/peach/burgundy/gold palette · soft motion, no harsh transitions */ (function () { "use strict"; function ready(fn) { if (document.readyState !== "loading") fn(); else document.addEventListener("DOMContentLoaded", fn); } ready(function () { setTimeout(initAll, 250); }); function initAll() { initGradientMesh(); initScrollProgress(); initSoftGrain(); initPetalShower(); initSparkleField(); init3DRose(); initSparkleCursor(); initMagneticButtons(); initCardShimmer(); initFloralRipple(); initCountUp(); initH1Shimmer(); initFormConfetti(); initFloatingDecor(); } // ========== 1. PETAL SHOWER (full-body slow-falling petals) ========== function initPetalShower() { var c = document.getElementById("wdPetals"); if (!c) { c = document.createElement("canvas"); c.id = "wdPetals"; c.setAttribute("aria-hidden", "true"); document.body.appendChild(c); } var ctx = c.getContext("2d"); var dpr = Math.min(window.devicePixelRatio || 1, 2); var W = 0, H = 0, petals = []; function resize() { W = c.width = window.innerWidth * dpr; H = c.height = window.innerHeight * dpr; c.style.width = window.innerWidth + "px"; c.style.height = window.innerHeight + "px"; } resize(); window.addEventListener("resize", resize); var COLORS = [ "rgba(231, 184, 138, 0.85)", // peach "rgba(212, 163, 115, 0.78)", // gold "rgba(252, 188, 165, 0.85)", // light coral "rgba(245, 195, 175, 0.70)", // soft pink "rgba(161, 62, 138, 0.45)" // burgundy hint ]; var N = window.innerWidth < 768 ? 14 : 26; for (var i = 0; i < N; i++) petals.push(makePetal(true)); function makePetal(initial) { return { x: Math.random() * W, y: initial ? Math.random() * H : -30 * dpr, vx: (Math.random() - 0.5) * 0.4 * dpr, vy: (0.25 + Math.random() * 0.55) * dpr, size: (10 + Math.random() * 16) * dpr, rot: Math.random() * Math.PI * 2, vrot: (Math.random() - 0.5) * 0.025, sway: Math.random() * Math.PI * 2, vsway: 0.008 + Math.random() * 0.015, amp: (15 + Math.random() * 25) * dpr, color: COLORS[Math.floor(Math.random() * COLORS.length)] }; } function drawPetal(p) { ctx.save(); ctx.translate(p.x + Math.sin(p.sway) * p.amp, p.y); ctx.rotate(p.rot); ctx.fillStyle = p.color; ctx.beginPath(); // teardrop / petal shape via two quadratic curves var s = p.size; ctx.moveTo(0, -s * 0.55); ctx.quadraticCurveTo(s * 0.55, -s * 0.15, 0, s * 0.55); ctx.quadraticCurveTo(-s * 0.55, -s * 0.15, 0, -s * 0.55); ctx.fill(); ctx.restore(); } function frame() { ctx.clearRect(0, 0, W, H); for (var i = 0; i < petals.length; i++) { var p = petals[i]; p.x += p.vx; p.y += p.vy; p.rot += p.vrot; p.sway += p.vsway; if (p.y > H + 40 * dpr) petals[i] = makePetal(false); drawPetal(p); } requestAnimationFrame(frame); } frame(); } // ========== 2. GOLDEN SPARKLE FIELD (in hero only, twinkling stars) ========== function initSparkleField() { var c = document.getElementById("wdParticles"); if (!c) return; var ctx = c.getContext("2d"); var dpr = Math.min(window.devicePixelRatio || 1, 2); var W = 0, H = 0, stars = []; function resize() { var r = c.parentElement.getBoundingClientRect(); W = c.width = Math.max(1, Math.floor(r.width * dpr)); H = c.height = Math.max(1, Math.floor(r.height * dpr)); c.style.width = r.width + "px"; c.style.height = r.height + "px"; } resize(); window.addEventListener("resize", resize); var N = window.innerWidth < 768 ? 32 : 70; for (var i = 0; i < N; i++) { stars.push({ x: Math.random() * W, y: Math.random() * H, baseSize: (Math.random() * 1.5 + 0.6) * dpr, phase: Math.random() * Math.PI * 2, speed: 0.015 + Math.random() * 0.04, hue: Math.random() < 0.6 ? "gold" : "rose" }); } var mx = -9999, my = -9999; var hero = c.parentElement; hero.addEventListener("mousemove", function (e) { var r = c.getBoundingClientRect(); mx = (e.clientX - r.left) * dpr; my = (e.clientY - r.top) * dpr; }); hero.addEventListener("mouseleave", function () { mx = -9999; my = -9999; }); function drawStar(x, y, r, color) { ctx.save(); ctx.translate(x, y); ctx.fillStyle = color; // 4-point sparkle ctx.beginPath(); ctx.moveTo(0, -r * 2); ctx.quadraticCurveTo(r * 0.3, -r * 0.3, r * 2, 0); ctx.quadraticCurveTo(r * 0.3, r * 0.3, 0, r * 2); ctx.quadraticCurveTo(-r * 0.3, r * 0.3, -r * 2, 0); ctx.quadraticCurveTo(-r * 0.3, -r * 0.3, 0, -r * 2); ctx.fill(); ctx.restore(); } function frame() { ctx.clearRect(0, 0, W, H); for (var i = 0; i < stars.length; i++) { var s = stars[i]; s.phase += s.speed; var twinkle = Math.abs(Math.sin(s.phase)); var size = s.baseSize * (0.6 + twinkle * 1.4); // proximity boost var dxm = s.x - mx, dym = s.y - my; var dm = Math.sqrt(dxm * dxm + dym * dym); var proximity = dm < 120 * dpr ? (1 - dm / (120 * dpr)) : 0; size *= 1 + proximity * 1.5; var opacity = 0.45 + twinkle * 0.5 + proximity * 0.4; var color = s.hue === "gold" ? "rgba(231, 184, 138, " + Math.min(1, opacity) + ")" : "rgba(207, 117, 142, " + Math.min(1, opacity * 0.85) + ")"; drawStar(s.x, s.y, size, color); } requestAnimationFrame(frame); } frame(); } // ========== 3. 3D TORUS-KNOT ROSE (soft pink/gold wireframe) ========== function init3DRose() { var box = document.getElementById("wdHero3D"); if (!box) return; if (matchMedia("(max-width: 900px)").matches) return; loadThree(function (THREE) { var w = box.clientWidth || 280; var h = box.clientHeight || 280; var scene = new THREE.Scene(); var cam = new THREE.PerspectiveCamera(45, w / h, 0.1, 100); cam.position.z = 4.2; var renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true }); renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, 2)); renderer.setSize(w, h); renderer.setClearColor(0x000000, 0); box.appendChild(renderer.domElement); // Outer torus knot — gold, looks like a swirling ribbon var outer = new THREE.Mesh( new THREE.TorusKnotGeometry(1.0, 0.32, 100, 16, 2, 3), new THREE.MeshBasicMaterial({ color: 0xd4a373, wireframe: true, transparent: true, opacity: 0.62 }) ); scene.add(outer); // Inner — burgundy "heart" var inner = new THREE.Mesh( new THREE.TorusKnotGeometry(0.6, 0.18, 80, 12, 3, 4), new THREE.MeshBasicMaterial({ color: 0xa13e8a, wireframe: true, transparent: true, opacity: 0.55 }) ); scene.add(inner); // Core sparkle — bright peach var core = new THREE.Mesh( new THREE.IcosahedronGeometry(0.28, 0), new THREE.MeshBasicMaterial({ color: 0xe7b88a, wireframe: true, transparent: true, opacity: 0.8 }) ); scene.add(core); var mxN = 0, myN = 0; window.addEventListener("mousemove", function (e) { mxN = (e.clientX / window.innerWidth - 0.5) * 2; myN = (e.clientY / window.innerHeight - 0.5) * 2; }); function loop() { outer.rotation.x += 0.0028 + myN * 0.0015; outer.rotation.y += 0.0042 + mxN * 0.0015; inner.rotation.x -= 0.0048; inner.rotation.y -= 0.0072; core.rotation.x += 0.012; core.rotation.y += 0.014; renderer.render(scene, cam); requestAnimationFrame(loop); } loop(); window.addEventListener("resize", function () { var nw = box.clientWidth, nh = box.clientHeight; if (nw && nh) { cam.aspect = nw / nh; cam.updateProjectionMatrix(); renderer.setSize(nw, nh); } }); }); } function loadThree(cb) { if (window.THREE) { cb(window.THREE); return; } if (window.__wdThreeLoading) { window.__wdThreeQueue.push(cb); return; } window.__wdThreeLoading = true; window.__wdThreeQueue = [cb]; function actuallyLoad() { var s = document.createElement("script"); s.src = "https://unpkg.com/three@0.160.0/build/three.min.js"; s.crossOrigin = "anonymous"; s.async = true; s.onload = function () { window.__wdThreeQueue.forEach(function (fn) { try { fn(window.THREE); } catch (e) {} }); window.__wdThreeQueue = []; }; s.onerror = function () { console.warn("three.js failed to load"); }; document.head.appendChild(s); } function startWhenIdle() { if (window.requestIdleCallback) { requestIdleCallback(actuallyLoad, { timeout: 2500 }); } else { setTimeout(actuallyLoad, 1200); } } if (document.readyState === "complete") startWhenIdle(); else window.addEventListener("load", function () { setTimeout(startWhenIdle, 200); }); } // ========== 4. SPARKLE CURSOR (gold dot + burgundy ring + sparkle trail) ========== function initSparkleCursor() { if (matchMedia("(pointer: coarse)").matches) return; document.body.classList.add("wd-has-cursor"); var dot = document.createElement("div"); dot.className = "wd-cursor wd-cursor--dot"; document.body.appendChild(dot); var ring = document.createElement("div"); ring.className = "wd-cursor wd-cursor--ring"; document.body.appendChild(ring); // Sparkle trail — emit small gold star elements that fade out var lastEmit = 0; var sparkles = []; var x = window.innerWidth / 2, y = window.innerHeight / 2; var rx = x, ry = y; document.addEventListener("mousemove", function (e) { x = e.clientX; y = e.clientY; dot.style.transform = "translate3d(" + (x - 5) + "px," + (y - 5) + "px,0)"; // emit sparkle var now = performance.now(); if (now - lastEmit > 55) { lastEmit = now; emitSparkle(e.clientX + (Math.random() - 0.5) * 8, e.clientY + (Math.random() - 0.5) * 8); } }); function emitSparkle(sx, sy) { var s = document.createElement("div"); s.className = "wd-cursor wd-cursor--sparkle"; s.style.left = sx + "px"; s.style.top = sy + "px"; var color = Math.random() < 0.6 ? "#e7b88a" : "#cf758e"; s.style.background = "radial-gradient(circle," + color + " 0%,transparent 70%)"; document.body.appendChild(s); setTimeout(function () { s.remove(); }, 700); } function loop() { rx += (x - rx) * 0.20; ry += (y - ry) * 0.20; ring.style.transform = "translate3d(" + (rx - 22) + "px," + (ry - 22) + "px,0)"; requestAnimationFrame(loop); } loop(); var hoverSel = "a, button, input, textarea, select, .wd-btn, .wd-quiz__option, .wd-card, .wd-list li, .wd-result__row, .wd-tech-chip, .wd-pill, .wd-svc-card, h1, h2, h3"; document.addEventListener("mouseover", function (e) { if (e.target.closest && e.target.closest(hoverSel)) ring.classList.add("is-hover"); }); document.addEventListener("mouseout", function (e) { if (e.target.closest && e.target.closest(hoverSel)) ring.classList.remove("is-hover"); }); document.addEventListener("mousedown", function () { ring.classList.add("is-down"); }); document.addEventListener("mouseup", function () { ring.classList.remove("is-down"); }); } function initMagneticButtons() { if (matchMedia("(pointer: coarse)").matches) return; document.querySelectorAll(".wd-btn, .wd-quiz__option").forEach(function (btn) { btn.addEventListener("mousemove", function (e) { var r = btn.getBoundingClientRect(); var x = e.clientX - r.left - r.width / 2; var y = e.clientY - r.top - r.height / 2; var force = 0.18; btn.style.setProperty("--mag-x", (x * force).toFixed(2) + "px"); btn.style.setProperty("--mag-y", (y * force).toFixed(2) + "px"); btn.classList.add("is-mag"); }); btn.addEventListener("mouseleave", function () { btn.style.setProperty("--mag-x", "0px"); btn.style.setProperty("--mag-y", "0px"); btn.classList.remove("is-mag"); }); }); } // ========== 5. ANIMATED GRADIENT MESH (cream/peach/gold) ========== function initGradientMesh() { if (document.getElementById("wdMesh")) return; var mesh = document.createElement("div"); mesh.id = "wdMesh"; mesh.setAttribute("aria-hidden", "true"); mesh.innerHTML = ''; document.body.appendChild(mesh); } // ========== 6. CARD SOFT SHIMMER (golden sweep on hover) ========== function initCardShimmer() { var sel = ".wd-card, .wd-quiz, .wd-quiz__option, .wd-result__row, .wd-lead, .wd-pull, .wd-list li, .wd-svc-card, .wd-tech-chip, .wd-pill"; document.querySelectorAll(sel).forEach(function (el) { el.classList.add("wd-shimmer"); el.addEventListener("mousemove", function (e) { var r = el.getBoundingClientRect(); var x = ((e.clientX - r.left) / r.width) * 100; var y = ((e.clientY - r.top) / r.height) * 100; el.style.setProperty("--sx", x + "%"); el.style.setProperty("--sy", y + "%"); }); }); } // ========== 7. FLORAL CLICK RIPPLE (rose burst at click point) ========== function initFloralRipple() { if (matchMedia("(pointer: coarse)").matches) return; document.addEventListener("click", function (e) { if (e.target.closest("input, textarea, select")) return; // outer rose ring var ring = document.createElement("span"); ring.className = "wd-ripple wd-ripple--ring"; ring.style.left = e.clientX + "px"; ring.style.top = e.clientY + "px"; document.body.appendChild(ring); setTimeout(function () { ring.remove(); }, 900); // 5-petal burst for (var i = 0; i < 5; i++) { var p = document.createElement("span"); p.className = "wd-ripple wd-ripple--petal"; var angle = (i / 5) * Math.PI * 2 + Math.random() * 0.6; var dist = 40 + Math.random() * 30; p.style.left = e.clientX + "px"; p.style.top = e.clientY + "px"; p.style.setProperty("--tx", Math.cos(angle) * dist + "px"); p.style.setProperty("--ty", Math.sin(angle) * dist + "px"); p.style.setProperty("--rot", Math.random() * 720 + "deg"); document.body.appendChild(p); setTimeout(function (el) { return function () { el.remove(); }; }(p), 900); } }); } // ========== 8. COUNT-UP ========== function initCountUp() { var els = document.querySelectorAll(".wd-proof__num, [data-count]"); if (!els.length || !("IntersectionObserver" in window)) return; var io = new IntersectionObserver(function (entries) { entries.forEach(function (e) { if (!e.isIntersecting) return; var el = e.target; if (el.dataset.counted) return; var raw = el.dataset.count || el.textContent.trim(); var m = raw.match(/^([+\-]?)(\d[\d\s]*)(.*)$/); if (!m) return; var prefix = m[1] || ""; var num = parseInt(m[2].replace(/\s/g, ""), 10); var suffix = m[3] || ""; if (isNaN(num) || num < 2) return; el.dataset.counted = "1"; var dur = 1500, start = performance.now(); function tick(now) { var p = Math.min(1, (now - start) / dur); var eased = 1 - Math.pow(1 - p, 3); el.textContent = prefix + Math.round(num * eased) + suffix; if (p < 1) requestAnimationFrame(tick); else el.textContent = prefix + num + suffix; } requestAnimationFrame(tick); io.unobserve(el); }); }, { threshold: 0.4 }); els.forEach(function (el) { io.observe(el); }); } // ========== 9. H1 SHIMMER (gradient sweep, no glitch) ========== function initH1Shimmer() { var h1 = document.querySelector(".wd-landing h1.wd-h1"); if (!h1) return; h1.classList.add("wd-h1-shimmer"); } // ========== 10. SOFT GRAIN ========== function initSoftGrain() { if (document.getElementById("wdGrain")) return; var c = document.createElement("canvas"); c.id = "wdGrain"; c.setAttribute("aria-hidden", "true"); document.body.appendChild(c); var ctx = c.getContext("2d"); var size = 150; c.width = size; c.height = size; function regen() { var img = ctx.createImageData(size, size); var d = img.data; for (var i = 0; i < d.length; i += 4) { var v = (Math.random() * 255) | 0; d[i] = d[i + 1] = d[i + 2] = v; d[i + 3] = 12; } ctx.putImageData(img, 0, 0); } regen(); setInterval(regen, 160); } // ========== 11. SCROLL PROGRESS ========== function initScrollProgress() { if (document.getElementById("wdScrollProgress")) return; var bar = document.createElement("div"); bar.id = "wdScrollProgress"; document.body.appendChild(bar); function update() { var h = document.documentElement; var max = h.scrollHeight - h.clientHeight; var p = max > 0 ? (h.scrollTop / max) * 100 : 0; bar.style.width = p.toFixed(2) + "%"; } update(); window.addEventListener("scroll", update, { passive: true }); window.addEventListener("resize", update); } // ========== 12. FORM SUBMIT — HEART CONFETTI ========== function initFormConfetti() { document.querySelectorAll("form").forEach(function (form) { form.addEventListener("submit", function () { burstConfetti(window.innerWidth / 2, 120); }); }); // Quiz lead-success custom event (dispatched from wd_quiz_v3.js after submission) window.addEventListener("wd:lead-success", function (ev) { var d = ev.detail || {}; var x = (typeof d.x === "number") ? d.x : window.innerWidth / 2; var y = (typeof d.y === "number") ? d.y : 120; burstConfetti(x, y); // second wave for a fuller celebration setTimeout(function () { burstConfetti(x - 120, y + 40); }, 180); setTimeout(function () { burstConfetti(x + 120, y + 40); }, 360); }); // Also on any [data-confetti] click document.addEventListener("click", function (e) { var btn = e.target.closest && e.target.closest("[data-confetti]"); if (!btn) return; var r = btn.getBoundingClientRect(); burstConfetti(r.left + r.width / 2, r.top + r.height / 2); }); function burstConfetti(cx, cy) { var COLORS = ["#d4a373", "#e7b88a", "#a13e8a", "#cf758e", "#fdc7c0"]; var SHAPES = ["heart", "petal", "petal", "petal"]; for (var i = 0; i < 36; i++) { var el = document.createElement("span"); el.className = "wd-confetti wd-confetti--" + SHAPES[Math.floor(Math.random() * SHAPES.length)]; el.style.left = cx + "px"; el.style.top = cy + "px"; el.style.background = COLORS[Math.floor(Math.random() * COLORS.length)]; var ang = Math.random() * Math.PI * 2; var spd = 80 + Math.random() * 220; el.style.setProperty("--tx", Math.cos(ang) * spd + "px"); el.style.setProperty("--ty", Math.sin(ang) * spd - 80 + "px"); el.style.setProperty("--rot", Math.random() * 720 + "deg"); el.style.animationDelay = (Math.random() * 0.15) + "s"; document.body.appendChild(el); setTimeout(function (e) { return function () { e.remove(); }; }(el), 2400); } } } // ========== 13. FLOATING DECOR (corner sparkle SVG, breathing) ========== function initFloatingDecor() { var hero = document.querySelector(".wd-section--hero .wd-wrap"); if (!hero) return; if (document.querySelector(".wd-decor")) return; var deco = document.createElement("div"); deco.className = "wd-decor"; deco.setAttribute("aria-hidden", "true"); deco.innerHTML = '' + ''; hero.appendChild(deco); } })();