// app-screens.jsx — Home, Category, Detail
const HOME_TABS = ['홈', '트로트', '난타·장구', '합창', '단체복'];
const TAB_FILTER = { '트로트': '트로트', '난타·장구': '난타', '합창': '합창', '단체복': '전통' };

// ── ① 메인 배너 (AI 연출 화보 랜덤 회전) ──
const HERO_PICKS = (() => {
  // 화보 보유 제품 풀에서 방문마다 랜덤 6벌 — 액세서리 제외, 카테고리 중복 최소화
  const pool = CATALOG.filter(p => p.editorial && p.cat !== '액세서리');
  const byCat = {};
  for (const p of pool) (byCat[p.cat] = byCat[p.cat] || []).push(p);
  const cats = Object.keys(byCat).sort(() => Math.random() - 0.5);
  const picks = [];
  for (const c of cats) {                 // 1차: 서로 다른 카테고리에서 한 벌씩
    if (picks.length >= 6) break;
    const arr = byCat[c];
    picks.push(arr[Math.floor(Math.random() * arr.length)]);
  }
  while (picks.length < 6 && pool.length > picks.length) {  // 풀이 작으면 채움
    const p = pool[Math.floor(Math.random() * pool.length)];
    if (!picks.includes(p)) picks.push(p);
  }
  return picks.length ? picks : CATALOG.slice(0, 6);
})();

// 시그니처 와이드 배너(AI 듀오 화보) — 첫 슬라이드
const HERO_BANNER = { id: '_banner', img: 'assets/editorial/hero_banner.jpg', genre: 'Signature', shortName: 'STAR 컬렉션 보기' };

function HeroCarousel({ go }) {
  const [i, setI] = React.useState(0);
  const slides = [HERO_BANNER, ...HERO_PICKS];
  React.useEffect(() => {
    if (slides.length < 2) return;
    const t = setInterval(() => setI(v => (v + 1) % slides.length), 3800);
    return () => clearInterval(t);
  }, [slides.length]);
  const p = slides[i] || {};
  return (
    <div style={{ position: 'relative', height: 380, background: '#1A1714', overflow: 'hidden', fontFamily: "'Noto Serif KR', serif" }}>
      {slides.map((s, k) => (
        <div key={s.id} onClick={() => s.id === '_banner' ? go('category') : go('detail', { id: s.id })} style={{ position: 'absolute', inset: 0, opacity: k === i ? 1 : 0, transition: 'opacity .9s ease', cursor: 'pointer' }}>
          <img src={s.img} alt="" style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', objectPosition: 'center 22%' }} />
          <div style={{ position: 'absolute', inset: 0, background: 'linear-gradient(to bottom, rgba(12,10,8,.12) 30%, rgba(12,10,8,.55) 72%, rgba(12,10,8,.82))' }} />
        </div>
      ))}
      {/* 브랜드 카피 */}
      <div style={{ position: 'absolute', left: 22, right: 22, bottom: 26, color: '#F4F1EA' }}>
        <div style={{ fontFamily: "'Jost', sans-serif", fontSize: 10.5, letterSpacing: '.28em', textTransform: 'uppercase', color: 'rgba(244,241,234,.75)' }}>Stage Costume · Made to order</div>
        <div style={{ fontFamily: "'Cormorant Garamond', serif", fontSize: 34, letterSpacing: '.14em', textIndent: '.14em', marginTop: 8, color: '#fff' }}>STAR</div>
        <div style={{ fontSize: 16, fontWeight: 400, marginTop: 6, letterSpacing: '.01em', lineHeight: 1.4, wordBreak: 'keep-all' }}>무대 위의 주인공을 위한<br />맞춤제작 무대의상</div>
        <div style={{ fontSize: 11.5, fontWeight: 300, marginTop: 9, color: 'rgba(244,241,234,.8)' }}>{p.genre} · {p.shortName}</div>
      </div>
      {/* 인디케이터 */}
      <div style={{ position: 'absolute', left: 22, top: 18, display: 'flex', gap: 5 }}>
        {slides.map((_, k) => <div key={k} style={{ width: k === i ? 18 : 6, height: 3, borderRadius: 2, background: k === i ? '#C19A3D' : 'rgba(244,241,234,.5)', transition: 'width .3s' }} />)}
      </div>
    </div>
  );
}

// ── 단체주문 프로모 (에디토리얼 · 실사 기반) ──
function GroupPromo({ go }) {
  return (
    <div style={{ margin: '0 16px 16px' }}>
      <Press onClick={() => go('group')} style={{ display: 'flex', alignItems: 'stretch', height: 112, borderRadius: 0, overflow: 'hidden', background: T.soft, border: `1px solid ${T.line}`, fontFamily: "'Noto Serif KR', serif" }}>
        {/* 텍스트 */}
        <div style={{ flex: 1, padding: '0 20px', display: 'flex', flexDirection: 'column', justifyContent: 'center', minWidth: 0 }}>
          <div style={{ fontSize: 10, fontWeight: 400, letterSpacing: '.22em', textTransform: 'uppercase', color: T.gold, fontFamily: "'Jost', sans-serif" }}>Group Order</div>
          <div style={{ fontSize: 19, fontWeight: 400, color: T.ink, lineHeight: 1.3, marginTop: 8, letterSpacing: '.01em' }}>팀 의상 <span style={{ color: T.gold }}>맞춤 견적</span></div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 11.5, fontWeight: 300, color: T.sub, marginTop: 10 }}>5벌 이상 · 카톡 1분 견적<span style={{ color: T.taupe }}>→</span></div>
        </div>
        {/* 실사 */}
        <div style={{ width: 116, position: 'relative', flex: '0 0 116px', background: '#EAE4D9' }}>
          <img src="assets/editorial/SM-0173_e.jpg" alt="" style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', objectPosition: 'center 18%' }} />
        </div>
      </Press>
    </div>
  );
}

// ── ③ 실시간 인기 랭킹 ──
function RankRow({ go }) {
  const ranked = [...CATALOG].sort((a, b) => b.reviews - a.reviews);
  return (
    <div style={{ marginBottom: 18, fontFamily: 'Noto Serif KR' }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 7, padding: '0 16px 12px' }}>
        <span style={{ fontSize: 18 }}>🔥</span><span style={{ fontFamily: '"Noto Serif KR"', fontSize: 18, color: T.ink, whiteSpace: 'nowrap' }}>실시간 인기 랭킹</span>
        <span style={{ fontSize: 11.5, color: T.muted, fontWeight: 600, whiteSpace: 'nowrap', marginLeft: 'auto' }}>오늘 11:00 기준</span>
      </div>
      <div style={{ display: 'flex', gap: 12, overflowX: 'auto', padding: '0 16px 2px' }}>
        {ranked.map((p, idx) => (
          <Press key={p.id} onClick={() => go('detail', { id: p.id })} style={{ flex: '0 0 134px' }}>
            <div style={{ position: 'relative' }}>
              <Ph h={150} grad={p.grad} img={p.img} round={14} label="" />
              <div style={{ position: 'absolute', left: 8, top: 8, minWidth: 26, height: 26, padding: '0 7px', borderRadius: 8, background: idx < 3 ? T.ink : 'rgba(26,23,20,.55)', color: idx < 3 ? T.yellow : '#FBFAF6', display: 'flex', alignItems: 'center', justifyContent: 'center', fontFamily: '"Noto Serif KR"', fontSize: 16 }}>{idx + 1}</div>
            </div>
            <div style={{ fontSize: 12.5, fontWeight: 600, color: T.ink, marginTop: 7, lineHeight: 1.32, height: 33, overflow: 'hidden' }}>{p.name}</div>
            <div style={{ display: 'flex', alignItems: 'baseline', gap: 4, marginTop: 2 }}>
              {p.sale && <span style={{ color: T.sale, fontWeight: 800, fontSize: 12.5 }}>{Math.round((1 - p.sale / p.price) * 100)}%</span>}
              <span style={{ fontFamily: '"Noto Serif KR"', fontSize: 15, color: T.ink }}>{KRW(p.sale || p.price)}</span>
            </div>
          </Press>
        ))}
      </div>
    </div>
  );
}

// ============ HOME ============
function HomeScreen({ go, cartCount, toast }) {
  const [count, setCount] = React.useState(8);
  const onScroll = (e) => {
    const el = e.currentTarget;
    if (el.scrollTop + el.clientHeight >= el.scrollHeight - 420) {
      setCount(c => (c >= 60 ? c : c + 6));
    }
  };
  const items = CATALOG.length ? Array.from({ length: count }, (_, i) => CATALOG[i % CATALOG.length]) : [];
  return (
    <div style={{ height: '100%', display: 'flex', flexDirection: 'column', background: T.bg }}>
      {/* header */}
      <div style={{ flex: '0 0 auto', padding: '10px 16px 12px', background: T.bg }}>
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 11 }}>
          <StarLogo size={24} />
          <div style={{ display: 'flex', gap: 12, alignItems: 'center' }}>
            <Press onClick={() => toast('새 소식이 없습니다')} style={{ padding: 4 }}>
              <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke={T.ink} strokeWidth="1.8"><path d="M18 8a6 6 0 1 0-12 0c0 7-3 9-3 9h18s-3-2-3-9M13.7 21a2 2 0 0 1-3.4 0"/></svg>
            </Press>
            <Press onClick={() => go('cart')} style={{ padding: 4, position: 'relative' }}>
              <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke={T.ink} strokeWidth="1.8"><path d="M5 7h14l-1.2 11.2a2 2 0 0 1-2 1.8H8.2a2 2 0 0 1-2-1.8L5 7ZM8.5 7a3.5 3.5 0 0 1 7 0"/></svg>
              {cartCount > 0 && <span style={{ position: 'absolute', top: -4, right: -4, background: T.ink, color: T.bg, fontSize: 9, fontWeight: 500, borderRadius: 9, padding: '1px 5px', fontFamily: "'Jost', sans-serif" }}>{cartCount}</span>}
            </Press>
          </div>
        </div>
        <Press onClick={() => go('category')}><SearchBar placeholder="STAR 무대의상 검색" /></Press>
      </div>
      {/* scroll */}
      <div style={{ flex: 1, overflow: 'auto' }} onScroll={onScroll}>
        {/* ① 롤링 캐러셀 */}
        <HeroCarousel go={go} toast={toast} />
        {/* category circles */}
        <div style={{ display: 'flex', gap: 16, padding: '6px 16px 18px', overflowX: 'auto', WebkitOverflowScrolling: 'touch' }}>
          {CATS.map((c, i) => (
            <Press key={i} onClick={() => go('category', { filter: c.name })} style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 8, width: 52, flex: '0 0 auto' }}>
              <div style={{ width: 52, height: 52, borderRadius: '50%', background: T.soft, border: `1px solid ${T.line}`, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 22, overflow: 'hidden' }}>
                {c.chip
                  ? <img src={c.chip} alt={c.name} style={{ width: '100%', height: '100%', objectFit: 'cover', objectPosition: 'center 12%' }} />
                  : c.emoji}
              </div>
              <span style={{ fontSize: 10.5, fontWeight: 300, color: T.sub, whiteSpace: 'nowrap', fontFamily: "'Noto Serif KR', serif", letterSpacing: '.02em' }}>{c.name}</span>
            </Press>
          ))}
        </div>
        {/* 의상 전체 나열 (무한 스크롤) */}
        {items.length ? (
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14, padding: '6px 16px 24px' }}>
            {items.map((p, i) => <ProductCard key={i} p={p} onClick={() => go('detail', { id: p.id })} />)}
          </div>
        ) : (
          <div style={{ padding: '48px 24px 64px', textAlign: 'center', fontFamily: "'Noto Serif KR', serif" }}>
            <div style={{ fontFamily: "'Jost', sans-serif", fontSize: 10.5, letterSpacing: '.2em', textTransform: 'uppercase', color: T.taupe }}>Coming Soon</div>
            <div style={{ fontSize: 15, fontWeight: 400, color: T.sub, marginTop: 12, lineHeight: 1.7 }}>등록된 상품이 아직 없습니다.<br/>곧 새로운 무대의상으로 찾아뵙겠습니다.</div>
          </div>
        )}
      </div>
      <NavBar active="home" onNav={go} />
    </div>
  );
}

// ============ CATEGORY / LIST ============
function CategoryScreen({ go, params, cartCount }) {
  const filters = ['전체', ...CATS.map(c => c.name)];
  const [f, setF] = React.useState(params?.filter || '전체');
  const list = f === '전체' ? CATALOG : CATALOG.filter(p => p.cat === f || (p.cats && p.cats.includes(f)));
  return (
    <div style={{ height: '100%', display: 'flex', flexDirection: 'column', background: '#F4F1EA' }}>
      <div style={{ flex: '0 0 auto', background: '#FBFAF6', borderBottom: `1px solid ${T.line}` }}>
        <AppHeader title="무대의상 전체" onBack={() => go('home')} onCart={() => go('cart')} cartCount={cartCount} />
        <div style={{ display: 'flex', gap: 8, padding: '4px 14px 12px', overflowX: 'auto' }}>
          {filters.map(c => (
            <Press key={c} onClick={() => setF(c)} style={{ flex: '0 0 auto', padding: '8px 17px', borderRadius: 20, background: f === c ? T.soft : 'transparent', border: f === c ? `1px solid ${T.ink}` : `1px solid ${T.line}`, color: f === c ? T.ink : T.taupe, fontSize: 13.5, fontWeight: f === c ? 500 : 300, whiteSpace: 'nowrap', fontFamily: "'Noto Serif KR', serif", letterSpacing: '.02em' }}>{c}</Press>
          ))}
        </div>
      </div>
      <div style={{ flex: 1, overflow: 'auto', padding: '14px 16px 20px' }}>
        <div style={{ fontSize: 13, color: T.muted, fontWeight: 600, marginBottom: 12, fontFamily: 'Noto Serif KR' }}>총 {list.length}개 · 맞춤제작 가능</div>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16 }}>
          {list.map(p => <ProductCard key={p.id} p={p} onClick={() => go('detail', { id: p.id })} />)}
        </div>
      </div>
      <NavBar active="category" onNav={go} />
    </div>
  );
}

// ============ DETAIL ============
function DetailScreen({ go, params, cartCount, addToCart, toast }) {
  const p = CATALOG.find(x => x.id === params.id) || CATALOG[0];
  if (!p) {
    return (
      <div style={{ height: '100%', display: 'flex', flexDirection: 'column', background: '#FBFAF6' }}>
        <AppHeader title="" onBack={() => go('home')} onCart={() => go('cart')} cartCount={cartCount} />
        <div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', textAlign: 'center', padding: '0 24px', fontFamily: "'Noto Serif KR', serif" }}>
          <div>
            <div style={{ fontFamily: "'Jost', sans-serif", fontSize: 10.5, letterSpacing: '.2em', textTransform: 'uppercase', color: T.taupe }}>Coming Soon</div>
            <div style={{ fontSize: 15, fontWeight: 400, color: T.sub, marginTop: 12 }}>상품을 준비하고 있습니다.</div>
          </div>
        </div>
        <NavBar active="home" onNav={go} />
      </div>
    );
  }
  const [photo, setPhoto] = React.useState(0);
  const [shareOpen, setShareOpen] = React.useState(false);
  const [measureOpen, setMeasureOpen] = React.useState(false);
  const emptyPerson = () => ({ name: '', height: '', weight: '', full: null, top: null, bottom: null, braBand: null, braCup: null });
  const [measures, setMeasures] = React.useState(() => Array.from({ length: p.minQty }, emptyPerson));
  const [color, setColor] = React.useState(p.primaryColor || null);
  const [qty, setQty] = React.useState(p.minQty);
  const unit = p.sale || p.price;

  // 수량이 바뀌면 인원별 실측 항목 수를 맞춘다
  React.useEffect(() => {
    setMeasures(prev => {
      if (prev.length === qty) return prev;
      if (prev.length < qty) return [...prev, ...Array.from({ length: qty - prev.length }, emptyPerson)];
      return prev.slice(0, qty);
    });
  }, [qty]);

  const isFilled = (m) => m.name && m.height && m.weight;
  const measureDoneCount = measures.filter(isFilled).length;
  const allMeasured = qty > 0 && measureDoneCount === qty;
  const ready = !!color && allMeasured;
  const measureSummary = measureDoneCount > 0
    ? (qty > 1 ? `${measureDoneCount}/${qty}명 입력됨` : `${measures[0].name} · ${measures[0].height}cm · ${measures[0].weight}kg`)
    : '';
  const G = p.gallery || (p.photos || ['사진']).map(label => ({ src: p.img || null, label }));
  const cur = G[photo] || G[0];
  const catLabel = (p.cats || [p.cat]).join(' · ');
  const doAdd = (then) => {
    if (!color) { toast('색상을 선택해주세요'); return false; }
    if (!allMeasured) { toast(qty > 1 ? `실측 사이즈를 ${qty}명 모두 입력해주세요` : '실측 사이즈를 입력해주세요'); setMeasureOpen(true); return false; }
    addToCart({ id: p.id, name: p.name, grad: p.grad, img: p.img, color, size: (measures[0] && measures[0].full) || '맞춤', qty, unit, measures: measures.filter(isFilled) });
    if (then) then(); else toast('장바구니에 담았어요');
    return true;
  };

  // ── 공유 ──
  const shareUrl = productUrl(p);
  const colorName = color ? (COL[color] && COL[color].name) || color : '';
  const inquiryMsg =
    `[STAR 무대의상 제작 문의]\n· 상품: ${p.name} (${p.sm || p.id})` +
    (colorName ? `\n· 희망 색상: ${colorName}` : '') +
    (qty > 1 ? `\n· 수량: ${qty}벌` : '') +
    `\n· 상품 링크: ${shareUrl}\n\n이 옷으로 제작 문의드려요!`;
  // 사장님 카톡으로 바로 문의 — 옷 정보를 복사해 두고 채널 1:1 채팅을 연다
  const inquireKakao = async () => {
    try { await navigator.clipboard.writeText(inquiryMsg); } catch (e) {}
    setShareOpen(false);
    toast('옷 정보를 복사했어요 · 카톡 채팅창에 붙여넣기 해주세요');
    window.open(CONTACT.kakaoChat, '_blank', 'noopener');
  };
  const copyLink = async () => {
    try { await navigator.clipboard.writeText(shareUrl); toast('상품 링크를 복사했어요'); }
    catch (e) { toast('링크 복사를 지원하지 않는 브라우저예요'); }
    setShareOpen(false);
  };
  // 친구·동료에게 공유 — 모바일 네이티브 공유 시트(카톡 포함), 없으면 링크 복사
  const shareNative = async () => {
    setShareOpen(false);
    if (navigator.share) {
      try { await navigator.share({ title: p.name, text: `[STAR 무대의상] ${p.name}`, url: shareUrl }); return; }
      catch (e) { if (e && e.name === 'AbortError') return; }
    }
    try { await navigator.clipboard.writeText(shareUrl); } catch (e) {}
    toast('공유 링크를 복사했어요 · 붙여넣어 보내주세요');
  };
  const saveImg = () => {
    setShareOpen(false);
    if (!cur.src) { toast('저장할 이미지가 없어요'); return; }
    try {
      const a = document.createElement('a');
      a.href = cur.src; a.download = (p.sm || p.id) + '.jpg';
      document.body.appendChild(a); a.click(); a.remove();
      toast('상품 이미지를 저장했어요');
    } catch (e) { toast('이미지를 길게 눌러 저장해 주세요'); }
  };

  return (
    <div style={{ height: '100%', display: 'flex', flexDirection: 'column', background: '#FBFAF6' }}>
      <AppHeader title="" onBack={() => go('home')} onCart={() => go('cart')} cartCount={cartCount} right={
        <Press onClick={() => setShareOpen(true)} style={{ width: 44, height: 44, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
          <svg width="21" height="21" viewBox="0 0 24 24" fill="none" stroke={T.ink} strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/><path d="m8.6 13.5 6.8 4M15.4 6.5l-6.8 4"/></svg>
        </Press>
      } />
      <div style={{ flex: 1, overflow: 'auto' }}>
        {/* photo */}
        <div style={{ position: 'relative', width: '100%', height: 420, background: '#EDEAE2', overflow: 'hidden' }}>
          {cur.src
            ? <img src={cur.src} alt="" style={{ width: '100%', height: '100%', objectFit: 'contain', objectPosition: 'center' }} />
            : <div style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center' }}><span style={{ fontFamily: "'Cormorant Garamond', serif", fontSize: 30, letterSpacing: '.2em', textIndent: '.2em', color: 'rgba(26,26,24,.25)' }}>STAR</span></div>}
          {p.tag && <span style={{ position: 'absolute', left: 14, top: 14, fontFamily: "'Jost', sans-serif", fontSize: 10, fontWeight: 500, letterSpacing: '.16em', color: T.ink, background: 'rgba(244,241,234,.9)', padding: '5px 10px' }}>{p.tag}</span>}
          <div style={{ position: 'absolute', right: 14, bottom: 14, fontFamily: "'Jost', sans-serif", fontSize: 10, letterSpacing: '.14em', color: '#FBFAF6', background: 'rgba(26,26,24,.55)', padding: '5px 10px' }}>{String(photo + 1).padStart(2, '0')} / {String(G.length).padStart(2, '0')} · {cur.label}</div>
        </div>
        <div style={{ display: 'flex', gap: 8, padding: '12px 16px', overflowX: 'auto' }}>
          {G.map((g, i) => (
            <Press key={i} onClick={() => setPhoto(i)} style={{ flex: '0 0 auto', width: 56, height: 56, background: g.src ? `#EDEAE2 url("${g.src}") center 18%/cover` : T.soft, border: i === photo ? `1.5px solid ${T.ink}` : `1px solid ${T.line}`, opacity: i === photo ? 1 : 0.6 }} />
          ))}
        </div>
        {p.hasModel && <div style={{ padding: '0 18px', fontSize: 10.5, fontWeight: 300, color: T.taupe, letterSpacing: '.02em' }}>※ 의상은 실제 제품 촬영본이며, 모델은 가상 인물입니다.</div>}
        {/* info */}
        <div style={{ padding: '6px 18px 0', fontFamily: "'Noto Serif KR', serif" }}>
          <div style={{ fontFamily: "'Jost', sans-serif", fontSize: 10.5, letterSpacing: '.18em', textTransform: 'uppercase', color: T.taupe }}>{catLabel}</div>
          <div style={{ fontSize: 21, fontWeight: 400, color: T.ink, lineHeight: 1.4, marginTop: 9, letterSpacing: '.01em' }}>{p.name}</div>
          <div style={{ display: 'flex', alignItems: 'baseline', gap: 10, marginTop: 16 }}>
            <span style={{ fontSize: 23, fontWeight: 500, color: T.gold, letterSpacing: '.01em' }}>제작 문의</span>
            <span style={{ fontFamily: "'Jost', sans-serif", fontSize: 11, letterSpacing: '.12em', textTransform: 'uppercase', color: T.taupe }}>Made to order</span>
          </div>
          <div style={{ marginTop: 8, fontSize: 12, fontWeight: 300, color: T.taupe, lineHeight: 1.6 }}>원단·디테일·색상·치수에 따라 견적이 달라집니다. 색상·실측을 고르고 카톡으로 1:1 견적을 받아보세요.</div>
          <div style={{ marginTop: 16, fontSize: 13.5, fontWeight: 300, color: T.sub, lineHeight: 1.8 }}>{p.desc}</div>
          {/* 속성 칩 */}
          <div style={{ display: 'flex', gap: 7, flexWrap: 'wrap', marginTop: 14 }}>
            {[p.genre, p.material, p.color, p.detail].filter(Boolean).map((t, i) => (
              <span key={i} style={{ fontSize: 11, fontWeight: 300, color: T.sub, background: T.bg, border: `1px solid ${T.line}`, padding: '5px 10px', letterSpacing: '.02em' }}>{t}</span>
            ))}
          </div>
          {p.minQty > 1 && <div style={{ marginTop: 14, border: `1px solid ${T.line}`, background: T.bg, color: T.sub, fontSize: 12, fontWeight: 300, padding: '12px 14px', letterSpacing: '.02em' }}>단체 주문 · 최소 {p.minQty}벌부터 제작됩니다</div>}
        </div>
        {/* 유튜브 쇼츠 */}
        {p.youtube && <ShortsBlock id={p.youtube} />}
        {/* options */}
        <div style={{ margin: '20px 18px 0', padding: '20px 0 4px', borderTop: `1px solid ${T.line}`, fontFamily: "'Noto Serif KR', serif" }}>
          <OptionBlock label="색상" required value={color}>
            <div style={{ display: 'flex', gap: 9, flexWrap: 'wrap' }}>
              {p.colors.map(c => {
                const cc = COL[c]; const on = color === c;
                return (
                  <Press key={c} onClick={() => setColor(c)} style={{ display: 'flex', alignItems: 'center', gap: 7, padding: '8px 13px 8px 9px', border: on ? `1px solid ${T.ink}` : `1px solid ${T.line}`, background: T.soft }}>
                    <span style={{ width: 18, height: 18, borderRadius: '50%', background: cc.hex, border: cc.hex === '#F4F1EA' ? '1px solid #ddd' : 'none' }} />
                    <span style={{ fontSize: 12.5, fontWeight: on ? 500 : 300, color: T.ink }}>{cc.name}</span>
                  </Press>
                );
              })}
            </div>
          </OptionBlock>
          <OptionBlock label={`수량${p.minQty > 1 ? ` (최소 ${p.minQty})` : ''}`}>
            <Stepper value={qty} setValue={setQty} min={p.minQty} />
          </OptionBlock>
          <OptionBlock label={qty > 1 ? `실측 사이즈 (${qty}명)` : '실측 사이즈'} hint={qty > 1 ? '인원별로 사이즈를 입력해 주세요 · 카톡 상담도 가능' : '맞춤제작을 위해 입력해 주세요 · 사이즈가 고민되면 카톡 상담'}>
            <Press onClick={() => setMeasureOpen(true)} style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10, padding: '14px 15px', border: `1px solid ${measureDoneCount > 0 ? T.ink : T.line}`, background: T.soft }}>
              <span style={{ fontSize: 13, fontWeight: measureDoneCount > 0 ? 400 : 300, color: measureDoneCount > 0 ? T.ink : T.taupe }}>{measureSummary || (qty > 1 ? `${qty}명 실측 정보 입력하기` : '실측 정보 입력하기')}</span>
              <span style={{ fontFamily: "'Jost', sans-serif", fontSize: 16, color: T.taupe }}>›</span>
            </Press>
          </OptionBlock>
        </div>
        <div style={{ height: 12 }} />
      </div>
      {/* sticky purchase bar */}
      <div style={{ flex: '0 0 auto', borderTop: `1px solid ${T.line}`, background: T.soft, padding: '10px 14px', fontFamily: "'Noto Serif KR', serif" }}>
        <Press onClick={() => allMeasured ? toast('카카오톡 채널 상담을 시작합니다') : setMeasureOpen(true)} style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 7, marginBottom: 10, color: allMeasured ? T.sub : T.gold, fontSize: 11.5, fontWeight: 300, letterSpacing: '.02em', whiteSpace: 'nowrap' }}>
          <span style={{ width: 5, height: 5, borderRadius: '50%', background: T.gold }} />
          {allMeasured ? '맞춤제작 · 사이즈 문의는 카톡 상담' : (qty > 1 ? `실측 사이즈 ${measureDoneCount}/${qty}명 · 입력해야 주문됩니다` : '실측 사이즈를 입력해야 주문됩니다')}
        </Press>
        <div style={{ display: 'flex', gap: 9, opacity: ready ? 1 : 0.4, transition: 'opacity .15s' }}>
          <Press onClick={() => doAdd()} style={{ flex: '0 0 44%', textAlign: 'center', padding: '15px', border: `1px solid ${T.ink}`, color: T.ink, fontSize: 13.5, fontWeight: 400, letterSpacing: '.04em' }}>장바구니</Press>
          <Press onClick={() => doAdd(() => go('cart'))} style={{ flex: 1, textAlign: 'center', padding: '15px', background: T.gold, color: T.ink, fontSize: 13.5, fontWeight: 500, letterSpacing: '.04em' }}>바로 구매</Press>
        </div>
      </div>

      {/* 공유 시트 */}
      <Sheet open={shareOpen} onClose={() => setShareOpen(false)} height="auto">
        <div style={{ fontFamily: "'Noto Serif KR', serif", padding: '2px 2px 6px' }}>
          <div style={{ fontFamily: "'Jost', sans-serif", fontSize: 10.5, letterSpacing: '.2em', textTransform: 'uppercase', color: T.taupe, textAlign: 'center' }}>Share</div>
          <div style={{ fontSize: 18, fontWeight: 400, color: T.ink, letterSpacing: '.02em', textAlign: 'center', marginTop: 6 }}>이 옷 공유하기</div>
          {/* 상품 미리보기 */}
          <div style={{ display: 'flex', alignItems: 'center', gap: 13, marginTop: 18, padding: '12px', border: `1px solid ${T.line}`, background: T.bg }}>
            <div style={{ width: 52, height: 64, flex: '0 0 52px', background: cur.src ? `#EAE4D9 url("${cur.src}") center 18%/cover` : T.soft }} />
            <div style={{ minWidth: 0, flex: 1 }}>
              <div style={{ fontSize: 13.5, fontWeight: 400, color: T.ink, lineHeight: 1.4, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{p.name}</div>
              <div style={{ fontSize: 13, fontWeight: 500, color: T.ink, marginTop: 5, whiteSpace: 'nowrap' }}>{KRW(unit)}</div>
            </div>
          </div>
          {/* 사장님께 제작 문의 (강조) */}
          <Press onClick={inquireKakao} style={{ display: 'flex', alignItems: 'center', gap: 12, marginTop: 12, padding: '15px 16px', background: T.kakao }}>
            <svg width="24" height="24" viewBox="0 0 24 24" style={{ flex: '0 0 24px' }}><path d="M12 3C6.5 3 2 6.6 2 11c0 2.8 1.9 5.3 4.7 6.7l-1 3.6c-.1.4.3.7.6.5l4.3-2.8c.4 0 .9.1 1.4.1 5.5 0 10-3.6 10-8s-4.5-8-10-8Z" fill="#3C1E1E"/></svg>
            <div style={{ flex: 1 }}>
              <div style={{ fontSize: 14, fontWeight: 500, color: T.kakaoInk, letterSpacing: '.01em' }}>사장님께 제작 문의하기</div>
              <div style={{ fontSize: 11.5, fontWeight: 300, color: 'rgba(60,30,30,.7)', marginTop: 3 }}>옷 정보를 복사하고 카톡 1:1 채팅을 열어드려요</div>
            </div>
            <span style={{ fontFamily: "'Jost', sans-serif", fontSize: 16, color: T.kakaoInk }}>→</span>
          </Press>
          {/* 기타 공유 */}
          <div style={{ display: 'flex', gap: 9, marginTop: 10 }}>
            {[
              { label: '링크 복사', onClick: copyLink, icon: <path d="M9 15 15 9M10.5 6.5 12 5a4 4 0 0 1 6 6l-1.5 1.5M13.5 17.5 12 19a4 4 0 0 1-6-6l1.5-1.5" /> },
              { label: '공유하기', onClick: shareNative, icon: <><circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/><path d="m8.6 13.5 6.8 4M15.4 6.5l-6.8 4"/></> },
              { label: '이미지 저장', onClick: saveImg, icon: <><rect x="3" y="4" width="18" height="16" rx="1"/><path d="m3 16 5-5 4 4 3-3 6 6"/><circle cx="8.5" cy="9" r="1.4"/></> },
            ].map((b, i) => (
              <Press key={i} onClick={b.onClick} style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 8, padding: '15px 4px', border: `1px solid ${T.line}`, background: T.soft }}>
                <svg width="21" height="21" viewBox="0 0 24 24" fill="none" stroke={T.ink} strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round">{b.icon}</svg>
                <span style={{ fontSize: 11.5, fontWeight: 300, color: T.sub }}>{b.label}</span>
              </Press>
            ))}
          </div>
        </div>
      </Sheet>
      <MeasureSheet open={measureOpen} onClose={() => setMeasureOpen(false)} measures={measures} setMeasures={setMeasures} qty={qty} toast={toast} />
    </div>
  );
}

function OptionBlock({ label, required, value, hint, children }) {
  return (
    <div style={{ marginBottom: 22 }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 12 }}>
        <span style={{ fontSize: 13.5, fontWeight: 400, color: T.ink, letterSpacing: '.02em' }}>{label}</span>
        {required && <span style={{ fontFamily: "'Jost', sans-serif", fontSize: 9.5, letterSpacing: '.12em', textTransform: 'uppercase', color: value ? T.gold : T.taupe }}>{value ? 'Selected' : 'Required'}</span>}
      </div>
      {children}
      {hint && <div style={{ fontSize: 11, fontWeight: 300, color: T.taupe, marginTop: 9 }}>{hint}</div>}
    </div>
  );
}

// ============ 실측 사이즈 입력 시트 (인원별) ============
function MeasureSheet({ open, onClose, measures, setMeasures, qty, toast }) {
  const [active, setActive] = React.useState(0);
  const idx = Math.min(active, Math.max(0, qty - 1));
  const m = measures[idx] || { name: '', height: '', weight: '', full: null, top: null, bottom: null, braBand: null, braCup: null };
  const set = (k, v) => setMeasures(arr => arr.map((row, i) => i === idx ? { ...row, [k]: v } : row));
  const isFilled = (row) => row && row.name && row.height && row.weight;
  const filledCount = measures.filter(isFilled).length;
  const inputStyle = { width: '100%', padding: '12px 14px', border: `1px solid ${T.line}`, background: '#fff', fontSize: 14, color: T.ink, fontFamily: "'Noto Serif KR', serif", outline: 'none', boxSizing: 'border-box', borderRadius: 0 };
  const FULL = ['44', '55', '66', '77', '88', '자유(맞춤)'];
  const TOP = ['85', '90', '95', '100', '105', '110'];
  const BOTTOM = ['28', '29', '30', '31', '32', '33', '34', '35', '36'];
  const BAND = ['65', '70', '75', '80', '85', '90', '95'];
  const CUP = ['A', 'B', 'C', 'D', 'E', 'F'];
  const chip = (label, on, onClick) => (
    <Press key={label} onClick={onClick} style={{ flex: '0 0 auto', minWidth: 44, textAlign: 'center', padding: '10px 14px', border: on ? `1px solid ${T.ink}` : `1px solid ${T.line}`, background: on ? T.soft : 'transparent', color: on ? T.ink : T.taupe, fontSize: 13, fontWeight: on ? 500 : 300 }}>{label}</Press>
  );
  const fieldLabel = (t) => <div style={{ fontSize: 13, fontWeight: 400, color: T.ink, marginBottom: 10, letterSpacing: '.02em' }}>{t}</div>;
  const allDone = filledCount === qty;
  return (
    <Sheet open={open} onClose={onClose} height="92%">
      <div style={{ fontFamily: "'Noto Serif KR', serif", padding: '2px 2px 10px' }}>
        <div style={{ fontFamily: "'Jost', sans-serif", fontSize: 10.5, letterSpacing: '.2em', textTransform: 'uppercase', color: T.gold, textAlign: 'center' }}>Measurements</div>
        <div style={{ fontSize: 18, fontWeight: 400, color: T.ink, textAlign: 'center', marginTop: 6 }}>실측 사이즈 입력</div>
        <div style={{ fontSize: 11.5, fontWeight: 300, color: T.taupe, textAlign: 'center', marginTop: 7, marginBottom: 18, lineHeight: 1.6, wordBreak: 'keep-all' }}>
          {qty > 1 ? `${qty}벌을 인원별로 제작합니다. 한 명씩 선택해 입력해 주세요.` : '맞춤제작에 사용됩니다. 모르는 항목은 비워두고 카톡 상담도 가능해요.'}
        </div>

        {qty > 1 && (
          <div style={{ marginBottom: 20 }}>
            <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', marginBottom: 10 }}>
              <span style={{ fontFamily: "'Jost', sans-serif", fontSize: 10.5, letterSpacing: '.14em', textTransform: 'uppercase', color: T.taupe }}>인원 {qty}명</span>
              <span style={{ fontFamily: "'Jost', sans-serif", fontSize: 11, letterSpacing: '.06em', color: allDone ? T.gold : T.taupe }}>{filledCount} / {qty} 완료</span>
            </div>
            <div style={{ display: 'flex', gap: 8, overflowX: 'auto', paddingBottom: 4 }}>
              {measures.map((row, i) => {
                const on = i === idx; const done = isFilled(row);
                return (
                  <Press key={i} onClick={() => setActive(i)} style={{ flex: '0 0 auto', display: 'flex', alignItems: 'center', gap: 7, padding: '9px 14px', border: on ? `1px solid ${T.ink}` : `1px solid ${T.line}`, background: on ? T.soft : 'transparent', color: on ? T.ink : T.taupe, fontSize: 13, fontWeight: on ? 500 : 300, whiteSpace: 'nowrap' }}>
                    <span>{row.name ? row.name : `${i + 1}번`}</span>
                    <span style={{ width: 6, height: 6, borderRadius: '50%', background: done ? T.gold : 'rgba(26,26,24,.16)' }} />
                  </Press>
                );
              })}
            </div>
          </div>
        )}

        <div style={{ marginBottom: 18 }}>
          {fieldLabel(qty > 1 ? `이름 · ${idx + 1}번` : '이름')}
          <input value={m.name} onChange={e => set('name', e.target.value)} placeholder="입을 분 성함" style={inputStyle} />
        </div>
        <div style={{ display: 'flex', gap: 10, marginBottom: 22 }}>
          <div style={{ flex: 1 }}>
            {fieldLabel('키 (cm)')}
            <input value={m.height} onChange={e => set('height', e.target.value.replace(/[^0-9]/g, ''))} inputMode="numeric" placeholder="예) 162" style={inputStyle} />
          </div>
          <div style={{ flex: 1 }}>
            {fieldLabel('몸무게 (kg)')}
            <input value={m.weight} onChange={e => set('weight', e.target.value.replace(/[^0-9]/g, ''))} inputMode="numeric" placeholder="예) 54" style={inputStyle} />
          </div>
        </div>

        <div style={{ marginBottom: 20 }}>
          {fieldLabel('전체 사이즈')}
          <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>{FULL.map(s => chip(s, m.full === s, () => set('full', m.full === s ? null : s)))}</div>
        </div>
        <div style={{ marginBottom: 20 }}>
          {fieldLabel('상의 사이즈')}
          <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>{TOP.map(s => chip(s, m.top === s, () => set('top', m.top === s ? null : s)))}</div>
        </div>
        <div style={{ marginBottom: 20 }}>
          {fieldLabel('하의 사이즈')}
          <div style={{ display: 'flex', gap: 8, overflowX: 'auto', paddingBottom: 2 }}>{BOTTOM.map(s => chip(s, m.bottom === s, () => set('bottom', m.bottom === s ? null : s)))}</div>
        </div>
        <div style={{ marginBottom: 22 }}>
          {fieldLabel('브래지어')}
          <div style={{ fontFamily: "'Jost', sans-serif", fontSize: 10.5, letterSpacing: '.14em', textTransform: 'uppercase', color: T.taupe, marginBottom: 8 }}>밴드 (cm)</div>
          <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>{BAND.map(s => chip(s, m.braBand === s, () => set('braBand', m.braBand === s ? null : s)))}</div>
          <div style={{ fontFamily: "'Jost', sans-serif", fontSize: 10.5, letterSpacing: '.14em', textTransform: 'uppercase', color: T.taupe, margin: '14px 0 8px' }}>컵</div>
          <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>{CUP.map(s => chip(s, m.braCup === s, () => set('braCup', m.braCup === s ? null : s)))}</div>
          {(m.braBand || m.braCup) && <div style={{ marginTop: 12, padding: '10px 14px', background: T.soft, border: `1px solid ${T.line}`, display: 'flex', alignItems: 'baseline', gap: 8 }}><span style={{ fontSize: 11.5, fontWeight: 300, color: T.taupe }}>선택한 사이즈</span><span style={{ fontFamily: "'Jost', sans-serif", fontSize: 16, letterSpacing: '.04em', color: T.ink }}>{(m.braBand || '__')}{m.braCup || '_'}</span></div>}
        </div>

        {qty > 1 && idx < qty - 1 ? (
          <div style={{ display: 'flex', gap: 9 }}>
            <Press onClick={() => { onClose(); toast(`${filledCount}/${qty}명 저장됐어요`); }} style={{ flex: '0 0 40%', textAlign: 'center', padding: '15px', border: `1px solid ${T.ink}`, color: T.ink, fontSize: 13.5, fontWeight: 400 }}>저장하고 닫기</Press>
            <Press onClick={() => setActive(idx + 1)} style={{ flex: 1, textAlign: 'center', padding: '15px', background: T.gold, color: T.ink, fontSize: 13.5, fontWeight: 500, letterSpacing: '.02em' }}>다음 ({idx + 2}번) →</Press>
          </div>
        ) : (
          <Press onClick={() => { onClose(); toast(qty > 1 ? `${filledCount}/${qty}명 실측 저장됐어요` : '실측 사이즈가 저장됐어요'); }} style={{ marginTop: 4, textAlign: 'center', padding: '15px', background: T.gold, color: T.ink, fontSize: 14, fontWeight: 500, letterSpacing: '.04em' }}>입력 완료</Press>
        )}
      </div>
    </Sheet>
  );
}

// ── 유튜브 쇼츠 임베드 ──
function ShortsBlock({ id }) {
  const [play, setPlay] = React.useState(false);
  return (
    <div style={{ margin: '22px 18px 0', paddingTop: 22, borderTop: `1px solid ${T.line}`, fontFamily: "'Noto Serif KR', serif" }}>
      <div style={{ display: 'flex', alignItems: 'baseline', gap: 9, marginBottom: 12 }}>
        <span style={{ fontFamily: "'Jost', sans-serif", fontSize: 10.5, letterSpacing: '.2em', textTransform: 'uppercase', color: T.gold }}>Shorts</span>
        <span style={{ fontSize: 15, fontWeight: 400, color: T.ink, letterSpacing: '.01em' }}>무대 영상으로 보기</span>
      </div>
      <div style={{ position: 'relative', width: '100%', maxWidth: 260, margin: '0 auto', aspectRatio: '9 / 16', background: '#0c0a08', overflow: 'hidden', border: `1px solid ${T.line}` }}>
        {play ? (
          <iframe title="shorts" src={`https://www.youtube-nocookie.com/embed/${id}?autoplay=1&rel=0&playsinline=1`}
            style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', border: 'none' }}
            allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowFullScreen />
        ) : (
          <Press onClick={() => setPlay(true)} style={{ position: 'absolute', inset: 0 }}>
            <img src={`https://i.ytimg.com/vi/${id}/maxresdefault.jpg`} alt="" onError={(e) => { if (!e.currentTarget.dataset.fb) { e.currentTarget.dataset.fb = '1'; e.currentTarget.src = `https://i.ytimg.com/vi/${id}/hqdefault.jpg`; } }}
              style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover' }} />
            <div style={{ position: 'absolute', inset: 0, background: 'rgba(0,0,0,.18)' }} />
            <div style={{ position: 'absolute', left: '50%', top: '50%', transform: 'translate(-50%,-50%)', width: 56, height: 56, borderRadius: 28, background: 'rgba(244,241,234,.92)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
              <svg width="22" height="22" viewBox="0 0 24 24" fill={T.ink}><path d="M8 5v14l11-7z" /></svg>
            </div>
            <div style={{ position: 'absolute', left: 10, bottom: 10, fontFamily: "'Jost', sans-serif", fontSize: 9.5, letterSpacing: '.12em', color: '#FBFAF6', background: 'rgba(26,23,20,.6)', padding: '4px 8px' }}>▶ YOUTUBE SHORTS</div>
          </Press>
        )}
      </div>
      <a href={`https://www.youtube.com/shorts/${id}`} target="_blank" rel="noreferrer" style={{ display: 'block', textAlign: 'center', marginTop: 10, fontSize: 11.5, fontWeight: 300, color: T.taupe, textDecoration: 'none' }}>유튜브에서 전체 보기 ↗</a>
    </div>
  );
}

// ── 모델 화보 (starevent) ──
function ModelBlock({ images }) {
  const [i, setI] = React.useState(0);
  const cur = images[Math.min(i, images.length - 1)];
  return (
    <div style={{ margin: '22px 18px 0', paddingTop: 22, borderTop: `1px solid ${T.line}`, fontFamily: "'Noto Serif KR', serif" }}>
      <div style={{ display: 'flex', alignItems: 'baseline', gap: 9, marginBottom: 12 }}>
        <span style={{ fontFamily: "'Jost', sans-serif", fontSize: 10.5, letterSpacing: '.2em', textTransform: 'uppercase', color: T.gold }}>Lookbook</span>
        <span style={{ fontSize: 15, fontWeight: 400, color: T.ink, letterSpacing: '.01em' }}>모델 화보</span>
      </div>
      <div style={{ width: '100%', background: '#EDEAE2', overflow: 'hidden', border: `1px solid ${T.line}` }}>
        <img src={cur} alt="" style={{ width: '100%', display: 'block' }} />
      </div>
      {images.length > 1 && (
        <div style={{ display: 'flex', gap: 8, marginTop: 10, overflowX: 'auto' }}>
          {images.map((src, k) => (
            <Press key={k} onClick={() => setI(k)} style={{ flex: '0 0 auto', width: 52, height: 64, background: `#EDEAE2 url("${src}") center/cover`, border: k === i ? `1.5px solid ${T.ink}` : `1px solid ${T.line}`, opacity: k === i ? 1 : 0.6 }} />
          ))}
        </div>
      )}
      <div style={{ marginTop: 10, fontSize: 10.5, fontWeight: 300, color: T.taupe, letterSpacing: '.02em' }}>※ 의상은 실제 제품 촬영본이며, 모델은 가상 인물입니다.</div>
    </div>
  );
}

Object.assign(window, { HomeScreen, CategoryScreen, DetailScreen, OptionBlock, MeasureSheet, ShortsBlock, ModelBlock });
