// Directory (listings) page
const SHOPS = [
  { id: 'fieldhouse', name: 'Fieldhouse', city: 'Hudson, NY', vibe: 'Quiet · Kitchen-like', rating: 4.9, reviews: 312, price: '$$', img: IMG.dispensary1, tagline: 'Feels like visiting a friend who happens to stock excellent pre-rolls.', hours: 'Open til 9pm', known: ['Small-batch flower', 'House tinctures', 'Sunday readings'] },
  { id: 'poppy', name: 'Poppy & Stem', city: 'Brooklyn, NY', vibe: 'Social · Warm', rating: 4.8, reviews: 548, price: '$$$', img: IMG.dispensary2, tagline: 'A neighborhood shop with a long bench out front and a dog named Juno.', hours: 'Open til 10pm', known: ['Curated edibles', 'Local art', 'Friendliest budtenders'] },
  { id: 'slow-sunday', name: 'Slow Sunday', city: 'Portland, OR', vibe: 'Artsy · Minimal', rating: 4.9, reviews: 221, price: '$$', img: IMG.dispensary3, tagline: 'White walls, one long oak table, and a single plant in the window.', hours: 'Open til 8pm', known: ['Single-origin flower', 'Glasswork', 'Quiet'] },
  { id: 'homestead', name: 'Homestead Co.', city: 'Boulder, CO', vibe: 'Rustic · Practical', rating: 4.7, reviews: 189, price: '$', img: IMG.dispensary4, tagline: 'Pine shelves, handwritten labels, the smell of cedar.', hours: 'Open til 8pm', known: ['Budget picks', 'Honest menu', 'Local growers'] },
  { id: 'night-garden', name: 'Night Garden', city: 'Los Angeles, CA', vibe: 'Dreamy · Evening', rating: 4.8, reviews: 702, price: '$$$', img: IMG.evening, tagline: 'Low lights, a record player, and the best sativa rotation in Silverlake.', hours: 'Open til 11pm', known: ['Evening rituals', 'Vinyl Sundays', 'Rare strains'] },
  { id: 'the-porch', name: 'The Porch', city: 'Austin, TX', vibe: 'Farmers market', rating: 4.7, reviews: 156, price: '$$', img: IMG.market, tagline: 'Stationed next to the Saturday farmers market. Good iced tea, better advice.', hours: 'Open til 9pm', known: ['Texas-made goods', 'Iced tea bar', 'Weekend markets'] },
];

function Directory({ go }) {
  const [q, setQ] = React.useState('');
  const [vibe, setVibe] = React.useState('All');
  const [view, setView] = React.useState('list'); // 'list' | 'map'
  const [sort, setSort] = React.useState('Editor\'s pick');

  const filtered = SHOPS.filter(s =>
    (q === '' || (s.name + s.city).toLowerCase().includes(q.toLowerCase())) &&
    (vibe === 'All' || s.vibe.toLowerCase().includes(vibe.toLowerCase()))
  );

  return (
    <div>
      {/* Directory hero */}
      <section style={{ maxWidth: 'var(--maxw)', margin: '0 auto', padding: '60px var(--gutter) 40px' }}>
        <div className="eyebrow" style={{ marginBottom: 20 }}>— The directory</div>
        <div style={{ display: 'grid', gridTemplateColumns: '2.2fr 1fr', gap: 60, alignItems: 'end' }}>
          <h1 className="serif" style={{ fontSize: 'clamp(48px, 6vw, 88px)', lineHeight: 0.98, margin: 0, fontWeight: 400, letterSpacing: '-0.02em' }}>
            Every shop, visited<br/>
            <em style={{ fontStyle: 'italic', color: 'var(--accent-deep)' }}>in person.</em>
          </h1>
          <p style={{ fontSize: 16, color: 'var(--ink-soft)', lineHeight: 1.6, margin: 0 }}>
            412 shops. 38 states. No paid placements, ever. We write up each one the way we'd tell a friend about it.
          </p>
        </div>
      </section>

      {/* Search bar */}
      <section style={{ maxWidth: 'var(--maxw)', margin: '0 auto', padding: '0 var(--gutter)' }}>
        <div style={{
          display: 'flex', gap: 8, alignItems: 'stretch',
          background: 'white', padding: 8, borderRadius: 999,
          boxShadow: '0 10px 40px rgba(0,0,0,0.06)', border: '1px solid var(--hairline)',
          maxWidth: 720,
        }}>
          <div style={{ display: 'flex', alignItems: 'center', padding: '0 16px', color: 'var(--ink-soft)' }}>
            <Icon.search size={16}/>
          </div>
          <input placeholder="Search by shop, city, or ZIP" value={q} onChange={e => setQ(e.target.value)}
                 style={{ border: 'none', outline: 'none', flex: 1, fontFamily: 'var(--sans)', fontSize: 15, background: 'transparent' }}/>
          <select value={vibe} onChange={e => setVibe(e.target.value)}
                  style={{ border: 'none', outline: 'none', background: 'var(--bg-tint)', padding: '0 16px', borderRadius: 999, fontFamily: 'var(--sans)', fontSize: 13, color: 'var(--ink)' }}>
            {['All', 'Quiet', 'Social', 'Artsy', 'Rustic', 'Dreamy', 'Farmers'].map(v => <option key={v}>{v}</option>)}
          </select>
          <button className="btn btn-primary" style={{ padding: '12px 20px', fontSize: 13 }}>
            Search <Icon.arrow size={12}/>
          </button>
        </div>

        <div style={{ marginTop: 28, display: 'flex', justifyContent: 'space-between', alignItems: 'center', flexWrap: 'wrap', gap: 16 }}>
          <div style={{ fontSize: 14, color: 'var(--ink-soft)' }}>
            <span style={{ color: 'var(--ink)', fontWeight: 500 }}>{filtered.length} shops</span> · sorted by {sort.toLowerCase()}
          </div>
          <div style={{ display: 'flex', gap: 10, alignItems: 'center' }}>
            <div style={{ display: 'inline-flex', background: 'white', border: '1px solid var(--hairline)', borderRadius: 999, padding: 4 }}>
              {['list', 'map'].map(v => (
                <button key={v} onClick={() => setView(v)}
                        style={{ padding: '8px 16px', border: 'none', borderRadius: 999,
                                 background: view === v ? 'var(--ink)' : 'transparent',
                                 color: view === v ? 'var(--bg)' : 'var(--ink)',
                                 fontSize: 12, fontFamily: 'var(--sans)', cursor: 'pointer', letterSpacing: '0.06em', textTransform: 'uppercase' }}>
                  {v}
                </button>
              ))}
            </div>
            <select value={sort} onChange={e => setSort(e.target.value)}
                    style={{ border: '1px solid var(--hairline)', borderRadius: 999, padding: '8px 16px', fontFamily: 'var(--sans)', fontSize: 13, background: 'white', color: 'var(--ink)', outline: 'none' }}>
              <option>Editor's pick</option>
              <option>Rating</option>
              <option>Nearest</option>
              <option>Newest</option>
            </select>
          </div>
        </div>
      </section>

      {/* Content */}
      {view === 'list' ? (
        <ListView shops={filtered} go={go} />
      ) : (
        <MapView shops={filtered} go={go} />
      )}
    </div>
  );
}

function ListView({ shops, go }) {
  return (
    <section style={{ maxWidth: 'var(--maxw)', margin: '0 auto', padding: '40px var(--gutter) 80px' }}>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 32 }}>
        {shops.map((s, i) => <ShopCard key={s.id} shop={s} idx={i+1} go={go} />)}
      </div>
    </section>
  );
}

function ShopCard({ shop, idx, go }) {
  return (
    <article onClick={() => go('/shop/' + shop.id)} className="shop-card" style={{ cursor: 'pointer', display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 20 }}>
      <div className="shop-img-wrap" style={{ overflow: 'hidden' }}>
        <WarmImg src={shop.img} aspect="4/5" placeholder="shop" />
      </div>
      <div style={{ display: 'flex', flexDirection: 'column', justifyContent: 'space-between', padding: '8px 0' }}>
        <div>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline' }}>
            <div className="eyebrow" style={{ color: 'var(--accent-deep)' }}>{String(idx).padStart(2, '0')} · {shop.vibe}</div>
            <div style={{ fontFamily: 'var(--sans)', fontSize: 12, color: 'var(--ink-soft)' }}>{shop.price}</div>
          </div>
          <h3 className="serif" style={{ fontSize: 28, lineHeight: 1.1, margin: '12px 0 6px', fontWeight: 500, letterSpacing: '-0.01em' }}>{shop.name}</h3>
          <div style={{ fontSize: 13, color: 'var(--ink-soft)', display: 'flex', alignItems: 'center', gap: 8 }}>
            <Icon.pin size={12}/>{shop.city}
          </div>
          <p style={{ fontSize: 14, lineHeight: 1.55, color: 'var(--ink)', marginTop: 14, fontStyle: 'italic', textWrap: 'pretty' }}>
            "{shop.tagline}"
          </p>
        </div>
        <div style={{ marginTop: 16, display: 'flex', justifyContent: 'space-between', alignItems: 'center', paddingTop: 14, borderTop: '1px solid var(--hairline)' }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 6, color: 'var(--accent-deep)', fontSize: 13 }}>
            <Icon.star size={13}/>
            <span style={{ color: 'var(--ink)', fontWeight: 500 }}>{shop.rating}</span>
            <span style={{ color: 'var(--ink-soft)' }}>({shop.reviews})</span>
          </div>
          <div style={{ fontSize: 12, color: 'var(--sage-deep)', display: 'flex', alignItems: 'center', gap: 6 }}>
            <span style={{ width: 6, height: 6, borderRadius: '50%', background: 'var(--sage)' }}></span>
            {shop.hours}
          </div>
        </div>
      </div>
    </article>
  );
}

function MapView({ shops, go }) {
  const [hover, setHover] = React.useState(null);
  return (
    <section style={{ maxWidth: 'var(--maxw)', margin: '0 auto', padding: '40px var(--gutter) 80px' }}>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1.4fr', gap: 24, height: 720 }}>
        {/* Shop list */}
        <div style={{ overflow: 'auto', paddingRight: 10 }}>
          {shops.map((s, i) => (
            <div key={s.id} onClick={() => go('/shop/' + s.id)} onMouseEnter={() => setHover(s.id)} onMouseLeave={() => setHover(null)}
                 style={{ display: 'flex', gap: 16, padding: '18px 0', borderBottom: '1px solid var(--hairline)', cursor: 'pointer',
                          background: hover === s.id ? 'var(--bg-tint)' : 'transparent', transition: 'background 180ms', marginLeft: hover === s.id ? -12 : 0, paddingLeft: hover === s.id ? 12 : 0, paddingRight: 12, borderRadius: hover === s.id ? 4 : 0 }}>
              <div style={{ width: 88, height: 88, flexShrink: 0, overflow: 'hidden' }}>
                <WarmImg src={s.img} aspect="1/1" placeholder="shop"/>
              </div>
              <div style={{ flex: 1 }}>
                <div className="eyebrow" style={{ color: 'var(--accent-deep)', fontSize: 10, marginBottom: 6 }}>{String(i+1).padStart(2, '0')} · {s.vibe}</div>
                <div className="serif" style={{ fontSize: 20, fontWeight: 500 }}>{s.name}</div>
                <div style={{ fontSize: 12, color: 'var(--ink-soft)', marginTop: 2 }}>{s.city}</div>
                <div style={{ marginTop: 8, display: 'flex', gap: 10, alignItems: 'center', fontSize: 12, color: 'var(--ink-soft)' }}>
                  <span style={{ color: 'var(--accent-deep)', display: 'inline-flex', alignItems: 'center', gap: 4 }}>
                    <Icon.star size={11}/> {s.rating}
                  </span>
                  <span className="dot"></span>
                  <span>{s.price}</span>
                  <span className="dot"></span>
                  <span>{s.hours}</span>
                </div>
              </div>
            </div>
          ))}
        </div>
        {/* Map */}
        <div style={{ position: 'relative', background: 'var(--bg-tint)', borderRadius: 4, overflow: 'hidden', border: '1px solid var(--hairline)' }}>
          {/* Stylized map background */}
          <svg viewBox="0 0 600 720" preserveAspectRatio="xMidYMid slice" style={{ position: 'absolute', inset: 0, width: '100%', height: '100%' }}>
            <rect width="600" height="720" fill="#F0E6D2"/>
            {/* rivers */}
            <path d="M 0 200 Q 150 240, 280 210 T 600 260" stroke="#C3D4C4" strokeWidth="22" fill="none" opacity="0.6"/>
            <path d="M 80 500 Q 220 440, 360 480 T 600 520" stroke="#C3D4C4" strokeWidth="14" fill="none" opacity="0.55"/>
            {/* parks */}
            <ellipse cx="180" cy="320" rx="80" ry="55" fill="#C3D4C4" opacity="0.55"/>
            <ellipse cx="420" cy="580" rx="70" ry="44" fill="#C3D4C4" opacity="0.55"/>
            {/* streets */}
            {Array.from({length: 18}).map((_, i) => (
              <line key={'v'+i} x1={i*40} y1="0" x2={i*40} y2="720" stroke="rgba(58,58,58,0.08)" strokeWidth="1"/>
            ))}
            {Array.from({length: 22}).map((_, i) => (
              <line key={'h'+i} x1="0" y1={i*40} x2="600" y2={i*40} stroke="rgba(58,58,58,0.08)" strokeWidth="1"/>
            ))}
            {/* Diagonal */}
            <line x1="0" y1="100" x2="600" y2="400" stroke="rgba(58,58,58,0.12)" strokeWidth="2"/>
            <line x1="120" y1="720" x2="540" y2="0" stroke="rgba(58,58,58,0.1)" strokeWidth="2"/>
          </svg>
          {/* Pins */}
          {shops.map((s, i) => {
            const positions = [[22, 30], [58, 22], [40, 55], [72, 48], [30, 74], [65, 80]];
            const [x, y] = positions[i % positions.length];
            const active = hover === s.id;
            return (
              <div key={s.id} style={{ position: 'absolute', left: x + '%', top: y + '%', transform: 'translate(-50%, -100%)', cursor: 'pointer', zIndex: active ? 10 : 1 }}
                   onMouseEnter={() => setHover(s.id)} onMouseLeave={() => setHover(null)} onClick={() => go('/shop/' + s.id)}>
                <div style={{
                  background: active ? 'var(--accent)' : 'var(--ink)', color: 'white',
                  padding: '8px 14px', borderRadius: 999, fontFamily: 'var(--serif)', fontSize: 14,
                  boxShadow: '0 6px 18px rgba(0,0,0,0.2)', whiteSpace: 'nowrap',
                  transform: active ? 'scale(1.08)' : 'scale(1)', transition: 'all 200ms ease',
                }}>
                  {s.name}
                </div>
                <div style={{ width: 10, height: 10, background: active ? 'var(--accent)' : 'var(--ink)', transform: 'rotate(45deg) translate(-50%, -50%)', margin: '-4px auto 0', transformOrigin: 'center', width: 12, height: 12, marginLeft: '50%' }}></div>
              </div>
            );
          })}
          {/* Legend */}
          <div style={{ position: 'absolute', bottom: 16, left: 16, background: 'white', padding: '10px 16px', borderRadius: 999, boxShadow: '0 6px 20px rgba(0,0,0,0.1)', fontSize: 12, display: 'flex', gap: 14, alignItems: 'center' }}>
            <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>
              <span style={{ width: 10, height: 10, background: 'var(--accent)', borderRadius: '50%' }}></span>Editor's picks
            </span>
            <span className="dot"></span>
            <span>{shops.length} shops visible</span>
          </div>
        </div>
      </div>
    </section>
  );
}

Object.assign(window, { Directory, SHOPS });
