// 타운카 제휴업체 — 메인 앱
// 화면: home (메인) → category (카테고리별 리스트)

const { useState, useMemo, useEffect, useRef } = React;

// ────────────────────────────────────────────────────────────
// 카테고리 안내 카피
// ────────────────────────────────────────────────────────────
const INTROS = {
  'new-domestic': {
    title: '신차 (국산)',
    desc: '국산차는 온라인 판매가 제한돼요. 가까운 지점에 내방해 "타운카 회원"임을 알리고 상담받으세요.',
    accent: 'rgba(11,181,59,0.08)', icon: 'car'
  },
  'new-imported': {
    title: '신차 (수입)',
    desc: '수입차 공식 전시장입니다. 카마스터 직통 연락처로 시승·견적 상담을 받으실 수 있어요.',
    accent: 'rgba(0,138,237,0.08)', icon: 'car-front'
  },
  used: {
    title: '중고차 구매',
    desc: '검증된 매매상사에서 시세 상담과 매물 추천을 받으실 수 있어요.',
    accent: 'rgba(0,138,237,0.08)', icon: 'badge-dollar-sign'
  },
  accident: {
    title: '차량 사고 정비',
    desc: '사고 접수와 견적은 담당자에게 직접 문의해주세요. 테슬라 공인 바디샵도 포함됩니다.',
    accent: 'rgba(228,31,16,0.06)', icon: 'wrench'
  },
  service: {
    title: '차량 일반 정비',
    desc: '정기 점검, 소모품 교체, 경정비 등 일상 정비를 받을 수 있는 제휴 업체입니다.',
    accent: 'rgba(245,185,0,0.10)', icon: 'settings'
  },
  inspection: {
    title: '자동차 검사',
    desc: 'TS 한국교통안전공단 지정 검사소 및 출장 검사장입니다. 정기검사·차령연장에 활용하세요.',
    accent: 'rgba(0,138,237,0.08)', icon: 'clipboard-check'
  },
  detailing: {
    title: '세차 · 디테일링',
    desc: '출장 세차·유리막 코팅·흡연/에바 클리닝 수준까지 차량 관리 제휴 업체입니다.',
    accent: 'rgba(142,88,240,0.08)', icon: 'sparkles'
  },
  custom: {
    title: '썬팅 · 복원 · 개조',
    desc: '썬팅·PPF·블랙박스 시공부터 실내·가죽 복원, 캠핑카 개조까지 자잘한 특수 시공을 맡아드려요.',
    accent: 'rgba(255,87,134,0.08)', icon: 'wand-2'
  }
};

// 카테고리별 카드 컬러 톤
const CAT_TONES = {
  'new-domestic': { bg: 'linear-gradient(135deg,#E6F8EC,#DAF1E2)', accent: '#06842B' },
  'new-imported': { bg: 'linear-gradient(135deg,#E5F2FE,#D9EAFB)', accent: '#0067BC' },
  'used': { bg: 'linear-gradient(135deg,#FFF4E5,#FFE9CC)', accent: '#A85800' },
  'accident': { bg: 'linear-gradient(135deg,#FFEAE6,#FFD9D2)', accent: '#B81000' },
  'service': { bg: 'linear-gradient(135deg,#FFF7DA,#FFEFB8)', accent: '#8A6500' },
  'inspection': { bg: 'linear-gradient(135deg,#E8E9F8,#DCDEF3)', accent: '#3D44A3' },
  'detailing': { bg: 'linear-gradient(135deg,#F1E7FB,#E6D8F7)', accent: '#6526C4' },
  'custom': { bg: 'linear-gradient(135deg,#FFE7EF,#FFD3E1)', accent: '#C61C5A' }
};

// ────────────────────────────────────────────────────────────
// 루트 앱
// ────────────────────────────────────────────────────────────
function App() {
  const [screen, setScreen] = useState('home'); // 'home' | 'category'
  const [activeCategory, setActiveCategory] = useState(null);
  const [activeSub, setActiveSub] = useState(null);
  const [detailId, setDetailId] = useState(null);
  const [toast, setToast] = useState({ msg: '', visible: false });

  const showToast = (msg) => {
    setToast({ msg, visible: true });
    setTimeout(() => setToast((t) => ({ ...t, visible: false })), 1800);
  };

  const handleCardClick = (p) => setDetailId(p.id);
  const handleCall = () => {}; // tel: 링크가 직접 처리
  const handleCopy = (text) => {
    if (navigator.clipboard) navigator.clipboard.writeText(text).catch(() => {});
    showToast('주소가 복사됐어요');
  };
  const handleDirections = () => {}; // 네이버 지도 링크가 직접 처리

  const detailPartner = PARTNERS.find((p) => p.id === detailId);

  const openCategory = (cid, sub) => {
    setActiveCategory(cid);
    setActiveSub(sub || null);
    setScreen('category');
  };

  return (
    <div style={{
      minHeight: '100vh', background: '#F2F2F4',
      fontFamily: FF, WebkitFontSmoothing: 'antialiased'
    }}>
      {/* 모바일 컨테이너 (max 480px) */}
      <div style={{
        maxWidth: 480, margin: '0 auto',
        minHeight: '100vh', background: '#fff',
        position: 'relative',
        boxShadow: '0 0 0 1px rgba(0,0,0,0.04)'
      }}>
        {screen === 'home' ?
        <HomeScreen
          onOpenCategory={openCategory}
          onOpenDetail={handleCardClick}
          onClose={() => showToast('웹뷰를 닫습니다 (앱 전용)')} /> :


        <CategoryScreen
          initialCategory={activeCategory}
          initialSub={activeSub}
          onBack={() => setScreen('home')}
          onOpenDetail={handleCardClick} />

        }

        {/* 상세 모달 */}
        <DetailModal
          partner={detailId ? detailPartner : null}
          onClose={() => setDetailId(null)}
          onCall={handleCall}
          onCopy={handleCopy}
          onDirections={handleDirections} />
        

        {/* 토스트 */}
        <Toast message={toast.msg} visible={toast.visible} />
      </div>
    </div>);

}

// ────────────────────────────────────────────────────────────
// HOME 스크린
// ────────────────────────────────────────────────────────────
function HomeScreen({ onOpenCategory, onOpenDetail, onClose }) {
  const officialsDrag = useDragScroll();
  const counts = useMemo(() => {
    const out = {};
    CATEGORIES.forEach((c) => {out[c.id] = PARTNERS.filter((p) => p.category === c.id).length;});
    return out;
  }, []);

  const total = PARTNERS.length;

  const officials = useMemo(() => PARTNERS.filter((p) => p.official), []);
  const discounts = useMemo(() => PARTNERS.filter((p) => p.discount), []);

  return (
    <div style={{
      display: 'flex', flexDirection: 'column', minHeight: '100vh',
      background: '#F2F2F4',
    }}>
      {/* 헤더 */}
      <PageHeader title="타운카 제휴 업체"
      leadingIcon="x"
      onLeading={onClose} />
      

      <div style={{ flex: 1 }}>
        {/* 업체 광고 배너 */}
        <AdCarousel ads={ADS} onAdClick={onOpenDetail} total={total} />

        {/* 카테고리 그리드 */}
        <section style={{ padding: '4px 16px 8px' }}>
          <SectionTitle>카테고리</SectionTitle>
          <div style={{
            display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8, marginTop: 12
          }}>
            {CATEGORIES.map((c) =>
            <CategoryCard
              key={c.id}
              category={c}
              count={counts[c.id]}
              onClick={() => onOpenCategory(c.id)} />

            )}
          </div>
        </section>

        {/* 공식 리테일러 */}
        {officials.length > 0 &&
        <section style={{ padding: '16px 0 8px' }}>
            <div style={{ padding: '0 16px' }}>
              <SectionTitle
              action={{ label: '전체 보기', onClick: () => onOpenCategory(officials[0].category) }}>
              
                타운카 공식
              </SectionTitle>
              <div style={{ fontSize: 12, color: TC.textNeutral, letterSpacing: '0.020em', lineHeight: '17px', marginTop: 4 }}>
                타운카가 공식 협력하는 수입차 리테일러입니다
              </div>
            </div>
            <div ref={officialsDrag.ref} {...officialsDrag.handlers} style={{
            display: 'flex', gap: 10, padding: '12px 16px 4px',
            overflowX: 'auto', scrollbarWidth: 'none',
            cursor: 'grab',
          }} className="hide-scroll">
              {officials.map((p) =>
            <OfficialCard key={p.id} partner={p} onClick={() => onOpenDetail(p)} />
            )}
            </div>
          </section>
        }

        {/* 제휴 할인 */}
        {discounts.length > 0 &&
        <section style={{ padding: '12px 16px 8px' }}>
            <SectionTitle>제휴 할인 운영 매장</SectionTitle>
            <div style={{ fontSize: 12, color: TC.textNeutral, letterSpacing: '0.020em', lineHeight: '17px', marginTop: 4, marginBottom: 8 }}>
              타운카 회원 전용 할인이 적용되는 매장이에요
            </div>
            <div style={{
            borderRadius: 14, overflow: 'hidden',
            background: '#fff'
          }}>
              {discounts.map((p, i) =>
            <PartnerCard
              key={p.id}
              partner={p}
              brandLabel={p.brand}
              onClick={() => onOpenDetail(p)} />

            )}
            </div>
          </section>
        }

        {/* 푸터 */}
        <ListFooter />
      </div>
    </div>);

}

// ── 업체 광고 캐러셀
function AdCarousel({ ads, onAdClick, total }) {
  const [index, setIndex] = React.useState(0);
  const drag = useDragScroll();
  const trackRef = drag.ref;
  const containerRef = React.useRef(null);
  const rafRef = React.useRef(null);

  // 스크롤 → 인덱스 동기화 (rAF 스로틀)
  const handleScroll = () => {
    if (rafRef.current) return;
    rafRef.current = requestAnimationFrame(() => {
      rafRef.current = null;
      const el = trackRef.current;
      if (!el) return;
      const w = el.clientWidth;
      const i = Math.round(el.scrollLeft / w);
      setIndex(prev => prev === i ? prev : i);
    });
  };

  const goTo = (i) => {
    const el = trackRef.current;
    if (!el) return;
    el.scrollTo({ left: el.clientWidth * i, behavior: 'smooth' });
  };

  return (
    <div style={{ paddingTop: 12 }}>
      {/* 트랙 (가로 스냅 스크롤) */}
      <div ref={containerRef} style={{ position: 'relative' }}>
        <div ref={trackRef} onScroll={handleScroll} {...drag.handlers} style={{
          display: 'flex', overflowX: 'auto', scrollSnapType: 'x mandatory',
          WebkitOverflowScrolling: 'touch', scrollbarWidth: 'none',
          padding: '0 16px', gap: 12, scrollPaddingLeft: 16,
          cursor: 'grab',
        }} className="hide-scroll">
          {ads.map(ad => (
            <AdSlide key={ad.id} ad={ad} onClick={() => {
              const partner = PARTNERS.find(p => p.id === ad.partnerId);
              if (partner) onAdClick(partner);
            }} />
          ))}
        </div>
      </div>

      {/* 인디케이터 + 라벨 */}
      <div style={{
        padding: '12px 20px 4px',
        display: 'flex', alignItems: 'center', justifyContent: 'space-between',
      }}>
        <div style={{ display: 'flex', gap: 5 }}>
          {ads.map((_, i) => (
            <button key={i} onClick={() => goTo(i)} style={{
              all: 'unset', cursor: 'pointer',
              width: i === index ? 16 : 6, height: 6, borderRadius: 999,
              background: i === index ? TC.textStrong : TC.fillStrong,
              transition: 'width 200ms cubic-bezier(0.2,0,0,1), background 200ms',
            }} aria-label={`광고 ${i + 1}`} />
          ))}
        </div>
        <div style={{
          fontSize: 11, color: TC.textNeutral, letterSpacing: '0.025em',
          display: 'inline-flex', alignItems: 'center', gap: 4,
        }}>
          <Icon name="store" size={12} color={TC.textNeutral} stroke={2} />
          전체 {total}개 제휴 업체
        </div>
      </div>
    </div>
  );
}

// ── 광고 슬라이드 한 장
function AdSlide({ ad, onClick }) {
  return (
    <button onClick={onClick} style={{
      all: 'unset', cursor: 'pointer', flexShrink: 0,
      width: 'calc(100% - 8px)', scrollSnapAlign: 'start',
      borderRadius: 16, overflow: 'hidden',
      background: ad.bg, color: ad.fg,
      padding: '18px 18px 16px', position: 'relative',
      boxSizing: 'border-box', minHeight: 158,
      display: 'flex', flexDirection: 'column', justifyContent: 'space-between',
    }}>
      {/* 장식 라인 (우상단) */}
      <svg width="120" height="120" viewBox="0 0 120 120" style={{
        position: 'absolute', right: -20, top: -20, opacity: 0.16,
      }}>
        <circle cx="60" cy="60" r="60" fill={ad.accent} />
        <circle cx="60" cy="60" r="34" fill="none" stroke={ad.fg} strokeWidth="1" opacity="0.4" />
      </svg>

      <div style={{ position: 'relative', zIndex: 1 }}>
        <span style={{
          display: 'inline-flex', alignItems: 'center', gap: 4,
          height: 20, padding: '0 8px', borderRadius: 999,
          background: 'rgba(255,255,255,0.15)',
          color: ad.fg, fontSize: 10, fontWeight: 700, letterSpacing: '0.05em',
        }}>{ad.badge}</span>
        <div style={{
          marginTop: 8, fontSize: 12, fontWeight: 600,
          letterSpacing: '0.020em', color: ad.fg, opacity: 0.78,
        }}>{ad.eyebrow}</div>
        <div style={{
          marginTop: 3, fontSize: 18, fontWeight: 700, lineHeight: '24px',
          letterSpacing: '-0.025em', color: ad.fg,
          maxWidth: 240, wordBreak: 'keep-all',
        }}>{ad.headline}</div>
      </div>

      <div style={{
        position: 'relative', zIndex: 1,
        display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', gap: 12,
      }}>
        <div style={{
          fontSize: 12, opacity: 0.78, letterSpacing: '0.015em',
          color: ad.fg, lineHeight: '17px', wordBreak: 'keep-all', flex: 1,
        }}>{ad.body}</div>
        <span style={{
          flexShrink: 0,
          display: 'inline-flex', alignItems: 'center', gap: 3,
          height: 30, padding: '0 12px', borderRadius: 999,
          background: ad.accent, color: ad.bg,
          fontSize: 12, fontWeight: 700, letterSpacing: '0.015em',
        }}>
          {ad.cta}
          <Icon name="arrow-right" size={13} color={ad.bg} stroke={2.4} />
        </span>
      </div>
    </button>
  );
}

// ── 카테고리 카드 (흰 배경 · 회색 페이지 위에)
function CategoryCard({ category, count, onClick }) {
  const tone = CAT_TONES[category.id] || {};
  return (
    <button onClick={onClick} style={{
      all: 'unset', cursor: 'pointer', position: 'relative',
      borderRadius: 14, padding: '18px 18px 16px',
      background: '#fff',
      minHeight: 108, display: 'flex', flexDirection: 'column',
      justifyContent: 'space-between', gap: 14,
      boxSizing: 'border-box',
      transition: 'transform 120ms cubic-bezier(0.2,0,0,1), background 120ms',
    }}
    onPointerDown={(e) => { e.currentTarget.style.transform = 'scale(0.97)'; e.currentTarget.style.background = TC.fillSubtle; }}
    onPointerUp={(e) => { e.currentTarget.style.transform = 'scale(1)'; e.currentTarget.style.background = '#fff'; }}
    onPointerLeave={(e) => { e.currentTarget.style.transform = 'scale(1)'; e.currentTarget.style.background = '#fff'; }}>
      <Icon name={category.icon} size={26} color={tone.accent || TC.textStrong} stroke={1.8} />
      <div>
        <div style={{
          fontSize: 14, fontWeight: 700, color: TC.textStrong,
          letterSpacing: '-0.020em', lineHeight: '18px', marginBottom: 3,
        }}>{category.label}</div>
        <div style={{
          fontSize: 12, color: TC.textNeutral,
          fontWeight: 500, letterSpacing: '0.020em',
        }}>{count}개 {category.unit}</div>
      </div>
    </button>);

}

// ── 고객센터 카드 (그리드 마지막 셀)
function ContactCard() {
  return (
    <button style={{
      all: 'unset', cursor: 'pointer',
      borderRadius: 14, padding: '16px 14px 14px',
      background: '#F4F4F6',
      border: '1px dashed ' + TC.line,
      minHeight: 110, display: 'flex', flexDirection: 'column',
      justifyContent: 'space-between', boxSizing: 'border-box'
    }}>
      <div style={{
        width: 38, height: 38, borderRadius: 10,
        background: '#fff',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        boxShadow: '0 1px 2px rgba(0,0,0,0.04)'
      }}>
        <Icon name="headphones" size={19} color={TC.textStrong} stroke={2} />
      </div>
      <div>
        <div style={{
          fontSize: 14, fontWeight: 700, color: TC.textStrong,
          letterSpacing: '-0.020em', marginBottom: 2
        }}>제휴 문의</div>
        <div style={{
          fontSize: 11.5, color: TC.textNeutral,
          fontWeight: 500, letterSpacing: '0.025em', lineHeight: '16px'
        }}>입점·수정·제안<br />고객센터로</div>
      </div>
    </button>);

}

// ── 공식 리테일러 카드 (가로 스크롤)
function OfficialCard({ partner, onClick }) {
  return (
    <button onClick={onClick} style={{
      all: 'unset', cursor: 'pointer', flexShrink: 0,
      width: 220, padding: 16, borderRadius: 14,
      background: '#fff',
      display: 'flex', flexDirection: 'column', gap: 10,
      boxSizing: 'border-box'
    }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
        <Icon name="badge-check" size={15} color={TC.primary} stroke={2.4} />
        <span style={{
          fontSize: 11, fontWeight: 700, color: TC.primaryPressed,
          letterSpacing: '0.025em'
        }}>타운카 공식</span>
      </div>
      <div>
        <div style={{
          fontSize: 11, fontWeight: 600, color: TC.textNeutral,
          letterSpacing: '0.025em', marginBottom: 3
        }}>{partner.brand}</div>
        <div style={{
          fontSize: 16, fontWeight: 700, color: TC.textStrong,
          letterSpacing: '-0.020em', lineHeight: '21px'
        }}>{partner.name}</div>
      </div>
      <div style={{
        fontSize: 12, color: TC.text, letterSpacing: '0.015em',
        lineHeight: '17px', display: 'flex', alignItems: 'center', gap: 4,
        minWidth: 0,
      }}>
        <Icon name="map-pin" size={11} color={TC.textNeutral} stroke={2} style={{ flexShrink: 0 }} />
        <span style={{
          flex: 1, minWidth: 0,
          whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
        }}>{partner.address}</span>
      </div>
    </button>);

}

// ── 섹션 타이틀
function SectionTitle({ children, action }) {
  return (
    <div style={{
      display: 'flex', alignItems: 'baseline', justifyContent: 'space-between'
    }}>
      <h2 style={{
        margin: 0, fontSize: 17, fontWeight: 700, color: TC.textStrong,
        letterSpacing: '-0.020em'
      }}>{children}</h2>
      {action &&
      <button onClick={action.onClick} style={{
        all: 'unset', cursor: 'pointer',
        fontSize: 12, fontWeight: 500, color: TC.textNeutral,
        letterSpacing: '0.020em', display: 'inline-flex', alignItems: 'center', gap: 2
      }}>
          {action.label}
          <Icon name="chevron-right" size={13} color={TC.textNeutral} stroke={2} />
        </button>
      }
    </div>);

}

// ── 푸터
function ListFooter() {
  return (
    <div style={{
      padding: '24px 24px 36px',
      display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4,
      fontFamily: FF
    }}>
      <div style={{ width: 36, height: 1.5, background: TC.fillStrong, marginBottom: 6 }} />
      <div style={{ fontSize: 12, color: TC.textNeutral, letterSpacing: '0.025em', textAlign: 'center', lineHeight: '17px' }}>
        제휴업체 입점 문의 / 정보 수정 요청은
      </div>
      <div style={{ fontSize: 12, fontWeight: 600, color: TC.text, letterSpacing: '0.025em' }}>
        타운카 고객센터로 알려주세요
      </div>
    </div>);

}

// ────────────────────────────────────────────────────────────
// 카테고리 스크린
// ────────────────────────────────────────────────────────────
function CategoryScreen({ initialCategory, initialSub, onBack, onOpenDetail }) {
  const [category, setCategory] = useState(initialCategory || 'new-domestic');
  const [sub, setSub] = useState(initialSub || null);
  const [search, setSearch] = useState('');

  const counts = useMemo(() => {
    const out = {};
    CATEGORIES.forEach((c) => {out[c.id] = PARTNERS.filter((p) => p.category === c.id).length;});
    return out;
  }, []);

  const listRef = useRef(null);
  useEffect(() => {
    setSub(null);
    if (listRef.current) listRef.current.scrollTop = 0;
  }, [category]);
  useEffect(() => {
    if (listRef.current) listRef.current.scrollTop = 0;
  }, [sub, search]);

  const filtered = useMemo(() => {
    let list = PARTNERS.filter((p) => p.category === category);
    if (sub) list = list.filter((p) => p.sub === sub);
    if (search.trim()) {
      const q = search.trim().toLowerCase();
      list = list.filter((p) =>
      p.name.toLowerCase().includes(q) ||
      (p.address || '').toLowerCase().includes(q) ||
      (p.brand || '').toLowerCase().includes(q) ||
      (p.area || '').toLowerCase().includes(q)
      );
    }
    return list;
  }, [category, sub, search]);

  const subItems = useMemo(() => {
    if (category === 'new-domestic') return DOMESTIC_BRANDS.map((b) => ({ id: b.id, label: b.label }));
    if (category === 'new-imported') return IMPORTED_BRANDS.map((b) => ({ id: b.id, label: b.label }));
    if (category === 'detailing') return DETAILING_SUBS;
    if (category === 'custom') return CUSTOM_SUBS;
    return null;
  }, [category]);

  const grouped = useMemo(() => {
    const groupSpec =
    category === 'new-domestic' ? DOMESTIC_BRANDS :
    category === 'new-imported' ? IMPORTED_BRANDS :
    category === 'detailing' ? DETAILING_SUBS :
    category === 'custom' ? CUSTOM_SUBS : null;

    if (!groupSpec || sub || search.trim()) return null;
    const map = new Map();
    groupSpec.forEach((b) => map.set(b.id, { brand: b, items: [] }));
    filtered.forEach((p) => {
      const g = map.get(p.sub);
      if (g) g.items.push(p);
    });
    return Array.from(map.values()).filter((g) => g.items.length > 0);
  }, [category, sub, search, filtered]);

  const intro = INTROS[category];

  return (
    <div style={{
      display: 'flex', flexDirection: 'column', minHeight: '100vh',
      background: '#fff', fontFamily: FF
    }}>
      {/* 헤더 */}
      <PageHeader title="타운카 제휴 업체" onLeading={onBack} leadingIcon="chevron-left" />

      {/* 카테고리 탭 */}
      <CategoryTabs items={CATEGORIES} active={category} onChange={setCategory} counts={counts} />

      {/* 서브 칩 */}
      {subItems && <SubChips items={subItems} active={sub} onChange={setSub} />}

      {/* 검색바 */}
      <div style={{
        background: '#fff', padding: '10px 16px 6px',
        borderBottom: '0.5px solid ' + TC.lineSoft
      }}>
        <div style={{
          height: 40, padding: '0 12px',
          borderRadius: 10, background: TC.fillSubtle,
          display: 'flex', alignItems: 'center', gap: 8
        }}>
          <Icon name="search" size={18} color={TC.textNeutral} stroke={2} />
          <input
            value={search}
            onChange={(e) => setSearch(e.target.value)}
            placeholder="지점명·지역으로 검색"
            style={{
              all: 'unset', flex: 1, fontSize: 14, fontWeight: 500,
              fontFamily: FF, letterSpacing: '0.015em', color: TC.textStrong, minWidth: 0
            }} />
          
          {search &&
          <button onClick={() => setSearch('')} style={{
            all: 'unset', cursor: 'pointer', display: 'flex',
            width: 18, height: 18, borderRadius: 999, background: TC.fillStrong,
            alignItems: 'center', justifyContent: 'center'
          }}><Icon name="x" size={12} color={TC.text} stroke={2.5} /></button>
          }
        </div>
      </div>

      {/* 결과 카운트 */}
      <div style={{
        padding: '10px 16px 12px', background: '#fff',
        display: 'flex', alignItems: 'center', justifyContent: 'space-between'
      }}>
        <div style={{ fontSize: 13, color: TC.text, letterSpacing: '0.015em', whiteSpace: 'nowrap' }}>
          {sub ?
          <>
              <span style={{ color: TC.textNeutral }}>{[...NEW_BRANDS, ...ETC_SUBS].find((x) => x.id === sub)?.label}</span>
              {' · '}
              <strong style={{ fontWeight: 700, color: TC.textStrong }}>{filtered.length}개 {CATEGORIES.find(c => c.id === category)?.unit || ''}</strong>
            </> :

          <>총 <strong style={{ fontWeight: 700, color: TC.textStrong }}>{filtered.length}개</strong> {CATEGORIES.find(c => c.id === category)?.unit || '제휴 업체'}</>
          }
        </div>
      </div>

      {/* 리스트 영역 */}
      <div ref={listRef} style={{ flex: 1, overflowY: 'auto', WebkitOverflowScrolling: 'touch', background: '#fff' }}>
        {intro && !sub && !search.trim() &&
        <CategoryIntro {...intro} />
        }

        {filtered.length === 0 ?
        <EmptyState
          title={search.trim() ? '검색 결과가 없어요' : '등록된 업체가 없어요'}
          subtitle={search.trim() ? '다른 키워드로 검색해보세요' : '다른 카테고리를 선택해주세요'} /> :

        grouped ?
        grouped.map((g) =>
        <div key={g.brand.label}>
              <GroupHeader label={g.brand.label} count={g.items.length} />
              {g.items.map((p) =>
          <PartnerCard
            key={p.id}
            partner={p}
            brandLabel={null}
            onClick={() => onOpenDetail(p)} />

          )}
            </div>
        ) :

        filtered.map((p) =>
        <PartnerCard
          key={p.id}
          partner={p}
          brandLabel={(category === 'new-domestic' || category === 'new-imported') && !sub ? p.brand : null}
          onClick={() => onOpenDetail(p)} />

        )
        }

        {filtered.length > 0 && <ListFooter />}
      </div>
    </div>);

}

// ── 카테고리 안내
function CategoryIntro({ title, desc, accent, icon }) {
  return (
    <div style={{
      margin: '4px 16px 14px', padding: '14px 16px',
      borderRadius: 14, background: accent,
      display: 'flex', gap: 12, alignItems: 'flex-start',
      fontFamily: FF
    }}>
      <div style={{
        flexShrink: 0, width: 36, height: 36, borderRadius: 10,
        background: '#fff',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        boxShadow: '0 1px 2px rgba(0,0,0,0.04)'
      }}>
        <Icon name={icon} size={19} color={TC.textStrong} stroke={1.9} />
      </div>
      <div style={{ flex: 1, paddingTop: 1 }}>
        <div style={{
          fontSize: 13.5, fontWeight: 700, color: TC.textStrong,
          letterSpacing: '-0.010em', marginBottom: 3
        }}>{title}</div>
        <div style={{
          fontSize: 12.5, color: TC.text, letterSpacing: '0.015em',
          lineHeight: '17px', wordBreak: 'keep-all'
        }}>{desc}</div>
      </div>
    </div>);

}

// ── 그룹 헤더
function GroupHeader({ label, count }) {
  return (
    <div style={{
      position: 'sticky', top: 0, zIndex: 5,
      background: '#fff',
      padding: '12px 16px 8px',
      display: 'flex', alignItems: 'baseline', gap: 6,
      borderBottom: '0.5px solid ' + TC.lineSoft,
      fontFamily: FF
    }}>
      <h3 style={{
        margin: 0, fontSize: 14, fontWeight: 700, color: TC.textStrong,
        letterSpacing: '-0.020em'
      }}>{label}</h3>
      <span style={{
        fontSize: 12, fontWeight: 600, color: TC.primary, letterSpacing: '0.025em'
      }}>{count}곳</span>
    </div>);

}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);

Object.assign(window, {
  App, HomeScreen, CategoryScreen, AdCarousel, AdSlide, CategoryCard, OfficialCard,
  GroupHeader, CategoryIntro, SectionTitle, ListFooter, INTROS, CAT_TONES
});