Initial AI-generated site

This commit is contained in:
2026-09-02 15:54:43 +00:00
parent 5574bb7dbe
commit a33d09856e
3 changed files with 2227 additions and 1779 deletions
+483 -402
View File
File diff suppressed because it is too large Load Diff
+361 -209
View File
@@ -1,132 +1,262 @@
/**
* 7XL – Interactive Features
* Clean, accessible, respects user preferences
*/
(function() { (function() {
'use strict'; 'use strict';
// Check for reduced motion preference
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches; const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
/** // ========================================
* Header scroll behavior // SCROLL REVEAL ANIMATIONS
*/ // ========================================
function initHeader() {
const header = document.querySelector('.site-header');
if (!header) return;
let ticking = false;
function handleScroll() {
if (!ticking) {
requestAnimationFrame(() => {
if (window.pageYOffset > 40) {
header.classList.add('scrolled');
} else {
header.classList.remove('scrolled');
}
ticking = false;
});
ticking = true;
}
}
window.addEventListener('scroll', handleScroll, { passive: true });
handleScroll();
}
/**
* Mobile menu toggle
*/
function initMobileMenu() {
const toggle = document.querySelector('.mobile-toggle');
const mobileNav = document.querySelector('.mobile-nav');
if (!toggle || !mobileNav) return;
toggle.addEventListener('click', () => {
const isExpanded = toggle.getAttribute('aria-expanded') === 'true';
toggle.setAttribute('aria-expanded', !isExpanded);
mobileNav.hidden = isExpanded;
if (!isExpanded) {
const firstLink = mobileNav.querySelector('a');
if (firstLink) firstLink.focus();
}
});
// Close on link click
mobileNav.querySelectorAll('a').forEach(link => {
link.addEventListener('click', () => {
toggle.setAttribute('aria-expanded', 'false');
mobileNav.hidden = true;
});
});
// Close on escape
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && !mobileNav.hidden) {
toggle.setAttribute('aria-expanded', 'false');
mobileNav.hidden = true;
toggle.focus();
}
});
}
/**
* Scroll reveal animations
*/
function initScrollReveal() { function initScrollReveal() {
if (prefersReducedMotion) return; if (prefersReducedMotion) return;
const revealElements = document.querySelectorAll( const revealElements = document.querySelectorAll(
'.feature-card, .sport-card, .casino-game, .bonus-card, .bonus-main, .section-header' '.feature-card, .sport-item, .game-card, .bonus-card, .download-btn, .section-header'
); );
if (!revealElements.length) return; revealElements.forEach(el => {
el.classList.add('reveal');
});
revealElements.forEach(el => el.classList.add('reveal')); const observerOptions = {
root: null,
rootMargin: '0px 0px -100px 0px',
threshold: 0.1
};
const observer = new IntersectionObserver( const observer = new IntersectionObserver((entries) => {
(entries) => { entries.forEach(entry => {
entries.forEach((entry) => { if (entry.isIntersecting) {
if (entry.isIntersecting) { entry.target.classList.add('active');
entry.target.classList.add('visible'); observer.unobserve(entry.target);
observer.unobserve(entry.target); }
} });
}); }, observerOptions);
},
{
threshold: 0.15,
rootMargin: '0px 0px -40px 0px'
}
);
revealElements.forEach(el => observer.observe(el)); revealElements.forEach(el => {
observer.observe(el);
});
} }
/** // ========================================
* Smooth scroll for anchor links // HEADER SCROLL EFFECT
*/ // ========================================
function initHeaderScroll() {
const header = document.querySelector('.site-header');
if (!header) return;
window.addEventListener('scroll', () => {
const currentScroll = window.pageYOffset;
if (currentScroll > 100) {
header.style.background = 'rgba(10, 22, 40, 0.95)';
} else {
header.style.background = 'rgba(10, 22, 40, 0.8)';
}
}, { passive: true });
}
// ========================================
// SPORTS TABS INTERACTION WITH KEYBOARD SUPPORT
// ========================================
function initSportsTabs() {
const sportItems = document.querySelectorAll('.sport-item');
const sportsList = document.querySelector('.sports-list');
if (!sportsList || sportItems.length === 0) return;
// Click handler
sportItems.forEach(item => {
item.addEventListener('click', () => {
activateTab(item, sportItems);
});
});
// Keyboard navigation
sportsList.addEventListener('keydown', (e) => {
const currentTab = document.activeElement;
if (!currentTab.classList.contains('sport-item')) return;
const tabs = Array.from(sportItems);
const currentIndex = tabs.indexOf(currentTab);
let newIndex;
switch(e.key) {
case 'ArrowDown':
case 'ArrowLeft': // RTL: left is next
e.preventDefault();
newIndex = (currentIndex + 1) % tabs.length;
break;
case 'ArrowUp':
case 'ArrowRight': // RTL: right is previous
e.preventDefault();
newIndex = (currentIndex - 1 + tabs.length) % tabs.length;
break;
case 'Home':
e.preventDefault();
newIndex = 0;
break;
case 'End':
e.preventDefault();
newIndex = tabs.length - 1;
break;
default:
return;
}
tabs[newIndex].focus();
activateTab(tabs[newIndex], sportItems);
});
function activateTab(selectedTab, allTabs) {
allTabs.forEach(t => {
t.classList.remove('active');
t.setAttribute('aria-selected', 'false');
t.setAttribute('tabindex', '-1');
});
selectedTab.classList.add('active');
selectedTab.setAttribute('aria-selected', 'true');
selectedTab.setAttribute('tabindex', '0');
}
}
// ========================================
// ODDS BUTTON INTERACTION
// ========================================
function initOddsButtons() {
const oddBtns = document.querySelectorAll('.odd-btn');
oddBtns.forEach(btn => {
btn.addEventListener('click', () => {
oddBtns.forEach(b => b.classList.remove('highlighted'));
btn.classList.add('highlighted');
});
});
}
// ========================================
// MOBILE MENU
// ========================================
function initMobileMenu() {
const menuBtn = document.querySelector('.mobile-menu-btn');
const navLinks = document.querySelector('.nav-links');
if (!menuBtn || !navLinks) return;
let mobileNav = null;
menuBtn.addEventListener('click', () => {
const isOpen = menuBtn.classList.toggle('open');
menuBtn.setAttribute('aria-expanded', isOpen ? 'true' : 'false');
if (isOpen) {
// Create mobile menu
mobileNav = document.createElement('nav');
mobileNav.className = 'mobile-nav';
mobileNav.id = 'mobile-nav';
mobileNav.setAttribute('aria-label', 'תפריט ניווט ראשי');
mobileNav.innerHTML = `<ul>${navLinks.innerHTML}</ul>`;
mobileNav.style.cssText = `
position: fixed;
top: 70px;
inset-inline: 0;
background: rgba(10, 22, 40, 0.98);
backdrop-filter: blur(20px);
padding: 2rem;
border-bottom: 1px solid rgba(255,255,255,0.1);
z-index: 999;
`;
const links = mobileNav.querySelectorAll('a');
links.forEach((link, i) => {
link.style.cssText = `
display: block;
padding: 1rem 0;
font-size: 1.125rem;
border-bottom: 1px solid rgba(255,255,255,0.05);
opacity: 0;
animation: mobileSlideIn 0.3s ease ${i * 0.05}s forwards;
`;
});
// Add animation keyframes
if (!document.querySelector('#mobile-menu-styles')) {
const style = document.createElement('style');
style.id = 'mobile-menu-styles';
style.textContent = `
@keyframes mobileSlideIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
`;
document.head.appendChild(style);
}
document.body.appendChild(mobileNav);
// Close on link click
links.forEach(link => {
link.addEventListener('click', () => {
menuBtn.classList.remove('open');
menuBtn.setAttribute('aria-expanded', 'false');
if (mobileNav) {
mobileNav.remove();
mobileNav = null;
}
});
});
// Focus first link
if (links.length > 0) {
links[0].focus();
}
} else {
if (mobileNav) {
mobileNav.remove();
mobileNav = null;
}
}
});
// Close menu on escape
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && mobileNav) {
menuBtn.classList.remove('open');
menuBtn.setAttribute('aria-expanded', 'false');
mobileNav.remove();
mobileNav = null;
menuBtn.focus();
}
});
}
// ========================================
// SMOOTH SCROLL FOR ANCHOR LINKS
// ========================================
function initSmoothScroll() { function initSmoothScroll() {
document.querySelectorAll('a[href^="#"]').forEach(anchor => { document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function(e) { anchor.addEventListener('click', function(e) {
const targetId = this.getAttribute('href'); const href = this.getAttribute('href');
if (targetId === '#') return; if (href === '#') return;
const target = document.querySelector(targetId); const target = document.querySelector(href);
if (target) { if (target) {
e.preventDefault(); e.preventDefault();
const header = document.querySelector('.site-header'); const header = document.querySelector('.site-header');
const offset = header ? header.offsetHeight + 16 : 80; const headerHeight = header ? header.offsetHeight : 0;
const targetPosition = target.getBoundingClientRect().top + window.pageYOffset - offset; const targetPosition = target.getBoundingClientRect().top + window.pageYOffset - headerHeight - 20;
window.scrollTo({ window.scrollTo({
top: targetPosition, top: targetPosition,
behavior: prefersReducedMotion ? 'auto' : 'smooth' behavior: prefersReducedMotion ? 'auto' : 'smooth'
}); });
// Set focus for accessibility // Set focus for accessibility
target.setAttribute('tabindex', '-1'); target.setAttribute('tabindex', '-1');
target.focus({ preventScroll: true }); target.focus({ preventScroll: true });
@@ -135,132 +265,154 @@
}); });
} }
/** // ========================================
* Pause animations when not in view (performance) // PARALLAX EFFECTS
*/ // ========================================
function initAnimationPausing() { function initParallax() {
if (prefersReducedMotion) return; if (prefersReducedMotion) return;
const roulette = document.querySelector('.roulette-wheel'); const glows = document.querySelectorAll('.glow');
if (!roulette) return;
let ticking = false;
// Add animation via JS so it only runs when visible window.addEventListener('scroll', () => {
const style = document.createElement('style'); if (!ticking) {
style.textContent = ` window.requestAnimationFrame(() => {
.roulette-wheel.animate { const scrollY = window.pageYOffset;
animation: spin 15s linear infinite;
} glows.forEach((glow, index) => {
@keyframes spin { const speed = 0.05 + (index * 0.02);
from { transform: rotate(0deg); } glow.style.transform = `translateY(${scrollY * speed}px)`;
to { transform: rotate(360deg); }
}
`;
document.head.appendChild(style);
const observer = new IntersectionObserver(
(entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
roulette.classList.add('animate');
} else {
roulette.classList.remove('animate');
}
});
},
{ threshold: 0.3 }
);
observer.observe(roulette);
}
/**
* Floating cards animation (CSS-only when visible)
*/
function initFloatingCards() {
if (prefersReducedMotion) return;
const style = document.createElement('style');
style.textContent = `
@keyframes float {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-12px); }
}
.floating-card.animate {
animation: float 5s ease-in-out infinite;
}
.floating-card.card-2.animate {
animation-delay: 1.5s;
}
.floating-card.card-3.animate {
animation-delay: 3s;
}
`;
document.head.appendChild(style);
const cards = document.querySelectorAll('.floating-card');
if (!cards.length) return;
const observer = new IntersectionObserver(
(entries) => {
entries.forEach(entry => {
cards.forEach(card => {
if (entry.isIntersecting) {
card.classList.add('animate');
} else {
card.classList.remove('animate');
}
}); });
ticking = false;
}); });
}, ticking = true;
{ threshold: 0.2 } }
); }, { passive: true });
const heroVisual = document.querySelector('.hero-visual');
if (heroVisual) observer.observe(heroVisual);
} }
/** // ========================================
* Live pulse animation // LIVE ELEMENTS ANIMATION
*/ // ========================================
function initLivePulse() { function initLiveElements() {
if (prefersReducedMotion) return; if (prefersReducedMotion) return;
const style = document.createElement('style'); // Only animate when elements are visible
style.textContent = ` const liveMatchCard = document.querySelector('.live-match-card');
@keyframes pulse { if (!liveMatchCard) return;
0%, 100% { transform: scale(1); opacity: 1; }
50% { transform: scale(1.4); opacity: 0.6; } let animationInterval = null;
}
.live-pulse { const observer = new IntersectionObserver((entries) => {
animation: pulse 1.5s ease-in-out infinite; entries.forEach(entry => {
} if (entry.isIntersecting) {
.live-indicator { // Start animations
animation: blink 1.2s ease-in-out infinite; animationInterval = setInterval(() => {
} // Simulate odds changes
@keyframes blink { const oddValues = document.querySelectorAll('.odd-value');
0%, 100% { opacity: 1; } const randomOdd = oddValues[Math.floor(Math.random() * oddValues.length)];
50% { opacity: 0.5; } if (randomOdd) {
} const currentValue = parseFloat(randomOdd.textContent);
`; if (!isNaN(currentValue)) {
document.head.appendChild(style); const change = (Math.random() - 0.5) * 0.1;
const newValue = Math.max(1.01, currentValue + change).toFixed(2);
randomOdd.style.transition = 'color 0.3s ease';
randomOdd.style.color = change > 0 ? '#22c55e' : '#ef4444';
randomOdd.textContent = newValue;
setTimeout(() => {
randomOdd.style.color = '';
}, 1000);
}
}
}, 4000);
} else {
// Stop animations when not visible
if (animationInterval) {
clearInterval(animationInterval);
animationInterval = null;
}
}
});
}, { threshold: 0.1 });
observer.observe(liveMatchCard);
} }
/** // ========================================
* Initialize all features // BUTTON RIPPLE EFFECT
*/ // ========================================
function initRippleEffect() {
if (prefersReducedMotion) return;
// Add ripple animation styles once
if (!document.querySelector('#ripple-styles')) {
const style = document.createElement('style');
style.id = 'ripple-styles';
style.textContent = `
@keyframes ripple {
to {
transform: scale(4);
opacity: 0;
}
}
.btn, .download-btn, .support-btn {
position: relative;
overflow: hidden;
}
`;
document.head.appendChild(style);
}
const buttons = document.querySelectorAll('.btn, .download-btn, .support-btn');
buttons.forEach(btn => {
btn.addEventListener('click', function(e) {
const rect = this.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
const ripple = document.createElement('span');
ripple.style.cssText = `
position: absolute;
background: rgba(255,255,255,0.3);
border-radius: 50%;
width: 100px;
height: 100px;
left: ${x - 50}px;
top: ${y - 50}px;
transform: scale(0);
animation: ripple 0.6s ease-out;
pointer-events: none;
`;
this.appendChild(ripple);
setTimeout(() => ripple.remove(), 600);
});
});
}
// ========================================
// INITIALIZE ALL
// ========================================
function init() { function init() {
initHeader();
initMobileMenu();
initScrollReveal(); initScrollReveal();
initHeaderScroll();
initSportsTabs();
initOddsButtons();
initMobileMenu();
initSmoothScroll(); initSmoothScroll();
initAnimationPausing(); initParallax();
initFloatingCards(); initLiveElements();
initLivePulse(); initRippleEffect();
} }
// Run on DOM ready
if (document.readyState === 'loading') { if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init); document.addEventListener('DOMContentLoaded', init);
} else { } else {
init(); init();
} }
})(); })();
+1383 -1168
View File
File diff suppressed because it is too large Load Diff