// map-iso.jsx — REAL GPS map (Leaflet + dark tiles) for the Las Vegas Strip.
// Toggle: My Boys (real friends) vs Fantasy Roster (drafted pros).
// Markers sit on actual lat/lng of each casino. Crew chat panel for nudging pros.

const { useState: uS_iso, useMemo: uM_iso, useEffect: uE_iso, useRef: uR_iso } = React;

// ───── Real-world coordinates ─────────────────────────────────────────────
const CASINO_COORDS = {
  'Resorts World':  [36.1369, -115.1671],
  'Wynn':           [36.1267, -115.1668],
  'Venetian':       [36.1213, -115.1693],
  'Horseshoe':      [36.1143, -115.1739],
  'Paris':          [36.1126, -115.1707],
  'Bellagio':       [36.1126, -115.1767],
  'Cosmopolitan':   [36.1101, -115.1750],
  'Aria':           [36.1075, -115.1764],
  'MGM':            [36.1023, -115.1697],
  'Orleans':        [36.1015, -115.2106],
};
const YOU_COORDS = [36.1101, -115.1750]; // at Cosmo

function venueKey(s) {
  if (!s) return null;
  const lower = String(s).toLowerCase();
  for (const k of Object.keys(CASINO_COORDS)) {
    if (lower.includes(k.toLowerCase())) return k;
  }
  return null;
}

// ───── Main map component ─────────────────────────────────────────────────
function IsoStripMap({ tournaments, friends, onZoomIn, onPin }) {
  const [layer, setLayer] = uS_iso('boys'); // 'boys' | 'fantasy'
  const [selected, setSelected] = uS_iso(null);
  const [chatOpen, setChatOpen] = uS_iso(false);
  const [messages, setMessages] = uS_iso([
    { who: 'You',     avatar: 'AH', text: "Phil busted #54 L8. Throwing him in $1k Mystery if he wants.", ts: '2:08 PM' },
    { who: 'Phil H.', avatar: 'PH', text: "tilted but in. $1k buyin?", ts: '2:11 PM', isRoster: true },
    { who: 'Kyle',    avatar: '◆',  text: "Phil on a soft Mystery field = +60 POY EV. Send it.", ts: '2:12 PM', isCoach: true },
  ]);

  const fantasy = window.APP_DATA.fantasy.myLeague;
  const roster = fantasy.myRoster;

  // Build people list for the active layer
  const people = uM_iso(() => {
    if (layer === 'fantasy') {
      return roster.map(r => ({
        kind: 'fantasy', id: r.id, name: r.name, handle: r.handle,
        status: r.status, chips: r.chips, avg: r.avg, pts: r.pts,
        avatar: r.avatar, venue: venueKey(r.venue), where: r.where,
        table: r.table, lastEvent: r.lastEvent,
      }));
    }
    return friends.map(f => ({
      kind: 'friend', id: f.id, name: f.name, handle: f.handle,
      status: f.status, chips: f.chips, avg: f.avg,
      avatar: f.name.slice(0,2).toUpperCase(),
      venue: venueKey((f.where || '').split(' · ')[1] || f.where),
      where: f.where, table: f.table,
      lastSeen: f.lastSeen, lastResult: f.lastResult,
    }));
  }, [layer, friends]);

  const peopleByVenue = uM_iso(() => {
    const m = {};
    people.forEach(p => { if (p.venue) (m[p.venue] = m[p.venue] || []).push(p); });
    return m;
  }, [people]);

  const eventsByVenue = uM_iso(() => {
    const m = {};
    tournaments.forEach(t => {
      const v = t.casino === 'Venetian Poker' ? 'Venetian' : t.casino;
      (m[v] = m[v] || []).push(t);
    });
    return m;
  }, [tournaments]);

  const alive = people.filter(p => p.status === 'alive').length;
  const busted = people.filter(p => p.status === 'busted').length;

  // ── Leaflet setup ───────────────────────────────────────────────────────
  const mapDivRef = uR_iso(null);
  const mapRef = uR_iso(null);
  const markerLayerRef = uR_iso(null);

  uE_iso(() => {
    if (!mapDivRef.current || mapRef.current) return;
    if (!window.L) return;

    const L = window.L;
    const map = L.map(mapDivRef.current, {
      center: [36.117, -115.174],
      zoom: 14,
      zoomControl: false,
      attributionControl: false,
      scrollWheelZoom: false,
      doubleClickZoom: true,
      touchZoom: true,
      dragging: true,
    });

    // Dark tiles — CartoDB dark_matter (no API key)
    L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png', {
      maxZoom: 19,
      subdomains: 'abcd',
    }).addTo(map);

    L.control.zoom({ position: 'bottomright' }).addTo(map);

    markerLayerRef.current = L.layerGroup().addTo(map);
    mapRef.current = map;

    // Force resize after mount
    setTimeout(() => map.invalidateSize(), 100);

    // Felt-green tint that fades in past street level
    const updateFeltTint = () => {
      const z = map.getZoom();
      const t = Math.max(0, Math.min(1, (z - 14.5) / 2.5));
      if (mapDivRef.current) {
        mapDivRef.current.style.setProperty('--lr-felt', t.toFixed(2));
      }
    };
    map.on('zoom', updateFeltTint);
    updateFeltTint();

    return () => {
      map.remove();
      mapRef.current = null;
    };
  }, []);

  // ── Render markers when data/layer changes ─────────────────────────────
  uE_iso(() => {
    if (!mapRef.current || !markerLayerRef.current || !window.L) return;
    const L = window.L;
    const group = markerLayerRef.current;
    group.clearLayers();

    // YOU marker — pulsing blue dot
    const youIcon = L.divIcon({
      className: 'lr-you-icon',
      html: `<div class="lr-you"><div class="lr-you-pulse"></div><div class="lr-you-dot"></div><div class="lr-you-label">YOU</div></div>`,
      iconSize: [60, 60], iconAnchor: [30, 30],
    });
    L.marker(YOU_COORDS, { icon: youIcon, interactive: false }).addTo(group);

    // Casino markers — gold ◆ chip for venues with events, simple label otherwise
    Object.entries(CASINO_COORDS).forEach(([name, coords]) => {
      const events = eventsByVenue[name] || [];
      const ppl = peopleByVenue[name] || [];
      const isWSOP = name === 'Horseshoe';
      const evCount = events.length;

      // Pick the soonest-closing event for the countdown ring
      const soonest = events
        .filter(e => e.regClose && (e.regClose.getTime() - Date.now()) > 0)
        .sort((a, b) => a.regClose.getTime() - b.regClose.getTime())[0];
      const minsLeft = soonest
        ? Math.max(0, Math.floor((soonest.regClose.getTime() - Date.now()) / 60000))
        : null;
      // 90-minute reg window → percent remaining for the ring
      const pct = minsLeft != null ? Math.max(0, Math.min(1, minsLeft / 90)) : 0;
      const closing = minsLeft != null && minsLeft < 15;

      // Heat plume strength: any alive friend at a deep run (>1.5× avg) = full heat
      const heatAlive = ppl.filter(p => p.status === 'alive');
      const deepRatio = Math.max(0, ...heatAlive.map(p => p.avg ? (p.chips / p.avg) : 1));
      const heat = isWSOP ? 1 : Math.min(1, Math.max(0, (deepRatio - 1) * 1.4));

      const ringSvg = soonest ? `
        <svg class="lr-venue-ring" viewBox="0 0 40 40" width="40" height="40">
          <circle cx="20" cy="20" r="17" fill="none"
            stroke="rgba(212,175,55,0.18)" stroke-width="2.5"/>
          <circle cx="20" cy="20" r="17" fill="none"
            stroke="${closing ? '#d63b32' : '#d4af37'}" stroke-width="2.5"
            stroke-dasharray="${(pct * 106.8).toFixed(1)} 106.8"
            stroke-linecap="round"
            transform="rotate(-90 20 20)"/>
          <text x="20" y="23" text-anchor="middle"
            font-family="JetBrains Mono, monospace" font-size="9"
            font-weight="700" fill="${closing ? '#d63b32' : '#d4af37'}">${minsLeft}m</text>
        </svg>` : '';

      const html = `
        ${heat > 0 ? `<div class="lr-heat" style="--heat:${heat.toFixed(2)}"></div>` : ''}
        <div class="lr-venue ${isWSOP ? 'lr-venue-wsop' : ''} ${evCount ? 'lr-venue-events' : ''}">
          <div class="lr-venue-name">${isWSOP ? '◆ WSOP' : name.toUpperCase()}</div>
          ${evCount ? `<div class="lr-venue-events-chip">♠ ${evCount}</div>` : ''}
        </div>
        ${ringSvg}`;
      const venueIcon = L.divIcon({
        className: 'lr-venue-icon',
        html,
        iconSize: [110, 70], iconAnchor: [55, 35],
      });
      const m = L.marker(coords, { icon: venueIcon });
      if (isWSOP) m.on('click', () => onZoomIn && onZoomIn());
      m.addTo(group);
    });

    // People markers — clustered per venue, fanned out
    Object.entries(peopleByVenue).forEach(([name, ppl]) => {
      const base = CASINO_COORDS[name];
      if (!base) return;
      ppl.forEach((p, i) => {
        // Fan out around the casino
        const total = ppl.length;
        const angle = total === 1 ? -Math.PI / 2 : (Math.PI * 2 * i) / total - Math.PI / 2;
        const radius = 0.00065; // ~70m
        const lat = base[0] + Math.sin(angle) * radius * 0.7 + 0.0009;
        const lng = base[1] + Math.cos(angle) * radius;

        const stateColor =
          p.status === 'alive'    ? '#3aa168' :
          p.status === 'busted'   ? '#d63b32' :
          p.status === 'on_break' ? '#c98a1a' : '#7a8295';

        const metric = layer === 'fantasy'
          ? (p.pts != null ? `${p.pts}pt` : '')
          : (p.status === 'alive' && p.chips ? `${(p.chips/1000).toFixed(0)}k` : '');

        const isSel = selected && selected.id === p.id;
        const pulse = p.status === 'alive' ? `<div class="lr-pin-pulse" style="background:${stateColor}"></div>` : '';
        const html = `
          <div class="lr-pin ${isSel ? 'lr-pin-sel' : ''}">
            ${pulse}
            <div class="lr-pin-dot" style="border-color:${stateColor}">
              <div class="lr-pin-avatar">${p.avatar}</div>
              <div class="lr-pin-status" style="background:${stateColor}"></div>
            </div>
            ${metric ? `<div class="lr-pin-metric ${layer === 'fantasy' ? 'lr-pin-metric-fantasy' : ''}">${metric}</div>` : ''}
          </div>`;

        const icon = L.divIcon({
          className: 'lr-pin-icon',
          html,
          iconSize: [44, 56], iconAnchor: [22, 56],
        });
        const m = L.marker([lat, lng], { icon, zIndexOffset: 100 });
        m.on('click', () => setSelected(prev => prev && prev.id === p.id ? null : p));
        m.addTo(group);
      });
    });
  }, [layer, peopleByVenue, eventsByVenue, selected, onZoomIn]);

  const sendMsg = (text, target) => {
    if (!text || !text.trim()) return;
    const finalText = target ? text.replace('{name}', target.name.split(' ')[0]) : text;
    setMessages(m => [...m, { who: 'You', avatar: 'AH', text: finalText, ts: 'now', target: target && target.id }]);
    if (target) {
      setTimeout(() => setMessages(m => [...m, {
        who: target.name, avatar: target.avatar,
        text: pickReply(target), ts: 'now', isRoster: true,
      }]), 1400);
      setTimeout(() => setMessages(m => [...m, {
        who: 'Kyle', avatar: '◆',
        text: doyleTakeFor(target), ts: 'now', isCoach: true,
      }]), 2800);
    }
  };

  return (
    <div style={{ width: '100%', height: '100%', position: 'relative', overflow: 'hidden', background: '#0b0d12' }}>
      <div ref={mapDivRef} style={{ position: 'absolute', inset: 0 }}/>

      {/* CSS for markers */}
      <style>{`
        .lr-pin-icon, .lr-venue-icon, .lr-you-icon { background: transparent !important; border: 0 !important; }

        /* Felt-green tint that fades in as you zoom into casino-floor scale */
        .leaflet-tile-pane::after {
          content: '';
          position: absolute; inset: 0;
          background: radial-gradient(ellipse at center, rgba(20,80,55,0.45) 0%, rgba(15,40,30,0.15) 60%, transparent 100%);
          mix-blend-mode: multiply;
          opacity: var(--lr-felt, 0);
          transition: opacity 220ms ease;
          pointer-events: none;
        }

        /* Heat plume — gold glow on hero / deep-run venues */
        .lr-heat {
          position: absolute; left: 50%; top: 50%;
          width: 110px; height: 110px;
          transform: translate(-50%, -50%);
          background: radial-gradient(circle,
            rgba(212,175,55, calc(0.55 * var(--heat, 1))) 0%,
            rgba(212,175,55, calc(0.20 * var(--heat, 1))) 30%,
            rgba(212,175,55, 0) 70%);
          animation: lrHeat 3.2s ease-in-out infinite;
          pointer-events: none;
        }
        @keyframes lrHeat {
          0%, 100% { transform: translate(-50%, -50%) scale(0.9); opacity: 0.9; }
          50%      { transform: translate(-50%, -50%) scale(1.18); opacity: 1; }
        }

        /* Countdown ring on event venues */
        .lr-venue-ring {
          position: absolute; left: 50%; top: -8px;
          transform: translateX(-50%);
          pointer-events: none;
          filter: drop-shadow(0 1px 2px rgba(0,0,0,0.6));
        }

        /* Venue labels */
        .lr-venue {
          display: inline-flex; align-items: center; gap: 4px;
          padding: 3px 7px; background: rgba(14,20,34,0.85);
          border: 1px solid rgba(212,175,55,0.35);
          font-family: 'JetBrains Mono', monospace;
          font-size: 9.5px; letter-spacing: 0.12em; color: #d4af37;
          font-weight: 600; white-space: nowrap;
          box-shadow: 0 1px 4px rgba(0,0,0,0.5);
          backdrop-filter: blur(2px);
        }
        .lr-venue-wsop {
          background: rgba(26,62,122,0.95); border-color: #d4af37;
          color: #fff; font-size: 11px;
          box-shadow: 0 0 12px rgba(212,175,55,0.4), 0 1px 4px rgba(0,0,0,0.6);
        }
        .lr-venue-events { border-color: #d4af37; }
        .lr-venue-events-chip {
          background: #d4af37; color: #0e1422;
          padding: 0 4px; font-weight: 700; font-size: 9px;
        }

        /* YOU dot */
        .lr-you { position: relative; width: 60px; height: 60px;
          display: flex; align-items: center; justify-content: center; }
        .lr-you-pulse {
          position: absolute; width: 18px; height: 18px; border-radius: 50%;
          background: #4a90e2; opacity: 0.35;
          animation: lrPulse 2.2s ease-out infinite;
        }
        .lr-you-dot {
          position: absolute; width: 14px; height: 14px; border-radius: 50%;
          background: #4a90e2; border: 3px solid #fff;
          box-shadow: 0 0 12px rgba(74,144,226,0.7);
        }
        .lr-you-label {
          position: absolute; top: 42px;
          background: #4a90e2; color: #fff;
          font-family: 'JetBrains Mono', monospace; font-size: 9px;
          font-weight: 700; letter-spacing: 0.15em;
          padding: 1px 6px;
        }
        @keyframes lrPulse {
          0%   { transform: scale(0.6); opacity: 0.55; }
          70%  { transform: scale(2.6); opacity: 0; }
          100% { transform: scale(2.6); opacity: 0; }
        }

        /* Person pins */
        .lr-pin {
          position: relative; width: 44px; height: 56px;
          display: flex; flex-direction: column; align-items: center; gap: 2px;
        }
        .lr-pin-pulse {
          position: absolute; top: 6px; left: 12px;
          width: 20px; height: 20px; border-radius: 50%;
          opacity: 0.25; animation: lrPinPulse 2.4s ease-out infinite;
        }
        @keyframes lrPinPulse {
          0%   { transform: scale(0.8); opacity: 0.4; }
          70%  { transform: scale(2.2); opacity: 0; }
          100% { transform: scale(2.2); opacity: 0; }
        }
        .lr-pin-dot {
          position: relative; width: 30px; height: 30px; border-radius: 50%;
          background: #0e1422; border-width: 2.5px; border-style: solid;
          display: flex; align-items: center; justify-content: center;
          box-shadow: 0 2px 6px rgba(0,0,0,0.7);
        }
        .lr-pin-sel .lr-pin-dot {
          box-shadow: 0 0 0 2px #d4af37, 0 2px 8px rgba(212,175,55,0.5);
        }
        .lr-pin-avatar {
          font-family: 'JetBrains Mono', monospace;
          font-size: 10px; font-weight: 700; color: #fff;
          line-height: 1;
        }
        .lr-pin-status {
          position: absolute; bottom: -2px; right: -2px;
          width: 10px; height: 10px; border-radius: 50%;
          border: 2px solid #0e1422;
        }
        .lr-pin-metric {
          background: #0e1422; color: #fff;
          font-family: 'JetBrains Mono', monospace;
          font-size: 9px; font-weight: 700;
          padding: 1px 5px;
          border: 1px solid rgba(255,255,255,0.2);
          white-space: nowrap;
        }
        .lr-pin-metric-fantasy {
          background: #1a3e7a; border-color: #d4af37; color: #d4af37;
        }

        /* Leaflet UI tweaks for dark mode */
        .leaflet-control-zoom a {
          background: rgba(14,20,34,0.9) !important;
          color: #d4af37 !important;
          border: 1px solid rgba(212,175,55,0.4) !important;
        }
        .leaflet-control-zoom a:hover {
          background: rgba(26,62,122,0.95) !important;
        }
        .leaflet-container { background: #0b0d12 !important; outline: none !important; font-family: inherit !important; }
      `}</style>

      {/* TOP-LEFT HUD: toggle + status banner */}
      <div style={{
        position: 'absolute', top: 8, left: 8, zIndex: 500,
        display: 'flex', flexDirection: 'column', gap: 6,
      }}>
        <div style={{
          display: 'inline-flex',
          background: 'rgba(14,20,34,0.92)',
          border: '1px solid rgba(212,175,55,0.4)',
          boxShadow: '0 2px 10px rgba(0,0,0,0.5)',
          borderRadius: 999, padding: 2,
        }}>
          {[
            { k: 'boys',    label: '● My Boys' },
            { k: 'fantasy', label: '◆ Fantasy' },
          ].map(opt => (
            <button key={opt.k} onClick={() => { setLayer(opt.k); setSelected(null); }}
              style={{
                all: 'unset', cursor: 'pointer',
                padding: '5px 12px', borderRadius: 999,
                fontFamily: 'var(--font-mono)', fontSize: 10,
                letterSpacing: '0.12em', textTransform: 'uppercase',
                whiteSpace: 'nowrap',
                background: layer === opt.k
                  ? (opt.k === 'fantasy' ? '#d4af37' : '#3aa168') : 'transparent',
                color: layer === opt.k ? '#0e1422'
                  : (opt.k === 'fantasy' ? '#d4af37' : '#3aa168'),
                fontWeight: 700,
              }}>{opt.label}</button>
          ))}
        </div>

        <div style={{
          background: 'rgba(14,20,34,0.92)',
          border: '1px solid ' + (layer === 'fantasy' ? 'rgba(212,175,55,0.5)' : 'rgba(58,161,104,0.5)'),
          padding: '6px 10px',
          boxShadow: '0 2px 10px rgba(0,0,0,0.5)',
          color: '#fff', maxWidth: 240,
        }}>
          {layer === 'fantasy' ? (
            <>
              <div className="mono" style={{ fontSize: 8.5, color: '#d4af37', letterSpacing: '0.14em', fontWeight: 700 }}>
                ◆ DEGEN SUNDAYS · #{fantasy.myRank}/{fantasy.teams}
              </div>
              <div className="serif" style={{ fontSize: 15, lineHeight: 1.1, marginTop: 1 }}>
                {fantasy.points} pts <span style={{ color: '#a8b0c0', fontSize: 11 }}>
                  · {alive} alive · {busted} out
                </span>
              </div>
              <div className="mono" style={{ fontSize: 8.5, color: '#a8b0c0', letterSpacing: '0.1em', marginTop: 2 }}>
                LEADER {fantasy.leader.points} · GAP −{fantasy.leader.points - fantasy.points}
              </div>
            </>
          ) : (
            <>
              <div className="mono" style={{ fontSize: 8.5, color: '#3aa168', letterSpacing: '0.14em', fontWeight: 700 }}>
                ● MY BOYS · LIVE GPS
              </div>
              <div className="serif" style={{ fontSize: 14, lineHeight: 1.1, marginTop: 1 }}>
                {alive} alive · {tournaments.length} events
              </div>
            </>
          )}
        </div>
      </div>

      {/* TOP-RIGHT: chat toggle (fantasy mode) */}
      {layer === 'fantasy' && (
        <button onClick={() => setChatOpen(o => !o)}
          style={{
            position: 'absolute', top: 8, right: 8, zIndex: 500,
            all: 'unset', cursor: 'pointer',
            background: chatOpen ? '#d4af37' : 'rgba(14,20,34,0.92)',
            color: chatOpen ? '#0e1422' : '#d4af37',
            border: '1px solid #d4af37',
            padding: '6px 10px',
            fontFamily: 'var(--font-mono)', fontSize: 10,
            letterSpacing: '0.12em', textTransform: 'uppercase', fontWeight: 700,
            boxShadow: '0 2px 10px rgba(0,0,0,0.5)',
            display: 'flex', alignItems: 'center', gap: 6,
          }}>
          <span>◆ Crew Chat</span>
          <span style={{
            background: chatOpen ? '#0e1422' : '#d4af37',
            color: chatOpen ? '#d4af37' : '#0e1422',
            padding: '1px 5px', fontSize: 9,
          }}>{messages.length}</span>
        </button>
      )}

      {/* Selected person card */}
      {selected && !chatOpen && (
        <PersonCard p={selected} layer={layer}
          onClose={() => setSelected(null)}
          onNudge={() => setChatOpen(true)}/>
      )}

      {/* Crew chat */}
      {chatOpen && layer === 'fantasy' && (
        <CrewChat roster={roster} messages={messages}
          onSend={sendMsg} onClose={() => setChatOpen(false)}/>
      )}
    </div>
  );
}

// ───── Selected person card ──────────────────────────────────────────────
function PersonCard({ p, layer, onClose, onNudge }) {
  const stateColor =
    p.status === 'alive'    ? '#3aa168' :
    p.status === 'busted'   ? '#d63b32' :
    p.status === 'on_break' ? '#c98a1a' : '#7a8295';

  return (
    <div style={{
      position: 'absolute', left: 8, right: 8, bottom: 8, zIndex: 600,
      background: 'rgba(14,20,34,0.96)',
      border: '1px solid rgba(212,175,55,0.4)',
      boxShadow: '0 -4px 20px rgba(0,0,0,0.6)',
      padding: '12px 14px',
      display: 'flex', alignItems: 'flex-start', gap: 12,
      backdropFilter: 'blur(8px)',
    }}>
      <div style={{
        width: 42, height: 42, borderRadius: '50%',
        background: '#0e1422', border: `2.5px solid ${stateColor}`,
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        fontFamily: 'var(--font-mono)', fontSize: 14, fontWeight: 700,
        color: '#fff', flexShrink: 0,
      }}>{p.avatar}</div>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ display: 'flex', alignItems: 'baseline', gap: 8, flexWrap: 'wrap' }}>
          <div className="serif" style={{ fontSize: 17, lineHeight: 1.1, color: '#fff' }}>{p.name}</div>
          {layer === 'fantasy' && p.pts != null && (
            <div className="mono" style={{ fontSize: 11, color: '#d4af37', fontWeight: 700 }}>
              {p.pts} POY pts
            </div>
          )}
        </div>
        <div className="mono" style={{
          fontSize: 9.5, letterSpacing: '0.1em', marginTop: 3,
          color: stateColor, fontWeight: 700, textTransform: 'uppercase',
        }}>
          {p.status} {p.where ? `· ${p.where}` : ''}{p.table ? ` · ${p.table}` : ''}
        </div>
        {p.status === 'alive' && p.chips ? (
          <div className="mono" style={{ fontSize: 11, marginTop: 4, color: '#a8b0c0' }}>
            <span style={{ color: p.chips > p.avg ? '#3aa168' : '#d63b32', fontWeight: 700 }}>
              {(p.chips/1000).toFixed(1)}k
            </span>
            {p.avg ? <span> / avg {(p.avg/1000).toFixed(1)}k</span> : null}
          </div>
        ) : null}
        {p.lastEvent && (
          <div className="mono" style={{ fontSize: 10.5, marginTop: 4, color: '#a8b0c0' }}>
            {p.lastEvent}
          </div>
        )}
        {p.lastResult && (
          <div className="mono" style={{ fontSize: 10.5, marginTop: 4, color: '#d63b32' }}>
            {p.lastResult}
          </div>
        )}

        {layer === 'fantasy' ? (
          <div style={{ display: 'flex', gap: 6, marginTop: 10, flexWrap: 'wrap' }}>
            <button onClick={onNudge} style={{
              all: 'unset', cursor: 'pointer',
              background: '#d4af37', color: '#0e1422',
              padding: '6px 10px',
              fontFamily: 'var(--font-mono)', fontSize: 10,
              letterSpacing: '0.08em', textTransform: 'uppercase', fontWeight: 700,
            }}>{(p.status === 'busted' || p.status === 'inactive') ? '◆ Nudge to late reg' : `Message ${p.name.split(' ')[0]}`}</button>
            <button style={{
              all: 'unset', cursor: 'pointer',
              border: '1px solid rgba(212,175,55,0.4)', color: '#d4af37',
              padding: '6px 10px',
              fontFamily: 'var(--font-mono)', fontSize: 10,
              letterSpacing: '0.08em', textTransform: 'uppercase',
            }}>Drop / trade</button>
          </div>
        ) : (
          <div style={{ display: 'flex', gap: 6, marginTop: 10, flexWrap: 'wrap' }}>
            <button style={{
              all: 'unset', cursor: 'pointer',
              background: '#3aa168', color: '#0e1422',
              padding: '6px 10px',
              fontFamily: 'var(--font-mono)', fontSize: 10,
              letterSpacing: '0.08em', textTransform: 'uppercase', fontWeight: 700,
            }}>Text {p.name.split(' ')[0]}</button>
            <button style={{
              all: 'unset', cursor: 'pointer',
              border: '1px solid rgba(58,161,104,0.4)', color: '#3aa168',
              padding: '6px 10px',
              fontFamily: 'var(--font-mono)', fontSize: 10,
              letterSpacing: '0.08em', textTransform: 'uppercase',
            }}>Walk to {p.venue || 'them'}</button>
          </div>
        )}
      </div>
      <button onClick={onClose} style={{
        all: 'unset', cursor: 'pointer',
        color: '#a8b0c0', fontSize: 22, padding: 2, lineHeight: 1, flexShrink: 0,
      }}>×</button>
    </div>
  );
}

// ───── Crew chat panel ────────────────────────────────────────────────────
function CrewChat({ roster, messages, onSend, onClose }) {
  const [draft, setDraft] = uS_iso('');
  const [target, setTarget] = uS_iso(null);
  const scrollRef = uR_iso(null);

  uE_iso(() => {
    if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
  }, [messages.length]);

  const bustedOrIdle = roster.find(r => r.status === 'busted') || roster.find(r => r.status === 'inactive');
  const suggestions = [];
  if (bustedOrIdle) {
    suggestions.push({
      who: bustedOrIdle,
      text: `Yo {name}, $1k Mystery at Horseshoe closes in 38m. Get back in. +60 POY easy.`,
    });
  }
  const onBreak = roster.find(r => r.status === 'on_break');
  if (onBreak) {
    suggestions.push({
      who: onBreak,
      text: `{name} when you're back from break — push for chip lead. Top 10 finish locks +120 POY.`,
    });
  }
  if (!suggestions.length) {
    suggestions.push({
      who: roster[0],
      text: `Yo {name}, run good. We're chasing Coach K's Crushers — every cash counts.`,
    });
  }

  const send = (text, who) => {
    onSend(text, who);
    setDraft('');
    setTarget(null);
  };

  return (
    <div style={{
      position: 'absolute', left: 8, right: 8, bottom: 8, zIndex: 700,
      background: 'rgba(14,20,34,0.97)',
      border: '1px solid rgba(212,175,55,0.5)',
      boxShadow: '0 -4px 24px rgba(0,0,0,0.7)',
      display: 'flex', flexDirection: 'column',
      maxHeight: '78%', color: '#fff',
      backdropFilter: 'blur(8px)',
    }}>
      <div style={{
        padding: '10px 12px',
        background: 'linear-gradient(90deg, #1a3e7a, #0e1422)',
        borderBottom: '1px solid rgba(212,175,55,0.3)',
        display: 'flex', justifyContent: 'space-between', alignItems: 'center',
      }}>
        <div>
          <div className="mono" style={{ fontSize: 8.5, letterSpacing: '0.14em', color: '#d4af37', fontWeight: 700 }}>
            ◆ DEGEN SUNDAYS · CREW CHAT
          </div>
          <div className="serif" style={{ fontSize: 15, lineHeight: 1.1, marginTop: 1, color: '#fff' }}>
            You + {roster.length} roster · Coach Kyle
          </div>
        </div>
        <button onClick={onClose} style={{
          all: 'unset', cursor: 'pointer', color: '#d4af37',
          fontSize: 22, padding: 2, lineHeight: 1,
        }}>×</button>
      </div>

      <div style={{
        display: 'flex', gap: 8, padding: '8px 12px', overflowX: 'auto',
        borderBottom: '1px solid rgba(255,255,255,0.08)',
        background: 'rgba(0,0,0,0.3)',
      }}>
        {roster.map(r => {
          const c = r.status === 'alive' ? '#3aa168'
            : r.status === 'busted' ? '#d63b32'
            : r.status === 'on_break' ? '#c98a1a' : '#7a8295';
          const sel = target && target.id === r.id;
          return (
            <button key={r.id} onClick={() => setTarget(sel ? null : r)} style={{
              all: 'unset', cursor: 'pointer', flexShrink: 0,
              display: 'flex', flexDirection: 'column', alignItems: 'center', padding: 2,
            }}>
              <div style={{
                width: 32, height: 32, borderRadius: '50%',
                background: '#0e1422', border: `2px solid ${c}`,
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                fontFamily: 'var(--font-mono)', fontSize: 10, fontWeight: 700,
                color: '#fff',
                boxShadow: sel ? '0 0 0 2px #d4af37' : 'none',
              }}>{r.avatar}</div>
              <div className="mono" style={{ fontSize: 8.5, marginTop: 2, color: '#a8b0c0', letterSpacing: '0.04em' }}>
                {r.name.split(' ')[0]}
              </div>
              <div className="mono" style={{ fontSize: 8, color: c, fontWeight: 700, marginTop: 1 }}>
                {r.pts}
              </div>
            </button>
          );
        })}
      </div>

      <div ref={scrollRef} style={{
        flex: 1, overflowY: 'auto', padding: '10px 12px',
        display: 'flex', flexDirection: 'column', gap: 8,
        minHeight: 140, maxHeight: 240,
      }}>
        {messages.map((m, i) => {
          const isMe = m.who === 'You';
          const isCoach = m.isCoach;
          return (
            <div key={i} style={{
              display: 'flex', gap: 8,
              flexDirection: isMe ? 'row-reverse' : 'row',
              alignItems: 'flex-end',
            }}>
              <div style={{
                width: 24, height: 24, borderRadius: '50%',
                background: isCoach ? '#1a3e7a' : '#0e1422',
                border: `1.5px solid ${isCoach ? '#d4af37' : '#a8b0c0'}`,
                fontFamily: 'var(--font-mono)', fontSize: 9, fontWeight: 700,
                color: isCoach ? '#d4af37' : '#fff',
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                flexShrink: 0,
              }}>{m.avatar}</div>
              <div style={{ maxWidth: '78%' }}>
                <div className="mono" style={{
                  fontSize: 8.5, color: isCoach ? '#d4af37' : '#a8b0c0',
                  textAlign: isMe ? 'right' : 'left',
                  letterSpacing: '0.06em', marginBottom: 2,
                  fontWeight: isCoach ? 700 : 500,
                }}>
                  {m.who.toUpperCase()} · {m.ts}
                </div>
                <div style={{
                  padding: '7px 10px',
                  background: isMe ? '#3aa168'
                    : isCoach ? '#1a3e7a' : 'rgba(255,255,255,0.08)',
                  color: isMe ? '#0e1422' : '#fff',
                  fontFamily: 'var(--font-serif)', fontSize: 14, lineHeight: 1.3,
                  border: isCoach ? '1px solid #d4af37' : 'none',
                }}>
                  {m.text}
                </div>
              </div>
            </div>
          );
        })}

        <div style={{ marginTop: 6, display: 'flex', flexDirection: 'column', gap: 4 }}>
          <div className="mono" style={{
            fontSize: 8.5, color: '#d4af37', letterSpacing: '0.12em', fontWeight: 700,
          }}>◆ DOYLE SUGGESTS</div>
          {suggestions.map((s, i) => (
            <button key={i} onClick={() => send(s.text, s.who)} style={{
              all: 'unset', cursor: 'pointer',
              padding: '7px 10px',
              background: 'rgba(212,175,55,0.10)', border: '1px solid #d4af37',
              color: '#fff', fontFamily: 'var(--font-serif)', fontSize: 13,
              lineHeight: 1.3,
            }}>
              <span className="mono" style={{ fontSize: 9, color: '#d4af37', letterSpacing: '0.1em', marginRight: 6, fontWeight: 700 }}>
                → {s.who.name.split(' ')[0].toUpperCase()}
              </span>
              {s.text.replace('{name}', s.who.name.split(' ')[0])}
            </button>
          ))}
        </div>
      </div>

      <div style={{
        borderTop: '1px solid rgba(255,255,255,0.08)',
        padding: '8px 12px',
        display: 'flex', flexDirection: 'column', gap: 6,
      }}>
        {target && (
          <div className="mono" style={{
            fontSize: 9.5, color: '#d4af37', letterSpacing: '0.1em',
            display: 'flex', justifyContent: 'space-between',
          }}>
            <span>→ DM TO {target.name.toUpperCase()}</span>
            <button onClick={() => setTarget(null)} style={{
              all: 'unset', cursor: 'pointer', color: '#a8b0c0',
            }}>clear</button>
          </div>
        )}
        <div style={{ display: 'flex', gap: 6 }}>
          <input value={draft} onChange={e => setDraft(e.target.value)}
            onKeyDown={e => { if (e.key === 'Enter') send(draft, target); }}
            placeholder={target ? `Nudge ${target.name.split(' ')[0]}…` : 'Message the crew…'}
            style={{
              flex: 1, padding: '8px 10px',
              border: '1px solid rgba(255,255,255,0.15)',
              fontFamily: 'var(--font-system)', fontSize: 13,
              background: 'rgba(0,0,0,0.3)', color: '#fff',
              outline: 'none',
            }}/>
          <button onClick={() => send(draft, target)} style={{
            all: 'unset', cursor: 'pointer',
            background: '#d4af37', color: '#0e1422',
            padding: '8px 14px',
            fontFamily: 'var(--font-mono)', fontSize: 11,
            letterSpacing: '0.1em', textTransform: 'uppercase', fontWeight: 700,
          }}>Send</button>
        </div>
      </div>
    </div>
  );
}

function pickReply(target) {
  const replies = {
    alive:    ["copy. running it back.", "ya I see it. crushing here tho.", "after this orbit."],
    busted:   ["fuck it. heading over.", "give me 10. cab incoming.", "in. on tilt but in."],
    on_break: ["k. back from break in 5.", "noted. let me re-rack.", "send the link."],
    inactive: ["alright alright. registering.", "yeah I been sleeping. on my way.", "fine. let's run it."],
  };
  const bucket = replies[target.status] || replies.alive;
  return bucket[Math.floor(Math.random() * bucket.length)];
}

function doyleTakeFor(target) {
  if (target.status === 'busted') return `${target.name.split(' ')[0]} re-entering tilt — keep him on lower-variance bullets. No $5k Mixed.`;
  if (target.status === 'inactive') return `${target.name.split(' ')[0]} skipped 3 events this week. We need volume.`;
  if (target.status === 'on_break') return `Tell ${target.name.split(' ')[0]} to eat protein. Post-break ROI tanks when hungry.`;
  return `${target.name.split(' ')[0]} above chip avg — let them cook.`;
}

Object.assign(window, { IsoStripMap });
