// 매장 찾기 — 지도 + 리스트 토글, 검색, 매장 상세 프리뷰
// 매장찾기 탭과 예약 흐름의 매장 선택을 하나의 컴포넌트·하나의 데이터로 통일 (booking prop으로 모드 분기)
// 정렬·필터: 거리순/이름순 정렬 · 매장유형 · 예약여부 · 편의시설 · 즐겨찾기 · 영업중 · 무인 운영 (정책 D20)
// 지도: 자유 패닝 + 확대/축소(휠·핀치·버튼) · 매장 상세: 예약 불가 매장도 상세 열람 가능

// 통합 매장 데이터 — 매장찾기 탭·예약 매장 선택·예약 폼이 공유하는 단일 소스.
// hours: [[상품코드, 운영시간]] · machines/amenities/notice/parking/photos: 예약 폼 매장 정보용
const QR_STORES = [
  {id:1,name:"퀀텀 아카데미 판교점",addr:"경기도 성남시 분당구 판교역로 235 (삼평동 6…)",
    hours:[["FA","평일 09:30 - 익일 02:00 · 주말 09:30 - 익일 01:00"]],badges:["coupon"],x:36,y:24,type:"fa",open:true,distM:320,reservable:true,tel:"031-701-0001",
    machines:{FA:12},amenities:["주차가능","좌타석","스윙 플레이트"],notice:"연습 타석 전용 매장입니다. 코치존은 사전 예약제로 운영합니다.",parking:"주차가능 (건물 지하 주차장 2시간 무료)"},
  {id:2,name:"퀀텀 아카데미 판교점",addr:"경기도 성남시 분당구 판교역로 235 (삼평동 6…)",
    hours:[["Q","평일 09:30 - 익일 02:00 · 주말 09:30 - 익일 01:00"],["T2","평일 09:30 - 22:30 · 주말 08:00 - 익일 01:00"]],badges:["coupon"],x:54,y:50,type:"q",open:true,distM:500,reservable:true,tel:"031-701-0002",
    photos:["interior","machine","price"],
    machines:{Q:6,T2:5},amenities:["주차가능","좌타석","스윙 플레이트","9X플레이트"],notice:"2024년 리뉴얼 매장입니다. 최신형 기계와 넓고 깔끔한 시설로 쾌적하게 모시고 있습니다. 대회·모임 단체 예약은 매장으로 문의해 주세요. 주말·공휴일은 예약이 조기 마감될 수 있으니 서둘러 예약해 주세요.",parking:"주차가능 (유스페이스1 지하 주차장 · 이용 시간만큼 무료 등록)"},
  {id:3,name:"판교PDC스포츠센터",addr:"경기도 성남시 분당구 판교역로 235 (삼평동 6…)",
    hours:[["R","평일 09:30 - 익일 02:00 · 주말 09:30 - 익일 01:00"]],badges:["coupon"],x:18,y:40,type:"r",open:false,distM:1200,reservable:false,tel:"031-701-0003",
    machines:{R:4},amenities:["주차가능","스윙 플레이트"],notice:"스포츠센터 내 입점 매장입니다. 센터 회원은 데스크에 문의해 주세요."},
  {id:4,name:"퀀텀 아카데미 강남점",addr:"서울 강남구 테헤란로 152",
    hours:[["Q","평일 09:30 - 익일 02:00 · 주말 09:30 - 익일 01:00"]],badges:["coupon"],x:74,y:22,type:"q",open:true,distM:3800,reservable:true,tel:"02-555-0004",
    photos:["interior","machine"],
    machines:{Q:9},amenities:["좌타석","스윙 플레이트","9X플레이트","매트디스플레이"],notice:"지하 2층 매장으로 엘리베이터를 이용해 주세요.",parking:"주차불가 (인근 공영주차장 이용)"},
  {id:5,name:"퀀텀 아카데미 분당점",addr:"경기 성남시 분당구 정자일로 248",
    hours:[["T2","평일 09:30 - 22:30 · 주말 08:00 - 익일 01:00"]],badges:["coupon"],x:86,y:58,type:"t2",open:true,distM:2400,reservable:true,tel:"031-701-0005",
    photos:["interior","price"],
    machines:{T2:5},amenities:["주차가능","스윙 플레이트"],notice:"2021년 12월 오픈한 신규 매장입니다. 주차장과 같은 층에 위치해 이동이 편리합니다.",parking:"주차가능 (건물 주차장 · 매장 등록 시 3시간 무료)"},
  {id:6,name:"퀀텀 아카데미 용인구성점",addr:"경기도 용인시 수지구 구성로 100",
    hours:[["FA","평일 07:00 - 23:00"]],badges:["un","coupon"],x:12,y:70,type:"fa",open:false,distM:8200,reservable:false,tel:"031-336-0006",
    machines:{FA:10},amenities:["주차가능"],notice:"무인 운영 매장입니다. 입장은 QR 체크인으로 진행해 주세요."},
];
window.QR_STORES = QR_STORES;

const fmtDist = (m)=> m<1000 ? `${m}m` : `${(m/1000).toFixed(1)}km`;
const typeColorOf = (t)=> t==="fa"?"#16A34A" : t==="q"?"#1A1C1F" : t==="t2"?"#F59E0B" : "#3B82F6";

// 매장 상세 풀 페이지 — 예약 가능/불가 무관하게 매장 정보를 열람. 예약 가능하면 하단 CTA로 예약 진입.
function StoreDetailPage({ store, booking=false, isFav=false, onToggleFav, onBack, onReserve, onPick }){
  const [photoIdx, setPhotoIdx] = React.useState(0);
  const [noticeOpen, setNoticeOpen] = React.useState(false);
  const [toast, setToast] = React.useState(null);
  React.useEffect(()=>{ setPhotoIdx(0); setNoticeOpen(false); }, [store && store.id]);
  if (!store) return null;

  const machines = store.machines || {};
  const amenities = store.amenities || [];
  const screenHours = (store.hours || []).map(h=>Array.isArray(h)?h:[String(h).split("/")[0].trim(), String(h)]);
  const distText = store.distM!=null ? fmtDist(store.distM) : null;
  const noticeLong = store.notice && store.notice.length > 45;

  const showToast = (msg)=>{ setToast(msg); window.clearTimeout(showToast._t); showToast._t=window.setTimeout(()=>setToast(null),1800); };
  const copyText = (txt,msg)=>{ const done=()=>showToast(msg); if(navigator.clipboard&&navigator.clipboard.writeText) navigator.clipboard.writeText(txt).then(done,done); else done(); };
  const doReserve = ()=>{ onBack && onBack(); if(booking) onPick && onPick(store); else onReserve && onReserve(store); };

  return (
    <div className="screen" style={{zIndex:100}}>
      <StatusBar/>
      <Appbar title="매장 상세" onBack={onBack}/>
      <div className="scroll" style={{flex:1,minHeight:0,background:"#fff"}}>
          <StoreHero store={store} kicker={store.type ? store.type.toUpperCase() : "Store"} photoIdx={photoIdx} onDot={setPhotoIdx}/>

          {/* 아이덴티티 */}
          <div style={{padding:"16px 20px 8px"}}>
            <div style={{display:"flex",alignItems:"flex-start",justifyContent:"space-between",gap:10}}>
              <div style={{flex:1,minWidth:0}}>
                <div style={{display:"flex",alignItems:"center",gap:6,flexWrap:"wrap"}}>
                  <span style={{fontSize:18,fontWeight:800,letterSpacing:"-.02em",lineHeight:1.3}}>{store.name}</span>
                  {store.badges && store.badges.includes("un") && <span className="store-badge sb-un">무인</span>}
                  {store.badges && store.badges.includes("coupon") && <span className="store-badge sb-coupon">쿠폰</span>}
                </div>
                <div style={{display:"flex",alignItems:"center",gap:6,marginTop:5,fontSize:12,color:"var(--text-sub)",flexWrap:"wrap"}}>
                  <span style={{color:store.open?"var(--primary)":"var(--text-mute)",fontWeight:700}}>● {store.open?"영업중":"영업종료"}</span>
                  {Object.keys(machines).length>0 && (<><span className="sdot"/><span>{Object.entries(machines).map(([c,n])=>`${c==="Q"?"Quantum":c} ${n}대`).join(" · ")}</span></>)}
                  {distText && <><span className="sdot"/><span>{distText}</span></>}
                  <span className="sdot"/>
                  <span style={{fontSize:11,fontWeight:700,padding:"1px 6px",borderRadius:4,background:store.reservable?"var(--primary-tint)":"#FEECEA",color:store.reservable?"var(--primary)":"var(--danger)"}}>{store.reservable?"예약가능":"예약불가"}</span>
                </div>
              </div>
              <button onClick={()=>onToggleFav&&onToggleFav(store.id)} style={{flexShrink:0,width:40,height:40,borderRadius:12,border:"1px solid var(--line)",display:"flex",alignItems:"center",justifyContent:"center",color:isFav?"#F59E0B":"var(--text-mute)",background:isFav?"#FFF7E6":"#fff"}}>
                <Icon name="star" size={18} style={isFav?{fill:"#F59E0B"}:{}}/>
              </button>
            </div>

            {amenities.length>0 && (
              <div style={{display:"flex",gap:6,overflowX:"auto",scrollbarWidth:"none",marginTop:12,paddingBottom:2}}>
                {amenities.map(f=>(<span key={f} style={{flexShrink:0,padding:"5px 10px",borderRadius:6,background:"var(--bg-soft)",fontSize:11,fontWeight:600,color:"var(--text-sub)",whiteSpace:"nowrap"}}>{f}</span>))}
              </div>
            )}
          </div>

          {/* 퀵 액션 */}
          <div style={{padding:"12px 20px 4px",display:"flex",gap:6}}>
            <a href={`tel:${store.tel||"1666-1538"}`} style={{flex:1,padding:"10px 0",borderRadius:8,background:"var(--bg-soft)",display:"flex",flexDirection:"column",alignItems:"center",gap:4,color:"var(--text-sub)",textDecoration:"none"}}>
              <Icon name="phone" size={16}/><span style={{fontSize:11,fontWeight:600,color:"var(--text)"}}>전화</span>
            </a>
            {[["nav","길찾기","지도 앱으로 길을 안내할게요."],["share","공유","매장 링크를 복사했어요."]].map(([ic,lb,msg])=>(
              <button key={lb} onClick={()=>showToast(msg)} style={{flex:1,padding:"10px 0",borderRadius:8,background:"var(--bg-soft)",display:"flex",flexDirection:"column",alignItems:"center",gap:4,color:"var(--text-sub)"}}>
                <Icon name={ic} size={16}/><span style={{fontSize:11,fontWeight:600,color:"var(--text)"}}>{lb}</span>
              </button>
            ))}
          </div>

          {/* 주소 · 영업시간 · 전화 */}
          <div style={{padding:"16px 20px 4px"}}>
            <div style={{padding:14,borderRadius:10,background:"var(--bg-soft)",display:"flex",flexDirection:"column",gap:10}}>
              <div style={{display:"flex",gap:10,alignItems:"flex-start"}}>
                <div style={{width:18,color:"var(--text-mute)",marginTop:1,flexShrink:0}}><Icon name="location" size={16}/></div>
                <div style={{flex:1,fontSize:13,lineHeight:1.5,color:"var(--text)",fontWeight:500}}>
                  {store.addr}
                  <button onClick={()=>copyText(store.addr,"주소가 복사되었습니다.")} style={{marginLeft:6,background:"transparent",color:"var(--primary)",fontSize:12.5,fontWeight:700}}>복사</button>
                </div>
              </div>
              <div style={{height:1,background:"var(--line)"}}/>
              <div style={{display:"flex",gap:10,alignItems:"flex-start"}}>
                <div style={{width:18,color:"var(--text-mute)",marginTop:1,flexShrink:0}}><Icon name="clock" size={16}/></div>
                <div style={{flex:1,display:"flex",flexDirection:"column",gap:4}}>
                  {screenHours.map(([t,h],i)=>(
                    <div key={i} style={{display:"flex",gap:8,alignItems:"baseline",fontSize:12.5,lineHeight:1.6,fontWeight:500}}>
                      <span style={{flexShrink:0,fontWeight:700,color:"var(--text-sub)",width:24}}>{t}</span>
                      <span style={{color:"var(--text)"}}>{h}</span>
                    </div>
                  ))}
                </div>
              </div>
              <div style={{height:1,background:"var(--line)"}}/>
              <div style={{display:"flex",gap:10,alignItems:"center"}}>
                <div style={{width:18,color:"var(--text-mute)",flexShrink:0}}><Icon name="phone" size={16}/></div>
                <div style={{fontSize:13,color:"var(--text)",fontWeight:500,fontVariantNumeric:"tabular-nums"}}>
                  {store.tel||"1666-1538"}
                  <button onClick={()=>copyText(store.tel||"1666-1538","전화번호가 복사되었습니다.")} style={{marginLeft:6,background:"transparent",color:"var(--primary)",fontSize:12.5,fontWeight:700}}>복사</button>
                </div>
              </div>
            </div>

            {(store.notice || store.parking) && (
              <div style={{marginTop:10,padding:"12px 14px",borderRadius:10,background:"var(--bg-soft)"}}>
                {store.notice && (
                  <>
                    <div style={{fontSize:12,fontWeight:800,color:"var(--text)",marginBottom:4}}>매장 공지</div>
                    <div style={{fontSize:12.5,color:"var(--text-sub)",lineHeight:1.55,
                      ...(noticeLong && !noticeOpen ? {display:"-webkit-box",WebkitLineClamp:2,WebkitBoxOrient:"vertical",overflow:"hidden"} : {})}}>{store.notice}</div>
                    {noticeLong && (
                      <button onClick={()=>setNoticeOpen(v=>!v)} style={{marginTop:4,display:"inline-flex",alignItems:"center",gap:2,background:"transparent",color:"var(--text-sub)",fontSize:12,fontWeight:700}}>
                        {noticeOpen?"접기":"더보기"}<Icon name={noticeOpen?"chev-u":"chev-d"} size={12}/>
                      </button>
                    )}
                  </>
                )}
                {store.notice && store.parking && <div style={{height:1,background:"var(--line)",margin:"10px 0"}}/>}
                {store.parking && (
                  <>
                    <div style={{fontSize:12,fontWeight:800,color:"var(--text)",marginBottom:4}}>주차 안내</div>
                    <div style={{fontSize:12.5,color:"var(--text-sub)",lineHeight:1.55}}>{store.parking}</div>
                  </>
                )}
              </div>
            )}
            <div style={{height:16}}/>
          </div>
        </div>

        {/* 하단 CTA — 예약 가능하면 예약 진입 / 불가하면 안내 + 전화 문의 */}
        <div style={{flexShrink:0,padding:"12px 20px 22px",background:"#fff",borderTop:"1px solid var(--line)"}}>
          {store.reservable ? (
            <button className="btn btn-primary" style={{width:"100%"}} onClick={doReserve}>
              {booking ? "이 매장으로 예약" : "예약하기"}
            </button>
          ) : (
            <div style={{display:"flex",flexDirection:"column",gap:8}}>
              <div style={{fontSize:12,color:"var(--text-sub)",textAlign:"center",lineHeight:1.5}}>
                현재 앱 예약이 지원되지 않는 매장이에요. 이용은 매장으로 문의해 주세요.
              </div>
              <div style={{display:"flex",gap:8}}>
                <button className="btn btn-disabled" style={{flex:1}}>예약 불가</button>
                <a href={`tel:${store.tel||"1666-1538"}`} className="btn btn-outline" style={{flex:1,textDecoration:"none"}}>
                  <Icon name="phone" size={16}/> 전화 문의
                </a>
              </div>
            </div>
          )}
        </div>

        {toast && <div className="toast"><span>{toast}</span></div>}
      </div>
  );
}
window.StoreDetailPage = StoreDetailPage;

// booking=true 예약 흐름의 매장 선택(하단 탭바 없음, 예약 버튼 → onPick) / false 매장찾기 탭(탭바, 예약 → onReserve)
function StoreScreen({ onNav, onReserve, booking=false, onPick, onBack }){
  const [mode, setMode] = React.useState("map");
  const [search, setSearch] = React.useState(false);

  // 정렬·필터 상태 (D20)
  const [sort, setSort] = React.useState("dist");    // dist | name
  const [typeF, setTypeF] = React.useState("all");   // all | 매장유형 코드
  const [availF, setAvailF] = React.useState("all"); // all | y | n
  const [amenF, setAmenF] = React.useState([]);      // 편의시설 다중 선택
  const [favOnly, setFavOnly] = React.useState(false); // 즐겨찾는 매장만
  const [openF, setOpenF] = React.useState(false);   // 영업중만
  const [unF, setUnF] = React.useState(false);       // 무인 운영만
  const [drop, setDrop] = React.useState(null);      // 'sort' | 'type' | 'avail' | 'amen' | null

  // 즐겨찾기 (데모 시드) · 상세 시트 대상
  const [favs, setFavs] = React.useState([2,5]);
  const [detail, setDetail] = React.useState(null);  // 상세 열람 중인 매장 (예약 불가 포함)
  const toggleFav = (id)=> setFavs(f => f.includes(id) ? f.filter(x=>x!==id) : [...f, id]);

  const stores = QR_STORES;

  const typeLabel = (t)=> (t||"").toUpperCase();

  // 옵션 — 데이터에 존재하는 값만
  const typeOpts = React.useMemo(()=> ["all", ...Array.from(new Set(stores.map(s=>s.type)))], []);
  const amenityOpts = React.useMemo(()=> Array.from(new Set(stores.flatMap(s=>s.amenities||[]))), []);

  // 필터 + 정렬 적용 (지도 핀 · 리스트 공통)
  const shown = React.useMemo(()=>{
    const arr = stores.filter(s =>
      (typeF==="all" || s.type===typeF) &&
      (availF==="all" || (availF==="y" ? s.reservable : !s.reservable)) &&
      (amenF.length===0 || amenF.every(a => (s.amenities||[]).includes(a))) &&
      (!favOnly || favs.includes(s.id)) &&
      (!openF || s.open) &&
      (!unF || (s.badges||[]).includes("un"))
    );
    return arr.sort((a,b)=> sort==="dist" ? a.distM-b.distM : a.name.localeCompare(b.name,"ko"));
  }, [typeF, availF, amenF, favOnly, openF, unF, favs, sort]);

  const [selIdx, setSelIdx] = React.useState(0);
  React.useEffect(()=>{ setSelIdx(0); }, [typeF, availF, amenF, favOnly, openF, unF, sort]);
  const selected = shown.length ? (shown[selIdx] || shown[0]) : null;

  // 지도 자유 이동/확대 — view: {x,y(px 이동), k(배율)}
  const [view, setView] = React.useState({x:0,y:0,k:1});
  const viewRef = React.useRef(view);
  React.useEffect(()=>{ viewRef.current = view; }, [view]);
  const clampK = (k)=> Math.min(3, Math.max(0.6, k));
  const ptrs = React.useRef(new Map());   // 활성 포인터
  const panRef = React.useRef(null);      // {sx,sy,ox,oy}
  const pinchRef = React.useRef(null);    // {dist,k}
  const mapWrapRef = React.useRef(null);  // 지도 컨테이너(중앙 이동 계산용)

  const onMapDown = (e)=>{
    ptrs.current.set(e.pointerId, {x:e.clientX, y:e.clientY});
    try{ e.currentTarget.setPointerCapture(e.pointerId); }catch(_){}
    if (ptrs.current.size === 1){
      panRef.current = {sx:e.clientX, sy:e.clientY, ox:viewRef.current.x, oy:viewRef.current.y};
    } else if (ptrs.current.size === 2){
      const [a,b] = [...ptrs.current.values()];
      pinchRef.current = {dist:Math.hypot(a.x-b.x, a.y-b.y), k:viewRef.current.k};
      panRef.current = null;
    }
  };
  const onMapMove = (e)=>{
    if (!ptrs.current.has(e.pointerId)) return;
    ptrs.current.set(e.pointerId, {x:e.clientX, y:e.clientY});
    if (ptrs.current.size >= 2 && pinchRef.current){
      const [a,b] = [...ptrs.current.values()];
      const d = Math.hypot(a.x-b.x, a.y-b.y);
      setView(v => ({...v, k: clampK(pinchRef.current.k * d / (pinchRef.current.dist||1))}));
    } else if (panRef.current){
      const p = panRef.current;
      setView(v => ({...v, x: p.ox + (e.clientX - p.sx), y: p.oy + (e.clientY - p.sy)}));
    }
  };
  const onMapUp = (e)=>{
    ptrs.current.delete(e.pointerId);
    try{ e.currentTarget.releasePointerCapture(e.pointerId); }catch(_){}
    if (ptrs.current.size === 1){
      const p = [...ptrs.current.values()][0];
      panRef.current = {sx:p.x, sy:p.y, ox:viewRef.current.x, oy:viewRef.current.y};
      pinchRef.current = null;
    } else if (ptrs.current.size === 0){
      panRef.current = null; pinchRef.current = null;
    }
  };
  const onMapWheel = (e)=>{ setView(v => ({...v, k: clampK(v.k * (e.deltaY<0 ? 1.12 : 0.9))})); };
  const zoomBy = (f)=> setView(v => ({...v, k: clampK(v.k*f)}));
  const resetView = ()=> setView({x:0,y:0,k:1});
  // 목록/핀 선택 → 해당 매장을 지도 중앙(가시영역)으로 이동 + 강조 (자유 패닝과 공존)
  const focusStore = (i)=>{
    setSelIdx(i);
    const el = mapWrapRef.current, s = shown[i];
    if (!el || !s) return;
    const W = el.clientWidth, H = el.clientHeight, k = viewRef.current.k;
    setView(v => ({...v, x: -k*((s.x/100)*W - W/2), y: -H*0.1 - k*((s.y/100)*H - H/2)}));
  };

  // 하단 바텀시트 — peek(대표 1곳) ↔ 전체 목록
  const [sheetExpanded, setSheetExpanded] = React.useState(false);
  const sheetDragY = React.useRef(null);
  const onSheetDown = (e)=>{ sheetDragY.current = e.clientY; };
  const onSheetUp = (e)=>{ if(sheetDragY.current==null) return; const dy = e.clientY - sheetDragY.current; sheetDragY.current=null; if(dy < -30) setSheetExpanded(true); else if(dy > 30) setSheetExpanded(false); };
  const selRowRef = React.useRef(null);
  React.useEffect(()=>{ if(mode==="map" && selRowRef.current) { try{ selRowRef.current.scrollIntoView({behavior:"smooth", block:"nearest"}); }catch(e){} } }, [selIdx, mode]);

  // 드롭다운/토글 칩
  const sortText  = sort==="dist" ? "거리순" : "이름순";
  const typeText  = typeF==="all" ? "매장유형" : typeLabel(typeF);
  const availText = availF==="all" ? "예약여부" : (availF==="y" ? "예약가능" : "예약불가");
  const amenText  = amenF.length ? `편의시설 ${amenF.length}` : "편의시설";
  const dropChips = [
    ["sort",  sortText,  sort!=="dist"],
    ["type",  typeText,  typeF!=="all"],
    ["avail", availText, availF!=="all"],
    ["amen",  amenText,  amenF.length>0],
  ];
  const toggleChips = [
    ["fav", "즐겨찾기",  favOnly, ()=>setFavOnly(v=>!v), "star"],
    ["open","영업중",    openF,   ()=>setOpenF(v=>!v),   null],
    ["un",  "무인 운영", unF,     ()=>setUnF(v=>!v),     null],
  ];
  const dropItems = drop==="sort"  ? [["dist","거리순"],["name","이름순"]]
                  : drop==="type"  ? typeOpts.map(t=>[t, t==="all"?"전체":typeLabel(t)])
                  : drop==="avail" ? [["all","전체"],["y","예약가능"],["n","예약불가"]]
                  : drop==="amen"  ? amenityOpts.map(a=>[a,a])
                  : [];
  const dropCurrent = drop==="sort" ? sort : drop==="type" ? typeF : drop==="avail" ? availF : null;
  const isChecked = (val)=> drop==="amen" ? amenF.includes(val) : dropCurrent===val;
  const applyDrop = (val)=>{
    if (drop==="amen"){ setAmenF(a => a.includes(val) ? a.filter(x=>x!==val) : [...a, val]); return; } // 다중 — 열어둔 채 토글
    if (drop==="sort") setSort(val); else if (drop==="type") setTypeF(val); else if (drop==="avail") setAvailF(val);
    setDrop(null);
  };

  return (
    <>
    <div className="screen">
      <StatusBar/>
      {search ? (
        <Appbar title="판교" onBack={()=>setSearch(false)}
          right={<button className="icon-btn"><Icon name="x" size={18}/></button>}/>
      ) : (
        <Appbar title="매장 선택" onBack={booking ? onBack : ()=>onNav("home")}
          right={<button className="icon-btn" onClick={()=>setSearch(true)}><Icon name="search" size={20}/></button>}/>
      )}

      <div style={{flex:1,position:"relative",overflow:"hidden"}}>
        {/* 드롭다운 바깥 클릭 시 닫기 */}
        {drop && <div onClick={()=>setDrop(null)} style={{position:"absolute",inset:0,zIndex:19}}/>}

        {/* 상단 컨트롤: 지도/리스트 토글 + 정렬·필터칩 (좌우 스와이프로 더 보기) */}
        <div style={{position:"absolute",top:12,left:12,right:12,zIndex:20}}>
          <div style={{display:"flex",alignItems:"center",gap:8}}>
            <div style={{display:"flex",background:"#fff",borderRadius:999,boxShadow:"0 2px 8px rgba(0,0,0,.12)",overflow:"hidden",border:"1px solid var(--line)",flexShrink:0}}>
              <button onClick={()=>setMode("map")} style={{padding:"8px 12px",background:mode==="map"?"var(--primary)":"#fff",color:mode==="map"?"#fff":"var(--text-sub)",fontWeight:700,fontSize:13,display:"flex",alignItems:"center"}}>
                <Icon name="map" size={16}/>
              </button>
              <button onClick={()=>setMode("list")} style={{padding:"8px 12px",background:mode==="list"?"var(--primary)":"#fff",color:mode==="list"?"#fff":"var(--text-sub)",fontWeight:700,fontSize:13,display:"flex",alignItems:"center"}}>
                <Icon name="list" size={16}/>
              </button>
            </div>
            <div style={{display:"flex",gap:6,overflowX:"auto",scrollbarWidth:"none",WebkitOverflowScrolling:"touch",flex:1,minWidth:0}}>
              {dropChips.map(([k,label,on])=>(
                <button key={k} onClick={()=>setDrop(drop===k?null:k)} className={"fchip " + ((on||drop===k)?"on":"")} style={{height:34,fontSize:12,flex:"0 0 auto"}}>
                  {label} <Icon name={drop===k?"chev-u":"chev-d"}/>
                </button>
              ))}
              {toggleChips.map(([k,label,on,fn,ic])=>(
                <button key={k} onClick={fn} className={"fchip " + (on?"on":"")} style={{height:34,fontSize:12,flex:"0 0 auto"}}>
                  {ic && <Icon name={ic} size={13} style={on?{fill:"#fff"}:{}}/>} {label}
                </button>
              ))}
            </div>
          </div>

          {/* 드롭다운 패널 (amen 은 다중 선택) */}
          {drop && dropItems.length>0 && (
            <div style={{marginTop:8,background:"#fff",borderRadius:12,border:"1px solid var(--line)",boxShadow:"0 6px 20px rgba(0,0,0,.14)",overflow:"hidden",width:200,maxHeight:260,overflowY:"auto",scrollbarWidth:"none"}}>
              {drop==="amen" && (
                <div style={{padding:"9px 14px 7px",fontSize:11,color:"var(--text-mute)",fontWeight:600,borderBottom:"1px solid var(--line)"}}>선택한 편의시설을 모두 갖춘 매장</div>
              )}
              {dropItems.map(([val,lab])=>{
                const cur = isChecked(val);
                return (
                  <button key={val} onClick={()=>applyDrop(val)} style={{display:"flex",alignItems:"center",justifyContent:"space-between",width:"100%",padding:"11px 14px",background:cur?"var(--primary-tint)":"#fff",border:"none",borderBottom:"1px solid var(--line)",textAlign:"left"}}>
                    <span style={{fontSize:13,fontWeight:cur?700:500,color:cur?"var(--primary)":"var(--text)"}}>{lab}</span>
                    {cur && <Icon name="check" size={15} style={{color:"var(--primary)"}}/>}
                  </button>
                );
              })}
              {drop==="amen" && amenF.length>0 && (
                <button onClick={()=>setAmenF([])} style={{width:"100%",padding:"10px 14px",background:"#fff",textAlign:"center",fontSize:12.5,fontWeight:700,color:"var(--text-sub)"}}>모두 해제</button>
              )}
            </div>
          )}
        </div>

        {mode==="map" ? (
          <>
            {/* 지도 — 드래그로 자유 이동, 휠·핀치·버튼으로 확대/축소 */}
            <div ref={mapWrapRef} onPointerDown={onMapDown} onPointerMove={onMapMove} onPointerUp={onMapUp} onPointerCancel={onMapUp} onWheel={onMapWheel}
              style={{position:"absolute",inset:0,overflow:"hidden",touchAction:"none",cursor:"grab"}}>
              <div style={{position:"absolute",inset:0,transform:`translate(${view.x}px, ${view.y}px) scale(${view.k})`,transformOrigin:"center center",willChange:"transform"}}>
                {/* 텍스처 배경 (확장 — 패닝 시 빈 영역 방지) */}
                <div className="map-bg" style={{position:"absolute",inset:"-120%"}}>
                  <div style={{position:"absolute",top:"40%",left:0,right:0,height:6,background:"#FECACA",opacity:.6,transform:"rotate(-4deg)"}}/>
                  <div style={{position:"absolute",top:"30%",left:"36%",right:"34%",bottom:"30%",background:"rgba(134,239,172,.25)",borderRadius:40}}/>
                </div>

                {/* 동네 라벨 */}
                {[
                  ["정자역","22%","14%"],["성남신기","40%","10%"],["상록마을1,2단지","24%","30%"],
                  ["정든마을한진","44%","50%"],["계원예술고등학교","58%","62%"],["한솔고등학교","56%","14%"],
                  ["탄천초등학교","32%","48%"],["불정초등학교","58%","38%"],
                ].map(([n,l,t],i)=>(
                  <div key={i} style={{position:"absolute",left:l,top:t,fontSize:9,color:"#475569",fontWeight:500,pointerEvents:"none",whiteSpace:"nowrap"}}>{n}</div>
                ))}

                {/* 핀 — 필터/정렬 결과만. 핀에서 시작한 포인터는 패닝을 막고 선택만 */}
                {shown.map((s,i)=>{
                  const on = selIdx===i;
                  return (
                    <button key={s.id} onPointerDown={e=>e.stopPropagation()} onClick={()=>focusStore(i)} style={{position:"absolute",left:`${s.x}%`,top:`${s.y}%`,transform:"translate(-50%,-100%)",background:"none",zIndex:on?5:1}}>
                      <div className="pin" style={{background: s.reservable ? typeColorOf(s.type) : "#9CA3AF",transform:on?"scale(1.25)":"scale(1)",transition:"transform .2s",boxShadow:on?"0 6px 14px rgba(0,0,0,.3)":"0 4px 10px rgba(34,187,95,.3)",opacity:s.reservable?1:.7}}>
                        <span style={{fontSize:10,fontWeight:800}}>{s.type.toUpperCase()}</span>
                      </div>
                    </button>
                  );
                })}

                {/* 내 위치 */}
                <div style={{position:"absolute",left:"50%",top:"52%",transform:"translate(-50%,-50%)",pointerEvents:"none"}}>
                  <div style={{width:20,height:20,borderRadius:"50%",background:"rgba(239,68,68,.25)",display:"flex",alignItems:"center",justifyContent:"center"}}>
                    <div style={{width:10,height:10,borderRadius:"50%",background:"#EF4444",border:"2px solid #fff"}}/>
                  </div>
                </div>
              </div>
            </div>

            {/* 지도 컨트롤 — 확대/축소 · 현위치 초기화 */}
            <div style={{position:"absolute",right:12,top:64,zIndex:15,display:"flex",flexDirection:"column",gap:8}}>
              <div style={{background:"#fff",borderRadius:10,boxShadow:"0 2px 8px rgba(0,0,0,.14)",border:"1px solid var(--line)",overflow:"hidden"}}>
                <button onClick={()=>zoomBy(1.25)} style={{width:38,height:38,display:"flex",alignItems:"center",justifyContent:"center",color:"var(--text)",borderBottom:"1px solid var(--line)"}}><Icon name="plus" size={18}/></button>
                <button onClick={()=>zoomBy(0.8)} style={{width:38,height:38,display:"flex",alignItems:"center",justifyContent:"center",color:"var(--text)"}}><Icon name="menu" size={18} style={{transform:"scaleY(.25)"}}/></button>
              </div>
              <button onClick={resetView} style={{width:38,height:38,borderRadius:10,background:"#fff",boxShadow:"0 2px 8px rgba(0,0,0,.14)",border:"1px solid var(--line)",display:"flex",alignItems:"center",justifyContent:"center",color:"var(--primary)"}}><Icon name="target" size={18}/></button>
            </div>

            {/* 하단 매장 목록 바텀시트 — peek(대표 1곳) ↔ 전체 목록 (행 탭 → 지도에 표시, [상세] 버튼 → 상세 페이지) */}
            <div style={{position:"absolute",left:0,right:0,bottom:0,top: sheetExpanded ? "14%" : "56%",
              background:"#fff",borderRadius:"18px 18px 0 0",boxShadow:"0 -6px 22px rgba(0,0,0,.14)",zIndex:30,
              display:"flex",flexDirection:"column",transition:"top .3s cubic-bezier(.2,.8,.2,1)",overflow:"hidden"}}>
              <div onPointerDown={onSheetDown} onPointerUp={onSheetUp} onClick={()=>setSheetExpanded(v=>!v)}
                style={{padding:"9px 0 6px",display:"flex",justifyContent:"center",touchAction:"none",cursor:"grab",flexShrink:0}}>
                <div style={{width:38,height:4,borderRadius:99,background:"var(--line-strong)"}}/>
              </div>
              <div style={{padding:"0 18px 8px",display:"flex",alignItems:"center",justifyContent:"space-between",flexShrink:0}}>
                <span style={{fontSize:13.5,fontWeight:800}}>매장 <span style={{color:"var(--primary)"}}>{shown.length}</span>곳</span>
                <span style={{fontSize:11,color:"var(--text-mute)"}}>{sheetExpanded ? "매장을 눌러 상세 보기" : "위로 올려 전체 보기"}</span>
              </div>

              {shown.length===0 ? (
                <div style={{flex:1,display:"flex",alignItems:"center",justifyContent:"center",fontSize:13,color:"var(--text-mute)"}}>조건에 맞는 매장이 없어요.</div>
              ) : (
                <div className="scroll" style={{flex:1,minHeight:0}}>
                  {shown.map((s,i)=>{
                    const on = selIdx===i;
                    const isFav = favs.includes(s.id);
                    return (
                      <div key={s.id} ref={on?selRowRef:null} onClick={()=>focusStore(i)}
                        style={{display:"flex",gap:10,alignItems:"flex-start",padding:"13px 18px",borderBottom:"1px solid var(--line)",background:on?"var(--primary-tint)":"#fff",cursor:"pointer"}}>
                        <div style={{flex:1,minWidth:0}}>
                          <div style={{display:"flex",alignItems:"center",gap:6,marginBottom:4}}>
                            <span style={{fontSize:15,fontWeight:800,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}}>{s.name}</span>
                            {s.badges.includes("un") && <span className="store-badge sb-un">무인</span>}
                            {s.badges.includes("coupon") && <span className="store-badge sb-coupon">쿠폰</span>}
                          </div>
                          <div style={{fontSize:12,color:"var(--text-sub)",display:"flex",alignItems:"center",gap:6,marginBottom:6,flexWrap:"wrap"}}>
                            <span style={{color:s.open?"var(--primary)":"var(--text-mute)",fontWeight:700}}>{s.open?"영업중":"영업종료"}</span>
                            <span className="sdot"/><span style={{fontWeight:700}}>{fmtDist(s.distM)}</span>
                            <span style={{fontSize:10,fontWeight:700,padding:"1px 6px",borderRadius:4,background:s.reservable?"var(--primary-tint)":"#FEECEA",color:s.reservable?"var(--primary)":"var(--danger)"}}>{s.reservable?"예약가능":"예약불가"}</span>
                          </div>
                          <div style={{display:"flex",alignItems:"center",gap:5,flexWrap:"wrap"}}>
                            {s.hours.map((h,hi)=>{ const [t]=Array.isArray(h)?h:h.split(" / "); return <span key={hi} className={"store-badge sb-"+String(t).toLowerCase()}>{t}</span>; })}
                            <span style={{fontSize:11,color:"var(--text-mute)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}}>{Array.isArray(s.hours[0])?s.hours[0][1]:s.hours[0]}</span>
                          </div>
                        </div>
                        <div style={{display:"flex",flexDirection:"column",gap:6,alignItems:"center",flexShrink:0}}>
                          <button onClick={e=>{ e.stopPropagation(); toggleFav(s.id); }} style={{width:34,height:34,borderRadius:9,border:"1px solid var(--line)",display:"flex",alignItems:"center",justifyContent:"center",color:isFav?"#F59E0B":"var(--text-mute)",background:isFav?"#FFF7E6":"#fff"}}><Icon name="star" size={15} style={isFav?{fill:"#F59E0B"}:{}}/></button>
                          <button onClick={e=>{ e.stopPropagation(); if(s.reservable){ booking ? (onPick && onPick(s)) : (onReserve && onReserve(s)); } else setDetail(s); }} style={{fontSize:11.5,fontWeight:700,color:s.reservable?"var(--primary)":"var(--text-sub)",display:"flex",alignItems:"center",background:"transparent"}}>
                            {s.reservable ? "선택" : "상세"}<Icon name="chev-r" size={12}/>
                          </button>
                        </div>
                      </div>
                    );
                  })}
                </div>
              )}
            </div>
          </>
        ) : (
          <div className="scroll" style={{position:"absolute",inset:0,paddingTop:60,background:"#fff"}}>
            {shown.map((s,i)=>{
              const isFav = favs.includes(s.id);
              return (
              <div key={s.id} onClick={()=>{ setSelIdx(i); if(s.reservable){ booking ? (onPick && onPick(s)) : (onReserve && onReserve(s)); } else setDetail(s); }} style={{display:"flex",gap:10,alignItems:"flex-start",width:"100%",textAlign:"left",padding:"14px 20px",borderBottom:"1px solid var(--line)",background:"transparent",cursor:"pointer"}}>
                <div style={{flex:1,minWidth:0}}>
                  <div style={{display:"flex",alignItems:"center",gap:8,marginBottom:6}}>
                    <div style={{fontSize:15,fontWeight:800}}>{s.name}</div>
                    {s.badges.includes("un") && <span className="store-badge sb-un">무인</span>}
                    {s.badges.includes("coupon") && <span className="store-badge sb-coupon">쿠폰</span>}
                  </div>
                  <div style={{fontSize:12,color:"var(--text-sub)",marginBottom:4}}>
                    <span style={{color:s.open?"var(--primary)":"var(--text-mute)",fontWeight:700}}>{s.open?"영업중":"영업종료"}</span>
                    <span className="sdot"/>
                    <span style={{fontWeight:700}}>{fmtDist(s.distM)}</span>
                    <span className="sdot"/>
                    <span style={{fontSize:10,fontWeight:700,padding:"1px 6px",borderRadius:4,background:s.reservable?"var(--primary-tint)":"#FEECEA",color:s.reservable?"var(--primary)":"var(--danger)"}}>{s.reservable?"예약가능":"예약불가"}</span>
                    <div style={{marginTop:3}}>{s.addr}</div>
                  </div>
                  {s.hours.map((h,hi)=>{
                    const [t, txt] = Array.isArray(h) ? h : (()=>{ const [a,...b]=h.split(" / "); return [a, b.join(" / ")]; })();
                    return (
                      <div key={hi} style={{display:"flex",alignItems:"center",gap:6,margin:"3px 0"}}>
                        <span className={"store-badge sb-"+String(t).toLowerCase()}>{t}</span>
                        <span style={{fontSize:11.5,color:"var(--text-sub)"}}>{txt}</span>
                      </div>
                    );
                  })}
                </div>
                <button onClick={e=>{ e.stopPropagation(); toggleFav(s.id); }} style={{flexShrink:0,width:34,height:34,borderRadius:9,border:"1px solid var(--line)",display:"flex",alignItems:"center",justifyContent:"center",color:isFav?"#F59E0B":"var(--text-mute)",background:isFav?"#FFF7E6":"#fff"}}><Icon name="star" size={15} style={isFav?{fill:"#F59E0B"}:{}}/></button>
              </div>
              );
            })}
            {shown.length===0 && (
              <div style={{padding:"60px 20px",textAlign:"center",fontSize:13,color:"var(--text-mute)"}}>조건에 맞는 매장이 없어요.</div>
            )}
          </div>
        )}

      </div>

      {!booking && <TabBar current="store" onNav={onNav}/>}
    </div>
    {/* 매장 상세 — 풀 페이지 (예약 불가 매장도 열람) */}
    {detail && (
      <StoreDetailPage store={detail} booking={booking} isFav={favs.includes(detail.id)} onToggleFav={toggleFav}
        onBack={()=>setDetail(null)} onReserve={onReserve} onPick={onPick}/>
    )}
    </>
  );
}

window.StoreScreen = StoreScreen;
