      <script>
      (function(){
        const csrf = <?= json_encode(function_exists('csrf_token') ? (string)csrf_token() : '', JSON_UNESCAPED_UNICODE) ?>;

        const REACT_I18N = <?= json_encode([
          'likes' => $T('Лайків', 'Лайков', 'Likes'),
          'dislikes' => $T('Дизлайків', 'Дизлайков', 'Dislikes'),
        ], JSON_UNESCAPED_UNICODE) ?>;

        async function hydratePreview(el){
          const url = el.getAttribute('data-lp-url');
          if (!url) return;

          const img = el.querySelector('img');
          const hasImg = img && img.getAttribute('src');
          const hasDesc = el.querySelector('.lp-desc')?.textContent?.trim();
          const hasSite = el.querySelector('.lp-site')?.textContent?.trim();

          if (hasImg || hasDesc || hasSite) return;

          try{
            const res = await fetch('/link_preview.php?url=' + encodeURIComponent(url), { headers:{'Accept':'application/json'} });
            const data = await res.json();
            if (!data || !data.ok) return;

            const t = el.querySelector('.lp-title');
            if (t) t.textContent = (data.title || data.url || '').trim();

            if (data.description) {
              let d = el.querySelector('.lp-desc');
              if (!d) {
                d = document.createElement('div');
                d.className = 'lp-desc';
                el.querySelector('.lp-meta')?.appendChild(d);
              }
              d.textContent = data.description;
            }

            if (data.site_name) {
              let s = el.querySelector('.lp-site');
              if (!s) {
                s = document.createElement('div');
                s.className = 'lp-site';
                el.querySelector('.lp-meta')?.appendChild(s);
              }
              s.textContent = data.site_name;
            }

            if (data.image && img) {
              img.src = data.image;
              img.style.display = 'block';
            }
          }catch(e){}
        }

        const previewEls = Array.from(document.querySelectorAll('.lp-card-feed[data-lp-url]'));
        previewEls.forEach(hydratePreview);

        document.addEventListener('click', async (e) => {
          const btn = e.target.closest('button[data-react][data-post]');
          if (!btn) return;
          e.preventDefault();

          const postId = btn.getAttribute('data-post');
          const reaction = btn.getAttribute('data-react');

          try {
            const body = new URLSearchParams();
            body.set('csrf', csrf);
            body.set('post_id', postId);
            body.set('reaction', reaction);
            body.set('back', location.pathname + location.search + '#post-' + postId);

            const res = await fetch('/post_react.php', {
              method: 'POST',
              headers: {
                'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
                'X-Requested-With': 'XMLHttpRequest',
                'Accept': 'application/json'
              },
              body
            });

            const data = await res.json();
            if (!data || !data.ok) return location.reload();

            const wrap = document.getElementById('post-' + postId);
            if (wrap) {
              const likeBtn = wrap.querySelector('button[data-react="like"]');
              const disBtn  = wrap.querySelector('button[data-react="dislike"]');
              const likesEl = document.getElementById('likes-' + postId);
              const dislikesEl = document.getElementById('dislikes-' + postId);

              if (likesEl) likesEl.textContent = data.likes;
              if (dislikesEl) dislikesEl.textContent = data.dislikes;

              if (likeBtn) {
                likeBtn.classList.remove('btn-outline-success', 'btn-success');
                likeBtn.classList.add(data.my === 'like' ? 'btn-success' : 'btn-outline-success');
                likeBtn.title = (REACT_I18N.likes || 'Likes') + ': ' + data.likes;
              }

              if (disBtn) {
                disBtn.classList.remove('btn-outline-danger', 'btn-danger');
                disBtn.classList.add(data.my === 'dislike' ? 'btn-danger' : 'btn-outline-danger');
                disBtn.title = (REACT_I18N.dislikes || 'Dislikes') + ': ' + data.dislikes;
              }
            }
          } catch (err) {
            location.reload();
          }
        });

        document.addEventListener('click', async (e) => {
          const btn = e.target.closest('button[data-cmtreact][data-comment]');
          if (!btn) return;
          e.preventDefault();

          const commentId = btn.getAttribute('data-comment');
          const reaction = btn.getAttribute('data-cmtreact');

          try {
            const body = new URLSearchParams();
            body.set('csrf', csrf);
            body.set('comment_id', commentId);
            body.set('reaction', reaction);
            body.set('back', location.pathname + location.search + '#comment-' + commentId);

            const res = await fetch('/comment_react.php', {
              method: 'POST',
              headers: {
                'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
                'X-Requested-With': 'XMLHttpRequest',
                'Accept': 'application/json'
              },
              body
            });

            const data = await res.json();
            if (!data || !data.ok) return location.reload();

            const likesEl = document.getElementById('clikes-' + commentId);
            const dislikesEl = document.getElementById('cdislikes-' + commentId);

            if (likesEl) likesEl.textContent = data.likes;
            if (dislikesEl) dislikesEl.textContent = data.dislikes;

            const root = document.getElementById('comment-' + commentId);
            if (root) {
              const likeBtn = root.querySelector('button[data-cmtreact="like"]');
              const disBtn  = root.querySelector('button[data-cmtreact="dislike"]');

              if (likeBtn) {
                likeBtn.classList.remove('btn-outline-success', 'btn-success');
                likeBtn.classList.add(data.my === 'like' ? 'btn-success' : 'btn-outline-success');
                likeBtn.title = (REACT_I18N.likes || 'Likes') + ': ' + data.likes;
              }

              if (disBtn) {
                disBtn.classList.remove('btn-outline-danger', 'btn-danger');
                disBtn.classList.add(data.my === 'dislike' ? 'btn-danger' : 'btn-outline-danger');
                disBtn.title = (REACT_I18N.dislikes || 'Dislikes') + ': ' + data.dislikes;
              }
            }
          } catch (err) {
            location.reload();
          }
        });

        document.addEventListener('click', (e) => {
          const openBtn = e.target.closest('[data-reply-toggle]');
          if (openBtn) {
            const id = openBtn.getAttribute('data-reply-toggle');
            const box = document.getElementById('reply-form-' + id);
            if (box) box.classList.toggle('d-none');
            if (window.VMEmojiInit) window.VMEmojiInit();
            return;
          }

          const cancelBtn = e.target.closest('[data-reply-cancel]');
          if (cancelBtn) {
            const id = cancelBtn.getAttribute('data-reply-cancel');
            const box = document.getElementById('reply-form-' + id);
            if (box) box.classList.add('d-none');
          }
        });

        if (window.VMEmojiInit) window.VMEmojiInit();
      })();
      </script>
