// 스크린 B — 모임 상세 · 이용수칙 모달 · 재확인 시트 · 채팅방 · 호스트 프로필
function ScrDetail({S, set, go}) {
  const m = MEETUPS[S.detailId] || S.tempDetail || null;
  if (!m) return <MeetupNotFoundNotice go={go}/>;
  if (!meetupVisibleTo(m, S.viewAsUser)) return <MeetupBlockedNotice go={go}/>;
  const full = effectiveJoined(m) >= m.capMax;
  const status = S.joined[m.id];
  const joined = status==='waitlisted', confirmed = status==='confirmed';
  const previewNames = ATTENDEES.slice(0, Math.min(4, m.capJoined||3));
  const [companionOpen, setCompanionOpen] = React.useState(false);
  return <div className="scr">
    {m.lat?<div style={{position:'relative'}}>
      <MapEmbed lat={m.lat} lng={m.lng} height={150}/>
      <button className="iconbtn" aria-label="뒤로" style={{position:'absolute', top:10, left:10, background:'rgba(255,255,255,.9)'}} onClick={()=>go('home')}><Ic n="IconNormalChevronLeftNameChevronLeftTightFalseThick" s={20}/></button>
      {m.sponsor&&<span className="chip orange" style={{position:'absolute', top:12, right:12, background:'var(--c-bg)'}}><Ic n="IconNormalMegaphoneNameMegaphoneFillFalse" s={13}/>{m.sponsor}</span>}
    </div>:<div className="pad" style={{paddingTop:14, paddingBottom:0}}>
      <button className="iconbtn" aria-label="뒤로" onClick={()=>go('home')}><Ic n="IconNormalChevronLeftNameChevronLeftTightFalseThick" s={20}/></button>
    </div>}
    <div className="pad" style={{paddingTop:m.lat?16:6}}>
      <h1 style={{fontSize:20, fontWeight:800, margin:'0 0 10px', letterSpacing:'-.01em'}}>{m.title}</h1>
      <div style={{display:'flex', gap:5, flexWrap:'wrap', marginBottom:12}}>{m.tags.map(t=><Chip key={t[0]} label={t[0]} tone={t[1]}/>)}</div>
      <div style={{display:'flex', gap:6, marginBottom:16}}>
        {full?<Chip label="정원 마감 · 대기 가능" tone="orange"/>:null}
      </div>
      {m.soloWelcome&&<div className="notice" style={{marginBottom:16}}><Ic n="IconNormalHeartNameHeartFillFalse" s={16} c="var(--c-violet)"/><span>혼자 오시는 분도 편하게 어울릴 수 있도록 진행해요.</span></div>}
      <div className="card" style={{marginBottom:16}}>
        <InfoRow icon="IconNormalCalendarNameCalendar">{m.when}</InfoRow>
        <InfoRow icon="IconNormalLocation2NameLocationFillFalse">{m.region} · {m.place}</InfoRow>
        <InfoRow icon="IconNormalTicketNameTicketFillFalse">{m.fee}</InfoRow>
        <CapacityBar m={m}/>
      </div>
      <button className="card" style={{width:'100%', display:'flex', gap:12, alignItems:'center', cursor:'pointer', fontFamily:'inherit', textAlign:'left', marginBottom:14}} onClick={()=>go('host')}>
        <Av name={m.host.name} size={44} tone="p"/>
        <span style={{flex:1}}>
          <b style={{fontSize:14.5}}>호스트 · {m.host.name}</b>
          <span style={{display:'flex', gap:5, marginTop:5, flexWrap:'wrap'}}>{m.host.badges.slice(0,2).map(b=><Chip key={b} label={b} tone="green"/>)}</span>
        </span>
        <span className="meta">후기 {m.host.reviews} <Ic n="IconNormalChevronRightNameChevronRightTightFalseThick" s={12}/></span>
      </button>
      <p style={{fontSize:14, lineHeight:1.65, color:'var(--c-sub)', margin:'0 0 16px'}}>{m.desc}</p>
      <div className="card" style={{marginBottom:16}}>
        <b style={{fontSize:13.5}}>참가 예정 멤버</b>
        <div className="row" style={{gap:-6, marginTop:10}}>
          <div style={{display:'flex'}}>{previewNames.map((n,i)=><span key={n} style={{marginLeft:i?-10:0, border:'2px solid var(--c-bg)', borderRadius:'50%'}}><Av name={n} size={32}/></span>)}</div>
          <span className="meta" style={{marginLeft:8}}>정원 {m.capMax}명 중 {effectiveJoined(m)}명 참여 확정</span>
        </div>
      </div>
      <CompanionInfoCard/>
      <div className="card" style={{marginBottom:16}}>
        <b style={{fontSize:13.5}}>모임 이용 안내</b>
        <div style={{marginTop:8, display:'flex', flexDirection:'column', gap:7}}>
          <InfoRow icon="IconNormalTicketNameTicketFillFalse">예상 개인 비용 — 식사·음료 등은 현장에서 각자 결제해요</InfoRow>
          <InfoRow icon="IconNormalCircleInfo2NameCircleInfoFillFalse">취소 조건 — 24시간 전까지 무료 취소</InfoRow>
          <InfoRow icon="IconNormalImageNameImage">사진 촬영 — 참가자 동의 시에만 SNS 게시</InfoRow>
        </div>
      </div>
      <div className="notice orange" style={{marginBottom:16}}><Ic n="IconNormalBell2NameBellFillFalse" s={16}/><span>참가 확정 후, 행사 24시간 전에 참석 여부를 다시 한 번 확인해드려요. 미응답 시 대기자에게 자리가 넘어갈 수 있어요.</span></div>
      {joined&&<div className="notice blue" style={{marginBottom:16}}><Ic n="IconNormalCircleCheck2NameCircleCheckFillFillTrue" s={16}/><span><b>대기 {myWaitlistPosition(m.id,S)||1}번째로 등록됐어요.</b> 자리가 나면 바로 알림을 드리고, 채팅방이 자동으로 열려요.</span></div>}
      {confirmed&&<div className="notice blue" style={{marginBottom:16}}><Ic n="IconNormalCircleCheck2NameCircleCheckFillFillTrue" s={16}/><span><b>참가 확정!</b> 참가자 채팅방이 열렸어요. 호스트의 환영 메시지를 확인해보세요.</span></div>}
    </div>
    <div className="pad" style={{position:'sticky', bottom:0, background:'var(--c-bg)', padding:'8px 18px 14px', borderTop:'1px solid var(--c-line)'}}>
      <CompanionAskLink onOpen={()=>setCompanionOpen(true)} style={{padding:'2px 2px 8px'}}/>
      {joined||confirmed
        ?<DSBtn label={confirmed?'채팅방 열기':`대기 등록 완료 · 순번 ${myWaitlistPosition(m.id,S)||1}번`} variant={confirmed?'solid':'outlined'} color={confirmed?'primary':'assistive'} onClick={confirmed?()=>go('chat',{detailId:m.id}):undefined}/>
        :<DSBtn label={full?'대기 명단 신청하기 (정원 마감)':'참가 신청하기'} onClick={()=>set({rulesOpen:true})}/>}
    </div>
    {companionOpen&&<div className="overlay" onClick={()=>setCompanionOpen(false)}>
      <div className="sheet" onClick={e=>e.stopPropagation()}>
        <h2 style={{fontSize:17,margin:'0 0 10px'}}>친구와 함께 참여하고 싶나요?</h2>
        <p style={{fontSize:13.5,color:'var(--c-sub)',lineHeight:1.6,margin:'0 0 10px'}}>참가자는 각자 가입하고 신청하는 것을 권장해요. 가입하지 않은 지인과 함께하고 싶다면 모임 채팅에서 주최자에게 먼저 문의해주세요. 동반자는 주최자 승인 후 정원에 포함됩니다.</p>
        <p style={{fontSize:12,color:'var(--c-faint)',lineHeight:1.6,margin:'0 0 16px'}}>사전 승인 없이 지인을 데려오는 경우 현장에서 참여가 어려울 수 있어요.</p>
        {confirmed?<DSBtn label="모임 채팅에서 문의하기" onClick={()=>{setCompanionOpen(false); go('chat',{detailId:m.id});}}/>:<DSBtn label="확인했어요" variant="outlined" color="assistive" onClick={()=>setCompanionOpen(false)}/>}
      </div>
    </div>}
  </div>;
}
function RulesModal({S, set, go}) {
  const m = MEETUPS[S.detailId] || S.tempDetail || MEETUPS.m1;
  const full = effectiveJoined(m) >= m.capMax;
  const conflict = findScheduleConflict(S, S.detailId);
  const rules = ['서로 존중해주세요. 나이·학교·국가와 상관없이 예의를 지켜주세요.','과도한 스킨십은 금지돼 있어요.','식사·음료 등 개인 비용은 각자 결제하는 게 기본이에요. (스폰서 모임 예외)','노쇼 시 다음 모임 신청이 제한될 수 있어요.','불편한 상황에는 신고하기 — 성희롱·폭언·영업·다단계·사기·스토킹·사진 무단 게시 등 유형별로 접수돼요.','모임 사진은 참가자 동의 없이 SNS에 올릴 수 없어요.'];
  return <div className="overlay" onClick={()=>set({rulesOpen:false})}>
    <div className="sheet" onClick={e=>e.stopPropagation()}>
      <h2 style={{fontSize:18, margin:'0 0 4px'}}>함께 즐거운 모임을 위해</h2>
      <div className="meta" style={{marginBottom:16}}>{m.title} · {m.when}</div>
      {m.purposes&&m.purposes.length>1&&<div className="notice" style={{marginBottom:14}}><Ic n="IconNormalCircleInfo2NameCircleInfoFillFalse" s={15}/><span>이 모임은 <b>{m.purposes.join(' · ')}</b> 여러 활동으로 진행돼요. 일부 활동만 참여하고 싶다면 신청 후 채팅방에서 주최자에게 미리 알려주세요 — 부분 참여 조율은 참가자와 주최자가 직접 나눠요.</span></div>}
      <ScheduleConflictNotice conflict={conflict} ack={!!S.scheduleAck} onAck={v=>set({scheduleAck:v})}/>
      {rules.map((r,i)=><div key={i} className="rule"><span className="rulenum">{i+1}</span><span>{r}</span></div>)}
      <button style={{background:'none', border:'none', color:'var(--c-primary)', fontFamily:'inherit', fontSize:12.5, padding:'2px 0 14px', cursor:'pointer'}} onClick={()=>set({policyOpen:!S.policyOpen})}>{S.policyOpen?'안전정책 접기':'전체 안전정책 자세히 보기'}</button>
      {S.policyOpen&&<div style={{background:'var(--c-fill-a)', borderRadius:10, padding:'12px 14px', margin:'-4px 0 14px', fontSize:12.5, color:'var(--c-sub)', lineHeight:1.75}}>
        <b style={{display:'block', marginBottom:6, color:'var(--c-text)'}}>신뢰·안전 정책 (PRD 8장)</b>
        신고 유형 — 성희롭/폭언/영업·다단계/사기/스토킹/사진 무단 게시/기타로 분류되어 접수되고, 긴급 신고는 일반 불편 신고보다 우선 처리돼요.<br/>
        차단 시 상대에게 내 프로필과 참가 예정 모임이 보이지 않도록 처리돼요.<br/>
        신고 접수 후에는 임시 신청 제한이 검토되고, 채팅 기록은 신고 처리를 위한 최소 기간만 보관돼요.<br/>
        음주 모임은 연령 제한과 신분 확인 절차가 적용되며, 서비스는 안전을 보장하지 않지만 이 보호 조치들을 함께 제공해요.
      </div>}
      <label className="row" style={{gap:8, marginBottom:10, cursor:'pointer', fontSize:13.5}}>
        <input type="checkbox" checked={S.ruleCheck||false} onChange={e=>set({ruleCheck:e.target.checked})} style={{width:18, height:18, accentColor:'var(--c-primary)'}}/>
        위 이용수칙에 동의하고 참가할게요
      </label>
      {m.photoPromoConsent&&<div className="notice" style={{marginBottom:14}}><Ic n="IconNormalImageNameImage" s={15}/><span>이 모임에서 찍는 사진이 모임 후기 게시물에 올라오면, 운영진이 SNS 홍보에 활용할 수 있어요. 후기에 올리지 않으면 홍보에 쓰이지 않아요.</span></div>}
      <DSBtn label={full?'대기 명단 확정하기':(m.approvalMode==='approval'?'참가 신청하기 (승인 대기)':'참가 확정하기')} disable={!S.ruleCheck||(!!conflict&&!S.scheduleAck)} onClick={()=>{
        if (!full && S.joined[m.id]!=='confirmed') m.capJoined=(m.capJoined||0)+1;
        const status = full?'waitlisted':(m.approvalMode==='approval'?'pending':'confirmed');
        const patch = {rulesOpen:false, scheduleAck:false, joined:{...S.joined,[m.id]:status}};
        if (full) {
          patch.waitlists = joinWaitlist(m.id, S);
          const pos = myWaitlistPosition(m.id, {waitlists:patch.waitlists}) || (patch.waitlists[m.id]||[]).length;
          patch.toast = `대기 ${pos}번째로 등록됐어요`;
        } else {
          patch.toast = status==='pending' ? '신청이 접수됐어요 — 모임장 승인을 기다려주세요' : '참가가 확정됐어요 — 채팅방이 열렸어요';
        }
        set(patch);
      }}/>
    </div>
  </div>;
}
function meetupWindow(m) {
  if (!m || !m.startsAt) return null;
  const start = new Date(m.startsAt);
  if (isNaN(start)) return null;
  const end = new Date(start.getTime() + (m.durationHours||2)*3600000);
  return {start, end};
}
function formatTimeShort(d) {
  const h = d.getHours(), ap = h<12?'오전':'오후', h12 = h%12===0?12:h%12;
  return `${ap} ${h12}시${d.getMinutes()?':'+String(d.getMinutes()).padStart(2,'0'):''}`;
}
// 참가 예정인 다른 모임과 시간이 겹치는지 확인 — 겹쳐도 막지 않고, 사용자가 알고 참가할 수 있게 경고만 해요.
function findScheduleConflict(S, targetId) {
  const target = MEETUPS[targetId] || S.tempDetail;
  const tw = meetupWindow(target);
  if (!tw) return null;
  const activeIds = Object.keys(S.joined||{}).filter(id=>id!==targetId && S.joined[id] && S.joined[id]!=='waitlisted' && !(S.completed||[]).includes(id));
  for (const id of activeIds) {
    const other = MEETUPS[id];
    const ow = meetupWindow(other);
    if (!ow) continue;
    if (tw.start < ow.end && ow.start < tw.end) {
      return {other, otherWindow:ow};
    }
  }
  return null;
}
function ScheduleConflictNotice({conflict, ack, onAck}) {
  if (!conflict) return null;
  return <div style={{background:'var(--c-orange-bg)', borderRadius:10, padding:'12px 14px', margin:'-4px 0 14px'}}>
    <div className="row" style={{gap:8, marginBottom:6}}><Ic n="IconNormalCircleExclamation2NameCircleExclamationFillFalse" s={16} c="var(--c-orange)"/><b style={{fontSize:13, color:'var(--c-orange)'}}>일정이 겹쳐요</b></div>
    <p style={{fontSize:12.5, color:'var(--c-sub)', margin:'0 0 10px', lineHeight:1.6}}>이미 참가 예정인 <b>&ldquo;{conflict.other.title}&rdquo;</b>({formatTimeShort(conflict.otherWindow.start)}~{formatTimeShort(conflict.otherWindow.end)})과 시간이 겹쳐요. 두 모임 모두 온전히 참석하기 어려울 수 있어요.</p>
    <label className="row" style={{gap:8, cursor:'pointer', fontSize:12.5}}>
      <input type="checkbox" checked={ack} onChange={e=>onAck(e.target.checked)} style={{width:16, height:16, accentColor:'var(--c-orange)'}}/>
      알고 있어요 — 일정을 조율해서 참가할게요 (한쪽에서 일찍 나가는 등)
    </label>
  </div>;
}
function ReconfirmSheet({S, set, go}) {
  const id = S.detailId;
  const m = MEETUPS[id] || (S.tempDetail && S.tempDetail.id===id ? S.tempDetail : null) || MEETUPS.m1;
  const waitingCount = ((S.waitlists&&S.waitlists[id])||[]).length;
  return <div className="overlay">
    <div className="sheet">
      <div className="row" style={{gap:8, marginBottom:8}}><Ic n="IconNormalBell2NameBellFillFillTrue" s={20} c="var(--c-orange)"/><b style={{fontSize:12.5, color:'var(--c-orange)'}}>행사 24시간 전 · 참석 재확인</b></div>
      <h2 style={{fontSize:18, margin:'0 0 6px'}}>{m.when}, {m.title}에 참석하시나요?</h2>
      <p style={{fontSize:13.5, color:'var(--c-sub)', margin:'0 0 6px', lineHeight:1.6}}>미응답 시 자리가 대기자에게 자동으로 전달될 수 있어요. {waitingCount>0?`지금 대기 중인 분이 ${waitingCount}명 있어요.`:'지금은 대기 중인 분이 없어요.'}</p>
      <p style={{fontSize:12.5, color:'var(--c-faint)', margin:'0 0 16px'}}>응답 마감: 모임 시작 12시간 전</p>
      <div style={{display:'flex', flexDirection:'column', gap:8}}>
        <DSBtn label="참석할게요" onClick={()=>set({reconfirmOpen:false, reconfirmedMap:{...(S.reconfirmedMap||{}), [id]:true}, toast:'참석 확정! 내일 봬요 — 채팅방에서 아이스브레이커가 기다려요'})}/>
        <DSBtn label="참석이 어려워요" variant="outlined" color="assistive" onClick={()=>releaseSlotAndPromote(id, S, set, true, {reconfirmOpen:false})}/>
        <button style={{background:'none', border:'none', color:'var(--c-faint)', fontFamily:'inherit', fontSize:12.5, cursor:'pointer', padding:'4px 0'}} onClick={()=>set({reconfirmOpen:false, toast:'응답 마감 전에 다시 알려드릴게요'})}>나중에 다시 알림</button>
      </div>
    </div>
  </div>;
}
function ScrChatList({S, go}) {
  const ids = Object.keys(S.joined||{}).filter(id=>S.joined[id]==='confirmed');
  const hosted = S.myHostedMeetups.map((m,i)=>({id:'my'+i, title:m.title||'(제목 없음)'})).filter(h=>S.myHostedMeetups.length);
  const rooms = [...ids.map(id=>({id, title:(MEETUPS[id]||{}).title||'모임 채팅방'})), ...hosted];
  return <div className="scr">
    <TopBar title="채팅"/>
    <div className="pad" style={{flex:1, paddingTop:8}}>
      {!rooms.length&&<div style={{textAlign:'center', padding:'60px 20px'}}>
        <img src={asset('assets/modumoyeo-icon.png')} alt="" style={{width:56, height:56, borderRadius:14, margin:'0 auto 16px'}}/>
        <p style={{fontSize:14, color:'var(--c-sub)', lineHeight:1.6, margin:0}}>참가가 확정된 모임이 생기면<br/>여기서 참가자 채팅방을 볼 수 있어요.</p>
      </div>}
      {rooms.map(r=><button key={r.id} className="row" style={{width:'100%', gap:12, padding:'14px 0', borderBottom:'1px solid var(--c-line)', background:'none', border:'none', borderBottom:'1px solid var(--c-line)', cursor:'pointer', fontFamily:'inherit', textAlign:'left'}} onClick={()=>go('chat', {detailId:r.id})}>
        <Av name={r.title} size={44}/>
        <div style={{flex:1}}><b style={{fontSize:14.5}}>{r.title}</b><div className="meta" style={{marginTop:2}}>참가자 채팅방</div></div>
        <Ic n="IconNormalChevronRightNameChevronRightTightFalseThick" s={14} c="var(--c-faint)"/>
      </button>)}
    </div>
  </div>;
}
function ScrChat({S, set, go}) {
  const hosted = /^my\d+$/.test(S.detailId);
  const hm = hosted ? S.myHostedMeetups[+S.detailId.slice(2)] : null;
  const m = hosted ? {id:S.detailId, title:(hm&&hm.title)||'새 모임', place:(hm&&hm.place)||'장소 미정'} : (MEETUPS[S.detailId] || null);
  if (!m) return <ChatNotFoundNotice go={go}/>;
  const chatHostName = (m.host && m.host.name) || '호스트';
  const baseMsgs = [
    {sys:true, text:`${m.title||'새 모임'} 모임의 채팅방입니다`},
    ...(hosted ? [
    {who:'나', host:true, text:`${hm&&hm.title?hm.title:'새 모임'} 채팅방을 열었어요 — 참가자들이 모이면 여기서 공지해주세요.`},
    {who:'나', host:true, text:'운영진 검토 후 공개되면 이 채팅방으로 참가자들이 모여요 — 이용수칙과 개인 비용 안내를 미리 공지해보세요.'},
  ] : (DEMO_MODE?[
    {who:chatHostName, host:true, text:'환영해요! 다들 처음이라 어색할 수 있는데, 걱정 마세요. 도착하시면 &lsquo;웰컴 테이블&rsquo;로 안내해드릴게요.'},
    {who:chatHostName, host:true, ice:true, text:'미리 답해볼까요? — 유학 시절 가장 웃겼던 에피소드는?'},
    {who:'닉네임A', text:'저 첫 참여인데 8시에 가면 될까요? 조금 떨리네요'},
    {who:'나', me:true, text:'저도 혼자 가요! 웰컴 테이블에서 봬요'},
  ]:[])),
  ];
  const msgs = [...baseMsgs, ...S.chatMsgs];
  const send = () => { if(!S.chatInput.trim()) return; set({chatMsgs:[...S.chatMsgs, {who:'나', me:true, text:S.chatInput.trim()}], chatInput:''}); };
  const companion = !hosted ? getCompanion(m.id) : null;
  const askCompanion = () => { setCompanion(m.id, {status:'requested'}); set({chatMsgs:[...S.chatMsgs, {who:'나', me:true, text:'친구 한 명과 함께 가고 싶은데 괜찮을까요?'}]}); };
  return <div className="scr" style={{background:'var(--c-bg-alt)'}}>
    <TopBar back onBack={()=>go(hosted?'mymeet':(S.detailId==='m1'?'detail':'mymeet'))} title={m.title} right={<span className="meta">참가자 {m.capJoined||0}명</span>}/>
    <div className="pad" style={{paddingTop:8}}>
      <div className="card" style={{padding:'10px 12px', marginBottom:14}}>
        <div className="row" style={{gap:6, marginBottom:6}}><Ic n="IconNormalPin2NamePinFillFillTrue" s={14} c="var(--c-red)"/><b style={{fontSize:12.5}}>모임 이용수칙 (요약) — 고정됨</b></div>
        <div style={{fontSize:12, color:'var(--c-sub)', lineHeight:1.6}}>서로 존중 · 과도한 스킨십 금지 · 비용은 각자 결제 · 노쇼 시 신청 제한 · 신고 기능 상시 이용 가능</div>
        <button style={{background:'none', border:'none', color:'var(--c-primary)', fontSize:12, fontFamily:'inherit', padding:'4px 0 0', cursor:'pointer'}} onClick={()=>set({rulesOpen:true})}>전체 수칙 다시보기</button>
      </div>
      {msgs.length===0&&<div style={{textAlign:'center', padding:'28px 12px'}}>
        <p style={{fontSize:14, fontWeight:700, margin:'0 0 4px'}}>아직 시작된 대화가 없어요.</p>
        <p className="meta" style={{margin:0}}>참가가 확정된 모임의 대화가 여기에 표시돼요.</p>
      </div>}
      {msgs.map((msg,i)=>msg.sys?<div key={i} style={{textAlign:'center',margin:'10px 0'}}><span style={{background:'var(--c-fill)',color:'var(--c-sub)',fontSize:11.5,fontWeight:600,padding:'6px 12px',borderRadius:20,display:'inline-block'}}>{msg.text}</span></div>:<div key={i} className={'msg'+(msg.me?' me':'')} style={{display:'flex', width:'100%', justifyContent:msg.me?'flex-end':'flex-start', gap:8, marginBottom:12}}>
        {!msg.me&&<Av name={msg.who} size={32} tone={msg.host?'p':undefined}/>}
        <div style={{maxWidth:'78%', marginLeft:msg.me?'auto':0}}>
          {!msg.me&&<div className="meta" style={{marginBottom:3}}>{msg.who}{msg.host&&<span className="chip green" style={{fontSize:10, padding:'1px 6px', marginLeft:5}}>인증 호스트</span>}{msg.ice&&<span className="chip violet" style={{fontSize:10, padding:'1px 6px', marginLeft:5}}>아이스브레이커</span>}</div>}
          <div className="bubble" style={msg.me?{background:'var(--c-primary)', color:'#fff', borderRadius:14, padding:'10px 14px', display:'inline-block'}:{background:'var(--c-fill)', borderRadius:14, padding:'10px 14px', display:'inline-block'}} dangerouslySetInnerHTML={{__html:msg.text}}></div>
        </div>
      </div>)}
      {!hosted&&(!companion||companion.status==='none')&&<button type="button" onClick={askCompanion} style={{background:'none',border:'none',color:'var(--c-faint)',fontFamily:'inherit',fontSize:12,cursor:'pointer',padding:'8px 2px',textDecoration:'underline',minHeight:32}}>친구 동반 참가 문의하기</button>}
      {!hosted&&companion&&companion.status!=='none'&&<CompanionDecisionCard m={m} S={S} set={set}/>}
      {S.chatEnded&&<div>
        <div style={{textAlign:'center', fontSize:11.5, color:'var(--c-faint)', margin:'16px 0'}}>— 모임 종료 · 이 채팅방은 2주 후 보관됩니다 —</div>
        <div className="card" style={{marginBottom:14}}>
          <b style={{fontSize:14}}>채팅방이 닫히기 전에, 오늘 만난 사람과 연락처를 공유할까요?</b>
          <p className="meta" style={{margin:'6px 0 12px'}}>상대방이 수락한 경우에만, 한 명씩 원하는 연락수단으로 공유돼요.</p>
          {['닉네임A','닉네임B','닉네임C'].map(name=>{
            const cs = (S.contactShare||{})[name];
            return <div key={name} style={{borderTop:'1px solid var(--c-line)', padding:'10px 0'}}>
              <div className="row" style={{gap:10, marginBottom:cs?8:0}}>
                <Av name={name} size={30}/><span style={{flex:1, fontSize:13.5, fontWeight:600}}>{name}</span>
                {!cs&&<DSBtn label="연락처 공유 요청" size="sm" fit onClick={()=>set({contactShare:{...S.contactShare, [name]:'accepted'}, toast:name+'님이 요청을 수락했어요 — 연락수단을 선택해주세요'})}/>}
                {cs&&cs!=='done'&&<Chip label="수락됨" tone="green"/>}
                {cs==='done'&&<Chip icon="IconNormalCheckNameCheckThickFalse" label="공유 완료" tone="green"/>}
              </div>
              {cs&&cs!=='done'&&<div style={{display:'flex', flexDirection:'column', gap:8}}>
                <div className="meta">연락수단 선택</div>
                <div style={{display:'flex', gap:6, flexWrap:'wrap'}}>{['내부 채팅','카카오톡 ID','인스타그램','전화번호'].map(ch=><Chip key={ch} label={ch} onClick={()=>set({contactShare:{...S.contactShare, [name]:ch}})} on={cs===ch||(cs==='accepted'&&ch==='내부 채팅')}/>)}</div>
                <DSBtn label="이 방법으로 공유하기" size="sm" fit onClick={()=>set({contactShare:{...S.contactShare, [name]:'done'}, toast:name+'님과 '+(cs==='accepted'?'내부 채팅':cs)+'으로 연결됐어요'})}/>
              </div>}
            </div>;})}
        </div>
        <DSBtn label="오늘 만난 사람 보기" variant="outlined" onClick={()=>go('postmeetup',{detailId:m.id, completed:[...new Set([...S.completed, m.id])]})} style={{marginBottom:18}}/>
      </div>}
    </div>
    <div style={{padding:'4px 14px', textAlign:'center'}}><span className="meta" style={{fontSize:10.5}}>사진·링크 전송은 신고·안전을 위해 제한될 수 있어요</span></div>
    <div style={{marginTop:'auto', position:'sticky', bottom:0, background:'var(--c-bg)', borderTop:'1px solid var(--c-line)', padding:'10px 14px', display:'flex', gap:8, alignItems:'center'}}>
      <button className="iconbtn" aria-label="신고하기" onClick={()=>set({reportOpen:true, reportPrefill:m.title})}><Ic n="IconNormalFlagNameFlagFillFalse" s={20} c="var(--c-faint)"/></button>
      <input value={S.chatInput} onChange={e=>set({chatInput:e.target.value})} onKeyDown={e=>{if(e.key==='Enter') send();}} placeholder="메시지 보내기" style={{flex:1, background:'var(--c-fill)', border:'none', borderRadius:999, padding:'9px 14px', fontSize:13.5, fontFamily:'inherit', outline:'none'}}/>
      <button className="iconbtn" aria-label="메시지 보내기" onClick={send}><Ic n="IconNormalSendNameSendFillFillTrue" s={20} c="var(--c-primary)"/></button>
    </div>
  </div>;
}
function ScrHost({S, set, go}) {
  const revs = [['시간·장소 안내가 정확했어요',24],['혼자 온 참가자를 잘 챙겼어요',19],['분위기가 편안했어요',15],['아이스브레이커가 재밌었어요',8]];
  const max = 24;
  const m = MEETUPS[S.detailId] || (S.tempDetail && S.tempDetail.id===S.detailId ? S.tempDetail : null);
  const hostName = (m && m.host && m.host.name) || '호스트';
  const hostBadges = (m && m.host && m.host.badges) || ['인증 호스트'];
  return <div className="scr">
    <TopBar title="호스트 프로필" back onBack={()=>go('detail')}/>
    <div className="pad">
      <div className="row" style={{gap:14, margin:'6px 0 12px'}}>
        <Av name={hostName} size={64} tone="p"/>
        <div>
          <div className="row" style={{gap:8, alignItems:'center'}}><div style={{fontSize:18, fontWeight:800}}>{hostName}</div><AvoidUserButton hostName={hostName} S={S} set={set}/></div>
          <div className="meta" style={{margin:'2px 0 8px'}}>2025.03부터 활동 · 강남/홍대 지역 위주</div>
          <TrustBadges items={hostBadges}/>
          <div style={{marginTop:8, display:'flex', flexDirection:'column', gap:6}}>
            {['호스트 모임 12회 운영','최근 노쇼 없음','학교 인증 완료'].map(label=><div key={label} className="row" style={{gap:7}}><Ic n="IconNormalCircleCheck2NameCircleCheckFillFillTrue" s={14} c="var(--c-green)"/><span style={{fontSize:12.5, fontWeight:600}}>{label}</span></div>)}
          </div>
        </div>
      </div>
      <div className="card" style={{background:'var(--c-primary-bg)', border:'none', marginBottom:14}}>
        <b style={{fontSize:13.5, color:'var(--c-primary)'}}>운영 가이드 준수 체크리스트 (참가자에게 사전 공개)</b>
        {['예상 개인 비용 — 식사·음료 등은 현장에서 각자 결제해요','취소 조건 — 24시간 전까지 무료 취소','사진 촬영 여부 — 촬영 있음 / 참가자 동의 시 SNS 게시'].map(c=><div key={c} className="row" style={{gap:7, marginTop:8, fontSize:13}}><Ic n="IconNormalCheckNameCheckThickFalse" s={15} c="var(--c-primary)"/>{c}</div>)}
      </div>
      <b style={{fontSize:14.5}}>참가자 후기 (태그형) <span className="meta" style={{fontWeight:400}}>— 별점 대신</span></b>
      <div style={{margin:'10px 0 16px'}}>
        {revs.map(r=><div key={r[0]} className="tagrev">
          <span style={{fontSize:12.5, width:170, flexShrink:0}}>{r[0]}</span>
          <span className="bar"><i style={{'--w':(r[1]/max*100)+'%'}}></i></span>
          <b style={{fontSize:12, color:'var(--c-primary)', width:20, textAlign:'right'}}>{r[1]}</b>
        </div>)}
      </div>
      <b style={{fontSize:14.5}}>참가자 후기</b>
      <div style={{margin:'10px 0 20px'}}>
        {[['닉네임B','8월 2일 웰컴파티 참여','처음 참가라 긴장했는데 호스트님이 먼저 말 걸어주셔서 금방 편해졌어요. 시간·장소 안내도 정확했고요.'],['닉네임F','강남 밤모임 참여','혼자 갔는데도 자연스럽게 어울릴 수 있었어요. 다음에도 이 호스트님 모임 또 갈 것 같아요.'],['닉네임H','홍대 브런치 모임 참여','정산이 깔끔하고 아이스브레이커도 재밌어서 어색함이 금방 풀렸어요.']].map((r,i)=><Reveal key={r[0]} delay={i*80}><div className="card" style={{marginBottom:8}}>
          <div className="row" style={{gap:8, marginBottom:6}}><Av name={r[0]} size={26}/><b style={{fontSize:13}}>{r[0]}</b><span className="meta">· {r[1]}</span></div>
          <p style={{fontSize:13, color:'var(--c-sub)', margin:0, lineHeight:1.55}}>{r[2]}</p>
        </div></Reveal>)}
      </div>
      <b style={{fontSize:14.5}}>이 호스트가 연 모임</b>
      <div style={{margin:'10px 0 20px'}}>
        {[['강남 밤모임 · 8/2(토)','참가 12명','m2'],['홍대 브런치 모임 · 8/9(토)','모집중','m1']].map(e=><button key={e[0]} className="card row" style={{width:'100%', gap:10, marginBottom:8, cursor:'pointer', fontFamily:'inherit', textAlign:'left'}} onClick={()=>go('detail',{detailId:e[2]})}>
          <Ph h={44} w={44} r={10} label=""/>
          <span style={{flex:1, fontSize:13.5}}><b>{e[0]}</b><br/><span className="meta">{e[1]}</span></span>
          <Ic n="IconNormalChevronRightNameChevronRightTightFalseThick" s={14} c="var(--c-faint)"/>
        </button>)}
      </div>
    </div>
    <NavBar S={S} go={go}/>
  </div>;
}
Object.assign(window, {ScrDetail, RulesModal, ReconfirmSheet, ScrChat, ScrChatList, ScrHost});
