// TownPost — Messages / DM system

const TP_THREADS = [
  { id: 't1', name: 'Curt Hollow', hue: 0, last: 'Sounds good — see you Thursday morning.', time: '12m', unread: 2, online: true, role: 'Plumber · verified' },
  { id: 't2', name: 'Belleville & Area', hue: 6, last: 'Maya: anyone else lose power on Linden?', time: '1h', unread: 5, group: true, members: 47, role: 'Neighborhood group' },
  // Market threads — buyer/seller DMs anchored to a listing
  { id: 'tm1', kind: 'market', name: 'Tomás Wexler', hue: 3, last: 'Still available! When works for pickup?', time: '24m', unread: 1, role: 'Marketplace · seller', listing: { title: 'Vintage cherrywood drafting table', price: 220, status: 'Available' } },
  { id: 'tm2', kind: 'market', name: 'Hana Okafor', hue: 5, last: 'You: I can do $35 if you can pick up tonight.', time: '2h', unread: 0, sent: true, role: 'Marketplace · buyer', listing: { title: 'Pair of cast-iron andirons', price: 45, status: 'Pending offer' } },
  { id: 't3', name: 'Priya Naidu', hue: 1, last: 'Thanks for the toolshed recco 🙏', time: '3h', unread: 0 },
  { id: 'tm3', kind: 'market', name: 'Beth Ngata', hue: 0, last: 'Beth sent you an offer: $180', time: '5h', unread: 2, role: 'Marketplace · buyer', listing: { title: 'Ash dining chairs (set of 4)', price: 240, status: 'Offer received', offer: 180 } },
  { id: 't4', name: 'Marisol Hernández', hue: 4, last: 'Voice message · 0:42', time: 'Yesterday', unread: 0, voice: true },
  { id: 'tm4', kind: 'market', name: 'Jules Rinaldi', hue: 2, last: 'Picked up — thanks again! 🌱', time: 'Yesterday', unread: 0, role: 'Marketplace · sold', listing: { title: 'Maple seedling, 3ft', price: 0, status: 'Sold · free' } },
  { id: 't5', name: 'Soccer Pickup — Tuesdays', hue: 5, last: 'Ben: bringing two extra cones', time: 'Yesterday', unread: 0, group: true, members: 12, role: 'Group chat' },
  { id: 't6', name: 'Renee O.', hue: 2, last: 'You: I think I saw it on Park st last week', time: 'Mon', unread: 0, sent: true },
  { id: 't7', name: 'Quinte West Library', hue: 3, last: 'Your hold on "The Overstory" is ready.', time: 'Sun', unread: 0, official: true, role: 'Official · library' },
];

const TP_REQUESTS = 3;

// ─── Inbox / threads list ──────────────────────────
function ScreenMessages({ onNav = () => {}, onBack = () => {}, onOpenThread = () => {}, onCompose = () => {} }) {
  const [filter, setFilter] = React.useState('all');
  const unreadTotal = TP_THREADS.reduce((s, t) => s + (t.unread || 0), 0);
  const visible = TP_THREADS.filter(t => {
    if (filter === 'all') return true;
    if (filter === 'unread') return t.unread;
    if (filter === 'market') return t.kind === 'market';
    if (filter === 'groups') return t.group;
    return true;
  });
  const marketThreads = visible.filter(t => t.kind === 'market');
  const otherThreads = visible.filter(t => t.kind !== 'market');
  return (
    <div style={{ background: TP.cream, height: '100%', display: 'flex', flexDirection: 'column' }}>
      {/* Top bar */}
      <div style={{ padding: '12px 16px 14px', background: TP.paper, borderBottom: `1px solid ${TP.hairline}` }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 12 }}>
          <button onClick={onBack} style={{ width: 32, height: 32, borderRadius: '50%', background: 'transparent', border: 'none', display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer', marginLeft: -4 }}>
            <TPIcon name="chevronLeft" size={20} color={TP.ink} />
          </button>
          <div style={{ flex: 1 }}>
            <div style={{ fontFamily: TP.serif, fontSize: 22, color: TP.ink, lineHeight: 1.05, letterSpacing: -0.3 }}>Messages</div>
            <div style={{ fontFamily: TP.mono, fontSize: 10, color: TP.muted, letterSpacing: 1.4, textTransform: 'uppercase', marginTop: 2 }}>
              {unreadTotal} UNREAD · {TP_THREADS.length} CHATS
            </div>
          </div>
          <button onClick={onCompose} aria-label="New message" style={{ width: 36, height: 36, borderRadius: '50%', background: TP.forest, border: 'none', display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer' }}>
            <TPIcon name="plus" size={16} stroke={2.5} color={TP.cream} />
          </button>
        </div>
        {/* Search */}
        <div style={{
          display: 'flex', gap: 8, alignItems: 'center',
          background: TP.cream, borderRadius: TP.r.pill, padding: '8px 14px',
        }}>
          <TPIcon name="search" size={16} color={TP.muted} />
          <span style={{ fontFamily: TP.sans, fontSize: 13, color: TP.muted, flex: 1 }}>Search messages…</span>
        </div>
      </div>

      <div style={{ flex: 1, overflow: 'auto' }}>
        {/* Filter tabs */}
        <div style={{ display: 'flex', padding: '10px 16px 4px', gap: 6, background: TP.paper, borderBottom: `1px solid ${TP.hairline}` }}>
          {[
            { id: 'all', label: 'All', count: TP_THREADS.length },
            { id: 'unread', label: 'Unread', count: TP_THREADS.filter(t => t.unread).length },
            { id: 'market', label: 'Market', count: TP_THREADS.filter(t => t.kind === 'market').length, icon: 'tag' },
            { id: 'groups', label: 'Groups', count: TP_THREADS.filter(t => t.group).length },
            { id: 'requests', label: 'Requests', count: TP_REQUESTS, dot: true },
          ].map(f => {
            const active = filter === f.id;
            return (
            <button key={f.id} onClick={() => setFilter(f.id)} style={{
              padding: '6px 12px', borderRadius: TP.r.pill,
              background: active ? TP.ink : 'transparent',
              border: active ? 'none' : `1px solid ${TP.hairlineStrong}`,
              color: active ? TP.cream : TP.inkSoft,
              fontFamily: TP.sans, fontSize: 12, fontWeight: 600,
              display: 'flex', alignItems: 'center', gap: 5, cursor: 'pointer',
              position: 'relative', flexShrink: 0,
            }}>
              {f.icon && <TPIcon name={f.icon} size={11} color={active ? TP.cream : TP.inkSoft} stroke={2} />}
              {f.label}
              {f.count > 0 && <span style={{ fontFamily: TP.mono, fontSize: 10, fontWeight: 700, opacity: 0.7 }}>{f.count}</span>}
              {f.dot && <span style={{ width: 6, height: 6, borderRadius: '50%', background: TP.alertRed }} />}
            </button>
          );})}
        </div>

        {/* Pinned section — only when no filter is restricting things */}
        {filter === 'all' && (
          <div style={{ background: TP.paper }}>
            <div style={{ padding: '10px 16px 4px', display: 'flex', alignItems: 'center', gap: 6 }}>
              <TPIcon name="pin" size={11} color={TP.muted} stroke={2} />
              <span style={{ fontFamily: TP.mono, fontSize: 9.5, color: TP.muted, fontWeight: 700, letterSpacing: 1.2, textTransform: 'uppercase' }}>Pinned</span>
              <div style={{ flex: 1, height: 1, background: TP.hairline }} />
            </div>
            <ThreadRow t={TP_THREADS[0]} onTap={() => onOpenThread(TP_THREADS[0])} />
            <ThreadRow t={TP_THREADS[1]} onTap={() => onOpenThread(TP_THREADS[1])} />
          </div>
        )}

        {/* Marketplace — collapsible / always visible when filter says so */}
        {marketThreads.length > 0 && (
          <div style={{ background: TP.paper, marginTop: 8 }}>
            <div style={{ padding: '10px 16px 4px', display: 'flex', alignItems: 'center', gap: 6 }}>
              <TPIcon name="tag" size={11} color={TP.terracotta} stroke={2} />
              <span style={{ fontFamily: TP.mono, fontSize: 9.5, color: TP.terracotta, fontWeight: 700, letterSpacing: 1.2, textTransform: 'uppercase' }}>Marketplace</span>
              <span style={{ fontFamily: TP.mono, fontSize: 9.5, color: TP.muted, fontWeight: 600 }}>· {marketThreads.length}</span>
              <div style={{ flex: 1, height: 1, background: TP.hairline }} />
              <span style={{ fontFamily: TP.sans, fontSize: 11, color: TP.inkSoft, fontWeight: 500 }}>See all</span>
            </div>
            {marketThreads.map(t => <ThreadRow key={t.id} t={t} onTap={() => onOpenThread(t)} />)}
          </div>
        )}

        {/* Recent / filtered other threads */}
        {(filter !== 'market') && (
          <div style={{ background: TP.paper, marginTop: 8 }}>
            <div style={{ padding: '10px 16px 4px' }}>
              <span style={{ fontFamily: TP.mono, fontSize: 9.5, color: TP.muted, fontWeight: 700, letterSpacing: 1.2, textTransform: 'uppercase' }}>
                {filter === 'all' ? 'Recent' : filter === 'unread' ? 'Unread' : filter === 'groups' ? 'Groups' : 'Recent'}
              </span>
            </div>
            {(filter === 'all' ? otherThreads.slice(2) : otherThreads).map(t => <ThreadRow key={t.id} t={t} onTap={() => onOpenThread(t)} />)}
            {(filter === 'all' ? otherThreads.slice(2) : otherThreads).length === 0 && (
              <div style={{ padding: '24px 16px', textAlign: 'center', fontFamily: TP.sans, fontSize: 12.5, color: TP.muted }}>
                No threads in this filter.
              </div>
            )}
          </div>
        )}

        <div style={{ height: 80 }} />
      </div>

      <TPTabBar active="" onChange={onNav} />
    </div>
  );
}

// ─── A single thread/conversation row ──────────────────────────
function ThreadRow({ t, onTap }) {
  return (
    <div onClick={onTap} style={{
      display: 'flex', gap: 12, padding: '12px 16px',
      borderBottom: `1px solid ${TP.hairline}`,
      cursor: 'pointer', alignItems: 'center',
    }}>
      <div style={{ position: 'relative', flexShrink: 0 }}>
        {t.group ? (
          <div style={{ width: 48, height: 48, borderRadius: 12, background: TP.amberTint, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
            <TPIcon name="profile" size={22} color={TP.ochre} stroke={2} />
          </div>
        ) : (
          <TPAvatar name={t.name} hue={t.hue} size={48} />
        )}
        {t.online && (
          <div style={{ position: 'absolute', bottom: 0, right: 0, width: 13, height: 13, borderRadius: '50%', background: TP.forest, border: `2.5px solid ${TP.paper}` }} />
        )}
        {t.kind === 'market' && (
          <div style={{ position: 'absolute', bottom: -2, right: -2, width: 18, height: 18, borderRadius: '50%', background: TP.terracotta, border: `2px solid ${TP.paper}`, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
            <TPIcon name="tag" size={10} color="#fff" stroke={2.5} />
          </div>
        )}
        {t.official && (
          <div style={{ position: 'absolute', bottom: -2, right: -2, width: 16, height: 16, borderRadius: '50%', background: TP.terracotta, border: `2px solid ${TP.paper}`, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
            <TPIcon name="shield" size={9} color="#fff" stroke={2.5} />
          </div>
        )}
      </div>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ display: 'flex', alignItems: 'baseline', gap: 6, marginBottom: 2 }}>
          <span style={{
            fontFamily: TP.sans, fontSize: 14.5, color: TP.ink,
            fontWeight: t.unread ? 700 : 600,
            overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', flex: 1,
          }}>{t.name}</span>
          <span style={{ fontFamily: TP.mono, fontSize: 10, color: t.unread ? TP.terracotta : TP.muted, fontWeight: t.unread ? 700 : 500, flexShrink: 0, letterSpacing: 0.4 }}>{t.time}</span>
        </div>
        {t.role && (
          <div style={{ fontFamily: TP.mono, fontSize: 9.5, color: TP.muted, fontWeight: 600, letterSpacing: 0.8, textTransform: 'uppercase', marginBottom: 2 }}>{t.role}{t.members ? ` · ${t.members}` : ''}</div>
        )}
        {t.kind === 'market' && t.listing && (
          <div style={{
            display: 'flex', alignItems: 'center', gap: 6,
            padding: '3px 7px 3px 4px', marginBottom: 4,
            background: TP.cream, border: `1px solid ${TP.hairline}`, borderRadius: 6,
            maxWidth: '100%',
          }}>
            <div style={{
              width: 18, height: 18, borderRadius: 3, flexShrink: 0,
              background: `linear-gradient(135deg, ${TP.amberTint}, ${TP.terracottaTint || TP.amberTint})`,
              display: 'flex', alignItems: 'center', justifyContent: 'center',
            }}>
              <TPIcon name="tag" size={9} color={TP.terracotta} stroke={2.4} />
            </div>
            <span style={{ fontFamily: TP.sans, fontSize: 11, fontWeight: 600, color: TP.ink, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', minWidth: 0, flex: 1 }}>
              {t.listing.title}
            </span>
            <span style={{ fontFamily: TP.mono, fontSize: 10, fontWeight: 700, color: TP.terracotta, flexShrink: 0, letterSpacing: 0.3 }}>
              {t.listing.price === 0 ? 'FREE' : `$${t.listing.price}`}
            </span>
          </div>
        )}
        <div style={{
          display: 'flex', alignItems: 'center', gap: 5,
          fontFamily: TP.sans, fontSize: 12.5,
          color: t.unread ? TP.ink : TP.muted,
          fontWeight: t.unread ? 500 : 400,
        }}>
          {t.sent && <TPIcon name="check" size={11} color={TP.muted} stroke={2.5} />}
          {t.voice && <TPIcon name="mic" size={11} color={TP.terracotta} stroke={2} />}
          <span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', flex: 1, minWidth: 0 }}>{t.last}</span>
        </div>
      </div>
      {t.unread > 0 && (
        <div style={{
          flexShrink: 0, minWidth: 20, height: 20, padding: '0 6px', borderRadius: '50%',
          background: TP.terracotta, color: '#fff',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          fontFamily: TP.sans, fontSize: 11, fontWeight: 700,
        }}>{t.unread}</div>
      )}
    </div>
  );
}

// ─── Single conversation thread ──────────────────────────
const TP_THREAD_MESSAGES = [
  { id: 'm1', from: 'them', text: 'Hey Dev — got your note about the basement leak.', time: '9:42 AM' },
  { id: 'm2', from: 'them', text: 'Want me to swing by Thursday morning around 8? I\'m doing a job two streets over.', time: '9:42 AM' },
  { id: 'm3', from: 'me', text: 'That would be perfect. Anything I should have ready?', time: '9:51 AM', read: true },
  { id: 'm4', from: 'them', text: 'Just clear access to the shutoff and the hot water tank. I\'ll bring everything else.', time: '9:53 AM' },
  { id: 'm5', from: 'them', text: 'Also — if you can take a quick photo of where the water is coming in, that helps me bring the right parts.', time: '9:53 AM' },
  { id: 'm6', from: 'me', text: 'Will do. I\'ll text you a photo tonight.', time: '10:04 AM', read: true },
  { id: 'm7', from: 'them', text: 'Sounds good — see you Thursday morning.', time: '10:08 AM' },
];

function ScreenMessageThread({ thread = TP_THREADS[0], quotedItem = null, offerMode = false, onNav = () => {}, onBack = () => {} }) {
  const t = thread;
  const isMarket = !!quotedItem || t.kind === 'market';
  const firstName = (t.name || '').split(' ')[0];
  // Pre-seed draft for marketplace flows
  const initialDraft = offerMode
    ? '' // offer composer has its own state
    : quotedItem
      ? `Hi ${firstName}, is this still available? `
      : '';
  const [draft, setDraft] = React.useState(initialDraft);
  const [offerAmount, setOfferAmount] = React.useState(
    quotedItem?.priceVal ? String(Math.max(1, Math.floor(quotedItem.priceVal * 0.85))) : ''
  );
  const [offerNote, setOfferNote] = React.useState('');
  const [sentOffer, setSentOffer] = React.useState(null); // {amount, note} once sent
  // Choose message backlog: vanilla plumber thread vs. market intro thread
  const messages = quotedItem
    ? [
        { id: 'mq1', from: 'system', kind: 'listing-card', listing: quotedItem, time: 'Listed 2 days ago' },
        { id: 'mq2', from: 'them', text: `Yep — still available! Asking ${quotedItem.price || `$${quotedItem.priceVal}`}. Pickup is from my place on Park St.`, time: '11:14 AM' },
      ]
    : TP_THREAD_MESSAGES;
  return (
    <div style={{ background: TP.cream, height: '100%', display: 'flex', flexDirection: 'column' }}>
      {/* Top bar */}
      <div style={{ padding: '10px 12px', background: TP.paper, borderBottom: `1px solid ${TP.hairline}`, display: 'flex', alignItems: 'center', gap: 10 }}>
        <button onClick={onBack} style={{ width: 32, height: 32, borderRadius: '50%', background: 'transparent', border: 'none', display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer' }}>
          <TPIcon name="chevronLeft" size={20} color={TP.ink} />
        </button>
        <div style={{ position: 'relative', flexShrink: 0 }}>
          <TPAvatar name={t.name} hue={t.hue} size={36} />
          {t.online && <div style={{ position: 'absolute', bottom: -1, right: -1, width: 11, height: 11, borderRadius: '50%', background: TP.forest, border: `2px solid ${TP.paper}` }} />}
        </div>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontFamily: TP.sans, fontSize: 14, fontWeight: 700, color: TP.ink, lineHeight: 1.2 }}>{t.name}</div>
          <div style={{ fontFamily: TP.sans, fontSize: 11.5, color: t.online ? TP.forest : TP.muted, fontWeight: 500 }}>
            {t.online ? 'Active now' : t.role || 'Last active 2h ago'}
          </div>
        </div>
        <button style={{ width: 36, height: 36, borderRadius: '50%', background: 'transparent', border: 'none', display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer' }}>
          <TPIcon name="search" size={18} color={TP.ink} stroke={2} />
        </button>
        <button style={{ width: 36, height: 36, borderRadius: '50%', background: 'transparent', border: 'none', display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer' }}>
          <TPIcon name="settings" size={18} color={TP.ink} />
        </button>
      </div>

      {/* Trust chip — marketplace shows seller-trust framing */}
      <div style={{ padding: '10px 16px', background: TP.paper, borderBottom: `1px solid ${TP.hairline}`, display: 'flex', alignItems: 'center', gap: 8, justifyContent: 'center' }}>
        <TPIcon name="shield" size={12} color={TP.forest} stroke={2.2} />
        <span style={{ fontFamily: TP.mono, fontSize: 10, color: TP.forest, fontWeight: 700, letterSpacing: 1.2, textTransform: 'uppercase' }}>
          {isMarket ? 'Verified seller · 4.9 trust' : 'Verified neighbor · 4.9 trust'}
        </span>
        <span style={{ fontFamily: TP.sans, fontSize: 11, color: TP.muted }}>· 0.4mi away</span>
      </div>

      {/* Sticky listing strip — pinned just below the trust chip when this is a market thread */}
      {quotedItem && (
        <div style={{
          padding: '10px 12px', background: TP.paper, borderBottom: `1px solid ${TP.hairline}`,
          display: 'flex', alignItems: 'center', gap: 10,
        }}>
          <div style={{
            width: 44, height: 44, borderRadius: 8, flexShrink: 0,
            background: quotedItem.image
              ? `url(${quotedItem.image}) center/cover`
              : `linear-gradient(135deg, ${TP.amberTint}, ${TP.terracotta || TP.amberTint})`,
            border: `1px solid ${TP.hairline}`,
          }} />
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontFamily: TP.mono, fontSize: 9, color: TP.terracotta, fontWeight: 700, letterSpacing: 1, textTransform: 'uppercase' }}>
              Marketplace inquiry
            </div>
            <div style={{ fontFamily: TP.sans, fontSize: 13, fontWeight: 600, color: TP.ink, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', marginTop: 1 }}>
              {quotedItem.title}
            </div>
          </div>
          <div style={{ fontFamily: TP.serif, fontSize: 16, color: TP.ink, fontWeight: 600, flexShrink: 0 }}>
            {quotedItem.price || `$${quotedItem.priceVal}`}
          </div>
          <button onClick={onBack} style={{
            padding: '5px 10px', borderRadius: 999,
            background: TP.cream, border: `1px solid ${TP.hairline}`, cursor: 'pointer',
            fontFamily: TP.sans, fontSize: 11, fontWeight: 600, color: TP.inkSoft,
          }}>View</button>
        </div>
      )}

      {/* Messages */}
      <div style={{ flex: 1, overflow: 'auto', padding: '12px 12px 4px', display: 'flex', flexDirection: 'column', gap: 4 }}>
        <div style={{ textAlign: 'center', padding: '8px 0 12px', fontFamily: TP.mono, fontSize: 10, color: TP.muted, fontWeight: 600, letterSpacing: 1, textTransform: 'uppercase' }}>
          Today
        </div>
        {messages.map((m, i) => {
          if (m.kind === 'listing-card') return <ListingCardBubble key={m.id} m={m} />;
          const prev = messages[i - 1];
          const sameAuthor = prev && prev.from === m.from;
          const next = messages[i + 1];
          const isLast = !next || next.from !== m.from;
          return <Bubble key={m.id} m={m} grouped={sameAuthor} isLast={isLast} />;
        })}
        {/* Sent offer renders as a special bubble */}
        {sentOffer && (
          <OfferBubble amount={sentOffer.amount} note={sentOffer.note} listing={quotedItem} />
        )}
        <div style={{ height: 8 }} />
      </div>

      {/* Composer — offer mode swaps in a price input + send-offer CTA */}
      {offerMode && !sentOffer ? (
        <div style={{ padding: '12px 12px 12px', background: TP.paper, borderTop: `1px solid ${TP.hairline}` }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 8 }}>
            <TPIcon name="tag" size={11} color={TP.terracotta} stroke={2.2} />
            <span style={{ fontFamily: TP.mono, fontSize: 9.5, color: TP.terracotta, fontWeight: 700, letterSpacing: 1.2, textTransform: 'uppercase' }}>Make an offer</span>
            {quotedItem && (
              <span style={{ fontFamily: TP.sans, fontSize: 11, color: TP.muted, marginLeft: 'auto' }}>
                Asking {quotedItem.price || `$${quotedItem.priceVal}`}
              </span>
            )}
          </div>
          <div style={{
            display: 'flex', alignItems: 'center', gap: 10,
            background: TP.cream, border: `1px solid ${TP.hairlineStrong}`, borderRadius: 12,
            padding: '12px 14px', marginBottom: 8,
          }}>
            <span style={{ fontFamily: TP.serif, fontSize: 26, color: TP.muted, fontWeight: 600 }}>$</span>
            <input
              type="number"
              value={offerAmount}
              onChange={(e) => setOfferAmount(e.target.value)}
              placeholder="0"
              style={{
                flex: 1, border: 'none', background: 'transparent', outline: 'none',
                fontFamily: TP.serif, fontSize: 26, fontWeight: 600, color: TP.ink, letterSpacing: -0.4,
                width: '100%',
              }}
            />
            {quotedItem?.priceVal > 0 && offerAmount && (
              <span style={{ fontFamily: TP.mono, fontSize: 10, color: TP.muted, fontWeight: 600 }}>
                {Math.round((Number(offerAmount) / quotedItem.priceVal) * 100)}% of asking
              </span>
            )}
          </div>
          <input
            value={offerNote}
            onChange={(e) => setOfferNote(e.target.value)}
            placeholder="Add a note (optional) — e.g. 'Can pick up tonight in cash'"
            style={{
              width: '100%', boxSizing: 'border-box',
              padding: '10px 14px', borderRadius: TP.r.pill,
              border: `1px solid ${TP.hairline}`, background: TP.cream,
              fontFamily: TP.sans, fontSize: 13, color: TP.ink, outline: 'none',
              marginBottom: 10,
            }}
          />
          <button
            onClick={() => {
              if (!offerAmount) return;
              setSentOffer({ amount: Number(offerAmount), note: offerNote });
            }}
            style={{
              width: '100%', height: 48, borderRadius: 12,
              background: offerAmount ? TP.forest : TP.hairlineStrong, border: 'none',
              color: TP.cream, fontFamily: TP.sans, fontSize: 14, fontWeight: 700,
              cursor: offerAmount ? 'pointer' : 'default',
              display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 6,
            }}
          >
            <TPIcon name="arrowUp" size={15} color={TP.cream} stroke={2.5} />
            Send offer{offerAmount ? ` · $${offerAmount}` : ''}
          </button>
        </div>
      ) : (
        <div style={{ padding: '8px 12px 10px', background: TP.paper, borderTop: `1px solid ${TP.hairline}`, display: 'flex', alignItems: 'center', gap: 8 }}>
          <button style={{ width: 36, height: 36, borderRadius: '50%', background: TP.cream, border: `1px solid ${TP.hairline}`, display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer', flexShrink: 0 }}>
            <TPIcon name="plus" size={18} color={TP.ink} stroke={2.2} />
          </button>
          <div style={{
            flex: 1, display: 'flex', alignItems: 'center', gap: 8,
            background: TP.cream, borderRadius: TP.r.pill, padding: '8px 12px',
            border: `1px solid ${TP.hairline}`,
          }}>
            <input
              value={draft}
              onChange={(e) => setDraft(e.target.value)}
              placeholder={isMarket ? `Message ${firstName}…` : `Message ${firstName || 'Curt'}…`}
              style={{
                flex: 1, border: 'none', background: 'transparent', outline: 'none',
                fontFamily: TP.sans, fontSize: 13.5, color: TP.ink,
              }}
            />
            <TPIcon name="image" size={18} color={TP.muted} stroke={2} />
            <TPIcon name="mic" size={18} color={TP.muted} stroke={2} />
          </div>
          <button style={{ width: 36, height: 36, borderRadius: '50%', background: draft ? TP.forest : TP.hairlineStrong, border: 'none', display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: draft ? 'pointer' : 'default', flexShrink: 0, transition: 'background 0.15s' }}>
            <TPIcon name="arrowUp" size={18} color="#fff" stroke={2.5} />
          </button>
        </div>
      )}
    </div>
  );
}

function Bubble({ m, grouped, isLast }) {
  const mine = m.from === 'me';
  return (
    <div style={{
      display: 'flex', justifyContent: mine ? 'flex-end' : 'flex-start',
      marginTop: grouped ? 1 : 6,
    }}>
      <div style={{ maxWidth: '78%', display: 'flex', flexDirection: 'column', alignItems: mine ? 'flex-end' : 'flex-start' }}>
        <div style={{
          padding: '9px 13px',
          borderRadius: 18,
          borderTopLeftRadius: !mine && grouped ? 6 : 18,
          borderTopRightRadius: mine && grouped ? 6 : 18,
          borderBottomLeftRadius: !mine && !isLast ? 6 : 18,
          borderBottomRightRadius: mine && !isLast ? 6 : 18,
          background: mine ? TP.forest : TP.paper,
          color: mine ? TP.cream : TP.ink,
          fontFamily: TP.sans, fontSize: 13.5, lineHeight: 1.45,
          border: mine ? 'none' : `1px solid ${TP.hairline}`,
        }}>
          {m.text}
        </div>
        {isLast && (
          <div style={{
            display: 'flex', alignItems: 'center', gap: 4,
            fontFamily: TP.mono, fontSize: 9.5, color: TP.muted,
            fontWeight: 600, letterSpacing: 0.4, marginTop: 3, padding: '0 4px',
          }}>
            {m.time}
            {mine && m.read && <TPIcon name="check" size={10} color={TP.forest} stroke={2.5} />}
          </div>
        )}
      </div>
    </div>
  );
}

// ─── A pinned listing-card system bubble inside the conversation ──
function ListingCardBubble({ m }) {
  const l = m.listing || {};
  return (
    <div style={{ display: 'flex', justifyContent: 'center', margin: '4px 0 10px' }}>
      <div style={{
        width: '100%', maxWidth: 320,
        background: TP.paper, border: `1px solid ${TP.hairlineStrong}`, borderRadius: 14,
        overflow: 'hidden',
      }}>
        <div style={{
          height: 110,
          background: l.image
            ? `url(${l.image}) center/cover`
            : `linear-gradient(135deg, ${TP.amberTint}, ${TP.terracotta})`,
          position: 'relative',
        }}>
          <div style={{
            position: 'absolute', top: 8, left: 8,
            padding: '3px 8px', borderRadius: 999,
            background: 'rgba(255,255,255,0.92)', backdropFilter: 'blur(4px)',
            fontFamily: TP.mono, fontSize: 9, fontWeight: 700, color: TP.terracotta,
            letterSpacing: 1, textTransform: 'uppercase',
          }}>
            <TPIcon name="tag" size={9} color={TP.terracotta} stroke={2.4} style={{ marginRight: 4, verticalAlign: '-1px' }} />
            Marketplace
          </div>
        </div>
        <div style={{ padding: '10px 12px 12px' }}>
          <div style={{ fontFamily: TP.sans, fontSize: 13.5, fontWeight: 600, color: TP.ink, lineHeight: 1.3 }}>
            {l.title}
          </div>
          <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', marginTop: 6 }}>
            <span style={{ fontFamily: TP.serif, fontSize: 18, color: TP.ink, fontWeight: 600, letterSpacing: -0.3 }}>
              {l.price || (l.priceVal ? `$${l.priceVal}` : 'Free')}
            </span>
            <span style={{ fontFamily: TP.mono, fontSize: 9.5, color: TP.muted, fontWeight: 600, letterSpacing: 0.6, textTransform: 'uppercase' }}>
              {m.time || 'Listed today'}
            </span>
          </div>
        </div>
      </div>
    </div>
  );
}

// ─── A "sent offer" bubble — quoted listing + offer amount + status ──
function OfferBubble({ amount, note, listing }) {
  return (
    <div style={{ display: 'flex', justifyContent: 'flex-end', margin: '6px 0' }}>
      <div style={{ maxWidth: '82%', display: 'flex', flexDirection: 'column', alignItems: 'flex-end' }}>
        <div style={{
          background: TP.forest, color: TP.cream, borderRadius: 18, borderBottomRightRadius: 6,
          padding: 4, minWidth: 240,
        }}>
          {/* Inner quoted listing card */}
          {listing && (
            <div style={{
              background: 'rgba(0,0,0,0.18)', borderRadius: 14,
              padding: '8px 10px', marginBottom: 6,
              display: 'flex', alignItems: 'center', gap: 8,
            }}>
              <div style={{
                width: 30, height: 30, borderRadius: 6, flexShrink: 0,
                background: listing.image
                  ? `url(${listing.image}) center/cover`
                  : `linear-gradient(135deg, ${TP.amberTint}, ${TP.terracotta})`,
              }} />
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontFamily: TP.mono, fontSize: 8.5, fontWeight: 700, opacity: 0.7, letterSpacing: 1, textTransform: 'uppercase' }}>
                  Quoted listing
                </div>
                <div style={{ fontFamily: TP.sans, fontSize: 11.5, fontWeight: 600, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', marginTop: 1 }}>
                  {listing.title} · {listing.price || `$${listing.priceVal}`}
                </div>
              </div>
            </div>
          )}
          <div style={{ padding: '6px 12px 4px' }}>
            <div style={{ fontFamily: TP.mono, fontSize: 9, fontWeight: 700, opacity: 0.7, letterSpacing: 1.2, textTransform: 'uppercase' }}>
              Your offer
            </div>
            <div style={{ fontFamily: TP.serif, fontSize: 28, fontWeight: 600, letterSpacing: -0.5, lineHeight: 1.05, marginTop: 2 }}>
              ${amount}
            </div>
            {note && (
              <div style={{ fontFamily: TP.sans, fontSize: 12.5, opacity: 0.92, marginTop: 6, lineHeight: 1.4 }}>
                {note}
              </div>
            )}
          </div>
          <div style={{
            display: 'flex', alignItems: 'center', gap: 5,
            padding: '6px 12px 8px',
            fontFamily: TP.mono, fontSize: 9, fontWeight: 700, opacity: 0.85, letterSpacing: 1, textTransform: 'uppercase',
          }}>
            <span style={{ width: 6, height: 6, borderRadius: '50%', background: TP.amberTint }} />
            Awaiting response
          </div>
        </div>
        <div style={{
          fontFamily: TP.mono, fontSize: 9.5, color: TP.muted,
          fontWeight: 600, letterSpacing: 0.4, marginTop: 3, padding: '0 4px',
          display: 'flex', alignItems: 'center', gap: 4,
        }}>
          Just now
          <TPIcon name="check" size={10} color={TP.forest} stroke={2.5} />
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { ScreenMessages, ScreenMessageThread, TP_THREADS });
