// 통합예약 (Unified Booking) — type select → store select → booking form → confirm → edit info

function BookingTypeSelect({ onBack, onNext, selected, setSelected }){
  const types = [
    {id:"screen",label:"스크린"},
    {id:"training",label:"트레이닝"},
    {id:"lesson",label:"레슨"},
    {id:"field",label:"필드예약"},
  ];
  return (
    <div className="screen">
      <StatusBar/>
      <Appbar title="통합 예약하기" onBack={onBack}/>
      <div className="scroll" style={{padding:"8px 20px 100px"}}>
        <div style={{fontSize:20,fontWeight:800,letterSpacing:"-.02em",lineHeight:1.4,margin:"8px 0 28px"}}>
          원하는 매장 타입을<br/>선택해 주세요.
        </div>
        <div style={{display:"flex",flexDirection:"column",gap:10}}>
          {types.map(t=>(
            <button key={t.id} onClick={()=>setSelected(t.id)} style={{
              height:60,borderRadius:10,fontSize:15,fontWeight:700,
              background: selected===t.id ? "#fff" : "var(--bg-soft)",
              color: selected===t.id ? "var(--primary)" : "var(--text-mute)",
              border: selected===t.id ? "1.5px solid var(--primary)" : "1.5px solid transparent",
            }}>{t.label}</button>
          ))}
        </div>
      </div>
      <div style={{position:"absolute",bottom:0,left:0,right:0,padding:"12px 20px 24px",background:"#fff"}}>
        <button className={"btn " + (selected?"btn-primary":"btn-disabled")} style={{width:"100%"}} onClick={selected?onNext:null}>다음</button>
      </div>
    </div>
  );
}

function BookingForm({ onBack, onClose, onNext, store, setForm, reserver, onEditUser, onChangeStore, todayCount=0, limit=2, onCycleLimit }){
  const limitReached = todayCount >= limit;
  const [product, setProduct] = React.useState("Q");
  const [date, setDate] = React.useState(0);
  const [payMethod, setPayMethod] = React.useState("app");
  // 반복 노쇼(누적 3회) 선결제 전환 — 사전 결제 강제 (정책 §7) · 데모 토글
  const [prepayRequired, setPrepayRequired] = React.useState(false);
  const [holes, setHoles] = React.useState("18");
  const [people, setPeople] = React.useState(2); // 디폴트 2명
  const [req, setReq] = React.useState(["t3","left","fourball"]);
  const [note, setNote] = React.useState("");
  const [toast, setToast] = React.useState(null);
  // 시작 시간 — 시·분 휠 시트로 변경. 종료 = 시작 + 인원 × (18홀 60분 / 9홀 30분)
  const [startT, setStartT] = React.useState("13:00");
  const [timeOpen, setTimeOpen] = React.useState(false);
  const [photoIdx, setPhotoIdx] = React.useState(0); // 매장 사진 (등록 이미지 스와이프)
  const [noticeOpen, setNoticeOpen] = React.useState(false); // 매장 공지 더보기

  const showToast = (msg)=>{
    setToast(msg);
    window.clearTimeout(showToast._t);
    showToast._t = window.setTimeout(()=>setToast(null), 2000);
  };
  const copyText = (txt, msg)=>{
    const done = ()=>showToast(msg);
    if (navigator.clipboard && navigator.clipboard.writeText) navigator.clipboard.writeText(txt).then(done, done);
    else done();
  };

  // Derive available products from store.hours (e.g. [["Q",...],["T2",...]])
  const availableProducts = React.useMemo(()=>{
    if (!store?.hours) return ["Q","T2"];
    const codes = store.hours.map(h => Array.isArray(h) ? h[0] : String(h).split("/")[0].trim());
    const screen = codes.filter(c => c==="Q" || c==="T2");
    // 스크린 예약은 모든 매장이 Q/T2 중 최소 하나는 보유 — 데이터에 없으면 둘 다 가능으로 폴백 (둘 다 비활성 방지)
    return screen.length ? screen : ["Q","T2"];
  }, [store]);

  // 가용 제품에 맞춰 보정 — 현재 선택이 불가하면 첫 가용 제품으로
  React.useEffect(()=>{
    setProduct(prev => availableProducts.includes(prev) ? prev : (availableProducts[0] || prev));
  }, [availableProducts]);

  const productLabel = (p)=> p==="Q" ? "Quantum" : p==="T2" ? "T2" : p;

  // 단일 선택 — Q/T2 중 하나만
  const onPickProduct = (p)=>{
    if (!availableProducts.includes(p)) {
      setToast(`해당 매장은 ${productLabel(p)} 예약이 불가합니다.`);
      window.clearTimeout(onPickProduct._t);
      onPickProduct._t = window.setTimeout(()=>setToast(null), 2200);
      return;
    }
    setProduct(p);
  };

  // 예약 가능 기간: 당일 ~ 14일 후 (정책 §1)
  const WD = ["일","월","화","수","목","금","토"];
  const today = new Date();
  const days14 = Array.from({length:14},(_,i)=>{ const d=new Date(today); d.setDate(today.getDate()+i); return d; });
  const reqs = [
    {id:"t3",label:"T3 신규 제품"},
    {id:"left",label:"좌타방"},
    {id:"2game",label:"2게임 예약"},
    {id:"joined",label:"연결된 방"},
    {id:"fourball",label:"포섬"},
    {id:"4ball",label:"포볼"},
    {id:"etc",label:"기타 (직접입력)"},
  ];

  const toggle = (id)=> setReq(r => r.includes(id) ? r.filter(x=>x!==id) : [...r, id]);

  // 티타임 계산 — 18홀 60분/인 · 9홀 30분/인 (인원 0명이면 1명 기준 표시)
  const perMin = holes === "18" ? 60 : 30;
  const calcPeople = Math.max(1, people);
  const startMin = (()=>{ const m = String(startT).match(/(\d{1,2}):(\d{2})/); return m ? (+m[1])*60 + (+m[2]) : 780; })();
  const endMinTotal = startMin + calcPeople * perMin;
  const endT = `${endMinTotal >= 1440 ? "익일 " : ""}${String(Math.floor(endMinTotal/60)%24).padStart(2,"0")}:${String(endMinTotal%60).padStart(2,"0")}`;

  // 매장 정보 표시 값 (선택 매장 데이터 · 없으면 데모 폴백)
  const storeAddr = store?.addr || "경기 성남시 분당구 판교역로 235 (삼평동) 유스페이스1 지하 1층";
  const storeTel = store?.tel || "031-701-0002";
  const storeMachines = store?.machines || {Q:6, T2:5};
  const storeAmenities = store?.amenities || ["주차가능","좌타석","스윙 플레이트","9X플레이트"];
  // 매장 공지·주차 안내 — 미등록 시 해당 영역 숨김 (폴백 없음)
  const storeNotice = store?.notice || null;
  const storeParking = store?.parking || null;
  const screenHours = (store?.hours || [["Q","평일 09:30 - 익일 02:00 · 주말 09:30 - 익일 01:00"]]).filter(h=>Array.isArray(h));
  const distText = store?.distM != null ? (store.distM >= 1000 ? (store.distM/1000).toFixed(1)+"km" : store.distM+"m") : null;

  // 결제 금액 — 입력에 따라 차등: 18홀 1인 19,000원 / 9홀 1인 11,000원 × 인원 (데모. 실제 가격은 매장 자율, §1)
  const UNIT = holes === "18" ? 19000 : 11000;
  const won = (n)=> n.toLocaleString("ko-KR") + "원";
  const isApp = payMethod === "app" || prepayRequired;
  const total = UNIT * Math.max(1, people);
  const canPay = !limitReached && people >= 1; // 인원 미선택 시 결제/요청 불가
  const noticeLong = storeNotice && storeNotice.length > 45; // 긴 공지 → 더보기

  const goNext = ()=>{
    setForm({store, product, date, holes, people, req, note, payMethod, startT, endT, time:`${startT} ~ ${endT}`});
    onNext();
  };

  return (
    <div className="screen">
      <StatusBar/>
      <Appbar title="스크린 예약하기" onBack={onBack}
        right={<button className="icon-btn" onClick={onClose}><Icon name="x" size={18}/></button>}/>

      <div className="scroll" style={{paddingBottom:100,background:"#fff"}}>
        {/* === 1. 매장 사진 — 등록 이미지 있으면 등록 이미지(실내/기기/가격표), 없으면 기본 이미지 === */}
        <StoreHero store={store} kicker="Screen" photoIdx={photoIdx} onDot={setPhotoIdx}/>

        {/* === 2. 매장 아이덴티티 (매장명 · 영업상태 · 기기 대수 · 평점) === */}
        <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>
                {screenHours.map(([t])=>(<span key={t} className={"store-badge sb-"+String(t).toLowerCase()}>{t}</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===false?"var(--text-mute)":"var(--primary)",fontWeight:700}}>● {store?.open===false?"영업전":"영업중"}</span>
                {Object.keys(storeMachines).length > 0 && (
                  <><span className="sdot"/><span>{Object.entries(storeMachines).map(([code,cnt])=>`${code==="Q"?"Quantum":code==="T2"?"T2":code} ${cnt}대`).join(" · ")}</span></>
                )}
                {distText && <><span className="sdot"/><span>{distText}</span></>}
              </div>
            </div>
            <div style={{display:"flex",flexDirection:"column",alignItems:"center",padding:"6px 11px",borderRadius:10,background:"var(--primary-tint)"}}>
              <div style={{display:"flex",alignItems:"center",gap:3}}>
                <Icon name="star" size={12} style={{color:"var(--primary)"}}/>
                <span style={{fontSize:14,fontWeight:800,color:"var(--primary)"}}>4.9</span>
              </div>
              <div style={{fontSize:9.5,color:"var(--primary)",fontWeight:600,marginTop:1,letterSpacing:".02em"}}>리뷰 128</div>
            </div>
          </div>

          {/* 편의시설 칩 — 미등록 시 숨김 */}
          {storeAmenities.length > 0 && (
            <div style={{display:"flex",gap:6,overflowX:"auto",scrollbarWidth:"none",marginTop:12,paddingBottom:2}}>
              {storeAmenities.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>

        {/* === 3. 퀵 액션 (전화 · 길찾기 · 공유) — 매장 변경은 뒤로가기로 대체 === */}
        <div style={{padding:"12px 20px 4px",display:"flex",gap:6}}>
          <a href={`tel:${storeTel}`} 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>
          {[
            {icon:"nav",   label:"길찾기", fn:null},
            {icon:"share", label:"공유",   fn:null},
          ].map(a=>(
            <button key={a.label} onClick={a.fn} 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={a.icon} size={16}/>
              <span style={{fontSize:11,fontWeight:600,color:"var(--text)"}}>{a.label}</span>
            </button>
          ))}
        </div>

        {/* === 4. 주소 · 영업시간 · 전화 카드 (복사 버튼 포함) === */}
        <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}}>
                {storeAddr}
                <button onClick={()=>copyText(storeAddr,"주소가 복사되었습니다.")} 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"}}>
                {storeTel}
                <button onClick={()=>copyText(storeTel,"전화번호가 복사되었습니다.")} style={{marginLeft:6,background:"transparent",color:"var(--primary)",fontSize:12.5,fontWeight:700}}>복사</button>
              </div>
            </div>
          </div>

          {/* 매장 공지 · 주차 안내 — 미등록 항목은 숨김, 둘 다 없으면 박스 전체 미노출. 공지 길면 더보기 */}
          {(storeNotice || storeParking) && (
            <div style={{marginTop:10,padding:"12px 14px",borderRadius:10,background:"var(--bg-soft)"}}>
              {storeNotice && (
                <>
                  <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"} : {})}}>{storeNotice}</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>
                  )}
                </>
              )}
              {storeNotice && storeParking && <div style={{height:1,background:"var(--line)",margin:"10px 0"}}/>}
              {storeParking && (
                <>
                  <div style={{fontSize:12,fontWeight:800,color:"var(--text)",marginBottom:4}}>주차 안내</div>
                  <div style={{fontSize:12.5,color:"var(--text-sub)",lineHeight:1.55}}>{storeParking}</div>
                </>
              )}
            </div>
          )}
        </div>

        {/* === 5. 예약자 === */}
        <div style={{padding:"16px 20px 0"}}>
          <button onClick={onEditUser} style={{width:"100%",display:"flex",alignItems:"center",justifyContent:"space-between",padding:"14px 14px",borderRadius:10,border:"1px solid var(--line)",background:"#fff",textAlign:"left"}}>
            <div style={{display:"flex",alignItems:"center",gap:10}}>
              <div style={{width:30,height:30,borderRadius:8,background:"var(--primary-tint)",color:"var(--primary)",display:"flex",alignItems:"center",justifyContent:"center"}}><Icon name="user" size={14}/></div>
              <div>
                <div style={{fontSize:10.5,color:"var(--text-sub)",fontWeight:600,letterSpacing:".02em"}}>예약자</div>
                <div style={{fontSize:13,fontWeight:700,marginTop:1}}>{(reserver?.name||"홍길동")} · {(reserver?.phone||"010-1234-5678")}</div>
              </div>
            </div>
            <Icon name="chev-r" size={14} style={{color:"var(--text-mute)"}}/>
          </button>
        </div>

        {/* divider */}
        <div style={{height:8,margin:"22px 0 0",background:"#F4F6F9"}}/>

        {/* 1일 예약 한도 안내 (정책 §1) */}
        <div style={{paddingTop:14}}><DailyLimitBanner count={todayCount} limit={limit} onCycle={onCycleLimit}/></div>

        {/* Product select */}
        <div style={{padding:"20px 20px 8px"}}>
          <div style={{display:"flex",alignItems:"baseline",gap:6,marginBottom:10}}>
            <div style={{fontSize:14,fontWeight:800}}>제품 선택</div>
            <div style={{fontSize:11,color:"var(--text-mute)",fontWeight:500}}>· Q / T2 중 하나 선택</div>
          </div>
          <div style={{display:"flex",background:"var(--bg-soft)",borderRadius:8,padding:3,gap:3}}>
            {["Quantum","T2"].map((p,i)=>{
              const code = i===0 ? "Q" : "T2";
              const active = product===code;
              const disabled = !availableProducts.includes(code);
              return (
                <button key={p} onClick={()=>onPickProduct(code)} style={{
                  flex:1,height:42,borderRadius:6,fontSize:14,fontWeight:700,
                  display:"flex",alignItems:"center",justifyContent:"center",gap:6,
                  background: active ? "#fff" : "transparent",
                  color: disabled ? "var(--text-mute)" : (active ? "var(--primary)" : "var(--text-mute)"),
                  boxShadow: active ? "0 1px 3px rgba(0,0,0,.08)" : "none",
                  opacity: disabled ? .55 : 1,
                }}>{active && <Icon name="check" size={13} stroke={3}/>}{p}{disabled ? " ⊘" : ""}</button>
              );
            })}
          </div>
        </div>

        {/* Date — 당일~14일 (정책 §1) */}
        <div style={{padding:"18px 20px 8px"}}>
          <div style={{display:"flex",alignItems:"baseline",gap:6,marginBottom:10}}>
            <div style={{fontSize:14,fontWeight:800}}>날짜</div>
            <div style={{fontSize:11,color:"var(--text-mute)",fontWeight:500}}>· 당일부터 14일 이내</div>
          </div>
          <div style={{display:"flex",gap:8,overflowX:"auto",scrollbarWidth:"none",margin:"0 -20px",padding:"0 20px 4px"}}>
            {days14.map((d,i)=>{
              const on = date===i, dow = d.getDay();
              return (
                <button key={i} onClick={()=>setDate(i)} style={{
                  flex:"0 0 auto",width:48,padding:"8px 0",borderRadius:12,textAlign:"center",
                  background: on?"var(--primary)":"var(--bg-soft)",
                  color: on?"#fff":(dow===0?"#EF4444":dow===6?"#3B82F6":"var(--text)"),
                  border:"1.5px solid "+(on?"var(--primary)":"transparent")
                }}>
                  <div style={{fontSize:10,fontWeight:600,opacity:on?.9:.7}}>{i===0?"오늘":WD[dow]}</div>
                  <div style={{fontSize:15,fontWeight:800,marginTop:2}}>{d.getDate()}</div>
                </button>
              );
            })}
          </div>
        </div>

        {/* Time */}
        <div style={{padding:"18px 20px 8px"}}>
          <div style={{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:10}}>
            <div style={{fontSize:14,fontWeight:800}}>시간</div>
            <div style={{display:"flex",background:"var(--bg-soft)",borderRadius:999,padding:2}}>
              {["18H","9H"].map((h,i)=>(
                <button key={h} onClick={()=>setHoles(i===0?"18":"9")} style={{
                  padding:"6px 14px",borderRadius:999,fontSize:12,fontWeight:700,
                  background: ((holes==="18"&&i===0)||(holes==="9"&&i===1)) ? "var(--primary)" : "transparent",
                  color: ((holes==="18"&&i===0)||(holes==="9"&&i===1)) ? "#fff" : "var(--text-mute)",
                }}>{h}</button>
              ))}
            </div>
          </div>
          <div style={{fontSize:11,color:"var(--text-sub)",marginBottom:10}}>
            {holes === "18"
              ? "18홀 게임의 티타임은 한 사람 당 60분으로 계산돼요."
              : "9홀 게임의 티타임은 한 사람 당 30분으로 계산돼요."}
            <br/>이용 시작 10분 전까지 예약할 수 있어요.
          </div>
          <div style={{display:"flex",gap:10}}>
            <button onClick={()=>setTimeOpen(true)} style={{flex:1,border:"1.5px solid var(--primary)",borderRadius:8,padding:"10px 14px",background:"#fff",textAlign:"left"}}>
              <div style={{fontSize:11,color:"var(--primary)",fontWeight:700}}>시작</div>
              <div style={{display:"flex",alignItems:"center",justifyContent:"space-between",marginTop:2}}>
                <div style={{fontSize:16,fontWeight:700,fontVariantNumeric:"tabular-nums"}}>{startT}</div>
                <Icon name="chev-d" size={14}/>
              </div>
            </button>
            <div style={{flex:1,border:"1.5px solid var(--line-strong)",borderRadius:8,padding:"10px 14px",background:"var(--bg-soft)"}}>
              <div style={{fontSize:11,color:"var(--text-mute)",fontWeight:700}}>종료</div>
              <div style={{fontSize:16,fontWeight:700,color:"var(--text-mute)",marginTop:2,fontVariantNumeric:"tabular-nums"}}>{endT}</div>
            </div>
          </div>
          <div style={{fontSize:11,color:"var(--text-mute)",marginTop:8}}>
            종료 시간은 <b style={{color:"var(--text-sub)"}}>{holes}홀 · {calcPeople}명 × {perMin}분</b> 기준으로 자동 계산돼요.
          </div>
        </div>

        {/* People */}
        <div style={{padding:"18px 20px 8px"}}>
          <div style={{display:"flex",alignItems:"center",justifyContent:"space-between"}}>
            <div style={{fontSize:14,fontWeight:800}}>인원</div>
            <div style={{display:"flex",alignItems:"center",gap:12}}>
              <button onClick={()=>setPeople(Math.max(0,people-1))} style={{width:28,height:28,borderRadius:"50%",background:"var(--bg-soft)",color:"var(--text)"}}><Icon name="menu" size={14} stroke={3} style={{transform:"scaleY(.3)"}}/></button>
              <div style={{width:32,height:32,borderRadius:"50%",background:people>0?"var(--primary)":"transparent",color:people>0?"#fff":"var(--text)",display:"flex",alignItems:"center",justifyContent:"center",fontSize:16,fontWeight:800}}>{people}</div>
              <button onClick={()=>setPeople(people+1)} style={{width:28,height:28,borderRadius:"50%",background:"var(--bg-soft)",color:"var(--text)"}}><Icon name="plus" size={14} stroke={3}/></button>
            </div>
          </div>
        </div>

        {/* Requests */}
        <div style={{padding:"18px 20px 24px"}}>
          <div style={{fontSize:14,fontWeight:800,marginBottom:10}}>요청사항</div>
          <div style={{display:"flex",flexDirection:"column",gap:0}}>
            {reqs.map(r=>{
              const on = req.includes(r.id);
              return (
                <button key={r.id} onClick={()=>toggle(r.id)} style={{display:"flex",alignItems:"center",gap:10,padding:"10px 0",background:"transparent",textAlign:"left"}}>
                  <div style={{width:22,height:22,borderRadius:"50%",background:on?"var(--primary)":"transparent",border:on?"none":"1.5px solid var(--line-strong)",color:"#fff",display:"flex",alignItems:"center",justifyContent:"center"}}>
                    {on && <Icon name="check" size={13} stroke={3}/>}
                  </div>
                  <div style={{fontSize:14,fontWeight:500,color:on?"var(--text)":"var(--text-sub)"}}>{r.label}</div>
                </button>
              );
            })}
          </div>
          {req.includes("etc") && (
            <div style={{marginTop:10,border:"1.5px solid var(--primary)",borderRadius:8,padding:12,position:"relative"}}>
              <textarea value={note} onChange={e=>setNote(e.target.value.slice(0,100))}
                placeholder="기타 요청사항을 입력해 주세요."
                style={{width:"100%",border:0,outline:"none",resize:"none",fontSize:12,lineHeight:1.5,color:"var(--text)",background:"transparent",minHeight:60}}/>
              <div style={{textAlign:"right",fontSize:11,color:"var(--text-mute)"}}>{note.length}/100</div>
            </div>
          )}
        </div>

        {/* 결제 방식 — 사전결제(App)/현장결제 선택 (정책 §4) · 선결제 전환 시 현장결제 불가 (정책 §7) */}
        <div style={{padding:"4px 20px 24px"}}>
          <div style={{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:10}}>
            <div style={{fontSize:14,fontWeight:800}}>결제 방식</div>
            <button onClick={()=>setPrepayRequired(v=>{ const nv=!v; if(nv) setPayMethod("app"); return nv; })}
              style={{fontSize:9,color:"var(--text-mute)",background:"transparent",border:"1px dashed var(--line)",borderRadius:4,padding:"3px 5px",fontWeight:600}}>데모: 선결제 전환 {prepayRequired?"ON":"OFF"}</button>
          </div>
          {prepayRequired && (
            <div style={{margin:"0 0 10px",padding:"11px 14px",borderRadius:10,background:"#FEECEA",border:"1px solid #F8C6BF",display:"flex",gap:10,alignItems:"flex-start"}}>
              <div style={{color:"var(--danger)",marginTop:1,flexShrink:0}}><Icon name="info" size={16}/></div>
              <div style={{fontSize:12,color:"var(--text-sub)",lineHeight:1.5}}>반복 노쇼(누적 3회)로 <b style={{color:"var(--text)"}}>선결제가 적용</b>돼요. 현장 결제는 선택할 수 없고, 예약과 동시에 결제해야 확정됩니다.</div>
            </div>
          )}
          <div style={{display:"flex",gap:8}}>
            {[["app","App 결제","예약과 동시에 카드·간편결제"],["onsite","현장 결제","이용 시작 전 매장에서 결제"]].map(([id,label,desc])=>{
              const on = payMethod===id;
              const disabled = prepayRequired && id==="onsite";
              return (
                <button key={id} onClick={disabled ? null : ()=>setPayMethod(id)} style={{
                  flex:1,textAlign:"left",padding:"12px 14px",borderRadius:10,
                  background:on?"var(--primary-tint)":(disabled?"var(--bg)":"#fff"),border:"1.5px solid "+(on?"var(--primary)":"var(--line)"),
                  opacity:disabled?.5:1,cursor:disabled?"default":"pointer"
                }}>
                  <div style={{fontSize:13.5,fontWeight:700,color:on?"var(--primary)":(disabled?"var(--text-mute)":"var(--text)")}}>{label}{disabled?" · 불가":""}</div>
                  <div style={{fontSize:11,color:"var(--text-sub)",marginTop:3,lineHeight:1.4}}>{desc}</div>
                </button>
              );
            })}
          </div>
          <div style={{fontSize:11,color:"var(--text-mute)",marginTop:8,lineHeight:1.5}}>
            {prepayRequired
              ? "선결제 전환 상태에서는 예약과 동시에 App 결제가 필요해요. 노쇼 해제는 매장에서 처리할 수 있어요."
              : "사전결제는 선택이에요. 현장 결제 시 예약은 확정되고, 이용 시작 전 매장에서 결제하면 됩니다."}
          </div>
        </div>

        {/* 결제 금액 — 예약 화면에서 바로 확인 (App: 결제 예정 / 현장: 예상 참고) */}
        <div style={{padding:"4px 20px 24px"}}>
          <div style={{fontSize:14,fontWeight:800,marginBottom:10}}>결제 금액</div>
          <div style={{padding:16,borderRadius:10,background:"var(--bg-soft)"}}>
            <div style={{display:"flex",justifyContent:"space-between",fontSize:13}}>
              <span style={{color:"var(--text-sub)"}}>이용 요금 (1인 {won(UNIT)} × {Math.max(1,people)}명)</span>
              <span style={{fontWeight:700}}>{won(total)}</span>
            </div>
            <div style={{height:1,background:"var(--line)",margin:"12px 0"}}/>
            <div style={{display:"flex",justifyContent:"space-between",alignItems:"center"}}>
              <span style={{fontSize:14,fontWeight:800}}>{isApp ? "결제 예정 금액" : "예상 결제 금액 (참고)"}</span>
              <span style={{fontSize:19,fontWeight:800,color:isApp?"var(--primary)":"var(--text)"}}>{won(total)}</span>
            </div>
            <div style={{fontSize:11,color:"var(--text-mute)",marginTop:8,lineHeight:1.5}}>
              {isApp ? "다음 화면에서 결제 수단 선택 후 결제가 완료돼요." : "현장에서 결제하며, 실제 매장 이용금액과 다를 수 있어요."}
            </div>
          </div>
        </div>
      </div>

      <div style={{position:"absolute",bottom:0,left:0,right:0,padding:"12px 20px 24px",background:"#fff",borderTop:"1px solid var(--line)"}}>
        {limitReached && <div style={{fontSize:11.5,color:"var(--danger)",fontWeight:600,marginBottom:8,textAlign:"center"}}>오늘 예약 한도(2건)를 모두 사용했어요.</div>}
        {!limitReached && people < 1 && <div style={{fontSize:11.5,color:"var(--text-mute)",fontWeight:600,marginBottom:8,textAlign:"center"}}>인원을 선택해 주세요.</div>}
        <button className={"btn " + (canPay ? "btn-primary" : "btn-disabled")} style={{width:"100%"}} onClick={canPay ? goNext : null}>
          {isApp ? `${won(total)} 결제하기` : "예약 요청하기 (현장결제)"}
        </button>
      </div>

      {timeOpen && <TimePickerSheet title="시작시간 변경" value={startT}
        onClose={()=>setTimeOpen(false)}
        onApply={(v)=>{ setStartT(v); setTimeOpen(false); }}/>}

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

/* 예약 내역 확인 + 결제 (병합) — App 결제: 요약+결제수단+동의를 한 화면에서 처리 / 현장 결제: 요약+예약 요청 */
function BookingConfirm({ onBack, onClose, form, store, reserver, onPaid, onOnsite, onCollide, expanded }){
  const f = form || {};
  const isExpanded = expanded;
  // 결제 금액 — 입력에 따라 차등: 18홀 1인 19,000원 / 9홀 1인 11,000원 × 인원 (데모)
  const UNIT = f.holes === "9" ? 11000 : 19000;
  const people = Math.max(1, f.people || 1);
  const total = UNIT * people;
  const won = (n)=> n.toLocaleString("ko-KR") + "원";
  const fmt = (n)=> n.toLocaleString("ko-KR");
  const isApp = f.payMethod !== "onsite";
  const [method, setMethod] = React.useState("card");
  const [processing, setProcessing] = React.useState(false);
  // 할인 — 보유 할인권 목록에서 선택 사용 · 포인트 (데모 보유값)
  const OWNED_COUPONS = [
    {id:"c1", name:"신규 가입 할인권", value:5000, expiry:"2026.08.31"},
    {id:"c2", name:"주중 라운드 할인권", value:3000, expiry:"2026.07.31"},
  ];
  const HELD_POINTS = 12500;         // 보유 포인트
  const MIN_POINTS = 1000;           // 최소 사용 포인트
  const [couponSheet, setCouponSheet] = React.useState(false);   // 할인권 선택 시트
  const [couponId, setCouponId] = React.useState(null);          // 선택한 할인권 id
  const [pointsInput, setPointsInput] = React.useState("");
  const selectedCoupon = OWNED_COUPONS.find(c=>c.id===couponId) || null;
  const couponDiscount = selectedCoupon ? Math.min(selectedCoupon.value, total) : 0;
  const maxPoints = Math.max(0, Math.min(HELD_POINTS, total - couponDiscount));
  const rawPoints = parseInt((pointsInput||"").replace(/[^0-9]/g,"")) || 0;
  const pointsUsed = rawPoints >= MIN_POINTS ? Math.min(rawPoints, maxPoints) : 0;
  const finalTotal = Math.max(0, total - couponDiscount - pointsUsed);
  const vxReward = method === "vxmoney" ? Math.floor(finalTotal * 0.01) : 0; // VX머니 1% 적립 → 다음 결제 포인트
  // VX머니 계좌 연동 — 최초 결제 시 연동 필요
  const VX_BANKS = ["국민","신한","우리","하나","카카오뱅크","토스뱅크"];
  const [vxLinked, setVxLinked] = React.useState(false);
  const [vxAccount, setVxAccount] = React.useState(null);
  const [vxSheet, setVxSheet] = React.useState(false);
  const [vxBank, setVxBank] = React.useState(null);
  const needsVxLink = isApp && method === "vxmoney" && !vxLinked;
  // 필수 동의 — 개인정보 제3자 수집/제공
  const [agreePrivacy, setAgreePrivacy] = React.useState(false);
  const [pointHelp, setPointHelp] = React.useState(false); // 포인트 도움말 팝업

  const storeName = (isExpanded ? "퀀텀 아카데미 판교 파미어스몰 C-1, 612-123점" : (store?.name || f.store?.name || "퀀텀 아카데미 판교점"));
  const productText = (Array.isArray(f.product) ? f.product : [f.product||"Q"]).map(c=>c==="T2"?"T2":"Quantum").join(" · ");
  const reqLabels = {t3:"T3 신규 제품",left:"좌타방","2game":"2게임 예약",joined:"연결된 방",fourball:"포섬","4ball":"포볼"};
  const reqText = (()=>{
    const arr = (f.req||[]).filter(id=>id!=="etc").map(id=>reqLabels[id]||id);
    if (f.note) arr.push(f.note);
    return arr.length ? arr.join(", ") : "없음";
  })();
  // 예약 일자 — 폼에서 고른 날짜(오늘+n일) + 시작~종료(18홀 60분/9홀 30분 × 인원 자동 계산)
  const dateText = (()=>{
    const d = new Date(); d.setDate(d.getDate() + (f.date || 0));
    const WD = ["일","월","화","수","목","금","토"];
    const p2 = (n)=>String(n).padStart(2,"0");
    const base = `${d.getFullYear()}.${p2(d.getMonth()+1)}.${p2(d.getDate())}(${WD[d.getDay()]})`;
    return f.time ? `${base} ${f.time}` : `${base} 12:00`;
  })();
  const methods = [
    {id:"vxmoney", label:"VX머니 결제", sub:"계좌 연결 · 결제 금액 1% 적립", badge:"VX", reward:true},
    {id:"card", label:"신용·체크카드", sub:"신한카드 ···· 4821"},
    {id:"kakaopay", label:"카카오페이", sub:"간편결제"},
  ];
  const ctaDisabled = isApp && (!agreePrivacy || processing || needsVxLink);
  const submit = ()=>{
    if (isApp) {
      if (!agreePrivacy || processing || needsVxLink) return;
      setProcessing(true);
      // 결제 처리(데모). 실패 시 정책 §4·§15: 예약 일정 시간 유지·재결제 기회.
      setTimeout(()=>{ setProcessing(false); onPaid && onPaid(); }, 1400);
    } else {
      onOnsite && onOnsite();
    }
  };
  const AgreeRow = ({ on, onToggle, children })=>(
    <button onClick={onToggle} style={{display:"flex",gap:10,alignItems:"flex-start",textAlign:"left",width:"100%",padding:"6px 0"}}>
      <div style={{width:18,height:18,borderRadius:4,background:on?"var(--primary)":"#fff",border:"1.5px solid "+(on?"var(--primary)":"var(--line-strong)"),display:"flex",alignItems:"center",justifyContent:"center",flexShrink:0,marginTop:1}}>
        {on && <Icon name="check" size={12} stroke={3} style={{color:"#fff"}}/>}
      </div>
      <div style={{fontSize:12.5,color:"var(--text-sub)"}}>{children}<span className="link" style={{marginLeft:6}}>내용 보기</span></div>
    </button>
  );
  return (
    <div className="screen">
      <StatusBar/>
      <Appbar title="예약 내역 확인" onBack={onBack}
        right={<button className="icon-btn" onClick={onClose}><Icon name="x" size={18}/></button>}/>

      <div className="scroll" style={{padding:"8px 20px 140px"}}>
        {/* App 결제: 결제 중 타석 점유 안내 (정책 §1) */}
        {isApp && (
          <div style={{margin:"8px 0 4px",padding:"12px 14px",borderRadius:10,background:"var(--primary-tint)",border:"1px solid #BDEACC",display:"flex",gap:10,alignItems:"flex-start"}}>
            <div style={{color:"var(--primary)",marginTop:1}}><Icon name="clock" size={16}/></div>
            <div style={{fontSize:12.5,color:"var(--text-sub)",lineHeight:1.5}}>결제하는 동안 타석을 <b style={{color:"var(--text)"}}>10분간</b> 잡아둡니다. 시간 내 결제하지 않으면 자동 해제돼요.</div>
          </div>
        )}
        {onCollide && isApp && (
          <div style={{textAlign:"right",marginTop:6}}>
            <button onClick={onCollide} style={{fontSize:9,color:"var(--text-mute)",background:"transparent",border:"1px dashed var(--line)",borderRadius:4,padding:"3px 6px",fontWeight:600}}>데모: 동시 예약 충돌(점유 실패) 재현</button>
          </div>
        )}

        {/* 예약 정보 */}
        <div style={{fontSize:16,fontWeight:800,color:"var(--text-sub)",margin:"18px 0 18px"}}>예약 정보</div>
        <div style={{display:"grid",gridTemplateColumns:"80px 1fr",rowGap:22,fontSize:14}}>
          <div style={{color:"var(--text-sub)"}}>매장명</div>
          <div style={{fontWeight:600,textAlign:"right"}}>{storeName}</div>

          <div style={{color:"var(--text-sub)"}}>예약자</div>
          <div style={{fontWeight:600,textAlign:"right"}}>{(reserver?.name||"홍길동")} · {(reserver?.phone||"010-1234-5678")}</div>

          <div style={{color:"var(--text-sub)"}}>제품</div>
          <div style={{fontWeight:600,textAlign:"right"}}>{productText}</div>

          <div style={{color:"var(--text-sub)"}}>예약 일자</div>
          <div style={{fontWeight:600,textAlign:"right",lineHeight:1.5}}>{dateText}{f.holes ? ` · ${f.holes}홀` : ""}</div>

          <div style={{color:"var(--text-sub)"}}>인원</div>
          <div style={{fontWeight:600,textAlign:"right"}}>{f.people ? `${f.people}명` : `${people}명`}</div>

          <div style={{color:"var(--text-sub)"}}>결제 방식</div>
          <div style={{fontWeight:600,textAlign:"right"}}>{isApp ? "App 결제" : "현장 결제"}</div>

          <div style={{color:"var(--text-sub)"}}>요청사항</div>
          <div style={{fontWeight:600,textAlign:"right",lineHeight:1.6}}>{reqText}</div>
        </div>

        {/* App 결제: 할인 (할인권·포인트) */}
        {isApp && (
          <div style={{marginTop:24,paddingTop:20,borderTop:"8px solid var(--bg-soft)"}}>
            <div style={{fontSize:16,fontWeight:800,marginBottom:12}}>할인</div>

            {/* 할인권(쿠폰) 사용 — 탭 시 보유 할인권 선택 시트 */}
            <button onClick={()=>setCouponSheet(true)} className="card" style={{width:"100%",textAlign:"left",padding:14,marginBottom:8}}>
              <div style={{display:"flex",justifyContent:"space-between",alignItems:"center"}}>
                <div style={{display:"flex",alignItems:"center",gap:10}}>
                  <div style={{width:34,height:34,borderRadius:8,background:"var(--primary-tint)",display:"flex",alignItems:"center",justifyContent:"center",color:"var(--primary)"}}><Icon name="ticket" size={16}/></div>
                  <div>
                    <div style={{fontWeight:700,fontSize:13.5,color:"var(--text)"}}>할인권 사용</div>
                    <div style={{fontSize:11.5,color:"var(--text-sub)",marginTop:2}}>{selectedCoupon ? selectedCoupon.name : `보유 ${OWNED_COUPONS.length}장`}</div>
                  </div>
                </div>
                <div style={{fontSize:13.5,fontWeight:700,color:selectedCoupon?"var(--primary)":"var(--text-mute)",display:"flex",alignItems:"center",gap:4}}>
                  {selectedCoupon ? `-${won(couponDiscount)}` : <><span style={{fontSize:12.5}}>선택</span><Icon name="chev-r" size={15}/></>}
                </div>
              </div>
            </button>
            {!selectedCoupon && OWNED_COUPONS.length>0 && (
              <div style={{fontSize:12,color:"var(--primary)",fontWeight:600,margin:"0 2px 14px"}}>사용 가능한 할인권이 {OWNED_COUPONS.length}장 있어요.</div>
            )}
            {selectedCoupon && <div style={{height:14}}/>}

            {/* 포인트 사용 */}
            <div className="card" style={{padding:14,position:"relative"}}>
              <div style={{display:"flex",alignItems:"center",gap:10,marginBottom:12}}>
                <div style={{width:34,height:34,borderRadius:8,background:"var(--primary-tint)",display:"flex",alignItems:"center",justifyContent:"center",color:"var(--primary)",fontWeight:800,fontSize:15}}>P</div>
                <div style={{flex:1}}>
                  <div style={{display:"flex",alignItems:"center",gap:4}}>
                    <span style={{fontWeight:700,fontSize:13.5,color:"var(--text)"}}>포인트 사용</span>
                    <button onClick={()=>setPointHelp(v=>!v)} aria-label="포인트 안내" style={{background:"transparent",color:"var(--text-mute)",display:"flex",alignItems:"center",padding:2}}><Icon name="info" size={14}/></button>
                  </div>
                  <div style={{fontSize:11.5,color:"var(--text-sub)",marginTop:2}}>보유 {fmt(HELD_POINTS)}P</div>
                </div>
              </div>
              {pointHelp && (
                <div style={{position:"absolute",left:14,right:14,top:52,zIndex:40,background:"var(--text)",color:"#fff",borderRadius:10,padding:"12px 14px",boxShadow:"0 8px 24px rgba(0,0,0,.28)"}}>
                  <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",gap:8,marginBottom:6}}>
                    <span style={{fontSize:12.5,fontWeight:800}}>포인트 안내</span>
                    <button onClick={()=>setPointHelp(false)} style={{background:"transparent",color:"rgba(255,255,255,.7)"}}><Icon name="x" size={14}/></button>
                  </div>
                  <div style={{fontSize:11.5,lineHeight:1.7,color:"rgba(255,255,255,.9)"}}>
                    · VX머니 결제 시 결제 금액의 <b style={{color:"#fff"}}>1%</b>가 포인트로 적립돼요.<br/>
                    · 적립 포인트는 <b style={{color:"#fff"}}>예약이 확정된 이후</b>부터 사용할 수 있어요. (예약 후 취소 시 적립되지 않아요)<br/>
                    · 포인트 유효기간은 적립일로부터 <b style={{color:"#fff"}}>6개월</b>이에요.
                  </div>
                </div>
              )}
              <div style={{display:"flex",gap:8,alignItems:"center"}}>
                <div style={{flex:1,display:"flex",alignItems:"center",border:"1.5px solid var(--line-strong)",borderRadius:8,padding:"10px 12px"}}>
                  <input value={pointsInput} inputMode="numeric" placeholder="0"
                    onChange={e=>{ const d=e.target.value.replace(/[^0-9]/g,""); const n=Math.min(parseInt(d)||0, HELD_POINTS); setPointsInput(n?String(n):""); }}
                    style={{flex:1,border:0,outline:"none",fontSize:15,fontWeight:700,textAlign:"right",background:"transparent",color:"var(--text)"}}/>
                  <span style={{marginLeft:6,fontSize:14,fontWeight:700,color:"var(--text-sub)"}}>P</span>
                </div>
                <button onClick={()=>setPointsInput(maxPoints>=MIN_POINTS?String(maxPoints):"")} style={{padding:"11px 14px",borderRadius:8,background:"var(--bg-soft)",fontSize:13,fontWeight:700,color:"var(--text)"}}>전액 사용</button>
              </div>
              <div style={{fontSize:11,color: (rawPoints>0 && rawPoints<MIN_POINTS) ? "var(--danger)" : "var(--text-mute)",marginTop:8}}>최소 {fmt(MIN_POINTS)}P부터 사용할 수 있어요.</div>
            </div>
          </div>
        )}

        {/* 결제 금액 — App 결제: 할인 반영 최종 금액 / 현장 결제: 예상 금액(참고) */}
        <div style={{marginTop:24,paddingTop:20,borderTop:"8px solid var(--bg-soft)"}}>
          <div style={{fontSize:16,fontWeight:800,marginBottom:6}}>결제 금액</div>
          <div style={{display:"flex",justifyContent:"space-between",padding:"12px 0",fontSize:14,borderBottom:"1px solid var(--line)"}}>
            <span style={{color:"var(--text-sub)"}}>이용 요금 (1인 {won(UNIT)} × {people}명)</span><span style={{fontWeight:700}}>{won(total)}</span>
          </div>
          {isApp && couponDiscount>0 && (
            <div style={{display:"flex",justifyContent:"space-between",padding:"12px 0",fontSize:14,borderBottom:"1px solid var(--line)"}}>
              <span style={{color:"var(--text-sub)"}}>할인권</span><span style={{fontWeight:700,color:"var(--primary)"}}>-{won(couponDiscount)}</span>
            </div>
          )}
          {isApp && pointsUsed>0 && (
            <div style={{display:"flex",justifyContent:"space-between",padding:"12px 0",fontSize:14,borderBottom:"1px solid var(--line)"}}>
              <span style={{color:"var(--text-sub)"}}>포인트</span><span style={{fontWeight:700,color:"var(--primary)"}}>-{won(pointsUsed)}</span>
            </div>
          )}
          <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",padding:"16px 0 6px",borderTop:"2px solid var(--line)"}}>
            <span style={{fontSize:15,fontWeight:800}}>{isApp ? "최종 결제 금액" : "예상 결제 금액 (참고)"}</span>
            <span style={{fontSize:20,fontWeight:800,color:isApp?"var(--primary)":"var(--text)"}}>{won(isApp?finalTotal:total)}</span>
          </div>
          <div style={{fontSize:11.5,color:"var(--text-mute)",lineHeight:1.5,marginTop:6}}>
            {isApp ? "아래에서 결제 수단을 선택하고 결제하면 예약이 확정됩니다." : "현장에서 결제하며, 지금 금액은 참고용입니다. 실제 매장 이용금액과 다를 수 있어요."}
          </div>
        </div>

        {/* App 결제: 결제 수단 (VX머니·카드·카카오페이) */}
        {isApp && (
          <div style={{marginTop:24,paddingTop:20,borderTop:"8px solid var(--bg-soft)"}}>
            <div style={{fontSize:16,fontWeight:800,marginBottom:10}}>결제 수단</div>
            <div className="card" style={{padding:4}}>
              {methods.map(m=>{
                const on = method===m.id;
                return (
                  <button key={m.id} onClick={()=>setMethod(m.id)} className="row" style={{width:"100%",textAlign:"left",cursor:"pointer"}}>
                    <div style={{width:34,height:34,borderRadius:8,background:"var(--primary-tint)",display:"flex",alignItems:"center",justifyContent:"center",color:"var(--primary)",fontWeight:800,fontSize:12.5}}>
                      {m.badge ? m.badge : <Icon name="card" size={16}/>}
                    </div>
                    <div style={{flex:1}}>
                      <div style={{fontWeight:600,fontSize:13.5,color:"var(--text)",display:"flex",alignItems:"center",gap:6}}>{m.label}{m.reward && <span style={{fontSize:10,fontWeight:700,color:"var(--primary)",background:"var(--primary-tint)",padding:"1px 6px",borderRadius:999}}>1% 적립</span>}</div>
                      <div className="mono" style={{fontSize:11,color:"var(--text-mute)",marginTop:2}}>{m.sub}</div>
                    </div>
                    <div style={{width:18,height:18,borderRadius:"50%",border:"2px solid "+(on?"var(--primary)":"var(--line-strong)"),display:"flex",alignItems:"center",justifyContent:"center"}}>
                      {on && <span style={{width:8,height:8,borderRadius:"50%",background:"var(--primary)"}}/>}
                    </div>
                  </button>
                );
              })}
            </div>
            {method==="vxmoney" && (
              vxLinked ? (
                <div style={{marginTop:8,padding:"10px 12px",borderRadius:8,background:"var(--primary-tint)",display:"flex",gap:8,alignItems:"flex-start"}}>
                  <div style={{color:"var(--primary)",marginTop:1}}><Icon name="info" size={14}/></div>
                  <div style={{fontSize:12,color:"var(--text-sub)",lineHeight:1.55}}><b style={{color:"var(--text)"}}>{vxAccount}</b> 계좌에서 <b style={{color:"var(--text)"}}>{won(finalTotal)}</b>이 출금돼요. 결제 금액의 1%인 <b style={{color:"var(--primary)"}}>{fmt(vxReward)}P</b>가 적립되며, <b style={{color:"var(--text)"}}>예약 확정 이후</b>부터 사용할 수 있어요(유효기간 6개월).</div>
                </div>
              ) : (
                <div style={{marginTop:8,padding:"12px 14px",borderRadius:8,background:"var(--bg-soft)",border:"1px solid var(--line)"}}>
                  <div style={{display:"flex",gap:8,alignItems:"flex-start"}}>
                    <div style={{color:"var(--text-mute)",marginTop:1}}><Icon name="info" size={14}/></div>
                    <div style={{flex:1,fontSize:12,color:"var(--text-sub)",lineHeight:1.55}}>VX머니 결제를 처음 이용하려면 <b style={{color:"var(--text)"}}>계좌 연동</b>이 필요해요. 연동한 계좌에서 결제 금액이 출금되고 1%가 포인트로 적립돼요.</div>
                  </div>
                  <button onClick={()=>{ setVxBank(null); setVxSheet(true); }} className="btn btn-soft" style={{width:"100%",height:44,marginTop:10,fontSize:14}}>계좌 연동하기</button>
                </div>
              )
            )}
          </div>
        )}

        {/* 취소·환불 및 노쇼 안내 — App/현장 공통 */}
        <div style={{marginTop:24,paddingTop:20,borderTop:"8px solid var(--bg-soft)"}}>
          <div style={{fontSize:16,fontWeight:800,marginBottom:10}}>취소·환불 및 노쇼 안내</div>
          <div style={{padding:"12px 14px",borderRadius:10,background:"var(--bg-soft)",fontSize:12,color:"var(--text-sub)",lineHeight:1.75}}>
            · <b style={{color:"var(--text)"}}>예약 시간 30분 전</b>까지 취소하면 100% 환불돼요.<br/>
            · 예약 시간 <b style={{color:"var(--text)"}}>30분 이내</b>에는 취소·환불이 불가해요.<br/>
            · 노쇼(미방문)가 <b style={{color:"var(--text)"}}>반복(3회 이상)</b>되면 앱에서 현장 결제가 제한되고 앱 사전 결제만 가능해요.<br/>
            · 예약 시간 1시간 이내 취소가 반복되면 페널티가 부여될 수 있어요.
          </div>
        </div>

        {/* App 결제: 필수 동의 (개인정보 제3자) */}
        {isApp && (
          <div style={{marginTop:16}}>
            <AgreeRow on={agreePrivacy} onToggle={()=>setAgreePrivacy(v=>!v)}>[필수] 개인정보 제3자 수집·제공에 동의합니다.</AgreeRow>
          </div>
        )}
      </div>

      <div style={{position:"absolute",bottom:0,left:0,right:0,padding:"12px 20px 24px",background:"#fff",borderTop:"1px solid var(--line)"}}>
        <button className={"btn " + (ctaDisabled ? "btn-disabled" : "btn-primary")} style={{width:"100%"}} onClick={ctaDisabled ? null : submit}>
          {isApp ? `${won(finalTotal)} 결제하기` : "예약 요청하기 (현장결제)"}
        </button>
      </div>

      {/* 보유 할인권 선택 시트 */}
      {couponSheet && (
        <div style={{position:"absolute",inset:0,background:"rgba(0,0,0,.4)",display:"flex",alignItems:"flex-end",zIndex:210}} onClick={()=>setCouponSheet(false)}>
          <div onClick={e=>e.stopPropagation()} style={{background:"#fff",width:"100%",borderRadius:"16px 16px 0 0",padding:"20px 0 24px",maxHeight:"75%",display:"flex",flexDirection:"column"}}>
            <div style={{display:"flex",alignItems:"center",justifyContent:"space-between",padding:"0 20px 6px"}}>
              <div style={{fontSize:17,fontWeight:800}}>할인권 선택</div>
              <button onClick={()=>setCouponSheet(false)} style={{background:"transparent",color:"var(--text-mute)"}}><Icon name="x" size={18}/></button>
            </div>
            <div style={{fontSize:12,color:"var(--text-sub)",padding:"0 20px 10px"}}>보유 {OWNED_COUPONS.length}장 · 예약당 1장 사용 가능</div>
            <div style={{flex:1,overflowY:"auto",padding:"4px 20px 0"}}>
              {OWNED_COUPONS.map(c=>{
                const on = couponId===c.id;
                const usable = c.value>0; // 조건 없는 데모 — 실제로는 최소 결제금액·매장·기간 조건 검증
                return (
                  <button key={c.id} onClick={()=>{ setCouponId(on?null:c.id); setCouponSheet(false); }}
                    style={{width:"100%",textAlign:"left",display:"flex",alignItems:"center",gap:12,padding:"14px 12px",marginBottom:8,borderRadius:10,
                      border:"1.5px solid "+(on?"var(--primary)":"var(--line)"),background:on?"var(--primary-tint)":"#fff"}}>
                    <div style={{width:38,height:38,borderRadius:8,background:"var(--primary-tint)",display:"flex",alignItems:"center",justifyContent:"center",color:"var(--primary)",flexShrink:0}}><Icon name="ticket" size={17}/></div>
                    <div style={{flex:1,minWidth:0}}>
                      <div style={{fontWeight:700,fontSize:14,color:"var(--text)"}}>{c.name}</div>
                      <div style={{fontSize:11.5,color:"var(--text-mute)",marginTop:2}}>~{c.expiry}까지</div>
                    </div>
                    <div style={{fontSize:15,fontWeight:800,color:"var(--primary)"}}>{fmt(c.value)}원</div>
                  </button>
                );
              })}
            </div>
            <div style={{padding:"12px 20px 0"}}>
              <button className="btn btn-outline" style={{width:"100%"}} onClick={()=>{ setCouponId(null); setCouponSheet(false); }}>할인권 사용 안 함</button>
            </div>
          </div>
        </div>
      )}

      {/* VX머니 계좌 연동 시트 */}
      {vxSheet && (
        <div style={{position:"absolute",inset:0,background:"rgba(0,0,0,.4)",display:"flex",alignItems:"flex-end",zIndex:210}} onClick={()=>setVxSheet(false)}>
          <div onClick={e=>e.stopPropagation()} style={{background:"#fff",width:"100%",borderRadius:"16px 16px 0 0",padding:"20px 0 24px",maxHeight:"78%",display:"flex",flexDirection:"column"}}>
            <div style={{display:"flex",alignItems:"center",justifyContent:"space-between",padding:"0 20px 6px"}}>
              <div style={{fontSize:17,fontWeight:800}}>VX머니 계좌 연동</div>
              <button onClick={()=>setVxSheet(false)} style={{background:"transparent",color:"var(--text-mute)"}}><Icon name="x" size={18}/></button>
            </div>
            <div style={{fontSize:12.5,color:"var(--text-sub)",padding:"0 20px 14px",lineHeight:1.55}}>결제할 계좌를 선택하고 연동해 주세요. 연동 후 계좌에서 결제 금액이 출금되고 1%가 포인트로 적립돼요.</div>
            <div style={{flex:1,overflowY:"auto",padding:"0 20px"}}>
              <div style={{fontSize:12,fontWeight:700,color:"var(--text-sub)",marginBottom:8}}>은행 선택</div>
              <div style={{display:"grid",gridTemplateColumns:"repeat(3,1fr)",gap:8}}>
                {VX_BANKS.map(b=>{
                  const on = vxBank===b;
                  return (
                    <button key={b} onClick={()=>setVxBank(b)} style={{padding:"14px 8px",borderRadius:10,fontSize:13,fontWeight:700,
                      border:"1.5px solid "+(on?"var(--primary)":"var(--line)"),background:on?"var(--primary-tint)":"#fff",color:on?"var(--primary)":"var(--text)"}}>{b}</button>
                  );
                })}
              </div>
              <div style={{marginTop:14,padding:"11px 14px",borderRadius:10,background:"var(--bg-soft)",fontSize:11.5,color:"var(--text-mute)",lineHeight:1.6}}>
                · 연동 시 은행 앱 또는 ARS 인증을 거쳐요(데모에서는 생략).<br/>· 연동 계좌는 마이 &gt; 결제 수단 관리에서 변경·해지할 수 있어요.
              </div>
            </div>
            <div style={{padding:"14px 20px 0"}}>
              <button className={"btn " + (vxBank?"btn-primary":"btn-disabled")} style={{width:"100%"}}
                onClick={vxBank ? ()=>{ setVxLinked(true); setVxAccount(`${vxBank} ···· 1234`); setVxSheet(false); } : null}>
                {vxBank ? `${vxBank} 계좌 연동하기` : "은행을 선택해 주세요"}
              </button>
            </div>
          </div>
        </div>
      )}

      {processing && (
        <div style={{position:"absolute",inset:0,background:"rgba(255,255,255,.72)",zIndex:200,display:"flex",alignItems:"center",justifyContent:"center"}}>
          <div style={{fontSize:14,fontWeight:700,color:"var(--text)"}}>결제를 진행하고 있어요…</div>
        </div>
      )}
    </div>
  );
}

function BookingEdit({ onBack, reserver, onSave }){
  const [name, setName] = React.useState(reserver?.name || "홍길동");
  const [phone, setPhone] = React.useState((reserver?.phone || "").replace(/-/g,""));
  const canSave = name.trim().length>0;
  const save = ()=>{
    if(!canSave) return;
    const formatted = phone.length>=10
      ? phone.replace(/(\d{3})(\d{3,4})(\d{4})/, "$1-$2-$3")
      : phone || (reserver?.phone || "");
    onSave && onSave({name: name.trim(), phone: formatted});
  };
  return (
    <div className="screen">
      <StatusBar/>
      <Appbar title="예약자 정보 편집" onBack={onBack}/>

      <div style={{padding:"20px 20px",flex:1}}>
        <div style={{fontSize:13,color:"var(--primary)",fontWeight:600,marginBottom:6}}>예약자</div>
        <div style={{padding:"10px 0",borderBottom:"1.5px solid var(--primary)",display:"flex",alignItems:"center",gap:8}}>
          <input value={name} onChange={e=>setName(e.target.value)} style={{flex:1,fontSize:16,fontWeight:500,border:0,outline:"none",background:"transparent",color:"var(--primary)"}}/>
          <button onClick={()=>setName("")} style={{width:20,height:20,borderRadius:"50%",background:"#E5E7EB",display:"flex",alignItems:"center",justifyContent:"center"}}><Icon name="x" size={12}/></button>
        </div>

        <div style={{fontSize:13,color:"var(--text-sub)",fontWeight:600,marginTop:28,marginBottom:6}}>휴대폰 번호</div>
        <div style={{padding:"10px 0",borderBottom:"1.5px solid var(--line-strong)"}}>
          <input value={phone} onChange={e=>setPhone(e.target.value.replace(/[^0-9]/g,""))} placeholder="-를 제외하고 입력" inputMode="numeric"
            style={{width:"100%",fontSize:16,fontWeight:500,border:0,outline:"none",background:"transparent"}}/>
        </div>
      </div>

      {/* iOS QWERTY keyboard */}
      <div style={{background:"#D1D4DB",padding:"8px 4px 4px"}}>
        <button onClick={save} disabled={!canSave} style={{display:"block",width:"calc(100% + 8px)",background:canSave?"var(--primary)":"#A7E5C3",color:"#fff",padding:"14px 0",textAlign:"center",fontSize:15,fontWeight:700,margin:"-8px -4px 10px",border:0,cursor:canSave?"pointer":"default"}}>확인</button>
        <div style={{display:"grid",gridTemplateColumns:"repeat(10,1fr)",gap:4,marginBottom:6}}>
          {"QWERTYUIOP".split("").map(k=><div key={k} style={{background:"#fff",borderRadius:5,padding:"10px 0",textAlign:"center",fontSize:16,fontWeight:500,boxShadow:"0 1px 0 rgba(0,0,0,.2)"}}>{k}</div>)}
        </div>
        <div style={{display:"grid",gridTemplateColumns:"repeat(9,1fr)",gap:4,marginBottom:6,padding:"0 16px"}}>
          {"ASDFGHJKL".split("").map(k=><div key={k} style={{background:"#fff",borderRadius:5,padding:"10px 0",textAlign:"center",fontSize:16,fontWeight:500,boxShadow:"0 1px 0 rgba(0,0,0,.2)"}}>{k}</div>)}
        </div>
        <div style={{display:"grid",gridTemplateColumns:"1.5fr repeat(7,1fr) 1.5fr",gap:4,marginBottom:6}}>
          <div style={{background:"#ACB0BA",borderRadius:5,padding:"10px 0",textAlign:"center",fontSize:14,color:"#fff",fontWeight:700}}>⇧</div>
          {"ZXCVBNM".split("").map(k=><div key={k} style={{background:"#fff",borderRadius:5,padding:"10px 0",textAlign:"center",fontSize:16,fontWeight:500,boxShadow:"0 1px 0 rgba(0,0,0,.2)"}}>{k}</div>)}
          <div style={{background:"#ACB0BA",borderRadius:5,padding:"10px 0",textAlign:"center",fontSize:14,color:"#fff"}}>⌫</div>
        </div>
        <div style={{display:"grid",gridTemplateColumns:"1fr 4fr 1fr",gap:4}}>
          <div style={{background:"#ACB0BA",borderRadius:5,padding:"10px 0",textAlign:"center",fontSize:13,fontWeight:600,color:"#fff"}}>123</div>
          <div style={{background:"#fff",borderRadius:5,padding:"10px 0",textAlign:"center",fontSize:14,fontWeight:500}}>space</div>
          <div style={{background:"#ACB0BA",borderRadius:5,padding:"10px 0",textAlign:"center",fontSize:13,color:"#fff"}}>return</div>
        </div>
        <div style={{textAlign:"right",padding:"8px 8px 0"}}>🎙</div>
      </div>
    </div>
  );
}

/* ============================================================
   TRAINING booking — 매장 > 날짜/시간대 + 타석그리드 > 타석시간상세 > 확인(이용권)
   ============================================================ */

function TrainingForm({ onBack, onClose, onPickBay, store, reserver, onEditUser, todayCount=0, limit=2, onCycleLimit }){
  const limitReached = todayCount >= limit;
  const [date, setDate] = React.useState(3);
  const [startT, setStartT] = React.useState("13:00");
  const [endT, setEndT] = React.useState("15:00");
  const [pickerOpen, setPickerOpen] = React.useState(null); // 'start' | 'end' | null
  const [selectedBay, setSelectedBay] = React.useState(null);
  const [photoIdx, setPhotoIdx] = React.useState(0);
  const [req, setReq] = React.useState(new Set(["left"]));
  const [note, setNote] = React.useState("");
  const [policyOpen, setPolicyOpen] = React.useState(false);
  const days = ["일","월","화","수","목","금","토"];
  const dayNums = [1,2,3,4,5,6,7];

  // duration helper (minutes)
  const toMin = (t)=>{ const [h,m] = t.split(":").map(Number); return h*60+m; };
  const durMin = Math.max(0, toMin(endT) - toMin(startT));
  const rangeValid = durMin >= 30;

  // 타석은 번호가 아니라 '타석 이름'(카카오프렌즈)으로 선택 — 정책 §9 타석 운영 (등급별 가격 차등은 추후)
  const BAY_NAMES = ["라이언","어피치","프로도","네오","무지","콘","튜브","제이지","춘식","죠르디","스카피","앙몬드"];
  const seed = date * 31 + toMin(startT);
  const bays = Array.from({length:BAY_NAMES.length},(_,i)=>({
    no: i+1,
    name: BAY_NAMES[i] + "석",
    avail: ((i*7 + seed) % 5) !== 0, // ~80% available, shifts with seed
    mine: i===0, // 같은 시간·타석에 이미 내 예약이 있는 경우 (중복 예약 불가 — 정책 §1)
  }));

  const features = ["4K 프로젝터","좌타방","연결된 방","모션플레이트","코치존","주차가능"];

  const toggleReq = (id)=> setReq(r=>{
    const next = new Set(r);
    if (next.has(id)) next.delete(id); else next.add(id);
    return next;
  });

  const canNext = !!selectedBay;
  const storeName = store?.name || "퀀텀 아카데미 판교점";

  return (
    <div className="screen">
      <StatusBar/>
      <Appbar title="예약 정보" onBack={onBack}
        right={<button className="icon-btn" onClick={onClose}><Icon name="x" size={18}/></button>}/>

      <div className="scroll" style={{paddingBottom:160,background:"#fff"}}>
        {/* === 1. 매장 사진 — 등록 이미지 있으면 등록 이미지(실내/기기/가격표), 없으면 기본 이미지 === */}
        <StoreHero store={store} kicker="Training Bay" photoIdx={photoIdx} onDot={setPhotoIdx}/>

        {/* === 2. Store identity block === */}
        <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={{fontSize:18,fontWeight:800,letterSpacing:"-.02em",lineHeight:1.3}}>{storeName}</div>
              <div style={{display:"flex",alignItems:"center",gap:6,marginTop:5,fontSize:12,color:"var(--text-sub)"}}>
                <span style={{color:"var(--primary)",fontWeight:700}}>● 영업중</span>
                <span className="sdot"/>
                <span>전체 21대 운영</span>
              </div>
            </div>
            {/* rating pill */}
            <div style={{display:"flex",flexDirection:"column",alignItems:"center",padding:"6px 11px",borderRadius:10,background:"var(--primary-tint)"}}>
              <div style={{display:"flex",alignItems:"center",gap:3}}>
                <Icon name="star" size={12} style={{color:"var(--primary)"}}/>
                <span style={{fontSize:14,fontWeight:800,color:"var(--primary)"}}>4.9</span>
              </div>
              <div style={{fontSize:9.5,color:"var(--primary)",fontWeight:600,marginTop:1,letterSpacing:".02em"}}>리뷰 128</div>
            </div>
          </div>

          {/* features chips */}
          <div style={{display:"flex",gap:6,overflowX:"auto",scrollbarWidth:"none",marginTop:12,paddingBottom:2}}>
            {features.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>

        {/* === 3. Quick actions === */}
        <div style={{padding:"12px 20px 4px",display:"flex",gap:6}}>
          {[
            {icon:"phone",  label:"전화"},
            {icon:"location",label:"길찾기"},
            {icon:"share",  label:"공유"},
          ].map(a=>(
            <button key={a.label} 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={a.icon} size={16}/>
              <span style={{fontSize:11,fontWeight:600,color:"var(--text)"}}>{a.label}</span>
            </button>
          ))}
        </div>

        {/* === 4. Address & hours card === */}
        <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={{fontSize:13,lineHeight:1.5,color:"var(--text)",fontWeight:500}}>
                경기 성남시 분당구 판교역로 235<br/>
                <span style={{color:"var(--text-mute)",fontSize:11}}>(삼평동) 유스페이스1 지하 1층 126호</span>
              </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={{fontSize:12.5,lineHeight:1.65,color:"var(--text)",fontWeight:500}}>
                <span style={{display:"inline-block",width:42,color:"var(--text-sub)"}}>평일</span>09:30 ~ 익일 02:00<br/>
                <span style={{display:"inline-block",width:42,color:"var(--text-sub)"}}>주말</span>09:30 ~ 익일 01:00
              </div>
            </div>
          </div>
        </div>

        {/* === 5. 예약자 row === */}
        <div style={{padding:"16px 20px 0"}}>
          <button onClick={onEditUser} style={{width:"100%",display:"flex",alignItems:"center",justifyContent:"space-between",padding:"14px 14px",borderRadius:10,border:"1px solid var(--line)",background:"#fff",textAlign:"left"}}>
            <div style={{display:"flex",alignItems:"center",gap:10}}>
              <div style={{width:30,height:30,borderRadius:8,background:"var(--primary-tint)",color:"var(--primary)",display:"flex",alignItems:"center",justifyContent:"center"}}><Icon name="user" size={14}/></div>
              <div>
                <div style={{fontSize:10.5,color:"var(--text-sub)",fontWeight:600,letterSpacing:".02em"}}>예약자</div>
                <div style={{fontSize:13,fontWeight:700,marginTop:1}}>{(reserver?.name||"홍길동")} · {(reserver?.phone||"010-1234-5678")}</div>
              </div>
            </div>
            <Icon name="chev-r" size={14} style={{color:"var(--text-mute)"}}/>
          </button>
        </div>

        {/* divider */}
        <div style={{height:8,margin:"22px 0 0",background:"#F4F6F9"}}/>

        {/* 1일 예약 한도 안내 (정책 §1) */}
        <div style={{paddingTop:14}}><DailyLimitBanner count={todayCount} limit={limit} onCycle={onCycleLimit}/></div>

        {/* === 6. 예약 일정 === */}
        <div style={{padding:"22px 20px 4px"}}>
          <div style={{display:"flex",alignItems:"baseline",gap:6,marginBottom:14}}>
            <div style={{fontSize:16,fontWeight:800,letterSpacing:"-.01em"}}>예약 일정</div>
            <div style={{fontSize:11,color:"var(--text-mute)",fontWeight:500}}>· 한 사람 당 60분 기준</div>
          </div>

          {/* 날짜 */}
          <div style={{fontSize:12,fontWeight:700,color:"var(--text-sub)",marginBottom:10}}>날짜</div>
          <div style={{display:"grid",gridTemplateColumns:"repeat(7,1fr)",gap:4}}>
            {dayNums.map((n,i)=>{
              const on = date===n;
              const dayColor = i===0?"#EF4444":i===6?"#3B82F6":"var(--text-sub)";
              return (
                <button key={n} onClick={()=>setDate(n)} style={{
                  display:"flex",flexDirection:"column",alignItems:"center",gap:3,padding:"8px 0",
                  borderRadius:10,
                  background: on ? "var(--primary)" : "transparent",
                  color: on ? "#fff" : (i===0?"#EF4444":i===6?"#3B82F6":"var(--text)"),
                  border: on ? "none" : "1px solid transparent",
                }}>
                  <span style={{fontSize:10,fontWeight:600,color: on ? "rgba(255,255,255,.85)" : dayColor}}>{days[i]}</span>
                  <span style={{fontSize:15,fontWeight:800,lineHeight:1}}>{n}</span>
                </button>
              );
            })}
          </div>

          {/* 이용 시간 — start ~ end */}
          <div style={{display:"flex",alignItems:"center",justifyContent:"space-between",margin:"22px 0 10px"}}>
            <div style={{fontSize:12,fontWeight:700,color:"var(--text-sub)"}}>이용 시간</div>
            <div style={{fontSize:11,color: rangeValid?"var(--text-mute)":"#EF4444",fontWeight:600}}>
              {rangeValid ? `${Math.floor(durMin/60)}시간 ${durMin%60? (durMin%60+"분"):""}`.trim() : "시작보다 늦은 시간을 선택해 주세요"}
            </div>
          </div>
          <div style={{display:"flex",gap:8,alignItems:"center"}}>
            <button onClick={()=>setPickerOpen("start")} style={{
              flex:1,display:"flex",alignItems:"center",justifyContent:"space-between",
              padding:"12px 14px",borderRadius:10,
              background:"#fff",border:"1.5px solid var(--primary)"
            }}>
              <span style={{fontSize:12,fontWeight:700,color:"var(--primary)"}}>시작</span>
              <div style={{display:"flex",alignItems:"center",gap:4}}>
                <span style={{fontSize:15,fontWeight:800,color:"var(--text)",fontVariantNumeric:"tabular-nums"}}>{startT}</span>
                <Icon name="chev-d" size={12} style={{color:"var(--primary)"}}/>
              </div>
            </button>
            <div style={{width:8,height:1.5,background:"var(--line-strong)",flexShrink:0}}/>
            <button onClick={()=>setPickerOpen("end")} style={{
              flex:1,display:"flex",alignItems:"center",justifyContent:"space-between",
              padding:"12px 14px",borderRadius:10,
              background:"#fff",border:"1.5px solid " + (rangeValid?"var(--line-strong)":"#EF4444")
            }}>
              <span style={{fontSize:12,fontWeight:700,color:"var(--text-sub)"}}>종료</span>
              <div style={{display:"flex",alignItems:"center",gap:4}}>
                <span style={{fontSize:15,fontWeight:800,color:"var(--text-sub)",fontVariantNumeric:"tabular-nums"}}>{endT}</span>
                <Icon name="chev-d" size={12} style={{color:"var(--text-mute)"}}/>
              </div>
            </button>
          </div>
        </div>

        {/* === 7. 예약가능 타석 === */}
        <div style={{padding:"22px 20px 8px"}}>
          <div style={{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:12}}>
            <div style={{fontSize:16,fontWeight:800,letterSpacing:"-.01em"}}>
              예약 가능 타석 <span style={{color:"var(--primary)",marginLeft:2}}>{bays.filter(b=>b.avail).length}</span>
            </div>
            <button style={{display:"flex",alignItems:"center",gap:4,fontSize:11,color:"var(--text-sub)",background:"transparent",fontWeight:600}}>
              <Icon name="refresh" size={13}/> 새로고침
            </button>
          </div>

          <div style={{overflowX:"auto",margin:"0 -20px",padding:"0 20px 4px",scrollbarWidth:"none"}}>
            <div style={{display:"grid",gridTemplateRows:"1fr 1fr",gridAutoFlow:"column",gridAutoColumns:"108px",gap:8}}>
              {bays.map(b=>{
                const blocked = !b.avail || b.mine;
                const on = selectedBay?.no===b.no && !blocked;
                const statusColor = b.mine ? "#2563EB" : b.avail ? "var(--primary)" : "var(--text-mute)";
                return (
                  <button key={b.no} onClick={()=> !blocked && setSelectedBay(b)} style={{
                    textAlign:"left",padding:"10px 12px",borderRadius:10,
                    background: on ? "#fff" : (b.mine ? "#EEF3FF" : "var(--bg-soft)"),
                    border: on ? "1.5px solid var(--primary)" : (b.mine ? "1.5px solid #BFD3FF" : "1.5px solid transparent"),
                    boxShadow: on ? "0 4px 14px rgba(34,187,95,.18)" : "none",
                    opacity: blocked && !b.mine ? .55 : 1,
                    cursor: blocked ? "default" : "pointer",
                    transition:"box-shadow .15s",
                  }}>
                    <div style={{display:"flex",alignItems:"center",gap:4,fontSize:9.5,fontWeight:700,letterSpacing:".04em",color: statusColor}}>
                      <span style={{width:5,height:5,borderRadius:"50%",background: statusColor}}/>
                      {b.mine ? "내 예약" : b.avail ? "이용가능" : "마감"}
                    </div>
                    <div style={{fontSize:12,fontWeight:700,color:blocked && !b.mine ?"var(--text-mute)":"var(--text)",whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis",marginTop:6}}>
                      {b.name}
                    </div>
                    <div style={{fontSize:14,fontWeight:800,marginTop:3,color: b.mine ? "#2563EB" : (b.avail ? "var(--text)" : "var(--text-mute)"),fontVariantNumeric:"tabular-nums"}}>
                      {b.mine ? "예약중" : b.avail ? `${startT}~${endT}` : "—"}
                    </div>
                  </button>
                );
              })}
            </div>
          </div>
          <div style={{display:"flex",gap:4,marginTop:10,justifyContent:"flex-start"}}>
            <i style={{width:40,height:3,borderRadius:2,background:"#1A1C1F"}}/>
            <i style={{width:16,height:3,borderRadius:2,background:"#E5E7EB"}}/>
          </div>
        </div>

        {/* === 8. 요청사항 === */}
        <div style={{padding:"20px 20px 4px"}}>
          <div style={{fontSize:16,fontWeight:800,letterSpacing:"-.01em",marginBottom:12}}>요청사항 <span style={{fontSize:11,fontWeight:500,color:"var(--text-mute)",marginLeft:4}}>선택</span></div>
          <div style={{display:"flex",gap:8,flexWrap:"wrap"}}>
            {[
              {id:"left",label:"좌타방"},
              {id:"linked",label:"연결된 방"},
              {id:"coach",label:"코치 도움"},
            ].map(c=>{
              const on = req.has(c.id);
              return (
                <button key={c.id} onClick={()=>toggleReq(c.id)} style={{
                  display:"inline-flex",alignItems:"center",gap:6,padding:"9px 13px",borderRadius:999,
                  background: on ? "var(--primary-tint)" : "#fff",
                  border: on ? "1.5px solid var(--primary)" : "1.5px solid var(--line)",
                  color: on ? "var(--primary)" : "var(--text-sub)",
                  fontSize:13,fontWeight:600,
                }}>
                  <span style={{width:14,height:14,borderRadius:"50%",background:on?"var(--primary)":"transparent",border:on?"none":"1.5px solid var(--line-strong)",display:"flex",alignItems:"center",justifyContent:"center",color:"#fff"}}>
                    {on && <Icon name="check" size={9} stroke={3}/>}
                  </span>
                  {c.label}
                </button>
              );
            })}
          </div>
          <textarea value={note} onChange={e=>setNote(e.target.value.slice(0,100))}
            placeholder="추가 요청사항을 직접 입력해 주세요. (선택)"
            style={{width:"100%",marginTop:10,padding:"12px 14px",border:"1px solid var(--line)",borderRadius:10,outline:"none",resize:"none",fontSize:13,lineHeight:1.5,color:"var(--text)",background:"#fff",minHeight:64,fontFamily:"inherit"}}/>
        </div>

        {/* === 9. 예약 안내 (collapsible) === */}
        <div style={{padding:"14px 20px 24px"}}>
          <button onClick={()=>setPolicyOpen(!policyOpen)}
            style={{width:"100%",display:"flex",alignItems:"center",justifyContent:"space-between",padding:"14px 4px",background:"transparent",borderTop:"1px solid var(--line)",borderBottom:policyOpen?"none":"1px solid var(--line)"}}>
            <div style={{display:"flex",alignItems:"center",gap:6,fontSize:13,fontWeight:700}}>
              <Icon name="info" size={14} style={{color:"var(--text-sub)"}}/>
              예약 취소 및 페널티 안내
            </div>
            <Icon name={policyOpen?"chev-u":"chev-d"} size={14} style={{color:"var(--text-mute)"}}/>
          </button>
          {policyOpen && (
            <div style={{padding:"4px 4px 14px",fontSize:12.5,lineHeight:1.7,color:"var(--text-sub)",borderBottom:"1px solid var(--line)"}}>
              · 무료 취소는 예약 시간 60분 전까지 가능<br/>
              · 무료 취소 시간 경과 후에는 환불 불가 (이용권 예약은 차감 유지)<br/>
              · 노쇼 시 환불 불가·이용권 차감 유지, 누적 3회 시 선결제 전환<br/>
              · 같은 시간·타석 중복 예약은 불가하며, 하루 최대 2건까지 예약할 수 있어요
            </div>
          )}
        </div>
      </div>

      {/* === Sticky bottom: selected bay + CTA === */}
      <div style={{position:"absolute",bottom:0,left:0,right:0,background:"#fff",borderTop:"1px solid var(--line)",boxShadow:"0 -4px 16px rgba(0,0,0,.04)"}}>
        {selectedBay ? (
          <div style={{padding:"12px 20px 8px",display:"flex",alignItems:"center",gap:12}}>
            <div style={{width:36,height:36,borderRadius:8,background:"var(--primary-tint)",color:"var(--primary)",display:"flex",alignItems:"center",justifyContent:"center",fontSize:14,fontWeight:800,flexShrink:0}}>
              {selectedBay.name[0]}
            </div>
            <div style={{flex:1,minWidth:0}}>
              <div style={{fontSize:13.5,fontWeight:800,whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis"}}>{selectedBay.name}</div>
              <div style={{fontSize:11.5,color:"var(--text-sub)",marginTop:1,fontVariantNumeric:"tabular-nums"}}>{startT} ~ {endT} ({durMin}분)</div>
            </div>
            <button onClick={()=>setSelectedBay(null)} style={{background:"transparent",padding:4,color:"var(--text-mute)"}}><Icon name="x" size={16}/></button>
          </div>
        ) : (
          <div style={{padding:"14px 20px 8px",display:"flex",alignItems:"center",gap:8,color:"var(--text-mute)",fontSize:12.5}}>
            <Icon name="info" size={14}/>
            <span>예약할 타석을 선택해 주세요.</span>
          </div>
        )}
        <div style={{padding:"4px 20px 24px"}}>
          {limitReached && <div style={{fontSize:11.5,color:"var(--danger)",fontWeight:600,marginBottom:8,textAlign:"center"}}>오늘 예약 한도(2건)를 모두 사용했어요.</div>}
          <button className={"btn " + (canNext&&rangeValid&&!limitReached?"btn-primary":"btn-disabled")} style={{width:"100%"}}
            onClick={canNext&&rangeValid&&!limitReached ? ()=>onPickBay({date, startT, endT, bay:selectedBay}) : null}>다음</button>
        </div>
      </div>

      {pickerOpen && <TimePickerSheet onClose={()=>setPickerOpen(null)}
        title={pickerOpen==="start"?"시작 시간 선택":"종료 시간 선택"}
        value={pickerOpen==="start"?startT:endT}
        onApply={(v)=>{ if(pickerOpen==="start") setStartT(v); else setEndT(v); setPickerOpen(null); }}/>}
    </div>
  );
}

function BayTimeDetail({ onBack, onNext, bay, startHour }){
  const slots = [
    {id:"8-9",  label:"08:00 ~ 09:00", state:"avail"},
    {id:"12-13",label:"12:00 ~ 13:00", state:"avail"},
    {id:"14-15",label:"14:00 ~ 15:00", state:"done"},
  ];
  const [expanded, setExpanded] = React.useState("8-9");
  const [selected, setSelected] = React.useState("8-9");
  const [pickerOpen, setPickerOpen] = React.useState(false);
  const [pickerTarget, setPickerTarget] = React.useState("start");
  const [startT, setStartT] = React.useState("08:00");
  const [endT, setEndT] = React.useState("09:00");

  const canConfirm = !!selected;

  return (
    <div className="screen">
      <StatusBar/>
      <Appbar title={`${bay?.no || 120}번 라이언 냠냠석`} onBack={onBack}/>

      <div className="scroll" style={{padding:"8px 20px 100px"}}>
        <div style={{fontSize:18,fontWeight:800,letterSpacing:"-.02em",lineHeight:1.45,margin:"6px 0 22px"}}>
          예약이 가능한 시간대를 선택하면,<br/>범위 내에서 조정이 가능해요.
        </div>

        <div style={{display:"flex",flexDirection:"column",gap:10}}>
          {slots.map(s=>{
            const isDone = s.state==="done";
            const on = !isDone && selected===s.id;
            const open = expanded===s.id && on;
            return (
              <div key={s.id} style={{background:"var(--bg-soft)",borderRadius:10,overflow:"hidden",opacity:isDone?.7:1}}>
                <button onClick={()=>{ if(!isDone){ setSelected(s.id); setExpanded(expanded===s.id?null:s.id);} }}
                  style={{width:"100%",display:"flex",alignItems:"center",justifyContent:"space-between",padding:"18px 18px",background:"transparent"}}>
                  <div style={{fontSize:15,fontWeight:700,color:isDone?"var(--text-mute)":"var(--text)"}}>{s.label}</div>
                  <div style={{display:"flex",alignItems:"center",gap:6}}>
                    <div style={{fontSize:13,fontWeight:800,color:isDone?"var(--text-mute)":"var(--primary)"}}>
                      {isDone?"예약완료":"이용가능"}
                    </div>
                    <Icon name={open?"chev-u":"chev-d"} size={14} style={{color:isDone?"var(--text-mute)":"var(--primary)"}}/>
                  </div>
                </button>
                {open && (
                  <div style={{padding:"0 18px 18px",display:"flex",gap:10}}>
                    <button onClick={()=>{ setPickerTarget("start"); setPickerOpen(true); }} style={{
                      flex:1,padding:"12px 14px",borderRadius:8,background:"#fff",
                      border:"1.5px solid var(--primary)",display:"flex",alignItems:"center",justifyContent:"space-between"}}>
                      <div style={{display:"flex",alignItems:"center",gap:8}}>
                        <span style={{fontSize:13,fontWeight:700,color:"var(--primary)"}}>시작</span>
                        <span style={{fontSize:14,fontWeight:700}}>{startT}</span>
                      </div>
                      <Icon name="chev-d" size={12} style={{color:"var(--primary)"}}/>
                    </button>
                    <button onClick={()=>{ setPickerTarget("end"); setPickerOpen(true); }} style={{
                      flex:1,padding:"12px 14px",borderRadius:8,background:"#fff",
                      border:"1.5px solid var(--line-strong)",display:"flex",alignItems:"center",justifyContent:"space-between"}}>
                      <div style={{display:"flex",alignItems:"center",gap:8}}>
                        <span style={{fontSize:13,fontWeight:700,color:"var(--text-mute)"}}>종료</span>
                        <span style={{fontSize:14,fontWeight:700,color:"var(--text-mute)"}}>{endT}</span>
                      </div>
                      <Icon name="chev-d" size={12} style={{color:"var(--text-mute)"}}/>
                    </button>
                  </div>
                )}
              </div>
            );
          })}
        </div>
      </div>

      <div style={{position:"absolute",bottom:0,left:0,right:0,padding:"12px 20px 24px",background:"#fff"}}>
        <button className={"btn " + (canConfirm?"btn-primary":"btn-disabled")} style={{width:"100%"}}
          onClick={canConfirm ? ()=>onNext({startT, endT}) : null}>확인</button>
      </div>

      {pickerOpen && <TimePickerSheet onClose={()=>setPickerOpen(false)} title="시간 선택"
        value={pickerTarget==="start"?startT:endT}
        onApply={(v)=>{ if(pickerTarget==="start") setStartT(v); else setEndT(v); setPickerOpen(false); }}/>}
    </div>
  );
}

/* 시간 선택 시트 — 시(0~23)·분(10분 단위) 휠을 각각 스크롤/탭으로 선택 (기존 30분 단위 목록 대체) */
function TimePickerSheet({ onClose, title="시작시간 변경", value="11:30", onApply }){
  const ITEM = 44;                 // 휠 행 높이
  const PAD = ITEM * 2;            // 중앙 정렬용 위·아래 여백 (5행 표시)
  const H = ITEM * 5;
  const hours = Array.from({length:24},(_,i)=>i);
  const mins = [0,10,20,30,40,50];
  const parse = (v)=>{
    const m = String(v).match(/(\d{1,2}):(\d{2})/);
    if (!m) return [0,0];
    const h = Math.max(0, Math.min(23, +m[1]));
    const mi = Math.max(0, Math.min(50, Math.round((+m[2])/10)*10));
    return [h, mi];
  };
  const [initH, initM] = parse(value);
  const [hh, setHh] = React.useState(initH);
  const [mm, setMm] = React.useState(initM);
  const pad2 = (n)=>String(n).padStart(2,"0");

  function Wheel({ items, sel, onSel, fmt }){
    const ref = React.useRef(null);
    React.useEffect(()=>{
      const el = ref.current;
      if (el) el.scrollTop = Math.max(0, items.indexOf(sel)) * ITEM;
    // eslint-disable-next-line react-hooks/exhaustive-deps
    },[]);
    const settle = ()=>{
      const el = ref.current; if (!el) return;
      window.clearTimeout(settle._t);
      settle._t = window.setTimeout(()=>{
        const i = Math.max(0, Math.min(items.length-1, Math.round(el.scrollTop/ITEM)));
        if (items[i] !== sel) onSel(items[i]);
        el.scrollTo({top:i*ITEM, behavior:"smooth"});
      }, 90);
    };
    const pick = (it)=>{
      onSel(it);
      const el = ref.current;
      if (el) el.scrollTo({top:items.indexOf(it)*ITEM, behavior:"smooth"});
    };
    return (
      <div ref={ref} onScroll={settle} style={{height:H,overflowY:"auto",scrollbarWidth:"none",flex:1,scrollSnapType:"y mandatory",position:"relative",zIndex:1}}>
        <div style={{height:PAD}}/>
        {items.map(it=>(
          <button key={it} onClick={()=>pick(it)} style={{
            display:"flex",alignItems:"center",justifyContent:"center",width:"100%",height:ITEM,
            scrollSnapAlign:"center",background:"transparent",
            fontSize:24,fontWeight:700,fontVariantNumeric:"tabular-nums",
            color: it===sel ? "var(--text)" : "var(--text-mute)",
            opacity: it===sel ? 1 : .45,transition:"opacity .15s"
          }}>{fmt(it)}</button>
        ))}
        <div style={{height:PAD}}/>
      </div>
    );
  }

  return (
    <div style={{position:"absolute",inset:0,background:"rgba(0,0,0,.4)",display:"flex",alignItems:"flex-end",zIndex:30}} onClick={onClose}>
      <div onClick={e=>e.stopPropagation()} style={{background:"#fff",width:"100%",borderRadius:"16px 16px 0 0",padding:"20px 0 20px",display:"flex",flexDirection:"column"}}>
        <div style={{display:"flex",alignItems:"center",justifyContent:"space-between",padding:"0 20px 6px"}}>
          <div style={{fontSize:17,fontWeight:800}}>{title}</div>
          <button onClick={onClose} style={{background:"transparent",color:"var(--text-mute)"}}><Icon name="x" size={18}/></button>
        </div>

        {/* 시 · 분 휠 — 가운데 밴드가 선택 값 */}
        <div style={{position:"relative",display:"flex",gap:8,padding:"6px 28px"}}>
          <div style={{position:"absolute",left:28,right:28,top:6+PAD,height:ITEM,borderRadius:10,background:"var(--bg-soft)",zIndex:0}}/>
          <Wheel items={hours} sel={hh} onSel={setHh} fmt={(n)=>String(n)}/>
          <Wheel items={mins}  sel={mm} onSel={setMm} fmt={(n)=>pad2(n)}/>
        </div>

        <div style={{padding:"12px 20px 0"}}>
          <button className="btn btn-primary" style={{width:"100%"}}
            onClick={()=>onApply(`${pad2(hh)}:${pad2(mm)}`)}>{hh}:{pad2(mm)}으로 설정</button>
        </div>
      </div>
    </div>
  );
}

/* ============================================================
   LESSON booking — 담당프로 + 날짜 + 시작시간대 + 레슨시간 슬롯
   ============================================================ */

function LessonForm({ onBack, onClose, onNext, store, todayCount=0, limit=2, onCycleLimit }){
  const limitReached = todayCount >= limit;
  const [pro, setPro] = React.useState("조현진");
  const [date, setDate] = React.useState(3);
  const [startHour, setStartHour] = React.useState(9);
  const [slots, setSlots] = React.useState([
    {id:"9-915",  label:"09:00 ~ 09:15", dur:15},
    {id:"915-930",label:"09:15 ~ 09:30", dur:15},
  ]);
  const days = ["일","월","화","수","목","금","토"];
  const hours = [7,8,9,10];
  const canNext = slots.length>0;

  return (
    <div className="screen">
      <StatusBar/>
      <Appbar title="예약 확인" onBack={onBack}
        right={<button className="icon-btn" onClick={onClose}><Icon name="x" size={18}/></button>}/>

      <div className="scroll" style={{padding:"8px 20px 100px"}}>
        {/* 1일 예약 한도 안내 (정책 §1) */}
        <div style={{margin:"0 -20px"}}><DailyLimitBanner count={todayCount} limit={limit} onCycle={onCycleLimit}/></div>
        {/* 담당 프로 */}
        <div style={{marginTop:18}}>
          <div style={{fontSize:16,fontWeight:800,letterSpacing:"-.01em",marginBottom:14}}>담당 프로 선택</div>
          <div>
            <div style={{fontSize:11,color:"var(--text-sub)",marginBottom:4}}>프로</div>
            <div style={{display:"flex",alignItems:"center",justifyContent:"space-between",padding:"8px 0",borderBottom:"1.5px solid var(--line-strong)"}}>
              <div style={{fontSize:15,fontWeight:600}}>{pro}</div>
              <Icon name="chev-d" size={14} style={{color:"var(--text-mute)"}}/>
            </div>
          </div>
        </div>

        {/* 날짜 */}
        <div style={{marginTop:28}}>
          <div style={{fontSize:16,fontWeight:800,marginBottom:14}}>날짜</div>
          <div style={{display:"grid",gridTemplateColumns:"repeat(7,1fr)",gap:4,marginBottom:6}}>
            {days.map((d,i)=><div key={d} style={{textAlign:"center",fontSize:11,color:i===0?"#EF4444":i===6?"#3B82F6":"var(--text-mute)"}}>{d}</div>)}
          </div>
          <div style={{display:"grid",gridTemplateColumns:"repeat(7,1fr)",gap:4}}>
            {[1,2,3,4,5,6,7].map(n=>{
              const on = date===n;
              return (
                <button key={n} onClick={()=>setDate(n)} style={{
                  height:38,borderRadius:"50%",fontSize:15,fontWeight:700,
                  background: on ? "var(--primary)" : "transparent",
                  color: on ? "#fff" : (n===1?"#EF4444":n===7?"#3B82F6":"var(--text-mute)"),
                }}>{n}</button>
              );
            })}
          </div>
        </div>

        {/* 시작 시간대 */}
        <div style={{marginTop:24}}>
          <div style={{fontSize:16,fontWeight:800,marginBottom:12}}>시작 시간대</div>
          <div style={{display:"flex",gap:8}}>
            {hours.map(h=>{
              const on = startHour===h;
              return (
                <button key={h} onClick={()=>setStartHour(h)} style={{
                  flex:1,padding:"10px 0",borderRadius:999,fontSize:12,fontWeight:700,
                  border: on ? "1.5px solid var(--primary)" : "1px solid var(--line-strong)",
                  background: "#fff",
                  color: on ? "var(--primary)" : "var(--text-sub)",
                  display:"flex",alignItems:"center",justifyContent:"center",gap:4
                }}>
                  <svg viewBox="0 0 12 12" width="11" height="11"><path d="M3 10c0-2 1.5-3 3-3s3 1 3 3M6 3l-1 3h2z" fill={on?"var(--primary)":"#9CA3AF"}/></svg>
                  {String(h).padStart(2,"0")}:00
                </button>
              );
            })}
          </div>
        </div>

        {/* 레슨 시간 */}
        <div style={{marginTop:28}}>
          <div style={{fontSize:16,fontWeight:800,marginBottom:12}}>레슨 시간 <span style={{color:"var(--primary)"}}>{slots.length}</span></div>
          <div style={{display:"flex",flexDirection:"column",gap:8}}>
            {slots.map(s=>(
              <div key={s.id} style={{display:"flex",alignItems:"center",justifyContent:"space-between",padding:"14px 16px",background:"var(--bg-soft)",borderRadius:8}}>
                <div style={{fontSize:14,fontWeight:700}}>{s.label}</div>
                <div style={{display:"flex",alignItems:"center",gap:10}}>
                  <div style={{fontSize:13,fontWeight:800,color:"var(--primary)"}}>{s.dur}분</div>
                  <button onClick={()=>setSlots(slots.filter(x=>x.id!==s.id))} style={{background:"transparent",color:"var(--text-mute)"}}><Icon name="x" size={14}/></button>
                </div>
              </div>
            ))}
          </div>
        </div>
      </div>

      <div style={{position:"absolute",bottom:0,left:0,right:0,padding:"12px 20px 24px",background:"#fff"}}>
        {limitReached && <div style={{fontSize:11.5,color:"var(--danger)",fontWeight:600,marginBottom:8,textAlign:"center"}}>오늘 예약 한도(2건)를 모두 사용했어요.</div>}
        <button className={"btn " + (canNext&&!limitReached?"btn-primary":"btn-disabled")} style={{width:"100%"}}
          onClick={canNext&&!limitReached ? ()=>onNext({pro, date, slots}) : null}>다음</button>
      </div>
    </div>
  );
}

/* ============================================================
   이용권 체크 — 없으면 empty screen (구매유도), 있으면 선택
   ============================================================ */

function TicketCheck({ onBack, tickets=[], onBuy, onPick, type="레슨" }){
  const [empty, setEmpty] = React.useState(tickets.length===0);
  const [cat, setCat] = React.useState("all");
  const shown = tickets.filter(t => cat==="all" || ticketCat(t)===cat);
  return (
    <div className="screen">
      <StatusBar/>
      <Appbar title={`사용 가능한 ${type}권`} onBack={onBack}
        right={tickets.length>0 ? <button className="icon-btn" onClick={()=>setEmpty(e=>!e)} style={{fontSize:10,fontWeight:600,color:"var(--text-mute)",padding:"4px 6px",width:"auto"}}>(데모 {empty?"빈상태":"보유"})</button> : undefined}/>

      {empty ? (
        <>
          <div style={{flex:1,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",padding:"0 20px"}}>
            <svg viewBox="0 0 120 120" width="120" height="120" style={{marginBottom:18}}>
              <path d="M25 45c0-12 11-22 25-22h20c14 0 25 10 25 22s-11 22-25 22H55l-12 10v-10c-10-2-18-10-18-22z" fill="#E5E7EB"/>
              <circle cx="48" cy="45" r="4" fill="#fff"/>
              <circle cx="60" cy="45" r="4" fill="#fff"/>
              <circle cx="72" cy="45" r="4" fill="#fff"/>
            </svg>
            <div style={{fontSize:14,color:"var(--text-mute)"}}>사용 가능한 이용권이 없어요.</div>
          </div>
          <div style={{padding:"12px 20px 24px"}}>
            <button className="btn btn-primary" style={{width:"100%"}} onClick={onBuy}>{type}권 구매하기</button>
          </div>
        </>
      ) : (
        <div className="scroll" style={{padding:"12px 20px 100px"}}>
          <TicketCatChips cat={cat} setCat={setCat}/>
          <div style={{display:"flex",flexDirection:"column",gap:10}}>
            {shown.map(t=>(
              <button key={t.id} onClick={()=>onPick(t)} style={{textAlign:"left",padding:16,background:"var(--bg-soft)",borderRadius:10}}>
                <div style={{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:4}}>
                  <div style={{fontSize:11,color:"var(--text-sub)"}}>{t.kind}</div>
                  <div style={{fontSize:12,color:"var(--text-sub)"}}><span style={{color:"var(--primary)",fontWeight:800}}>{t.left}</span> {t.leftUnit}</div>
                </div>
                <div style={{display:"flex",alignItems:"center",gap:4}}>
                  <div style={{fontSize:15,fontWeight:800}}>{t.name}</div>
                  <Icon name="chev-r" size={12} style={{color:"var(--text-mute)"}}/>
                </div>
                <div style={{fontSize:12,color:"var(--text-sub)",marginTop:4,display:"flex",alignItems:"center",gap:4}}>
                  <svg viewBox="0 0 12 12" width="11" height="11"><path d="M3 10c0-2 1.5-3 3-3s3 1 3 3M6 3l-1 3h2z" fill="#9CA3AF"/></svg>
                  {t.store}
                </div>
                {t.progress != null && (
                  <>
                    <div style={{height:6,background:"#E5E7EB",borderRadius:3,marginTop:10,overflow:"hidden"}}>
                      <div style={{width:`${t.progress}%`,height:"100%",background:"var(--primary)"}}/>
                    </div>
                    <div style={{display:"flex",justifyContent:"space-between",marginTop:6,fontSize:11}}>
                      <span style={{color:"var(--primary)",fontWeight:700}}>{t.used}분 연습완료</span>
                      <span style={{color:"var(--text-sub)"}}>{t.remain}분 이용가능</span>
                    </div>
                  </>
                )}
              </button>
            ))}
            {shown.length===0 && <div style={{padding:"24px 0",textAlign:"center",fontSize:13,color:"var(--text-mute)"}}>해당 유형의 이용권이 없어요.</div>}
          </div>
          {/* 보유 목록에서도 신규 구매 가능 */}
          <button onClick={onBuy} style={{marginTop:16,width:"100%",height:46,borderRadius:10,background:"#fff",border:"1px solid var(--line-strong)",fontSize:13,fontWeight:700,color:"var(--text)",display:"flex",alignItems:"center",justifyContent:"center",gap:6}}>
            <span style={{fontSize:15,lineHeight:1}}>+</span> {type}권 신규 구매
          </button>
        </div>
      )}
    </div>
  );
}

/* ============================================================
   예약확인 (이용권 선택 포함 — expandable with more)
   ============================================================ */

function ReservationConfirm({ onBack, onClose, onSubmit, rows=[], tickets=[], onCollide }){
  const [selected, setSelected] = React.useState(tickets.length ? tickets[0] : null);
  const [expanded, setExpanded] = React.useState(false);
  const [sheetOpen, setSheetOpen] = React.useState(false);
  const canSubmit = !!selected;

  return (
    <div className="screen">
      <StatusBar/>
      <Appbar title="예약 확인" onBack={onBack}
        right={<button className="icon-btn" onClick={onClose}><Icon name="x" size={18}/></button>}/>

      <div className="scroll" style={{padding:"8px 20px 100px"}}>
        <div style={{fontSize:18,fontWeight:800,letterSpacing:"-.02em",lineHeight:1.45,margin:"6px 0 22px"}}>
          사용하실 이용권을<br/>선택해주세요.
        </div>

        {/* 이용권 select */}
        <div style={{marginBottom:24}}>
          <div style={{fontSize:11,color: selected?"var(--primary)":"var(--text-sub)",marginBottom:4}}>이용권 선택</div>
          <button onClick={()=> tickets.length && setSheetOpen(true)} style={{
            width:"100%",display:"flex",alignItems:"center",justifyContent:"space-between",
            padding:"8px 0",borderBottom:"1.5px solid " + (selected?"var(--line-strong)":"var(--line-strong)"),
            background:"transparent"
          }}>
            <span style={{fontSize:15,fontWeight:600,color: selected ? "var(--primary)" : "var(--text-mute)"}}>
              {selected ? selected.name : "보유 이용권이 없어요."}
            </span>
            <Icon name="chev-d" size={14} style={{color:"var(--text-mute)"}}/>
          </button>
        </div>

        {/* divider */}
        <div style={{height:6,margin:"0 -20px",background:"var(--bg)"}}/>

        {/* 예약 정보 */}
        <div style={{marginTop:20}}>
          <div style={{fontSize:15,fontWeight:800,marginBottom:14}}>예약 정보 <span style={{color:"var(--primary)"}}>{rows.length||3}</span></div>

          {(expanded ? rows : rows.slice(0,1)).map((r,i)=>(
            <div key={i} style={{marginBottom:20}}>
              {[
                ["매장명", r.store || "퀀텀 아카데미 판교점"],
                ["예약 타석", r.bay || "2번"],
                ["예약 날짜", r.date || "2023.12.29 (목)"],
                ["예약 시간", r.time || "08:00 ~ 09:00 (60분)"],
              ].map(([k,v])=>(
                <div key={k} style={{display:"flex",justifyContent:"space-between",padding:"10px 0",fontSize:14}}>
                  <div style={{color:"var(--text-sub)"}}>{k}</div>
                  <div style={{fontWeight:600}}>{v}</div>
                </div>
              ))}
              {i < rows.length-1 && <div style={{height:1,background:"var(--line)",margin:"4px 0"}}/>}
            </div>
          ))}

          {rows.length>1 && (
            <button onClick={()=>setExpanded(!expanded)} style={{width:"100%",textAlign:"center",padding:"10px 0",background:"transparent",fontSize:13,color:"var(--text-sub)",fontWeight:600,display:"flex",alignItems:"center",justifyContent:"center",gap:4}}>
              {expanded? "접기":"더보기"} <Icon name={expanded?"chev-u":"chev-d"} size={12}/>
            </button>
          )}
        </div>

        {/* 예약 유의사항 (정책 §1·5·6·7·8) */}
        <div style={{height:6,margin:"20px -20px 0",background:"var(--bg)"}}/>
        <div style={{marginTop:18}}>
          <div style={{fontSize:15,fontWeight:800,marginBottom:10}}>예약 유의사항</div>
          {[
            "이용권은 이용 시작 시간 도래 시 차감됩니다.",
            "매장 도착 후 QR 체크인으로 입장하며, 체크인 시 사용이 확정됩니다.",
            "무료 취소 마감 시간이 지난 뒤 취소하면 환불·이용권 복구가 되지 않습니다.",
            "예약 시간에 입장하지 않으면(노쇼) 이용권은 차감 유지됩니다. (기본 대기 15분)",
          ].map((t,i)=>(
            <div key={i} style={{display:"flex",gap:8,padding:"5px 0",fontSize:12.5,color:"var(--text-sub)",lineHeight:1.5}}>
              <span style={{color:"var(--text-mute)",fontWeight:700}}>·</span><span>{t}</span>
            </div>
          ))}
        </div>
      </div>

      <div style={{position:"absolute",bottom:0,left:0,right:0,padding:"12px 20px 24px",background:"#fff"}}>
        {onCollide && (
          <div style={{textAlign:"center",marginBottom:8}}>
            <button onClick={onCollide} style={{fontSize:9,color:"var(--text-mute)",background:"transparent",border:"1px dashed var(--line)",borderRadius:4,padding:"3px 6px",fontWeight:600}}>데모: 동시 예약 실패(선점 누락) 재현</button>
          </div>
        )}
        <button className={"btn " + (canSubmit?"btn-primary":"btn-disabled")} style={{width:"100%"}}
          onClick={canSubmit ? onSubmit : null}>예약 요청하기</button>
      </div>

      {sheetOpen && (
        <div style={{position:"absolute",inset:0,background:"rgba(0,0,0,.4)",display:"flex",alignItems:"flex-end",zIndex:30}} onClick={()=>setSheetOpen(false)}>
          <div onClick={e=>e.stopPropagation()} style={{background:"#fff",width:"100%",borderRadius:"16px 16px 0 0",padding:"20px 0 20px"}}>
            <div style={{display:"flex",alignItems:"center",justifyContent:"space-between",padding:"0 20px 18px"}}>
              <div style={{fontSize:16,fontWeight:800}}>이용권 선택</div>
              <button onClick={()=>setSheetOpen(false)} style={{background:"transparent",color:"var(--text-mute)"}}><Icon name="x" size={18}/></button>
            </div>
            <div>
              {tickets.map(t=>{
                const on = selected?.id===t.id;
                return (
                  <button key={t.id} onClick={()=>setSelected(t)} style={{display:"flex",alignItems:"center",justifyContent:"space-between",width:"100%",padding:"14px 20px",background:"transparent",textAlign:"left"}}>
                    <span style={{fontSize:15,fontWeight:on?700:500}}>{t.name}</span>
                    {on && <Icon name="check" size={16} style={{color:"var(--primary)"}}/>}
                  </button>
                );
              })}
            </div>
            <div style={{padding:"12px 20px 0"}}>
              <button className="btn btn-primary" style={{width:"100%"}} onClick={()=>setSheetOpen(false)}>적용</button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

/* ============================================================
   중복 예약 금지 / 1일 한도 / 선점·점유 실패 (정책 §1·§15)
   ============================================================ */

// 하루 예약 한도 안내 배너 — 정책 §1 (유저 1인당 1일 2건까지)
function DailyLimitBanner({ count, limit=2, onCycle }){
  const reached = count >= limit;
  return (
    <div style={{margin:"8px 20px 0",padding:"11px 14px",borderRadius:10,
      background: reached ? "#FEECEA" : "var(--bg-soft)",
      border: "1px solid " + (reached ? "#F8C6BF" : "var(--line)"),
      display:"flex",alignItems:"center",gap:10}}>
      <div style={{color: reached ? "var(--danger)" : "var(--text-sub)",flexShrink:0}}>
        <Icon name={reached ? "info" : "calendar"} size={16}/>
      </div>
      <div style={{flex:1,fontSize:12,lineHeight:1.5,color:"var(--text-sub)"}}>
        {reached
          ? <>오늘 예약 한도(<b style={{color:"var(--danger)"}}>{limit}건</b>)를 모두 사용했어요. 내일 다시 예약할 수 있어요.</>
          : <>오늘 <b style={{color:"var(--text)"}}>{count}건</b> 예약했어요 · 하루 최대 <b style={{color:"var(--text)"}}>{limit}건</b>까지 예약할 수 있어요.</>}
      </div>
      {onCycle && <button onClick={onCycle} style={{fontSize:9,color:"var(--text-mute)",background:"transparent",border:"1px dashed var(--line)",borderRadius:4,padding:"3px 5px",fontWeight:600,flexShrink:0}}>데모 {count}/{limit}</button>}
    </div>
  );
}

// 예약 실패 — 동시 체결 시 선점 누락 / 결제 중 점유 실패 / 중복 예약 (정책 §1·§15: 먼저 확정 우선)
function BookingFailed({ onRetry, onClose, reason }){
  return (
    <div className="screen">
      <StatusBar/>
      <Appbar title="예약 실패" onBack={onClose}/>
      <div className="scroll" style={{padding:"16px 20px 120px",textAlign:"center"}}>
        <div style={{width:88,height:88,borderRadius:"50%",background:"#FEECEA",display:"flex",alignItems:"center",justifyContent:"center",margin:"24px auto 0",color:"var(--danger)"}}>
          <Icon name="info" size={44}/>
        </div>
        <div className="h1" style={{marginTop:20}}>예약을 완료하지 못했어요</div>
        <div className="muted" style={{fontSize:13.5,marginTop:8,lineHeight:1.6}}>
          {reason || "방금 다른 고객이 먼저 예약을 확정했어요. 같은 시간대는 먼저 확정된 예약이 우선돼요. 다른 시간이나 타석을 선택해 주세요."}
        </div>
        <div style={{marginTop:20,padding:"14px 16px",background:"var(--bg-soft)",borderRadius:10,textAlign:"left",fontSize:12.5,color:"var(--text-sub)",lineHeight:1.7}}>
          · 결제 중 점유(10분) 시간 안에 결제가 완료되지 않으면 타석이 자동 해제됩니다.<br/>
          · 결제가 이미 진행된 경우 자동으로 취소·환불 처리됩니다.
        </div>
      </div>
      <div className="footer-bar" style={{display:"flex",gap:10}}>
        <button className="btn btn-outline" style={{flex:1}} onClick={onClose}>닫기</button>
        <button className="btn btn-primary" style={{flex:2}} onClick={onRetry}>다른 시간 선택</button>
      </div>
    </div>
  );
}

/* ============================================================
   Flow router
   ============================================================ */

const TRAINING_TICKETS = [
  {id:"tt1", kind:"정기 이용권", name:"FA 무제한 60분", store:"퀀텀 아카데미 판교점", left:"14", leftUnit:"회 남음"},
  {id:"tt2", kind:"시간제 이용권", name:"시간제 이용권 1,200분", store:"퀀텀 아카데미 판교점", left:"720", leftUnit:"분 남음", progress:40, used:480, remain:720},
];
const LESSON_TICKETS = [
  {id:"t1", kind:"정기이용권", name:"조현진 프로 레슨권", store:"퀀텀 아카데미 광교점", left:"1회(60분)", leftUnit:"남음"},
  {id:"t2", kind:"일일이용권", name:"한진선 프로 레슨권 100", store:"퀀텀 아카데미 판교점", left:"8일", leftUnit:"남음", progress:40, used:40, remain:60},
];

function BookingFlow({ onClose, goHome, onOpenReservation, initialType, initialStore, onLesson }){
  // 유형별 예약 폼 스텝
  const formStepFor = (t)=> t==="training" ? "training-form" : t==="lesson" ? "lesson-form" : "form";
  const [step, setStep] = React.useState(
    initialStore
      ? (initialType ? formStepFor(initialType) : "type")   // 매장 있음: 유형 알면 폼, 모르면(매장찾기 진입) 유형 선택 먼저
      : (initialType ? "store" : "type")
  );
  const [type, setType] = React.useState(initialType || "screen");
  const [store, setStore] = React.useState(initialStore || null);
  const [form, setForm] = React.useState(null);
  const [bayPick, setBayPick] = React.useState(null);
  const [lessonPick, setLessonPick] = React.useState(null);
  const [tickets, setTickets] = React.useState([]);
  const [toast, setToast] = React.useState(false);
  const [reserver, setReserver] = React.useState({name:"홍길동", phone:"010-1234-5678"});
  const [storeReturn, setStoreReturn] = React.useState(false); // 폼에서 매장 변경으로 진입했는지
  // 1일 예약 한도 (정책 §1: 유저 1인당 1일 2건) — 데모: 오늘 이미 1건 예약했다고 가정
  const LIMIT = 2;
  const [todayCount, setTodayCount] = React.useState(1);
  const cycleLimit = ()=> setTodayCount(c=> c>=LIMIT ? 0 : c+1);
  // 선점·점유 실패 시 돌아갈 폼 (정책 §1·§15)
  const retryStep = type==="training" ? "training-form" : type==="lesson" ? "lesson-form" : "form";

  const onStoreNext = ()=>{
    setStoreReturn(false);
    // training/lesson go into their own forms; screen uses generic form
    if (type==="training") setStep("training-form");
    else if (type==="lesson") { if (onLesson) { onLesson(); return; } setStep("lesson-form"); } // 레슨은 정본(레슨권→LessonFlow)으로 핸드오프
    else setStep("form");
  };

  const buildRows = ()=>{
    if (type==="training" && bayPick) {
      const toMin = (t)=>{ const [h,m] = t.split(":").map(Number); return h*60+m; };
      const dur = bayPick.startT && bayPick.endT ? (toMin(bayPick.endT)-toMin(bayPick.startT)) : 60;
      return [{
        store: store?.name, bay: bayPick.bay.name,
        date:"2023.12.29 (목)",
        time: bayPick.startT && bayPick.endT ? `${bayPick.startT} ~ ${bayPick.endT} (${dur}분)` : "—"
      }];
    }
    if (type==="lesson" && lessonPick) return lessonPick.slots.map(s=>({
      store: store?.name, bay: `프로 ${lessonPick.pro}`,
      date:"2023.12.29 (목)", time:`${s.label} (${s.dur}분)`
    }));
    return [{store: store?.name}];
  };

  // 폼에서 뒤로가기 목적지 — 매장찾기 진입(매장만 있음)은 유형 선택으로, 매장 미선택 진입은 매장 선택으로, 둘 다 지정된 딥링크는 닫기
  const backFromForm = (initialStore && initialType) ? onClose : (initialStore ? ()=>setStep("type") : ()=>setStep("store"));

  if (step==="type") return <BookingTypeSelect onBack={onClose} onNext={()=>{ if (type==="lesson" && onLesson) { onLesson(); return; } setStep(initialStore ? formStepFor(type) : "store"); }} selected={type} setSelected={setType}/>;
  // 매장 선택 — 매장찾기 탭과 동일한 StoreScreen을 예약 모드로 재사용 (UI·데이터 통일)
  if (step==="store") return <StoreScreen booking
    onBack={storeReturn ? ()=>{ setStoreReturn(false); setStep("form"); } : (initialType ? onClose : ()=>setStep("type"))}
    onPick={(s)=>{ setStore(s); onStoreNext(); }}/>;

  // SCREEN flow (game-type)
  if (step==="form") return <BookingForm onBack={backFromForm} onClose={onClose} onNext={()=>setStep("screen-confirm")} store={store} setForm={setForm} reserver={reserver} onEditUser={()=>setStep("form-edit-user")} onChangeStore={()=>{ setStoreReturn(true); setStep("store"); }} todayCount={todayCount} limit={LIMIT} onCycleLimit={cycleLimit}/>;
  if (step==="form-edit-user") return <BookingEdit onBack={()=>setStep("form")} reserver={reserver} onSave={(r)=>{ setReserver(r); setStep("form"); }}/>;
  if (step==="screen-confirm") return (
    <>
      {/* 예약 내역 확인 + 결제 병합 — App 결제는 여기서 결제까지 완료 (정책 §4) */}
      <BookingConfirm onBack={()=>setStep("form")} onClose={onClose} form={form} store={store} reserver={reserver}
        onPaid={()=>setStep("screen-done")}
        onOnsite={()=>{ setToast(true); setTimeout(goHome, 1500); }}
        onCollide={()=>setStep("failed")}/>
      {toast && <div className="toast"><span>예약 요청이 완료되었습니다. (현장 결제)</span></div>}
    </>
  );
  if (step==="screen-done") return <ScreenDone store={store} form={form} reserver={reserver}
    onHome={goHome}
    onReservations={()=>{
      // 방금 만든 예약의 상세로 이동 (홈이 아니라 예약 상세)
      if (!onOpenReservation) { goHome(); return; }
      const d = new Date(); d.setDate(d.getDate() + (form?.date || 0));
      const dText = `${d.getMonth()+1}월 ${d.getDate()}일`;
      const productText = (Array.isArray(form?.product) ? form.product : [form?.product||"Q"]).map(c=>c==="T2"?"T2":"Quantum").join(" · ");
      onOpenReservation({
        d: dText,
        t: form?.startT || form?.time || "13:00",
        pro: `${productText} · ${store?.name || "퀀텀 아카데미 판교점"}`,
        tag: "스크린",
        status: "예약완료",
        store: store?.name || "퀀텀 아카데미 판교점",
      });
    }}/>;

  // TRAINING flow
  if (step==="training-form") return <TrainingForm onBack={backFromForm} onClose={onClose} store={store}
    reserver={reserver} onEditUser={()=>setStep("training-edit-user")}
    onPickBay={(b)=>{ setBayPick(b); setStep("training-ticket-empty"); }}
    todayCount={todayCount} limit={LIMIT} onCycleLimit={cycleLimit}/>;
  if (step==="training-edit-user") return <BookingEdit onBack={()=>setStep("training-form")} reserver={reserver} onSave={(r)=>{ setReserver(r); setStep("training-form"); }}/>;
  if (step==="training-ticket-empty") return <TicketCheck type="트레이닝" tickets={TRAINING_TICKETS}
    onBack={()=>setStep("training-form")}
    onBuy={()=>setStep("training-ticket-buy")}
    onPick={(t)=>{ setTickets([t]); setStep("training-confirm"); }}/>;
  if (step==="training-ticket-buy") return <TicketPurchase type="트레이닝" onBack={()=>setStep("training-ticket-empty")}
    onPurchased={(t)=>{ setTickets([t]); setStep("training-confirm"); }}/>;
  if (step==="training-confirm") return (
    <>
      <ReservationConfirm onBack={()=>setStep("training-form")} onClose={onClose}
        rows={buildRows()} tickets={tickets}
        onSubmit={()=>{ setToast(true); setTimeout(goHome, 1500); }}
        onCollide={()=>setStep("failed")}/>
      {toast && <div className="toast"><span>예약 요청이 완료되었습니다.</span></div>}
    </>
  );

  // LESSON flow
  if (step==="lesson-form") return <LessonForm onBack={backFromForm} onClose={onClose} store={store}
    onNext={(f)=>{ setLessonPick(f); setStep("lesson-ticket"); }}
    todayCount={todayCount} limit={LIMIT} onCycleLimit={cycleLimit}/>;
  if (step==="lesson-ticket") {
    const myTickets = LESSON_TICKETS; // pretend user has these
    // if empty: go to empty state; else proceed straight to confirm (tickets passed)
    if (myTickets.length===0) {
      return <TicketCheck type="레슨" tickets={[]} onBack={()=>setStep("lesson-form")}
        onBuy={()=>setStep("lesson-ticket-buy")} onPick={()=>{}}/>;
    }
    return <TicketCheck type="레슨" tickets={myTickets} onBack={()=>setStep("lesson-form")}
      onBuy={()=>setStep("lesson-ticket-buy")}
      onPick={(t)=>{ setTickets([t, ...myTickets.filter(x=>x.id!==t.id)]); setStep("lesson-confirm"); }}/>;
  }
  if (step==="lesson-ticket-buy") return <TicketPurchase type="레슨" onBack={()=>setStep("lesson-ticket")}
    onPurchased={(t)=>{ setTickets([t]); setStep("lesson-confirm"); }}/>;
  if (step==="lesson-confirm") return (
    <>
      <ReservationConfirm onBack={()=>setStep("lesson-ticket")} onClose={onClose}
        rows={buildRows()} tickets={tickets.length?tickets:LESSON_TICKETS}
        onSubmit={()=>{ setToast(true); setTimeout(goHome, 1500); }}
        onCollide={()=>setStep("failed")}/>
      {toast && <div className="toast"><span>예약 요청이 완료되었습니다.</span></div>}
    </>
  );

  // 예약 실패 — 선점 누락 / 점유 실패 / 중복 (정책 §1·§15)
  if (step==="failed") return <BookingFailed onClose={onClose} onRetry={()=>setStep(retryStep)}/>;

  return null;
}

/* simple purchase stub */
function TicketPurchase({ onBack, type, onPurchased }){
  const plans = [
    {id:"p1", name:`${type}권 10회`, price:"150,000원", desc:"60분 × 10회 · 3개월 유효"},
    {id:"p2", name:`${type}권 20회`, price:"280,000원", desc:"60분 × 20회 · 6개월 유효", tag:"인기"},
    {id:"p3", name:`${type}권 30회`, price:"390,000원", desc:"60분 × 30회 · 9개월 유효"},
  ];
  const [sel, setSel] = React.useState(plans[1].id);
  return (
    <div className="screen">
      <StatusBar/>
      <Appbar title={`${type}권 구매`} onBack={onBack}/>
      <div className="scroll" style={{padding:"8px 20px 100px"}}>
        <div style={{fontSize:18,fontWeight:800,letterSpacing:"-.02em",lineHeight:1.45,margin:"6px 0 22px"}}>
          이용권을 선택해주세요.
        </div>
        <div style={{display:"flex",flexDirection:"column",gap:10}}>
          {plans.map(p=>{
            const on = sel===p.id;
            return (
              <button key={p.id} onClick={()=>setSel(p.id)} style={{
                textAlign:"left",padding:16,borderRadius:10,background:"#fff",
                border: on ? "1.5px solid var(--primary)" : "1.5px solid var(--line)",
              }}>
                <div style={{display:"flex",alignItems:"center",gap:8,marginBottom:6}}>
                  <div style={{fontSize:15,fontWeight:800}}>{p.name}</div>
                  {p.tag && <span className="chip" style={{background:"var(--primary-tint,#DCFCE7)",color:"var(--primary)",fontSize:10,fontWeight:700,padding:"2px 8px"}}>{p.tag}</span>}
                </div>
                <div style={{fontSize:12,color:"var(--text-sub)",marginBottom:8}}>{p.desc}</div>
                <div style={{fontSize:18,fontWeight:800,color:on?"var(--primary)":"var(--text)"}}>{p.price}</div>
              </button>
            );
          })}
        </div>
      </div>
      <div style={{position:"absolute",bottom:0,left:0,right:0,padding:"12px 20px 24px",background:"#fff"}}>
        <button className="btn btn-primary" style={{width:"100%"}}
          onClick={()=>{ const p=plans.find(x=>x.id===sel); onPurchased({id:"purchased", kind:"정기이용권", name:p.name, store:"퀀텀 아카데미 판교점", left:p.name.match(/\d+회/)[0], leftUnit:"남음"}); }}>
          결제하기
        </button>
      </div>
    </div>
  );
}

function ScreenDone({ store, form, reserver, onHome, onReservations }){
  const f = form || {};
  return (
    <div className="screen">
      <StatusBar/>
      <Appbar title="예약 완료" onBack={onHome}/>
      <div className="scroll" style={{padding:"16px 20px 120px",textAlign:"center"}}>
        <div className="circle-ok bump" style={{marginTop:24}}><Icon name="check" size={42} stroke={2.6}/></div>
        <div className="h1" style={{marginTop:20}}>결제 완료 · 예약 확정</div>
        <div className="muted" style={{fontSize:13,marginTop:6}}>예약 시간 10분 전까지 매장으로 와주세요</div>
        <div className="card" style={{marginTop:24,padding:18,textAlign:"left"}}>
          <div style={{display:"flex",alignItems:"center",gap:10,marginBottom:14}}>
            <span className="chip chip-primary">CONFIRMED</span>
            <span className="mono" style={{fontSize:11,color:"var(--text-mute)"}}>Q-{Date.now().toString().slice(-6)}</span>
          </div>
          <div style={{fontWeight:700,fontSize:15.5,color:"var(--text)"}}>{store?.name || "퀀텀 아카데미 판교점"}</div>
          <div className="muted" style={{fontSize:12.5,marginTop:4}}>{(Array.isArray(f.product) ? f.product : [f.product||"Q"]).map(c=>c==="T2"?"T2":"Quantum").join(" · ")} · {f.people?`${f.people}명`:"1명"}</div>
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:14,marginTop:16,padding:"14px 0 0",borderTop:"1px dashed var(--line)"}}>
            <div><div className="label">예약자</div><div className="val" style={{marginTop:3}}>{reserver?.name||"홍길동"}</div></div>
            <div><div className="label">결제</div><div className="val" style={{marginTop:3,color:"var(--primary)"}}>App 결제 완료</div></div>
          </div>
        </div>
      </div>
      <div className="footer-bar" style={{display:"flex",gap:10}}>
        <button className="btn btn-outline" style={{flex:1}} onClick={onHome}>홈으로</button>
        <button className="btn btn-primary" style={{flex:2}} onClick={onReservations}>내 예약 보기</button>
      </div>
    </div>
  );
}

Object.assign(window, { BookingTypeSelect, BookingForm, BookingConfirm, BookingEdit, BookingFlow, TrainingForm, LessonForm, BayTimeDetail, TicketCheck, ReservationConfirm, TicketPurchase, ScreenDone, DailyLimitBanner, BookingFailed });
