function MyPostMenuSheet({ post, onClose, onEdit, onPhotos, onHide, onShare, onDelete, onLike, onComments, liked }) {
  const { BottomSheet } = window.SpotureDesignSystem_f7ad96;
  const p = post || {};
  const count = p.mediaCount || 1;
  const hidden = !!p.hidden;
  const acc = accountVis();
  const pvis = p.vis || (hidden ? 'private' : 'public');
  const title = p.menu ? '#' + p.menu : (p.place || '내 게시물');
  const meta = [p.place && p.menu ? p.place : null, '사진 ' + count + '장', p.time].filter(Boolean).join(' · ');
  const rows = [
    { icon: 'pencil', label: '게시물 수정', sub: '메뉴 태그 · 본문 · 시간대 바꾸기', act: onEdit },
    { icon: 'photo-edit', label: '사진 관리', sub: '사진 ' + count + '장 중 일부만 지우기', act: onPhotos },
    { icon: visMeta(pvis).icon, label: '공개 범위', sub: visMeta(pvis).label + (visCapped(acc, pvis) ? ' · 계정 설정 때문에 지금은 ' + visMeta(effVis(acc, pvis)).label : ''), act: onHide },
    { icon: 'share-2', label: '공유하기', sub: '링크 복사 · 카카오톡', act: onShare },
    { icon: 'trash', label: '게시물 삭제', sub: '사진 전체와 좋아요·댓글이 사라져요', act: onDelete, danger: true }
  ];
  return (
    <BottomSheet title="내 게시물" onClose={onClose}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 12, background: 'var(--surface-2)', borderRadius: 'var(--radius-tile)', padding: 12, marginBottom: 14 }}>
        <div style={{ width: 48, height: 48, borderRadius: 12, background: 'var(--surface-1)', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}><i className={p.hasVideo ? 'ti ti-video' : 'ti ti-photo'} style={{ fontSize: 19, color: 'var(--text-muted)' }}></i></div>
        <div style={{ minWidth: 0 }}>
          <div style={{ font: 'var(--text-body-strong)', marginBottom: 3, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{title}</div>
          <div style={{ font: 'var(--text-micro)', color: 'var(--text-muted)' }}>{meta}</div>
        </div>
      </div>
      {onLike && (
        <div style={{ display: 'flex', gap: 8, marginBottom: 14 }}>
          <div onClick={onLike} style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 6, background: liked ? 'var(--bg-accent)' : 'var(--surface-2)', borderRadius: 'var(--radius-tile)', padding: '14px 0', cursor: 'pointer' }}>
            <i className="ti ti-heart" style={{ fontSize: 20, color: liked ? 'var(--text-accent)' : 'var(--text-primary)' }}></i>
            <span style={{ font: '600 13px/1 var(--font-family)', color: liked ? 'var(--text-accent)' : 'var(--text-primary)' }}>{(p.likes || 0) + (liked ? 1 : 0)}</span>
          </div>
          <div onClick={onComments} style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 6, background: 'var(--surface-2)', borderRadius: 'var(--radius-tile)', padding: '14px 0', cursor: 'pointer' }}>
            <i className="ti ti-message-circle" style={{ fontSize: 20, color: 'var(--text-primary)' }}></i>
            <span style={{ font: '600 13px/1 var(--font-family)', color: 'var(--text-primary)' }}>{p.comments || 0}</span>
          </div>
          <div onClick={() => onShare ? onShare() : onClose()} style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 6, background: 'var(--surface-2)', borderRadius: 'var(--radius-tile)', padding: '14px 0', cursor: 'pointer' }}>
            <i className="ti ti-share-2" style={{ fontSize: 20, color: 'var(--text-primary)' }}></i>
            <span style={{ font: '600 13px/1 var(--font-family)', color: 'var(--text-primary)' }}>공유</span>
          </div>
        </div>
      )}
      {visCapped(acc, pvis) && <div style={{ marginBottom: 12 }}><VisibilityNotice account={acc} item={pvis} /></div>}
      <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
        {rows.map(r => (
          <div key={r.label} onClick={r.act} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '15px 16px', background: r.danger ? 'var(--bg-danger)' : 'var(--surface-2)', borderRadius: 'var(--radius-tile)', cursor: 'pointer' }}>
            <i className={'ti ti-' + r.icon} style={{ fontSize: 19, color: r.danger ? 'var(--text-danger)' : 'var(--text-primary)', flexShrink: 0 }}></i>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ font: 'var(--text-body)', color: r.danger ? 'var(--text-danger)' : 'var(--text-primary)', marginBottom: 2 }}>{r.label}</div>
              <div style={{ font: 'var(--text-micro)', color: r.danger ? 'var(--text-danger)' : 'var(--text-muted)', opacity: r.danger ? .75 : 1 }}>{r.sub}</div>
            </div>
            <i className="ti ti-chevron-right" style={{ fontSize: 15, color: r.danger ? 'var(--text-danger)' : 'var(--text-muted)', flexShrink: 0, opacity: r.danger ? .6 : 1 }}></i>
          </div>
        ))}
      </div>
    </BottomSheet>
  );
}
window.MyPostMenuSheet = MyPostMenuSheet;

function EditPhotosSheet({ post, onClose, onDone, onDeletePost }) {
  const { BottomSheet, Button } = window.SpotureDesignSystem_f7ad96;
  const p = post || {};
  const count = p.mediaCount || 1;
  const [gone, setGone] = React.useState([]);
  const toggle = i => setGone(g => g.includes(i) ? g.filter(x => x !== i) : g.concat(i));
  const left = count - gone.length;
  const all = left === 0;
  const footer = gone.length === 0
    ? <Button variant="secondary" onClick={onClose}>닫기</Button>
    : all
      ? <Button variant="danger" onClick={onDeletePost}>사진을 다 지우고 게시물 삭제하기</Button>
      : <Button variant="primary" onClick={() => onDone(gone.length, left)}>사진 {gone.length}장 삭제하기</Button>;
  return (
    <BottomSheet title="사진 관리" titleAside={<span style={{ font: 'var(--text-small)', color: 'var(--text-muted)' }}>{left} / {count}</span>} footer={footer} onClose={onClose}>
      <p style={{ font: 'var(--text-caption)', color: 'var(--text-secondary)', margin: '0 0 14px', lineHeight: 1.6 }}>지울 사진을 골라주세요. 삭제하기 전까진 다시 되돌릴 수 있어요.</p>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3,1fr)', gap: 8 }}>
        {Array.from({ length: count }, (_, i) => {
          const off = gone.includes(i);
          const isVid = p.hasVideo && i === count - 1;
          return (
            <div key={i} onClick={() => toggle(i)} style={{ position: 'relative', aspectRatio: '1', borderRadius: 12, overflow: 'hidden', background: 'var(--surface-2)', border: off ? '1.5px solid var(--border-accent)' : '1.5px solid transparent', cursor: 'pointer' }}>
              <div style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', filter: off ? 'grayscale(1)' : 'none', opacity: off ? .35 : 1 }}>
                <i className={isVid ? 'ti ti-video' : 'ti ti-photo'} style={{ fontSize: 21, color: 'var(--text-muted)' }}></i>
              </div>
              {off && (
                <div style={{ position: 'absolute', inset: 0, background: 'rgba(227,30,36,.10)', display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 4 }}>
                  <i className="ti ti-rotate" style={{ fontSize: 17, color: 'var(--text-accent)' }}></i>
                  <span style={{ font: '600 10px/1 var(--font-family)', color: 'var(--text-accent)' }}>되돌리기</span>
                </div>
              )}
              <span style={{ position: 'absolute', left: 6, top: 6, font: 'var(--text-micro)', color: '#fff', background: 'rgba(26,26,26,.62)', borderRadius: 999, padding: '3px 7px' }}>{i + 1}</span>
              {!off && <span style={{ position: 'absolute', right: 5, top: 5, width: 22, height: 22, borderRadius: '50%', background: 'rgba(26,26,26,.68)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}><i className="ti ti-x" style={{ fontSize: 12, color: '#fff' }}></i></span>}
            </div>
          );
        })}
      </div>
      {all && (
        <div style={{ display: 'flex', gap: 10, background: 'var(--bg-danger)', borderRadius: 'var(--radius-tile)', padding: '13px 14px', marginTop: 14 }}>
          <i className="ti ti-alert-circle" style={{ fontSize: 16, color: 'var(--text-danger)', flexShrink: 0, marginTop: 1 }}></i>
          <span style={{ font: 'var(--text-small)', color: 'var(--text-primary)', lineHeight: 1.6 }}>사진이 하나도 남지 않으면 게시물 자체가 삭제돼요. 좋아요 {p.likes || 0}개와 댓글 {p.comments || 0}개도 함께 사라져요.</span>
        </div>
      )}
      {!all && gone.length > 0 && (
        <div style={{ display: 'flex', gap: 10, background: 'var(--surface-2)', borderRadius: 'var(--radius-tile)', padding: '13px 14px', marginTop: 14 }}>
          <i className="ti ti-info-circle" style={{ fontSize: 16, color: 'var(--text-secondary)', flexShrink: 0, marginTop: 1 }}></i>
          <span style={{ font: 'var(--text-small)', color: 'var(--text-secondary)', lineHeight: 1.6 }}>사진에 달린 메뉴 태그도 함께 지워져요. 좋아요와 댓글은 그대로 남아요.</span>
        </div>
      )}
    </BottomSheet>
  );
}
window.EditPhotosSheet = EditPhotosSheet;

function DeletePostConfirm({ post, onCancel, onConfirm }) {
  const p = post || {};
  const count = p.mediaCount || 1;
  const lines = [
    { icon: 'photo', text: '사진 ' + count + '장이 기기가 아닌 서비스에서만 삭제돼요' },
    { icon: 'heart', text: '좋아요 ' + (p.likes || 0) + '개 · 댓글 ' + (p.comments || 0) + '개가 함께 사라져요' },
    p.place
      ? { icon: 'map-pin', text: p.place + ' 등록 사진 수에서도 빠져요' }
      : { icon: 'map-pin-question', text: '이웃이 보낸 위치 제보도 함께 취소돼요' },
    p.mission
      ? { icon: 'gift', text: '미션 인증이 취소되고 응모권은 회수돼요', warn: true }
      : { icon: 'clock', text: '30일이 지나면 복구할 수 없어요' }
  ];
  return (
    <div style={{ position: 'fixed', inset: 0, background: 'rgba(20,20,20,.42)', display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 32, zIndex: 90 }}>
      <div style={{ background: 'var(--surface-1)', borderRadius: 'var(--radius-card)', padding: 24, textAlign: 'center', boxShadow: 'var(--shadow-float)', maxWidth: 300 }}>
        <div style={{ width: 52, height: 52, borderRadius: '50%', background: 'var(--bg-danger)', display: 'flex', alignItems: 'center', justifyContent: 'center', margin: '0 auto 14px' }}><i className="ti ti-trash" style={{ fontSize: 23, color: 'var(--text-danger)' }}></i></div>
        <span style={{ font: 'var(--text-heading)', display: 'block', marginBottom: 8 }}>이 게시물을 삭제할까요?</span>
        <p style={{ font: 'var(--text-caption)', color: 'var(--text-secondary)', margin: '0 0 16px', lineHeight: 1.6, textWrap: 'pretty' }}>{p.menu ? '#' + p.menu : '게시물'}{p.place ? ' · ' + p.place : ''}</p>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 10, background: 'var(--surface-2)', borderRadius: 'var(--radius-tile)', padding: '14px 15px', marginBottom: 20, textAlign: 'left' }}>
          {lines.map(l => (
            <div key={l.text} style={{ display: 'flex', gap: 10 }}>
              <i className={'ti ti-' + l.icon} style={{ fontSize: 15, color: l.warn ? 'var(--text-danger)' : 'var(--text-secondary)', flexShrink: 0, marginTop: 2 }}></i>
              <span style={{ font: 'var(--text-small)', color: l.warn ? 'var(--text-danger)' : 'var(--text-secondary)', lineHeight: 1.55 }}>{l.text}</span>
            </div>
          ))}
        </div>
        <div style={{ display: 'flex', gap: 8 }}>
          <button onClick={onCancel} style={{ flex: 1, padding: '13px 0', font: '600 14px/1 var(--font-family)', border: '1px solid var(--border-strong)', background: 'var(--surface-1)', color: 'var(--text-primary)', borderRadius: 999, cursor: 'pointer' }}>그대로 둘게요</button>
          <button onClick={onConfirm} style={{ flex: 1, padding: '13px 0', font: '600 14px/1 var(--font-family)', border: 'none', background: 'var(--text-danger)', color: '#fff', borderRadius: 999, cursor: 'pointer' }}>삭제하기</button>
        </div>
      </div>
    </div>
  );
}
window.DeletePostConfirm = DeletePostConfirm;

function PostActionSheets({ post, onClose, onDeleted, onReport, onEdit }) {
  const { Toast } = window.SpotureDesignSystem_f7ad96;
  const [step, setStep] = React.useState('menu');
  const [toast, setToast] = React.useState(null);
  if (!post) return null;
  const mine = post.isMine || post.user === '국밥러버92';
  const close = () => { setStep('menu'); onClose && onClose(); };
  if (toast) return <Toast message={toast} icon={toast.indexOf('숨') > -1 || toast.indexOf('공개') > -1 ? 'eye-off' : toast.indexOf('수정') > -1 ? 'check' : 'trash'} onClose={() => { setToast(null); close(); }} />;
  if (!mine) return <PostMenuSheet post={post} onClose={close} onReport={() => { close(); onReport && onReport(post); }} onShare={close} />;
  if (step === 'hide') return <HidePostConfirm post={post} hidden={!!post.hidden} onCancel={() => setStep('menu')} onConfirm={(v) => { setStep('menu'); setToast('공개 범위를 ' + visMeta(effVis(accountVis(), v)).label + '로 바꿨어요'); }} />;
  if (step === 'photos') return <EditPhotosSheet post={post} onClose={() => setStep('menu')} onDone={(n, left) => setToast('사진 ' + n + '장을 지웠어요 · ' + left + '장 남음')} onDeletePost={() => setStep('delete')} />;
  if (step === 'delete') return <DeletePostConfirm post={post} onCancel={() => setStep('menu')} onConfirm={() => { setStep('menu'); onClose && onClose(); onDeleted && onDeleted(post); }} />;
  return <MyPostMenuSheet post={post} onClose={close} onEdit={() => { close(); onEdit && onEdit(post); }} onPhotos={() => setStep('photos')} onHide={() => setStep('hide')} onShare={close} onDelete={() => setStep('delete')} />;
}
window.PostActionSheets = PostActionSheets;
