(() => { const loadTailwind = () => { if (window.tailwind) return; const tw = document.createElement('script'); tw.src = 'https://cdn.tailwindcss.com'; tw.async = true; document.head.appendChild(tw); }; loadTailwind(); const i18n = { ru: { siteTitle: '', nav: { home: 'Главная', catalog: 'Каталог', contact: 'Контакты' }, welcome: { title: 'Добро пожаловать', subtitle: 'Подождите 3‑5 секунд, чтобы увидеть демонстрацию адаптивного модального окна.' }, popup: { title: 'Рекламные предложения', timerPrefix: 'Закроется через', timerSuffix: 'сек.', closeBtn: 'Закрыть окно', learnMore: 'Получить бонус', closeIconAria: 'Close popup' }, placeholder: 'Контент сайта {n}' }, en: { siteTitle: '', nav: { home: 'Home', catalog: 'Catalog', contact: 'Contact' }, welcome: { title: 'Welcome', subtitle: 'Wait 3‑5 seconds to see the responsive modal demo.' }, popup: { title: 'Promotional Offers', timerPrefix: 'Will close in', timerSuffix: 'seconds', closeBtn: 'Close window', learnMore: 'Get a bonus', closeIconAria: 'Close popup' }, placeholder: 'Site content {n}' } }; let currentLang = (navigator.language || '').startsWith('en') ? 'en' : 'ru'; const t = (path, ...repl) => { const parts = path.split('.'); let txt = i18n[currentLang]; for (const p of parts) txt = txt?.[p]; if (txt && repl.length) { repl.forEach((v, i) => { txt = txt.replace(`{${i}}`, v); }); } return txt ?? ''; }; const createPopup = (offers, autoCloseSec) => { const backdrop = document.createElement('div'); backdrop.className = 'fixed inset-0 bg-black/60 backdrop-blur-sm transition-opacity'; backdrop.setAttribute('aria-hidden', 'true'); const container = document.createElement('div'); container.className = 'fixed inset-0 z-10 overflow-y-auto'; const wrapper = document.createElement('div'); wrapper.className = 'flex min-h-full items-center justify-center p-4 text-center'; const panel = document.createElement('div'); panel.className = 'relative w-full max-w-5xl transform bg-white text-left rounded-2xl shadow-2xl animate-popup flex flex-col overflow-hidden my-8 transition-all'; const header = document.createElement('div'); header.className = 'flex items-center justify-between px-6 py-4 border-b border-gray-100 bg-gray-50/50 sticky top-0 z-20 backdrop-blur-md'; const h2 = document.createElement('h2'); h2.id = 'popup-title'; h2.className = 'text-xl md:text-2xl font-bold text-gray-800'; h2.textContent = t('popup.title'); const headerRight = document.createElement('div'); headerRight.className = 'flex items-center space-x-4'; const timerBadge = document.createElement('div'); timerBadge.className = 'flex items-center space-x-2 text-gray-500 bg-gray-100 px-3 py-1.5 rounded-full text-sm font-medium whitespace-nowrap'; timerBadge.innerHTML = ` ${t('popup.timerPrefix')} ${autoCloseSec} ${t('popup.timerSuffix')} `; const closeBtn = document.createElement('button'); closeBtn.className = 'group p-2 rounded-full bg-red-50 hover:bg-red-100 transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-red-500'; closeBtn.setAttribute('aria-label', t('popup.closeIconAria')); closeBtn.innerHTML = ` `; closeBtn.style.display = 'none'; headerRight.append(timerBadge, closeBtn); header.append(h2, headerRight); const body = document.createElement('div'); body.className = 'p-6 md:p-8 bg-white'; const grid = document.createElement('div'); grid.className = 'grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6'; offers.forEach(offer => { const a = document.createElement('a'); a.href = offer.linkUrl; a.target = '_blank'; a.rel = 'noopener noreferrer'; a.className = 'group flex flex-col h-full bg-white rounded-xl border border-gray-200 overflow-hidden hover:shadow-xl hover:border-blue-200 transition-all duration-300 transform hover:-translate-y-1'; const imgWrap = document.createElement('div'); imgWrap.className = 'relative w-full aspect-video overflow-hidden bg-gray-200 shrink-0'; const img = document.createElement('img'); img.src = offer.imageUrl; img.alt = offer.title[currentLang] ?? offer.title.en; img.className = 'w-full h-full object-cover transition-transform duration-500 group-hover:scale-105'; img.loading = 'lazy'; const overlay = document.createElement('div'); overlay.className = 'absolute inset-0 bg-black/0 group-hover:bg-black/5 transition-colors duration-300'; imgWrap.append(img, overlay); const content = document.createElement('div'); content.className = 'flex flex-col flex-grow p-5'; const h3 = document.createElement('h3'); h3.className = 'text-lg font-bold text-gray-900 mb-2 group-hover:text-blue-600 transition-colors'; h3.textContent = offer.title[currentLang] ?? offer.title.en; const p = document.createElement('p'); p.className = 'text-gray-600 text-sm mb-4 line-clamp-2 flex-grow'; p.textContent = offer.description[currentLang] ?? offer.description.en; const linkWrap = document.createElement('div'); linkWrap.className = 'mt-auto'; const linkSpan = document.createElement('span'); linkSpan.className = 'inline-flex items-center text-sm font-semibold text-blue-600 group-hover:text-blue-700 transition-colors'; linkSpan.innerHTML = ` ${t('popup.learnMore')} `; linkWrap.append(linkSpan); content.append(h3, p, linkWrap); a.append(imgWrap, content); grid.appendChild(a); }); body.appendChild(grid); const footer = document.createElement('div'); footer.className = 'md:hidden px-6 pb-6'; const mobileClose = document.createElement('button'); mobileClose.className = 'w-full py-3 bg-gray-100 hover:bg-gray-200 text-gray-800 font-semibold rounded-lg transition-colors'; mobileClose.textContent = t('popup.closeBtn'); mobileClose.style.display = 'none'; footer.appendChild(mobileClose); panel.append(header, body, footer); wrapper.appendChild(panel); container.appendChild(wrapper); const root = document.createElement('div'); root.className = 'relative z-50'; root.setAttribute('role', 'dialog'); root.setAttribute('aria-modal', 'true'); root.setAttribute('aria-labelledby', 'popup-title'); root.append(backdrop, container); document.body.appendChild(root); let timeLeft = autoCloseSec; const timerEl = document.getElementById('popup-timer'); const tick = () => { timeLeft--; if (timerEl) timerEl.textContent = timeLeft; if (timeLeft <= 0) { clearInterval(timerId); timerBadge.style.display = 'none'; closeBtn.style.display = ''; mobileClose.style.display = ''; } }; const timerId = setInterval(tick, 1000); const closeAll = () => { clearInterval(timerId); root.remove(); }; closeBtn.addEventListener('click', closeAll); mobileClose.addEventListener('click', closeAll); backdrop.addEventListener('click', closeAll); }; const DEFAULT_OFFERS = [ { id: '1', title: { ru: '300 % до 3000 $', en: '300% up to 3000$' }, description: { ru: "Не упустите приветственный бонус: 200% + 30FS+100%! Только сегодня!", en: "Don't miss out on the welcome bonus: 200% + 30FS+100%! Only today!" }, imageUrl: 'https://image2url.com/r2/default/images/1773919449944-3a6ade99-c2d4-48f2-9ac1-9c45a0ae2825.png', linkUrl: 'https://t.nimje.org/zhv8c5' }, { id: '2', title: { ru: '300 % до 3000 $', en: '300% up to 3000$' }, description: { ru: "Не упустите приветственный бонус: 200% + 30FS+100%! Только сегодня!", en: "Don't miss out on the welcome bonus: 200% + 30FS+100%! Only today!" }, imageUrl: 'https://image2url.com/r2/default/images/1773919449944-3a6ade99-c2d4-48f2-9ac1-9c45a0ae2825.png', linkUrl: 'https://shorturl.fm/czrAS' } , { id: '3', title: { ru: '300 % до 3000 $', en: '300% up to 3000$' }, description: { ru: "Не упустите приветственный бонус: 200% + 30FS+100%! Только сегодня!", en: "Don't miss out on the welcome bonus: 200% + 30FS+100%! Only today!" }, imageUrl: 'https://image2url.com/r2/default/images/1773919449944-3a6ade99-c2d4-48f2-9ac1-9c45a0ae2825.png', linkUrl: 'https://t.nimje.org/zhv8c5' } ]; const PromoPopup = { init(cfg = {}) { if (cfg.lang && (cfg.lang === 'ru' || cfg.lang === 'en')) { currentLang = cfg.lang; } if (cfg.customTexts) { Object.entries(cfg.customTexts).forEach(([lang, map]) => { if (i18n[lang]) { i18n[lang] = { ...i18n[lang], ...map }; } }); } const offers = cfg.offers ?? DEFAULT_OFFERS; const timer = Number.isInteger(cfg.autoCloseTimer) ? cfg.autoCloseTimer : 5; const delay = Number.isInteger(cfg.delay) ? cfg.delay : 10000; setTimeout(() => createPopup(offers, timer), delay); } }; window.PromoPopup = PromoPopup; })();