Посуда mindbox = window.mindbox || function() { mindbox.queue.push(arguments); }; mindbox.queue = mindbox.queue || []; mindbox('create', { endpointId: 'vbru.Website' });
  • var _tmr = window._tmr || (window._tmr = []); _tmr.push({ id: "3243070", type: "pageView", start: (new Date()).getTime(), pid: "40668266" }); (function (d, w, id) { if (d.getElementById(id)) return; var ts = d.createElement("script"); ts.type = "text/javascript"; ts.async = true; ts.id = id; ts.src = "https://top-fwz1.mail.ru/js/code.js"; var f = function () { var s = d.getElementsByTagName("script")[0]; s.parentNode.insertBefore(ts, s); }; if (w.opera == "[object Opera]") { d.addEventListener("DOMContentLoaded", f, false); } else { f(); } })(document, window, "tmr-code"); var digiScript = document.createElement('script'); digiScript.src = '//cdn.diginetica.net/7549/client.js'; digiScript.defer = true; digiScript.async = true; document.head.appendChild(digiScript);
    В связи с нестабильной работой интернета в Москве до конца майских праздников возможны перебои с оплатой банковскими картами в пунктах самовывоза и при оплате курьеру.
    :root { --top-alert-height: 0px; } body.has-top-alert { --top-alert-height: 40px; } .top-alert { width: 100%; background: #111111; color: #ffffff; font-size: 14px; line-height: 1.4; z-index: 10000; } .top-alert__inner { max-width: 1440px; margin: 0 auto; min-height: 40px; padding: 8px 48px 8px 24px; display: flex; align-items: center; justify-content: center; position: relative; box-sizing: border-box; } .top-alert__text { text-align: center; font-weight: 600; } .top-alert__close { position: absolute; right: 18px; top: 50%; transform: translateY(-50%); width: 28px; height: 28px; border: 0; background: transparent; color: #ffffff; font-size: 28px; line-height: 1; cursor: pointer; padding: 0; opacity: 0.7; transition: opacity 0.2s ease; } .top-alert__close:hover { opacity: 1; } .top-alert.is-hidden { display: none; } @media (max-width: 767px) { body.has-top-alert { --top-alert-height: 56px; } .top-alert__inner { min-height: 56px; padding: 8px 42px 8px 14px; } .top-alert__text { text-align: left; font-size: 12px; font-weight: 500; } .top-alert__close { right: 10px; width: 26px; height: 26px; font-size: 24px; } } document.addEventListener('DOMContentLoaded', function () { const alertBlock = document.getElementById('topAlert'); const closeButton = document.getElementById('topAlertClose'); const storageKey = 'vb_top_alert_payment_may_2026_closed'; if (!alertBlock || !closeButton) return; if (localStorage.getItem(storageKey) === 'true') { alertBlock.classList.add('is-hidden'); document.body.classList.remove('has-top-alert'); } else { document.body.classList.add('has-top-alert'); } closeButton.addEventListener('click', function () { alertBlock.classList.add('is-hidden'); document.body.classList.remove('has-top-alert'); localStorage.setItem(storageKey, 'true'); }); });
    Иконка телефона
    Телефон

    Поиск
    Войти
    Позвонить
    Меню
    Фильтр
    Сортировка
    Цена
    1180 82170
    Бренд
    Kатегория
    Коллекция
    Стиль
    Цвет
    Материал
    Новинка
    НОВИНКА
    СКИДКА
    Perlemor Coral Кружка 350 мл Perlemor Coral Кружка 350 мл Perlemor Coral Кружка 350 мл Perlemor Coral Кружка 350 мл
    Как вам новый сайт?
    Что улучшить?
    Спасибо
    .site-feedback { position: fixed; right: 20px; bottom: 20px; z-index: 9999; font-family: Arial, sans-serif; } .site-feedback__bar { display: flex; align-items: center; justify-content: flex-end; gap: 8px; } .site-feedback__trigger { border: none; background: #111; color: #fff; padding: 14px 18px; border-radius: 999px; font-size: 14px; cursor: pointer; box-shadow: 0 10px 30px rgba(0,0,0,0.2); transition: all 0.2s ease; position: relative; overflow: hidden; } .site-feedback__trigger:hover { transform: translateY(-2px); opacity: 0.9; } .site-feedback__trigger-text { position: relative; z-index: 1; } .site-feedback__flare { position: absolute; top: 0; left: -150%; width: 45px; height: 100%; transform: skewX(-25deg); background: linear-gradient(90deg, rgba(255,255,255,0.08), rgba(255,255,255,0.38)); animation: siteFeedbackFlare 3s linear infinite; } @keyframes siteFeedbackFlare { 0% { left: -150%; } 100% { left: 150%; } } .site-feedback__dismiss { width: 34px; height: 34px; border: none; border-radius: 50%; background: #fff; color: #111; font-size: 20px; line-height: 1; cursor: pointer; box-shadow: 0 10px 30px rgba(0,0,0,0.15); } .site-feedback__panel { position: absolute; right: 0; bottom: 60px; width: 320px; background: #fff; border-radius: 16px; box-shadow: 0 20px 50px rgba(0,0,0,0.18); padding: 20px; display: none; } .site-feedback.is-open .site-feedback__panel { display: block; } .site-feedback__close { position: absolute; top: 10px; right: 12px; border: none; background: none; font-size: 22px; cursor: pointer; } .site-feedback__title { font-size: 16px; font-weight: 600; margin-bottom: 14px; } .site-feedback__stars { display: flex; gap: 6px; } .site-feedback__star { border: none; background: none; font-size: 28px; color: #ccc; cursor: pointer; transition: 0.2s; } .site-feedback__star.active { color: #111; } .site-feedback__stats { margin-top: 12px; font-size: 13px; color: #666; display: none; } .site-feedback__stats.is-visible { display: block; } textarea { width: 100%; min-height: 90px; border-radius: 10px; border: 1px solid #ddd; padding: 10px; font-size: 14px; margin-bottom: 10px; } .site-feedback__submit { border: none; background: #111; color: #fff; padding: 10px 14px; border-radius: 999px; cursor: pointer; } .site-feedback__step--hidden { display: none; } document.addEventListener('DOMContentLoaded', () => { const widget = document.getElementById('siteFeedback'); const trigger = document.getElementById('siteFeedbackTrigger'); const close = document.getElementById('siteFeedbackClose'); const dismiss = document.getElementById('siteFeedbackDismiss'); const stars = document.querySelectorAll('.site-feedback__star'); const starsWrap = document.getElementById('feedbackStars'); const step1 = document.getElementById('feedbackStep1'); const step2 = document.getElementById('feedbackStep2'); const step3 = document.getElementById('feedbackStep3'); const submit = document.getElementById('feedbackSubmit'); const message = document.getElementById('feedbackMessage'); const stats = document.getElementById('feedbackStats'); let rating = 0; const hiddenKey = 'siteFeedbackHidden'; const votedKey = 'siteFeedbackVoted'; const feedbackEndpoint = '/feedback-widget/save_feedback.php'; const showStats = new URLSearchParams(window.location.search).get('feedbackStats') === '1'; function renderStats(serverStats) { if (!showStats || !serverStats || !serverStats.ratings) { return; } const ratings = serverStats.ratings; const lines = [ `5 звезд: ${Number(ratings['5']) || 0}`, `4 звезды: ${Number(ratings['4']) || 0}`, `3 звезды: ${Number(ratings['3']) || 0}`, `2 звезды: ${Number(ratings['2']) || 0}`, `1 звезда: ${Number(ratings['1']) || 0}`, `Всего: ${Number(serverStats.total) || 0}`, `С отзывом: ${Number(serverStats.withMessage) || 0}` ]; stats.innerHTML = lines.join('
    '); stats.classList.add('is-visible'); } async function requestStats() { if (!showStats) { return; } try { const response = await fetch(`${feedbackEndpoint}?feedbackStats=1`, { cache: 'no-store' }); const result = await response.json(); if (!response.ok || !result.success) { throw new Error(result.message || 'Failed to load stats'); } renderStats(result.stats); } catch (error) { stats.textContent = 'Не удалось загрузить статистику'; stats.classList.add('is-visible'); } } async function saveFeedbackToServer(value, text) { const response = await fetch(feedbackEndpoint, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' }, body: new URLSearchParams({ rating: String(value), message: text }).toString() }); const result = await response.json(); if (!response.ok || !result.success) { throw new Error(result.message || 'Failed to save feedback'); } return result; } function hideWidget() { widget.style.display = 'none'; localStorage.setItem(hiddenKey, '1'); } function finishVoting() { localStorage.setItem(votedKey, '1'); widget.classList.remove('is-open'); widget.style.display = 'none'; } function paintStars(value) { stars.forEach(star => { star.classList.toggle('active', Number(star.dataset.value) <= value); }); } if (!showStats && (localStorage.getItem(hiddenKey) === '1' || localStorage.getItem(votedKey) === '1')) { widget.style.display = 'none'; return; } if (showStats) { widget.classList.add('is-open'); } requestStats(); paintStars(rating); trigger.oncl ick = () => widget.classList.toggle('is-open'); close.oncl ick = () => widget.classList.remove('is-open'); dismiss.oncl ick = hideWidget; function showStep(step) { [step1, step2, step3].forEach(s => s.classList.add('site-feedback__step--hidden')); step.classList.remove('site-feedback__step--hidden'); } stars.forEach(star => { star.addEventListener('mouseenter', () => { paintStars(Number(star.dataset.value)); }); star.addEventListener('click', () => { rating = Number(star.dataset.value); paintStars(rating); if (rating <= 3) { showStep(step2); } else { saveFeedbackToServer(rating, '') .then(result => { renderStats(result.stats); showStep(step3); setTimeout(() => { finishVoting(); }, 1500); }) .catch(() => { alert('Не удалось сохранить оценку. Попробуйте еще раз.'); }); } }); }); starsWrap.addEventListener('mouseleave', () => { paintStars(rating); }); submit.oncl ick = async () => { const text = message.value.trim(); try { const result = await saveFeedbackToServer(rating, text); renderStats(result.stats); showStep(step3); setTimeout(() => { finishVoting(); message.value = ''; }, 2000); } catch (error) { alert('Не удалось сохранить отзыв. Попробуйте еще раз.'); } }; });