function PostViewer({ post, onClose, onComments, onMenu, onSuggest, onConfirm, onPlace, onUser }) {
  const { Avatar } = window.SpotureDesignSystem_f7ad96;
  const count = post.mediaCount || 1;
  const [active, setActive] = React.useState(0);
  const [liked, setLiked] = React.useState(!!post.liked);
  const [burst, setBurst] = React.useState(false);
  const [fit, setFit] = React.useState(false);
  const [tall, setTall] = React.useState(false);
  React.useEffect(() => { setTall(false); setFit(false); }, [post.src]);
  const drag = React.useRef(null);
  const tap = React.useRef({ time: 0 });
  const isVideo = post.hasVideo && active === count - 1;
  const tags = post.tags || {};
  const menuTags = (tags[active] && tags[active].length) ? tags[active] : (post.menu ? [post.menu] : []);
  const go = d => setActive(i => Math.min(count - 1, Math.max(0, i + d)));
  const onDown = e => { drag.current = { x: e.clientX, y: e.clientY }; };
  const onUp = e => {
    const d = drag.current; drag.current = null;
    if (!d) return;
    const dx = e.clientX - d.x, dy = e.clientY - d.y;
    if (Math.abs(dx) > 44 && Math.abs(dx) > Math.abs(dy)) { go(dx < 0 ? 1 : -1); return; }
    if (Math.abs(dx) > 10 || Math.abs(dy) > 10) return;
    const now = Date.now();
    if (now - tap.current.time < 300) { tap.current.time = 0; setLiked(true); setBurst(true); setTimeout(() => setBurst(false), 620); }
    else tap.current.time = now;
  };
  return (
    <div style={{ position: 'fixed', inset: 0, background: '#0E0E0E', zIndex: 80, overflow: 'hidden' }}>
      <div onPointerDown={onDown} onPointerUp={onUp} style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', touchAction: 'pan-y', userSelect: 'none' }}>
        <div style={{ position: 'absolute', inset: 0, background: post.src ? 'transparent' : '#1A1A1A' }}>
          {post.src && fit && <div style={{ position: 'absolute', inset: 0, backgroundImage: 'url(' + post.src + ')', backgroundSize: 'cover', backgroundPosition: 'center', filter: 'blur(34px) saturate(.7) brightness(.5)', transform: 'scale(1.12)' }}></div>}
          <div style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
            {post.src ? <img src={post.src} alt={post.place || '사진'} onLoad={e => { const t = e.target; setTall(t.naturalHeight / t.naturalWidth > 1.25); }} style={{ width: '100%', height: 'auto', maxHeight: fit ? '100%' : 'none', objectFit: 'contain', display: 'block' }} /> : <div style={{ width: '100%', height: '100%', display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 8, background: '#2E2E2E' }}><i className="ti ti-photo" style={{ fontSize: 28, color: 'rgba(255,255,255,.34)' }}></i><span style={{ font: '600 12px/1 var(--font-family)', color: 'rgba(255,255,255,.34)' }}>사진</span></div>}
          </div>
          <div style={{ position: 'absolute', inset: 0 }}></div>
          {isVideo && <div style={{ position: 'absolute', top: '50%', left: '50%', transform: 'translate(-50%,-50%)', width: 62, height: 62, borderRadius: '50%', background: 'rgba(26,26,26,.6)', display: 'flex', alignItems: 'center', justifyContent: 'center', pointerEvents: 'none' }}><i className="ti ti-player-play" style={{ fontSize: 24, color: '#fff' }}></i></div>}
        </div>
        {count > 1 && (
          <span style={{ position: 'absolute', top: 100, right: 16, font: '600 12px/1 var(--font-family)', color: '#fff', background: 'rgba(26,26,26,.66)', borderRadius: 999, padding: '8px 12px' }}>{active + 1}/{count}</span>
        )}
        {burst && <i className="ti ti-heart" style={{ position: 'absolute', fontSize: 104, color: 'rgba(227,30,36,.92)', animation: 'spotureBurst .62s ease-out forwards', pointerEvents: 'none' }}></i>}
        {count > 1 && (
          <div style={{ position: 'absolute', left: 0, right: 0, bottom: 12, display: 'flex', justifyContent: 'center', gap: 6, zIndex: 2 }}>
            {Array.from({ length: count }, (_, i) => <span key={i} onClick={() => setActive(i)} style={{ width: i === active ? 18 : 6, height: 6, borderRadius: 999, background: i === active ? '#fff' : 'rgba(255,255,255,.4)', cursor: 'pointer', transition: 'width .18s ease' }}></span>)}
          </div>
        )}
      </div>
      <div style={{ position: 'absolute', inset: 0, display: 'flex', flexDirection: 'column', pointerEvents: 'none' }}>
      <div style={{ flexShrink: 0, background: 'linear-gradient(to bottom, rgba(0,0,0,.72) 0%, rgba(0,0,0,.42) 55%, transparent 100%)', paddingBottom: 10, pointerEvents: 'auto' }}>
      <div className="statusbar" style={{ color: '#fff' }}>
        <span>9:41</span>
        <span className="icons"><i className="ti ti-antenna-bars-5"></i><i className="ti ti-wifi"></i><i className="ti ti-battery-2"></i></span>
      </div>
      <div style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '6px 16px 14px' }}>
        <div onClick={onClose} style={{ width: 40, height: 40, borderRadius: '50%', background: 'rgba(255,255,255,.12)', display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer', flexShrink: 0 }}><i className="ti ti-x" style={{ fontSize: 19, color: '#fff' }}></i></div>
        <div onClick={onUser} style={{ flex: 1, minWidth: 0, display: 'flex', alignItems: 'center', gap: 10, cursor: onUser ? 'pointer' : 'default' }}>
          <Avatar user={post.user} size={36} />
          <div style={{ minWidth: 0 }}>
            <span style={{ font: 'var(--text-body-strong)', color: '#fff', display: 'block' }}>{post.user}</span>
            <span style={{ font: 'var(--text-small)', color: 'rgba(255,255,255,.6)' }}>{[post.meal, post.category].filter(Boolean).join(' · ')}</span>
          </div>
        </div>
        {post.src && tall && <div onClick={() => setFit(f => !f)} style={{ width: 40, height: 40, borderRadius: '50%', background: 'rgba(255,255,255,.12)', display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer', flexShrink: 0 }}><i className={fit ? 'ti ti-arrows-maximize' : 'ti ti-arrows-minimize'} style={{ fontSize: 18, color: '#fff' }}></i></div>}
        <div onClick={onMenu} style={{ width: 40, height: 40, borderRadius: '50%', background: 'rgba(255,255,255,.12)', display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer', flexShrink: 0 }}><i className="ti ti-dots" style={{ fontSize: 19, color: '#fff' }}></i></div>
      </div>
      </div>
      <div style={{ flex: '1 1 0%', minHeight: 0 }}></div>
      <div style={{ flexShrink: 0, padding: '46px 16px 42px', background: 'linear-gradient(to top, rgba(0,0,0,.82) 0%, rgba(0,0,0,.55) 46%, transparent 100%)', pointerEvents: 'auto' }}>
        {menuTags.length > 0 && (
          <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', marginBottom: 10 }}>
            {menuTags.map(t => <span key={t} style={{ font: '500 13px/1 var(--font-family)', color: '#fff', background: 'rgba(26,26,26,.5)', backdropFilter: 'blur(10px)', border: '1px solid rgba(255,255,255,.24)', borderRadius: 999, padding: '9px 13px' }}>#{t}</span>)}
          </div>
        )}
        <div style={{ background: 'rgba(255,255,255,.09)', backdropFilter: 'blur(16px)', border: '1px solid rgba(255,255,255,.14)', borderRadius: 18, overflow: 'hidden' }}>
          {post.mission || post.place ? (
            <div onClick={onPlace} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '13px 12px 13px 16px', cursor: 'pointer' }}>
              <i className={post.mission ? 'ti ti-building-store' : 'ti ti-map-pin'} style={{ fontSize: 19, color: '#fff', flexShrink: 0 }}></i>
              <div style={{ flex: 1, minWidth: 0 }}>
                <span style={{ font: '600 15px/1.3 var(--font-family)', color: '#fff', display: 'block', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{post.place || '식탁이있는삶 역삼점'}</span>
                <span style={{ font: 'var(--text-micro)', color: 'rgba(255,255,255,.62)' }}>{post.mission ? '스폰서 판매처 · ' + (post.distance || '320m') : [[post.city, post.area].filter(Boolean).join(' '), post.distance || post.dist].filter(Boolean).join(' · ')}</span>
              </div>
              <span style={{ flexShrink: 0, display: 'inline-flex', alignItems: 'center', gap: 6, font: '600 14px/1 var(--font-family)', color: 'var(--text-primary)', background: '#fff', borderRadius: 999, padding: '6px 6px 6px 14px' }}>길찾기<span style={{ width: 30, height: 30, borderRadius: '50%', background: 'var(--text-primary)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}><i className="ti ti-arrow-right" style={{ fontSize: 16, color: '#fff' }}></i></span></span>
            </div>
          ) : post.estimatedLocation ? (
            <div style={{ padding: '13px 16px', background: 'rgba(214,158,46,.16)' }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
                <i className="ti ti-map-pin-question" style={{ fontSize: 19, color: 'var(--text-warning)', flexShrink: 0 }}></i>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <span style={{ font: '600 15px/1.3 var(--font-family)', color: '#fff', display: 'block', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{post.estimatedLocation}<span style={{ font: 'var(--text-micro)', color: 'rgba(255,255,255,.62)' }}> · 추정</span></span>
                  <span style={{ font: 'var(--text-micro)', color: 'rgba(255,255,255,.62)' }}>이웃 제보 {post.reportCount || 2}건 · {post.isMine ? '승인하면 위치가 채워져요' : '작성자 승인 전'}</span>
                </div>
                {post.isMine
                  ? <span onClick={onConfirm} style={{ flexShrink: 0, font: '600 13px/1 var(--font-family)', color: 'var(--text-primary)', background: '#fff', borderRadius: 999, padding: '12px 15px', cursor: 'pointer' }}>제보 확인</span>
                  : <span onClick={onSuggest} style={{ flexShrink: 0, font: '600 13px/1 var(--font-family)', color: '#fff', background: 'rgba(255,255,255,.18)', border: '1px solid rgba(255,255,255,.3)', borderRadius: 999, padding: '12px 15px', cursor: 'pointer' }}>다른 곳 제보</span>}
              </div>
            </div>
          ) : (
            <div onClick={onSuggest} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '13px 16px', cursor: 'pointer' }}>
              <i className={post.isMine ? 'ti ti-map-pin-off' : 'ti ti-map-pin-question'} style={{ fontSize: 19, color: 'rgba(255,255,255,.8)', flexShrink: 0 }}></i>
              <div style={{ flex: 1, minWidth: 0 }}>
                <span style={{ font: '600 15px/1.3 var(--font-family)', color: '#fff', display: 'block' }}>{post.isMine ? '장소가 아직 비어 있어요' : '여기 어디예요?'}</span>
                <span style={{ font: 'var(--text-micro)', color: 'rgba(255,255,255,.62)' }}>{post.isMine ? '들어온 제보 없음 · 직접 지정할 수 있어요' : '아시는 곳이면 알려주세요'}</span>
              </div>
              <span style={{ flexShrink: 0, font: '600 13px/1 var(--font-family)', color: '#fff', background: 'var(--text-accent)', borderRadius: 999, padding: '12px 16px' }}>{post.isMine ? '지정하기' : '알려주기'}</span>
            </div>
          )}
        </div>
      </div>
      </div>
    </div>
  );
}
window.PostViewer = PostViewer;
