Recommended
GreenSpins Casino
100% up to $500 + 50 Free Spins
Super-fast payouts (same day)
Crypto & fiat supported
Curacao eGaming license
24/7 live chat support
Play Now
LightningBet Casino
200% up to $300 + 100 Free Spins
Weekly cashback up to 10%
Slots, Live Casino, Sports
MGA-compliant fairness
iOS & Android friendly
Play Now
Royal Ace Play
150% up to $700 + 75 Free Spins
VIP rewards & rakeback
Provably fair games
Responsible tools built-in
Secure SSL encryption
Play Now
🔒 SSL Secured
✅ Licensed
⚡ Fast Payouts
🪙 Crypto Friendly
18+ Only
Please gamble responsibly. 18+ only. This site may contain affiliate links that can result in a commission at no extra cost to you. Offers are subject to change — always read the full T&Cs on the casino site.
For QA/SEO testing purposes only, this page includes the keyword: тест paddy power.
2) styles.css
:root {
--bg: #0e0f13;
--card: #161821;
--muted: #a7adbb;
--text: #eef2f7;
--accent: #2ecc71;
--accent-2: #6c5ce7;
--accent-3: #f39c12;
--border: #232635;
--shadow: 0 10px 30px rgba(0, 0, 0, 0.35);
}
* { box-sizing: border-box; }
html, body { height: 100%; }
body {
margin: 0;
font-family: system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, sans-serif;
color: var(--text);
background: radial-gradient(1200px 800px at 20% -10%, #1a1d28 0%, #0e0f13 60%);
line-height: 1.55;
}
.container {
width: 100%;
max-width: 1100px;
margin: 0 auto;
padding: 0 16px;
}
.hero {
padding: 48px 0 20px;
text-align: center;
}
.hero h1 {
margin: 0 0 8px;
font-size: 1.9rem;
letter-spacing: 0.2px;
}
.hero .subhead {
margin: 0 auto;
max-width: 780px;
color: var(--muted);
}
.grid {
margin-top: 24px;
display: grid;
grid-template-columns: 1fr;
gap: 16px;
}
.casino-card {
position: relative;
background: linear-gradient(180deg, rgba(255,255,255,0.02), rgba(255,255,255,0.00));
border: 1px solid var(--border);
border-radius: 16px;
padding: 18px;
outline: none;
cursor: pointer;
box-shadow: 0 0 0 rgba(0,0,0,0);
transition: transform 0.2s ease, box-shadow 0.25s ease, border-color 0.25s ease;
}
.casino-card:hover, .casino-card:focus {
transform: translateY(-3px);
box-shadow: var(--shadow);
border-color: #2a2f44;
}
.casino-card.recommended {
border: 1px solid rgba(46, 204, 113, 0.5);
background: linear-gradient(180deg, rgba(46, 204, 113, 0.07), rgba(255,255,255,0));
}
.ribbon {
position: absolute;
top: 12px;
left: -6px;
background: linear-gradient(90deg, #27ae60, #2ecc71);
color: white;
padding: 6px 12px;
border-top-right-radius: 8px;
border-bottom-right-radius: 8px;
font-size: 0.8rem;
font-weight: 700;
letter-spacing: 0.3px;
}
.logo { display: inline-block; margin-bottom: 12px; }
.name { margin: 4px 0; font-size: 1.1rem; }
.bonus { margin: 4px 0 10px; color: #d8f8e6; font-weight: 600; }
.features { margin: 0 0 14px; padding-left: 18px; color: var(--muted); }
.features li { margin: 6px 0; }
.btn {
appearance: none;
border: none;
padding: 12px 16px;
border-radius: 12px;
font-weight: 700;
cursor: pointer;
color: #0d1419;
background: linear-gradient(90deg, #2ecc71, #27ae60);
box-shadow: 0 8px 20px rgba(46, 204, 113, 0.25);
transition: transform 0.15s ease, box-shadow 0.2s ease, filter 0.15s ease;
}
.btn:hover { transform: translateY(-1px) scale(1.02); filter: brightness(1.05); }
.btn:active { transform: translateY(0) scale(0.98); box-shadow: 0 4px 12px rgba(46, 204, 113, 0.25); }
/* Trust badges */
.trust {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin: 20px 0 8px;
}
.badge {
background: #151724;
border: 1px solid var(--border);
color: var(--muted);
padding: 6px 10px;
border-radius: 999px;
font-size: 0.85rem;
}
.disclaimer {
color: var(--muted);
font-size: 0.9rem;
margin: 8px 0 24px;
}
.footer {
border-top: 1px solid var(--border);
padding: 18px 0 30px;
color: var(--muted);
text-align: center;
}
/* Larger screens */
@media (min-width: 700px) {
.hero { padding: 64px 0 28px; }
.hero h1 { font-size: 2.2rem; }
.grid { grid-template-columns: repeat(3, 1fr); gap: 18px; }
}
3) script.js
// ====== OFFER CONFIG (Edit these URLs only) ======
const OFFERS = {
greenspins: {
name: 'GreenSpins Casino',
url: 'https://example.com/offer/greenspins' // TODO: replace with your affiliate URL
},
lightningbet: {
name: 'LightningBet Casino',
url: 'https://example.com/offer/lightningbet' // TODO: replace with your affiliate URL
},
royalace: {
name: 'Royal Ace Play',
url: 'https://example.com/offer/royalace' // TODO: replace with your affiliate URL
}
};
// ================================================
// Utility: detect device type
function getDeviceType() {
const isMobileUA = /Mobi|Android|iPhone|iPad|iPod/i.test(navigator.userAgent || '');
const isNarrow = window.matchMedia && window.matchMedia('(max-width: 767px)').matches;
return (isMobileUA || isNarrow) ? 'mobile' : 'desktop';
}
// Tracking: log to console
function trackClick(casinoId) {
const payload = {
event: 'casino_click',
casino_id: casinoId,
timestamp: new Date().toISOString(),
device_type: getDeviceType()
};
// In production, send to your endpoint via fetch
console.log('[TRACK]', JSON.stringify(payload));
}
// Redirect using JS
function redirectToOffer(casinoId) {
const offer = OFFERS[casinoId];
if (!offer || !offer.url) {
console.warn('Missing offer URL for casino_id:', casinoId);
return;
}
// Optionally delay a few ms to ensure console flush
window.location.href = offer.url;
}
// Unified handler
function handleGo(e, targetEl) {
const root = targetEl.closest('[data-casino-id]');
if (!root) return;
const casinoId = root.getAttribute('data-casino-id');
trackClick(casinoId);
redirectToOffer(casinoId);
}
// Event delegation for clicks
document.addEventListener('click', function (e) {
const clickable = e.target.closest('[data-casino-id]');
if (!clickable) return;
handleGo(e, clickable);
});
// Keyboard accessibility (Enter/Space)
document.addEventListener('keydown', function (e) {
if (e.key !== 'Enter' && e.key !== ' ') return;
const active = document.activeElement;
if (active && active.matches('[data-casino-id]')) {
e.preventDefault();
handleGo(e, active);
}
});
// Footer year
document.addEventListener('DOMContentLoaded', function () {
const y = document.getElementById('year');
if (y) y.textContent = new Date().getFullYear();
});