/var/www/coeditor.org/users/coeditor.org/assets/js
Edit: /var/www/coeditor.org/users/coeditor.org/assets/js/main.js (27566B)
console.log("Landing generated successfully");
// Hero Video Playback Modes
(function() {
var videos = document.querySelectorAll('.hero-video-background video');
if (!videos.length) return;
function normalizeVideoMode(rawMode) {
var mode = String(rawMode || '').trim().toLowerCase();
if (!mode) return 'loop';
if (mode === 'loop' || mode.indexOf('по кругу') !== -1) return 'loop';
if (mode === 'once' || mode.indexOf('один раз') !== -1) return 'once';
if (mode === 'boomerang' || mode.indexOf('бумеранг') !== -1 || mode.indexOf('вперёд-назад') !== -1) return 'boomerang';
return 'loop';
}
videos.forEach(function(video) {
var mode = normalizeVideoMode(video.dataset.videoPlayMode || video.getAttribute('data-video-play-mode'));
video.loop = mode === 'loop';
if (mode === 'loop') return;
video.removeAttribute('loop');
if (mode !== 'boomerang') return;
var reverseFrameId = null;
var isManualReverse = false;
var reverseStarted = false;
function stopManualReverse() {
isManualReverse = false;
if (reverseFrameId !== null) {
cancelAnimationFrame(reverseFrameId);
reverseFrameId = null;
}
}
function playForwardFromStart() {
stopManualReverse();
reverseStarted = false;
video.loop = false;
video.removeAttribute('loop');
video.playbackRate = 1;
video.currentTime = 0;
video.play().catch(function() {});
}
function playBackwardFromEndManual() {
if (isManualReverse) return;
var lastTimestamp = null;
var duration = video.duration || 0;
stopManualReverse();
isManualReverse = true;
reverseStarted = true;
video.loop = false;
video.removeAttribute('loop');
video.pause();
video.currentTime = Math.max(duration - 0.05, 0);
function step(timestamp) {
if (!isManualReverse) return;
if (lastTimestamp === null) {
lastTimestamp = timestamp;
reverseFrameId = requestAnimationFrame(step);
return;
}
var deltaSeconds = (timestamp - lastTimestamp) / 1000;
lastTimestamp = timestamp;
var nextTime = video.currentTime - deltaSeconds;
if (nextTime <= 0.05) {
video.currentTime = 0;
playForwardFromStart();
return;
}
video.currentTime = nextTime;
reverseFrameId = requestAnimationFrame(step);
}
reverseFrameId = requestAnimationFrame(step);
}
video.addEventListener('ended', function() {
playBackwardFromEndManual();
});
video.addEventListener('timeupdate', function() {
if (isManualReverse) return;
video.loop = false;
if (video.hasAttribute('loop')) video.removeAttribute('loop');
var duration = video.duration || 0;
if (!duration) return;
if (!reverseStarted && video.currentTime >= duration - 0.08) {
playBackwardFromEndManual();
}
if (video.currentTime < 0.2) {
reverseStarted = false;
}
});
video.addEventListener('play', function() {
if (isManualReverse) {
video.pause();
}
});
video.addEventListener('emptied', function() {
stopManualReverse();
});
});
})();
// Dynamic JSON Form Block
(function() {
var forms = document.querySelectorAll('.dynamic-json-form[data-submit-url]');
if (!forms.length) return;
function formDataToJson(formData) {
var result = {};
formData.forEach(function(value, key) {
if (Object.prototype.hasOwnProperty.call(result, key)) {
if (!Array.isArray(result[key])) result[key] = [result[key]];
result[key].push(value);
} else {
result[key] = value;
}
});
return result;
}
forms.forEach(function(form) {
var statusEl = form.querySelector('.form-submit-status');
var submitBtn = form.querySelector('button[type="submit"]');
var submitUrl = form.dataset.submitUrl;
var successMessage = form.dataset.successMessage || 'Спасибо! Заявка отправлена.';
var errorMessage = form.dataset.errorMessage || 'Не удалось отправить форму. Попробуйте позже.';
var resetOnSuccess = form.dataset.resetOnSuccess !== 'false';
var isSubmitting = false;
function setStatus(message, kind) {
if (!statusEl) return;
statusEl.textContent = message || '';
statusEl.classList.remove('is-success', 'is-error', 'is-loading');
if (kind) statusEl.classList.add(kind);
}
form.addEventListener('submit', async function(e) {
e.preventDefault();
if (isSubmitting) return;
if (!submitUrl) return;
isSubmitting = true;
if (submitBtn) submitBtn.disabled = true;
setStatus('Отправка...', 'is-loading');
try {
var payload = {
formId: form.id || null,
submittedAt: new Date().toISOString(),
pageUrl: window.location.href,
data: formDataToJson(new FormData(form))
};
var response = await fetch(submitUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify(payload)
});
if (!response.ok) {
throw new Error('HTTP ' + response.status);
}
setStatus(successMessage, 'is-success');
if (resetOnSuccess) form.reset();
} catch (_) {
setStatus(errorMessage, 'is-error');
} finally {
isSubmitting = false;
if (submitBtn) submitBtn.disabled = false;
}
});
});
})();
// Sticky Header Shrink + Anchor Offset Scroll
(function() {
var headers = document.querySelectorAll('.block-header.header-sticky');
if (!headers.length) return;
var docEl = document.documentElement;
var menuToggle = document.querySelector('.mobile-menu-toggle');
var headerNav = document.querySelector('.header-nav');
var ticking = false;
function currentHeader() {
return headers[0] || null;
}
var cachedCompactHeight = null;
function getAnchorOffset() {
var header = currentHeader();
if (!header) return 56;
if (header.classList.contains('header-scrolled')) {
cachedCompactHeight = Math.ceil(header.getBoundingClientRect().height);
return cachedCompactHeight + 12;
}
if (cachedCompactHeight !== null) return cachedCompactHeight + 12;
// First-time measurement: temporarily toggle class with transitions disabled
var container = header.querySelector('.container');
var items = header.querySelectorAll('.logo, .logo-image, .menu > a, .menu-item-has-children, .btn-header');
var origT = header.style.transition;
var origCT = container ? container.style.transition : '';
header.style.transition = 'none';
if (container) container.style.transition = 'none';
items.forEach(function(el) { el.dataset._t = el.style.transition; el.style.transition = 'none'; });
header.classList.add('header-scrolled');
void header.offsetHeight;
cachedCompactHeight = Math.ceil(header.getBoundingClientRect().height);
header.classList.remove('header-scrolled');
header.style.transition = origT;
if (container) container.style.transition = origCT;
items.forEach(function(el) { el.style.transition = el.dataset._t || ''; delete el.dataset._t; });
void header.offsetHeight;
return cachedCompactHeight + 12;
}
function setAnchorOffsetVar() {
docEl.style.setProperty('--header-anchor-offset', getAnchorOffset() + 'px');
}
function updateHeaderState() {
var y = window.pageYOffset || docEl.scrollTop || 0;
headers.forEach(function(header) {
header.classList.toggle('header-scrolled', y > 16);
});
setAnchorOffsetVar();
}
function onScroll() {
if (ticking) return;
ticking = true;
requestAnimationFrame(function() {
updateHeaderState();
ticking = false;
});
}
function findHashTarget(hash) {
if (!hash || hash.length < 2) return null;
var id = decodeURIComponent(hash.slice(1));
return document.getElementById(id) || document.querySelector('[name="' + id.replace(/"/g, '\\"') + '"]');
}
function scrollToHash(hash, behavior) {
var target = findHashTarget(hash);
if (!target) return false;
// Measure target position first, then offset separately
var targetTop = window.pageYOffset + target.getBoundingClientRect().top;
var offset = getAnchorOffset();
var top = targetTop - offset;
window.scrollTo({ top: Math.max(0, top), behavior: behavior || 'smooth' });
return true;
}
document.addEventListener('click', function(e) {
var link = e.target.closest('a[href*="#"]');
if (!link) return;
var href = link.getAttribute('href') || '';
if (href === '#' || href.indexOf('#') === -1) return;
var targetUrl;
try {
targetUrl = new URL(link.href, window.location.href);
} catch (_) {
return;
}
if (targetUrl.origin !== window.location.origin) return;
if (targetUrl.pathname !== window.location.pathname) return;
if (!targetUrl.hash) return;
if (!findHashTarget(targetUrl.hash)) return;
e.preventDefault();
scrollToHash(targetUrl.hash, 'smooth');
if (menuToggle && headerNav) {
menuToggle.classList.remove('active');
headerNav.classList.remove('active');
}
if (window.history && typeof window.history.pushState === 'function') {
window.history.pushState(null, '', targetUrl.hash);
}
});
window.addEventListener('scroll', onScroll, { passive: true });
window.addEventListener('resize', function() {
cachedCompactHeight = null;
updateHeaderState();
});
window.addEventListener('load', function() {
updateHeaderState();
if (window.location.hash) {
setTimeout(function() {
scrollToHash(window.location.hash, 'auto');
}, 0);
}
});
updateHeaderState();
// Logo click: scroll to top on home page, navigate to / on other pages
document.addEventListener('click', function(e) {
var logo = e.target.closest('.block-header .logo');
if (!logo) return;
var loc = window.location;
// Resolve the logo href to absolute path
var resolved;
try { resolved = new URL(logo.href, loc.href); } catch(_) { return; }
// Check if we're already on the page the logo points to
if (resolved.origin === loc.origin && resolved.pathname === loc.pathname) {
e.preventDefault();
window.scrollTo({ top: 0, behavior: 'smooth' });
if (loc.hash) history.pushState(null, '', loc.pathname);
}
// Otherwise let the browser navigate normally
});
})();
// Mobile Menu Toggle
(function() {
const menuToggle = document.querySelector('.mobile-menu-toggle');
const headerNav = document.querySelector('.header-nav');
const menuDropdowns = document.querySelectorAll('.menu-item-dropdown');
if (!menuToggle || !headerNav) return;
// Toggle mobile menu
menuToggle.addEventListener('click', function(e) {
e.stopPropagation();
menuToggle.classList.toggle('active');
headerNav.classList.toggle('active');
});
// Close menu when clicking outside
document.addEventListener('click', function(e) {
if (!headerNav.contains(e.target) && !menuToggle.contains(e.target)) {
menuToggle.classList.remove('active');
headerNav.classList.remove('active');
}
});
// Handle dropdown menus on mobile
menuDropdowns.forEach(dropdown => {
const link = dropdown.querySelector('.menu-item-has-children');
if (link) {
link.addEventListener('click', function(e) {
if (window.innerWidth <= 768) {
e.preventDefault();
dropdown.classList.toggle('active');
}
});
}
});
// Close mobile menu when window is resized to desktop
window.addEventListener('resize', function() {
if (window.innerWidth > 768) {
menuToggle.classList.remove('active');
headerNav.classList.remove('active');
menuDropdowns.forEach(dropdown => {
dropdown.classList.remove('active');
});
}
});
})();
// Scroll to Top Button
(function() {
const scrollToTopBtn = document.getElementById('scrollToTop');
if (!scrollToTopBtn) return;
// Show/hide button based on scroll position
function toggleScrollButton() {
if (window.pageYOffset > 300) {
scrollToTopBtn.classList.add('visible');
} else {
scrollToTopBtn.classList.remove('visible');
}
}
// Scroll to top when button is clicked
function scrollToTop() {
window.scrollTo({
top: 0,
behavior: 'smooth'
});
}
// Event listeners
window.addEventListener('scroll', toggleScrollButton);
scrollToTopBtn.addEventListener('click', scrollToTop);
// Initial check
toggleScrollButton();
})();
// Cookie Consent Banner
(function() {
const cookieBanner = document.getElementById('cookieConsent');
const acceptButton = document.getElementById('cookieConsentBtn');
const COOKIE_CONSENT_KEY = 'cookieConsentAccepted';
if (!cookieBanner || !acceptButton) return;
// Check if user has already accepted cookies
function hasAcceptedCookies() {
return localStorage.getItem(COOKIE_CONSENT_KEY) === 'true';
}
// Show banner if consent not given
function showBanner() {
if (!hasAcceptedCookies()) {
setTimeout(function() {
cookieBanner.classList.add('show');
}, 1000); // Show after 1 second delay
}
}
// Hide banner and save consent
function acceptCookies() {
cookieBanner.classList.remove('show');
localStorage.setItem(COOKIE_CONSENT_KEY, 'true');
// Remove from DOM after animation
setTimeout(function() {
cookieBanner.remove();
}, 400);
}
// Event listener for accept button
acceptButton.addEventListener('click', acceptCookies);
// Initialize
showBanner();
})();
// Testimonials Carousel Navigation
(function() {
const testimonialsSection = document.querySelector('.block-testimonials');
if (!testimonialsSection) return;
const grid = testimonialsSection.querySelector('.testimonials-grid');
const prevBtn = testimonialsSection.querySelector('.testimonials-nav-prev');
const nextBtn = testimonialsSection.querySelector('.testimonials-nav-next');
const dots = testimonialsSection.querySelectorAll('.testimonials-dot');
const items = testimonialsSection.querySelectorAll('.testimonial-item');
if (!grid || !prevBtn || !nextBtn || dots.length === 0) return;
let currentIndex = 0;
// Scroll to specific testimonial
function scrollToTestimonial(index) {
if (index < 0 || index >= items.length) return;
currentIndex = index;
const item = items[index];
const scrollLeft = item.offsetLeft - grid.offsetLeft;
grid.scrollTo({
left: scrollLeft,
behavior: 'smooth'
});
updateActiveDot();
updateNavButtons();
}
// Update active dot indicator
function updateActiveDot() {
dots.forEach(function(dot, index) {
if (index === currentIndex) {
dot.classList.add('active');
} else {
dot.classList.remove('active');
}
});
}
// Update navigation button states
function updateNavButtons() {
prevBtn.disabled = currentIndex === 0;
nextBtn.disabled = currentIndex === items.length - 1;
}
// Navigate to previous testimonial
function prevTestimonial() {
if (currentIndex > 0) {
scrollToTestimonial(currentIndex - 1);
}
}
// Navigate to next testimonial
function nextTestimonial() {
if (currentIndex < items.length - 1) {
scrollToTestimonial(currentIndex + 1);
}
}
// Update current index based on scroll position
function updateIndexFromScroll() {
const scrollLeft = grid.scrollLeft;
let newIndex = 0;
let minDistance = Infinity;
items.forEach(function(item, index) {
const itemLeft = item.offsetLeft - grid.offsetLeft;
const distance = Math.abs(scrollLeft - itemLeft);
if (distance < minDistance) {
minDistance = distance;
newIndex = index;
}
});
if (newIndex !== currentIndex) {
currentIndex = newIndex;
updateActiveDot();
updateNavButtons();
}
}
// Event listeners
prevBtn.addEventListener('click', prevTestimonial);
nextBtn.addEventListener('click', nextTestimonial);
dots.forEach(function(dot) {
dot.addEventListener('click', function() {
const index = parseInt(this.getAttribute('data-index'), 10);
scrollToTestimonial(index);
});
});
// Update on scroll
let scrollTimeout;
grid.addEventListener('scroll', function() {
clearTimeout(scrollTimeout);
scrollTimeout = setTimeout(updateIndexFromScroll, 100);
});
// Initial setup
updateNavButtons();
})();
// Fortune Wheel Widget
(function() {
var canvases = document.querySelectorAll('.fortune-wheel-canvas');
if (!canvases.length) return;
canvases.forEach(function(canvas) {
var widget = canvas.closest('.fortune-wheel-widget');
if (!widget) return;
var ctx = canvas.getContext('2d');
var segments = JSON.parse(canvas.dataset.segments || '[]');
var spinDuration = parseFloat(canvas.dataset.spinDuration) || 4;
var spinBtn = widget.querySelector('.fortune-wheel-spin-btn');
var resultBox = widget.querySelector('.fortune-wheel-result');
var resultText = widget.querySelector('.fortune-wheel-result-text');
if (!segments.length) return;
var segmentCount = segments.length;
var arcSize = (2 * Math.PI) / segmentCount;
var currentAngle = 0;
var isSpinning = false;
var defaultColors = [
'#FF6B6B', '#6366F1', '#10B981', '#F59E0B',
'#EC4899', '#8B5CF6', '#14B8A6', '#EF4444',
'#3B82F6', '#22C55E', '#A855F7', '#F97316'
];
function drawWheel(angle) {
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
var radius = Math.min(centerX, centerY) - 8;
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Outer ring
ctx.beginPath();
ctx.arc(centerX, centerY, radius + 4, 0, 2 * Math.PI);
ctx.lineWidth = 6;
ctx.strokeStyle = 'rgba(255,255,255,0.3)';
ctx.stroke();
for (var i = 0; i < segmentCount; i++) {
var startAngle = angle + i * arcSize;
var endAngle = startAngle + arcSize;
var segColor = segments[i].color || defaultColors[i % defaultColors.length];
// Segment
ctx.beginPath();
ctx.moveTo(centerX, centerY);
ctx.arc(centerX, centerY, radius, startAngle, endAngle);
ctx.closePath();
ctx.fillStyle = segColor;
ctx.fill();
ctx.lineWidth = 2;
ctx.strokeStyle = 'rgba(255,255,255,0.3)';
ctx.stroke();
// Label
ctx.save();
ctx.translate(centerX, centerY);
ctx.rotate(startAngle + arcSize / 2);
ctx.textAlign = 'right';
ctx.fillStyle = '#fff';
ctx.font = 'bold ' + Math.max(11, Math.floor(140 / segmentCount)) + 'px sans-serif';
ctx.shadowColor = 'rgba(0,0,0,0.5)';
ctx.shadowBlur = 3;
ctx.fillText(segments[i].label, radius - 16, 5);
ctx.restore();
}
// Center circle
ctx.beginPath();
ctx.arc(centerX, centerY, 22, 0, 2 * Math.PI);
ctx.fillStyle = '#fff';
ctx.fill();
ctx.shadowColor = 'transparent';
ctx.shadowBlur = 0;
ctx.beginPath();
ctx.arc(centerX, centerY, 18, 0, 2 * Math.PI);
ctx.fillStyle = '#333';
ctx.fill();
}
function spin() {
if (isSpinning) return;
isSpinning = true;
spinBtn.disabled = true;
var totalRotation = (5 + Math.random() * 3) * 2 * Math.PI;
var targetAngle = currentAngle + totalRotation;
var startTime = null;
var duration = spinDuration * 1000;
function easeOut(t) {
return 1 - Math.pow(1 - t, 3);
}
function animate(time) {
if (!startTime) startTime = time;
var elapsed = time - startTime;
var progress = Math.min(elapsed / duration, 1);
var easedProgress = easeOut(progress);
var angle = currentAngle + (targetAngle - currentAngle) * easedProgress;
drawWheel(angle);
if (progress < 1) {
requestAnimationFrame(animate);
} else {
currentAngle = targetAngle % (2 * Math.PI);
isSpinning = false;
// Winner: pointer is at top = -PI/2 in canvas coords
var pointerAngle = -Math.PI / 2;
var relativeAngle = (pointerAngle - currentAngle) % (2 * Math.PI);
if (relativeAngle < 0) relativeAngle += 2 * Math.PI;
var winIndex = Math.floor(relativeAngle / arcSize) % segmentCount;
var winner = segments[winIndex];
// Hide spin button
spinBtn.style.display = 'none';
// Show modal popup
var modal = widget.querySelector('.fortune-wheel-modal');
if (modal && resultText) {
resultText.textContent = winner.value || winner.label;
setTimeout(function() {
modal.classList.add('active');
}, 300);
}
}
}
requestAnimationFrame(animate);
}
// Close modal
var modalClose = widget.querySelector('.fortune-wheel-modal-close');
if (modalClose) {
modalClose.addEventListener('click', function() {
var modal = widget.querySelector('.fortune-wheel-modal');
if (modal) modal.classList.remove('active');
});
}
drawWheel(currentAngle);
if (spinBtn) spinBtn.addEventListener('click', spin);
});
})();
// Slot Machine Widget
(function() {
var machines = document.querySelectorAll('.slot-machine-widget');
if (!machines.length) return;
machines.forEach(function(widget) {
var reelsData = JSON.parse(widget.dataset.reels || '[]');
var prizesData = JSON.parse(widget.dataset.prizes || '[]');
var spinDuration = (parseFloat(widget.dataset.spinDuration) || 2) * 1000;
var spinBtn = widget.querySelector('.slot-machine-spin-btn');
var reelEls = widget.querySelectorAll('.slot-reel');
var resultText = widget.querySelector('.slot-machine-result-text');
var isSpinning = false;
if (!reelsData.length || !reelEls.length) return;
var symbolHeight = 100; // matches CSS .slot-symbol height
var reelCount = reelEls.length;
// Build extended reel strips for smooth scrolling
reelEls.forEach(function(reelEl, i) {
var strip = reelEl.querySelector('.slot-reel-strip');
var symbols = reelsData[i] || reelsData[0];
// Clone symbols enough times for smooth animation
var html = '';
for (var repeat = 0; repeat < 20; repeat++) {
for (var s = 0; s < symbols.length; s++) {
html += '
' + symbols[s] + '
';
}
}
strip.innerHTML = html;
});
function spin() {
if (isSpinning) return;
isSpinning = true;
spinBtn.disabled = true;
// Determine final symbols for each reel
var finalSymbols = [];
for (var i = 0; i < reelCount; i++) {
var symbols = reelsData[i] || reelsData[0];
var idx = Math.floor(Math.random() * symbols.length);
finalSymbols.push({ index: idx, symbol: symbols[idx] });
}
// Animate each reel with staggered stop
var completed = 0;
reelEls.forEach(function(reelEl, i) {
var strip = reelEl.querySelector('.slot-reel-strip');
var symbols = reelsData[i] || reelsData[0];
var symbolCount = symbols.length;
var targetIdx = finalSymbols[i].index;
// Total distance: several full cycles + target position
var fullCycles = 4 + i * 2; // More cycles for later reels
var targetPos = (fullCycles * symbolCount + targetIdx) * symbolHeight;
reelEl.classList.add('spinning');
var startTime = null;
var duration = spinDuration + i * 500; // Stagger: each reel takes longer
function easeOut(t) {
return 1 - Math.pow(1 - t, 3);
}
function animate(time) {
if (!startTime) startTime = time;
var elapsed = time - startTime;
var progress = Math.min(elapsed / duration, 1);
var easedProgress = easeOut(progress);
var currentPos = targetPos * easedProgress;
strip.style.transform = 'translateY(-' + currentPos + 'px)';
if (progress < 1) {
requestAnimationFrame(animate);
} else {
reelEl.classList.remove('spinning');
reelEl.classList.add('stopped');
completed++;
if (completed === reelCount) {
onSpinComplete(finalSymbols);
}
}
}
requestAnimationFrame(animate);
});
}
function onSpinComplete(finalSymbols) {
isSpinning = false;
// Check result
var resultSymbols = finalSymbols.map(function(s) { return s.symbol; });
var allSame = resultSymbols.every(function(s) { return s === resultSymbols[0]; });
// Not a win — allow spinning again
if (!allSame) {
spinBtn.disabled = false;
widget.classList.remove('win');
return;
}
// WIN! All 3 match — hide button and show prize
spinBtn.style.display = 'none';
widget.classList.add('win');
// Find matching prize
var prize = null;
if (prizesData.length) {
for (var p = 0; p < prizesData.length; p++) {
var pd = prizesData[p];
if (pd.combination) {
var combo = pd.combination;
var match = true;
for (var c = 0; c < combo.length; c++) {
if (combo[c] !== '*' && combo[c] !== resultSymbols[c]) {
match = false;
break;
}
}
if (match) { prize = pd; break; }
} else if (pd.symbol && pd.symbol === resultSymbols[0]) {
prize = pd;
break;
}
}
// Default prize
if (!prize) {
for (var d = 0; d < prizesData.length; d++) {
if (prizesData[d].default) {
prize = prizesData[d];
break;
}
}
}
}
// Show modal with prize
var displayText = prize ? prize.label : (resultSymbols[0] + ' ' + resultSymbols[0] + ' ' + resultSymbols[0]);
var modal = widget.querySelector('.slot-machine-modal');
if (modal && resultText) {
resultText.textContent = displayText;
setTimeout(function() {
modal.classList.add('active');
}, 1500); // Delay for win glow animation
}
}
// Close modal
var modalClose = widget.querySelector('.slot-machine-modal-close');
if (modalClose) {
modalClose.addEventListener('click', function() {
var modal = widget.querySelector('.slot-machine-modal');
if (modal) modal.classList.remove('active');
});
}
var modalBackdrop = widget.querySelector('.slot-machine-modal-backdrop');
if (modalBackdrop) {
modalBackdrop.addEventListener('click', function() {
var modal = widget.querySelector('.slot-machine-modal');
if (modal) modal.classList.remove('active');
});
}
if (spinBtn) spinBtn.addEventListener('click', spin);
});
})();