/** * Beezy Video Widget SDK v1.0.0 * Embeddable stories/reels player with rewards * https://www.iambeezy.app * * Usage: * * */ ((window, document) => { // Prevent double-init if (window.BeezyWidget && window.BeezyWidget._initialized) return; // ======================================================================== // CONFIG // ======================================================================== const API_BASE = (document.currentScript && document.currentScript.getAttribute('data-api')) || 'https://api.iambeezy.app'; const AUTH_URL = (document.currentScript && document.currentScript.getAttribute('data-auth-url')) || 'https://www.iambeezy.app/auth/widget-claim'; const WIDGET_MODE = (document.currentScript && document.currentScript.getAttribute('data-mode')) || 'merchant'; const DEFAULT_CONFIG = { apiKey: '', position: 'bottom-right', // 'bottom-right' | 'bottom-left' | 'modal' — where the player opens theme: 'dark', size: 'medium', format: 'circles', // 'circles' | 'cards' | 'squares' | 'richcards' | 'instatriptych' | 'cinematic' | 'editorial' | 'minimal' | 'sticky' | 'banner' autoPlay: true, container: null, // CSS selector for inline mode (e.g. '#beezy-stories') }; // Max visible items per format (aesthetic limits) const FORMAT_MAX_ITEMS = { circles: 6, cards: 4, squares: 5, instatriptych: 3, cinematic: 1, editorial: 1, minimal: 1, banner: 1, }; // CTA i18n key → display text fallback (handles keys stored in DB) const CTA_LABELS = { 'campaigns.createForm.content.ctaOptions.discover': 'Découvrir', 'campaigns.createForm.content.ctaOptions.learn_more': 'En savoir plus', 'campaigns.createForm.content.ctaOptions.watch_video': 'Voir la vidéo', 'campaigns.createForm.content.ctaOptions.see_menu': 'Voir le menu', 'campaigns.createForm.content.ctaOptions.shop_now': 'Acheter', 'campaigns.createForm.content.ctaOptions.order_now': 'Commander', 'campaigns.createForm.content.ctaOptions.get_offer': "Obtenir l'offre", 'campaigns.createForm.content.ctaOptions.sign_up': "S'inscrire", 'campaigns.createForm.content.ctaOptions.subscribe': "S'abonner", 'campaigns.createForm.content.ctaOptions.get_quote': 'Demander un devis', 'campaigns.createForm.content.ctaOptions.request_demo': 'Demander une démo', 'campaigns.createForm.content.ctaOptions.apply_now': 'Postuler', 'campaigns.createForm.content.ctaOptions.contact_us': 'Nous contacter', 'campaigns.createForm.content.ctaOptions.call_now': 'Appeler', 'campaigns.createForm.content.ctaOptions.send_message': 'Envoyer un message', 'campaigns.createForm.content.ctaOptions.book_now': 'Réserver', 'campaigns.createForm.content.ctaOptions.get_directions': 'Itinéraire', 'campaigns.createForm.content.ctaOptions.download': 'Télécharger', 'campaigns.createForm.content.ctaOptions.install': 'Installer', 'campaigns.createForm.content.ctaOptions.donate': 'Faire un don', 'campaigns.createForm.content.ctaOptions.vote': 'Voter', 'campaigns.createForm.content.ctaOptions.participate': 'Participer', 'campaigns.createForm.content.ctaOptions.give_opinion': 'Donner son avis', 'campaigns.createForm.content.ctaOptions.take_survey': 'Répondre au sondage', 'campaigns.createForm.content.ctaOptions.join_live': 'Rejoindre le live', }; function resolveCta(text) { return CTA_LABELS[text] || text; } // SDK i18n — auto-detect browser language const SDK_I18N = { fr: { earnReward: 'Recevez votre récompense', claimText: 'Connectez-vous sur I am Beezy
pour réclamer votre récompense', claimBtn: 'Réclamer', followBrand: 'Suivre cette marque', earnRewards: 'Gagner des récompenses', noStories: 'Aucune story disponible pour le moment.' }, en: { earnReward: 'Claim your reward', claimText: 'Sign in to I am Beezy
to claim your reward', claimBtn: 'Claim Reward', followBrand: 'Follow this brand', earnRewards: 'Earn rewards', noStories: 'No stories available right now.' }, de: { earnReward: 'Belohnung erhalten', claimText: 'Melden Sie sich bei I am Beezy an
um Ihre Belohnung zu erhalten', claimBtn: 'Einlösen', followBrand: 'Marke folgen', earnRewards: 'Belohnungen verdienen', noStories: 'Derzeit keine Stories verfügbar.' }, es: { earnReward: 'Recibe tu recompensa', claimText: 'Inicia sesión en I am Beezy
para reclamar tu recompensa', claimBtn: 'Reclamar', followBrand: 'Seguir esta marca', earnRewards: 'Ganar recompensas', noStories: 'No hay stories disponibles ahora.' }, it: { earnReward: 'Ricevi il tuo premio', claimText: 'Accedi a I am Beezy
per riscuotere il tuo premio', claimBtn: 'Riscuoti', followBrand: 'Segui questo brand', earnRewards: 'Guadagna premi', noStories: 'Nessuna story disponibile al momento.' }, pt: { earnReward: 'Receba sua recompensa', claimText: 'Entre no I am Beezy
para resgatar sua recompensa', claimBtn: 'Resgatar', followBrand: 'Seguir esta marca', earnRewards: 'Ganhar recompensas', noStories: 'Nenhuma story disponível no momento.' }, nl: { earnReward: 'Ontvang uw beloning', claimText: 'Log in bij I am Beezy
om uw beloning te claimen', claimBtn: 'Claimen', followBrand: 'Merk volgen', earnRewards: 'Beloningen verdienen', noStories: 'Momenteel geen stories beschikbaar.' }, el: { earnReward: 'Λάβετε την ανταμοιβή', claimText: 'Συνδεθείτε στο I am Beezy
για να διεκδικήσετε την ανταμοιβή σας', claimBtn: 'Διεκδίκηση', followBrand: 'Ακολουθήστε', earnRewards: 'Κερδίστε ανταμοιβές', noStories: 'Δεν υπάρχουν stories αυτή τη στιγμή.' }, tr: { earnReward: 'Ödülünüzü alın', claimText: 'Ödülünüzü almak için
I am Beezy\'e giriş yapın', claimBtn: 'Talep Et', followBrand: 'Markayı takip et', earnRewards: 'Ödül kazan', noStories: 'Şu anda story bulunmuyor.' }, ja: { earnReward: 'リワードを受け取る', claimText: 'I am Beezyにログインして
リワードを受け取る', claimBtn: '受け取る', followBrand: 'ブランドをフォロー', earnRewards: 'リワードを獲得', noStories: '現在利用可能なストーリーはありません。' }, ko: { earnReward: '리워드 받기', claimText: 'I am Beezy에 로그인하여
리워드를 받으세요', claimBtn: '받기', followBrand: '브랜드 팔로우', earnRewards: '리워드 획득', noStories: '현재 이용 가능한 스토리가 없습니다.' }, }; const sdkLang = (navigator.language || 'fr').slice(0, 2).toLowerCase(); const t18n = SDK_I18N[sdkLang] || SDK_I18N.fr; const SIZE_MAP = { small: { width: 304, height: 540 }, medium: { width: 394, height: 700 }, large: { width: 462, height: 820 }, }; // ======================================================================== // STATE // ======================================================================== let config = { ...DEFAULT_CONFIG }; let widgetConfig = null; let campaigns = []; let currentIndex = 0; let isOpen = false; let visitorId = ''; let fingerprint = ''; let shadowRoot = null; let hostEl = null; let watchStartTime = 0; const watchTimers = {}; const claimedCampaigns = new Set(); let cachedSessionToken = null; // Filled by silent auth check, popup login, or localStorage let cachedUserId = null; // Filled by silent auth check, popup login, or localStorage var pendingPublisherComplete = null; // Stores video_complete data when user needs to login first // Restore session from localStorage (persists across page loads on external domains) try { var storedSession = localStorage.getItem('beezy_widget_session'); if (storedSession) { var parsed = JSON.parse(storedSession); if (parsed.sessionToken) cachedSessionToken = parsed.sessionToken; if (parsed.userId) cachedUserId = parsed.userId; } } catch(e) { /* localStorage not available */ } var accentColor = (widgetConfig && widgetConfig.accentColor) || '#10B981'; // ======================================================================== // VISITOR ID // ======================================================================== function persistSession(token, uid) { try { localStorage.setItem('beezy_widget_session', JSON.stringify({ sessionToken: token, userId: uid })); } catch(e) { /* ignore */ } } function getVisitorId() { const key = 'beezy_widget_vid'; let id = localStorage.getItem(key); if (!id) { id = 'bv_' + Date.now().toString(36) + Math.random().toString(36).slice(2, 10); localStorage.setItem(key, id); } return id; } // ======================================================================== // FINGERPRINT (lightweight browser fingerprint for fraud detection) // ======================================================================== function generateFingerprint() { var components = [ navigator.userAgent, navigator.language, screen.width + 'x' + screen.height, screen.colorDepth, new Date().getTimezoneOffset(), navigator.hardwareConcurrency || 0, navigator.deviceMemory || 0, !!window.sessionStorage, !!window.localStorage, !!window.indexedDB, navigator.platform, ]; // Simple hash var str = components.join('|'); var hash = 0; for (var i = 0; i < str.length; i++) { var chr = str.charCodeAt(i); hash = ((hash << 5) - hash) + chr; hash |= 0; } return 'fp_' + Math.abs(hash).toString(36) + '_' + str.length.toString(36); } // ======================================================================== // API // ======================================================================== function apiGet(path) { var hdrs = { 'X-Widget-Api-Key': config.apiKey, 'X-Widget-Fingerprint': fingerprint, }; if (cachedSessionToken) hdrs['Authorization'] = 'Bearer ' + cachedSessionToken; return fetch(API_BASE + '/video-widget/public/' + path, { headers: hdrs, }).then((r) => { if (!r.ok) throw new Error('API error ' + r.status); return r.json(); }); } function apiPost(path, body) { return fetch(API_BASE + '/video-widget/public/' + path, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Widget-Api-Key': config.apiKey, 'X-Widget-Fingerprint': fingerprint, }, body: JSON.stringify(body), }).then((r) => { if (!r.ok) throw new Error('API error ' + r.status); return r.json(); }); } function trackEvent(eventType, campaignId, metadata) { var meta = { pageUrl: window.location.href, deviceType: getDeviceType(), }; if (cachedUserId) meta.userId = cachedUserId; if (metadata) { for (var k in metadata) { meta[k] = metadata[k]; } } return apiPost('events', { visitorId, eventType, campaignId: campaignId || null, fingerprint, metadata: meta, }).catch(function() { return {}; }); } function getDeviceType() { var w = window.innerWidth; if (w < 768) return 'mobile'; if (w < 1024) return 'tablet'; return 'desktop'; } // ======================================================================== // STYLES // ======================================================================== function getStyles() { var accent = (widgetConfig && widgetConfig.accentColor) || '#10B981'; var borderRadius = (widgetConfig && widgetConfig.borderRadius) || 16; var isDark = config.theme === 'dark' || (widgetConfig && widgetConfig.theme === 'dark'); var bg = isDark ? '#0f0f0f' : '#ffffff'; var fg = isDark ? '#ffffff' : '#0f0f0f'; var fgMuted = isDark ? '#a1a1aa' : '#71717a'; var sizes = SIZE_MAP[config.size] || SIZE_MAP.medium; return ( '\ * { box-sizing: border-box; margin: 0; padding: 0; }\ \ .beezy-launcher {\ position: fixed;\ z-index: 99999;\ display: none;\ }\ .beezy-launcher.bottom-right { bottom: 24px; right: 24px; }\ .beezy-launcher.bottom-left { bottom: 24px; left: 24px; }\ \ .beezy-stories-row {\ position: fixed;\ z-index: 99999;\ display: flex;\ align-items: flex-end;\ gap: 12px;\ padding: 12px 16px;\ overflow-x: auto;\ -webkit-overflow-scrolling: touch;\ scrollbar-width: none;\ }\ .beezy-stories-row::-webkit-scrollbar { display: none; }\ .beezy-stories-row.bottom-right { bottom: 16px; right: 16px; flex-direction: row-reverse; }\ .beezy-stories-row.bottom-left { bottom: 16px; left: 16px; }\ .beezy-stories-row.modal { bottom: 16px; left: 50%; transform: translateX(-50%); }\ \ .beezy-story-bubble {\ flex-shrink: 0;\ display: flex;\ flex-direction: column;\ align-items: center;\ gap: 4px;\ cursor: pointer;\ transition: transform 0.2s;\ max-width: 72px;\ }\ .beezy-story-bubble:hover {\ transform: scale(1.08);\ }\ .beezy-story-ring {\ position: relative;\ width: 72px;\ height: 72px;\ border-radius: 50%;\ padding: 2px;\ background: linear-gradient(45deg, #f09433, #e6683c, #dc2743, #cc2366, #bc1888);\ flex-shrink: 0;\ box-shadow: 0 2px 12px rgba(0,0,0,0.25);\ overflow: hidden;\ }\ .beezy-story-ring.viewed {\ background: #dbdbdb;\ }\ .beezy-story-thumb {\ width: 100%;\ height: 100%;\ border-radius: 50%;\ object-fit: cover;\ background: ' + (isDark ? '#27272a' : '#e4e4e7') + ';\ border: 4px solid #ffffff;\ }\ .beezy-story-thumb-placeholder {\ width: 100%;\ height: 100%;\ border-radius: 50%;\ background: ' + (isDark ? '#27272a' : '#e4e4e7') + ';\ border: 4px solid #ffffff;\ display: flex;\ align-items: center;\ justify-content: center;\ }\ .beezy-story-thumb-placeholder svg {\ width: 24px;\ height: 24px;\ fill: ' + fgMuted + ';\ }\ .beezy-story-label {\ font-size: 11px;\ color: ' + fg + ';\ text-align: center;\ line-height: 1.15;\ max-width: 74px;\ overflow: hidden;\ display: -webkit-box;\ -webkit-line-clamp: 2;\ -webkit-box-orient: vertical;\ word-break: break-word;\ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;\ margin-top: 4px;\ }\ \ /* ── PLAY OVERLAY (circles default) ── */\ .beezy-card-play {\ position: absolute;\ top: 50%;\ left: 50%;\ transform: translate(-50%, -50%);\ width: 24px;\ height: 24px;\ border-radius: 50%;\ background: rgba(0,0,0,0.45);\ display: flex;\ align-items: center;\ justify-content: center;\ pointer-events: none;\ z-index: 2;\ }\ .beezy-card-play svg {\ width: 11px;\ height: 11px;\ fill: white;\ margin-left: 1px;\ }\ .beezy-story-bubble:hover .beezy-card-play {\ display: none;\ }\ \ /* ── INLINE MODE ── */\ .beezy-stories-row.inline {\ position: relative;\ bottom: auto;\ left: auto;\ right: auto;\ z-index: auto;\ transform: none;\ padding: 12px 0 8px;\ overflow-x: visible;\ overflow-y: visible;\ flex-wrap: wrap;\ width: 100%;\ }\ .beezy-stories-row.inline .beezy-story-label {\ color: #333;\ text-shadow: none;\ }\ .beezy-stories-row .beezy-row-tag {\ position: absolute;\ top: 2px;\ right: 4px;\ background: rgba(0,0,0,0.35);\ backdrop-filter: blur(4px);\ color: rgba(255,255,255,0.7);\ font-size: 9px;\ padding: 2px 7px;\ border-radius: 10px;\ font-weight: 500;\ pointer-events: none;\ z-index: 1;\ display: flex;\ align-items: center;\ gap: 4px;\ }\ .beezy-row-tag-dot {\ display: inline-block;\ width: 6px;\ height: 6px;\ border-radius: 50%;\ background: #ef4444;\ transition: background 0.3s ease;\ }\ .beezy-row-tag-dot.signed {\ background: #10b981;\ }\ .beezy-stories-row .beezy-row-powered {\ width: 100%;\ text-align: right;\ font-size: 10px;\ color: #aaa;\ margin-top: 4px;\ pointer-events: auto;\ }\ .beezy-stories-row .beezy-row-powered a {\ color: ' + accent + ';\ text-decoration: none;\ font-weight: 600;\ }\ .beezy-stories-row.inline .beezy-row-tag {\ color: rgba(0,0,0,0.45);\ background: rgba(0,0,0,0.06);\ backdrop-filter: none;\ }\ .beezy-stories-row.inline .beezy-row-powered {\ color: #aaa;\ }\ \ /* ── CARDS / VIGNETTES FORMAT (9:16 vertical rectangles) ── */\ .beezy-stories-row.format-cards {\ gap: 8px;\ padding: 8px 0;\ }\ .beezy-stories-row.format-cards .beezy-story-bubble {\ max-width: 135px;\ }\ /* Original values without white border/shadow: box-shadow: none; */\ .beezy-stories-row.format-cards .beezy-story-ring {\ width: 135px;\ height: 240px;\ border-radius: 8px;\ padding: 0;\ background: none;\ position: relative;\ overflow: hidden;\ }\ /* Original value without white border: border: none; background: transparent; */\ .beezy-stories-row.format-cards .beezy-story-thumb {\ border-radius: 8px;\ border: none;\ }\ .beezy-stories-row.format-cards .beezy-story-thumb-placeholder {\ border-radius: 8px;\ border: none;\ background: #e4e4e7;\ }\ .beezy-stories-row.format-cards .beezy-card-play {\ position: absolute;\ top: 50%;\ left: 50%;\ transform: translate(-50%, -50%);\ width: 32px;\ height: 32px;\ border-radius: 50%;\ background: rgba(0,0,0,0.45);\ display: flex;\ align-items: center;\ justify-content: center;\ pointer-events: none;\ z-index: 2;\ transition: opacity .2s;\ }\ .beezy-stories-row.format-cards .beezy-story-bubble:hover .beezy-card-play {\ opacity: 0;\ }\ .beezy-stories-row.format-cards .beezy-card-play svg {\ width: 14px;\ height: 14px;\ fill: white;\ margin-left: 2px;\ }\ .beezy-stories-row.format-cards .beezy-story-label {\ max-width: 135px;\ font-size: 12px;\ font-weight: 500;\ margin-top: 6px;\ text-shadow: none;\ color: ' + fg + ';\ }\ \ /* ── RICH CARDS FORMAT (landscape YouTube/Discover style) ── */\ .beezy-stories-row.format-richcards {\ gap: 16px;\ padding: 0 0 12px;\ overflow-x: auto;\ scroll-snap-type: x mandatory;\ flex-wrap: nowrap;\ scrollbar-width: thin;\ scrollbar-color: rgba(0,0,0,.15) transparent;\ }\ .beezy-stories-row.format-richcards::-webkit-scrollbar { height: 4px; }\ .beezy-stories-row.format-richcards::-webkit-scrollbar-thumb { background: rgba(0,0,0,.15); border-radius: 4px; }\ .beezy-stories-row.format-richcards::-webkit-scrollbar-track { background: transparent; }\ .beezy-stories-row.format-richcards .beezy-card-item {\ flex-shrink: 0;\ width: 300px;\ border-radius: 10px;\ overflow: hidden;\ background: #ffffff;\ border: 1px solid #e5e5e5;\ cursor: pointer;\ scroll-snap-align: start;\ transition: box-shadow .3s, transform .2s;\ }\ .beezy-stories-row.format-richcards .beezy-card-item:hover {\ box-shadow: 0 4px 20px rgba(0,0,0,.08);\ transform: translateY(-2px);\ }\ .beezy-stories-row.format-richcards .beezy-card-thumb-wrap {\ width: 100%;\ height: 170px;\ position: relative;\ overflow: hidden;\ background: linear-gradient(135deg, #1e3a5f, #0d1b2a);\ }\ .beezy-stories-row.format-richcards .beezy-card-thumb-wrap img,\ .beezy-stories-row.format-richcards .beezy-card-thumb-wrap video {\ width: 100%;\ height: 100%;\ object-fit: cover;\ }\ .beezy-stories-row.format-richcards .beezy-card-play-btn {\ position: absolute;\ top: 50%;\ left: 50%;\ transform: translate(-50%, -50%);\ width: 36px;\ height: 36px;\ background: rgba(0,0,0,0.45);\ border-radius: 50%;\ display: flex;\ align-items: center;\ justify-content: center;\ pointer-events: none;\ z-index: 2;\ }\ .beezy-stories-row.format-richcards .beezy-card-item:hover .beezy-card-play-btn { display: none; }\ .beezy-stories-row.format-richcards .beezy-card-play-btn svg { fill: #fff; width: 16px; margin-left: 2px; }\ .beezy-stories-row.format-richcards .beezy-card-duration {\ position: absolute;\ bottom: 8px;\ right: 8px;\ background: rgba(0,0,0,.65);\ color: #fff;\ font-size: 11px;\ padding: 2px 7px;\ border-radius: 4px;\ font-variant-numeric: tabular-nums;\ z-index: 2;\ }\ .beezy-stories-row.format-richcards .beezy-card-item:hover .beezy-card-duration { display: none; }\ .beezy-stories-row.format-richcards .beezy-card-body {\ padding: 14px 16px;\ }\ .beezy-stories-row.format-richcards .beezy-card-brand {\ display: flex;\ align-items: center;\ gap: 8px;\ margin-bottom: 8px;\ }\ .beezy-stories-row.format-richcards .beezy-card-avatar {\ width: 24px;\ height: 24px;\ border-radius: 6px;\ background: ' + accent + ';\ display: flex;\ align-items: center;\ justify-content: center;\ font-size: 10px;\ font-weight: 700;\ color: #fff;\ overflow: hidden;\ }\ .beezy-stories-row.format-richcards .beezy-card-avatar img {\ width: 100%;\ height: 100%;\ object-fit: cover;\ }\ .beezy-stories-row.format-richcards .beezy-card-brand-name {\ font-size: 12px;\ color: #6b7280;\ font-weight: 500;\ }\ .beezy-stories-row.format-richcards .beezy-card-brand-name .sponsored { color: #aaa; font-weight: 400; }\ .beezy-stories-row.format-richcards .beezy-card-body h4 {\ font-size: 15px;\ font-weight: 600;\ line-height: 1.35;\ margin: 0 0 6px;\ color: #111;\ }\ .beezy-stories-row.format-richcards .beezy-card-body .card-desc {\ font-size: 13px;\ color: #6b7280;\ line-height: 1.5;\ display: -webkit-box;\ -webkit-line-clamp: 2;\ -webkit-box-orient: vertical;\ overflow: hidden;\ margin: 0;\ min-height: 39px;\ }\ .beezy-stories-row.format-richcards .beezy-card-footer {\ display: flex;\ align-items: center;\ justify-content: space-between;\ padding: 10px 16px;\ border-top: 1px solid #e5e5e5;\ }\ .beezy-stories-row.format-richcards .beezy-card-reward {\ font-size: 9px;\ color: rgba(0,0,0,0.45);\ font-weight: 500;\ display: flex;\ align-items: center;\ gap: 4px;\ background: rgba(0,0,0,0.06);\ padding: 2px 7px;\ border-radius: 10px;\ }\ .beezy-stories-row.format-richcards .beezy-card-cta {\ font-size: 12px;\ color: ' + accent + ';\ font-weight: 600;\ display: flex;\ align-items: center;\ gap: 4px;\ }\ \ /* ── SQUARES FORMAT (1:1) ── */\ .beezy-stories-row.format-squares {\ display: flex;\ flex-wrap: wrap;\ gap: 8px;\ padding: 8px 0;\ justify-content: center;\ }\ .beezy-stories-row.format-squares .beezy-square-item {\ width: 135px;\ height: 135px;\ position: relative;\ overflow: hidden;\ cursor: pointer;\ background: #e4e4e7;\ border-radius: 8px;\ flex-shrink: 0;\ }\ .beezy-stories-row.format-squares .beezy-square-item img,\ .beezy-stories-row.format-squares .beezy-square-item video {\ width: 100%;\ height: 100%;\ object-fit: cover;\ position: absolute;\ inset: 0;\ border-radius: 8px;\ }\ .beezy-stories-row.format-squares .beezy-square-play {\ position: absolute;\ top: 50%;\ left: 50%;\ transform: translate(-50%, -50%);\ width: 32px;\ height: 32px;\ background: rgba(0,0,0,0.45);\ border-radius: 50%;\ display: flex;\ align-items: center;\ justify-content: center;\ transition: opacity .2s;\ z-index: 2;\ }\ .beezy-stories-row.format-squares .beezy-square-item:hover .beezy-square-play {\ opacity: 0;\ }\ .beezy-stories-row.format-squares .beezy-square-play svg { fill: #fff; width: 14px; margin-left: 2px; }\ .beezy-stories-row.format-squares .beezy-square-overlay {\ position: absolute;\ inset: 0;\ background: linear-gradient(to top, rgba(0,0,0,.65) 0%, transparent 50%);\ display: flex;\ flex-direction: column;\ justify-content: flex-end;\ padding: 12px;\ opacity: 0;\ transition: opacity .3s;\ z-index: 1;\ }\ .beezy-stories-row.format-squares .beezy-square-item:hover .beezy-square-overlay { opacity: 1; }\ .beezy-stories-row.format-squares .beezy-square-overlay h5 {\ color: #fff;\ font-size: 12px;\ font-weight: 600;\ line-height: 1.3;\ margin: 0 0 4px;\ display: -webkit-box;\ -webkit-line-clamp: 2;\ -webkit-box-orient: vertical;\ overflow: hidden;\ text-overflow: ellipsis;\ }\ .beezy-stories-row.format-squares .beezy-square-overlay .sq-brand {\ font-size: 10px;\ color: rgba(255,255,255,.6);\ }\ .beezy-stories-row.format-squares .beezy-square-reward {\ position: absolute;\ top: 8px;\ right: 8px;\ background: rgba(0,0,0,.4);\ backdrop-filter: blur(4px);\ color: rgba(255,255,255,.7);\ font-size: 9px;\ padding: 2px 7px;\ border-radius: 10px;\ font-weight: 500;\ z-index: 2;\ display: flex;\ align-items: center;\ gap: 4px;\ }\ .beezy-stories-row.format-squares .beezy-square-tag {\ position: absolute;\ top: 8px;\ left: 8px;\ background: rgba(0,0,0,.4);\ backdrop-filter: blur(4px);\ color: rgba(255,255,255,.7);\ font-size: 9px;\ padding: 2px 7px;\ border-radius: 10px;\ font-weight: 500;\ z-index: 2;\ }\ \ /* ── INSTATRIPTYCH FORMAT (3 large panels, center no radius) ── */\ .beezy-stories-row.format-instatriptych {\ display: grid;\ grid-template-columns: repeat(3, 1fr);\ gap: 4px;\ padding: 0;\ border-radius: 10px;\ overflow: hidden;\ }\ .beezy-stories-row.format-instatriptych .beezy-triptych-item {\ aspect-ratio: 1;\ position: relative;\ overflow: hidden;\ cursor: pointer;\ }\ .beezy-stories-row.format-instatriptych .beezy-triptych-item:first-child {\ border-radius: 10px 0 0 10px;\ }\ .beezy-stories-row.format-instatriptych .beezy-triptych-item:nth-child(2) {\ border-radius: 0;\ }\ .beezy-stories-row.format-instatriptych .beezy-triptych-item:last-child {\ border-radius: 0 10px 10px 0;\ }\ .beezy-stories-row.format-instatriptych .beezy-triptych-item img,\ .beezy-stories-row.format-instatriptych .beezy-triptych-item video {\ width: 100%;\ height: 100%;\ object-fit: cover;\ position: absolute;\ inset: 0;\ }\ .beezy-stories-row.format-instatriptych .beezy-triptych-play {\ position: absolute;\ top: 50%;\ left: 50%;\ transform: translate(-50%, -50%);\ width: 40px;\ height: 40px;\ background: rgba(255,255,255,.2);\ backdrop-filter: blur(4px);\ border-radius: 50%;\ display: flex;\ align-items: center;\ justify-content: center;\ transition: transform .2s;\ z-index: 2;\ }\ .beezy-stories-row.format-instatriptych .beezy-triptych-item:hover .beezy-triptych-play {\ transform: translate(-50%, -50%) scale(1.1);\ }\ .beezy-stories-row.format-instatriptych .beezy-triptych-play svg { fill: #fff; width: 16px; margin-left: 2px; }\ .beezy-stories-row.format-instatriptych .beezy-triptych-overlay {\ position: absolute;\ inset: 0;\ background: linear-gradient(to top, rgba(0,0,0,.65) 0%, transparent 50%);\ display: flex;\ flex-direction: column;\ justify-content: flex-end;\ padding: 12px;\ opacity: 0;\ transition: opacity .3s;\ z-index: 1;\ }\ .beezy-stories-row.format-instatriptych .beezy-triptych-item:hover .beezy-triptych-overlay { opacity: 1; }\ .beezy-stories-row.format-instatriptych .beezy-triptych-overlay h5 {\ color: #fff;\ font-size: 13px;\ font-weight: 600;\ line-height: 1.3;\ margin: 0 0 4px;\ }\ .beezy-stories-row.format-instatriptych .beezy-triptych-overlay .tri-brand {\ font-size: 10px;\ color: rgba(255,255,255,.6);\ }\ .beezy-stories-row.format-instatriptych .beezy-triptych-reward {\ position: absolute;\ top: 8px;\ right: 8px;\ background: rgba(16,185,129,.3);\ border: 1px solid rgba(16,185,129,.5);\ color: #fff;\ font-size: 9px;\ padding: 2px 7px;\ border-radius: 20px;\ font-weight: 600;\ z-index: 2;\ }\ .beezy-stories-row.format-instatriptych .beezy-triptych-tag {\ position: absolute;\ top: 8px;\ left: 8px;\ background: rgba(0,0,0,.4);\ backdrop-filter: blur(4px);\ color: rgba(255,255,255,.7);\ font-size: 9px;\ padding: 2px 7px;\ border-radius: 10px;\ font-weight: 500;\ z-index: 2;\ }\ \ /* ── CINEMATIC FORMAT (Google Discovery style) ── */\ .beezy-stories-row.format-cinematic {\ display: block;\ padding: 0;\ }\ .beezy-single-ad.cinematic {\ width: 100%;\ border-radius: 16px;\ overflow: hidden;\ position: relative;\ height: 440px;\ cursor: pointer;\ }\ .beezy-single-ad.cinematic .sad-bg-video {\ position: absolute;\ inset: 0;\ background: linear-gradient(135deg, #0c0c1d 0%, #1a0a2e 40%, #2d1b4e 100%);\ display: flex;\ align-items: center;\ justify-content: center;\ }\ .beezy-single-ad.cinematic .sad-bg-video .sad-thumb {\ position: absolute;\ inset: 0;\ width: 100%;\ height: 100%;\ object-fit: cover;\ opacity: 0.85;\ transition: opacity 0.4s ease;\ }\ .beezy-single-ad.cinematic:hover .sad-thumb {\ opacity: 1;\ }\ .beezy-single-ad.cinematic .sad-overlay {\ position: absolute;\ inset: 0;\ background: linear-gradient(to top, rgba(0,0,0,.75) 0%, transparent 50%);\ display: flex;\ flex-direction: column;\ justify-content: flex-end;\ padding: 36px;\ }\ .beezy-single-ad.cinematic .sad-sponsored {\ font-size: 10px;\ text-transform: uppercase;\ letter-spacing: 2px;\ color: rgba(255,255,255,.5);\ margin-bottom: 10px;\ font-weight: 600;\ }\ .beezy-single-ad.cinematic .sad-title {\ font-family: "Playfair Display", serif;\ color: #fff;\ font-size: 28px;\ font-weight: 600;\ line-height: 1.25;\ margin: 0 0 10px;\ }\ .beezy-single-ad.cinematic .sad-desc {\ color: rgba(255,255,255,.7);\ font-size: 14px;\ margin: 0 0 20px;\ max-width: 400px;\ }\ .beezy-single-ad.cinematic .sad-cta-row {\ display: flex;\ align-items: center;\ gap: 16px;\ }\ .beezy-single-ad.cinematic .sad-cta-btn {\ background: #fff;\ color: #1a1a1a;\ border: none;\ padding: 12px 28px;\ border-radius: 50px;\ font-size: 14px;\ font-weight: 600;\ cursor: pointer;\ transition: transform .2s, box-shadow .2s;\ }\ .beezy-single-ad.cinematic .sad-cta-btn:hover {\ transform: translateY(-2px);\ box-shadow: 0 8px 24px rgba(255,255,255,.2);\ }\ .beezy-single-ad.cinematic .sad-reward-badge {\ display: flex;\ align-items: center;\ gap: 6px;\ background: rgba(16,185,129,.2);\ border: 1px solid rgba(16,185,129,.4);\ color: #6ee7b7;\ padding: 8px 16px;\ border-radius: 50px;\ font-size: 12px;\ font-weight: 600;\ }\ .beezy-single-ad.cinematic .sad-play-ring {\ position: absolute;\ top: 50%;\ left: 50%;\ transform: translate(-50%, -50%);\ width: 48px;\ height: 48px;\ border-radius: 50%;\ background: rgba(0,0,0,0.45);\ display: flex;\ align-items: center;\ justify-content: center;\ pointer-events: none;\ z-index: 2;\ }\ .beezy-single-ad.cinematic:hover .sad-play-ring {\ display: none;\ }\ .beezy-single-ad.cinematic .sad-play-ring svg {\ fill: #fff;\ margin-left: 4px;\ }\ .beezy-single-ad.cinematic .sad-tag {\ position: absolute;\ top: 16px;\ right: 16px;\ background: rgba(0,0,0,.4);\ backdrop-filter: blur(8px);\ color: rgba(255,255,255,.8);\ font-size: 10px;\ padding: 5px 10px;\ border-radius: 20px;\ font-weight: 500;\ display: flex;\ align-items: center;\ gap: 4px;\ }\ .beezy-single-ad.cinematic .sad-progress-bar {\ position: absolute;\ bottom: 0;\ left: 0;\ height: 3px;\ background: ' + accent + ';\ width: 0%;\ border-radius: 0 2px 0 0;\ }\ \ /* ── EDITORIAL FORMAT (NYT/Vogue style) ── */\ .beezy-stories-row.format-editorial {\ display: block;\ padding: 0;\ }\ .beezy-single-ad.editorial {\ background: #fff;\ border: 1px solid #e5e5e5;\ border-radius: 16px;\ overflow: hidden;\ cursor: pointer;\ transition: box-shadow .3s;\ }\ .beezy-single-ad.editorial:hover {\ box-shadow: 0 8px 30px rgba(0,0,0,0.12);\ }\ .beezy-single-ad.editorial .sad-video-wrap {\ height: 280px;\ background: linear-gradient(135deg, #1e3a5f 0%, #0d1b2a 100%);\ position: relative;\ overflow: hidden;\ }\ .beezy-single-ad.editorial .sad-shimmer {\ position: absolute;\ inset: 0;\ background: linear-gradient(90deg, transparent 0%, rgba(255,255,255,.03) 50%, transparent 100%);\ animation: beezy-shimmer 3s ease-in-out infinite;\ }\ @keyframes beezy-shimmer {\ 0% { transform: translateX(-100%); }\ 100% { transform: translateX(100%); }\ }\ .beezy-single-ad.editorial .sad-thumb {\ position: absolute;\ inset: 0;\ width: 100%;\ height: 100%;\ object-fit: cover;\ z-index: 1;\ }\ .beezy-single-ad.editorial .sad-play-center {\ position: absolute;\ top: 50%;\ left: 50%;\ transform: translate(-50%, -50%);\ width: 48px;\ height: 48px;\ background: rgba(0,0,0,0.45);\ border-radius: 50%;\ display: flex;\ align-items: center;\ justify-content: center;\ transition: opacity .2s;\ z-index: 2;\ pointer-events: none;\ }\ .beezy-single-ad.editorial:hover .sad-play-center {\ opacity: 0;\ }\ .beezy-single-ad.editorial .sad-play-center svg {\ fill: #fff;\ margin-left: 3px;\ }\ .beezy-single-ad.editorial .sad-duration {\ position: absolute;\ bottom: 12px;\ right: 12px;\ background: rgba(0,0,0,.6);\ color: #fff;\ font-size: 11px;\ padding: 3px 8px;\ border-radius: 4px;\ font-weight: 500;\ font-variant-numeric: tabular-nums;\ z-index: 2;\ }\ .beezy-single-ad.editorial .sad-body {\ padding: 28px;\ }\ .beezy-single-ad.editorial .sad-sponsor {\ display: flex;\ align-items: center;\ gap: 10px;\ margin-bottom: 14px;\ }\ .beezy-single-ad.editorial .sad-sponsor-logo {\ width: 36px;\ height: 36px;\ border-radius: 10px;\ background: linear-gradient(135deg, #d4a853, #c4983d);\ display: flex;\ align-items: center;\ justify-content: center;\ font-weight: 700;\ font-size: 14px;\ color: #fff;\ flex-shrink: 0;\ object-fit: cover;\ overflow: hidden;\ }\ img.sad-sponsor-logo {\ object-fit: cover;\ }\ \ .beezy-single-ad.editorial .sad-sponsor-name {\ font-weight: 600;\ font-size: 14px;\ color: #111;\ }\ .beezy-single-ad.editorial .sad-sponsor-name .sponsored {\ color: #6b7280;\ font-weight: 400;\ }\ .beezy-single-ad.editorial .sad-sponsor-tag {\ margin-left: auto;\ display: inline-flex;\ align-items: center;\ gap: 6px;\ background: rgba(0,0,0,.06);\ color: #555;\ font-size: 11px;\ font-weight: 500;\ padding: 4px 10px;\ border-radius: 50px;\ }\ .beezy-single-ad.editorial .sad-title {\ font-family: "Playfair Display", serif;\ font-size: 22px;\ font-weight: 600;\ margin: 0 0 10px;\ line-height: 1.3;\ color: #111;\ }\ .beezy-single-ad.editorial .sad-desc {\ color: #6b7280;\ font-size: 15px;\ line-height: 1.6;\ margin: 0 0 20px;\ }\ .beezy-single-ad.editorial .sad-watch-link {\ display: inline-flex;\ align-items: center;\ gap: 8px;\ color: #065f46;\ font-weight: 600;\ font-size: 14px;\ text-decoration: none;\ transition: gap .2s;\ }\ .beezy-single-ad.editorial:hover .sad-watch-link {\ gap: 12px;\ }\ \ /* ── MINIMAL FORMAT (Taboola Premium style) ── */\ .beezy-stories-row.format-minimal {\ display: block;\ padding: 0;\ }\ .beezy-single-ad.minimal {\ display: flex;\ gap: 20px;\ background: #fff;\ border: 1px solid #e5e5e5;\ border-radius: 10px;\ padding: 20px;\ cursor: pointer;\ transition: box-shadow .3s, transform .2s;\ position: relative;\ }\ .beezy-single-ad.minimal:hover {\ box-shadow: 0 4px 16px rgba(0,0,0,0.08);\ transform: translateY(-1px);\ }\ .beezy-single-ad.minimal .sad-thumb-wrap {\ flex-shrink: 0;\ width: 160px;\ height: 110px;\ border-radius: 8px;\ background: linear-gradient(135deg, #2d1b4e 0%, #44337a 100%);\ position: relative;\ overflow: hidden;\ }\ .beezy-single-ad.minimal .sad-thumb {\ width: 100%;\ height: 100%;\ object-fit: cover;\ }\ .beezy-single-ad.minimal .sad-play-mini {\ position: absolute;\ top: 50%;\ left: 50%;\ transform: translate(-50%, -50%);\ width: 36px;\ height: 36px;\ background: rgba(0,0,0,0.45);\ border-radius: 50%;\ display: flex;\ align-items: center;\ justify-content: center;\ transition: opacity .2s;\ z-index: 2;\ }\ .beezy-single-ad.minimal:hover .sad-play-mini {\ opacity: 0;\ }\ .beezy-single-ad.minimal .sad-play-mini svg {\ fill: #fff;\ width: 14px;\ margin-left: 2px;\ }\ .beezy-single-ad.minimal .sad-duration {\ position: absolute;\ bottom: 6px;\ right: 6px;\ background: rgba(0,0,0,.65);\ color: #fff;\ font-size: 10px;\ padding: 2px 6px;\ border-radius: 3px;\ font-variant-numeric: tabular-nums;\ }\ .beezy-single-ad.minimal .sad-content {\ display: flex;\ flex-direction: column;\ justify-content: center;\ flex: 1;\ min-width: 0;\ }\ .beezy-single-ad.minimal .sad-sponsor-row {\ display: flex;\ align-items: center;\ gap: 6px;\ margin-bottom: 6px;\ }\ .beezy-single-ad.minimal .sad-sponsor-dot {\ width: 20px;\ height: 20px;\ border-radius: 5px;\ background: ' + accent + ';\ display: flex;\ align-items: center;\ justify-content: center;\ font-size: 9px;\ font-weight: 700;\ color: #fff;\ flex-shrink: 0;\ }\ .beezy-single-ad.minimal .sad-sponsor-name {\ font-size: 12px;\ color: #6b7280;\ font-weight: 500;\ }\ .beezy-single-ad.minimal .sad-title {\ font-size: 16px;\ font-weight: 600;\ line-height: 1.35;\ margin: 0 0 6px;\ color: #111;\ }\ .beezy-single-ad.minimal .sad-desc {\ font-size: 13px;\ color: #6b7280;\ line-height: 1.5;\ margin: 0;\ display: -webkit-box;\ -webkit-line-clamp: 2;\ -webkit-box-orient: vertical;\ overflow: hidden;\ }\ .beezy-single-ad.minimal .sad-tag {\ position: absolute;\ top: 10px;\ right: 10px;\ font-size: 10px;\ color: #555;\ font-weight: 500;\ display: inline-flex;\ align-items: center;\ gap: 4px;\ background: rgba(0,0,0,.06);\ padding: 3px 8px;\ border-radius: 50px;\ }\ \ /* ── BANNER FORMAT (autoplay muted inline) ── */\ .beezy-stories-row.format-banner {\ display: block;\ padding: 0;\ }\ .beezy-single-ad.banner {\ width: 100%;\ height: 200px;\ position: relative;\ overflow: hidden;\ cursor: pointer;\ background: #000;\ border-radius: 0;\ }\ .beezy-single-ad.banner .sad-vb-bg {\ position: absolute;\ inset: 0;\ background: linear-gradient(90deg, #0c0c1d 0%, #1a1a2e 50%, #2d1b4e 100%);\ animation: beezy-vb-pan 12s ease-in-out infinite alternate;\ }\ @keyframes beezy-vb-pan {\ 0% { background-position: 0% 50%; }\ 100% { background-position: 100% 50%; }\ }\ .beezy-single-ad.banner .sad-vb-scanline {\ position: absolute;\ inset: 0;\ background: repeating-linear-gradient(0deg, transparent, transparent 2px, rgba(255,255,255,.02) 2px, rgba(255,255,255,.02) 4px);\ pointer-events: none;\ }\ .beezy-single-ad.banner .sad-vb-content {\ position: absolute;\ inset: 0;\ display: flex;\ align-items: center;\ padding: 0 40px;\ gap: 32px;\ }\ .beezy-single-ad.banner .sad-vb-visual {\ flex-shrink: 0;\ width: 120px;\ height: 120px;\ border-radius: 12px;\ background: linear-gradient(145deg, rgba(255,255,255,.1), rgba(255,255,255,.03));\ border: 1px solid rgba(255,255,255,.1);\ display: flex;\ align-items: center;\ justify-content: center;\ position: relative;\ overflow: hidden;\ }\ .beezy-single-ad.banner .sad-vb-visual .sad-thumb {\ position: absolute;\ inset: 0;\ width: 100%;\ height: 100%;\ object-fit: cover;\ }\ .beezy-single-ad.banner .sad-vb-play-icon {\ position: absolute;\ top: 50%;\ left: 50%;\ transform: translate(-50%, -50%);\ width: 36px;\ height: 36px;\ background: rgba(0,0,0,0.45);\ border-radius: 50%;\ display: flex;\ align-items: center;\ justify-content: center;\ z-index: 2;\ transition: opacity .2s;\ }\ .beezy-single-ad.banner .sad-vb-play-icon svg {\ margin-left: 2px;\ }\ .beezy-single-ad.banner:hover .sad-vb-play-icon {\ opacity: 0;\ }\ .beezy-single-ad.banner .sad-vb-equalizer {\ display: flex;\ align-items: flex-end;\ gap: 3px;\ height: 40px;\ }\ .beezy-single-ad.banner .sad-vb-equalizer span {\ width: 4px;\ background: ' + accent + ';\ border-radius: 2px;\ animation: beezy-vb-eq 1.2s ease-in-out infinite;\ }\ .beezy-single-ad.banner .sad-vb-equalizer span:nth-child(1) { height: 60%; animation-delay: 0s; }\ .beezy-single-ad.banner .sad-vb-equalizer span:nth-child(2) { height: 100%; animation-delay: .2s; }\ .beezy-single-ad.banner .sad-vb-equalizer span:nth-child(3) { height: 40%; animation-delay: .4s; }\ .beezy-single-ad.banner .sad-vb-equalizer span:nth-child(4) { height: 80%; animation-delay: .6s; }\ .beezy-single-ad.banner .sad-vb-equalizer span:nth-child(5) { height: 50%; animation-delay: .8s; }\ @keyframes beezy-vb-eq {\ 0%, 100% { transform: scaleY(1); }\ 50% { transform: scaleY(.3); }\ }\ .beezy-single-ad.banner .sad-vb-text {\ flex: 1;\ min-width: 0;\ }\ .beezy-single-ad.banner .sad-vb-sponsored {\ font-size: 10px;\ text-transform: uppercase;\ letter-spacing: 1.5px;\ color: rgba(255,255,255,.4);\ margin-bottom: 6px;\ font-weight: 500;\ }\ .beezy-single-ad.banner .sad-title {\ color: #fff;\ font-size: 22px;\ font-weight: 600;\ line-height: 1.3;\ margin: 0 0 8px;\ }\ .beezy-single-ad.banner .sad-desc {\ color: rgba(255,255,255,.5);\ font-size: 13px;\ margin: 0 0 14px;\ }\ .beezy-single-ad.banner .sad-vb-actions {\ display: flex;\ align-items: center;\ gap: 14px;\ }\ .beezy-single-ad.banner .sad-vb-watch-btn {\ background: ' + accent + ';\ color: #fff;\ border: none;\ padding: 10px 24px;\ border-radius: 50px;\ font-size: 13px;\ font-weight: 600;\ cursor: pointer;\ transition: background .2s;\ display: flex;\ align-items: center;\ gap: 6px;\ }\ .beezy-single-ad.banner .sad-vb-watch-btn:hover {\ filter: brightness(1.15);\ }\ .beezy-single-ad.banner .sad-vb-reward-tag {\ display: flex;\ align-items: center;\ gap: 5px;\ color: #6ee7b7;\ font-size: 12px;\ font-weight: 600;\ }\ .beezy-single-ad.banner .sad-tag {\ position: absolute;\ top: 12px;\ right: 16px;\ background: rgba(0,0,0,.3);\ backdrop-filter: blur(4px);\ color: rgba(255,255,255,.6);\ font-size: 9px;\ padding: 3px 8px;\ border-radius: 10px;\ font-weight: 500;\ display: flex;\ align-items: center;\ gap: 4px;\ }\ .beezy-single-ad.banner .sad-vb-progress {\ position: absolute;\ bottom: 0;\ left: 0;\ height: 2px;\ background: ' + accent + ';\ width: 0%;\ animation: beezy-progress-demo 10s linear infinite;\ }\ \ /* ── STICKY FORMAT (fixed bottom bar) ── */\ .beezy-stories-row.format-sticky {\ display: block;\ padding: 0;\ }\ .beezy-single-ad.sticky {\ background: rgba(15,15,20,.95);\ backdrop-filter: blur(16px);\ border-top: 1px solid rgba(255,255,255,.08);\ padding: 12px 24px;\ display: flex;\ align-items: center;\ gap: 16px;\ cursor: pointer;\ border-radius: 12px;\ position: relative;\ }\ .beezy-single-ad.sticky .sad-sticky-thumb {\ width: 56px;\ height: 56px;\ border-radius: 10px;\ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\ flex-shrink: 0;\ position: relative;\ overflow: hidden;\ }\ .beezy-single-ad.sticky .sad-sticky-thumb .sad-thumb {\ position: absolute;\ inset: 0;\ width: 100%;\ height: 100%;\ object-fit: cover;\ border-radius: 10px;\ }\ .beezy-single-ad.sticky .sad-sticky-play {\ position: absolute;\ inset: 0;\ display: flex;\ align-items: center;\ justify-content: center;\ transition: opacity .2s;\ }\ .beezy-single-ad.sticky .sad-sticky-play svg {\ fill: #fff;\ width: 18px;\ margin-left: 2px;\ }\ .beezy-single-ad.sticky:hover .sad-sticky-play {\ opacity: 0;\ }\ .beezy-single-ad.sticky:hover .sad-sticky-duration {\ opacity: 0;\ }\ .beezy-single-ad.sticky .sad-sticky-info {\ flex: 1;\ min-width: 0;\ }\ .beezy-single-ad.sticky .sad-sticky-info h5 {\ color: #fff;\ font-size: 14px;\ font-weight: 600;\ margin: 0;\ white-space: nowrap;\ overflow: hidden;\ text-overflow: ellipsis;\ }\ .beezy-single-ad.sticky .sad-sticky-sub {\ color: rgba(255,255,255,.5);\ font-size: 12px;\ display: flex;\ align-items: center;\ gap: 8px;\ margin-top: 2px;\ }\ .beezy-single-ad.sticky .sad-sticky-sub .sticky-sponsored {\ color: rgba(255,255,255,.4);\ font-weight: 400;\ }\ .beezy-single-ad.sticky .sad-sticky-cta {\ background: ' + accent + ';\ color: #fff;\ border: none;\ padding: 10px 24px;\ border-radius: 50px;\ font-size: 13px;\ font-weight: 600;\ cursor: pointer;\ flex-shrink: 0;\ transition: filter .2s;\ font-family: inherit;\ margin-right: 60px;\ }\ .beezy-single-ad.sticky .sad-sticky-cta:hover {\ filter: brightness(1.15);\ }\ .beezy-single-ad.sticky .sad-sticky-duration {\ position: absolute;\ bottom: 3px;\ right: 3px;\ background: rgba(0,0,0,.75);\ color: #fff;\ font-size: 9px;\ font-weight: 500;\ padding: 1px 4px;\ border-radius: 3px;\ z-index: 2;\ transition: opacity .2s;\ }\ .beezy-single-ad.sticky .sad-tag {\ position: absolute;\ top: 6px;\ right: 8px;\ color: rgba(255,255,255,.4);\ font-size: 9px;\ font-weight: 500;\ display: flex;\ align-items: center;\ gap: 4px;\ }\ \ /* ── SINGLE-AD RESPONSIVE ── */\ @media (max-width: 640px) {\ .beezy-single-ad.minimal { flex-direction: column; }\ .beezy-single-ad.minimal .sad-thumb-wrap { width: 100%; height: 180px; }\ .beezy-single-ad.banner { height: 280px; }\ .beezy-single-ad.banner .sad-vb-content { flex-direction: column; padding: 20px; gap: 16px; text-align: center; }\ .beezy-single-ad.banner .sad-vb-visual { width: 60px; height: 60px; }\ .beezy-single-ad.banner .sad-vb-actions { justify-content: center; }\ }\ \ .beezy-widget-panel {\ position: fixed;\ z-index: 100000;\ width: ' + sizes.width + 'px;\ height: ' + sizes.height + 'px;\ max-height: 90vh;\ border-radius: 12px;\ background: #000;\ box-shadow: 0 8px 48px rgba(0,0,0,0.4);\ overflow: hidden;\ display: none;\ flex-direction: column;\ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;\ color: ' + fg + ';\ }\ .beezy-widget-panel.open { display: flex; }\ .beezy-widget-panel.bottom-right { bottom: 24px; right: 24px; }\ .beezy-widget-panel.bottom-left { bottom: 24px; left: 24px; }\ /* inline is a deployment mode, not a position — panel uses server-configured position class */\ /* .beezy-widget-panel.center { top: 50%; left: 50%; transform: translate(-50%, -50%); } */\ \ .beezy-backdrop {\ position: fixed;\ inset: 0;\ z-index: 99999;\ background: rgba(0,0,0,0.75);\ opacity: 0;\ pointer-events: none;\ transition: opacity 0.3s ease;\ }\ .beezy-backdrop.open { opacity: 1; pointer-events: auto; }\ \ .beezy-widget-panel.modal {\ top: 50%; left: 50%;\ transform: translate(-50%, -50%);\ width: auto !important;\ height: 95vh !important;\ max-height: 95vh !important;\ aspect-ratio: 9/16;\ }\ .beezy-widget-panel.modal .beezy-nav-left,\ .beezy-widget-panel.modal .beezy-nav-right {\ width: 48px;\ height: 48px;\ }\ .beezy-widget-panel.modal .beezy-nav-left { left: 12px; }\ .beezy-widget-panel.modal .beezy-nav-right { right: 12px; }\ .beezy-widget-panel.modal .beezy-nav-left svg,\ .beezy-widget-panel.modal .beezy-nav-right svg {\ width: 24px;\ height: 24px;\ }\ \ .beezy-header {\ position: absolute;\ top: 0;\ left: 0;\ right: 0;\ z-index: 11;\ display: flex;\ align-items: center;\ gap: 8px;\ padding: 28px 12px 20px;\ background: linear-gradient(rgba(0,0,0,0.5) 0%, rgba(0,0,0,0.2) 60%, transparent 100%);\ color: white;\ }\ .beezy-header-avatar {\ width: 36px;\ height: 36px;\ border-radius: 50%;\ object-fit: cover;\ border: 2px solid ' + accent + ';\ flex-shrink: 0;\ }\ .beezy-header-avatar-placeholder {\ width: 36px;\ height: 36px;\ border-radius: 50%;\ background: ' + accent + ';\ display: flex;\ align-items: center;\ justify-content: center;\ color: white;\ font-size: 16px;\ font-weight: 700;\ flex-shrink: 0;\ }\ .beezy-header-info {\ flex: 1;\ min-width: 0;\ }\ .beezy-header-title {\ font-size: 14px;\ font-weight: 700;\ color: white;\ white-space: nowrap;\ overflow: hidden;\ text-overflow: ellipsis;\ }\ .beezy-header-category {\ font-size: 10px;\ color: white;\ white-space: nowrap;\ overflow: hidden;\ text-overflow: ellipsis;\ }\ .beezy-close-btn {\ background: rgba(0,0,0,0.4);\ border: none;\ border-radius: 50%;\ width: 32px;\ height: 32px;\ display: flex;\ align-items: center;\ justify-content: center;\ cursor: pointer;\ color: white;\ flex-shrink: 0;\ font-size: 20px;\ line-height: 0;\ padding: 0;\ transition: background 0.2s, opacity 0.2s;\ opacity: 0.6;\ }\ .beezy-close-btn:hover {\ opacity: 1;\ }\ .beezy-widget-panel.ended .beezy-close-btn {\ background: rgba(255,255,255,0.15);\ opacity: 1;\ }\ .beezy-widget-panel.ended .beezy-close-btn:hover {\ background: rgba(255,255,255,0.3);\ }\ \ .beezy-progress-bar {\ position: absolute;\ top: 0;\ left: 0;\ right: 0;\ z-index: 6;\ display: flex;\ gap: 4px;\ padding: 8px 12px 0;\ }\ .beezy-progress-segment {\ flex: 1;\ height: 2px;\ border-radius: 1px;\ background: ' + (isDark ? '#333' : '#e4e4e7') + ';\ overflow: hidden;\ }\ .beezy-progress-fill {\ height: 100%;\ background: ' + accent + ';\ width: 0%;\ transition: width 0.3s linear;\ }\ .beezy-progress-segment.done .beezy-progress-fill { width: 100%; }\ .beezy-progress-segment.active .beezy-progress-fill { width: 50%; }\ \ .beezy-video-container {\ position: absolute;\ inset: 0;\ overflow: hidden;\ background: #000;\ border-radius: 12px;\ }\ .beezy-video-container video {\ position: relative;\ z-index: 1;\ width: 100%;\ height: 100%;\ object-fit: cover;\ border-radius: 12px;\ }\ .beezy-video-loader {\ position: absolute;\ inset: 0;\ display: flex;\ align-items: center;\ justify-content: center;\ z-index: 8;\ background-size: cover;\ background-position: center;\ background-color: #111;\ transition: opacity 0.3s;\ }\ .beezy-video-loader.hidden {\ opacity: 0;\ pointer-events: none;\ }\ .beezy-video-loader .beezy-spinner {\ width: 36px;\ height: 36px;\ border: 3px solid rgba(255,255,255,0.2);\ border-top-color: #10b981;\ border-radius: 50%;\ animation: beezy-spin 0.8s linear infinite;\ }\ @keyframes beezy-spin {\ to { transform: rotate(360deg); }\ }\ \ .beezy-nav-left, .beezy-nav-right {\ position: absolute;\ width: 40px;\ height: 40px;\ top: 50%;\ transform: translateY(-50%);\ border-radius: 50%;\ background: rgba(0,0,0,0.3);\ border: none;\ display: flex;\ align-items: center;\ justify-content: center;\ z-index: 11;\ cursor: pointer;\ transition: background 0.2s, opacity 0.2s;\ opacity: 0.6;\ }\ .beezy-nav-left:hover, .beezy-nav-right:hover {\ opacity: 1;\ }\ .beezy-video-container.ended .beezy-nav-left,\ .beezy-video-container.ended .beezy-nav-right {\ background: rgba(255,255,255,0.15);\ opacity: 1;\ }\ .beezy-video-container.ended .beezy-nav-left:hover,\ .beezy-video-container.ended .beezy-nav-right:hover {\ background: rgba(255,255,255,0.3);\ }\ .beezy-nav-left { left: 8px; }\ .beezy-nav-right { right: 8px; }\ .beezy-nav-left svg, .beezy-nav-right svg {\ width: 20px;\ height: 20px;\ }\ \ .beezy-overlay {\ position: absolute;\ bottom: 0;\ left: 0;\ right: 0;\ padding: 0 16px 16px;\ background: none;\ color: white;\ z-index: 3;\ display: flex;\ flex-direction: column;\ align-items: center;\ pointer-events: none;\ }\ .beezy-overlay-title {\ display: none;\ }\ .beezy-overlay-desc {\ display: none;\ }\ \ .beezy-cta-btn {\ pointer-events: auto;\ display: flex;\ align-items: center;\ justify-content: center;\ gap: 8px;\ width: 100%;\ padding: 12px 16px;\ background: rgba(255,255,255,0.06);\ backdrop-filter: blur(4px);\ border: 1px solid rgba(255,255,255,0.12);\ color: white;\ border-radius: 12px;\ font-size: 14px;\ font-weight: 700;\ cursor: pointer;\ transition: all 0.2s;\ }\ .beezy-cta-btn:hover { background: rgba(255,255,255,0.18); }\ \ .beezy-reward-dots {\ display: flex;\ gap: 6px;\ justify-content: center;\ margin-top: 10px;\ }\ .beezy-reward-dot {\ width: 8px;\ height: 8px;\ border-radius: 50%;\ border: 1.5px solid rgba(16, 185, 129, 0.35);\ background: transparent;\ transition: all 0.4s ease;\ }\ .beezy-reward-dot.claimed {\ background: rgba(16, 185, 129, 0.5);\ border-color: rgba(16, 185, 129, 0.7);\ box-shadow: 0 0 6px rgba(16, 185, 129, 0.3);\ }\ \ .beezy-reward-badge {\ position: absolute;\ top: 12px;\ right: 12px;\ z-index: 4;\ display: flex;\ align-items: center;\ gap: 4px;\ padding: 4px 10px;\ border-radius: 20px;\ background: rgba(0,0,0,0.6);\ backdrop-filter: blur(8px);\ color: ' + accent + ';\ font-size: 12px;\ font-weight: 600;\ }\ .beezy-reward-badge svg {\ width: 14px;\ height: 14px;\ fill: ' + accent + ';\ }\ \ .beezy-claim-overlay {\ display: none;\ position: absolute;\ inset: 0;\ z-index: 10;\ background: rgba(0,0,0,0.85);\ flex-direction: column;\ align-items: center;\ justify-content: center;\ color: white;\ text-align: center;\ padding: 24px;\ }\ .beezy-claim-overlay h3 {\ font-size: 18px;\ font-weight: 700;\ margin-bottom: 8px;\ }\ .beezy-claim-overlay p {\ font-size: 13px;\ opacity: 0.8;\ margin-bottom: 16px;\ }\ .beezy-claim-btn {\ padding: 10px 24px;\ background: ' + accent + ';\ color: white;\ border: none;\ border-radius: 10px;\ font-size: 14px;\ font-weight: 700;\ cursor: pointer;\ }\ \ .beezy-branding {\ position: absolute;\ bottom: 0;\ left: 0;\ right: 0;\ z-index: 2;\ text-align: center;\ font-size: 8px;\ color: rgba(255,255,255,0.25);\ background: linear-gradient(transparent, rgba(0,0,0,0.6));\ padding: 20px 0 3px;\ pointer-events: auto;\ letter-spacing: 0.3px;\ }\ .beezy-branding a {\ color: rgba(255,255,255,0.35);\ text-decoration: none;\ }\ .beezy-branding a:hover {\ color: rgba(255,255,255,0.7);\ }\ /* Inline branding below stories row */\ .beezy-inline-branding {\ font-size: 9px;\ color: ' + fgMuted + ';\ text-align: left;\ padding: 4px 0 0;\ opacity: 0.6;\ }\ .beezy-inline-branding a {\ color: ' + accent + ';\ text-decoration: none;\ }\ \ .beezy-play-btn {\ background: rgba(0,0,0,0.4);\ border: none;\ border-radius: 50%;\ width: 32px;\ height: 32px;\ display: flex;\ align-items: center;\ justify-content: center;\ cursor: pointer;\ color: white;\ flex-shrink: 0;\ }\ .beezy-play-btn svg {\ width: 14px;\ height: 14px;\ fill: white;\ }\ \ .beezy-mute-btn {\ background: rgba(0,0,0,0.4);\ border: none;\ border-radius: 50%;\ width: 32px;\ height: 32px;\ display: flex;\ align-items: center;\ justify-content: center;\ cursor: pointer;\ color: white;\ flex-shrink: 0;\ }\ .beezy-mute-btn svg {\ width: 14px;\ height: 14px;\ fill: white;\ }\ \ .beezy-header-entity {\ display: flex;\ align-items: center;\ gap: 10px;\ cursor: pointer;\ flex: 1;\ min-width: 0;\ }\ .beezy-header-entity:hover {\ opacity: 0.85;\ }\ \ .beezy-bio-overlay {\ position: absolute;\ inset: 0;\ z-index: 20;\ background: rgba(0,0,0,0.6);\ backdrop-filter: blur(16px);\ display: flex;\ align-items: center;\ justify-content: center;\ }\ .beezy-bio-card {\ display: flex;\ flex-direction: column;\ align-items: center;\ gap: 10px;\ padding: 28px 20px;\ text-align: center;\ color: white;\ width: 85%;\ max-width: 320px;\ }\ .beezy-bio-avatar {\ width: 64px;\ height: 64px;\ border-radius: 50%;\ object-fit: cover;\ border: 3px solid ' + accent + ';\ }\ .beezy-bio-avatar-placeholder {\ width: 64px;\ height: 64px;\ border-radius: 50%;\ background: ' + accent + ';\ display: flex;\ align-items: center;\ justify-content: center;\ font-size: 32px;\ font-weight: 700;\ color: white;\ }\ .beezy-bio-name {\ font-size: 20px;\ font-weight: 700;\ }\ .beezy-bio-category {\ font-size: 12px;\ opacity: 0.7;\ }\ .beezy-bio-media-grid {\ display: grid;\ grid-template-columns: 1fr 1fr 1fr;\ gap: 4px;\ width: 100%;\ margin-top: 4px;\ }\ .beezy-bio-media-item {\ aspect-ratio: 9/16;\ border-radius: 6px;\ overflow: hidden;\ background: rgba(255,255,255,0.1);\ position: relative;\ cursor: pointer;\ }\ .beezy-bio-media-item img, .beezy-bio-media-item video {\ width: 100%;\ height: 100%;\ object-fit: cover;\ }\ .beezy-bio-media-play {\ position: absolute;\ inset: 0;\ display: flex;\ align-items: center;\ justify-content: center;\ background: rgba(0,0,0,0.25);\ transition: opacity 0.2s;\ pointer-events: none;\ }\ .beezy-bio-media-item:hover .beezy-bio-media-play {\ opacity: 0;\ }\ .beezy-bio-followers {\ font-size: 13px;\ opacity: 0.8;\ margin-top: -2px;\ }\ .beezy-bio-followers strong {\ font-weight: 700;\ opacity: 1;\ }\ .beezy-bio-follow-btn {\ width: 100%;\ padding: 10px 24px;\ background: ' + accent + ';\ border: none;\ border-radius: 8px;\ color: white;\ font-size: 13px;\ font-weight: 600;\ cursor: pointer;\ margin-top: 4px;\ }\ .beezy-bio-follow-btn:hover { opacity: 0.9; }\ .beezy-bio-close {\ position: absolute;\ top: 12px;\ right: 12px;\ width: 28px;\ height: 28px;\ display: flex;\ align-items: center;\ justify-content: center;\ background: rgba(255,255,255,0.15);\ backdrop-filter: blur(8px);\ border: none;\ border-radius: 50%;\ color: white;\ font-size: 16px;\ cursor: pointer;\ padding: 0;\ line-height: 0;\ }\ .beezy-bio-close:hover { background: rgba(255,255,255,0.25); }\ \ .beezy-empty {\ flex: 1;\ display: flex;\ align-items: center;\ justify-content: center;\ text-align: center;\ padding: 24px;\ color: ' + fgMuted + ';\ font-size: 13px;\ }\ \ @media (max-width: 768px) {\ .beezy-widget-panel {\ width: 100vw !important;\ max-width: 100vw !important;\ height: 100dvh !important;\ max-height: 100dvh !important;\ min-height: 100dvh !important;\ border-radius: 0 !important;\ top: 0 !important;\ left: 0 !important;\ right: 0 !important;\ bottom: auto !important;\ transform: none !important;\ overflow: hidden !important;\ box-sizing: border-box !important;\ }\ .beezy-video-container,\ .beezy-video-container video {\ border-radius: 0 !important;\ }\ .beezy-stories-row {\ bottom: 8px !important;\ right: 8px !important;\ left: 8px !important;\ gap: 8px;\ padding: 8px;\ }\ .beezy-story-ring {\ width: 56px;\ height: 56px;\ }\ .beezy-story-bubble {\ max-width: 64px;\ }\ .beezy-story-label {\ font-size: 10px;\ max-width: 58px;\ }\ }' ); } // ======================================================================== // SVG ICONS // ======================================================================== var ICON_PLAY = ''; var ICON_CHEVRON_LEFT = ''; var ICON_CHEVRON_RIGHT = ''; var ICON_GIFT = ''; var ICON_CLOSE = ''; var ICON_PAUSE = ''; var ICON_PLAY_VIDEO = ''; var ICON_SOUND_ON = ''; var ICON_SOUND_OFF = ''; // ======================================================================== // RENDER // ======================================================================== function createWidget() { // Clean up previous widget instance if re-rendering (e.g. after auth refresh) if (hostEl && hostEl.parentNode) { // Remove orphaned "Powered by" elements injected into page DOM var oldPowered = hostEl.parentNode.querySelectorAll('.beezy-powered-by'); for (var pi = 0; pi < oldPowered.length; pi++) oldPowered[pi].remove(); hostEl.parentNode.removeChild(hostEl); hostEl = null; shadowRoot = null; } // Inline mode: inject into user-specified container var inlineTarget = null; if (config.container) { inlineTarget = document.querySelector(config.container); } // Also detect
elements if (!inlineTarget) { inlineTarget = document.querySelector('[data-beezy-widget="' + config.apiKey + '"]'); } // Host element hostEl = document.createElement('div'); hostEl.id = 'beezy-widget-host'; if (inlineTarget) { inlineTarget.appendChild(hostEl); } else { document.body.appendChild(hostEl); } // Shadow DOM shadowRoot = hostEl.attachShadow({ mode: 'closed' }); // Styles var style = document.createElement('style'); style.textContent = getStyles(); shadowRoot.appendChild(style); // Stories carousel var isInline = !!inlineTarget; var formatClass = config.format !== 'circles' ? ' format-' + config.format : ''; var posClass = isInline ? 'inline' : config.position; var storiesRow = document.createElement('div'); storiesRow.className = 'beezy-stories-row ' + posClass + formatClass; buildStoriesBubbles(storiesRow); shadowRoot.appendChild(storiesRow); // Inline branding below stories (merchant mode only) if (isInline && WIDGET_MODE !== 'publisher') { var inlineBrand = document.createElement('div'); inlineBrand.className = 'beezy-inline-branding'; inlineBrand.innerHTML = 'Made by I am Beezy'; shadowRoot.appendChild(inlineBrand); } // Powered by branding (publisher mode) — injected into page DOM after host element if (isInline && WIDGET_MODE === 'publisher') { var poweredBy = document.createElement('div'); poweredBy.className = 'beezy-powered-by'; poweredBy.style.cssText = 'width:100%;text-align:right;font-size:10px;color:#aaa;margin-top:8px;margin-bottom:16px;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;'; poweredBy.innerHTML = 'Powered by I am Beezy'; hostEl.parentNode.insertBefore(poweredBy, hostEl.nextSibling); } // Backdrop (for modal mode) var backdrop = document.createElement('div'); backdrop.className = 'beezy-backdrop'; backdrop.addEventListener('click', function() { close(); }); shadowRoot.appendChild(backdrop); // Panel var panel = document.createElement('div'); panel.className = 'beezy-widget-panel ' + config.position; panel.innerHTML = buildPanelHTML(); shadowRoot.appendChild(panel); // Bind events bindPanelEvents(panel); } function buildStoriesBubbles(container) { container.innerHTML = ''; if (campaigns.length === 0) { // No slides — hide the widget entirely container.style.display = 'none'; return; } // Single-ad formats: cinematic, editorial, minimal, banner, sticky var singleAdFormats = ['cinematic', 'editorial', 'minimal', 'banner', 'sticky']; if (singleAdFormats.indexOf(config.format) !== -1) { buildSingleAdLayout(container); return; } // Rich cards format: landscape rich cards (YouTube/Google Discover style) if (config.format === 'richcards') { buildCardsLayout(container); return; } // Squares format: grid Instagram style if (config.format === 'squares') { buildSquaresLayout(container); return; } if (config.format === 'instatriptych') { buildInstatriptychLayout(container); return; } for (var i = 0; i < campaigns.length; i++) { (function(index) { var c = campaigns[index]; var bubble = document.createElement('div'); bubble.className = 'beezy-story-bubble'; var thumbHtml = ''; var videoSrc = c.videoUrl || (c.mediaUrls && c.mediaUrls[0]) || ''; if (c.thumbnailUrl) { thumbHtml = '' + (c.title || '') + ''; } else if (videoSrc) { // Placeholder image — will be replaced by Canvas-generated thumbnail thumbHtml = '' + (c.title || '') + ''; } else { thumbHtml = '
' + ICON_PLAY + '
'; } // Play overlay (all formats) var playOverlay = '
'; // Label: slide title (like Instagram shows Reel name) var label = c.title || 'Video ' + (index + 1); var maxLen = config.format === 'circles' ? 17 : 24; if (label.length > maxLen) label = label.substring(0, maxLen - 1) + '…'; bubble.innerHTML = '\
\ ' + thumbHtml + '\ ' + playOverlay + '\
\ ' + label + ''; bubble.addEventListener('click', function() { currentIndex = index; open(); }); container.appendChild(bubble); })(i); } // Add Beezy Ad tag (publisher mode only) — Powered by is handled globally after host element if (WIDGET_MODE === 'publisher') { var adTag = document.createElement('span'); adTag.className = 'beezy-row-tag'; adTag.innerHTML = ' Beezy Ad'; container.appendChild(adTag); } // Generate Canvas thumbnails for story bubbles that need them generateBubbleThumbnails(container); // Add hover-to-play on story bubbles with video thumbnails var allBubbles = container.querySelectorAll('.beezy-story-bubble'); allBubbles.forEach(function(bubble, idx) { // Find video source from campaign data var bubbleIndex = Array.prototype.indexOf.call(allBubbles, bubble); var videoSrc = (bubbleIndex >= 0 && bubbleIndex < campaigns.length) ? (campaigns[bubbleIndex].videoUrl || '') : ''; if (!videoSrc) return; var hoverVideo = null; var originalThumb = null; bubble.addEventListener('mouseenter', function() { // Find current thumb dynamically (may have been replaced by canvas thumbnail generator) var currentThumb = bubble.querySelector('.beezy-story-thumb'); if (!currentThumb) return; originalThumb = currentThumb; if (!hoverVideo) { hoverVideo = document.createElement('video'); hoverVideo.src = videoSrc; hoverVideo.muted = true; hoverVideo.playsInline = true; hoverVideo.loop = true; hoverVideo.className = 'beezy-story-thumb'; hoverVideo.style.cssText = 'width:100%;height:100%;object-fit:cover;border-radius:inherit;border:4px solid #fff;'; } if (originalThumb.parentNode) { originalThumb.parentNode.replaceChild(hoverVideo, originalThumb); } hoverVideo.currentTime = 0; hoverVideo.play().catch(function() {}); }); bubble.addEventListener('mouseleave', function() { if (hoverVideo && hoverVideo.parentNode && originalThumb) { hoverVideo.pause(); hoverVideo.parentNode.replaceChild(originalThumb, hoverVideo); } }); }); } // ======================================================================== // SQUARES LAYOUT (grid Instagram style — 3 columns, aspect-ratio 1:1) // ======================================================================== function buildSquaresLayout(container) { var entity = widgetConfig && widgetConfig.entity; var gradients = [ 'linear-gradient(135deg, #667eea, #764ba2)', 'linear-gradient(135deg, #f093fb, #f5576c)', 'linear-gradient(135deg, #4facfe, #00f2fe)', 'linear-gradient(135deg, #43e97b, #38f9d7)', 'linear-gradient(135deg, #fa709a, #fee140)', 'linear-gradient(135deg, #a18cd1, #fbc2eb)' ]; for (var i = 0; i < campaigns.length; i++) { (function(index) { var c = campaigns[index]; var advEntity = c.advertiserEntity || entity; var entityName = (advEntity && advEntity.name) || 'Sponsor'; var videoSrc = c.videoUrl || (c.mediaUrls && c.mediaUrls[0]) || ''; var sqThumbStyle = 'position:absolute;inset:0;width:100%;height:100%;object-fit:cover;border-radius:8px;'; var thumbHtml = ''; if (c.thumbnailUrl) { thumbHtml = '' + (c.title || '') + ''; } else if (videoSrc) { thumbHtml = '' + (c.title || '') + ''; } var title = (c.formatContent && c.formatContent.sqWidget && c.formatContent.sqWidget.headline) || c.title || ''; var item = document.createElement('div'); item.className = 'beezy-square-item'; item.style.background = gradients[index % gradients.length]; var isPublisherMode = WIDGET_MODE === 'publisher'; item.innerHTML = '\ ' + thumbHtml + '\
\ ' + (isPublisherMode ? '
Beezy Ad
' : '') + '\ ' + (isPublisherMode ? '
' + title + '
' + entityName + '
' : '') + ''; item.addEventListener('click', function() { currentIndex = index; open(); }); container.appendChild(item); })(i); } // Generate Canvas thumbnails generateBubbleThumbnails(container); // Hover-to-play on square items var sqItems = container.querySelectorAll('.beezy-square-item'); for (var j = 0; j < sqItems.length; j++) { (function(idx) { var sqEl = sqItems[idx]; var cc = campaigns[idx]; var vSrc = cc.videoUrl || (cc.mediaUrls && cc.mediaUrls[0]) || ''; if (!vSrc) return; var hoverVideo = null; sqEl.addEventListener('mouseenter', function() { if (hoverVideo) { hoverVideo.play(); return; } hoverVideo = document.createElement('video'); hoverVideo.src = vSrc; hoverVideo.muted = true; hoverVideo.loop = true; hoverVideo.playsInline = true; hoverVideo.style.cssText = 'position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:0;'; sqEl.appendChild(hoverVideo); hoverVideo.play(); }); sqEl.addEventListener('mouseleave', function() { if (hoverVideo) { hoverVideo.pause(); hoverVideo.currentTime = 0; } }); })(j); } } // ======================================================================== // INSTATRIPTYCH LAYOUT (3 large panels, center has no rounded borders) // ======================================================================== function buildInstatriptychLayout(container) { var entity = widgetConfig && widgetConfig.entity; var gradients = [ 'linear-gradient(135deg, #667eea, #764ba2)', 'linear-gradient(135deg, #f093fb, #f5576c)', 'linear-gradient(135deg, #4facfe, #00f2fe)' ]; var max = Math.min(campaigns.length, 3); for (var i = 0; i < max; i++) { (function(index) { var c = campaigns[index]; var advEntity = c.advertiserEntity || entity; var entityName = (advEntity && advEntity.name) || 'Sponsor'; var videoSrc = c.videoUrl || (c.mediaUrls && c.mediaUrls[0]) || ''; var thumbStyle = 'position:absolute;inset:0;width:100%;height:100%;object-fit:cover;'; var thumbHtml = ''; if (c.thumbnailUrl) { thumbHtml = '' + (c.title || '') + ''; } else if (videoSrc) { thumbHtml = '' + (c.title || '') + ''; } var title = c.title || ''; var item = document.createElement('div'); item.className = 'beezy-triptych-item'; item.style.background = gradients[index % gradients.length]; var isPublisherMode = WIDGET_MODE === 'publisher'; item.innerHTML = '\ ' + thumbHtml + '\
\ ' + (isPublisherMode ? '
Beezy Ad
' : '') + '\
' + title + '
' + entityName + '
'; item.addEventListener('click', function() { currentIndex = index; open(); }); container.appendChild(item); })(i); } // Generate Canvas thumbnails generateBubbleThumbnails(container); // Hover-to-play var items = container.querySelectorAll('.beezy-triptych-item'); for (var j = 0; j < items.length; j++) { (function(idx) { var el = items[idx]; var cc = campaigns[idx]; var vSrc = cc.videoUrl || (cc.mediaUrls && cc.mediaUrls[0]) || ''; if (!vSrc) return; var hoverVideo = null; el.addEventListener('mouseenter', function() { if (hoverVideo) { hoverVideo.play(); return; } hoverVideo = document.createElement('video'); hoverVideo.src = vSrc; hoverVideo.muted = true; hoverVideo.loop = true; hoverVideo.playsInline = true; hoverVideo.style.cssText = 'position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:0;'; el.appendChild(hoverVideo); hoverVideo.play(); }); el.addEventListener('mouseleave', function() { if (hoverVideo) { hoverVideo.pause(); hoverVideo.currentTime = 0; } }); })(j); } } // ======================================================================== // CARDS LAYOUT (landscape rich cards — YouTube/Google Discover style) // ======================================================================== function buildCardsLayout(container) { var entity = widgetConfig && widgetConfig.entity; var starSvg = ''; var arrowSvg = ''; for (var i = 0; i < campaigns.length; i++) { (function(index) { var c = campaigns[index]; // Entity: prefer advertiserEntity (publisher mode), fallback to widgetConfig.entity var advEntity = c.advertiserEntity || entity; var entityName = (advEntity && advEntity.name) || 'Sponsor'; var entityInitial = entityName.charAt(0).toUpperCase(); var entityAvatarUrl = advEntity && advEntity.avatarUrl; var avatarHtml = entityAvatarUrl ? '' + entityName + '' : entityInitial; // Video duration var videoDur = c.videoDuration || 0; var durMin = Math.floor(videoDur / 60); var durSec = Math.floor(videoDur % 60); var durationText = videoDur > 0 ? (durMin + ':' + (durSec < 10 ? '0' : '') + durSec) : ''; // Thumbnail var videoSrc = c.videoUrl || (c.mediaUrls && c.mediaUrls[0]) || ''; var thumbHtml = ''; if (c.thumbnailUrl) { thumbHtml = '' + (c.title || '') + ''; } else if (videoSrc) { thumbHtml = '' + (c.title || '') + ''; } var title = c.title || ''; var desc = c.description || ''; var rewardText = (c.rewardAmount && c.rewardCurrency) ? c.rewardAmount + ' ' + c.rewardCurrency : t18n.earnReward; var cta = resolveCta(c.ctaText) || 'Regarder'; var card = document.createElement('div'); card.className = 'beezy-card-item'; card.innerHTML = '\
\ ' + thumbHtml + '\
\ ' + (durationText ? '
' + durationText + '
' : '') + '\
\
\
\
' + avatarHtml + '
\ ' + entityName + ' \
\

' + title + '

\

' + (desc || ' ') + '

\
\ '; card.addEventListener('click', function() { currentIndex = index; open(); }); container.appendChild(card); })(i); } // Generate Canvas thumbnails for cards that need them generateBubbleThumbnails(container); // Hover-to-play on card thumbnails var cardItems = container.querySelectorAll('.beezy-card-item'); for (var j = 0; j < cardItems.length; j++) { (function(idx) { var cardEl = cardItems[idx]; var thumbWrap = cardEl.querySelector('.beezy-card-thumb-wrap'); if (!thumbWrap) return; var cc = campaigns[idx]; var vSrc = cc.videoUrl || (cc.mediaUrls && cc.mediaUrls[0]) || ''; if (!vSrc) return; // Preload video to get duration badge var preloadVid = document.createElement('video'); preloadVid.src = vSrc; preloadVid.preload = 'metadata'; preloadVid.addEventListener('loadedmetadata', function() { var dur = preloadVid.duration; if (dur > 0 && !thumbWrap.querySelector('.beezy-card-duration')) { var dm = Math.floor(dur / 60); var ds = Math.floor(dur % 60); var badge = document.createElement('div'); badge.className = 'beezy-card-duration'; badge.textContent = dm + ':' + (ds < 10 ? '0' : '') + ds; thumbWrap.appendChild(badge); } }); var hoverVideo = null; thumbWrap.addEventListener('mouseenter', function() { if (hoverVideo) { hoverVideo.play(); return; } hoverVideo = document.createElement('video'); hoverVideo.src = vSrc; hoverVideo.muted = true; hoverVideo.loop = true; hoverVideo.playsInline = true; hoverVideo.style.cssText = 'position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:1;'; thumbWrap.appendChild(hoverVideo); hoverVideo.play(); }); thumbWrap.addEventListener('mouseleave', function() { if (hoverVideo) { hoverVideo.pause(); hoverVideo.currentTime = 0; } }); })(j); } } // ======================================================================== // SINGLE-AD LAYOUTS (cinematic, editorial, minimal, banner) // ======================================================================== function buildSingleAdLayout(container) { var c = campaigns[0]; var videoSrc = c.videoUrl || (c.mediaUrls && c.mediaUrls[0]) || ''; var thumbSrc = c.thumbnailUrl || ''; var title = c.title || ''; var desc = c.description || ''; var cta = resolveCta(c.ctaText) || t18n.earnReward; var rewardText = c.videoReward ? (c.videoReward + ' ' + (c.rewardCurrency || '')) : t18n.earnRewards; var playSvg = ''; var starSvg = ''; var arrowSvg = ''; // Entity: use advertiser entity from campaign (publisher mode) or widgetConfig entity var entity = c.advertiserEntity || (widgetConfig && widgetConfig.entity); var entityName = (entity && entity.name) || 'Stories'; var entityCategory = (entity && entity.category) || ''; var entityAvatarUrl = entity && entity.avatarUrl; var entityInitial = entityName.charAt(0).toUpperCase(); // Format video duration as m:ss var videoDur = c.videoDuration || 0; var durMin = Math.floor(videoDur / 60); var durSec = Math.floor(videoDur % 60); var durationText = videoDur > 0 ? (durMin + ':' + (durSec < 10 ? '0' : '') + durSec) : ''; // Sponsor logo HTML: avatar image or initial placeholder var sponsorLogoHtml = entityAvatarUrl ? '' : ''; var thumbTag = thumbSrc ? '' + title + '' : (videoSrc ? '' + title + '' : ''); var html = ''; switch (config.format) { case 'cinematic': html = '\
\
\ ' + thumbTag + '\
\
\ \
\
\
\ ' + (entityAvatarUrl ? '' : '
' + entityInitial + '
') + '\ ' + entityName + ' · Sponsorisé\
\

' + title + '

\

' + desc + '

\
\ \
\
\
\ \ Beezy Ad\
\
'; break; case 'editorial': html = '\
\
\
\ ' + thumbTag + '\
\ \
\ ' + (durationText ? '
' + durationText + '
' : '') + '\
\
\
\ ' + sponsorLogoHtml + '\ ' + entityName + ' \
Beezy Ad
\
\

' + title + '

\

' + desc + '

\ \ Regarder la video\ ' + arrowSvg + '\ \
\
'; break; case 'minimal': var minimalAvatarHtml = entityAvatarUrl ? '' : '
' + entityInitial + '
'; html = '\
\
\ ' + thumbTag + '\
\ ' + playSvg + '\
\ ' + (durationText ? '
' + durationText + '
' : '') + '\
\
\
\ ' + minimalAvatarHtml + '\ ' + entityName + ' · Sponsorisé\
\

' + title + '

\

' + desc + '

\
\
Beezy Ad
\
'; break; case 'banner': html = '\ '; break; case 'sticky': html = '\
\
\ ' + thumbTag + '\
\ \
\ ' + (durationText ? '
' + durationText + '
' : '') + '\
\
\
' + title + '
\
\ ' + (entityAvatarUrl ? '' : '') + '\ ' + entityName + ' · Sponsorisé\
\
\ \
Beezy Ad
\
'; break; } container.innerHTML = html; // Click handler → open modal for all formats var adEl = container.querySelector('.beezy-single-ad'); if (adEl) { adEl.addEventListener('click', function() { currentIndex = 0; open(); }); } // Hover-to-play on thumbnail var thumbImg = container.querySelector('.sad-thumb'); if (thumbImg && videoSrc && adEl) { var hoverVideo = null; var originalThumb = null; adEl.addEventListener('mouseenter', function() { // Re-query in case generateBubbleThumbnails replaced the original element var currentThumb = container.querySelector('.sad-thumb'); if (!currentThumb || currentThumb === hoverVideo) return; originalThumb = currentThumb; if (!hoverVideo) { hoverVideo = document.createElement('video'); hoverVideo.src = videoSrc; hoverVideo.muted = true; hoverVideo.playsInline = true; hoverVideo.loop = true; hoverVideo.className = 'sad-thumb'; hoverVideo.style.cssText = originalThumb.style.cssText || 'width:100%;height:100%;object-fit:cover;'; } if (originalThumb.parentNode) { originalThumb.parentNode.replaceChild(hoverVideo, originalThumb); } hoverVideo.currentTime = 0; hoverVideo.play().catch(function() {}); }); adEl.addEventListener('mouseleave', function() { if (hoverVideo && hoverVideo.parentNode && originalThumb) { hoverVideo.pause(); hoverVideo.parentNode.replaceChild(originalThumb, hoverVideo); } }); } // Generate Canvas thumbnails if needed generateBubbleThumbnails(container); } /** * Generates lightweight JPEG thumbnails from video URLs via Canvas API. * Replaces placeholder images in story bubbles and bio media grid. * Only downloads video metadata + a single frame instead of full video files. */ function replaceWithVideoElement(img, videoSrc) { var fallbackVideo = document.createElement('video'); fallbackVideo.src = videoSrc + '#t=0.5'; fallbackVideo.muted = true; fallbackVideo.playsInline = true; fallbackVideo.preload = 'auto'; // Copy classes from original img (except beezy-needs-thumb/beezy-video-thumb) fallbackVideo.className = img.className.replace('beezy-needs-thumb', '').replace('beezy-video-thumb', '').trim(); var inheritStyle = img.style.cssText || ''; fallbackVideo.style.cssText = inheritStyle || 'width:100%;height:100%;object-fit:cover;'; // Seek to 0.5s to show first frame as thumbnail fallbackVideo.addEventListener('loadeddata', function() { fallbackVideo.currentTime = 0.5; }); if (img.parentNode) img.parentNode.replaceChild(fallbackVideo, img); } function generateCanvasThumbnail(img) { var videoSrc = img.getAttribute('data-video-src'); if (!videoSrc) return; // First try without crossOrigin (works for same-origin and permissive CORS) var thumbVideo = document.createElement('video'); thumbVideo.preload = 'auto'; thumbVideo.muted = true; thumbVideo.playsInline = true; var settled = false; thumbVideo.addEventListener('loadeddata', function() { thumbVideo.currentTime = Math.min(1, thumbVideo.duration); }); thumbVideo.addEventListener('seeked', function() { if (settled) return; settled = true; try { var canvas = document.createElement('canvas'); canvas.width = thumbVideo.videoWidth; canvas.height = thumbVideo.videoHeight; var ctx = canvas.getContext('2d'); if (ctx) { ctx.drawImage(thumbVideo, 0, 0, canvas.width, canvas.height); img.src = canvas.toDataURL('image/jpeg', 0.8); } } catch (e) { // Canvas tainted by CORS — replace with