// HQ Admin — 본사 관리자 콘솔
// 01 Approval · 02 Notices · 03 National Map · 04 KPI Dashboard · 05 AI Description

const { useState: useStateHQ } = React;

// ═══════════════════════════════════════════════════════════
// Shared HQ chrome
// ═══════════════════════════════════════════════════════════
function HQChrome({ active, children, title, subtitle }) {
  const nav = [
    ['notices', '📢', '공지 발송'],
    ['stores', '🏪', '매장 관리'],
    ['published', '📦', '발행 상품'],
    ['board', '📋', '게시판'],
    ['home-edit', '🏠', '홈 화면 관리'],
    ['approval', '✅', '점주 승인'],
    ['users', '👥', '회원 관리'],
    ['map', '🗺️', '전국 맵'],
    ['---', '', ''],
    ['preview-consumer', '👤', '회원 화면'],
    ['preview-owner', '🏬', '점주 화면'],
  ];
  const user = typeof getAuth === 'function' ? getAuth() : null;
  const navigate = (k) => { if (window.__hqNav) window.__hqNav(k); };
  const logout = () => { if (window.__hqLogout) window.__hqLogout(); };
  return (
    <div className="wu" style={{ display: 'flex', height: '100%', background: 'var(--wu-bg)' }}>
      <aside style={{ width: 200, background: 'var(--wu-ink)', color: 'var(--wu-paper)', display: 'flex', flexDirection: 'column', flexShrink: 0 }}>
        <div style={{ padding: '18px 18px 14px', borderBottom: '1px solid #1A1A17' }}>
          <div style={{ fontFamily: 'Archivo Black', fontSize: 18, letterSpacing: '-0.02em', lineHeight: 1, color: 'var(--wu-paper)' }}>
            WORKUP-STORE
          </div>
          <div className="mono" style={{ fontSize: 9, color: 'var(--wu-orange)', marginTop: 6, letterSpacing: '0.1em' }}>HQ ADMIN · 본사 관리</div>
        </div>
        <div style={{ padding: 10, flex: 1, overflow: 'auto' }} className="wu-scroll">
          {nav.map(([k, icon, l]) => {
            if (k === '---') return <div key="sep" style={{ height: 1, background: '#333', margin: '8px 0' }} />;
            const isPreview = k.startsWith('preview-');
            return (
              <button key={k} onClick={() => navigate(k)} className="kr" style={{ display: 'flex', alignItems: 'center', gap: 8, width: '100%', textAlign: 'left', padding: '10px 12px', fontSize: 12, fontWeight: 600, color: active === k ? '#fff' : isPreview ? '#8EC8F0' : '#B8B3A8', background: active === k ? (isPreview ? '#2A5A8A' : 'var(--wu-orange)') : 'transparent', borderRadius: 4, marginBottom: 2, cursor: 'pointer', border: 'none' }}>
                <span style={{ fontSize: 14, lineHeight: 1, flexShrink: 0 }}>{icon}</span>{l}
              </button>
            );
          })}
        </div>
        <div style={{ padding: 14, borderTop: '1px solid #1A1A17' }}>
          <div className="mono" style={{ fontSize: 9, color: 'var(--wu-mute)' }}>ADMIN</div>
          <div className="kr" style={{ fontSize: 12, fontWeight: 700, color: 'var(--wu-paper)', marginTop: 2 }}>{user?.name || '관리자'} · 본사 운영</div>
          {window.__hqBackToConsumer && (
            <button onClick={() => window.__hqBackToConsumer()} className="kr" style={{ display: 'block', width: '100%', marginTop: 10, padding: '8px 0', fontSize: 11, fontWeight: 700, color: 'var(--wu-lime)', cursor: 'pointer', border: '1px solid var(--wu-lime)', background: 'transparent', borderRadius: 4 }}>← 회원 화면으로</button>
          )}
          <button onClick={logout} className="mono" style={{ marginTop: 8, fontSize: 10, color: 'var(--wu-orange)', cursor: 'pointer', border: 'none', background: 'none', padding: 0 }}>LOGOUT →</button>
        </div>
      </aside>
      <div style={{ flex: 1, display: 'flex', flexDirection: 'column', minWidth: 0 }}>
        <header style={{ padding: '20px 28px 16px', borderBottom: '1px solid var(--wu-line)', background: 'var(--wu-paper)', display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end' }}>
          <div>
            <div className="mono" style={{ fontSize: 10, color: 'var(--wu-mute)' }}>{subtitle}</div>
            <div className="display" style={{ fontSize: 28, marginTop: 2 }}>{title}</div>
          </div>
          <div className="mono" style={{ fontSize: 10, color: 'var(--wu-mute)' }}>● 2026.04.21 화 · 14:22 KST</div>
        </header>
        <div style={{ flex: 1, overflow: 'auto' }} className="wu-scroll">{children}</div>
      </div>
    </div>
  );
}

// ═══════════════════════════════════════════════════════════
// Preview — 회원/점주 화면 미리보기 (관리자용)
// ═══════════════════════════════════════════════════════════
function HQPreview({ role }) {
  const realAuth = React.useRef(null);
  const [ready, setReady] = React.useState(false);

  // 미리보기 진입 시 임시 유저로 교체, 나갈 때 복원
  React.useEffect(() => {
    realAuth.current = localStorage.getItem('wu-auth-user');
    const fakeUser = role === 'owner'
      ? { name: '미리보기 점주', email: 'preview-owner@workup.co', role: 'owner', status: 'APPROVED', storeName: '워크업 강남점' }
      : { name: '미리보기 회원', email: 'preview-consumer@workup.co', role: 'consumer', status: 'APPROVED' };
    localStorage.setItem('wu-auth-user', JSON.stringify(fakeUser));
    setReady(true);
    return () => {
      if (realAuth.current) localStorage.setItem('wu-auth-user', realAuth.current);
      else localStorage.removeItem('wu-auth-user');
    };
  }, [role]);

  if (!ready) return null;

  const label = role === 'owner' ? '점주' : '회원';

  return (
    <HQChrome active={'preview-' + role} title={label + ' 화면 미리보기'} subtitle="PREVIEW MODE">
      <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'center', padding: '24px 20px', height: '100%', background: '#F0EEE9' }}>
        {/* 폰 프레임 */}
        <div style={{ position: 'relative', width: 390, height: 780, background: '#000', borderRadius: 44, padding: '12px 10px', boxShadow: '0 12px 40px rgba(0,0,0,0.25)' }}>
          {/* 노치 */}
          <div style={{ position: 'absolute', top: 0, left: '50%', transform: 'translateX(-50%)', width: 120, height: 28, background: '#000', borderRadius: '0 0 18px 18px', zIndex: 10 }} />
          {/* 화면 영역 */}
          <div style={{ width: '100%', height: '100%', borderRadius: 34, overflow: 'hidden', background: 'var(--wu-bg)', position: 'relative' }}>
            {/* 미리보기 배지 */}
            <div style={{ position: 'absolute', top: 14, left: '50%', transform: 'translateX(-50%)', zIndex: 50, background: role === 'owner' ? 'var(--wu-orange)' : 'var(--wu-ink)', color: '#fff', padding: '3px 14px', borderRadius: 999, fontSize: 10, fontWeight: 700, fontFamily: 'var(--wu-mono)', letterSpacing: '0.06em', opacity: 0.85 }}>
              {label.toUpperCase()} PREVIEW
            </div>
            {window.ConsumerMobileShell && React.createElement(window.ConsumerMobileShell, { initial: 'home', variant: 'pill', onLogout: () => { if (window.__hqNav) window.__hqNav('kpi'); } })}
          </div>
        </div>
        {/* 안내 패널 */}
        <div style={{ marginLeft: 28, paddingTop: 20, maxWidth: 260 }}>
          <div className="mono" style={{ fontSize: 10, color: 'var(--wu-mute)', letterSpacing: '0.1em' }}>PREVIEW</div>
          <div className="display" style={{ fontSize: 22, marginTop: 4 }}>{label} 화면</div>
          <div className="kr" style={{ fontSize: 13, color: 'var(--wu-mute)', marginTop: 12, lineHeight: 1.6 }}>
            로그인 없이 {label} 화면을 확인할 수 있습니다. 탭을 눌러 각 화면을 둘러보세요.
          </div>
          <div style={{ marginTop: 20, padding: '12px 16px', background: 'var(--wu-paper)', border: '1px solid var(--wu-line)', borderRadius: 8 }}>
            <div className="mono" style={{ fontSize: 9, color: 'var(--wu-mute)' }}>VIEWING AS</div>
            <div className="kr" style={{ fontSize: 14, fontWeight: 700, marginTop: 4 }}>{role === 'owner' ? '미리보기 점주' : '미리보기 회원'}</div>
            <div className="mono" style={{ fontSize: 11, color: 'var(--wu-mute)', marginTop: 2 }}>{role === 'owner' ? 'preview-owner@workup.co' : 'preview-consumer@workup.co'}</div>
            {role === 'owner' && <div className="kr" style={{ fontSize: 11, color: 'var(--wu-orange)', marginTop: 4, fontWeight: 600 }}>워크업 강남점</div>}
          </div>
          <button onClick={() => { if (window.__hqNav) window.__hqNav('kpi'); }} className="kr" style={{ marginTop: 16, padding: '10px 20px', background: 'var(--wu-ink)', color: 'var(--wu-lime)', border: 'none', borderRadius: 6, fontSize: 12, fontWeight: 600, cursor: 'pointer', width: '100%' }}>
            ← 관리자 화면으로 돌아가기
          </button>
        </div>
      </div>
    </HQChrome>
  );
}

// HQ App — navigable admin shell
function HQApp({ onLogout, onBackToConsumer }) {
  const [page, setPage] = React.useState('published');
  window.__hqNav = setPage;
  window.__hqLogout = onLogout;
  window.__hqBackToConsumer = onBackToConsumer;
  window.__hqPage = page;

  // 미리보기 모드
  if (page === 'preview-consumer') return React.createElement(HQPreview, { key: 'preview-consumer', role: 'consumer' });
  if (page === 'preview-owner') return React.createElement(HQPreview, { key: 'preview-owner', role: 'owner' });

  const local = { approval: HQApproval, notices: HQNotices, map: HQNationalMap };
  const Screen = local[page] || window[{ published: 'HQPublishedList', stores: 'HQStoreManager', board: 'HQBoard', 'home-edit': 'HQHomeEditor', users: 'AdminUserManager' }[page]] || (window.HQPublishedList || HQApproval);
  return React.createElement(Screen, { key: page });
}
window.HQChrome = HQChrome;
window.HQApp = HQApp;

// ═══════════════════════════════════════════════════════════
// 01 — 점주 승인 대시보드
// ═══════════════════════════════════════════════════════════
function HQApproval() {
  const [filter, setFilter] = useStateHQ('PENDING');
  const [selectedEmail, setSelectedEmail] = useStateHQ(null);
  const [memo, setMemo] = useStateHQ('');
  const [ver, setVer] = useStateHQ(0); // force re-render after mutations
  const [mode, setMode] = useStateHQ('view'); // view | edit | add
  const [editForm, setEditForm] = useStateHQ({ name: '', email: '', phone: '', storeName: '', password: '' });
  const [storeList, setStoreList] = useStateHQ([]);
  const [storeQuery, setStoreQuery] = useStateHQ('');
  const [showStoreDrop, setShowStoreDrop] = useStateHQ(false);
  const [formErr, setFormErr] = useStateHQ('');

  // 매장 목록 로드 (자동완성용)
  React.useEffect(() => {
    (async () => {
      try {
        const fn = window.getAllStores;
        if (fn) { const s = await fn(); setStoreList(s.map(x => x.name).filter(Boolean)); }
      } catch(e) {}
    })();
  }, []);

  // Firestore에서 점주(owner) 회원만 가져오기
  const [allUsers, setAllUsers] = React.useState([]);
  React.useEffect(() => {
    if (typeof getUsers === 'function') {
      getUsers().then(u => setAllUsers(u || [])).catch(() => {});
    }
  }, [ver]);
  const owners = allUsers.filter(u => u.role === 'owner');

  const filtered = owners.filter(a => filter === 'ALL' || a.status === filter);
  const app = selectedEmail ? owners.find(a => a.email === selectedEmail) : filtered[0];

  React.useEffect(() => {
    if (!selectedEmail && filtered.length > 0) setSelectedEmail(filtered[0].email);
  }, [filter, ver]);

  const counts = {
    PENDING: owners.filter(a => a.status === 'PENDING').length,
    APPROVED: owners.filter(a => a.status === 'APPROVED').length,
    REJECTED: owners.filter(a => a.status === 'REJECTED').length,
  };

  const refresh = () => setVer(v => v + 1);

  const changeStatus = async (email, status) => {
    const all = await getUsers();
    const idx = all.findIndex(u => u.email === email);
    if (idx >= 0) { all[idx].status = status; await saveUsers(all); }
  };

  const handleApprove = async () => {
    if (!app) return;
    await changeStatus(app.email, 'APPROVED');
    setSelectedEmail(null);
    refresh();
  };
  const handleReject = async () => {
    if (!app) return;
    await changeStatus(app.email, 'REJECTED');
    setSelectedEmail(null);
    refresh();
  };
  const handleDelete = async () => {
    if (!app) return;
    if (!confirm(app.name + ' (' + (app.storeName || '') + ') 점주를 삭제하시겠습니까?')) return;
    const all = (await getUsers()).filter(u => u.email !== app.email);
    await saveUsers(all);
    setSelectedEmail(null);
    setMode('view');
    refresh();
  };

  // 수정 모드 시작
  const startEdit = () => {
    if (!app) return;
    setEditForm({ name: app.name, email: app.email, phone: app.phone || '', storeName: app.storeName || '', password: '' });
    setStoreQuery(app.storeName || '');
    setFormErr('');
    setMode('edit');
  };
  // 추가 모드 시작
  const startAdd = () => {
    setEditForm({ name: '', email: '', phone: '', storeName: '', password: '' });
    setStoreQuery('');
    setFormErr('');
    setSelectedEmail(null);
    setMode('add');
  };

  const ef = (k, v) => setEditForm(f => ({ ...f, [k]: v }));

  // 이미 등록된 매장명
  const takenStores = owners.map(u => u.storeName).filter(Boolean);
  const filteredStoreOpts = storeList.filter(n => {
    if (!storeQuery) return true;
    return n.toLowerCase().includes(storeQuery.toLowerCase());
  });

  // 수정 저장
  const saveEdit = async () => {
    setFormErr('');
    if (!editForm.name || !editForm.storeName) { setFormErr('이름과 매장명은 필수입니다'); return; }
    const all = await getUsers();
    const idx = all.findIndex(u => u.email === app.email);
    if (idx < 0) { setFormErr('사용자를 찾을 수 없습니다'); return; }
    all[idx].name = editForm.name;
    all[idx].phone = editForm.phone;
    all[idx].storeName = editForm.storeName;
    if (editForm.password) all[idx].password = editForm.password;
    await saveUsers(all);
    const auth = getAuth();
    if (auth && auth.email === app.email) setAuth(all[idx]);
    setMode('view');
    refresh();
  };

  // 신규 추가 저장
  const saveAdd = async () => {
    setFormErr('');
    if (!editForm.name || !editForm.email || !editForm.storeName) { setFormErr('이름, 이메일, 매장명은 필수입니다'); return; }
    if (!editForm.password || editForm.password.length < 6) { setFormErr('비밀번호 6자 이상 필수'); return; }
    const all = await getUsers();
    if (all.find(u => u.email === editForm.email)) { setFormErr('이미 등록된 이메일입니다'); return; }
    if (takenStores.includes(editForm.storeName)) { setFormErr('이미 등록된 매장입니다'); return; }
    await addUser({
      email: editForm.email, password: editForm.password,
      name: editForm.name, phone: editForm.phone,
      storeName: editForm.storeName,
      role: 'owner', status: 'APPROVED',
      createdAt: new Date().toISOString().split('T')[0],
    });
    setSelectedEmail(editForm.email);
    setMode('view');
    refresh();
  };

  // 폼 입력 스타일
  const inpSt = { width: '100%', padding: '10px 12px', border: '1px solid var(--wu-line)', background: 'var(--wu-bg)', fontSize: 14, fontWeight: 600, fontFamily: 'var(--wu-kr)', outline: 'none' };
  const lblSt = { fontSize: 10, fontFamily: 'JetBrains Mono', color: 'var(--wu-mute)', marginBottom: 4, letterSpacing: '0.06em', display: 'block' };

  // 수정/추가 폼 렌더
  const renderForm = (isAdd) => (
    <div style={{ flex: 1, overflow: 'auto', padding: 28 }} className="wu-scroll">
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
        <div>
          <div className="mono" style={{ fontSize: 10, color: 'var(--wu-mute)' }}>{isAdd ? 'NEW OWNER' : 'EDIT OWNER'}</div>
          <div className="display" style={{ fontSize: 26, marginTop: 2 }}>{isAdd ? '점주 직접 추가' : '점주 정보 수정'}</div>
        </div>
        <button onClick={() => setMode('view')} style={{ padding: '8px 14px', fontSize: 12, fontWeight: 700, fontFamily: 'var(--wu-kr)', background: 'var(--wu-bg)', border: '1px solid var(--wu-line)', cursor: 'pointer' }}>← 취소</button>
      </div>

      <div style={{ marginTop: 20, background: 'var(--wu-paper)', border: '1px solid var(--wu-line)', padding: 24 }}>
        <div style={{ marginBottom: 16 }}>
          <label style={lblSt}>담당자 이름 *</label>
          <input value={editForm.name} onChange={e => ef('name', e.target.value)} placeholder="홍길동" style={inpSt} />
        </div>
        {isAdd && (
          <div style={{ marginBottom: 16 }}>
            <label style={lblSt}>이메일 *</label>
            <input value={editForm.email} onChange={e => ef('email', e.target.value)} placeholder="owner@workup.co" type="email" style={inpSt} />
          </div>
        )}
        <div style={{ marginBottom: 16 }}>
          <label style={lblSt}>연락처</label>
          <input value={editForm.phone} onChange={e => ef('phone', e.target.value)} placeholder="010-0000-0000" type="tel" style={inpSt} />
        </div>
        <div style={{ marginBottom: 16 }}>
          <label style={lblSt}>{isAdd ? '비밀번호 * (6자+)' : '비밀번호 변경 (비워두면 유지)'}</label>
          <input value={editForm.password} onChange={e => ef('password', e.target.value)} placeholder="••••••••" type="password" style={inpSt} />
        </div>

        {/* 매장명 자동완성 */}
        <div style={{ marginBottom: 16, position: 'relative' }}>
          <label style={lblSt}>대리점명 * (매장 관리 목록에서 선택)</label>
          <input
            value={storeQuery}
            onChange={e => { setStoreQuery(e.target.value); ef('storeName', ''); setShowStoreDrop(true); }}
            onFocus={() => setShowStoreDrop(true)}
            placeholder="매장명 검색"
            style={{ ...inpSt, border: '1px solid ' + (editForm.storeName ? 'var(--wu-lime)' : 'var(--wu-line)'), background: editForm.storeName ? '#F0FFD0' : 'var(--wu-bg)' }}
          />
          {editForm.storeName && (
            <div className="kr" style={{ fontSize: 11, color: 'var(--wu-ink)', marginTop: 4, fontWeight: 700 }}>
              <span style={{ color: 'var(--wu-lime)' }}>✓</span> {editForm.storeName}
              <button onClick={() => { ef('storeName', ''); setStoreQuery(''); }} style={{ marginLeft: 8, fontSize: 10, color: 'var(--wu-orange)', cursor: 'pointer', background: 'none', border: 'none', fontWeight: 700 }}>변경</button>
            </div>
          )}
          {showStoreDrop && !editForm.storeName && storeList.length > 0 && (
            <div style={{ position: 'absolute', top: '100%', left: 0, right: 0, maxHeight: 180, overflow: 'auto', background: 'var(--wu-paper)', border: '1px solid var(--wu-line)', boxShadow: '0 8px 24px rgba(0,0,0,0.12)', zIndex: 10 }}>
              {filteredStoreOpts.length === 0 ? (
                <div className="kr" style={{ padding: '12px 14px', fontSize: 12, color: 'var(--wu-mute)' }}>일치하는 매장 없음</div>
              ) : filteredStoreOpts.map(name => {
                const taken = takenStores.includes(name) && name !== (app && app.storeName);
                return (
                  <button key={name} disabled={taken} onClick={() => { ef('storeName', name); setStoreQuery(name); setShowStoreDrop(false); }}
                    style={{ display: 'block', width: '100%', padding: '10px 14px', textAlign: 'left', border: 'none', borderBottom: '1px solid var(--wu-line)', background: taken ? '#f5f3ee' : 'var(--wu-paper)', cursor: taken ? 'not-allowed' : 'pointer', opacity: taken ? 0.5 : 1 }}>
                    <span className="kr" style={{ fontSize: 13, fontWeight: 600 }}>{name}</span>
                    {taken && <span style={{ marginLeft: 8, fontSize: 10, color: '#C44', fontWeight: 700 }}>등록됨</span>}
                  </button>
                );
              })}
            </div>
          )}
        </div>

        {formErr && <div className="kr" style={{ fontSize: 12, color: '#C44', marginBottom: 12 }}>⚠ {formErr}</div>}

        <button onClick={isAdd ? saveAdd : saveEdit} className="wu-btn lime" style={{ width: '100%', padding: '14px', fontSize: 14, cursor: 'pointer' }}>
          {isAdd ? '점주 추가 (승인완료 상태)' : '변경사항 저장'}
        </button>
      </div>
    </div>
  );

  return (
    <HQChrome active="approval" title="점주 승인 대시보드" subtitle="HQ · FRANCHISE APPROVAL">
      <div style={{ display: 'flex', height: '100%' }}>
        {/* List */}
        <div style={{ width: 420, borderRight: '1px solid var(--wu-line)', display: 'flex', flexDirection: 'column', flexShrink: 0 }}>
          <div style={{ padding: '16px 20px', borderBottom: '1px solid var(--wu-line)', background: 'var(--wu-paper)' }}>
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 6 }}>
              {[['PENDING', '대기', counts.PENDING, 'var(--wu-orange)'], ['APPROVED', '승인', counts.APPROVED, 'var(--wu-lime)'], ['REJECTED', '반려', counts.REJECTED, '#C44']].map(([k, l, n, c]) => (
                <button key={k} onClick={() => { setFilter(k); setMode('view'); }} style={{ padding: 10, border: '1px solid ' + (filter === k ? 'var(--wu-ink)' : 'var(--wu-line)'), background: filter === k ? 'var(--wu-ink)' : 'var(--wu-bg)', color: filter === k ? 'var(--wu-paper)' : 'var(--wu-ink)', textAlign: 'left', cursor: 'pointer' }}>
                  <div className="mono" style={{ fontSize: 9, opacity: 0.7 }}>● {l}</div>
                  <div className="display" style={{ fontSize: 22, color: filter === k ? c : 'var(--wu-ink)', marginTop: 2 }}>{n}</div>
                </button>
              ))}
            </div>
            <button onClick={startAdd} style={{ width: '100%', marginTop: 8, padding: '10px', fontSize: 12, fontWeight: 700, fontFamily: 'var(--wu-kr)', background: 'var(--wu-orange)', color: '#fff', border: 'none', cursor: 'pointer' }}>
              + 점주 직접 추가
            </button>
          </div>
          <div style={{ flex: 1, overflow: 'auto' }} className="wu-scroll">
            {filtered.length === 0 && (
              <div style={{ padding: 40, textAlign: 'center', color: 'var(--wu-mute)' }}>
                <div style={{ fontSize: 32 }}>📋</div>
                <div className="kr" style={{ fontSize: 13, marginTop: 8 }}>
                  {filter === 'PENDING' ? '대기 중인 신청이 없습니다' : filter === 'APPROVED' ? '승인된 점주가 없습니다' : '반려된 신청이 없습니다'}
                </div>
              </div>
            )}
            {filtered.map(a => (
              <div key={a.email} onClick={() => { setSelectedEmail(a.email); setMode('view'); }} style={{ padding: '14px 20px', borderBottom: '1px solid var(--wu-line)', cursor: 'pointer', background: app && app.email === a.email && mode === 'view' ? 'var(--wu-paper)' : 'transparent', borderLeft: '3px solid ' + (app && app.email === a.email && mode === 'view' ? 'var(--wu-ink)' : 'transparent') }}>
                <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline' }}>
                  <div className="kr" style={{ fontSize: 13, fontWeight: 700 }}>{a.storeName || '매장 미정'} · {a.name}</div>
                  <div className="mono" style={{ fontSize: 9, color: 'var(--wu-mute)' }}>{a.createdAt}</div>
                </div>
                <div className="mono" style={{ fontSize: 10, color: 'var(--wu-mute)', marginTop: 2 }}>{a.email}</div>
                <div style={{ display: 'flex', gap: 4, marginTop: 6 }}>
                  <span className="mono" style={{ fontSize: 9, padding: '2px 5px', fontWeight: 700, background: a.status === 'PENDING' ? 'var(--wu-orange)' : a.status === 'APPROVED' ? 'var(--wu-lime)' : '#C44', color: a.status === 'APPROVED' ? 'var(--wu-ink)' : '#fff' }}>
                    {a.status === 'PENDING' ? '대기' : a.status === 'APPROVED' ? '승인완료' : '반려'}
                  </span>
                </div>
              </div>
            ))}
          </div>
        </div>

        {/* Right panel — view / edit / add */}
        {mode === 'add' && renderForm(true)}
        {mode === 'edit' && app && renderForm(false)}
        {mode === 'view' && app ? (
          <div style={{ flex: 1, overflow: 'auto', padding: 28 }} className="wu-scroll">
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
              <div>
                <div className="mono" style={{ fontSize: 10, color: 'var(--wu-mute)' }}>점주 정보</div>
                <div className="display" style={{ fontSize: 30, marginTop: 2 }}>{app.storeName || '매장 미정'}</div>
                <div className="kr" style={{ fontSize: 13, color: 'var(--wu-mute)', marginTop: 4 }}>신청일 {app.createdAt}</div>
              </div>
              <span className="mono" style={{ fontSize: 10, padding: '4px 10px', fontWeight: 700, background: app.status === 'PENDING' ? 'var(--wu-orange)' : app.status === 'APPROVED' ? 'var(--wu-lime)' : '#C44', color: app.status === 'APPROVED' ? 'var(--wu-ink)' : '#fff' }}>
                ● {app.status === 'PENDING' ? '승인 대기' : app.status === 'APPROVED' ? '승인 완료' : '반려'}
              </span>
            </div>

            {/* Applicant info */}
            <div style={{ marginTop: 24, background: 'var(--wu-paper)', border: '1px solid var(--wu-line)' }}>
              <div className="mono" style={{ fontSize: 10, color: 'var(--wu-mute)', padding: '12px 18px', borderBottom: '1px solid var(--wu-line)', letterSpacing: '0.08em' }}>신청자 정보</div>
              <div style={{ padding: 18, display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '12px 28px' }}>
                {[['이름', app.name], ['매장명', app.storeName || '—'], ['이메일', app.email], ['연락처', app.phone || '—']].map(([l, v]) => (
                  <div key={l}>
                    <div className="mono" style={{ fontSize: 9, color: 'var(--wu-mute)' }}>{l.toUpperCase()}</div>
                    <div className="kr" style={{ fontSize: 14, fontWeight: 600, marginTop: 2 }}>{v}</div>
                  </div>
                ))}
              </div>
            </div>

            {/* Review notes */}
            <div style={{ marginTop: 18, background: 'var(--wu-paper)', border: '1px solid var(--wu-line)', padding: 16 }}>
              <div className="mono" style={{ fontSize: 10, color: 'var(--wu-mute)', letterSpacing: '0.08em' }}>검토 메모</div>
              <textarea value={memo} onChange={e => setMemo(e.target.value)} placeholder="반려 사유 또는 검토 의견을 입력하세요" className="kr" rows={3} style={{ width: '100%', marginTop: 8, border: '1px solid var(--wu-line)', background: 'var(--wu-bg)', padding: 10, fontSize: 13, fontFamily: 'Pretendard', lineHeight: 1.5, resize: 'none', outline: 0 }} />
            </div>

            {/* Action buttons */}
            <div style={{ marginTop: 20, display: 'flex', gap: 8, justifyContent: 'space-between' }}>
              <div style={{ display: 'flex', gap: 8 }}>
                <button onClick={startEdit} style={{ padding: '10px 16px', fontSize: 12, fontWeight: 700, fontFamily: 'var(--wu-kr)', background: 'var(--wu-paper)', border: '1px solid var(--wu-line)', cursor: 'pointer' }}>✏ 수정</button>
                <button onClick={handleDelete} style={{ padding: '10px 16px', fontSize: 12, fontWeight: 700, fontFamily: 'var(--wu-kr)', background: '#fff', border: '1px solid #C44', color: '#C44', cursor: 'pointer' }}>🗑 삭제</button>
              </div>
              <div style={{ display: 'flex', gap: 8 }}>
                {app.status !== 'REJECTED' && (
                  <button onClick={handleReject} className="wu-btn ghost" style={{ fontSize: 12, padding: '10px 16px', color: '#C44', borderColor: '#C44', cursor: 'pointer' }}>✕ 반려</button>
                )}
                {app.status !== 'APPROVED' && (
                  <button onClick={handleApprove} className="wu-btn lime" style={{ fontSize: 12, padding: '10px 20px', cursor: 'pointer' }}>✓ 승인 → 점주 계정 활성화</button>
                )}
              </div>
            </div>
          </div>
        ) : mode === 'view' && (
          <div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'var(--wu-mute)' }}>
            <div style={{ textAlign: 'center' }}>
              <div style={{ fontSize: 48 }}>📋</div>
              <div className="kr" style={{ fontSize: 14, marginTop: 12 }}>점주 신청 내역이 없습니다</div>
              <div className="kr" style={{ fontSize: 12, color: 'var(--wu-mute)', marginTop: 4 }}>점주가 회원가입하거나 위 버튼으로 직접 추가하세요</div>
            </div>
          </div>
        )}
      </div>
    </HQChrome>
  );
}

// ═══════════════════════════════════════════════════════════
// 02 — 공지사항 관리
// ═══════════════════════════════════════════════════════════
function HQNotices() {
  const [notices, setNotices] = useStateHQ([]);
  const [loading, setLoading] = useStateHQ(true);
  const [msg, setMsg] = useStateHQ('');
  const [publishing, setPublishing] = useStateHQ(false);
  // 작성 폼
  const [title, setTitle] = useStateHQ('');
  const [body, setBody] = useStateHQ('');
  const [tag, setTag] = useStateHQ('운영');
  const [audience, setAudience] = useStateHQ('전체');
  const [pinned, setPinned] = useStateHQ(false);
  const [sendPush, setSendPush] = useStateHQ(true);
  const [photos, setPhotos] = useStateHQ([]); // [{ src: base64/url, file: File|null }]
  const photoRef = React.useRef(null);

  const tags = ['운영', '정책', '이벤트', '신상', '긴급', '필독'];
  const audiences = ['전체', '점주만', '회원만'];

  const load = async () => {
    setLoading(true);
    try { const list = await getNotices(); setNotices(list); } catch(e) {}
    setLoading(false);
  };
  React.useEffect(() => { load(); }, []);

  const flash = (t) => { setMsg(t); setTimeout(() => setMsg(''), 3000); };

  // 사진 추가
  const handleAddPhotos = (e) => {
    const files = Array.from(e.target.files || []);
    if (!files.length) return;
    files.forEach(file => {
      const reader = new FileReader();
      reader.onload = () => setPhotos(prev => [...prev, { src: reader.result, file }]);
      reader.readAsDataURL(file);
    });
    e.target.value = '';
  };

  const removePhoto = (idx) => setPhotos(prev => prev.filter((_, i) => i !== idx));

  const handlePublish = async () => {
    if (!title.trim()) { flash('제목을 입력하세요'); return; }
    setPublishing(true);
    try {
      const noticeData = { title: title.trim(), body: body.trim(), tag, audience, pinned, sendPush, photos: [] };
      // Firebase Storage에 사진 업로드
      const noticeId = 'NTC-' + Date.now();
      if (photos.length > 0 && typeof uploadImageToStorage === 'function') {
        for (let i = 0; i < photos.length; i++) {
          try {
            const url = await uploadImageToStorage(photos[i].src, 'notices/' + noticeId, i);
            noticeData.photos.push(url);
          } catch(e) {
            noticeData.photos.push(photos[i].src); // 실패 시 base64 유지
          }
        }
      } else {
        noticeData.photos = photos.map(p => p.src);
      }
      await publishNotice(noticeData);
      if (sendPush && 'Notification' in window && Notification.permission === 'granted') {
        navigator.serviceWorker.ready.then(reg => {
          reg.showNotification('WORKUP · ' + tag, {
            body: title.trim(),
            icon: '/icon-192.png',
            badge: '/icon-192.png',
            tag: 'workup-notice-' + Date.now(),
            vibrate: [200, 100, 200],
          });
        });
      }
      flash('공지 발행 완료!');
      setTitle(''); setBody(''); setPinned(false); setPhotos([]);
      load();
    } catch(e) { flash('발행 실패: ' + e.message); }
    setPublishing(false);
  };

  const handleDelete = async (id) => {
    if (!confirm('이 공지를 삭제하시겠습니까?')) return;
    try { await deleteNotice(id); flash('삭제 완료'); load(); } catch(e) { flash('삭제 실패'); }
  };

  const fmtDate = (iso) => {
    if (!iso) return '—';
    const d = new Date(iso);
    return d.getFullYear() + '.' + String(d.getMonth()+1).padStart(2,'0') + '.' + String(d.getDate()).padStart(2,'0') + ' ' + String(d.getHours()).padStart(2,'0') + ':' + String(d.getMinutes()).padStart(2,'0');
  };

  return (
    <HQChrome active="notices" title="공지사항 관리" subtitle={'HQ · ANNOUNCEMENTS · ' + notices.length + '건'}>
      <div style={{ padding: 28 }}>
        {msg && <div style={{ position: 'fixed', top: 16, left: '50%', transform: 'translateX(-50%)', zIndex: 9999, background: 'var(--wu-ink)', color: 'var(--wu-lime)', padding: '10px 24px', fontSize: 13, fontWeight: 700 }}>{msg}</div>}

        {/* Composer */}
        <div style={{ background: 'var(--wu-ink)', color: 'var(--wu-paper)', padding: 20, marginBottom: 24 }}>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end' }}>
            <div>
              <div className="mono" style={{ fontSize: 10, color: 'var(--wu-lime)' }}>● NEW NOTICE</div>
              <div className="display" style={{ fontSize: 20, marginTop: 2, color: 'var(--wu-paper)' }}>새 공지 작성</div>
            </div>
            <button onClick={handlePublish} disabled={publishing} className="wu-btn lime" style={{ fontSize: 12, padding: '10px 20px', opacity: publishing ? 0.5 : 1 }}>{publishing ? '발행 중...' : '발행하기'}</button>
          </div>

          <input value={title} onChange={e => setTitle(e.target.value)} placeholder="공지 제목을 입력하세요" className="kr" style={{ width: '100%', marginTop: 14, background: '#1A1A17', color: 'var(--wu-paper)', border: '1px solid #2A2A26', padding: '10px 12px', fontSize: 15, fontWeight: 700, outline: 0 }} />

          <div style={{ display: 'flex', gap: 8, marginTop: 10 }}>
            <div>
              <div className="mono" style={{ fontSize: 9, color: 'var(--wu-mute)', marginBottom: 4 }}>태그</div>
              <div style={{ display: 'flex', gap: 4 }}>
                {tags.map(t => (
                  <button key={t} onClick={() => setTag(t)} className="kr" style={{ padding: '5px 10px', fontSize: 11, fontWeight: 700, background: tag === t ? 'var(--wu-lime)' : '#1A1A17', color: tag === t ? 'var(--wu-ink)' : 'var(--wu-paper)', border: '1px solid #2A2A26', cursor: 'pointer' }}>{t}</button>
                ))}
              </div>
            </div>
            <div style={{ marginLeft: 16 }}>
              <div className="mono" style={{ fontSize: 9, color: 'var(--wu-mute)', marginBottom: 4 }}>대상</div>
              <div style={{ display: 'flex', gap: 4 }}>
                {audiences.map(a => (
                  <button key={a} onClick={() => setAudience(a)} className="kr" style={{ padding: '5px 10px', fontSize: 11, fontWeight: 700, background: audience === a ? 'var(--wu-orange)' : '#1A1A17', color: audience === a ? '#fff' : 'var(--wu-paper)', border: '1px solid #2A2A26', cursor: 'pointer' }}>{a}</button>
                ))}
              </div>
            </div>
          </div>

          <textarea value={body} onChange={e => setBody(e.target.value)} placeholder="공지 내용을 입력하세요" className="kr" rows={4} style={{ width: '100%', marginTop: 10, background: '#1A1A17', color: 'var(--wu-paper)', border: '1px solid #2A2A26', padding: 12, fontSize: 13, fontFamily: 'Pretendard', lineHeight: 1.6, resize: 'none', outline: 0 }} />

          {/* 사진 업로드 */}
          <div style={{ marginTop: 10 }}>
            <input ref={photoRef} type="file" accept="image/*" multiple onChange={handleAddPhotos} style={{ display: 'none' }} />
            <div style={{ display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap' }}>
              <button onClick={() => photoRef.current?.click()} style={{ width: 72, height: 72, background: '#1A1A17', border: '1px dashed #2A2A26', cursor: 'pointer', display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 4, color: 'var(--wu-mute)' }}>
                <svg width="20" height="20" viewBox="0 0 20 20" fill="none" stroke="currentColor" strokeWidth="1.5"><rect x="2" y="4" width="16" height="12" rx="1"/><circle cx="7" cy="9" r="1.5"/><path d="M2 14l4-4 3 3 4-5 5 6"/></svg>
                <span className="mono" style={{ fontSize: 9 }}>사진 추가</span>
              </button>
              {photos.map((p, i) => (
                <div key={i} style={{ position: 'relative', width: 72, height: 72 }}>
                  <img src={p.src} style={{ width: '100%', height: '100%', objectFit: 'cover', border: '1px solid #2A2A26' }} />
                  <button onClick={() => removePhoto(i)} style={{ position: 'absolute', top: -6, right: -6, width: 18, height: 18, borderRadius: 999, background: 'var(--wu-orange)', color: '#fff', border: 'none', fontSize: 11, cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>✕</button>
                </div>
              ))}
            </div>
          </div>

          <div style={{ display: 'flex', gap: 16, marginTop: 10, fontSize: 11 }} className="mono">
            <label style={{ display: 'flex', alignItems: 'center', gap: 4, color: '#B8B3A8', cursor: 'pointer' }}><input type="checkbox" checked={pinned} onChange={e => setPinned(e.target.checked)} /> 상단 고정</label>
            <label style={{ display: 'flex', alignItems: 'center', gap: 4, color: '#B8B3A8', cursor: 'pointer' }}><input type="checkbox" checked={sendPush} onChange={e => setSendPush(e.target.checked)} /> 푸시 알림 발송</label>
          </div>
        </div>

        {/* List */}
        <div className="mono" style={{ fontSize: 10, color: 'var(--wu-mute)', letterSpacing: '0.08em', marginBottom: 10 }}>발행 이력 · 총 {notices.length}건</div>
        {loading ? (
          <div className="kr" style={{ textAlign: 'center', padding: 40, color: 'var(--wu-mute)' }}>로딩 중...</div>
        ) : notices.length === 0 ? (
          <div style={{ textAlign: 'center', padding: 40, background: 'var(--wu-paper)', border: '1px solid var(--wu-line)' }}>
            <div className="kr" style={{ fontSize: 14, color: 'var(--wu-mute)' }}>발행된 공지가 없습니다</div>
          </div>
        ) : (
          <div style={{ background: 'var(--wu-paper)', border: '1px solid var(--wu-line)' }}>
            {notices.map(n => (
              <div key={n.id} style={{ padding: '14px 16px', borderBottom: '1px solid var(--wu-line)', display: 'flex', gap: 12, alignItems: 'flex-start' }}>
                {/* 썸네일 */}
                {n.photos && n.photos.length > 0 && (
                  <div style={{ width: 64, height: 64, flexShrink: 0, overflow: 'hidden', border: '1px solid var(--wu-line)' }}>
                    <img src={n.photos[0]} style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
                  </div>
                )}
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ display: 'flex', gap: 6, alignItems: 'center', flexWrap: 'wrap' }}>
                    <span className="mono" style={{ fontSize: 9, padding: '2px 6px', fontWeight: 700, background: n.tag === '긴급' ? 'var(--wu-orange)' : 'var(--wu-lime)', color: '#0E0E0C' }}>{n.tag}</span>
                    <span className="mono" style={{ fontSize: 9, padding: '2px 6px', background: 'var(--wu-bg)', color: 'var(--wu-mute)' }}>{n.audience}</span>
                    {n.pinned && <span style={{ fontSize: 11 }}>📌</span>}
                    {n.sendPush && <span className="mono" style={{ fontSize: 9, color: 'var(--wu-orange)' }}>PUSH</span>}
                    {n.photos && n.photos.length > 0 && <span className="mono" style={{ fontSize: 9, color: 'var(--wu-mute)' }}>📷 {n.photos.length}</span>}
                  </div>
                  <div className="kr" style={{ fontSize: 14, fontWeight: 700, marginTop: 6 }}>{n.title}</div>
                  {n.body && <div className="kr" style={{ fontSize: 12, color: 'var(--wu-mute)', marginTop: 4, lineHeight: 1.5, whiteSpace: 'pre-wrap' }}>{n.body.length > 100 ? n.body.slice(0, 100) + '...' : n.body}</div>}
                  <div className="mono" style={{ fontSize: 10, color: 'var(--wu-mute)', marginTop: 6 }}>{fmtDate(n.createdAt)}</div>
                </div>
                <button onClick={() => handleDelete(n.id)} style={{ background: 'none', border: '1px solid var(--wu-line)', padding: '4px 10px', fontSize: 11, cursor: 'pointer', color: 'var(--wu-mute)', flexShrink: 0 }} className="kr">삭제</button>
              </div>
            ))}
          </div>
        )}
      </div>
    </HQChrome>
  );
}

// ═══════════════════════════════════════════════════════════
// 03 — 전국 매장 현황 맵
// ═══════════════════════════════════════════════════════════
function HQNationalMap() {
  const [stores, setStores] = useStateHQ([]);
  const [loading, setLoading] = useStateHQ(true);
  const [search, setSearch] = useStateHQ('');
  const [activeRegion, setActiveRegion] = useStateHQ('전체');
  const [selected, setSelected] = useStateHQ(null);
  const [geoOk, setGeoOk] = useStateHQ(0);
  const [geoFail, setGeoFail] = useStateHQ(0);
  const mapRef = React.useRef(null);
  const mapObjRef = React.useRef(null);
  const markersRef = React.useRef([]);

  // 매장 데이터 로드
  React.useEffect(() => {
    (async () => {
      try { const list = await getAllStores(); setStores(list); } catch(e) {}
      setLoading(false);
    })();
  }, []);

  // 지역 분류
  const regionKeys = ['전체','서울','경기','인천','부산','대구','대전','광주','울산','강원','충북','충남','전북','전남','경북','경남','제주'];
  const getRegion = (addr) => {
    if (!addr) return '기타';
    for (const r of regionKeys) { if (r !== '전체' && addr.includes(r)) return r; }
    return '기타';
  };
  const regionCounts = {};
  stores.forEach(s => {
    const r = getRegion(s.address);
    regionCounts[r] = (regionCounts[r] || 0) + 1;
  });

  // 카카오맵 초기화 + 지오코딩
  React.useEffect(() => {
    if (!stores.length) return;
    const apiKey = localStorage.getItem('wu-kakao-key');
    if (!apiKey || !mapRef.current) return;
    const initMap = () => {
      try {
        kakao.maps.load(() => {
          const map = new kakao.maps.Map(mapRef.current, { center: new kakao.maps.LatLng(36.5, 127.0), level: 13 });
          map.addControl(new kakao.maps.ZoomControl(), kakao.maps.ControlPosition.RIGHT);
          mapObjRef.current = map;
          const geocoder = new kakao.maps.services.Geocoder();
          const places = new kakao.maps.services.Places();
          const newMarkers = [];
          let okCount = 0; let failCount = 0;
          const _clean = (addr) => {
            if (!addr) return '';
            let c = addr.trim().replace(/\([^)]*\)/g, '').trim();
            c = c.replace(/\s+(?:\d+층|\d+F|B\d+F?|\d+호|\d+동\s*\d*호?|지하\s*\d*층?).*$/i, '').trim();
            c = c.replace(/(\d+[-−]\d+)\s+.+$/, '$1').trim();
            c = c.replace(/,.*$/, '').trim();
            return c;
          };
          const addMk = (s, lat, lng) => {
            const pos = new kakao.maps.LatLng(lat, lng);
            const marker = new kakao.maps.Marker({ map, position: pos, title: s.name });
            const iw = new kakao.maps.InfoWindow({
              content: '<div style="padding:5px 10px;font-size:12px;font-family:Pretendard;font-weight:700;white-space:nowrap">' + (s.name || '') + '</div>',
            });
            kakao.maps.event.addListener(marker, 'click', () => { setSelected(s); iw.open(map, marker); });
            newMarkers.push({ marker, store: s });
            markersRef.current = [...newMarkers];
            okCount++; setGeoOk(okCount);
          };
          stores.forEach(s => {
            if (!s.address || !s.address.trim()) { failCount++; setGeoFail(failCount); return; }
            const raw = s.address.trim();
            const clean = _clean(raw);
            try {
              geocoder.addressSearch(raw, (r1, s1) => {
                if (s1 === kakao.maps.services.Status.OK) { addMk(s, r1[0].y, r1[0].x); return; }
                const tryClean = clean && clean !== raw;
                const step2 = tryClean ? (cb) => geocoder.addressSearch(clean, (r2, s2) => {
                  if (s2 === kakao.maps.services.Status.OK) { addMk(s, r2[0].y, r2[0].x); return; }
                  cb();
                }) : (cb) => cb();
                step2(() => {
                  const kw = s.name + ' ' + (tryClean ? clean : raw);
                  places.keywordSearch(kw, (r3, s3) => {
                    if (s3 === kakao.maps.services.Status.OK && r3.length) { addMk(s, r3[0].y, r3[0].x); return; }
                    places.keywordSearch(tryClean ? clean : raw, (r4, s4) => {
                      if (s4 === kakao.maps.services.Status.OK && r4.length) { addMk(s, r4[0].y, r4[0].x); }
                      else { failCount++; setGeoFail(failCount); }
                    });
                  });
                });
              });
            } catch(e) { failCount++; setGeoFail(failCount); }
          });
        });
      } catch(e) {}
    };
    if (window.kakao && window.kakao.maps) { initMap(); return; }
    if (document.getElementById('kakao-map-script')) { const check = setInterval(() => { if (window.kakao && window.kakao.maps) { clearInterval(check); initMap(); } }, 200); return; }
    const script = document.createElement('script');
    script.id = 'kakao-map-script';
    script.src = 'https://dapi.kakao.com/v2/maps/sdk.js?appkey=' + apiKey + '&libraries=services&autoload=false';
    script.onload = initMap;
    document.head.appendChild(script);
  }, [stores]);

  // 검색/필터 시 마커 show/hide
  React.useEffect(() => {
    if (!markersRef.current.length || !mapObjRef.current) return;
    const q = search.trim().toLowerCase();
    let bounds = null;
    try { bounds = new kakao.maps.LatLngBounds(); } catch(e) {}
    let visCount = 0;
    markersRef.current.forEach(({ marker, store }) => {
      const addr = (store.address || '').toLowerCase();
      const name = (store.name || '').toLowerCase();
      const regionMatch = activeRegion === '전체' || addr.includes(activeRegion);
      const searchMatch = !q || name.includes(q) || addr.includes(q) || (store.storeId || '').toLowerCase().includes(q);
      const visible = regionMatch && searchMatch;
      if (visible) {
        marker.setMap(mapObjRef.current);
        if (bounds) { try { bounds.extend(marker.getPosition()); } catch(e) {} }
        visCount++;
      } else { marker.setMap(null); }
    });
    if (visCount > 0 && bounds && mapObjRef.current) {
      try {
        if (visCount === 1) { mapObjRef.current.setCenter(bounds.getSouthWest()); mapObjRef.current.setLevel(5); }
        else { mapObjRef.current.setBounds(bounds); }
      } catch(e) {}
    }
  }, [search, activeRegion, geoOk]);

  // 필터된 매장 목록
  const filtered = stores.filter(s => {
    const addr = (s.address || '').toLowerCase();
    const name = (s.name || '').toLowerCase();
    const q = search.trim().toLowerCase();
    const regionMatch = activeRegion === '전체' || addr.includes(activeRegion);
    const searchMatch = !q || name.includes(q) || addr.includes(q) || (s.storeId || '').toLowerCase().includes(q);
    return regionMatch && searchMatch;
  });

  return (
    <HQChrome active="map" title="전국 매장 현황 맵" subtitle={'HQ · NATIONAL MAP · ' + stores.length + ' STORES'}>
      <div style={{ display: 'flex', height: '100%' }}>
        {/* 지도 영역 */}
        <div style={{ flex: 1, position: 'relative' }}>
          {/* 지역 필터 탭 */}
          <div style={{ position: 'absolute', top: 12, left: 12, zIndex: 10, display: 'flex', gap: 4, flexWrap: 'wrap', maxWidth: '70%' }}>
            {regionKeys.map(r => {
              const cnt = r === '전체' ? stores.length : (regionCounts[r] || 0);
              if (r !== '전체' && cnt === 0) return null;
              return (
                <button key={r} onClick={() => { setActiveRegion(r); setSelected(null); }} className="kr" style={{ padding: '5px 10px', fontSize: 11, fontWeight: 700, background: activeRegion === r ? 'var(--wu-ink)' : 'rgba(255,255,255,0.95)', color: activeRegion === r ? 'var(--wu-lime)' : 'var(--wu-ink)', border: '1px solid ' + (activeRegion === r ? 'var(--wu-ink)' : 'var(--wu-line)'), borderRadius: 4, cursor: 'pointer', boxShadow: '0 1px 3px rgba(0,0,0,0.15)' }}>
                  {r} {cnt}
                </button>
              );
            })}
          </div>
          {/* 지오코딩 상태 표시 */}
          <div style={{ position: 'absolute', bottom: 12, left: 12, zIndex: 10, background: 'rgba(255,255,255,0.95)', border: '1px solid var(--wu-line)', padding: '6px 12px', borderRadius: 4, boxShadow: '0 1px 3px rgba(0,0,0,0.1)' }}>
            <span className="mono" style={{ fontSize: 10, color: 'var(--wu-mute)' }}>매칭: </span>
            <span className="mono" style={{ fontSize: 11, color: 'var(--wu-lime)', fontWeight: 700 }}>{geoOk}</span>
            {geoFail > 0 && <span className="mono" style={{ fontSize: 11, color: 'var(--wu-orange)', fontWeight: 700, marginLeft: 8 }}>실패: {geoFail}</span>}
            <span className="mono" style={{ fontSize: 10, color: 'var(--wu-mute)', marginLeft: 8 }}>/ {stores.length}</span>
          </div>
          {!localStorage.getItem('wu-kakao-key') ? (
            <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100%', padding: 40 }}>
              <div className="kr" style={{ fontSize: 14, color: 'var(--wu-mute)', textAlign: 'center' }}>카카오맵 API 키가 설정되지 않았습니다<br/><span className="mono" style={{ fontSize: 11 }}>매장 관리에서 API 키를 설정하세요</span></div>
            </div>
          ) : (
            <div ref={mapRef} style={{ width: '100%', height: '100%' }} />
          )}
        </div>

        {/* 사이드바 — 매장 목록 */}
        <div style={{ width: 340, borderLeft: '1px solid var(--wu-line)', background: 'var(--wu-paper)', display: 'flex', flexDirection: 'column', flexShrink: 0 }}>
          {/* 헤더 */}
          <div style={{ padding: '16px 16px 12px', borderBottom: '1px solid var(--wu-line)' }}>
            <div className="mono" style={{ fontSize: 10, color: 'var(--wu-mute)' }}>NATIONWIDE</div>
            <div className="display" style={{ fontSize: 32, marginTop: 2 }}>{stores.length}<span className="mono" style={{ fontSize: 12, color: 'var(--wu-mute)', marginLeft: 6 }}>STORES</span></div>
            {/* 검색 */}
            <input value={search} onChange={e => setSearch(e.target.value)} placeholder="매장명 · 주소 검색" className="kr" style={{ width: '100%', marginTop: 10, padding: '8px 12px', fontSize: 13, border: '1px solid var(--wu-line)', background: 'var(--wu-bg)', outline: 'none' }} />
          </div>

          {/* 선택된 매장 상세 */}
          {selected && (
            <div style={{ padding: 16, background: 'var(--wu-ink)', color: 'var(--wu-paper)', borderBottom: '1px solid #333' }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
                <div>
                  <div className="display" style={{ fontSize: 18, color: 'var(--wu-paper)' }}>{selected.name}</div>
                  {selected.storeId && <div className="mono" style={{ fontSize: 10, color: 'var(--wu-lime)', marginTop: 2 }}>{selected.storeId}</div>}
                </div>
                <button onClick={() => setSelected(null)} style={{ background: 'none', border: 'none', color: 'var(--wu-mute)', fontSize: 16, cursor: 'pointer' }}>✕</button>
              </div>
              <div className="kr" style={{ fontSize: 12, color: 'var(--wu-mute)', marginTop: 8 }}>{selected.address || '주소 없음'}</div>
              {(selected.mobile || selected.phone) && <div className="mono" style={{ fontSize: 12, color: 'var(--wu-paper)', marginTop: 4 }}>{selected.mobile || selected.phone}</div>}
              {selected.manager && <div className="kr" style={{ fontSize: 11, color: 'var(--wu-mute)', marginTop: 4 }}>담당자: {selected.manager}</div>}
            </div>
          )}

          {/* 매장 리스트 */}
          <div className="wu-scroll" style={{ flex: 1, overflow: 'auto' }}>
            {loading ? (
              <div className="kr" style={{ padding: 40, textAlign: 'center', color: 'var(--wu-mute)' }}>매장 데이터 로딩 중...</div>
            ) : filtered.length === 0 ? (
              <div className="kr" style={{ padding: 40, textAlign: 'center', color: 'var(--wu-mute)' }}>매장이 없습니다</div>
            ) : (
              filtered.map((s, i) => (
                <div key={s.id || i} onClick={() => {
                  setSelected(s);
                  // 해당 마커로 포커스
                  const found = markersRef.current.find(m => m.store === s);
                  if (found && mapObjRef.current) {
                    mapObjRef.current.setCenter(found.marker.getPosition());
                    mapObjRef.current.setLevel(5);
                  }
                }} style={{ padding: '10px 16px', borderBottom: '1px solid var(--wu-line)', cursor: 'pointer', background: selected === s ? 'var(--wu-bg)' : 'transparent' }}>
                  <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
                    <div className="kr" style={{ fontSize: 13, fontWeight: 700 }}>{s.name}</div>
                    <span className="mono" style={{ fontSize: 10, color: 'var(--wu-lime)', background: 'var(--wu-ink)', padding: '2px 6px', borderRadius: 3 }}>{getRegion(s.address)}</span>
                  </div>
                  <div className="kr" style={{ fontSize: 11, color: 'var(--wu-mute)', marginTop: 2 }}>{s.address || '주소 없음'}</div>
                </div>
              ))
            )}
          </div>

          {/* 지역별 통계 */}
          <div style={{ padding: 12, borderTop: '1px solid var(--wu-line)', background: 'var(--wu-bg)' }}>
            <div className="mono" style={{ fontSize: 9, color: 'var(--wu-mute)', marginBottom: 6 }}>REGION SUMMARY</div>
            <div style={{ display: 'flex', flexWrap: 'wrap', gap: 4 }}>
              {regionKeys.filter(r => r !== '전체' && regionCounts[r]).map(r => (
                <span key={r} className="mono" style={{ fontSize: 10, padding: '3px 6px', background: 'var(--wu-paper)', border: '1px solid var(--wu-line)', borderRadius: 3 }}>{r} {regionCounts[r]}</span>
              ))}
            </div>
          </div>
        </div>
      </div>
    </HQChrome>
  );
}

// ═══════════════════════════════════════════════════════════
// 04 — 통합 KPI 대시보드
// ═══════════════════════════════════════════════════════════
function HQKPI() {
  const kpis = [
    { l: '이번 달 총 매출', v: '₩12.8B', delta: '+14%', pos: true },
    { l: '주문 건수', v: '38,291', delta: '+9%', pos: true },
    { l: '평균 객단가', v: '₩128k', delta: '+5%', pos: true },
    { l: '활성 회원', v: '48,292', delta: '+2,104', pos: true },
    { l: '재고 회전일', v: '42일', delta: '-3', pos: true },
    { l: '반품률', v: '2.8%', delta: '+0.3%', pos: false },
  ];

  // Simple bar chart data
  const months = [
    { m: '11월', v: 8.2 }, { m: '12월', v: 9.1 }, { m: '1월', v: 7.8 },
    { m: '2월', v: 8.9 }, { m: '3월', v: 11.2 }, { m: '4월', v: 12.8 },
  ];
  const max = 14;

  const topSku = [
    { rank: 1, sku: 'MD6MUAWT111', kr: '매드독 쿨링 팬 반팔', brand: 'MADDOG', units: 1240, rev: '₩66.7M' },
    { rank: 2, sku: 'WU-24-JK-012', kr: '카본 덕 자켓', brand: 'WORKUP', units: 842, rev: '₩159.1M' },
    { rank: 3, sku: 'FC-PT-034', kr: '헤비웨이트 카고', brand: 'FORGE&CO', units: 719, rev: '₩85.5M' },
    { rank: 4, sku: 'WU-24-BT-007', kr: '스틸토 부츠', brand: 'WORKUP', units: 512, rev: '₩127.5M' },
    { rank: 5, sku: 'WU-24-SH-019', kr: '필드 셔츠 V2', brand: 'WORKUP', units: 488, rev: '₩43.4M' },
  ];

  const brandShare = [
    { b: 'WORKUP', pct: 42, c: '#0E0E0C' },
    { b: 'MADDOG', pct: 18, c: '#D6FF3D' },
    { b: 'FORGE&CO', pct: 14, c: '#6B6157' },
    { b: 'OAKLANE', pct: 11, c: '#8B7355' },
    { b: 'MILLHOUSE', pct: 9, c: '#C44' },
    { b: '기타', pct: 6, c: '#B8B3A8' },
  ];

  return (
    <HQChrome active="kpi" title="통합 KPI 대시보드" subtitle="HQ · EXECUTIVE DASHBOARD · APR 2026">
      <div style={{ padding: 28 }}>
        {/* KPI strip */}
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(6, 1fr)', gap: 10 }}>
          {kpis.map(k => (
            <div key={k.l} style={{ background: 'var(--wu-paper)', border: '1px solid var(--wu-line)', padding: 14 }}>
              <div className="kr mono" style={{ fontSize: 10, color: 'var(--wu-mute)' }}>{k.l}</div>
              <div className="display" style={{ fontSize: 24, marginTop: 4 }}>{k.v}</div>
              <div className="mono" style={{ fontSize: 10, color: k.pos ? 'var(--wu-ink)' : '#C44', fontWeight: 700, marginTop: 4 }}>{k.pos ? '▲' : '▼'} {k.delta}</div>
            </div>
          ))}
        </div>

        {/* Chart + brand share */}
        <div style={{ display: 'grid', gridTemplateColumns: '2fr 1fr', gap: 16, marginTop: 16 }}>
          <div style={{ background: 'var(--wu-paper)', border: '1px solid var(--wu-line)', padding: 20 }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end' }}>
              <div>
                <div className="mono" style={{ fontSize: 10, color: 'var(--wu-mute)' }}>MONTHLY REVENUE · ₩B</div>
                <div className="display" style={{ fontSize: 20, marginTop: 2 }}>최근 6개월 매출 추이</div>
              </div>
              <div style={{ display: 'flex', gap: 4 }}>
                {['6M', '1Y', '3Y'].map(r => <button key={r} className="mono" style={{ padding: '4px 10px', fontSize: 10, fontWeight: 700, background: r === '6M' ? 'var(--wu-ink)' : 'var(--wu-bg)', color: r === '6M' ? 'var(--wu-lime)' : 'var(--wu-ink)', border: '1px solid var(--wu-ink)' }}>{r}</button>)}
              </div>
            </div>
            <div style={{ display: 'flex', alignItems: 'flex-end', gap: 16, marginTop: 24, height: 240, borderBottom: '1px solid var(--wu-line)', paddingBottom: 8 }}>
              {months.map((m, i) => (
                <div key={m.m} style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 6 }}>
                  <div className="mono" style={{ fontSize: 10, fontWeight: 700 }}>₩{m.v}B</div>
                  <div style={{ width: '100%', height: (m.v / max) * 200, background: i === months.length - 1 ? 'var(--wu-lime)' : 'var(--wu-ink)', position: 'relative' }}>
                    {i === months.length - 1 && <span className="mono" style={{ position: 'absolute', top: -18, left: '50%', transform: 'translateX(-50%)', fontSize: 9, color: 'var(--wu-ink)', fontWeight: 700, background: 'var(--wu-lime)', padding: '1px 4px' }}>● LIVE</span>}
                  </div>
                  <div className="kr" style={{ fontSize: 11, color: 'var(--wu-mute)' }}>{m.m}</div>
                </div>
              ))}
            </div>
          </div>

          <div style={{ background: 'var(--wu-paper)', border: '1px solid var(--wu-line)', padding: 20 }}>
            <div className="mono" style={{ fontSize: 10, color: 'var(--wu-mute)' }}>BRAND SHARE</div>
            <div className="display" style={{ fontSize: 20, marginTop: 2 }}>브랜드별 매출 비중</div>
            {/* Stacked bar */}
            <div style={{ display: 'flex', marginTop: 18, height: 14, border: '1px solid var(--wu-ink)' }}>
              {brandShare.map(b => <div key={b.b} style={{ width: b.pct + '%', background: b.c }} />)}
            </div>
            <div style={{ marginTop: 12 }}>
              {brandShare.map(b => (
                <div key={b.b} style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '5px 0', borderBottom: '1px solid var(--wu-line)' }}>
                  <div style={{ width: 12, height: 12, background: b.c, border: '1px solid rgba(0,0,0,0.1)' }} />
                  <div className="mono" style={{ fontSize: 11, fontWeight: 700, flex: 1 }}>{b.b}</div>
                  <div className="display" style={{ fontSize: 14 }}>{b.pct}%</div>
                </div>
              ))}
            </div>
          </div>
        </div>

        {/* Top SKU table */}
        <div style={{ marginTop: 16, background: 'var(--wu-paper)', border: '1px solid var(--wu-line)' }}>
          <div style={{ padding: '14px 20px', borderBottom: '1px solid var(--wu-line)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
            <div>
              <div className="mono" style={{ fontSize: 10, color: 'var(--wu-mute)' }}>TOP SKU · THIS MONTH</div>
              <div className="display" style={{ fontSize: 20, marginTop: 2 }}>베스트셀러 Top 5</div>
            </div>
            <button className="wu-btn ghost" style={{ fontSize: 11, padding: '6px 12px' }}>전체 리포트 →</button>
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: '50px 140px 1fr 120px 120px 120px', padding: '10px 20px', fontFamily: 'JetBrains Mono', fontSize: 9, color: 'var(--wu-mute)', letterSpacing: '0.06em', background: 'var(--wu-bg)', borderBottom: '1px solid var(--wu-line)' }}>
            <div>순위</div><div>SKU</div><div>상품명</div><div>브랜드</div><div>판매수량</div><div>매출</div>
          </div>
          {topSku.map(s => (
            <div key={s.sku} style={{ display: 'grid', gridTemplateColumns: '50px 140px 1fr 120px 120px 120px', padding: '14px 20px', borderBottom: '1px solid var(--wu-line)', alignItems: 'center' }}>
              <div className="display" style={{ fontSize: 22, color: s.rank === 1 ? 'var(--wu-orange)' : 'var(--wu-ink)' }}>{s.rank}</div>
              <div className="mono" style={{ fontSize: 11 }}>{s.sku}</div>
              <div className="kr" style={{ fontSize: 14, fontWeight: 700 }}>{s.kr}</div>
              <div className="mono" style={{ fontSize: 11, fontWeight: 700 }}>{s.brand}</div>
              <div className="display" style={{ fontSize: 16 }}>{s.units.toLocaleString()}</div>
              <div className="display" style={{ fontSize: 16, color: 'var(--wu-ink)' }}>{s.rev}</div>
            </div>
          ))}
        </div>
      </div>
    </HQChrome>
  );
}

// ═══════════════════════════════════════════════════════════
// 05 — AI 상세페이지 생성기
// ═══════════════════════════════════════════════════════════
function parseProductInput(raw) {
  const lines = raw.trim().split('\n');
  let name = '', code = '', wholesale = '', retail = '', colors = '', sizes = '', qty = '', features = [], brand = '';
  for (const line of lines) {
    const l = line.trim();
    if (l.startsWith('**') && l.endsWith('**')) { name = l.replace(/\*\*/g, '').trim(); }
    else if (l.match(/공급가/)) { const m = l.match(/[\d,]+/); if (m) wholesale = m[0]; }
    else if (l.match(/판매가/)) { const m = l.match(/[\d,]+/); if (m) retail = m[0]; }
    else if (l.match(/색\s*상/)) { colors = l.replace(/.*[:：]/, '').trim(); }
    else if (l.match(/사이즈/)) { sizes = l.replace(/.*[:：]/, '').trim(); }
    else if (l.match(/입수량/)) { qty = l.replace(/.*[:：]/, '').trim(); }
    else if (l.startsWith('✔')) { features.push(l.replace('✔', '').trim()); }
  }
  const codeMatch = raw.match(/[A-Z]{2,}\d+[A-Z]*\d*/);
  if (codeMatch) code = codeMatch[0];
  const brandMatch = name.match(/^([가-힣a-zA-Z]+)\s/);
  if (brandMatch) brand = brandMatch[1].toUpperCase();
  return { name, code, wholesale, retail, colors, sizes, qty, features, brand, raw };
}

function generateOutput(parsed, tone) {
  const { name, features, colors, sizes, brand } = parsed;
  const featureText = features.join(', ');
  if (tone === 'pro') {
    return {
      title: name + ' · 재입고',
      sub: features.slice(0, 3).join(' · '),
      body: (brand ? brand + '의 ' : '') + name + '. ' + (features.length > 0 ? features.join('. ') + '.' : '') + ' ' + (colors ? colors + ' 컬러로 출시' : '') + (sizes ? ', 사이즈 ' + sizes + ' 구성.' : '.') + ' 현장과 일상 모두 대응 가능한 실용적 디자인.',
      bullets: features.length > 0 ? features : ['상품 정보를 입력하세요'],
      care: '상품 라벨의 세탁 방법을 확인하세요.',
      seo: [brand, name.replace(/\s/g, ' '), colors, '워크웨어', 'workup'].filter(Boolean).join(', '),
    };
  }
  if (tone === 'casual') {
    return {
      title: name + ' 다시 왔어요!',
      sub: '품절됐던 그 제품, 놓치지 마세요.',
      body: '매번 품절이었던 ' + name + ', 드디어 재입고! ' + (features.length > 0 ? features[0] + '. ' : '') + (colors ? colors + ' 컬러로 준비했어요. ' : '') + (sizes ? '사이즈는 ' + sizes + '까지. ' : '') + '이번에도 빠르게 빠질 수 있으니 서두르세요.',
      bullets: features.map(f => f.replace(/^(발을|다양한|깊은|일체형)/, '→ $1')),
      care: '라벨 참고해서 세탁해주세요.',
      seo: [name, brand, '재입고', '인기템'].filter(Boolean).join(', '),
    };
  }
  if (tone === 'hype') {
    return {
      title: (brand || 'WORKUP') + ' · RESTOCK DROP',
      sub: 'SOLD OUT → BACK.',
      body: '품절을 반복한 ' + name + '. 다시 돌아왔다. ' + (features.length > 0 ? features[0] + '. ' : '') + '한정 수량. 152개 매장 동시 재입고.',
      bullets: features.map(f => '▪ ' + f),
      care: '라벨 참고',
      seo: [brand, name, 'RESTOCK', '워크웨어'].filter(Boolean).join(', '),
    };
  }
  return {
    title: name,
    sub: brand || '',
    body: name + '. ' + features.join('. ') + '.',
    bullets: features,
    care: '라벨 참고',
    seo: [name, brand].filter(Boolean).join(', '),
  };
}

function HQAIGenerator() {
  const [tone, setTone] = useStateHQ('pro');
  const [generated, setGenerated] = useStateHQ(false);
  const [rawInput, setRawInput] = useStateHQ('');
  const [loading, setLoading] = useStateHQ(false);
  const [parsed, setParsed] = useStateHQ(null);
  const [photos, setPhotos] = React.useState([]);
  const [published, setPublished] = React.useState(false);
  const fileRef = React.useRef(null);

  const handlePhotos = (e) => {
    const files = Array.from(e.target.files);
    const remaining = 20 - photos.length;
    const toAdd = files.slice(0, remaining);
    toAdd.forEach(file => {
      const isVideo = file.type.startsWith('video/');
      const reader = new FileReader();
      reader.onload = (ev) => {
        setPhotos(prev => {
          if (prev.length >= 20) return prev;
          return [...prev, { id: Date.now() + Math.random(), src: ev.target.result, name: file.name, type: isVideo ? 'video' : 'image' }];
        });
      };
      reader.readAsDataURL(file);
    });
    e.target.value = '';
  };

  const removePhoto = (id) => setPhotos(prev => prev.filter(p => p.id !== id));
  const movePhoto = (idx, dir) => setPhotos(prev => {
    const arr = [...prev];
    const newIdx = idx + dir;
    if (newIdx < 0 || newIdx >= arr.length) return arr;
    [arr[idx], arr[newIdx]] = [arr[newIdx], arr[idx]];
    return arr;
  });

  const tones = [
    { k: 'pro', l: '전문적', d: '스펙 중심' },
    { k: 'casual', l: '친근한', d: '구어체' },
    { k: 'hype', l: '임팩트', d: '강한 카피' },
    { k: 'minimal', l: '미니멀', d: '짧고 깔끔' },
  ];

  const handleGenerate = () => {
    if (!rawInput.trim()) return;
    setLoading(true);
    setPublished(false);
    const p = parseProductInput(rawInput);
    setParsed(p);
    setTimeout(() => { setGenerated(true); setLoading(false); }, 1500);
  };

  const handlePublish = async () => {
    if (!out || !parsed) return;
    const product = {
      ...out,
      highlights: out.bullets || [],
      parsed: { ...parsed },
      photos: photos.filter(p => p.type !== 'video').map(p => p.src),
      videos: photos.filter(p => p.type === 'video').map(p => p.src),
      media: photos.map(p => ({ src: p.src, type: p.type || 'image' })),
      tone,
    };
    try {
      await publishProduct(product);
      setPublished(true);
    } catch (e) {
      console.error('Publish failed:', e);
      alert('발행 실패: ' + e.message);
    }
  };

  const out = parsed ? generateOutput(parsed, tone) : null;

  return (
    <HQChrome active="ai" title="AI 상세페이지 생성기" subtitle="HQ · AI DESCRIPTION WRITER">
      <div style={{ display: 'flex', height: '100%' }}>
        {/* Input panel */}
        <div style={{ width: 440, borderRight: '1px solid var(--wu-line)', padding: 24, overflow: 'auto', flexShrink: 0 }} className="wu-scroll">
          <div className="mono" style={{ fontSize: 10, color: 'var(--wu-mute)', letterSpacing: '0.08em' }}>01 · SOURCE</div>
          <div className="kr" style={{ fontSize: 12, color: 'var(--wu-mute)', marginTop: 4 }}>텔레그램 · 공급처 데이터를 붙여넣기 하세요</div>

          <textarea value={rawInput} onChange={e => setRawInput(e.target.value)}
            placeholder={"** 브랜드 상품명 **\n☞ 공급가 : 10,000원\n☞ 판매가 : 15,000원\n☞ 색상 : 블랙\n☞ 사이즈 : M~XL\n✔ 특징 1\n✔ 특징 2"}
            className="kr" style={{ width: '100%', marginTop: 12, padding: 14, border: '1px solid var(--wu-line)', background: 'var(--wu-paper)', fontSize: 12, lineHeight: 1.6, resize: 'vertical', minHeight: 180, outline: 'none', fontFamily: 'var(--wu-mono)' }} />

          {parsed && (
            <div style={{ marginTop: 12, background: 'var(--wu-paper)', border: '1px solid var(--wu-line)', padding: 14 }}>
              <div className="mono" style={{ fontSize: 9, color: 'var(--wu-mute)', marginBottom: 6 }}>PARSED DATA</div>
              <div className="kr" style={{ fontSize: 14, fontWeight: 700 }}>{parsed.name || '상품명 미감지'}</div>
              <div className="mono" style={{ fontSize: 10, color: 'var(--wu-mute)', marginTop: 4, lineHeight: 1.5 }}>
                {parsed.code && <>코드: {parsed.code}<br /></>}
                {parsed.wholesale && <>공급가 ₩{parsed.wholesale}</>}{parsed.retail && <> · 판매가 ₩{parsed.retail}</>}{(parsed.wholesale || parsed.retail) && <br />}
                {parsed.colors && <>컬러: {parsed.colors}<br /></>}
                {parsed.sizes && <>사이즈: {parsed.sizes}<br /></>}
                {parsed.features.length > 0 && <>특징 {parsed.features.length}개 감지</>}
              </div>
            </div>
          )}

          <div className="mono" style={{ fontSize: 10, color: 'var(--wu-mute)', letterSpacing: '0.08em', marginTop: 24 }}>02 · MEDIA · 사진/영상 ({photos.length}/20)</div>
          <div className="kr" style={{ fontSize: 12, color: 'var(--wu-mute)', marginTop: 4 }}>최대 20개 · 영상은 메인에 자동 표시 · 첫번째가 대표</div>

          <input ref={fileRef} type="file" accept="image/*,video/mp4,video/quicktime,video/webm,video/mov" multiple onChange={handlePhotos} style={{ display: 'none' }} />

          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(5, 1fr)', gap: 6, marginTop: 10 }}>
            {photos.map((p, i) => (
              <div key={p.id} style={{ position: 'relative', aspectRatio: '1/1', borderRadius: 4, overflow: 'hidden', border: i === 0 ? '2px solid var(--wu-lime)' : '1px solid var(--wu-line)' }}>
                {p.type === 'video' ? (
                  <>
                    <video src={p.src} style={{ width: '100%', height: '100%', objectFit: 'cover' }} muted />
                    <div style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', background: 'rgba(0,0,0,0.25)' }}>
                      <div style={{ width: 24, height: 24, borderRadius: 999, background: 'rgba(255,255,255,0.9)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                        <span style={{ fontSize: 10, marginLeft: 2 }}>▶</span>
                      </div>
                    </div>
                  </>
                ) : (
                  <img src={p.src} style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
                )}
                {i === 0 && <div className="mono" style={{ position: 'absolute', top: 0, left: 0, background: 'var(--wu-lime)', color: 'var(--wu-ink)', fontSize: 7, padding: '2px 4px', letterSpacing: '0.05em' }}>MAIN</div>}
                {p.type === 'video' && <div className="mono" style={{ position: 'absolute', top: 0, right: 0, background: 'var(--wu-orange)', color: '#fff', fontSize: 7, padding: '2px 4px' }}>VIDEO</div>}
                <div style={{ position: 'absolute', top: 2, right: p.type === 'video' ? 'auto' : 2, left: p.type === 'video' ? 2 : 'auto', display: 'flex', gap: 2 }}>
                  <button onClick={() => removePhoto(p.id)} style={{ width: 16, height: 16, borderRadius: 999, background: 'rgba(0,0,0,0.6)', color: '#fff', fontSize: 10, display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer', border: 'none', lineHeight: 1 }}>×</button>
                </div>
                <div style={{ position: 'absolute', bottom: 2, left: '50%', transform: 'translateX(-50%)', display: 'flex', gap: 2 }}>
                  {i > 0 && <button onClick={() => movePhoto(i, -1)} style={{ width: 16, height: 16, borderRadius: 999, background: 'rgba(0,0,0,0.6)', color: '#fff', fontSize: 9, cursor: 'pointer', border: 'none', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>←</button>}
                  {i < photos.length - 1 && <button onClick={() => movePhoto(i, 1)} style={{ width: 16, height: 16, borderRadius: 999, background: 'rgba(0,0,0,0.6)', color: '#fff', fontSize: 9, cursor: 'pointer', border: 'none', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>→</button>}
                </div>
              </div>
            ))}
            {photos.length < 20 && (
              <button onClick={() => fileRef.current?.click()} style={{ aspectRatio: '1/1', border: '1.5px dashed var(--wu-line)', borderRadius: 4, background: 'var(--wu-paper)', cursor: 'pointer', display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 2 }}>
                <span style={{ fontSize: 18, color: 'var(--wu-mute)' }}>+</span>
                <span className="mono" style={{ fontSize: 8, color: 'var(--wu-mute)' }}>사진/영상</span>
              </button>
            )}
          </div>

          <div className="mono" style={{ fontSize: 10, color: 'var(--wu-mute)', letterSpacing: '0.08em', marginTop: 24 }}>03 · TONE · 문체</div>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 6, marginTop: 8 }}>
            {tones.map(t => (
              <button key={t.k} onClick={() => setTone(t.k)} style={{ background: tone === t.k ? 'var(--wu-ink)' : 'var(--wu-paper)', color: tone === t.k ? 'var(--wu-paper)' : 'var(--wu-ink)', border: '1px solid ' + (tone === t.k ? 'var(--wu-ink)' : 'var(--wu-line)'), padding: '12px 14px', textAlign: 'left' }}>
                <div className="kr" style={{ fontSize: 13, fontWeight: 700 }}>{t.l}</div>
                <div className="kr mono" style={{ fontSize: 10, opacity: 0.7, marginTop: 2 }}>{t.d}</div>
              </button>
            ))}
          </div>

          <div className="mono" style={{ fontSize: 10, color: 'var(--wu-mute)', letterSpacing: '0.08em', marginTop: 24 }}>04 · OPTIONS</div>
          <div style={{ marginTop: 8, background: 'var(--wu-paper)', border: '1px solid var(--wu-line)', padding: 14, fontSize: 12 }} className="kr">
            {[['상세 설명 (본문)', true], ['핵심 기능 불릿 (5개)', true], ['세탁 · 관리 방법', true], ['SEO 키워드', true], ['FAQ 자동 생성', false], ['사이즈 추천 가이드', false]].map(([l, d]) => (
              <label key={l} style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '6px 0' }}>
                <input type="checkbox" defaultChecked={d} />
                <span style={{ fontSize: 12, fontWeight: 600 }}>{l}</span>
              </label>
            ))}
          </div>

          <button onClick={handleGenerate} disabled={!rawInput.trim() || loading} className="wu-btn lime block" style={{ marginTop: 18, padding: '12px 16px', opacity: (!rawInput.trim() || loading) ? 0.5 : 1 }}>
            {loading ? '⏳ 생성 중...' : '✨ AI 생성 (3초)'}
          </button>
          <div className="mono" style={{ fontSize: 9, color: 'var(--wu-mute)', marginTop: 8, textAlign: 'center' }}>이번 달 생성: 142 / 500건</div>
        </div>

        {/* Output panel */}
        <div style={{ flex: 1, padding: 28, overflow: 'auto', background: 'var(--wu-bg)' }} className="wu-scroll">
          {!generated && !loading && (
            <div style={{ height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'var(--wu-mute)' }}>
              <div style={{ textAlign: 'center' }}>
                <div style={{ fontSize: 48, marginBottom: 16 }}>✨</div>
                <div className="kr" style={{ fontSize: 14 }}>왼쪽에 상품 데이터를 붙여넣고</div>
                <div className="kr" style={{ fontSize: 14 }}>"AI 생성" 버튼을 클릭하세요</div>
              </div>
            </div>
          )}
          {loading && (
            <div style={{ height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
              <div style={{ textAlign: 'center' }}>
                <div style={{ width: 48, height: 48, border: '3px solid var(--wu-line)', borderTopColor: 'var(--wu-lime)', borderRadius: '50%', animation: 'spin 0.8s linear infinite', margin: '0 auto' }} />
                <div className="kr" style={{ fontSize: 14, marginTop: 16, color: 'var(--wu-mute)' }}>AI가 상세페이지를 생성하고 있습니다...</div>
                <style>{'@keyframes spin{to{transform:rotate(360deg)}}'}</style>
              </div>
            </div>
          )}
          {generated && out && (
            <>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
                <div>
                  <div className="mono" style={{ fontSize: 10, color: 'var(--wu-mute)' }}>✨ GENERATED · {tones.find(t => t.k === tone).l.toUpperCase()} TONE</div>
                  <div className="display" style={{ fontSize: 26, marginTop: 2 }}>상세페이지 초안</div>
                </div>
                <div style={{ display: 'flex', gap: 6 }}>
                  <button onClick={handleGenerate} className="wu-btn ghost" style={{ fontSize: 11, padding: '8px 12px' }}>↻ 재생성</button>
                  <button className="wu-btn" style={{ fontSize: 11, padding: '8px 12px', background: 'var(--wu-paper)', border: '1px solid var(--wu-line)' }}>✏ 수정</button>
                  <button onClick={handlePublish} className="wu-btn lime" style={{ fontSize: 11, padding: '8px 14px' }}>{published ? '✓ 발행 완료!' : '상품 페이지 발행 →'}</button>
                </div>
              </div>

              {photos.length > 0 && (
                <div style={{ marginTop: 18 }}>
                  <div style={{ position: 'relative', background: '#0E0E0C', aspectRatio: '16/9', overflow: 'hidden', border: '1px solid var(--wu-line)' }}>
                    {photos[0].type === 'video' ? (
                      <video src={photos[0].src} controls autoPlay muted loop style={{ width: '100%', height: '100%', objectFit: 'contain' }} />
                    ) : (
                      <img src={photos[0].src} style={{ width: '100%', height: '100%', objectFit: 'contain' }} />
                    )}
                    <div style={{ position: 'absolute', bottom: 8, right: 8, background: 'rgba(0,0,0,0.7)', color: '#fff', padding: '4px 8px', borderRadius: 4 }}>
                      <span className="mono" style={{ fontSize: 10 }}>1 / {photos.length}</span>
                    </div>
                  </div>
                  {photos.length > 1 && (
                    <div style={{ display: 'flex', gap: 4, marginTop: 4, overflowX: 'auto' }} className="wu-scroll">
                      {photos.map((p, i) => (
                        <div key={p.id} style={{ width: 56, height: 56, flexShrink: 0, border: i === 0 ? '2px solid var(--wu-lime)' : '1px solid var(--wu-line)', overflow: 'hidden', cursor: 'pointer', position: 'relative' }}>
                          {p.type === 'video' ? (
                            <>
                              <video src={p.src} style={{ width: '100%', height: '100%', objectFit: 'cover' }} muted />
                              <div style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', background: 'rgba(0,0,0,0.3)' }}><span style={{ color: '#fff', fontSize: 14 }}>▶</span></div>
                            </>
                          ) : (
                            <img src={p.src} style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
                          )}
                        </div>
                      ))}
                    </div>
                  )}
                </div>
              )}

              <div style={{ marginTop: photos.length > 0 ? 16 : 18, background: 'var(--wu-paper)', border: '1px solid var(--wu-line)', padding: 28 }}>
                <div style={{ borderLeft: '3px solid var(--wu-lime)', paddingLeft: 12 }}>
                  <div className="mono" style={{ fontSize: 10, color: 'var(--wu-mute)' }}>TITLE · 상품명</div>
                  <div className="display" style={{ fontSize: 28, marginTop: 4, lineHeight: 1.2 }}>{out.title}</div>
                  <div className="kr" style={{ fontSize: 15, color: 'var(--wu-mute)', marginTop: 6, fontWeight: 600 }}>{out.sub}</div>
                </div>

                {parsed && (parsed.code || parsed.wholesale || parsed.retail || parsed.colors || parsed.sizes) && (
                  <div style={{ marginTop: 20, background: 'var(--wu-bg)', border: '1px solid var(--wu-line)', padding: 0 }}>
                    <div style={{ padding: '10px 16px', background: 'var(--wu-ink)', color: 'var(--wu-lime)' }}>
                      <span className="mono" style={{ fontSize: 10, letterSpacing: '0.1em' }}>PRODUCT SPEC · 상품 정보</span>
                    </div>
                    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)' }}>
                      {parsed.code && (
                        <div style={{ padding: '12px 16px', borderBottom: '1px solid var(--wu-line)', borderRight: '1px solid var(--wu-line)' }}>
                          <div className="mono" style={{ fontSize: 9, color: 'var(--wu-mute)', letterSpacing: '0.08em' }}>품번</div>
                          <div className="mono" style={{ fontSize: 14, fontWeight: 700, marginTop: 4 }}>{parsed.code}</div>
                        </div>
                      )}
                      {parsed.wholesale && (
                        <div style={{ padding: '12px 16px', borderBottom: '1px solid var(--wu-line)' }}>
                          <div className="mono" style={{ fontSize: 9, color: 'var(--wu-mute)', letterSpacing: '0.08em' }}>공급가</div>
                          <div className="display" style={{ fontSize: 18, marginTop: 4 }}>₩{parsed.wholesale}</div>
                        </div>
                      )}
                      {parsed.retail && (
                        <div style={{ padding: '12px 16px', borderBottom: '1px solid var(--wu-line)', borderRight: '1px solid var(--wu-line)' }}>
                          <div className="mono" style={{ fontSize: 9, color: 'var(--wu-mute)', letterSpacing: '0.08em' }}>판매가</div>
                          <div className="display" style={{ fontSize: 18, marginTop: 4 }}>₩{parsed.retail}</div>
                        </div>
                      )}
                      {parsed.colors && (
                        <div style={{ padding: '12px 16px', borderBottom: '1px solid var(--wu-line)' }}>
                          <div className="mono" style={{ fontSize: 9, color: 'var(--wu-mute)', letterSpacing: '0.08em' }}>색상</div>
                          <div className="kr" style={{ fontSize: 14, fontWeight: 600, marginTop: 4 }}>{parsed.colors}</div>
                        </div>
                      )}
                      {parsed.sizes && (
                        <div style={{ padding: '12px 16px', borderRight: '1px solid var(--wu-line)' }}>
                          <div className="mono" style={{ fontSize: 9, color: 'var(--wu-mute)', letterSpacing: '0.08em' }}>사이즈</div>
                          <div className="kr" style={{ fontSize: 14, fontWeight: 600, marginTop: 4 }}>{parsed.sizes}</div>
                        </div>
                      )}
                      {parsed.qty && (
                        <div style={{ padding: '12px 16px' }}>
                          <div className="mono" style={{ fontSize: 9, color: 'var(--wu-mute)', letterSpacing: '0.08em' }}>입수량</div>
                          <div className="kr" style={{ fontSize: 14, fontWeight: 600, marginTop: 4 }}>{parsed.qty}</div>
                        </div>
                      )}
                    </div>
                  </div>
                )}

                <div style={{ marginTop: 24 }}>
                  <div className="mono" style={{ fontSize: 10, color: 'var(--wu-mute)' }}>BODY · 본문</div>
                  <div className="kr" style={{ fontSize: 14, lineHeight: 1.8, marginTop: 6 }}>{out.body}</div>
                </div>

                <div style={{ marginTop: 24 }}>
                  <div className="mono" style={{ fontSize: 10, color: 'var(--wu-mute)' }}>HIGHLIGHTS · 핵심 기능</div>
                  <ul style={{ marginTop: 8, paddingLeft: 0, listStyle: 'none' }}>
                    {out.bullets.map((b, i) => (
                      <li key={i} className="kr" style={{ fontSize: 13, padding: '6px 0', borderBottom: i < out.bullets.length - 1 ? '1px solid var(--wu-line)' : 'none', display: 'flex', gap: 10 }}>
                        <span className="mono" style={{ color: 'var(--wu-mute)', fontSize: 10, marginTop: 2 }}>0{i + 1}</span>
                        <span style={{ fontWeight: 600 }}>{b}</span>
                      </li>
                    ))}
                  </ul>
                </div>

                <div style={{ marginTop: 24, display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 20 }}>
                  <div>
                    <div className="mono" style={{ fontSize: 10, color: 'var(--wu-mute)' }}>CARE · 세탁 · 관리</div>
                    <div className="kr" style={{ fontSize: 12, marginTop: 6, lineHeight: 1.6, color: '#555' }}>{out.care}</div>
                  </div>
                  <div>
                    <div className="mono" style={{ fontSize: 10, color: 'var(--wu-mute)' }}>SEO · 검색 키워드</div>
                    <div style={{ display: 'flex', flexWrap: 'wrap', gap: 4, marginTop: 6 }}>
                      {out.seo.split(', ').map(k => <span key={k} className="kr mono" style={{ fontSize: 10, padding: '3px 7px', background: 'var(--wu-bg)', border: '1px solid var(--wu-line)' }}>#{k}</span>)}
                    </div>
                  </div>
                </div>

                <div style={{ marginTop: 24, padding: 12, background: 'var(--wu-lime)', display: 'flex', alignItems: 'center', gap: 10 }}>
                  <span style={{ fontSize: 18 }}>✓</span>
                  <div className="kr" style={{ fontSize: 12, fontWeight: 700, flex: 1 }}>Claude Haiku로 생성 · 검토 후 상품 페이지에 그대로 반영 가능</div>
                  <span className="mono" style={{ fontSize: 10 }}>생성 2.4초</span>
                </div>
              </div>
            </>
          )}
        </div>
      </div>
    </HQChrome>
  );
}

Object.assign(window, { HQChrome, HQApproval, HQNotices, HQNationalMap, HQKPI, HQAIGenerator, HQApp });
