/* global React, OB_DATA */
const { useState: useStateS, useMemo: useMemoS } = React;

/* ====================================================
   SCREEN: Sign in — wired against the real back end.
   ====================================================
   The form POSTs to /api/auth/request via window.api.
   The server always returns 204 (no leaking of which
   addresses are registered), so success here means only
   that the request was accepted — the user must check
   their actual email and click the link, which lands on
   /auth/consume, sets the session cookie, and redirects
   back to /?auth=ok. There is no demo bypass any more.
*/

function SignIn({ onRequestLink, flash, onDismissFlash }) {
  const [email, setEmail] = useStateS('');
  const [submitted, setSubmitted] = useStateS(false);
  const [busy, setBusy] = useStateS(false);

  const submit = async () => {
    if (!email.trim() || busy) return;
    onDismissFlash && onDismissFlash();
    setBusy(true);
    const ok = await onRequestLink(email);
    setBusy(false);
    if (ok) setSubmitted(true);
  };

  const flashError = flash && flash.kind === 'error' ? flash.text : null;

  return (
    <div className="signin-wrap">
      <div className="signin-card">
        <div className="brand">
          <HallMark size={64} color="var(--olive-deep)" />
          <h1>St Katherine&rsquo;s Hall</h1>
          <div className="sub">Community Voice &middot; a members&rsquo; space</div>
        </div>

        {flashError && (
          <div className="signin-error">{flashError}</div>
        )}

        {submitted ? (
          <div className="magic-link-state">
            <div style={{ fontFamily: 'var(--serif)', fontSize: 22, fontStyle: 'italic', color: 'var(--olive-deep)', marginBottom: 8 }}>
              Check your inbox
            </div>
            <div style={{ fontSize: 14, color: 'var(--ink-soft)' }}>
              If <span className="mono">{email}</span> is on the invite list, a one-time link is on its way.
            </div>
            <div style={{ fontSize: 12, color: 'var(--ink-faint)', marginTop: 6, fontStyle: 'italic' }}>
              The link will work once and expires in 15 minutes.
            </div>
            <button
              className="btn btn-ghost btn-sm"
              style={{ marginTop: 14 }}
              onClick={() => { setSubmitted(false); setEmail(''); }}
            >
              Use a different address
            </button>
          </div>
        ) : (
          <>
            <label className="field">
              <span className="lbl">Email address</span>
              <input
                type="email"
                placeholder="you@example.org"
                value={email}
                onChange={e => setEmail(e.target.value)}
                onKeyDown={e => { if (e.key === 'Enter' && email.trim() && !busy) submit(); }}
                disabled={busy}
              />
              <span className="hint">We&rsquo;ll send you a one-time link. No password to remember.</span>
            </label>
            <button
              className="btn btn-primary"
              style={{ width: '100%', justifyContent: 'center' }}
              disabled={!email.trim() || busy}
              onClick={submit}
            >
              {busy ? 'Sending\u2026' : 'Send me a sign-in link'}
            </button>
          </>
        )}

        <p className="note">By invitation only. If you haven&rsquo;t received an invitation and would like to be part of the conversation, please write to LEAF directly at <span className="mono">admin@leafledbury.com</span>.</p>
      </div>
    </div>
  );
}

/* ====================================================
   SCREEN: Welcome
   ==================================================== */
function Welcome({ onNav, ideas, showBanner, currentFocus, currentUser, nameMode }) {
  const recent = [...ideas].sort((a, b) => (a.stage === 'In Discussion' || a.stage === 'Proposed' ? -1 : 1)).slice(0, 3);
  return (
    <div className="page">
      <div className="welcome-hero">
        <div className="corner-ornament">
          <HallMark size={300} color="var(--olive)" />
        </div>
        <div className="eyebrow">A welcome from LEAF</div>
        <h1>Pull up a chair. We&rsquo;re glad you&rsquo;re here.</h1>
        <p className="lede">
          The Community Voice is a small, invited room. We come here to think out loud together about how St Katherine&rsquo;s Hall can best serve the town &mdash; carefully, kindly, and at the pace good ideas need. Speak freely. Rank honestly. Expect to be heard.
        </p>
        <div className="sig">— LEAF</div>
      </div>

      {showBanner && (
        <div className="current-focus">
          <div style={{ flexShrink: 0, marginTop: 4 }}>
            <HallMark size={56} color="var(--olive-deep)" />
          </div>
          <div>
            <div className="focus-label">This month&rsquo;s invitation</div>
            <h3>{currentFocus.title}</h3>
            <p>{currentFocus.body}</p>
            <div className="cf-actions">
              <button className="btn btn-primary btn-sm" onClick={() => onNav('voice')}>Read what people are saying</button>
              <button className="btn btn-secondary btn-sm" onClick={() => onNav('submit')}>Share your own thought</button>
            </div>
          </div>
        </div>
      )}

      <CountsRow ideas={ideas} />

      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 16, marginTop: 12 }}>
        <h2 style={{ fontStyle: 'italic', fontWeight: 400 }}>What&rsquo;s being talked about</h2>
        <a onClick={() => onNav('voice')} style={{ cursor: 'pointer', fontFamily: 'var(--mono)', fontSize: 11, letterSpacing: '0.14em', textTransform: 'uppercase' }}>See all →</a>
      </div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
        {recent.map(idea => (
          <IdeaCard key={idea.id} idea={idea} onOpen={(id) => onNav('idea:' + id)} nameMode={nameMode} currentUserId={currentUser.id} />
        ))}
      </div>

      <div style={{ marginTop: 40 }}>
        <h2 style={{ fontStyle: 'italic', fontWeight: 400, marginBottom: 16 }}>Three things to know</h2>
        <div className="grid-3">
          <div className="welcome-tile" onClick={() => onNav('lib:ownership')}>
            <h4>Proposing, claiming, owning</h4>
            <p>Anyone can suggest an idea. Owning is a different commitment — a member who agrees to refine it and see it through.</p>
            <span className="more">Read more →</span>
          </div>
          <div className="welcome-tile" onClick={() => onNav('lib:ranking')}>
            <h4>On ranking, and what it isn&rsquo;t</h4>
            <p>You&rsquo;ll be asked to rank ideas on Need and Practicality. This is not voting. It helps LEAF think well — it does not bind us.</p>
            <span className="more">Read more →</span>
          </div>
          <div className="welcome-tile" onClick={() => onNav('lib:host')}>
            <h4>LEAF as host, not chair</h4>
            <p>We host this room because LEAF is funding and stewarding the hall. We&rsquo;ll listen carefully and decide thoughtfully.</p>
            <span className="more">Read more →</span>
          </div>
        </div>
      </div>
    </div>
  );
}

/* ====================================================
   SCREEN: Community Voice (list)
   ==================================================== */
function CommunityVoice({ ideas, onNav, nameMode, currentUserId }) {
  const { THEMES, STAGES } = window.OB_DATA;
  const [stage, setStage] = useStateS('all');
  const [theme, setTheme] = useStateS('all');
  const [sort, setSort] = useStateS('updated');
  const [ownerFilter, setOwnerFilter] = useStateS('all');

  const filtered = useMemoS(() => {
    let r = ideas.slice();
    if (stage !== 'all') r = r.filter(i => i.stage === stage);
    if (theme !== 'all') r = r.filter(i => i.theme === theme);
    if (ownerFilter === 'unclaimed') r = r.filter(i => (i.owners || []).length === 0);
    if (ownerFilter === 'mine') r = r.filter(i => (i.owners || []).includes(currentUserId));
    if (sort === 'need') r.sort((a, b) => b.rankings.need - a.rankings.need);
    else if (sort === 'practicality') r.sort((a, b) => b.rankings.practicality - a.rankings.practicality);
    else if (sort === 'voices') r.sort((a, b) => (b.commentsCount || 0) - (a.commentsCount || 0));
    return r;
  }, [ideas, stage, theme, sort, ownerFilter, currentUserId]);

  const unclaimedCount = ideas.filter(i => (i.owners || []).length === 0).length;
  const myCount = ideas.filter(i => (i.owners || []).includes(currentUserId)).length;

  return (
    <div className="page">
      <div className="page-head" style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end' }}>
        <div>
          <div className="eyebrow">Community Voice</div>
          <h1 style={{ fontStyle: 'italic', fontWeight: 400 }}>The ideas in the room</h1>
          <p className="lede">Every idea here came from a member. Read, comment, refine, rank. LEAF reads it all.</p>
        </div>
        <button className="btn btn-primary" onClick={() => onNav('submit')}>
          <span style={{ fontSize: 18, lineHeight: 0.5 }}>+</span> Propose an idea
        </button>
      </div>

      <div className="filter-bar">
        <span style={{ fontFamily: 'var(--mono)', fontSize: 10, letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--ink-faint)', marginRight: 8 }}>Show</span>
        <span className={'chip' + (ownerFilter === 'all' ? ' active' : '')} onClick={() => setOwnerFilter('all')}>All ideas</span>
        <span className={'chip' + (ownerFilter === 'unclaimed' ? ' active' : '')} onClick={() => setOwnerFilter('unclaimed')}>
          Looking for an owner {unclaimedCount > 0 && <span style={{ opacity: 0.7, marginLeft: 4 }}>({unclaimedCount})</span>}
        </span>
        <span className={'chip' + (ownerFilter === 'mine' ? ' active' : '')} onClick={() => setOwnerFilter('mine')}>
          Mine {myCount > 0 && <span style={{ opacity: 0.7, marginLeft: 4 }}>({myCount})</span>}
        </span>
      </div>

      <div className="filter-bar">
        <span style={{ fontFamily: 'var(--mono)', fontSize: 10, letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--ink-faint)', marginRight: 8 }}>Stage</span>
        <span className={'chip' + (stage === 'all' ? ' active' : '')} onClick={() => setStage('all')}>All</span>
        {STAGES.map(s => (
          <span key={s} className={'chip' + (stage === s ? ' active' : '')} onClick={() => setStage(s)}>{s}</span>
        ))}
      </div>

      <div className="filter-bar">
        <span style={{ fontFamily: 'var(--mono)', fontSize: 10, letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--ink-faint)', marginRight: 8 }}>Theme</span>
        <span className={'chip' + (theme === 'all' ? ' active' : '')} onClick={() => setTheme('all')}>All themes</span>
        {THEMES.map(t => (
          <span key={t} className={'chip' + (theme === t ? ' active' : '')} onClick={() => setTheme(t)}>{t}</span>
        ))}
        <span style={{ flex: 1 }} />
        <span style={{ fontFamily: 'var(--mono)', fontSize: 10, letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--ink-faint)', marginRight: 4 }}>Sort by</span>
        <select value={sort} onChange={e => setSort(e.target.value)} style={{ width: 160, padding: '6px 10px', fontSize: 13 }}>
          <option value="updated">Most recently updated</option>
          <option value="need">Highest need</option>
          <option value="practicality">Most practical</option>
          <option value="voices">Most voices</option>
        </select>
      </div>

      <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
        {filtered.length === 0 && (
          <div style={{ padding: '40px 20px', textAlign: 'center', color: 'var(--ink-faint)', fontStyle: 'italic' }}>
            No ideas match the current filter.
          </div>
        )}
        {filtered.map(idea => (
          <IdeaCard key={idea.id} idea={idea} onOpen={(id) => onNav('idea:' + id)} nameMode={nameMode} currentUserId={currentUserId} />
        ))}
      </div>
    </div>
  );
}

/* ====================================================
   SCREEN: Idea detail
   ==================================================== */
function IdeaDetail({ idea, onNav, onComment, onRank, onRequestClaim, onCancelClaim, onStepBack, onEditIdea, onApproveClaim, onDeclineClaim, currentUser, nameMode }) {
  const { MEMBER_BY_ID } = window.OB_DATA;
  const proposerMember = idea.proposerMember ? MEMBER_BY_ID[idea.proposerMember] : null;
  const myR = idea.myRanking || {};
  const owners = (idea.owners || []).map(id => MEMBER_BY_ID[id]).filter(Boolean);
  const isOwner = (idea.owners || []).includes(currentUser.id);
  const hasPendingClaim = (idea.claimRequests || []).some(r => r.memberId === currentUser.id);
  const isLeaf = currentUser.isLeaf;

  const [editing, setEditing] = useStateS(false);
  const [claimOpen, setClaimOpen] = useStateS(false);
  const [claimMessage, setClaimMessage] = useStateS('');
  const [draft, setDraft] = useStateS({
    title: idea.title, summary: idea.summary, what: idea.what, who: idea.who, needs: idea.needs, theme: idea.theme
  });

  const enterEdit = () => {
    setDraft({ title: idea.title, summary: idea.summary, what: idea.what, who: idea.who, needs: idea.needs, theme: idea.theme });
    setEditing(true);
  };
  const saveEdit = () => {
    onEditIdea(idea.id, draft);
    setEditing(false);
  };
  const lastEdit = (idea.edits && idea.edits.length) ? idea.edits[idea.edits.length - 1] : null;

  return (
    <div className="page">
      <button className="back-link" onClick={() => onNav('voice')}>← Back to Community Voice</button>

      <div className="idea-header">
        <div className="eyebrow">Idea · posted {idea.posted} · {idea.theme}</div>
        {editing ? (
          <input
            value={draft.title}
            onChange={e => setDraft({ ...draft, title: e.target.value })}
            style={{ fontFamily: 'var(--serif)', fontSize: 36, fontStyle: 'italic', padding: '8px 12px', marginBottom: 12, maxWidth: 800 }}
          />
        ) : (
          <h1 style={{ fontStyle: 'italic', fontWeight: 500 }}>{idea.title}</h1>
        )}
        <div className="meta" style={{ flexWrap: 'wrap' }}>
          {proposerMember ? (
            <span style={{ display: 'inline-flex', alignItems: 'center', gap: 8 }}>
              <Avatar member={proposerMember} size="sm" />
              <span>{idea.proposer}</span>
            </span>
          ) : (
            <span style={{ fontStyle: 'italic' }}>{idea.proposer}</span>
          )}
          <span style={{ color: 'var(--rule)' }}>·</span>
          <StagePill stage={idea.stage} />
          {lastEdit && !editing && (
            <>
              <span style={{ color: 'var(--rule)' }}>·</span>
              <span style={{ fontFamily: 'var(--mono)', fontSize: 11, color: 'var(--ink-faint)', letterSpacing: '0.04em' }}>
                refined by {MEMBER_BY_ID[lastEdit.by]?.first || 'someone'} · {lastEdit.when}
              </span>
            </>
          )}
        </div>
      </div>

      <div className="idea-body">
        <div>
          {editing ? (
            <div className="edit-form">
              <label className="field">
                <span className="lbl">In one sentence</span>
                <input value={draft.summary} onChange={e => setDraft({ ...draft, summary: e.target.value })} />
              </label>
              <label className="field">
                <span className="lbl">Theme</span>
                <select value={draft.theme} onChange={e => setDraft({ ...draft, theme: e.target.value })}>
                  {window.OB_DATA.THEMES.map(t => <option key={t} value={t}>{t}</option>)}
                </select>
              </label>
              <label className="field">
                <span className="lbl">What it would do</span>
                <textarea value={draft.what} onChange={e => setDraft({ ...draft, what: e.target.value })} rows={4} />
              </label>
              <label className="field">
                <span className="lbl">Who it would serve</span>
                <textarea value={draft.who} onChange={e => setDraft({ ...draft, who: e.target.value })} rows={3} />
              </label>
              <label className="field">
                <span className="lbl">What it would need</span>
                <textarea value={draft.needs} onChange={e => setDraft({ ...draft, needs: e.target.value })} rows={3} />
              </label>
              <div style={{ display: 'flex', gap: 10, marginTop: 8 }}>
                <button className="btn btn-primary" onClick={saveEdit}>Save refinements</button>
                <button className="btn btn-secondary" onClick={() => setEditing(false)}>Cancel</button>
              </div>
            </div>
          ) : (
            <>
              <section>
                <h4>What it would do</h4>
                <p className="answer">{idea.what}</p>
              </section>
              <section>
                <h4>Who it would serve</h4>
                <p className="answer">{idea.who}</p>
              </section>
              <section>
                <h4>What it would need</h4>
                <p className="answer">{idea.needs}</p>
              </section>
            </>
          )}

          {idea.leafResponse && !editing && (
            <section style={{ background: 'var(--olive-tint)', border: '1px solid var(--olive-soft)', borderRadius: 8, padding: '20px 24px' }}>
              <h4 style={{ color: 'var(--olive-deep)' }}>LEAF’s response</h4>
              <p className="answer" style={{ color: 'var(--olive-deep)', fontStyle: 'italic' }}>{idea.leafResponse}</p>
            </section>
          )}

          {!editing && (
            <Discussion
              comments={idea.comments}
              onPost={(text) => onComment(idea.id, text)}
              nameMode={nameMode}
              currentUser={currentUser}
            />
          )}
        </div>

        <aside>
          <div className="sidebar-block ownership-block">
            <h4>Ownership</h4>
            {owners.length === 0 ? (
              <>
                <div className="owner-status unclaimed-status">
                  <span className="unclaimed-dot" />
                  This idea is looking for an owner.
                </div>
                <p style={{ fontSize: 13, color: 'var(--ink-soft)', marginTop: 10 }}>
                  Owners commit to refining the idea, responding to questions, and helping LEAF move it forward. You can co-own with others.
                </p>
                {hasPendingClaim ? (
                  <div className="claim-pending-card">
                    <strong>Your claim is with LEAF.</strong>
                    <div style={{ fontSize: 12, color: 'var(--ink-soft)', marginTop: 4 }}>
                      They’ll approve or come back to you within a few days.
                    </div>
                    <button className="btn btn-ghost btn-sm" style={{ marginTop: 10, padding: '4px 8px' }} onClick={() => onCancelClaim(idea.id)}>Withdraw request</button>
                  </div>
                ) : claimOpen ? (
                  <div style={{ marginTop: 14 }}>
                    <label className="field">
                      <span className="lbl">A note for LEAF (optional)</span>
                      <textarea
                        rows={3}
                        value={claimMessage}
                        onChange={e => setClaimMessage(e.target.value)}
                        placeholder="Why this idea, what you bring, who you’d work with."
                      />
                    </label>
                    <div style={{ display: 'flex', gap: 8 }}>
                      <button className="btn btn-primary btn-sm" onClick={() => { onRequestClaim(idea.id, claimMessage); setClaimOpen(false); setClaimMessage(''); }}>Send to LEAF</button>
                      <button className="btn btn-secondary btn-sm" onClick={() => setClaimOpen(false)}>Cancel</button>
                    </div>
                  </div>
                ) : (
                  <button className="btn btn-primary btn-sm" style={{ marginTop: 14, width: '100%', justifyContent: 'center' }} onClick={() => setClaimOpen(true)}>
                    Claim this idea
                  </button>
                )}
              </>
            ) : (
              <>
                <div className="owner-list">
                  {owners.map(o => (
                    <div key={o.id} className="owner-row">
                      <Avatar member={o} size="sm" />
                      <span style={{ fontSize: 14, fontWeight: 600 }}>
                        {o.id === currentUser.id ? 'You' : displayName(o, nameMode)}
                      </span>
                      {o.id === currentUser.id && (
                        <button className="owner-step-back" onClick={() => onStepBack(idea.id)} title="Release ownership">step back</button>
                      )}
                    </div>
                  ))}
                </div>
                {isOwner ? (
                  !editing && (
                    <button className="btn btn-primary btn-sm" style={{ marginTop: 14, width: '100%', justifyContent: 'center' }} onClick={enterEdit}>
                      Refine this idea
                    </button>
                  )
                ) : hasPendingClaim ? (
                  <div className="claim-pending-card">
                    <strong>Your request to co-own is with LEAF.</strong>
                    <button className="btn btn-ghost btn-sm" style={{ marginTop: 8, padding: '4px 8px' }} onClick={() => onCancelClaim(idea.id)}>Withdraw</button>
                  </div>
                ) : claimOpen ? (
                  <div style={{ marginTop: 14 }}>
                    <label className="field">
                      <span className="lbl">A note for LEAF (optional)</span>
                      <textarea rows={3} value={claimMessage} onChange={e => setClaimMessage(e.target.value)} placeholder="Why you’d like to co-own, what you bring." />
                    </label>
                    <div style={{ display: 'flex', gap: 8 }}>
                      <button className="btn btn-primary btn-sm" onClick={() => { onRequestClaim(idea.id, claimMessage); setClaimOpen(false); setClaimMessage(''); }}>Send to LEAF</button>
                      <button className="btn btn-secondary btn-sm" onClick={() => setClaimOpen(false)}>Cancel</button>
                    </div>
                  </div>
                ) : (
                  <button className="btn btn-secondary btn-sm" style={{ marginTop: 14, width: '100%', justifyContent: 'center' }} onClick={() => setClaimOpen(true)}>
                    Ask to co-own
                  </button>
                )}
              </>
            )}

            {isLeaf && (idea.claimRequests || []).length > 0 && (
              <div className="leaf-claim-queue">
                <div className="leaf-queue-label">Pending claims (LEAF view)</div>
                {idea.claimRequests.map(r => {
                  const m = MEMBER_BY_ID[r.memberId];
                  return (
                    <div key={r.memberId} className="queue-row">
                      <Avatar member={m} size="sm" />
                      <div style={{ flex: 1, fontSize: 13 }}>
                        <div style={{ fontWeight: 600 }}>{m?.name}</div>
                        {r.message && <div style={{ fontStyle: 'italic', color: 'var(--ink-soft)', fontSize: 12, marginTop: 2 }}>“{r.message}”</div>}
                        <div style={{ fontSize: 11, color: 'var(--ink-faint)', fontFamily: 'var(--mono)', marginTop: 4 }}>{r.when}</div>
                      </div>
                      <div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
                        <button className="btn btn-primary btn-sm" style={{ padding: '3px 8px', fontSize: 11 }} onClick={() => onApproveClaim(idea.id, r.memberId)}>Approve</button>
                        <button className="btn btn-secondary btn-sm" style={{ padding: '3px 8px', fontSize: 11 }} onClick={() => onDeclineClaim(idea.id, r.memberId)}>Decline</button>
                      </div>
                    </div>
                  );
                })}
              </div>
            )}
          </div>

          <div className="sidebar-block">
            <h4>How you see this</h4>
            <p style={{ fontSize: 12, color: 'var(--ink-faint)', fontStyle: 'italic', marginTop: -6, marginBottom: 16 }}>
              Your honest read. Helps LEAF think — does not commit them.
            </p>

            <div className="rank-row">
              <div className="label">
                <span className="name">Need</span>
                <span className="desc">Does this matter for the town?</span>
              </div>
              <RankDots value={myR.need || 0} interactive onChange={(n) => onRank(idea.id, 'need', n)} />
            </div>
            <div className="rank-row">
              <div className="label">
                <span className="name">Practicality</span>
                <span className="desc">Could we actually do it?</span>
              </div>
              <RankDots value={myR.practicality || 0} interactive terra onChange={(n) => onRank(idea.id, 'practicality', n)} />
            </div>
          </div>

          <div className="sidebar-block">
            <h4>Community average</h4>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
                <span style={{ fontSize: 13 }}>Need</span>
                <span style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                  <RankDots value={idea.rankings.need} />
                  <span style={{ fontFamily: 'var(--mono)', fontSize: 12, color: 'var(--ink-faint)' }}>{idea.rankings.need.toFixed(1)}</span>
                </span>
              </div>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
                <span style={{ fontSize: 13 }}>Practicality</span>
                <span style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                  <RankDots value={idea.rankings.practicality} terra />
                  <span style={{ fontFamily: 'var(--mono)', fontSize: 12, color: 'var(--ink-faint)' }}>{idea.rankings.practicality.toFixed(1)}</span>
                </span>
              </div>
            </div>
            <div style={{ fontSize: 11, color: 'var(--ink-faint)', fontFamily: 'var(--mono)', letterSpacing: '0.08em', marginTop: 12 }}>
              {idea.rankings.votes} {idea.rankings.votes === 1 ? 'member has' : 'members have'} ranked
            </div>
          </div>

          <div className="sidebar-block">
            <h4>Where this idea is</h4>
            <StageTrack stage={idea.stage} />
          </div>
        </aside>
      </div>
    </div>
  );
}

/* ====================================================
   SCREEN: Submit
   ==================================================== */
function Submit({ onSubmit, onNav }) {
  const { THEMES } = window.OB_DATA;
  const [title, setTitle] = useStateS('');
  const [summary, setSummary] = useStateS('');
  const [what, setWhat] = useStateS('');
  const [who, setWho] = useStateS('');
  const [needs, setNeeds] = useStateS('');
  const [theme, setTheme] = useStateS(THEMES[0]);

  const ready = title.trim() && summary.trim() && what.trim();

  return (
    <div className="page narrow" style={{ maxWidth: 1080 }}>
      <button className="back-link" onClick={() => onNav('voice')}>← Back to Community Voice</button>
      <div className="page-head">
        <div className="eyebrow">Propose an idea</div>
        <h1 style={{ fontStyle: 'italic', fontWeight: 400 }}>What would help the hall serve the town?</h1>
        <p className="lede">A short, structured form. You can edit it once it&rsquo;s posted — and others can help you refine it.</p>
      </div>

      <div className="submit-grid">
        <div>
          <label className="field">
            <span className="lbl">A short name for the idea</span>
            <input value={title} onChange={e => setTitle(e.target.value)} placeholder="e.g. A weekly chess club for older neighbours" />
          </label>
          <label className="field">
            <span className="lbl">In one sentence</span>
            <input value={summary} onChange={e => setSummary(e.target.value)} placeholder="The one line you&rsquo;d say to someone over coffee." />
          </label>
          <label className="field">
            <span className="lbl">Theme</span>
            <select value={theme} onChange={e => setTheme(e.target.value)}>
              {THEMES.map(t => <option key={t} value={t}>{t}</option>)}
            </select>
          </label>
          <label className="field">
            <span className="lbl">What it would do</span>
            <textarea value={what} onChange={e => setWhat(e.target.value)} placeholder="A paragraph in your own words." />
          </label>
          <label className="field">
            <span className="lbl">Who it would serve</span>
            <textarea value={who} onChange={e => setWho(e.target.value)} placeholder="Be specific. Names of groups, ages, situations." />
          </label>
          <label className="field">
            <span className="lbl">What it would need</span>
            <textarea value={needs} onChange={e => setNeeds(e.target.value)} placeholder="People, time, equipment, money, room layout, anything." />
          </label>
          <div style={{ display: 'flex', gap: 12, marginTop: 24 }}>
            <button
              className="btn btn-primary"
              disabled={!ready}
              onClick={() => onSubmit({ title, summary, what, who, needs, theme })}
            >
              Post idea
            </button>
            <button className="btn btn-secondary" onClick={() => onNav('voice')}>Cancel</button>
          </div>
        </div>

        <aside className="hint-side">
          <h4>House posture</h4>
          <p style={{ marginTop: 4 }}>
            Write as if you&rsquo;re speaking to a friend who runs the hall. Don&rsquo;t pre-edit. Don&rsquo;t hedge.
          </p>
          <p>
            Half-formed is welcome. The point of this room is to let an idea grow before anyone has to decide on it.
          </p>
          <p style={{ marginTop: 14, fontSize: 13, paddingTop: 14, borderTop: '1px solid var(--olive-soft)', fontStyle: 'italic' }}>
            Your name will be visible to other members. You&rsquo;ll be set as the first owner so you can refine the idea over time. LEAF reads every idea posted here.
          </p>
        </aside>
      </div>
    </div>
  );
}

Object.assign(window, { SignIn, Welcome, CommunityVoice, IdeaDetail, Submit });
