(function() {
  var useState  = React.useState;
  var useEffect = React.useEffect;
  var useRef    = React.useRef;
  var Icon      = window.CBIcon; // crisp Lucide-style SVG icons (app-wide set)

  var ZONE_COLOR = { residential:'#35d0e0', commercial:'#b06cff', civic:'#ff5aa0', industrial:'#f2b23a', parks:'#9be23a' };

  function timeAgo(iso) {
    var s = Math.max(1, Math.floor((Date.now() - new Date(iso).getTime()) / 1000));
    if (s < 60) return s + 's';
    if (s < 3600) return Math.floor(s / 60) + 'm';
    if (s < 86400) return Math.floor(s / 3600) + 'h';
    if (s < 604800) return Math.floor(s / 86400) + 'd';
    return Math.floor(s / 604800) + 'w';
  }

  function initialsOf(name) {
    return (name || '?').split(' ').map(function(n){ return n[0] || ''; }).join('').slice(0, 2).toUpperCase();
  }

  function needLogin() {
    if (window.AuthState && window.AuthState.isLoggedIn()) return false;
    window.showUserToast('Sign in to join the conversation', 'rose');
    return true;
  }

  /* Vertex-generated action glyph (assets/gamification/social/, --set social)
     with an emoji fallback until the art is generated. */
  function SIcon(props) {
    var _f = useState(false); var failed = _f[0], setFailed = _f[1];
    var size = props.size || 24;
    if (failed) {
      return React.createElement('span', {
        className: 'sicon-fb', style: { fontSize: Math.round(size * 0.82) },
      }, props.fallback);
    }
    return React.createElement('img', {
      className: 'sicon',
      src: '/assets/gamification/social/' + props.name + '.png',
      alt: '', draggable: false,
      style: { width: size, height: size },
      onError: function() { setFailed(true); },
    });
  }
  window.CBSocialIcon = SIcon;

  /* ── One Instagram-style post card ─────────────────────────────────────── */
  function PostCard(props) {
    var post = props.post;
    var _p = useState(post);            var p = _p[0], setP = _p[1];
    var _showAfter = useState(true);    var showAfter = _showAfter[0], setShowAfter = _showAfter[1];
    var _burst = useState(false);       var burst = _burst[0], setBurst = _burst[1];
    var _comments = useState(null);     var comments = _comments[0], setComments = _comments[1];
    var _cInput = useState('');         var cInput = _cInput[0], setCInput = _cInput[1];
    var _busy = useState(false);        var busy = _busy[0], setBusy = _busy[1];
    var lastTap = useRef(0);

    var hover = function(){ document.body.classList.add('hov'); };
    var leave = function(){ document.body.classList.remove('hov'); };

    function toggleLike() {
      if (needLogin()) return;
      // Optimistic ♥ — snap the UI, then reconcile with the server
      setP(function(s){ return Object.assign({}, s, { likedByMe: !s.likedByMe, likes: s.likes + (s.likedByMe ? -1 : 1) }); });
      window.ApiClient.post('/social/projects/' + p.id + '/like', {})
        .then(function(r){ setP(function(s){ return Object.assign({}, s, { likedByMe: r.liked, likes: r.likes }); }); })
        .catch(function(){ setP(function(s){ return Object.assign({}, s, { likedByMe: !s.likedByMe }); }); });
    }

    function onMediaTap() {
      var now = Date.now();
      if (now - lastTap.current < 320) {          // double-tap = like + heart burst
        if (!p.likedByMe) toggleLike();
        setBurst(true);
        setTimeout(function(){ setBurst(false); }, 900);
      }
      lastTap.current = now;
    }

    function openComments() {
      if (comments) { setComments(null); return; }
      window.ApiClient.get('/social/projects/' + p.id + '/comments')
        .then(function(r){ setComments(r.comments || []); })
        .catch(function(){ window.showUserToast('Could not load comments', 'rose'); });
    }

    function postComment() {
      if (needLogin()) return;
      var text = cInput.trim();
      if (!text || busy) return;
      setBusy(true);
      window.ApiClient.post('/social/projects/' + p.id + '/comments', { text: text })
        .then(function(c) {
          setCInput('');
          setComments(function(list){ return [c].concat(list || []); });
          setP(function(s){ return Object.assign({}, s, { comments: s.comments + 1 }); });
        })
        .catch(function(e){ window.showUserToast(e.message || 'Comment failed', 'rose'); })
        .finally(function(){ setBusy(false); });
    }

    function likeComment(c) {
      if (needLogin()) return;
      window.ApiClient.post('/social/comments/' + c._id + '/like', {})
        .then(function(r) {
          setComments(function(list) {
            return (list || []).map(function(x){
              return x._id === c._id ? Object.assign({}, x, { likes: r.likes, likedByMe: r.liked }) : x;
            });
          });
        }).catch(function(){});
    }

    function share() {
      var url = window.location.origin + window.location.pathname + '#project-' + p.id;
      var done = function(){
        setP(function(s){ return Object.assign({}, s, { shares: (s.shares || 0) + 1 }); });
        window.ApiClient.post('/social/projects/' + p.id + '/share', {}).catch(function(){});
      };
      if (navigator.share) {
        navigator.share({ title: 'CityBuildRR — ' + p.title, text: p.title, url: url }).then(done).catch(function(){});
      } else {
        try {
          navigator.clipboard.writeText(url);
          window.showUserToast('Link copied', 'violet');
          done();
        } catch (e) { window.showUserToast('Could not copy link', 'rose'); }
      }
    }

    function message() {
      if (needLogin()) return;
      if (!p.author) return;
      window.navigate('messages', { userId: p.author._id, userName: p.author.name });
    }

    function openProject() { window.navigate('project-detail', { id: p.id }); }

    var media = showAfter ? p.afterUrl : (p.beforeUrl || p.afterUrl);
    var zoneColor = ZONE_COLOR[p.zone] || '#b06cff';

    var fundPct = p.funding && p.funding.goal > 0
      ? Math.min(100, Math.round((p.funding.raised / p.funding.goal) * 100))
      : null;

    /* Media-led card: identity rides on the image over a scrim, so the render
       is the hero and the chrome reads as an overlay on a place — not a
       social-network header band stacked above a photo. */
    return React.createElement('article', { className: 'feed-card' },

      React.createElement('div', { className: 'feed-media', onClick: onMediaTap },
        media
          ? React.createElement('img', { src: media, alt: p.title, loading: 'lazy' })
          : React.createElement('div', { className: 'feed-media-empty' },
              React.createElement(Icon, { name: 'building', size: 40 })),

        React.createElement('div', { className: 'feed-media-scrim', 'aria-hidden': 'true' }),

        React.createElement('header', { className: 'feed-head' },
          React.createElement('div', {
            className: 'feed-avatar',
            style: { background: 'linear-gradient(135deg,' + zoneColor + ',#8b5cf6)' },
          },
            p.author && p.author.avatar
              ? React.createElement('img', { src: p.author.avatar, alt: '' })
              : initialsOf(p.author && p.author.name)),
          React.createElement('div', { className: 'feed-head-meta' },
            React.createElement('div', { className: 'feed-author' }, (p.author && p.author.name) || 'Builder'),
            React.createElement('div', { className: 'feed-sub' },
              (p.district ? p.district + ' · ' : '') + p.zone + ' · ' + timeAgo(p.createdAt))),
          p.author && React.createElement('button', {
            type: 'button', className: 'feed-msg-btn', onClick: function(e){ e.stopPropagation(); message(); },
            onMouseEnter: hover, onMouseLeave: leave, 'aria-label': 'Message ' + ((p.author && p.author.name) || 'builder'),
          }, React.createElement(Icon, { name: 'mail', size: 16 }))),

        p.has3D && React.createElement('button', {
          type: 'button', className: 'feed-3d-chip',
          onClick: function(e){ e.stopPropagation(); openProject(); },
          onMouseEnter: hover, onMouseLeave: leave, 'aria-label': 'Open in 3D and AR',
        }, React.createElement(Icon, { name: 'box', size: 13 }), 'Live in AR'),

        p.beforeUrl && p.afterUrl && p.beforeUrl !== p.afterUrl && React.createElement('div', {
          className: 'feed-ba', role: 'group', 'aria-label': 'Compare before and after',
        },
          React.createElement('button', {
            type: 'button', className: 'feed-ba-btn' + (!showAfter ? ' on' : ''),
            'aria-pressed': !showAfter,
            onClick: function(e){ e.stopPropagation(); setShowAfter(false); },
          }, 'Before'),
          React.createElement('button', {
            type: 'button', className: 'feed-ba-btn' + (showAfter ? ' on' : ''),
            'aria-pressed': showAfter,
            onClick: function(e){ e.stopPropagation(); setShowAfter(true); },
          }, 'After')),

        burst && React.createElement('div', { className: 'feed-heart-burst' },
          React.createElement(Icon, { name: 'heart-fill', size: 96 }))
      ),

      React.createElement('div', { className: 'feed-body' },

        React.createElement('h3', { className: 'feed-card-title' }, p.title),
        p.description && React.createElement('p', { className: 'feed-caption' },
          p.description.length > 150 ? p.description.slice(0, 147) + '…' : p.description),

        fundPct !== null && React.createElement('div', { className: 'feed-funding' },
          React.createElement('div', { className: 'feed-funding-head' },
            React.createElement('span', { className: 'feed-funding-raised' },
              '$' + Math.round(p.funding.raised / 1000) + 'K'),
            React.createElement('span', { className: 'feed-funding-goal' },
              'of $' + Math.round(p.funding.goal / 1000) + 'K goal'),
            React.createElement('span', { className: 'feed-funding-pct' }, fundPct + '%')),
          React.createElement('div', {
            className: 'feed-funding-bar', role: 'progressbar',
            'aria-valuenow': fundPct, 'aria-valuemin': 0, 'aria-valuemax': 100,
            'aria-label': 'Funding progress',
          }, React.createElement('span', { style: { width: fundPct + '%' } }))),

        React.createElement('div', { className: 'feed-actions' },
          React.createElement('button', {
            type: 'button', className: 'feed-act' + (p.likedByMe ? ' liked' : ''), onClick: toggleLike,
            onMouseEnter: hover, onMouseLeave: leave,
            'aria-label': p.likedByMe ? 'Unlike' : 'Like', 'aria-pressed': !!p.likedByMe,
          }, React.createElement(Icon, { name: p.likedByMe ? 'heart-fill' : 'heart', size: 22 })),
          React.createElement('button', {
            type: 'button', className: 'feed-act', onClick: openComments,
            onMouseEnter: hover, onMouseLeave: leave, 'aria-label': 'Comments',
          }, React.createElement(Icon, { name: 'message-circle', size: 22 })),
          React.createElement('button', {
            type: 'button', className: 'feed-act', onClick: share,
            onMouseEnter: hover, onMouseLeave: leave, 'aria-label': 'Share',
          }, React.createElement(Icon, { name: 'send', size: 21 })),
          React.createElement('div', { className: 'feed-actions-spacer' }),
          React.createElement('button', {
            type: 'button', className: 'feed-act-3d', onClick: openProject,
            onMouseEnter: hover, onMouseLeave: leave,
          },
            React.createElement(Icon, { name: p.has3D ? 'box' : 'arrow-right', size: 15 }),
            p.has3D ? 'View in 3D' : 'View project')),

        React.createElement('div', { className: 'feed-likes' },
          p.likes > 0 ? p.likes.toLocaleString() + (p.likes === 1 ? ' like' : ' likes') : 'Be the first to like this'),

        !comments && p.comments > 0 && React.createElement('button', {
          type: 'button', className: 'feed-viewall', onClick: openComments,
          onMouseEnter: hover, onMouseLeave: leave,
        }, 'View all ' + p.comments + ' comments'),
        !comments && (p.topComments || []).map(function(c) {
          return React.createElement('div', { key: c._id, className: 'feed-comment' },
            React.createElement('strong', null, (c.author && c.author.name) || 'Builder'), ' ', c.text);
        }),
        comments && React.createElement('div', { className: 'feed-comment-list' },
          comments.length === 0 && React.createElement('div', { className: 'feed-comment-empty' }, 'No comments yet — start the conversation'),
          comments.map(function(c) {
            return React.createElement('div', { key: c._id, className: 'feed-comment feed-comment-row' },
              React.createElement('div', { style: { flex: 1, minWidth: 0 } },
                React.createElement('strong', null, (c.author && c.author.name) || 'Builder'), ' ', c.text,
                React.createElement('span', { className: 'feed-comment-time' }, ' · ' + timeAgo(c.createdAt))),
              React.createElement('button', {
                type: 'button', className: 'feed-comment-like' + (c.likedByMe ? ' on' : ''),
                onClick: function(){ likeComment(c); },
                onMouseEnter: hover, onMouseLeave: leave,
                'aria-label': c.likedByMe ? 'Unlike comment' : 'Like comment',
              },
                React.createElement(Icon, { name: c.likedByMe ? 'heart-fill' : 'heart', size: 13 }),
                c.likes ? React.createElement('span', null, c.likes) : null));
          })),

        React.createElement('div', { className: 'feed-compose' },
          React.createElement('input', {
            type: 'text', className: 'feed-compose-input', placeholder: 'Add a comment…',
            'aria-label': 'Add a comment',
            value: cInput, maxLength: 1000,
            onChange: function(e){ setCInput(e.target.value); },
            onKeyDown: function(e){ if (e.key === 'Enter') postComment(); },
            onFocus: function(){ if (!comments) openComments(); },
          }),
          React.createElement('button', {
            type: 'button', className: 'feed-compose-post', disabled: !cInput.trim() || busy,
            onClick: postComment, onMouseEnter: hover, onMouseLeave: leave,
          }, 'Post'))
      )
    );
  }

  /* ── The feed page (home screen) ───────────────────────────────────────── */
  function FeedPage() {
    var _posts = useState([]);   var posts = _posts[0], setPosts = _posts[1];
    var _page  = useState(1);    var page = _page[0], setPage = _page[1];
    var _pages = useState(1);    var pages = _pages[0], setPages = _pages[1];
    var _load  = useState(true); var loading = _load[0], setLoading = _load[1];
    var _err   = useState(null); var err = _err[0], setErr = _err[1];
    var initTab = (window.UserRouter && window.UserRouter.getParams().tab) || 'foryou';
    var _tab   = useState(initTab); var tab = _tab[0], setTab = _tab[1];
    var _zone  = useState('all');   var zone = _zone[0], setZone = _zone[1];
    function fetchPage(n, append) {
      setLoading(true);
      window.ApiClient.get('/social/feed?page=' + n)
        .then(function(r) {
          setPosts(function(prev){ return append ? prev.concat(r.posts) : r.posts; });
          setPage(r.page); setPages(r.pages); setErr(null);
        })
        .catch(function(e){ setErr(e.message || 'Could not load the feed'); })
        .finally(function(){ setLoading(false); });
    }

    useEffect(function(){ fetchPage(1, false); }, []);

    var hover = function(){ document.body.classList.add('hov'); };
    var leave = function(){ document.body.classList.remove('hov'); };

    /* Tab + zone filtering — pure client-side views over the same live feed */
    var shown = posts.slice();
    if (tab === 'following') shown = shown.filter(function(p){ return p.likedByMe; });
    if (tab === 'trending')  shown.sort(function(a, b){ return (b.engagementScore || 0) - (a.engagementScore || 0); });
    if (zone !== 'all')      shown = shown.filter(function(p){ return p.zone === zone; });

    function TabBtn(id, label) {
      return React.createElement('button', {
        type: 'button', className: 'fx-tab' + (tab === id ? ' on' : ''),
        onClick: function(){ setTab(id); }, onMouseEnter: hover, onMouseLeave: leave,
      }, label);
    }

    var feedHero = React.createElement('header', { className: 'fx-hero' },
      React.createElement('h1', { className: 'fx-hero-title' },
        'Community ', React.createElement('span', { className: 'fx-hero-accent' }, 'Feed')),
      React.createElement('p', { className: 'fx-hero-sub' }, 'Real people. Real places. Real change.'),
      React.createElement('div', { className: 'fx-hero-row' },
        React.createElement('div', { className: 'fx-tabs' },
          TabBtn('foryou', 'For You'), TabBtn('following', 'Following'), TabBtn('trending', 'Trending')),
        React.createElement('select', {
          className: 'fx-zone-select', value: zone, 'aria-label': 'Filter posts',
          onChange: function(e){ setZone(e.target.value); },
        },
          React.createElement('option', { value: 'all' }, 'All Posts'),
          React.createElement('option', { value: 'civic' }, 'Civic'),
          React.createElement('option', { value: 'commercial' }, 'Commercial'),
          React.createElement('option', { value: 'residential' }, 'Residential'),
          React.createElement('option', { value: 'parks' }, 'Parks'))));

    var feedCol = React.createElement('div', { className: 'user-screen feed-screen' },
      feedHero,
      err && React.createElement('div', { className: 'feed-error' }, err),

      shown.map(function(p){ return React.createElement(PostCard, { key: p.id, post: p }); }),

      !loading && posts.length > 0 && shown.length === 0 && !err &&
        React.createElement('div', { className: 'feed-empty fx-filter-empty' },
          React.createElement('p', null, tab === 'following'
            ? 'Nothing here yet — like a build to follow it.'
            : 'No posts match this filter.')),

      loading && React.createElement('div', { className: 'feed-loading' },
        React.createElement('div', { className: 'ar-model-spinner' })),

      !loading && posts.length === 0 && !err && React.createElement('div', { className: 'feed-empty' },
        React.createElement(SIcon, { name: 'empty-feed', fallback: '', size: 220 }),
        React.createElement('p', null, 'No visions yet. Photograph a place to begin.'),
        React.createElement('button', {
          type: 'button', className: 'btn btn-v', onClick: function(){ window.navigate('submit'); },
          onMouseEnter: hover, onMouseLeave: leave,
        }, React.createElement(Icon, { name: 'sparkles', size: 16 }), 'Create the first vision')),

      !loading && page < pages && React.createElement('button', {
        type: 'button', className: 'btn btn-o feed-more',
        onClick: function(){ fetchPage(page + 1, true); },
        onMouseEnter: hover, onMouseLeave: leave,
      }, 'Load more')
    );

    /* Desktop shell: side rail | feed | community rail (rails hidden <1024px) */
    return React.createElement('div', { className: 'fx-shell' },
      window.CBFeedSideRail && React.createElement(window.CBFeedSideRail, {
        active: tab === 'following' ? 'following' : 'feed',
        onFollowing: function(){ setTab('following'); window.scrollTo({ top: 0, behavior: 'smooth' }); },
      }),
      feedCol,
      window.CBFeedRightRail && React.createElement(window.CBFeedRightRail, { posts: posts }));
  }

  window.UserFeedPage = FeedPage;
})();
