// Skrrs portal — Search results. Responsive.
const { PropertyCard: SPCard, Button: SButton, Select: SSelect, Tag: STag, Checkbox: SCheck, Badge: SBg } = window.SkrrsDesignSystem_6013e8;

const TYPE_TABS = [
  { key:'all', label:'すべて' },
  { key:'office', label:'オフィス' },
  { key:'retail', label:'店舗' },
  { key:'rnd', label:'教室' },
  { key:'industrial', label:'倉庫' },
  { key:'datacenter', label:'工場' },
];
// こだわり条件（チップ・サイドバー共通）。判定関数までセットで定義＝全て実動作
const FEATURE_FILTERS = [
  { key:'zero',    label:'仲介手数料0円',       test:p=>!!p.zeroCommission },
  { key:'inuki',   label:'居抜き・セットアップ', test:p=>!!(p.flags&&p.flags.inuki) },
  { key:'new',     label:'NEW物件',             test:p=>!!p.isNew },
  { key:'parking', label:'駐車場あり',           test:p=>!!(p.flags&&p.flags.parking) },
  { key:'h24',     label:'24時間利用可',         test:p=>!!(p.flags&&p.flags.h24) },
  { key:'power',   label:'電力増設可',           test:p=>!!(p.flags&&p.flags.power) },
];
const RENT_STEPS = [5000,10000,15000,20000,25000,30000,50000];
const SIZE_STEPS = [10,20,30,50,80,100,150];
const rentOf = p => (p.rentNum>0 ? p.rentNum : (parseInt(String(p.rent).replace(/[^0-9]/g,''),10)||0));
const sizeOf = p => (p.sizeNum>0 ? p.sizeNum : (parseFloat(p.size)||0));

// ── 地図パネル（Leaflet + OSM）：絞り込み結果の物件をピン表示。ピン→ポップアップ→詳細へ ──
function ResultsMap({ list, onOpen }) {
  const { isMobile } = window.useViewport();
  const [open, setOpen] = React.useState(true);
  const mapRef = React.useRef(null);
  const mapObj = React.useRef(null);
  const layerRef = React.useRef(null);
  const pts = list.filter(p => p.lat && p.lng);
  const ptsKey = pts.map(p=>p.id).join(',');
  // 緯度経度を持つ物件が1件も無いときは、空の日本地図が出るだけなのでパネルごと出さない。
  // 物件データに lat / lng を入れれば自動で表示される。
  const hasPts = pts.length > 0;

  React.useEffect(() => {
    if (!open) return;
    let tries = 0, cancelled = false;
    const init = () => {
      if (cancelled) return;
      if (!window.L) { if (tries++ < 24) setTimeout(init, 250); return; }   // Leaflet読込待ち
      if (!mapRef.current) return;
      if (!mapObj.current) {
        mapObj.current = window.L.map(mapRef.current, { scrollWheelZoom: false });
        window.L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
          attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>', maxZoom: 18,
        }).addTo(mapObj.current);
        layerRef.current = window.L.layerGroup().addTo(mapObj.current);
      }
      const g = layerRef.current; g.clearLayers();
      if (!pts.length) { mapObj.current.setView([35.60, 139.60], 9); return; }
      pts.forEach(p => {
        const m = window.L.marker([p.lat, p.lng]).addTo(g);
        m.bindPopup(
          '<div style="min-width:180px;line-height:1.5">' +
          '<div style="font-weight:700;font-size:13px;margin-bottom:2px">' + p.name + '</div>' +
          '<div style="color:#556;font-size:11px">' + p.typeLabel + '・' + p.size + '・' + p.rent + '</div>' +
          '<a href="#" data-pid="' + p.id + '" class="sk-map-open" style="display:inline-block;margin-top:6px;color:#015E96;font-weight:700;font-size:12px;text-decoration:none">詳細を見る ›</a></div>'
        );
      });
      const b = window.L.latLngBounds(pts.map(p=>[p.lat,p.lng]));
      mapObj.current.fitBounds(b, { padding:[34,34], maxZoom: 14 });
      setTimeout(()=>{ if (mapObj.current) mapObj.current.invalidateSize(); }, 250);
    };
    init();
    return () => { cancelled = true; };
  }, [open, ptsKey]);

  // ポップアップ内「詳細を見る」→ 物件詳細へ
  React.useEffect(() => {
    const h = (e) => {
      const a = e.target && e.target.closest ? e.target.closest('.sk-map-open') : null;
      if (a) { e.preventDefault(); const p = list.find(x => x.id === a.getAttribute('data-pid')); if (p) onOpen(p); }
    };
    document.addEventListener('click', h);
    return () => document.removeEventListener('click', h);
  }, [ptsKey]);

  // 画面遷移時にマップを破棄
  React.useEffect(() => () => { if (mapObj.current) { mapObj.current.remove(); mapObj.current = null; layerRef.current = null; } }, []);

  if (!hasPts) return null;

  return (
    <div style={{ background:'var(--surface)', border:'1px solid var(--border-subtle)', borderRadius:'var(--r-md)', overflow:'hidden', boxShadow:'var(--shadow-sm)' }}>
      <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', padding:'10px 14px' }}>
        <span style={{ display:'inline-flex', alignItems:'center', gap:8, font:'700 var(--t-sm)/1 var(--font-display)', color:'var(--text-strong)' }}>
          <window.Icon name="pin" size={15} style={{ color:'var(--blue-600)' }}/>地図から探す
          <span style={{ font:'var(--fw-regular) var(--t-2xs)/1 var(--font-num)', color:'var(--text-muted)' }}>{pts.length}件を表示中</span>
        </span>
        <button onClick={()=>setOpen(v=>!v)} style={{ border:'none', background:'none', cursor:'pointer',
          font:'var(--fw-bold) var(--t-xs)/1 var(--font-body)', color:'var(--blue-600)' }}>{open ? '地図を閉じる' : '地図を開く'}</button>
      </div>
      {open && <div ref={mapRef} style={{ height: isMobile ? 230 : 320, width:'100%', zIndex:0 }} />}
    </div>
  );
}

function SearchScreen({ initialType = 'all', saved, onToggleSave, onOpen, onNav }) {
  const D = window.SKRRS_DATA;
  const { isMobile, isTablet } = window.useViewport();
  const [type, setType] = React.useState(initialType);
  const [feat, setFeat] = React.useState({});
  const [sort, setSort] = React.useState('new');
  const [showFilters, setShowFilters] = React.useState(false);
  const [pref, setPref] = React.useState('');           // 都県
  const [rentMin, setRentMin] = React.useState(0);
  const [rentMax, setRentMax] = React.useState(0);
  const [sizeMin, setSizeMin] = React.useState(0);
  const [sizeMax, setSizeMax] = React.useState(0);
  const [kw, setKw] = React.useState('');               // フリーワード（物件名/住所/駅）
  React.useEffect(()=>{ setType(initialType); }, [initialType]);

  const activeFeats = FEATURE_FILTERS.filter(f=>feat[f.key]);
  const kwLow = kw.trim().toLowerCase();
  const list = D.properties
    .filter(p => type === 'all' || p.type === type)
    .filter(p => !pref || String(p.area||'').indexOf(pref) === 0)
    .filter(p => { const r = rentOf(p); return (!rentMin || r >= rentMin) && (!rentMax || r <= rentMax); })
    .filter(p => { const s = sizeOf(p); return (!sizeMin || s >= sizeMin) && (!sizeMax || s <= sizeMax); })
    .filter(p => activeFeats.every(f => f.test(p)))
    .filter(p => !kwLow || [p.name,p.area,p.access,p.station,p.ward].some(v => String(v||'').toLowerCase().indexOf(kwLow) >= 0))
    .sort((a,b) => sort==='low' ? rentOf(a)-rentOf(b)
                 : sort==='high' ? rentOf(b)-rentOf(a)
                 : sort==='size' ? sizeOf(b)-sizeOf(a)
                 : sort==='sizeAsc' ? sizeOf(a)-sizeOf(b)
                 : (b.isNew?1:0)-(a.isNew?1:0));   // 新着順＝NEWを先頭に
  const cols = isMobile ? 2 : isTablet ? 2 : 3;
  const clearAll = () => { setFeat({}); setPref(''); setRentMin(0); setRentMax(0); setSizeMin(0); setSizeMax(0); setKw(''); setType('all'); };
  const hasCond = pref || rentMin || rentMax || sizeMin || sizeMax || kwLow || activeFeats.length || type!=='all';

  // ── ページネーション（実装）：12件/ページ。フィルタ変更で1ページ目へ戻す ──
  const PER_PAGE = 12;
  const [pageN, setPageN] = React.useState(1);
  React.useEffect(()=>{ setPageN(1); }, [type, pref, rentMin, rentMax, sizeMin, sizeMax, kwLow, sort, activeFeats.length]);
  const totalPages = Math.max(1, Math.ceil(list.length / PER_PAGE));
  const curPage = Math.min(pageN, totalPages);            // 件数減でページが消えても安全
  const paged = list.slice((curPage-1)*PER_PAGE, curPage*PER_PAGE);
  const goPage = (n) => { setPageN(n); window.scrollTo({ top: 0, behavior: 'smooth' }); };
  // 表示するページ番号：現在±2＋先頭末尾（1000件規模でも並びが破綻しない窓表示）
  const pageNums = [];
  for (let n = 1; n <= totalPages; n++) {
    if (n === 1 || n === totalPages || Math.abs(n - curPage) <= 2) pageNums.push(n);
    else if (pageNums[pageNums.length-1] !== '…') pageNums.push('…');
  }

  const rangeRow = (label, minV, setMin, maxV, setMax, steps, fmt) => (
    <div style={{ display:'flex', flexDirection:'column', gap:8 }}>
      <span style={{ font:'var(--fw-medium) var(--t-sm)/1.3 var(--font-body)', color:'var(--text-strong)' }}>{label}</span>
      <div style={{ display:'flex', alignItems:'center', gap:8 }}>
        <SSelect value={String(minV||'')} onChange={e=>setMin(Number(e.target.value)||0)}
          options={[{value:'',label:'下限なし'}].concat(steps.map(v=>({value:String(v),label:fmt(v)})))} />
        <span style={{ color:'var(--text-faint)' }}>〜</span>
        <SSelect value={String(maxV||'')} onChange={e=>setMax(Number(e.target.value)||0)}
          options={[{value:'',label:'上限なし'}].concat(steps.map(v=>({value:String(v),label:fmt(v)})))} />
      </div>
    </div>
  );

  const FilterPanel = (
    <div style={{ background:'var(--surface)', border:'1px solid var(--border-subtle)',
      borderRadius:'var(--r-md)', padding:'var(--sp-5)', display:'flex', flexDirection:'column', gap:'var(--sp-5)' }}>
      <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between' }}>
        <span style={{ font:'700 var(--t-sm)/1 var(--font-display)', color:'var(--text-strong)' }}>絞り込み条件</span>
        {hasCond && <button onClick={clearAll} style={{ border:'none', background:'none', cursor:'pointer',
          font:'var(--fw-medium) var(--t-2xs)/1 var(--font-body)', color:'var(--blue-600)', textDecoration:'underline' }}>条件をクリア</button>}
      </div>
      <div style={{ display:'flex', flexDirection:'column', gap:6 }}>
        <span style={{ font:'var(--fw-medium) var(--t-sm)/1.3 var(--font-body)', color:'var(--text-strong)' }}>フリーワード</span>
        <input value={kw} onChange={e=>setKw(e.target.value)} placeholder="駅名・エリア・物件名など"
          style={{ width:'100%', boxSizing:'border-box', padding:'10px 12px', border:'1.5px solid var(--border-default)', borderRadius:'var(--r-sm)',
            font:'var(--fw-regular) var(--t-sm)/1.4 var(--font-body)', color:'var(--text-strong)', outline:'none' }} />
      </div>
      <SSelect label="エリア" value={pref} onChange={e=>setPref(e.target.value)}
        options={[{value:'',label:'すべて'}].concat((D.areas||[]).map(a=>({value:a,label:a})))} />
      {rangeRow('賃料（坪単価）', rentMin, setRentMin, rentMax, setRentMax, RENT_STEPS, v=>'¥'+v.toLocaleString())}
      {rangeRow('面積（坪・㎡）', sizeMin, setSizeMin, sizeMax, setSizeMax, SIZE_STEPS, v=>v+'坪（約'+Math.round(v*3.3058)+'㎡）')}
      <div style={{ display:'flex', flexDirection:'column', gap:9 }}>
        <span style={{ font:'var(--fw-medium) var(--t-sm)/1.3 var(--font-body)', color:'var(--text-strong)' }}>こだわり条件</span>
        {FEATURE_FILTERS.map(f=>(
          <SCheck key={f.key} label={f.label} checked={!!feat[f.key]} onChange={()=>setFeat(s=>({...s,[f.key]:!s[f.key]}))} />
        ))}
      </div>
      {isMobile && <SButton variant="primary" full pill iconLeft={<window.Icon name="search" size={17}/>} onClick={()=>setShowFilters(false)}>この条件で検索（{list.length}件）</SButton>}
    </div>
  );

  // 宅建業法25条：供託／分担金の納付・届出が完了するまで物件広告は掲載できない。
  // data.js の release.properties を true にすると検索結果が公開される。
  if (!(D.release || {}).properties) {
    return (
      <main style={{ background:'var(--bg-page)', minHeight:'70vh' }}>
        <div style={{ background:'var(--surface)', borderBottom:'1px solid var(--border-subtle)' }}>
          <window.Container style={{ paddingTop:'var(--sp-6)', paddingBottom:'var(--sp-5)' }}>
            <div style={{ display:'flex', alignItems:'center', gap:8, marginBottom:12,
              font:'var(--fw-regular) var(--t-xs)/1 var(--font-body)', color:'var(--text-muted)' }}>
              <span style={{ cursor:'pointer' }} onClick={()=>onNav('home')}>ホーム</span><window.Icon name="chevR" size={12}/>
              <span style={{ color:'var(--text-body)' }}>賃貸物件を探す</span>
            </div>
            <h1 style={{ margin:0, font:'700 var(--t-h1)/1.2 var(--font-display)', color:'var(--text-strong)' }}>賃貸物件を探す</h1>
          </window.Container>
        </div>
        <window.Container style={{ paddingTop:'var(--sp-14)', paddingBottom:'var(--sp-20)' }}>
          <window.ComingSoon area="properties" onNav={onNav} />
        </window.Container>
      </main>
    );
  }

  return (
    <main style={{ background:'var(--bg-page)', minHeight:'70vh' }}>
      {/* breadcrumb + title */}
      <div style={{ background:'var(--surface)', borderBottom:'1px solid var(--border-subtle)' }}>
        <window.Container style={{ paddingTop:'var(--sp-6)', paddingBottom:'var(--sp-5)' }}>
          <div style={{ display:'flex', alignItems:'center', gap:8, marginBottom:12,
            font:'var(--fw-regular) var(--t-xs)/1 var(--font-body)', color:'var(--text-muted)' }}>
            <span style={{ cursor:'pointer' }} onClick={()=>onNav('home')}>ホーム</span><window.Icon name="chevR" size={12}/>
            <span style={{ color:'var(--text-body)' }}>物件を探す</span>
          </div>
          <div style={{ display:'flex', alignItems:'baseline', gap:16 }}>
            <h1 style={{ margin:0, font:'700 var(--t-h1)/1.2 var(--font-display)', color:'var(--text-strong)' }}>物件を探す</h1>
            <span style={{ display:'inline-flex', alignItems:'baseline', gap:5 }}>
              <span style={{ font:'700 var(--t-h2)/1 var(--font-num)', color:'var(--blue-600)' }}>{list.length}</span>
              <span style={{ font:'var(--fw-medium) var(--t-sm)/1 var(--font-body)', color:'var(--text-muted)' }}>件</span>
            </span>
          </div>
          {/* type tabs */}
          <div style={{ display:'flex', gap:4, marginTop:18, flexWrap:'wrap', overflowX: isMobile?'auto':'visible' }}>
            {TYPE_TABS.map(t=>{
              const on = type===t.key;
              return (
                <button key={t.key} onClick={()=>setType(t.key)} style={{ cursor:'pointer',
                  padding:'9px 16px', border:'none', borderRadius:'var(--r-sm) var(--r-sm) 0 0', whiteSpace:'nowrap',
                  background: on ? 'var(--blue-900)' : 'transparent',
                  color: on ? '#fff' : 'var(--text-body)',
                  font:`${on?'var(--fw-bold)':'var(--fw-medium)'} var(--t-sm)/1 var(--font-body)`,
                  borderBottom: on ? '2px solid var(--blue-500)' : '2px solid transparent' }}>{t.label}</button>
              );
            })}
          </div>
        </window.Container>
      </div>

      {/* 非公開物件バナー（表示件数の外に希少在庫がある＝問い合わせ動機） */}
      <window.Container style={{ paddingTop:'var(--sp-5)' }}>
        <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', gap:'var(--sp-4)', flexWrap:'wrap',
          background:'var(--blue-900)', borderRadius:'var(--r-md)', padding: isMobile?'var(--sp-5)':'var(--sp-5) var(--sp-7)' }}>
          <div style={{ display:'flex', alignItems:'center', gap:14 }}>
            <span style={{ display:'grid', placeItems:'center', width:44, height:44, borderRadius:'var(--r-pill)', background:'rgba(255,255,255,0.12)', color:'#fff', flex:'none' }}><window.Icon name="search" size={20}/></span>
            <div style={{ display:'flex', flexDirection:'column', gap:3 }}>
              <span style={{ font:'var(--fw-bold) var(--t-base)/1.4 var(--font-display)', color:'#fff' }}>
                Webに出ていない物件も、お探しします。
              </span>
              <span style={{ font:'var(--fw-regular) var(--t-xs)/1.5 var(--font-body)', color:'rgba(255,255,255,0.72)' }}>
                業者間の流通ネットワーク、大手仲介会社の取扱物件、シェアオフィスまで。ご希望の条件をお聞かせいただければ、担当エージェントより個別にご案内します。
              </span>
            </div>
          </div>
          <SButton variant="inverse" pill full={isMobile} iconLeft={<window.Icon name="mail" size={16}/>} onClick={()=>onNav('contact')}>非公開物件を相談する</SButton>
        </div>
      </window.Container>

      <window.Container style={{ paddingTop:'var(--sp-8)', paddingBottom: isMobile?'var(--sp-16)':'var(--sp-20)' }}>
        <div style={{ display:'grid', gridTemplateColumns: isMobile?'1fr':'264px 1fr', gap:'var(--sp-8)' }}>
          {/* ── Filter rail ── */}
          {isMobile ? (
            <div>
              <SButton variant="secondary" full iconLeft={<window.Icon name="filter" size={16}/>} onClick={()=>setShowFilters(v=>!v)}>
                絞り込み条件{showFilters?'を閉じる':'を開く'}
              </SButton>
              {showFilters && <div style={{ marginTop:'var(--sp-4)' }}>{FilterPanel}</div>}
            </div>
          ) : (
            <aside style={{ display:'flex', flexDirection:'column', gap:'var(--sp-5)' }}>{FilterPanel}</aside>
          )}

          {/* ── Results ── */}
          <div style={{ display:'flex', flexDirection:'column', gap:'var(--sp-5)' }}>
            {/* 地図（絞り込み結果と連動・ピン→詳細） */}
            <ResultsMap list={list} onOpen={onOpen} />
            <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', gap:16, flexWrap:'wrap' }}>
              <div style={{ display:'flex', gap:8, flexWrap:'wrap' }}>
                {FEATURE_FILTERS.map(f=>(
                  <STag key={f.key} selected={!!feat[f.key]} onClick={()=>setFeat(s=>({...s,[f.key]:!s[f.key]}))}>{f.label}</STag>
                ))}
              </div>
              <div style={{ display:'flex', alignItems:'center', gap:8, flex:'none' }}>
                <span style={{ font:'var(--fw-medium) var(--t-xs)/1 var(--font-body)', color:'var(--text-muted)' }}>並び替え</span>
                <div style={{ width:150 }}>
                  <SSelect value={sort} onChange={e=>setSort(e.target.value)}
                    options={[{value:'new',label:'新着順'},{value:'low',label:'賃料が安い順'},{value:'high',label:'賃料が高い順'},{value:'sizeAsc',label:'面積が狭い順'},{value:'size',label:'面積が広い順'}]} />
                </div>
              </div>
            </div>

            {list.length === 0 && (
              <div style={{ background:'var(--surface)', border:'1px solid var(--border-subtle)', borderRadius:'var(--r-md)',
                padding:'var(--sp-10)', textAlign:'center', display:'flex', flexDirection:'column', alignItems:'center', gap:14 }}>
                <span style={{ display:'grid', placeItems:'center', width:56, height:56, borderRadius:'var(--r-pill)', background:'var(--blue-50)', color:'var(--blue-400)' }}><window.Icon name="search" size={26}/></span>
                <span style={{ font:'700 var(--t-h4)/1.4 var(--font-display)', color:'var(--text-strong)' }}>条件に合う公開物件が見つかりませんでした</span>
                <span style={{ font:'var(--fw-regular) var(--t-sm)/1.8 var(--font-body)', color:'var(--text-muted)', maxWidth:420 }}>
                  Webに出ていない物件からも、ご条件に合うものを担当エージェントがお探しします。条件を少し緩めていただくか、お気軽にご相談ください。
                </span>
                <div style={{ display:'flex', gap:10, flexWrap:'wrap', justifyContent:'center' }}>
                  <SButton variant="primary" pill iconLeft={<window.Icon name="mail" size={16}/>} onClick={()=>onNav('contact')}>この条件で相談する</SButton>
                  <SButton variant="secondary" pill onClick={clearAll}>条件をクリア</SButton>
                </div>
              </div>
            )}
            <div style={{ display:'grid', gridTemplateColumns:`repeat(${cols}, 1fr)`, gap: isMobile?'var(--sp-3)':'var(--sp-5)' }}>
              {paged.map(p=>{
                const n = parseFloat(p.size);
                // 収容人数の目安は、人が滞在する用途にだけ出す。
                // 倉庫・工場に「◯〜◯名」を出しても意味がなく、かえって不正確に見える。
                const capTypes = ['office','rnd'];
                const cap = (n && capTypes.indexOf(p.type) >= 0) ? `${Math.max(2,Math.round(n*0.4))}〜${Math.round(n*0.6)}名` : null;
                const specRow = (icon,label,val,wrap)=>(
                  <div style={{ display:'flex', alignItems:'flex-start', gap:6, minWidth:0 }}>
                    <window.Icon name={icon} size={13} style={{ color:'var(--text-faint)', flex:'none', marginTop:wrap?2:0 }}/>
                    {label && <span style={{ font:'var(--fw-regular) var(--t-2xs)/1.3 var(--font-body)', color:'var(--text-muted)', flex:'none', marginTop:wrap?1:0 }}>{label}</span>}
                    <span style={{ font:`var(--fw-medium) ${isMobile?'var(--t-2xs)':'var(--t-xs)'}/1.4 var(--font-body)`, color:'var(--text-muted)', minWidth:0,
                      ...(wrap ? {} : { whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }) }}>{val}</span>
                  </div>
                );
                return (
                  <div key={p.id} className="sk-card" style={{ display:'flex', flexDirection:'column', background:'var(--surface)', border:'1px solid var(--border-subtle)',
                    borderRadius:'var(--r-md)', overflow:'hidden', boxShadow:'var(--shadow-sm)' }}>
                    {/* photo + badges */}
                    <div style={{ position:'relative', cursor:'pointer' }} onClick={()=>onOpen(p)}>
                      <window.Photo src={p.img} alt={p.name} hue={p.hue} ratio="16 / 10" icon="building" />
                      <div style={{ position:'absolute', top:10, left:10, display:'flex', gap:6, flexWrap:'wrap' }}>
                        <SBg tone={p.type} size="xs">{p.typeLabel}</SBg>
                        {p.isNew && <SBg tone="info" solid size="xs">NEW</SBg>}
                        {p.draft && <SBg tone="amber" solid size="xs">下書き（未公開）</SBg>}
                      </div>
                      <button aria-label="お気に入り" onClick={(e)=>{ e.stopPropagation(); onToggleSave(p.id); }}
                        style={{ position:'absolute', ...(isMobile ? { bottom:8, left:8 } : { top:8, right:8 }), width:30, height:30, borderRadius:'var(--r-pill)', border:'none',
                          background:'rgba(255,255,255,0.92)', boxShadow:'var(--shadow-xs)', cursor:'pointer', display:'grid', placeItems:'center',
                          color: saved[p.id]?'var(--blue-600)':'var(--text-muted)' }}>
                        <window.Icon name="heart" size={15} fill={saved[p.id]?'currentColor':'none'}/>
                      </button>
                    </div>
                    {/* body */}
                    <div style={{ padding: isMobile?'var(--sp-3) var(--sp-4) var(--sp-4)':'var(--sp-5)', display:'flex', flexDirection:'column', gap: isMobile?6:8, flex:1 }}>
                      <h3 onClick={()=>onOpen(p)} style={{ margin:0, cursor:'pointer', font:`var(--fw-bold) ${isMobile?'var(--t-base)':'var(--t-h4)'}/1.4 var(--font-display)`, color:'var(--blue-900)',
                        display:'-webkit-box', WebkitLineClamp:2, WebkitBoxOrient:'vertical', overflow:'hidden' }}>{p.name}</h3>
                      <div style={{ display:'flex', flexDirection:'column', gap:4 }}>
                        {specRow('pin','', p.area, true)}
                        {specRow('train','', p.access, true)}
                      </div>
                      <div style={{ display:'grid', gridTemplateColumns: isMobile?'1fr':'1fr 1fr', gap:'4px 10px' }}>
                        {specRow('ruler','面積', p.size)}
                        {cap && specRow('users','人数', cap)}
                      </div>
                      <div style={{ display:'flex', alignItems:'baseline', gap:6 }}>
                        <span style={{ font:`var(--fw-bold) ${isMobile?'1.05rem':'1.25rem'}/1 var(--font-num)`, color:'var(--blue-900)', whiteSpace:'nowrap' }}>{p.rent}</span>
                      </div>
                      {p.zeroCommission && <div><SBg tone="amber" size="sm">仲介手数料0円</SBg></div>}
                      <div style={{ display:'flex', flexDirection: isMobile?'column':'row', gap:8, marginTop:'auto', paddingTop:6 }}>
                        <SButton variant="primary" size="sm" full pill onClick={()=>onOpen(p)}>詳細を見る</SButton>
                        {!isMobile && <SButton variant="secondary" size="sm" full iconLeft={<window.Icon name="mail" size={14}/>} onClick={()=>onNav('contact')}>相談</SButton>}
                      </div>
                    </div>
                  </div>
                );
              })}
            </div>

            {totalPages > 1 && (
            <div style={{ display:'flex', alignItems:'center', justifyContent:'center', gap:6, marginTop:'var(--sp-8)', flexWrap:'wrap' }}>
              <PageBtn disabled={curPage===1} onClick={()=>goPage(curPage-1)}><window.Icon name="chevL" size={16}/></PageBtn>
              {pageNums.map((n,i)=>(
                n === '…'
                  ? <span key={'e'+i} style={{ padding:'0 4px', color:'var(--text-faint)' }}>…</span>
                  : <PageBtn key={n} active={n===curPage} onClick={()=>goPage(n)}>{n}</PageBtn>
              ))}
              <PageBtn disabled={curPage===totalPages} onClick={()=>goPage(curPage+1)}><window.Icon name="chevR" size={16}/></PageBtn>
            </div>
            )}
          </div>
        </div>
      </window.Container>
    </main>
  );
}

function PageBtn({ children, active, disabled, onClick }) {
  return (
    <button disabled={disabled} onClick={onClick} style={{ minWidth:40, height:40, padding:'0 10px', cursor: disabled?'not-allowed':'pointer',
      borderRadius:'var(--r-sm)', border:`1px solid ${active?'var(--blue-900)':'var(--border-default)'}`,
      background: active?'var(--blue-900)':'var(--surface)', color: active?'#fff':'var(--text-body)',
      opacity: disabled?0.4:1, font:'var(--fw-bold) var(--t-sm)/1 var(--font-num)',
      display:'inline-flex', alignItems:'center', justifyContent:'center' }}>{children}</button>
  );
}

Object.assign(window, { SearchScreen });
