/* Map screen — spatial view of mission/data status, NOT navigation. */

function MapScreen({ onTabChange, onMissionTap, selectedPoi, onWorldOpen }) {
  const mapDropAccess = window.MAP_DROP_ACCESS || {
    completedPoi: 3,
    requiredPoi: 5,
    districtRank: 148,
    rankCutoff: 100,
    districtProgress: 72,
    districtTarget: 100,
  };
  const mapDropQualified = window.isMapDropQualified
    ? window.isMapDropQualified(mapDropAccess)
    : (mapDropAccess.completedPoi >= mapDropAccess.requiredPoi || mapDropAccess.districtRank <= mapDropAccess.rankCutoff);
  const [layer, setLayer] = React.useState('missions');
  const [selectedPin, setSelectedPin] = React.useState(null);
  const [sheetExpanded, setSheetExpanded] = React.useState(false);
  const [dropRedeemed, setDropRedeemed] = React.useState(false);
  const [reviewSubmitted, setReviewSubmitted] = React.useState(false);
  const [view, setView] = React.useState({ x: 0, y: 0, zoom: 1 });
  const [filters, setFilters] = React.useState({
    avail: true,
    stale: true,
    rare: true,
    done: true,
    drop: true,
  });
  const dragRef = React.useRef(null);
  const sheetDragRef = React.useRef(null);
  const sheetDidDragRef = React.useRef(false);

  const standardPins = [
    { id:'p1', x:'22%', y:'28%', status:'rare', label:'Sarugakucho 14-3', type:'First Look', cp:90, dist:'280m' },
    { id:'p2', x:'48%', y:'22%', status:'done', label:'Cosme Kitchen', type:'Verified', cp:0, dist:'180m' },
    { id:'p3', x:'68%', y:'34%', status:'stale', label:'Onibus Coffee', type:'Refresh', cp:50, dist:'410m' },
    { id:'p4', x:'34%', y:'52%', status:'avail', label:'Mori Tea House', type:'Verify', cp:40, dist:'120m' },
    { id:'p5', x:'72%', y:'58%', status:'rare', label:'Coffee crawl · 4', type:'Route', cp:220, dist:'1.2km' },
    { id:'p6', x:'18%', y:'70%', status:'avail', label:'Tsutaya T-Site', type:'Angle', cp:70, dist:'650m' },
    { id:'p7', x:'56%', y:'76%', status:'done', label:'Ivy Place', type:'Verified', cp:0, dist:'520m' },
    { id:'p8', x:'82%', y:'80%', status:'stale', label:'Saturdays NYC', type:'Refresh', cp:40, dist:'780m' },
  ];

  const dropPins = [
    { id:'d1', x:'31%', y:'25%', status:'drop', label:'Mission Coffee', type:'Map Drop', cp:120, dist:'520m', left:18, total:40, reward:'Free cold brew', expires:'4h 12m' },
    { id:'d2', x:'56%', y:'36%', status:'drop', label:'Corner Bakery', type:'Map Drop', cp:110, dist:'760m', left:9, total:30, reward:'Cardamom bun', expires:'4h 12m' },
    { id:'d3', x:'73%', y:'55%', status:'drop', label:'Leaf & Steam', type:'Map Drop', cp:130, dist:'1.1km', left:24, total:50, reward:'Signature matcha', expires:'4h 12m' },
    { id:'d4', x:'44%', y:'72%', status:'drop', label:'Tiny Counter', type:'Map Drop', cp:100, dist:'880m', left:6, total:30, reward:'Espresso tonic', expires:'4h 12m' },
    { id:'d5', x:'18%', y:'63%', status:'drop', label:'North Lane Donuts', type:'Map Drop', cp:115, dist:'1.3km', left:31, total:50, reward:'House donut', expires:'4h 12m' },
  ];

  const pins = layer === 'mapdrop' ? dropPins : standardPins;
  const allPins = [...standardPins, ...dropPins];

  const statusColor = (s) => ({
    avail:'var(--status-done)',
    done:'var(--ink-3)',
    stale:'var(--status-stale)',
    rare:'var(--status-rare)',
    drop:'var(--warm)',
  })[s];

  const clampZoom = (z) => Math.max(0.8, Math.min(2.4, z));
  const visiblePins = pins.filter(p => filters[p.status]);
  const sel = visiblePins.find(p => p.id === selectedPin);
  const contributedInfo = sel ? [
    {
      title:'Menu photo',
      meta:'Added by Ren · reviewed',
      body:'Latest drink board captured near the entrance.',
      seed:sel.id + '-menu',
    },
    {
      title:'Exterior signage',
      meta:'Added by Mina · reviewed',
      body:`Visible sign text: ${sel.label}`,
      seed:sel.id + '-sign',
    },
    {
      title:'Interior context',
      meta:'Added by Kai · awaiting review',
      body:'Small counter service area, 8-10 seats, narrow aisle.',
      seed:sel.id + '-interior',
    },
  ] : [];

  React.useEffect(() => {
    if (!selectedPoi) return;
    const name = selectedPoi.name || selectedPoi.label || '';
    const pin = allPins.find(p => p.label === name || p.label.includes(name) || name.includes(p.label));
    if (!pin) return;
    setFilters(f => ({ ...f, [pin.status]: true }));
    if (pin.status === 'drop') setLayer('mapdrop');
    setSelectedPin(pin.id);
  }, [selectedPoi]);

  React.useEffect(() => {
    setSheetExpanded(false);
    setDropRedeemed(false);
    setReviewSubmitted(false);
  }, [selectedPin]);

  const mapTransform = {
    transform:`translate(${view.x}px, ${view.y}px) scale(${view.zoom})`,
    transformOrigin:'50% 50%',
    transition: dragRef.current ? 'none' : 'transform .18s ease',
  };

  function onMapPointerDown(e) {
    if (e.target.closest('button')) return;
    dragRef.current = {
      id: e.pointerId,
      x: e.clientX,
      y: e.clientY,
      startX: view.x,
      startY: view.y,
    };
    e.currentTarget.setPointerCapture?.(e.pointerId);
  }

  function onMapPointerMove(e) {
    const drag = dragRef.current;
    if (!drag || drag.id !== e.pointerId) return;
    setView(v => ({
      ...v,
      x: drag.startX + (e.clientX - drag.x),
      y: drag.startY + (e.clientY - drag.y),
    }));
  }

  function onMapPointerUp(e) {
    if (dragRef.current?.id === e.pointerId) dragRef.current = null;
  }

  function zoomBy(delta) {
    setView(v => ({ ...v, zoom: clampZoom(v.zoom + delta) }));
  }

  function recenter() {
    setView({ x: 0, y: 0, zoom: 1 });
    setSelectedPin(null);
  }

  function toggleFilter(status) {
    setFilters(f => ({ ...f, [status]: !f[status] }));
    if (selectedPin) {
      const selected = allPins.find(p => p.id === selectedPin);
      if (selected?.status === status && filters[status]) setSelectedPin(null);
    }
  }

  function onSheetPointerDown(e) {
    sheetDragRef.current = { id:e.pointerId, y:e.clientY };
    sheetDidDragRef.current = false;
    e.currentTarget.setPointerCapture?.(e.pointerId);
  }

  function onSheetPointerMove(e) {
    const drag = sheetDragRef.current;
    if (!drag || drag.id !== e.pointerId) return;
    const delta = e.clientY - drag.y;
    if (delta < -28) {
      sheetDidDragRef.current = true;
      setSheetExpanded(true);
      sheetDragRef.current = null;
    } else if (delta > 28) {
      sheetDidDragRef.current = true;
      setSheetExpanded(false);
      sheetDragRef.current = null;
    }
  }

  function onSheetHandleClick() {
    if (sheetDidDragRef.current) {
      sheetDidDragRef.current = false;
      return;
    }
    setSheetExpanded(v => !v);
  }

  function onSheetPointerUp(e) {
    if (sheetDragRef.current?.id === e.pointerId) sheetDragRef.current = null;
  }

  return (
    <>
      <StatusBar/>
      <div
        onPointerDown={onMapPointerDown}
        onPointerMove={onMapPointerMove}
        onPointerUp={onMapPointerUp}
        onPointerCancel={onMapPointerUp}
        style={{flex:1, position:'relative', overflow:'hidden', touchAction:'none', cursor:dragRef.current ? 'grabbing' : 'grab'}}
      >
        {/* Draggable map plane */}
        <div style={{position:'absolute', inset:0, ...mapTransform}}>
          {/* Map background */}
          <div style={{position:'absolute', inset:0, background:'var(--bg-elev)'}}>
            <svg viewBox="0 0 390 700" width="100%" height="100%" preserveAspectRatio="none">
              <defs>
                <pattern id="mapgrid" width="24" height="24" patternUnits="userSpaceOnUse">
                  <path d="M 24 0 L 0 0 0 24" fill="none" stroke="var(--line)" strokeWidth="0.5"/>
                </pattern>
              </defs>
              <rect width="390" height="700" fill="url(#mapgrid)"/>
              {/* roads */}
              <path d="M -10 200 Q 80 180 200 220 T 400 200" stroke="var(--line-2)" strokeWidth="2" fill="none"/>
              <path d="M -10 480 Q 100 460 200 440 T 400 480" stroke="var(--line-2)" strokeWidth="2" fill="none"/>
              <path d="M 80 -10 Q 100 200 130 400 T 160 710" stroke="var(--line-2)" strokeWidth="2" fill="none"/>
              <path d="M 280 -10 Q 290 200 270 400 T 300 710" stroke="var(--line-2)" strokeWidth="2" fill="none"/>
              {/* park blob */}
              <path d="M 30 320 Q 100 300 140 340 Q 150 400 100 410 Q 40 400 30 320 Z"
                fill="oklch(0.92 0.04 155)" opacity="0.4"/>
              <text x="60" y="370" fontFamily="var(--font-mono)" fontSize="9" fill="var(--ink-3)" letterSpacing="0.06em">PARK</text>
              {/* coverage gap */}
              <path d="M 220 540 L 360 540 L 360 660 L 220 660 Z"
                fill="none" stroke="var(--status-stale)" strokeWidth="1" strokeDasharray="3 3" opacity="0.6"/>
            </svg>
          </div>

          {/* User location */}
          <div style={{
            position:'absolute', left:'42%', top:'48%',
            width:14, height:14, borderRadius:'50%', background:'var(--ink)',
            boxShadow:'0 0 0 4px var(--bg-elev), 0 0 0 5px var(--ink), 0 0 0 18px rgba(20,32,31,0.06)',
            transform:'translate(-50%,-50%)', zIndex:5,
          }}/>

          {/* Pins */}
          {visiblePins.map(p => (
            <button key={p.id} onClick={() => setSelectedPin(p.id)} style={{
              position:'absolute', left:p.x, top:p.y, transform:'translate(-50%,-50%)',
              background:'transparent', border:0, padding:0, cursor:'pointer', zIndex:6,
            }}>
              <div style={{
                width: selectedPin === p.id ? 18 : 14,
                height: selectedPin === p.id ? 18 : 14,
                borderRadius:'50%',
                background: statusColor(p.status),
                border:'2px solid var(--bg-elev)',
                boxShadow: p.status === 'drop'
                  ? mapDropQualified
                    ? '0 0 0 5px var(--warm-soft), 0 0 20px rgba(214,119,54,0.36)'
                    : '0 0 0 5px var(--bg-sunk)'
                  : selectedPin === p.id ? `0 0 0 4px ${statusColor(p.status)}33` : 'none',
                transition:'all .15s',
                animation:p.status === 'drop' && mapDropQualified ? 'mapdrop-pulse 1.8s ease-in-out infinite' : 'none',
                opacity:p.status === 'drop' && !mapDropQualified ? 0.58 : 1,
              }}/>
              {p.status === 'drop' && (
                <span style={{
                  position:'absolute', left:'50%', top:18, transform:'translateX(-50%)',
                  background:'var(--bg-elev)', border:'1px solid var(--line)', borderRadius:999,
                  padding:'2px 6px', fontFamily:'var(--font-mono)', fontSize:8.5, fontWeight:700,
                  color:mapDropQualified ? 'var(--warm)' : 'var(--ink-3)', whiteSpace:'nowrap',
                }}>{mapDropQualified ? `${p.left} left` : 'locked'}</span>
              )}
            </button>
          ))}

          {/* Coverage gap label */}
          {filters.stale && (
            <div style={{
              position:'absolute', left:'72%', top:'85%',
              transform:'translate(-50%,-50%)',
              background:'var(--bg-elev)', border:'1px solid var(--line)', borderRadius:6,
              padding:'4px 10px', fontFamily:'var(--font-sans)', fontSize:11, fontWeight:500,
              color:'var(--status-stale)',
              whiteSpace:'nowrap', zIndex:4,
            }}>Coverage gap · 12 POIs</div>
          )}
        </div>

        {/* Top bar */}
        <div style={{
          position:'absolute', top:0, left:0, right:0,
          padding:'12px 16px',
          display:'flex', gap:8, alignItems:'center',
          background:'linear-gradient(var(--bg) 60%, transparent)',
          zIndex:10,
        }}>
          <div style={{
            flex:1, background:'var(--bg-elev)', border:'1px solid var(--line)',
            borderRadius:10, padding:'10px 14px',
            display:'flex', alignItems:'center', gap:8,
          }}>
            <svg width="14" height="14" viewBox="0 0 14 14" fill="none">
              <circle cx="6" cy="6" r="4.5" stroke="var(--ink-3)" strokeWidth="1.3"/>
              <path d="M 9.5 9.5 L 12.5 12.5" stroke="var(--ink-3)" strokeWidth="1.3" strokeLinecap="round"/>
            </svg>
            <span style={{fontSize:13, color:'var(--ink-3)'}}>Search this sector</span>
          </div>
          <button style={{
            width:40, height:40, borderRadius:10,
            background:'var(--bg-elev)', border:'1px solid var(--line)',
            cursor:'pointer', display:'flex', alignItems:'center', justifyContent:'center',
          }}>
            <svg width="16" height="16" viewBox="0 0 16 16" fill="none">
              <path d="M 2 4 L 14 4 M 4 8 L 12 8 M 6 12 L 10 12" stroke="var(--ink)" strokeWidth="1.4" strokeLinecap="round"/>
            </svg>
          </button>
        </div>

        {/* Layer chips */}
        <div style={{
          position:'absolute', top:64, left:0, right:0,
          padding:'4px 16px',
          display:'flex', gap:6, overflowX:'auto', zIndex:9,
        }}>
          {[
            {id:'missions', label:'Missions · 12'},
            {id:'mapdrop', label:'Map Drop · 5'},
            {id:'verified', label:'Verified · 84'},
            {id:'outdated', label:'Outdated · 23'},
            {id:'gaps', label:'Gaps · 4'},
            {id:'mine', label:'My contributions'},
            {id:'world', label:'▣ World'},
          ].map(c => (
            <button key={c.id} onClick={() => c.id === 'world' ? (onWorldOpen && onWorldOpen()) : setLayer(c.id)} style={{
              padding:'6px 13px',
              borderRadius:999,
              border:'1px solid var(--line)',
              background: layer === c.id ? 'var(--ink)' : 'var(--bg-elev)',
              color: layer === c.id ? 'var(--bg)' : 'var(--ink-2)',
              fontFamily:'var(--font-sans)', fontSize:12,
              cursor:'pointer', whiteSpace:'nowrap',
              fontWeight: layer === c.id ? 600 : 400,
            }}>{c.label}</button>
          ))}
        </div>

        {/* Filter legend */}
        <div style={{
          position:'absolute', left:16, top:116,
          background:'var(--bg-elev)', border:'1px solid var(--line)',
          borderRadius:10, padding:'10px 12px', zIndex:9,
          display:'flex', flexDirection:'column', gap:6,
        }}>
          <div className="mono" style={{fontSize:9, marginBottom:2}}>FILTER</div>
          {[
            {id:'avail', c:'var(--status-done)', l:'Available'},
            {id:'stale', c:'var(--status-stale)', l:'Outdated'},
            {id:'rare', c:'var(--status-rare)', l:'Rare'},
            {id:'done', c:'var(--ink-3)', l:'Done'},
            {id:'drop', c:'var(--warm)', l:'Map Drop'},
          ].map(row => (
            <button key={row.id} onClick={() => toggleFilter(row.id)} style={{
              display:'flex', alignItems:'center', gap:8,
              background:'transparent', border:0, padding:0,
              cursor:'pointer', opacity:filters[row.id] ? 1 : 0.35,
              fontFamily:'var(--font-sans)',
            }}>
              <span style={{
                width:12, height:12, borderRadius:4,
                border:'1px solid var(--line)', background:filters[row.id] ? row.c : 'transparent',
                display:'inline-flex', alignItems:'center', justifyContent:'center',
                color:'#fff', fontSize:8, lineHeight:1,
              }}>{filters[row.id] ? '✓' : ''}</span>
              <span style={{fontSize:11, color:'var(--ink-3)'}}>{row.l}</span>
            </button>
          ))}
        </div>

        {/* Map controls (right side) */}
        <div style={{position:'absolute', right:16, bottom: sel ? (sel.status === 'drop' ? 420 : sheetExpanded ? 520 : 240) : 24, display:'flex', flexDirection:'column', gap:8, zIndex:9, transition:'bottom .2s'}}>
          {[
            {icon: '+', label:'Zoom in', onClick:() => zoomBy(0.2)},
            {icon: '−', label:'Zoom out', onClick:() => zoomBy(-0.2)},
            {icon: '◎', label:'Re-center', onClick:recenter},
          ].map((b) => (
            <button key={b.label} aria-label={b.label} onClick={b.onClick} style={{
              width:40, height:40, borderRadius:10,
              background:'var(--bg-elev)', border:'1px solid var(--line)',
              cursor:'pointer', fontSize:16, color:'var(--ink)',
              fontFamily:'var(--font-sans)', fontWeight:500,
            }}>{b.icon}</button>
          ))}
        </div>

        {/* Selected pin sheet */}
        {sel && (
          <div style={{
            position:'absolute', left:12, right:12, bottom:12, zIndex:11,
            background:'var(--bg-elev)', border:'1px solid var(--line)',
            borderRadius:14, padding:'8px 14px 14px',
            boxShadow:'0 -4px 24px rgba(0,0,0,0.06)',
            maxHeight:sel.status === 'drop' ? 400 : sheetExpanded ? 500 : 220,
            overflow:'hidden',
            transition:'max-height .24s ease',
          }}>
            <button
              type="button"
              aria-label={sheetExpanded ? 'Collapse POI details' : 'Expand POI details'}
              onClick={onSheetHandleClick}
              onPointerDown={onSheetPointerDown}
              onPointerMove={onSheetPointerMove}
              onPointerUp={onSheetPointerUp}
              onPointerCancel={onSheetPointerUp}
              style={{
                width:'100%', height:24, background:'transparent', border:0,
                display:'flex', alignItems:'center', justifyContent:'center',
                cursor:'ns-resize', padding:0,
              }}
            >
              <span style={{
                width:42, height:4, borderRadius:999, background:'var(--line-2)',
                display:'block',
              }}/>
            </button>
            <div style={{display:'flex', justifyContent:'space-between', alignItems:'flex-start', marginBottom:10}}>
              <div className="mono" style={{fontSize:10, color: statusColor(sel.status), display:'inline-flex', gap:6, alignItems:'center'}}>
                <span style={{width:6, height:6, borderRadius:'50%', background:statusColor(sel.status)}}/>
                {sel.type.toUpperCase()}
              </div>
              <button onClick={()=>setSelectedPin(null)} style={{
                background:'transparent', border:0, color:'var(--ink-3)',
                cursor:'pointer', fontSize:18, lineHeight:1, padding:0,
              }}>×</button>
            </div>
            <div style={{display:'flex', gap:12}}>
              <CoordGlyph seed={sel.id + sel.label} size={56} accent={statusColor(sel.status)}/>
              <div style={{flex:1, minWidth:0}}>
                <div style={{fontSize:16, fontWeight:600, letterSpacing:'-0.015em'}}>{sel.label}</div>
                <div style={{fontSize:12, color:'var(--ink-3)', marginTop:2}}>{sel.dist} away · Daikanyama</div>
                <div style={{display:'flex', gap:6, marginTop:8}}>
                  {sel.cp > 0 && <Pill tone="teal">+{sel.cp} GP</Pill>}
                  {sel.status === 'rare' && <Pill tone="rare">◇ Rare</Pill>}
                  {sel.status === 'drop' && <Pill tone={mapDropQualified ? 'rare' : undefined}>
                    {mapDropQualified ? `${sel.left} of ${sel.total} left` : 'Access locked'}
                  </Pill>}
                </div>
              </div>
            </div>
            {sel.status === 'drop' ? (
              <MapDropActions
                drop={sel}
                access={mapDropAccess}
                qualified={mapDropQualified}
                redeemed={dropRedeemed}
                reviewSubmitted={reviewSubmitted}
                onVerify={() => setDropRedeemed(true)}
                onReview={() => setReviewSubmitted(true)}
                onStartMission={() => onMissionTap && onMissionTap({type:'verify', label:'Nearest POI mission', title:'Nearest POI mission', cp:40, dist:'120m', distance:'120m'})}
              />
            ) : sel.cp > 0 && (
              <button className="btn-primary" style={{marginTop:12, height:42}}
                onClick={() => onMissionTap && onMissionTap(sel)}>
                Start mission →
              </button>
            )}
            {sheetExpanded && (
              <div style={{
                marginTop:12, paddingTop:12, borderTop:'1px solid var(--line)',
                maxHeight:250, overflowY:'auto',
              }}>
                <div style={{display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:10}}>
                  <div style={{fontSize:14, fontWeight:700}}>Community details</div>
                  <span className="mono" style={{fontSize:9, color:'var(--ink-3)'}}>3 CONTRIBUTIONS</span>
                </div>
                <div style={{display:'grid', gap:9}}>
                  {contributedInfo.map(item => (
                    <div key={item.title} style={{
                      display:'grid', gridTemplateColumns:'62px 1fr', gap:10,
                      padding:10, border:'1px solid var(--line)', borderRadius:12,
                      background:'var(--bg-sunk)',
                    }}>
                      <div style={{
                        width:62, height:62, borderRadius:10, overflow:'hidden',
                        position:'relative', background:'var(--bg-elev)',
                      }}>
                        <img src={poiPhoto(item.seed, 160, 160)} alt={item.title} className="photo-cover" style={{position:'absolute', inset:0}}/>
                      </div>
                      <div style={{minWidth:0}}>
                        <div style={{fontSize:13, fontWeight:700, marginBottom:2}}>{item.title}</div>
                        <div className="mono" style={{fontSize:8.5, color:'var(--teal-ink)', marginBottom:5}}>{item.meta}</div>
                        <div style={{fontSize:12, color:'var(--ink-3)', lineHeight:1.35}}>{item.body}</div>
                      </div>
                    </div>
                  ))}
                </div>
              </div>
            )}
          </div>
        )}
      </div>
      <TabBar active="map" onChange={onTabChange}/>
    </>
  );
}

function MapDropActions({ drop, access, qualified, redeemed, reviewSubmitted, onVerify, onReview, onStartMission }) {
  const remaining = Math.max(0, access.requiredPoi - access.completedPoi);
  const districtPct = Math.min(100, Math.round((access.districtProgress / access.districtTarget) * 100));

  return (
    <div style={{marginTop:12}}>
      <div style={{
        display:'grid', gridTemplateColumns:'1fr 1fr 1fr', gap:6, marginBottom:10,
      }}>
        {[
          ['Reward', drop.reward],
          ['Window', drop.expires],
          ['Radius', '50m GPS'],
        ].map(row => (
          <div key={row[0]} style={{background:'var(--bg-sunk)', borderRadius:9, padding:'8px 7px', minHeight:52}}>
            <div style={{fontSize:10, color:'var(--ink-3)', marginBottom:4}}>{row[0]}</div>
            <div style={{fontSize:11.5, fontWeight:700, lineHeight:1.2}}>{row[1]}</div>
          </div>
        ))}
      </div>

      {!qualified ? (
        <div style={{
          border:'1px solid var(--line)', borderRadius:12,
          background:'var(--bg-sunk)', padding:12,
        }}>
          <div style={{display:'flex', justifyContent:'space-between', alignItems:'flex-start', gap:10, marginBottom:10}}>
            <div>
              <div className="mono" style={{fontSize:9, color:'var(--warm)', marginBottom:4}}>QUALIFICATION REQUIRED</div>
              <div style={{fontSize:14, fontWeight:800, letterSpacing:'-0.01em'}}>Map Drops are for trusted contributors.</div>
            </div>
            <Pill>Locked</Pill>
          </div>
          <div style={{display:'grid', gridTemplateColumns:'1fr 1fr', gap:8, marginBottom:10}}>
            <div style={{background:'var(--bg-elev)', borderRadius:9, padding:9}}>
              <div style={{fontSize:10.5, color:'var(--ink-3)', marginBottom:5}}>POI missions</div>
              <div style={{fontFamily:'var(--font-mono)', fontSize:15, fontWeight:800}}>
                {access.completedPoi}/{access.requiredPoi}
              </div>
              <div style={{fontSize:10.5, color:'var(--ink-3)', marginTop:4}}>{remaining} more needed</div>
            </div>
            <div style={{background:'var(--bg-elev)', borderRadius:9, padding:9}}>
              <div style={{fontSize:10.5, color:'var(--ink-3)', marginBottom:5}}>District rank</div>
              <div style={{fontFamily:'var(--font-mono)', fontSize:15, fontWeight:800}}>
                #{access.districtRank}
              </div>
              <div style={{fontSize:10.5, color:'var(--ink-3)', marginTop:4}}>Top {access.rankCutoff} qualifies</div>
            </div>
          </div>
          <div style={{height:5, background:'var(--bg-elev)', borderRadius:999, overflow:'hidden', marginBottom:9}}>
            <div style={{height:'100%', width:districtPct + '%', background:'var(--warm)', borderRadius:999}}/>
          </div>
          <div style={{fontSize:11, color:'var(--ink-3)', lineHeight:1.35, marginBottom:10}}>
            District unlock: {access.districtProgress}/{access.districtTarget} trusted POI contributions before this drop expands.
          </div>
          <button className="btn-primary" style={{height:40}} onClick={onStartMission}>
            Complete a POI mission
          </button>
        </div>
      ) : (
        <>
      {!redeemed ? (
        <>
          <button className="btn-primary" style={{height:42}} onClick={onVerify}>
            Verify arrival + unlock code
          </button>
          <div style={{fontSize:11, color:'var(--ink-3)', lineHeight:1.35, marginTop:8}}>
            Requires GPS at the storefront and one live photo. Screenshots do not redeem.
          </div>
        </>
      ) : (
        <div style={{
          border:'1px solid var(--line)', borderRadius:12,
          background:'var(--warm-soft)', padding:12,
        }}>
          <div style={{display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:8}}>
            <div>
              <div className="mono" style={{fontSize:9, color:'var(--warm)'}}>REDEMPTION CODE</div>
              <div style={{fontFamily:'var(--font-mono)', fontSize:20, fontWeight:800, letterSpacing:'0.04em'}}>DROP-1842</div>
            </div>
            <Pill tone="teal">GPS locked</Pill>
          </div>
          {reviewSubmitted ? (
            <div style={{fontSize:12, color:'var(--teal-ink)', fontWeight:700}}>In-store review submitted. Follow-up review unlocks in 24h.</div>
          ) : (
            <div>
              <div style={{fontSize:12, color:'var(--ink-2)', marginBottom:8}}>Submit the quick in-store rating before you leave.</div>
              <div style={{display:'grid', gridTemplateColumns:'repeat(4, 1fr)', gap:6}}>
                {['Taste', 'Space', 'Service', 'Value'].map(label => (
                  <button key={label} onClick={onReview} style={{
                    height:34, borderRadius:8, border:'1px solid var(--line)',
                    background:'var(--bg-elev)', fontFamily:'var(--font-sans)',
                    fontSize:11, fontWeight:700, color:'var(--ink)', cursor:'pointer',
                  }}>{label}</button>
                ))}
              </div>
            </div>
          )}
        </div>
      )}
        </>
      )}
    </div>
  );
}

window.MapScreen = MapScreen;
