// Item Card — expanded view with the big "I'm down" button + comments

function ItemCardScreen({ item, userId, huddle, comments, onClose, onToggleDown, onComment }) {
  const { state, actions } = useStore();
  const members = huddle?.members || [];
  const byId = (id) => members.find(m => m.id === id) || { id, name: '?', avatar: '?', color: C.inkMuted };
  const cat = catById(item.category);
  const author = byId(item.addedBy);
  const isDown = item.downs.includes(userId);
  const downsList = item.downs.map(byId);
  const youFirst = [
    ...downsList.filter(u => u.id === userId),
    ...downsList.filter(u => u.id !== userId),
  ];
  const effectiveDowns = youFirst;
  const count = effectiveDowns.length;

  const canEdit = userId === item.addedBy || userId === huddle?.ownerId;
  const proposals = state.proposals?.[item.id] || [];
  const reviews = state.reviews?.[item.id] || [];
  const now = new Date();
  const endD = labelToDate(item.endDate || item.date || '', now.getFullYear());
  const isPast = item.type === 'event' && endD &&
    endD.getTime() < new Date(now.getFullYear(), now.getMonth(), now.getDate()).getTime();
  const myReview = reviews.find(r => r.user === userId);
  const avgRating = reviews.length
    ? Math.round((reviews.reduce((s, r) => s + r.rating, 0) / reviews.length) * 10) / 10
    : null;
  const isOpenEnded = item.type === 'activity';

  const [menuOpen, setMenuOpen] = React.useState(false);
  const [sheet, setSheet] = React.useState(null); // 'edit' | 'delete' | 'propose' | 'review'

  const copyLink = async () => {
    const url = item.url || window.location.href;
    try {
      if (navigator.clipboard?.writeText) await navigator.clipboard.writeText(url);
    } catch {}
    setMenuOpen(false);
  };

  return (
    <div style={{
      background: C.cream, minHeight: '100%',
      paddingBottom: 140, position: 'relative',
    }}>
      {/* Hero image */}
      <div style={{ position: 'relative' }}>
        <Placeholder spec={item.image} style={{
          width: '100%', aspectRatio: '4 / 3',
        }}/>
        {/* Cream curve mask at bottom */}
        <div style={{
          position: 'absolute', bottom: -1, left: 0, right: 0,
          height: 28, background: C.cream,
          borderRadius: '28px 28px 0 0',
        }}/>
        {/* Back & more buttons */}
        <div style={{
          position: 'absolute', top: 'calc(env(safe-area-inset-top, 12px) + 14px)', left: 16, right: 16,
          display: 'flex', justifyContent: 'space-between',
        }}>
          <button onClick={onClose} style={{
            width: 40, height: 40, borderRadius: 20,
            background: 'rgba(255,255,255,0.95)',
            border: 'none', cursor: 'pointer',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            backdropFilter: 'blur(8px)',
            boxShadow: '0 2px 8px rgba(30,42,74,0.12)',
          }}>
            <svg width="12" height="20" viewBox="0 0 12 20">
              <path d="M10 2L2 10l8 8" stroke={C.navy} strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" fill="none"/>
            </svg>
          </button>
          <div style={{ position: 'relative' }}>
            <button onClick={() => setMenuOpen(m => !m)} style={{
              width: 40, height: 40, borderRadius: 20,
              background: 'rgba(255,255,255,0.95)',
              border: 'none', cursor: 'pointer',
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              backdropFilter: 'blur(8px)',
              boxShadow: '0 2px 8px rgba(30,42,74,0.12)',
            }}>
              <svg width="22" height="6" viewBox="0 0 22 6">
                <circle cx="3" cy="3" r="2.5" fill={C.navy}/>
                <circle cx="11" cy="3" r="2.5" fill={C.navy}/>
                <circle cx="19" cy="3" r="2.5" fill={C.navy}/>
              </svg>
            </button>
            {menuOpen && (
              <ItemMenu
                canEdit={canEdit}
                onClose={() => setMenuOpen(false)}
                onEdit={() => { setMenuOpen(false); setSheet('edit'); }}
                onCopyLink={copyLink}
                onDelete={() => { setMenuOpen(false); setSheet('delete'); }}
              />
            )}
          </div>
        </div>
        {/* Category badge */}
        <div style={{ position: 'absolute', left: 16, bottom: 18 }}>
          <CategoryBadge cat={cat} size="md"/>
        </div>
      </div>

      {/* Body */}
      <div style={{ padding: '0 20px' }}>
        {/* Title */}
        <h1 style={{
          margin: '16px 0 0',
          fontFamily: '"Instrument Serif", serif',
          fontStyle: 'italic',
          fontWeight: 400,
          fontSize: 32, lineHeight: 1.08,
          color: C.navy, letterSpacing: -0.6,
        }}>{item.title}</h1>

        {/* source row */}
        <div style={{
          display: 'flex', alignItems: 'center', gap: 8,
          marginTop: 10,
        }}>
          <SourceDot source={item.source}/>
          <span style={{
            fontFamily: '"DM Sans",system-ui', fontSize: 13,
            color: C.inkMuted, fontWeight: 500,
          }}>{item.source === 'Manual' ? 'manual entry' : item.source}</span>
          <span style={{ color: C.inkMuted, opacity: 0.5 }}>·</span>
          <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
            <Avatar user={author} size={16}/>
            <span style={{
              fontFamily: '"DM Sans",system-ui', fontSize: 13,
              color: C.inkMuted, fontWeight: 500,
            }}>added by {author.name} · {item.addedAt}</span>
          </div>
        </div>

        {/* Date/location card for events — single day shows block, multi-day shows range pill */}
        {item.type === 'event' && item.date && (
          <div style={{
            marginTop: 18,
            background: C.white, borderRadius: 18, padding: 14,
            display: 'flex', alignItems: 'center', gap: 14,
            boxShadow: '0 1px 3px rgba(30,42,74,0.04), 0 6px 14px rgba(30,42,74,0.05)',
            position: 'relative', overflow: 'hidden',
          }}>
            {item.endDate && (
              <div style={{
                position: 'absolute', left: 0, top: 0, bottom: 0, width: 6,
                background: `linear-gradient(180deg, ${C.coral}, ${C.coralSoft})`,
              }}/>
            )}
            <div style={{
              minWidth: 64, textAlign: 'center',
              background: C.coralSoft, borderRadius: 12,
              padding: '8px 10px',
            }}>
              <div style={{
                fontFamily: '"DM Sans",system-ui', fontSize: 10.5,
                fontWeight: 700, color: C.coralDeep, letterSpacing: 0.8,
              }}>{item.date.split(',')[0].toUpperCase()}</div>
              <div style={{
                fontFamily: '"Instrument Serif", serif',
                fontStyle: 'italic', fontSize: 22, lineHeight: 1, color: C.navy,
              }}>
                {item.endDate
                  ? `${item.date.split(' ').pop()}–${item.endDate.split(' ').pop()}`
                  : item.date.split(' ').pop()}
              </div>
            </div>
            <div style={{ flex: 1 }}>
              <div style={{
                fontFamily: '"DM Sans",system-ui', fontWeight: 600, fontSize: 15,
                color: C.navy,
              }}>{item.endDate
                ? (dateRangeLabel ? dateRangeLabel(item.date, item.endDate) : `${item.date} → ${item.endDate}`)
                : (item.time || item.date)}</div>
              <div style={{
                fontFamily: '"DM Sans",system-ui', fontSize: 13, color: C.inkMuted,
                marginTop: 2,
              }}>
                {item.endDate ? `${daysBetween(item.date, item.endDate)} days` : ''}
                {item.endDate && item.location ? ' · ' : ''}
                {item.location || ''}
              </div>
            </div>
          </div>
        )}

        {/* Propose-dates card — appears on open-ended (activity) items */}
        {isOpenEnded && (
          <ProposeDatesCard
            item={item}
            userId={userId}
            members={members}
            proposals={proposals}
            canLock={canEdit}
            onPropose={() => setSheet('propose')}
            onVote={(pid) => actions.voteProposal(item.id, pid)}
            onLock={(pid) => actions.lockProposal(item.id, pid)}
            onWithdraw={(pid) => actions.withdrawProposal(item.id, pid)}
          />
        )}

        {/* "How was it?" — past event */}
        {isPast && (
          <ReviewsCard
            item={item} userId={userId} members={members} reviews={reviews}
            avg={avgRating} myReview={myReview}
            onReview={(rating, text) => actions.submitReview(item.id, rating, text)}
            onOpenRating={() => setSheet('review')}
          />
        )}

        {/* Author note */}
        {item.note && (
          <div style={{
            marginTop: 16,
            background: 'transparent',
            borderLeft: `3px solid ${C.coral}`,
            padding: '4px 0 4px 14px',
          }}>
            <div style={{
              fontFamily: '"DM Sans",system-ui', fontSize: 15, color: C.navy,
              lineHeight: 1.45, letterSpacing: -0.1,
            }}>
              <span style={{ fontWeight: 600 }}>{author.name}:</span> {item.note}
            </div>
          </div>
        )}

        {/* "Who's down" — live */}
        <div style={{ marginTop: 22 }}>
          <div style={{
            display: 'flex', alignItems: 'baseline', justifyContent: 'space-between',
            marginBottom: 10,
          }}>
            <div style={{
              fontFamily: '"Instrument Serif", serif', fontStyle: 'italic',
              fontSize: 22, color: C.navy, letterSpacing: -0.3,
            }}>Who's down</div>
            <div style={{
              fontFamily: '"DM Sans",system-ui', fontSize: 13,
              color: C.inkMuted, fontVariantNumeric: 'tabular-nums',
            }}>{count} of {members.length}</div>
          </div>
          <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
            {effectiveDowns.map((u, i) => (
              <div key={u.id} style={{
                display: 'inline-flex', alignItems: 'center', gap: 7,
                background: u.id === userId ? C.sage : C.white,
                color: u.id === userId ? '#fff' : C.navy,
                padding: '5px 12px 5px 5px',
                borderRadius: 999,
                boxShadow: '0 1px 2px rgba(30,42,74,0.06)',
                animation: i === 0 && u.id === userId ? 'pop 380ms cubic-bezier(0.34,1.56,0.64,1)' : 'none',
              }}>
                <Avatar user={u} size={22}/>
                <span style={{ fontFamily: '"DM Sans",system-ui', fontSize: 13, fontWeight: 600 }}>
                  {u.name}
                </span>
              </div>
            ))}
            <style>{`@keyframes pop { 0%{transform:scale(0.6);opacity:0} 100%{transform:scale(1);opacity:1} }`}</style>
          </div>
        </div>

        {/* Comments */}
        <div style={{ marginTop: 26 }}>
          <div style={{
            fontFamily: '"Instrument Serif", serif', fontStyle: 'italic',
            fontSize: 22, color: C.navy, letterSpacing: -0.3, marginBottom: 12,
          }}>Chat</div>
          {comments.length === 0 && (
            <div style={{
              fontFamily: '"DM Sans",system-ui', fontSize: 13.5, color: C.inkMuted,
              lineHeight: 1.45, padding: '2px 0 10px',
            }}>no messages yet — be the first one.</div>
          )}
          {comments.map(c => {
            const u = byId(c.user);
            return (
              <div key={c.id} style={{ display: 'flex', gap: 10, marginBottom: 10 }}>
                <Avatar user={u} size={30}/>
                <div style={{
                  background: C.white, borderRadius: 16,
                  padding: '9px 13px',
                  boxShadow: '0 1px 2px rgba(30,42,74,0.04)',
                  maxWidth: '85%',
                }}>
                  <div style={{
                    display: 'flex', alignItems: 'baseline', gap: 8,
                    marginBottom: 1,
                  }}>
                    <span style={{ fontFamily: '"DM Sans",system-ui', fontWeight: 600, fontSize: 13, color: C.navy }}>
                      {u.name}
                    </span>
                    <span style={{ fontFamily: '"DM Sans",system-ui', fontSize: 11, color: C.inkMuted }}>
                      {c.time}
                    </span>
                  </div>
                  <div style={{ fontFamily: '"DM Sans",system-ui', fontSize: 14, color: C.navy, lineHeight: 1.35, letterSpacing: -0.1 }}>
                    {c.text}
                  </div>
                </div>
              </div>
            );
          })}
        </div>
      </div>

      {/* Floating bottom CTA — the hero "I'm down" */}
      <div style={{
        position: 'absolute', bottom: 0, left: 0, right: 0,
        padding: '12px 16px calc(env(safe-area-inset-bottom, 0px) + 20px)',
        background: `linear-gradient(to top, ${C.cream} 40%, rgba(251,246,238,0.7) 80%, rgba(251,246,238,0))`,
        zIndex: 20,
      }}>
        <ImDownButton
          isDown={isDown}
          count={count}
          avatars={effectiveDowns.slice(0, 3)}
          onToggle={() => onToggleDown(item.id)}
        />
        <CommentComposer onSend={onComment}/>
      </div>

      {sheet === 'edit' && (
        <EditItemSheet
          item={item}
          onClose={() => setSheet(null)}
          onSave={async (patch) => { await actions.editItem(item.id, patch); setSheet(null); }}
        />
      )}
      {sheet === 'delete' && (
        <DeleteItemSheet
          item={item}
          onClose={() => setSheet(null)}
          onDelete={async () => { await actions.deleteItem(item.id); onClose(); }}
        />
      )}
      {sheet === 'propose' && (
        <ProposeDatesSheet
          item={item}
          onClose={() => setSheet(null)}
          onSubmit={async (startDate, endDate) => {
            await actions.proposeDates(item.id, startDate, endDate);
            setSheet(null);
          }}
        />
      )}
      {sheet === 'review' && (
        <ReviewSheet
          item={item} myReview={myReview}
          onClose={() => setSheet(null)}
          onSubmit={async (rating, text) => {
            await actions.submitReview(item.id, rating, text);
            setSheet(null);
          }}
        />
      )}
    </div>
  );
}

// Kebab popover — sits inside ItemCardScreen's relative button wrapper
function ItemMenu({ canEdit, onClose, onEdit, onCopyLink, onDelete }) {
  const stop = (e) => e.stopPropagation();
  return (
    <>
      {/* Invisible backdrop — tapping anywhere outside closes the menu */}
      <div onClick={onClose} style={{
        position: 'fixed', inset: 0, zIndex: 49,
      }}/>
      <div onClick={stop} style={{
        position: 'absolute', top: 46, right: 0,
        background: '#FFFFFA', borderRadius: 16, padding: 6,
        boxShadow: '0 12px 32px rgba(30,42,74,0.2)',
        minWidth: 200, zIndex: 50,
      }}>
      {canEdit && (
        <MenuItem
          icon={<svg width="15" height="15" viewBox="0 0 15 15"><path d="M10 2l3 3-7 7H3v-3z M9 3l3 3" stroke={C.coral} strokeWidth="1.5" fill="none" strokeLinecap="round" strokeLinejoin="round"/></svg>}
          label="Edit details" onClick={onEdit} highlight
        />
      )}
      <MenuItem
        icon={<svg width="15" height="15" viewBox="0 0 15 15"><rect x="2" y="5" width="9" height="8" rx="1.5" stroke={C.navy} strokeWidth="1.3" fill="none"/><rect x="4" y="2" width="9" height="8" rx="1.5" stroke={C.navy} strokeWidth="1.3" fill="none"/></svg>}
        label="Copy link" onClick={onCopyLink}
      />
      <MenuItem
        icon={<svg width="15" height="15" viewBox="0 0 15 15"><circle cx="7.5" cy="7.5" r="5.5" stroke={C.navy} strokeWidth="1.3" fill="none"/><path d="M7.5 4.5v3M7.5 10v.5" stroke={C.navy} strokeWidth="1.3" strokeLinecap="round"/></svg>}
        label="Report" onClick={() => alert('Thanks — we\'ll review this.')}
      />
      {canEdit && (
        <>
          <div style={{ height: 1, background: 'rgba(30,42,74,0.08)', margin: '4px 10px' }}/>
          <MenuItem
            icon={<svg width="15" height="15" viewBox="0 0 15 15"><path d="M5 5h5M7 5V3a1 1 0 011-1h-1a1 1 0 011 1v2M4 5l.7 8a1.5 1.5 0 001.5 1.3h2.6A1.5 1.5 0 0010.3 13L11 5" stroke={C.coral} strokeWidth="1.3" fill="none" strokeLinecap="round" strokeLinejoin="round"/></svg>}
            label="Delete event" onClick={onDelete} danger
          />
        </>
      )}
      </div>
    </>
  );
}

function MenuItem({ icon, label, onClick, highlight, danger }) {
  return (
    <div onClick={onClick} style={{
      padding: '11px 14px', display: 'flex', alignItems: 'center', gap: 10,
      background: highlight ? 'rgba(255,107,91,0.08)' : 'transparent',
      borderRadius: 10, cursor: 'pointer',
    }}>
      {icon}
      <span style={{
        fontFamily: '"DM Sans",system-ui', fontSize: 13.5,
        color: danger || highlight ? C.coral : C.navy,
        fontWeight: danger || highlight ? 600 : 500,
      }}>{label}</span>
    </div>
  );
}

// Edit item — title, category, note, location, date, photo replace
function EditItemSheet({ item, onClose, onSave }) {
  const [title, setTitle] = React.useState(item.title);
  const [category, setCategory] = React.useState(item.category || 'food');
  const [note, setNote] = React.useState(item.note || '');
  const [location, setLocation] = React.useState(item.location || '');
  const [whenChoice, setWhenChoice] = React.useState(item.type === 'event' && item.date ? 'dated' : 'anytime');
  const [pickedStart, setPickedStart] = React.useState(item.date || defaultProposalStart());
  const [pickedEnd, setPickedEnd] = React.useState(item.endDate || null);
  const [imageOverride, setImageOverride] = React.useState(null);
  const [busy, setBusy] = React.useState(false);
  const fileRef = React.useRef(null);

  const pickPhoto = (e) => {
    const f = e.target.files?.[0]; if (!f) return;
    const url = URL.createObjectURL(f);
    // For edit, just upload via the existing /api/me/avatar-style flow isn't right — use the extract-image flow's upload side-effect?
    // Simpler: POST directly to an upload endpoint. For now, create an object URL preview and send the file along with the PATCH.
    // To keep it simple, skip real upload from edit for now and use a DataURL → tell user to re-scrape.
    setImageOverride({ url, file: f });
  };

  const save = async () => {
    setBusy(true);
    try {
      const patch = {
        title: title.trim(), category,
        note: note.trim() || null, location: location.trim() || null,
        type: whenChoice === 'dated' ? 'event' : 'activity',
        date: whenChoice === 'dated' ? pickedStart : null,
        endDate: whenChoice === 'dated' ? (pickedEnd || null) : null,
      };
      // If user picked a new photo, upload it first by posting to the extract endpoint (reuses multer handler)
      if (imageOverride?.file) {
        const fd = new FormData();
        fd.append('image', imageOverride.file);
        const r = await fetch('/api/extract/image', { method: 'POST', body: fd, credentials: 'same-origin' });
        if (r.ok) {
          const j = await r.json();
          if (j.uploadUrl) patch.image = { url: j.uploadUrl };
        }
      }
      await onSave(patch);
    } catch (e) { alert(e.message || 'save failed'); }
    finally { setBusy(false); }
  };

  const cats = ['food','music','arts','active','movies','outdoors','nightlife'];
  const catLabel = (id) => ({ food: '🍕 Food', music: '🎵 Music', arts: '🎨 Arts', active: '🏃 Active', movies: '🎬 Movies', outdoors: '🌲 Outdoors', nightlife: '🌙 Nightlife' }[id] || id);

  return (
    <BottomSheet title="edit details" onClose={onClose}
      cta={{ label: 'Save', onClick: save }} ctaDisabled={title.trim().length < 1} ctaLoading={busy}>
      <input ref={fileRef} type="file" accept="image/*" onChange={pickPhoto} style={{ display: 'none' }}/>
      {/* Image preview + replace */}
      <div style={{ background: C.white, borderRadius: 16, padding: 12, marginBottom: 14 }}>
        <div style={{ fontFamily: '"DM Sans",system-ui', fontSize: 11, fontWeight: 700, color: C.inkMuted, letterSpacing: 1, textTransform: 'uppercase', marginBottom: 8 }}>image</div>
        <div style={{ position: 'relative', height: 140, borderRadius: 14, background: C.coralSoft, overflow: 'hidden' }}>
          <Placeholder spec={imageOverride || item.image} style={{ width: '100%', height: '100%' }}/>
          <div style={{ position: 'absolute', bottom: 10, right: 10 }}>
            <button onClick={() => fileRef.current?.click()} style={{
              padding: '7px 12px', borderRadius: 999,
              background: 'rgba(30,42,74,0.85)', color: '#fff', border: 'none',
              fontFamily: '"DM Sans",system-ui', fontSize: 12, fontWeight: 600,
              backdropFilter: 'blur(8px)', cursor: 'pointer',
            }}>Replace photo</button>
          </div>
        </div>
      </div>

      {/* Title */}
      <div style={{ padding: '0 4px 6px', fontFamily: '"DM Sans",system-ui', fontSize: 11.5, fontWeight: 700, color: C.inkMuted, letterSpacing: 1, textTransform: 'uppercase' }}>title</div>
      <div style={{ background: C.white, borderRadius: 14, padding: '12px 14px', boxShadow: '0 1px 3px rgba(30,42,74,0.04)' }}>
        <input value={title} onChange={e => setTitle(e.target.value)} style={{
          width: '100%', border: 'none', background: 'transparent', outline: 'none',
          fontFamily: '"Instrument Serif",serif', fontStyle: 'italic', fontSize: 20, color: C.navy,
        }}/>
      </div>

      {/* Category */}
      <div style={{ padding: '16px 4px 6px', fontFamily: '"DM Sans",system-ui', fontSize: 11.5, fontWeight: 700, color: C.inkMuted, letterSpacing: 1, textTransform: 'uppercase' }}>category</div>
      <div style={{ display: 'flex', gap: 7, flexWrap: 'wrap' }}>
        {cats.map(id => {
          const on = category === id;
          return (
            <button key={id} onClick={() => setCategory(id)} style={{
              height: 34, padding: '0 13px', borderRadius: 999,
              background: on ? C.coral : C.white, color: on ? '#fff' : C.navy,
              border: `1.5px solid ${on ? C.coral : 'rgba(30,42,74,0.1)'}`,
              fontFamily: '"DM Sans",system-ui', fontWeight: 600, fontSize: 12.5,
              cursor: 'pointer',
            }}>{catLabel(id)}</button>
          );
        })}
      </div>

      {/* Location */}
      <div style={{ padding: '16px 4px 6px', fontFamily: '"DM Sans",system-ui', fontSize: 11.5, fontWeight: 700, color: C.inkMuted, letterSpacing: 1, textTransform: 'uppercase' }}>location</div>
      <div style={{ background: C.white, borderRadius: 14, padding: '12px 14px', display: 'flex', alignItems: 'center', gap: 8, boxShadow: '0 1px 3px rgba(30,42,74,0.04)' }}>
        <svg width="14" height="14" viewBox="0 0 14 14"><path d="M7 1a4.5 4.5 0 014.5 4.5c0 3-4.5 7.5-4.5 7.5S2.5 8.5 2.5 5.5A4.5 4.5 0 017 1z" stroke={C.coralDeep} strokeWidth="1.3" fill="none"/><circle cx="7" cy="5.5" r="1.5" fill={C.coralDeep}/></svg>
        <input value={location} onChange={e => setLocation(e.target.value)} placeholder="where is it?" style={{
          flex: 1, border: 'none', background: 'transparent', outline: 'none',
          fontFamily: '"DM Sans",system-ui', fontSize: 14,
        }}/>
      </div>

      {/* Note */}
      <div style={{ padding: '16px 4px 6px', fontFamily: '"DM Sans",system-ui', fontSize: 11.5, fontWeight: 700, color: C.inkMuted, letterSpacing: 1, textTransform: 'uppercase' }}>note for the crew</div>
      <textarea
        value={note} onChange={e => setNote(e.target.value)} rows={2}
        placeholder="say something…"
        style={{
          width: '100%', background: C.white, border: 'none', borderRadius: 14,
          padding: '12px 14px', resize: 'none', boxSizing: 'border-box',
          fontFamily: '"DM Sans",system-ui', fontSize: 14, color: C.navy,
          outline: 'none', boxShadow: '0 1px 3px rgba(30,42,74,0.04)',
        }}
      />

      {/* When — allow adding or clearing a date */}
      <div style={{ padding: '16px 4px 6px', fontFamily: '"DM Sans",system-ui', fontSize: 11.5, fontWeight: 700, color: C.inkMuted, letterSpacing: 1, textTransform: 'uppercase' }}>when</div>
      <div style={{
        display: 'flex', background: C.white,
        borderRadius: 14, padding: 4,
        boxShadow: '0 1px 3px rgba(30,42,74,0.04)',
      }}>
        {[
          { id: 'anytime', label: 'Anytime — on the Board' },
          { id: 'dated',   label: 'Pick a date' },
        ].map(o => {
          const on = whenChoice === o.id;
          return (
            <button key={o.id} onClick={() => setWhenChoice(o.id)} style={{
              flex: 1, height: 36, borderRadius: 10,
              background: on ? C.navy : 'transparent',
              color: on ? C.cream : C.navy,
              border: 'none', cursor: 'pointer',
              fontFamily: '"DM Sans",system-ui', fontSize: 12.5, fontWeight: 600,
            }}>{o.label}</button>
          );
        })}
      </div>
      {whenChoice === 'dated' && (
        <DateRangePicker start={pickedStart} end={pickedEnd}
          onChange={(s, e) => { setPickedStart(s); setPickedEnd(e); }}/>
      )}

      <div style={{ marginTop: 14, fontFamily: '"DM Sans",system-ui', fontSize: 11.5, color: C.inkMuted, lineHeight: 1.5 }}>
        original link, adder, and post time stay the same.
      </div>
    </BottomSheet>
  );
}

function DeleteItemSheet({ item, onClose, onDelete }) {
  const [busy, setBusy] = React.useState(false);
  const submit = async () => {
    setBusy(true);
    try { await onDelete(); }
    catch (e) { alert(e.message || 'delete failed'); setBusy(false); }
  };
  return (
    <BottomSheet title="delete this item?" onClose={onClose}
      cta={{ label: 'Delete', onClick: submit, danger: true }} ctaLoading={busy}>
      <div style={{ fontFamily: '"DM Sans",system-ui', fontSize: 14, color: C.navy, lineHeight: 1.5, marginBottom: 6 }}>
        <b>{item.title}</b> will be removed from the huddle. its {item.comments || 0} comments and votes go with it. this can't be undone.
      </div>
    </BottomSheet>
  );
}

function CommentComposer({ onSend }) {
  const [text, setText] = React.useState('');
  const send = () => {
    const t = text.trim();
    if (!t || !onSend) return;
    onSend(t);
    setText('');
  };
  return (
    <div style={{
      marginTop: 10,
      background: C.white, borderRadius: 999,
      padding: '4px 4px 4px 14px',
      display: 'flex', alignItems: 'center', gap: 8,
      boxShadow: '0 1px 3px rgba(30,42,74,0.06)',
    }}>
      <input
        value={text}
        onChange={e => setText(e.target.value)}
        onKeyDown={e => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); send(); } }}
        placeholder="add a comment…"
        style={{
          flex: 1, border: 'none', background: 'transparent', outline: 'none',
          fontFamily: '"DM Sans",system-ui', fontSize: 14, color: C.navy,
          padding: '10px 0',
        }}
      />
      <button onClick={send} disabled={!text.trim()} style={{
        width: 36, height: 36, borderRadius: 18,
        background: text.trim() ? C.navy : 'rgba(30,42,74,0.18)',
        color: C.cream, border: 'none',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        cursor: text.trim() ? 'pointer' : 'default', padding: 0,
        transition: 'background 180ms ease',
      }}>
        <svg width="15" height="15" viewBox="0 0 15 15" fill="none">
          <path d="M2 7.5L13 2l-3 11-2.5-4.5L2 7.5z" stroke="currentColor" strokeWidth="1.6" strokeLinejoin="round"/>
        </svg>
      </button>
    </div>
  );
}

// ─── Open-ended items: Propose dates + live poll ─────────────────────────
// Anyone can propose; anyone can vote; the original adder / huddle owner
// can lock a proposal which promotes the item to an event and clears the
// pool. Proposer implicitly votes for their own proposal on the server.
function ProposeDatesCard({ item, userId, members, proposals, canLock, onPropose, onVote, onLock, onWithdraw }) {
  const total = members.length;
  // Sort by vote count desc, then by creation time
  const ranked = [...proposals].sort((a, b) => (b.votes.length - a.votes.length) || (a.createdAt - b.createdAt));
  return (
    <div style={{
      marginTop: 18,
      background: C.white, borderRadius: 18, padding: 14,
      boxShadow: '0 1px 3px rgba(30,42,74,0.04), 0 6px 14px rgba(30,42,74,0.05)',
    }}>
      <div style={{ display: 'flex', gap: 12, alignItems: 'flex-start' }}>
        <div style={{
          width: 36, height: 36, borderRadius: 12, flexShrink: 0,
          background: `rgba(255,107,91,0.12)`,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
        }}>
          <svg width="20" height="20" viewBox="0 0 22 22" fill="none">
            <rect x="3" y="5" width="16" height="13" rx="2" stroke={C.coral} strokeWidth="1.5" fill="none"/>
            <path d="M3 9h16M7 3v3M15 3v3" stroke={C.coral} strokeWidth="1.5" strokeLinecap="round"/>
          </svg>
        </div>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontFamily: '"Instrument Serif",serif', fontStyle: 'italic', fontSize: 20, color: C.navy }}>
            {proposals.length === 0 ? 'no dates yet' : 'propose & vote'}
          </div>
          <div style={{ fontFamily: '"DM Sans",system-ui', fontSize: 12.5, color: C.inkMuted, lineHeight: 1.4, marginTop: 3 }}>
            {proposals.length === 0
              ? 'on the board as an idea — float some dates to get it on the calendar.'
              : 'tap a date to vote; the adder or owner locks the winning one.'}
          </div>
        </div>
        <button onClick={onPropose} style={{
          padding: '8px 13px', borderRadius: 999,
          background: C.coral, color: '#fff', border: 'none',
          fontFamily: '"DM Sans",system-ui', fontSize: 12.5, fontWeight: 700,
          cursor: 'pointer', display: 'inline-flex', alignItems: 'center', gap: 5,
          boxShadow: '0 4px 10px rgba(255,107,91,0.28)',
        }}>
          <svg width="11" height="11" viewBox="0 0 13 13"><path d="M6.5 2v9M2 6.5h9" stroke="#fff" strokeWidth="1.8" strokeLinecap="round"/></svg>
          Propose
        </button>
      </div>

      {ranked.length > 0 && (
        <div style={{ marginTop: 14, display: 'flex', flexDirection: 'column', gap: 8 }}>
          {ranked.map((p, i) => {
            const voted = p.votes.includes(userId);
            const pct = total > 0 ? Math.round(p.votes.length / total * 100) : 0;
            const isLeading = i === 0 && ranked.length > 1;
            return (
              <div key={p.id} style={{
                border: `1.5px solid ${voted ? C.coral : 'rgba(30,42,74,0.08)'}`,
                background: voted ? 'rgba(255,107,91,0.06)' : C.cream,
                borderRadius: 14, padding: 10,
                position: 'relative', overflow: 'hidden',
              }}>
                {/* vote progress bar */}
                <div style={{
                  position: 'absolute', left: 0, top: 0, bottom: 0,
                  width: `${pct}%`, background: voted ? 'rgba(255,107,91,0.1)' : 'rgba(138,168,150,0.12)',
                  transition: 'width 200ms ease',
                }}/>
                <div style={{ position: 'relative', display: 'flex', alignItems: 'center', gap: 10 }}>
                  <button onClick={() => onVote(p.id)} style={{
                    flex: 1, background: 'transparent', border: 'none', cursor: 'pointer',
                    display: 'flex', alignItems: 'center', gap: 10, padding: 0, textAlign: 'left',
                  }}>
                    <div style={{
                      width: 44, textAlign: 'center',
                      background: C.white, borderRadius: 10, padding: '5px 0',
                      boxShadow: '0 1px 2px rgba(30,42,74,0.06)',
                    }}>
                      <div style={{ fontFamily: '"DM Sans",system-ui', fontSize: 9, fontWeight: 700, color: C.coralDeep }}>
                        {p.startDate.split(',')[0].toUpperCase()}
                      </div>
                      <div style={{ fontFamily: '"Instrument Serif",serif', fontStyle: 'italic', fontSize: 18, lineHeight: 1, color: C.navy }}>
                        {p.endDate
                          ? `${p.startDate.split(' ').pop()}–${p.endDate.split(' ').pop()}`
                          : p.startDate.split(' ').pop()}
                      </div>
                    </div>
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <div style={{ fontFamily: '"DM Sans",system-ui', fontWeight: 600, fontSize: 13, color: C.navy }}>
                        {p.endDate ? (dateRangeLabel ? dateRangeLabel(p.startDate, p.endDate) : `${p.startDate} → ${p.endDate}`) : p.startDate}
                        {isLeading && <span style={{ marginLeft: 6, color: C.coralDeep, fontSize: 11, fontWeight: 700 }}>leading</span>}
                      </div>
                      <div style={{ fontFamily: '"DM Sans",system-ui', fontSize: 11.5, color: C.inkMuted, marginTop: 2, display: 'flex', alignItems: 'center', gap: 6 }}>
                        <AvatarStack users={p.votes.map(id => members.find(m => m.id === id)).filter(Boolean)} size={16} max={3}/>
                        <span>{p.votes.length} of {total}</span>
                        {voted && <span style={{ color: C.coralDeep, fontWeight: 700 }}>· you</span>}
                      </div>
                    </div>
                  </button>
                  {canLock && (
                    <button onClick={() => onLock(p.id)} style={{
                      padding: '6px 10px', borderRadius: 999,
                      background: C.navy, color: C.cream, border: 'none',
                      fontFamily: '"DM Sans",system-ui', fontSize: 11.5, fontWeight: 600,
                      cursor: 'pointer', flexShrink: 0,
                    }}>Lock</button>
                  )}
                  {!canLock && p.createdBy === userId && (
                    <button onClick={() => onWithdraw(p.id)} style={{
                      padding: 6, background: 'transparent', border: 'none',
                      color: C.inkMuted, cursor: 'pointer',
                    }}>×</button>
                  )}
                </div>
              </div>
            );
          })}
        </div>
      )}
    </div>
  );
}

function ProposeDatesSheet({ item, onClose, onSubmit }) {
  const [start, setStart] = React.useState(defaultProposalStart());
  const [end, setEnd] = React.useState(null);
  const [busy, setBusy] = React.useState(false);
  const submit = async () => {
    setBusy(true);
    try { await onSubmit(start, end); }
    catch (e) { alert(e.message || 'could not propose'); setBusy(false); }
  };
  return (
    <BottomSheet title="propose dates" onClose={onClose}
      cta={{ label: end ? `Propose ${start.split(' ').pop()}–${end.split(' ').pop()}` : `Propose ${start}`, onClick: submit }}
      ctaLoading={busy}>
      <div style={{ fontFamily: '"DM Sans",system-ui', fontSize: 13.5, color: C.inkMuted, lineHeight: 1.5, marginBottom: 14 }}>
        for <b style={{ color: C.navy }}>{item.title}</b> · pick a day or a range. the crew will vote.
      </div>
      <DateRangePicker start={start} end={end} onChange={(s, e) => { setStart(s); setEnd(e); }}/>
    </BottomSheet>
  );
}

function defaultProposalStart() {
  const d = new Date();
  const delta = (6 - d.getDay() + 7) % 7 || 7;
  d.setDate(d.getDate() + delta);
  return dateLabel(d);
}

// ─── Past events: "how was it?" ──────────────────────────────────────────
const RATING_EMOJIS = ['😬','😐','🙂','😍','🤩'];

function ReviewsCard({ item, userId, members, reviews, avg, myReview, onReview, onOpenRating }) {
  if (!myReview) {
    // Compact inline rating — tap an emoji to rate without opening the sheet
    return (
      <div style={{
        marginTop: 18,
        background: `linear-gradient(140deg,#FFF9F5,#FFFFFA)`,
        borderRadius: 18, padding: 14,
        boxShadow: '0 1px 3px rgba(30,42,74,0.04), 0 6px 14px rgba(30,42,74,0.05)',
      }}>
        <div style={{ fontFamily: '"DM Sans",system-ui', fontSize: 11.5, color: C.coralDeep, fontWeight: 700, letterSpacing: 0.8, textTransform: 'uppercase' }}>
          past event
        </div>
        <div style={{ fontFamily: '"Instrument Serif",serif', fontStyle: 'italic', fontSize: 22, color: C.navy, marginTop: 2 }}>
          how was it?
        </div>
        <div style={{ display: 'flex', gap: 6, marginTop: 10 }}>
          {RATING_EMOJIS.map((e, i) => (
            <button key={i} onClick={() => onReview(i + 1, '')} style={{
              flex: 1, height: 48, borderRadius: 12,
              border: '1.5px solid rgba(30,42,74,0.1)',
              background: '#FFFFFA', cursor: 'pointer',
              fontSize: 22, padding: 0,
            }}>{e}</button>
          ))}
        </div>
        <button onClick={onOpenRating} style={{
          marginTop: 10, width: '100%', height: 36, borderRadius: 999,
          background: 'transparent', border: `1.5px solid ${C.hairline}`,
          color: C.navy, cursor: 'pointer',
          fontFamily: '"DM Sans",system-ui', fontSize: 12.5, fontWeight: 600,
        }}>Rate + add a note</button>
      </div>
    );
  }
  // Already rated — show group summary
  return (
    <div style={{
      marginTop: 18,
      background: C.white, borderRadius: 18, padding: 14,
      boxShadow: '0 1px 3px rgba(30,42,74,0.04), 0 6px 14px rgba(30,42,74,0.05)',
    }}>
      <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between' }}>
        <div>
          <div style={{ fontFamily: '"DM Sans",system-ui', fontSize: 11.5, fontWeight: 700, color: C.inkMuted, letterSpacing: 0.8, textTransform: 'uppercase' }}>
            {reviews.length === members.length ? 'crew loved it' : 'early reviews'}
          </div>
          <div style={{ display: 'flex', alignItems: 'baseline', gap: 4, marginTop: 2 }}>
            <div style={{ fontFamily: '"Instrument Serif",serif', fontStyle: 'italic', fontSize: 32, lineHeight: 1, color: C.coral }}>
              {avg?.toFixed(1)}
            </div>
            <div style={{ fontFamily: '"DM Sans",system-ui', fontSize: 13, color: C.inkMuted }}>/5</div>
          </div>
        </div>
        <div style={{ textAlign: 'right', fontFamily: '"DM Sans",system-ui', fontSize: 11.5, color: C.inkMuted }}>
          {reviews.length} of {members.length} rated
          <div style={{ marginTop: 4 }}>
            <button onClick={onOpenRating} style={{
              padding: '6px 10px', borderRadius: 999,
              background: C.cream, border: 'none', cursor: 'pointer',
              fontFamily: '"DM Sans",system-ui', fontSize: 11.5, fontWeight: 600, color: C.navy,
            }}>Edit yours</button>
          </div>
        </div>
      </div>
      <div style={{ marginTop: 10, paddingTop: 10, borderTop: '1px solid rgba(30,42,74,0.08)', display: 'flex', flexDirection: 'column', gap: 10 }}>
        {reviews.map(r => {
          const u = members.find(m => m.id === r.user) || { id: r.user, name: '?', avatar: '?', color: C.inkMuted };
          return (
            <div key={r.user} style={{ display: 'flex', gap: 10, alignItems: 'flex-start' }}>
              <Avatar user={u} size={28}/>
              <div style={{ flex: 1 }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                  <span style={{ fontFamily: '"DM Sans",system-ui', fontWeight: 600, fontSize: 13 }}>{u.name}</span>
                  <span style={{ fontSize: 15 }}>{RATING_EMOJIS[r.rating - 1]}</span>
                </div>
                {r.text && (
                  <div style={{ fontFamily: '"DM Sans",system-ui', fontSize: 13, color: C.navy, opacity: 0.85, marginTop: 2, lineHeight: 1.4 }}>
                    {r.text}
                  </div>
                )}
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

function ReviewSheet({ item, myReview, onClose, onSubmit }) {
  const [rating, setRating] = React.useState(myReview?.rating || 4);
  const [text, setText] = React.useState(myReview?.text || '');
  const [busy, setBusy] = React.useState(false);
  const submit = async () => {
    setBusy(true);
    try { await onSubmit(rating, text.trim()); }
    catch (e) { alert(e.message || 'could not save'); setBusy(false); }
  };
  return (
    <BottomSheet title={`how was ${item.title.split(' — ')[0]}?`} onClose={onClose}
      cta={{ label: 'Post review', onClick: submit }} ctaLoading={busy}>
      <div style={{ display: 'flex', gap: 6, marginTop: 6 }}>
        {RATING_EMOJIS.map((e, i) => {
          const on = rating === i + 1;
          return (
            <button key={i} onClick={() => setRating(i + 1)} style={{
              flex: 1, height: 54, borderRadius: 12,
              border: on ? `2px solid ${C.coral}` : '1.5px solid rgba(30,42,74,0.1)',
              background: on ? 'rgba(255,107,91,0.08)' : '#FFFFFA',
              cursor: 'pointer', fontSize: 24, padding: 0,
              boxShadow: on ? '0 4px 10px rgba(255,107,91,0.15)' : 'none',
            }}>{e}</button>
          );
        })}
      </div>
      <div style={{ marginTop: 12, background: C.white, borderRadius: 12, padding: '10px 12px' }}>
        <input
          value={text} onChange={e => setText(e.target.value)}
          placeholder="one line for the crew…"
          maxLength={280}
          style={{
            width: '100%', border: 'none', background: 'transparent', outline: 'none',
            fontFamily: '"DM Sans",system-ui', fontSize: 14, color: C.navy,
          }}
        />
      </div>
    </BottomSheet>
  );
}

Object.assign(window, {
  ItemCardScreen, CommentComposer, ItemMenu, EditItemSheet, DeleteItemSheet,
  ProposeDatesCard, ProposeDatesSheet, ReviewsCard, ReviewSheet,
});
