/* ===== Shared ===== */
function PageShell({ firm, search, setSearch, nav, onMenu, onHome, onBack, crumbs, children }) {
  return (
    <div className={"page" + (firm.light ? " page--light" : "")} style={{ "--bg": firm.bg, "--deep": firm.deep, "--ink": firm.ink, "--accent": firm.accent }}>
      <TopBar search={search} setSearch={setSearch} tinted={true} inkColor={firm.ink} onMenu={onMenu} onHome={onHome} nav={nav} />
      <div className="page__body">
        <div className="pagenav">
          <Pill variant="tint" onClick={onBack}><span style={{ marginRight: 8 }}>←</span> Back</Pill>
          <Breadcrumbs crumbs={crumbs} />
        </div>
        {children}
      </div>
      <SiteFooter tinted={true} />
    </div>
  );
}

function SpecList({ rows }) {
  return (
    <dl className="spec">
      {rows.filter((r) => r && r.node != null && r.node !== "").map((r, i) => (
        <div className="spec__row" key={i}>
          <dt className="spec__label">{r.label}</dt>
          <dd className="spec__value">{r.node}</dd>
        </div>
      ))}
    </dl>
  );
}

function RelChip({ label, onClick, icon }) {
  return (
    <button className="relchip" onClick={onClick}>
      {icon && <span className="relchip__icon">{icon}</span>}
      <span>{label}</span>
    </button>
  );
}

function smoothTo(id) {
  const el = document.getElementById(id);
  if (!el) return;
  const y = el.getBoundingClientRect().top + window.scrollY - 24;
  window.scrollTo({ top: y, behavior: "smooth" });
}

/* Concise hover teaser for a fund tile — the fund's strategy, trimmed to fit. */
function fundTeaser(fd) {
  const s = (fd.strategy || "").trim();
  if (s.length <= 120) return s;
  return s.slice(0, 117).replace(/\s+\S*$/, "") + "…";
}

/* ===== YouTube embed (Acquired-style, above the written breakdown) =====
   Renders only when the record has a videoId (the YouTube ID, e.g. "eSZ4Xep1sJU"). */
function VideoEmbed({ videoId, title }) {
  if (!videoId) return null;
  return (
    <figure className="videoembed">
      <div className="videoembed__frame">
        <iframe
          src={"https://www.youtube-nocookie.com/embed/" + videoId}
          title={title || "Watch the episode"}
          loading="lazy"
          allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
          allowFullScreen
        ></iframe>
      </div>
      <figcaption className="videoembed__cap">Prefer to watch? The full story, narrated.</figcaption>
    </figure>
  );
}

/* ===== Long-form breakdown (lazy-loaded from breakdowns/<id>.md) ===== */
function BreakdownPanel({ firm }) {
  const [st, setSt] = React.useState({ loading: true, html: "", error: false });
  React.useEffect(() => {
    let alive = true;
    setSt({ loading: true, html: "", error: false });
    fetch("breakdowns/" + firm.id + ".md")
      .then((r) => { if (!r.ok) throw new Error("nf"); return r.text(); })
      .then((t) => { if (alive) setSt({ loading: false, html: window.mdToHtml(t), error: false }); })
      .catch(() => { if (alive) setSt({ loading: false, html: "", error: true }); });
    return () => { alive = false; };
  }, [firm.id]);

  if (st.loading) return <div className="breakdown__state">Loading the breakdown…</div>;
  if (st.error) return <div className="breakdown__state">The full breakdown for {firm.name} is being written — check back soon.</div>;
  return <article className="breakdown sec" dangerouslySetInnerHTML={{ __html: st.html }} />;
}

/* ===== Firm page ===== */
function FirmView({ firm, nav, search, setSearch }) {
  const funds = window.fundsForFirm(firm.id).sort((a, b) => (a.vintage || 0) - (b.vintage || 0));
  const people = window.peopleForFirm(firm.id);
  const more = window.FIRMS.filter((f) => f.id !== firm.id);
  const [tab, setTab] = React.useState("summary");
  React.useEffect(() => { setTab("summary"); }, [firm.id]);

  const goFunds = () => {
    setTab("summary");
    setTimeout(() => smoothTo("sec-funds"), 60);
  };

  const firmCrumbs = [{ label: "Home", onClick: nav.home }, { label: firm.name }];

  return (
    <PageShell firm={firm} search={search} setSearch={setSearch} nav={nav} onMenu={nav.menu} onHome={nav.home} onBack={nav.back} crumbs={firmCrumbs}>
      <section className="hero">
        <div className="hero__left">
          <h1 className="hero__title">{firm.name}</h1>
          <p className="hero__blurb">{firm.blurb}</p>
          <div className="hero__stats">
            {firm.stats.map((s, i) => (
              <div className="stat" key={i}>
                <span className="stat__k">{s.k}</span>
                <span className="stat__v">{s.v}</span>
              </div>
            ))}
          </div>
          <div className="hero__cta">
            {firm.breakdown && (
              <ArrowPill onClick={() => { setTab("breakdown"); setTimeout(() => smoothTo("sec-breakdown"), 80); }}>Read the breakdown</ArrowPill>
            )}
            <Pill variant="tint" onClick={goFunds}>Funds &amp; People ↓</Pill>
          </div>
        </div>
        <div className="hero__right">
          <figure className="herocard">
            <div className="herocard__photo" style={{ background: firm.deep }}>
              <span className="herocard__logo" style={{ color: firm.ink }}>{firm.name}</span>
              <image-slot id={"logo-" + firm.id} class="herocard__slot" shape="rounded" radius="3" fit="cover" src={firm.logoSrc || undefined} placeholder="Drop a photo"></image-slot>
            </div>
            <figcaption className="herocard__cap">{firm.teaser}</figcaption>
          </figure>
        </div>
      </section>

      <ResearchUpgrade compact={true} />

      {firm.breakdown && (
        <div className="firmtabs">
          <button className={"firmtab" + (tab === "summary" ? " is-active" : "")} onClick={() => setTab("summary")}>Summary</button>
          <button className={"firmtab" + (tab === "breakdown" ? " is-active" : "")} onClick={() => setTab("breakdown")}>The Breakdown</button>
        </div>
      )}

      {tab === "breakdown" && firm.breakdown ? (
        <React.Fragment>
          <div id="sec-breakdown" />
          <VideoEmbed videoId={firm.videoId} title={firm.name + " — The Vintage Project"} />
          <BreakdownPanel firm={firm} />
          <ResearchUpgrade />
          <section className="sec sec--more">
            <SectionHead n="✦" title="More firms" sub="Keep reading — every firm in the directory." />
            <div className="firmchips">
              {more.map((f) => <FirmChip key={f.id} firm={f} onClick={() => nav.firm(f.id)} />)}
            </div>
          </section>
        </React.Fragment>
      ) : (
      <React.Fragment>
      <section className="sec" id="sec-arch">
        <SectionHead n="01" title="Architecture Lessons" sub="The structural decisions behind the firm's returns." />
        {firm.lessonArtSrc && (
          <figure className="lessonart">
            <img src={firm.lessonArtSrc} alt={firm.name + " — the core lesson, visualized"} loading="lazy" />
          </figure>
        )}
        {(firm.foundingBet || firm.teaches) && (
          <div className="profile">
            {firm.foundingBet && (
              <div className="profile__block">
                <span className="profile__label">The Founding Bet</span>
                <p className="profile__text">{firm.foundingBet}</p>
              </div>
            )}
            {firm.teaches && (
              <div className="profile__block profile__block--accent">
                <span className="profile__label">What This Firm Uniquely Teaches</span>
                <p className="profile__text">{firm.teaches}</p>
              </div>
            )}
          </div>
        )}
        <div className="lessons">
          {firm.lessons.map((l, i) => (
            <article className="lesson" key={i}>
              <span className="lesson__num">{String(i + 1).padStart(2, "0")}</span>
              <h4 className="lesson__t">{l.t}</h4>
              <p className="lesson__b">{l.b}</p>
              {l.funds && l.funds.length > 0 && (
                <div className="lesson__srcs">
                  <span className="lesson__srclabel">From</span>
                  {l.funds.map((fid) => {
                    const fd = window.getFund(fid);
                    return fd ? <RelChip key={fid} label={fd.name} icon="▤" onClick={() => nav.fund(fid)} /> : null;
                  })}
                </div>
              )}
            </article>
          ))}
        </div>
        {firm.archTags && firm.archTags.length > 0 && (
          <div className="archtags">
            <span className="archtags__label">Lessons catalogued</span>
            <TagRow items={firm.archTags} />
          </div>
        )}
      </section>

      <InlineSubscribe tinted={true} />

      <section className="sec" id="sec-funds">
        <SectionHead n="02" title="Funds" sub="The story behind every vintage." />
        <DirectoryGrid>
          {funds.map((fd) => (
            <Tile key={fd.id} title={fd.name} tag={String(fd.vintage)} teaser={fundTeaser(fd)}
              bg={firm.bg} ink={firm.ink} accent={firm.accent} onClick={() => nav.fund(fd.id)} />
          ))}
        </DirectoryGrid>
      </section>

      <section className="sec" id="sec-people">
        <SectionHead n="03" title="People" sub="The investors who built the firm." />
        <DirectoryGrid>
          {people.map((p) => (
            <Tile key={p.id} variant="person" initials={initialsOf(p.name)} fullName={p.noPhoto ? p.name : null} title={p.name} tag={p.name}
              teaser={<React.Fragment><span className="tile__teaserrole">{p.role}</span><br />{p.tenure}</React.Fragment>}
              bg={p.noPhoto ? "#111111" : firm.bg} ink={p.noPhoto ? "#ffffff" : firm.ink} accent={firm.accent}
              logoId={p.noPhoto ? undefined : "headshot-" + p.id} src={p.noPhoto ? undefined : p.headshotSrc} onClick={() => nav.person(p.id)} />
          ))}
        </DirectoryGrid>
      </section>

      {firm.writing && firm.writing.length > 0 && (
        <section className="sec" id="sec-writing">
          <SectionHead n="04" title="Best writing" sub="The essays, talks, and letters that capture the firm's ethos." />
          <div className="writing">
            <ol className="writing__list">
              {firm.writing.map((w, i) => (
                <li className="writing__item" key={i}>
                  <span className="writing__year">{w.year}</span>
                  <div className="writing__meta">
                    {w.url ? (
                      <a className="writing__title writing__title--link" href={w.url} target="_blank" rel="noopener noreferrer">{w.title} <span className="writing__ext">↗</span></a>
                    ) : (
                      <span className="writing__title">{w.title}</span>
                    )}
                    <span className="writing__blurb">{w.by ? w.by + " — " : ""}{w.blurb}</span>
                  </div>
                </li>
              ))}
            </ol>
          </div>
        </section>
      )}

      <ResearchUpgrade />

      <section className="sec sec--more">
        <SectionHead n={firm.writing && firm.writing.length ? "05" : "04"} title="More firms" />
        <div className="firmchips">
          {more.map((f) => <FirmChip key={f.id} firm={f} onClick={() => nav.firm(f.id)} />)}
        </div>
      </section>
      </React.Fragment>
      )}
    </PageShell>
  );
}

function SectionHead({ n, title, sub }) {
  return (
    <div className="sechead">
      <span className="sechead__n">{n}</span>
      <div>
        <h2 className="sechead__title">{title}</h2>
        {sub && <p className="sechead__sub">{sub}</p>}
      </div>
    </div>
  );
}

/* ===== Fund prev / next navigator ===== */
function FundNav({ fund, nav }) {
  const allFunds = window.fundsForFirm(fund.firmId).sort((a, b) => (a.vintage || 0) - (b.vintage || 0));
  const idx = allFunds.findIndex((f) => f.id === fund.id);
  const prev = idx > 0 ? allFunds[idx - 1] : null;
  const next = idx < allFunds.length - 1 ? allFunds[idx + 1] : null;
  if (!prev && !next) return null;
  return (
    <div className="fundnav">
      {prev ? (
        <button className="fundnav__btn fundnav__btn--prev" onClick={() => nav.fund(prev.id)}>
          <span className="fundnav__arrow">←</span>
          <span className="fundnav__meta">
            <span className="fundnav__label">Previous fund</span>
            <span className="fundnav__name">{prev.name}</span>
          </span>
        </button>
      ) : <span />}
      {next ? (
        <button className="fundnav__btn fundnav__btn--next" onClick={() => nav.fund(next.id)}>
          <span className="fundnav__meta">
            <span className="fundnav__label">Next fund</span>
            <span className="fundnav__name">{next.name}</span>
          </span>
          <span className="fundnav__arrow">→</span>
        </button>
      ) : <span />}
    </div>
  );
}

/* ===== Fund page ===== */
function FundView({ fund, nav, search, setSearch }) {
  const firm = window.getFirm(fund.firmId);
  const people = (fund.peopleIds || []).map(window.getPerson).filter(Boolean);

  const rows = [
    { label: "Architecture Lessons", node: <TagRow items={fund.architectureLessons} /> },
    { label: "Firm", node: <RelChip label={firm.name} icon="▦" onClick={() => nav.firm(firm.id)} /> },
    { label: "Fund Size", node: <span className="spec__strong">{fund.fundSize}</span> },
    { label: "Vintage Year", node: <span className="spec__strong">{fund.vintage}</span> },
    { label: "People", node: people.length ? <div className="relchips">{people.map((p) => <RelChip key={p.id} label={p.name} icon="◷" onClick={() => nav.person(p.id)} />)}</div> : null },
    { label: "Structural Innovation", node: <TagRow items={fund.structuralInnovation} /> },
    { label: "Notable Investments", node: <p className="spec__prose">{fund.notable}</p> },
  ];

  const fundCrumbs = [
    { label: "Home", onClick: nav.home },
    { label: firm.name, onClick: () => nav.firm(firm.id) },
    { label: fund.name },
  ];

  return (
    <PageShell firm={firm} search={search} setSearch={setSearch} nav={nav} onMenu={nav.menu} onHome={nav.home} onBack={nav.back} crumbs={fundCrumbs}>
      <div className="record">
        {firm.coverSrc ? (
          <image-slot id={"fund-" + fund.id} class="record__photo" shape="rounded" radius="8" fit="cover" src={fund.coverSrc || firm.coverSrc} placeholder="Drop a defining photo for this fund"></image-slot>
        ) : (
          <image-slot id={"fund-" + fund.id} class="record__photo record__photo--brand" shape="rounded" radius="8" fit="contain" src={firm.logoSrc || undefined} placeholder="Drop a defining photo for this fund"></image-slot>
        )}
        <span className="record__kicker">Fund · {firm.name}</span>
        <h1 className="record__title">{fund.name}</h1>
        <ResearchUpgrade compact={true} />
        <SpecList rows={rows} />

        <InlineSubscribe tinted={true} />

        <div className="prose">
          <h3 className="prose__h">Strategy at the Time</h3>
          <p>{fund.strategy}</p>
          <h3 className="prose__h">Returns / Outcome</h3>
          <p>{fund.returns}</p>
          {!fund.firstFund && (
            <React.Fragment>
              <h3 className="prose__h">What Changed from the Prior Fund</h3>
              <p>{fund.whatChanged}</p>
            </React.Fragment>
          )}
        </div>
        <FundLongform fund={fund} nav={nav} />
      </div>
    </PageShell>
  );
}

/* Full Notion page body for a fund, lazy-loaded from breakdowns/funds/<id>.md.
   The Sources block is split out and rendered *below* the prev/next navigator,
   so "Next fund" always sits at the bottom, just above Sources. */
function FundLongform({ fund, nav }) {
  const [st, setSt] = React.useState({ body: "", sources: "" });
  React.useEffect(() => {
    let alive = true;
    setSt({ body: "", sources: "" });
    fetch("breakdowns/funds/" + fund.id + ".md")
      .then((r) => (r.ok ? r.text() : null))
      .then((t) => { if (alive && t) setSt(window.mdSplitSources(t)); })
      .catch(() => {});
    return () => { alive = false; };
  }, [fund.id]);
  return (
    <React.Fragment>
      <VideoEmbed videoId={fund.videoId} title={fund.name + " — The Vintage Project"} />
      {st.body && (
        <div className="fundfull">
          <span className="fundfull__label">The full record</span>
          <article className="breakdown breakdown--fund" dangerouslySetInnerHTML={{ __html: st.body }} />
        </div>
      )}
      <FundNav fund={fund} nav={nav} />
      {st.sources && (
        <article className="breakdown breakdown--fund fundfull__sources" dangerouslySetInnerHTML={{ __html: st.sources }} />
      )}
      <ResearchUpgrade />
    </React.Fragment>
  );
}

/* Full Notion page body for a person, lazy-loaded from breakdowns/people/<id>.md */
function PersonBreakdown({ person }) {
  const [html, setHtml] = React.useState(null);
  React.useEffect(() => {
    let alive = true;
    setHtml(null);
    fetch("breakdowns/people/" + person.id + ".md")
      .then((r) => (r.ok ? r.text() : null))
      .then((t) => { if (alive && t) setHtml(window.mdToHtml(t)); })
      .catch(() => {});
    return () => { alive = false; };
  }, [person.id]);
  if (!html) return null;
  return (
    <div className="fundfull">
      <span className="fundfull__label">The full profile</span>
      <article className="breakdown breakdown--fund" dangerouslySetInnerHTML={{ __html: html }} />
    </div>
  );
}

/* ===== Person page ===== */
function PersonView({ person, nav, search, setSearch }) {
  const firm = window.getFirm(person.firmId);
  const funds = (person.fundsPresided || []).map(window.getFund).filter(Boolean);

  const rows = [
    { label: "Firm", node: <RelChip label={firm.name} icon="▦" onClick={() => nav.firm(firm.id)} /> },
    { label: "Funds Presided Over", node: <div className="relchips">{funds.map((fd) => <RelChip key={fd.id} label={fd.name} icon="▤" onClick={() => nav.fund(fd.id)} />)}</div> },
    { label: "Role", node: <span className="spec__strong">{person.role}</span> },
    { label: "Generation", node: <TagRow items={[person.generation]} /> },
    { label: "Tenure", node: person.tenure },
    { label: "Known For Thinking", node: <TagRow items={person.knownFor} /> },
    { label: "Architecture Lessons", node: <TagRow items={person.architectureLessons} /> },
  ];

  const personCrumbs = [
    { label: "Home", onClick: nav.home },
    { label: firm.name, onClick: () => nav.firm(firm.id) },
    { label: person.name },
  ];

  return (
    <PageShell firm={firm} search={search} setSearch={setSearch} nav={nav} onMenu={nav.menu} onHome={nav.home} onBack={nav.back} crumbs={personCrumbs}>
      <div className="record">
        <div className="record__head">
          {person.noPhoto
            ? <div className="record__portrait record__portrait--named">{person.name}</div>
            : <image-slot id={"headshot-" + person.id} class="record__portrait" shape="rounded" radius="10" fit="cover" src={person.headshotSrc || undefined} placeholder="Drop a portrait"></image-slot>}
          <div className="record__headmeta">
            <span className="record__kicker">Person · {firm.name}</span>
            <h1 className="record__title">{person.name}</h1>
          </div>
        </div>
        <ResearchUpgrade compact={true} />
        <SpecList rows={rows} />

        <InlineSubscribe tinted={true} />

        <div className="prose prose--bio">
          <h3 className="prose__h">Biography</h3>
          <p>{person.bio}</p>
        </div>

        <PersonBreakdown person={person} />

        <div className="writing">
          <SectionHead n="✶" title="Notable Writing" sub={person.writing.length ? null : undefined} />
          {person.writing.length ? (
            <ol className="writing__list">
              {person.writing.map((w, i) => (
                <li className="writing__item" key={i}>
                  <span className="writing__year">{w.year}</span>
                  <div className="writing__meta">
                    {w.url ? (
                      <a className="writing__title writing__title--link" href={w.url} target="_blank" rel="noopener noreferrer">{w.title} <span className="writing__ext">↗</span></a>
                    ) : (
                      <span className="writing__title">{w.title}</span>
                    )}
                    <span className="writing__blurb">{w.blurb}</span>
                  </div>
                </li>
              ))}
            </ol>
          ) : (
            <p className="writing__empty">No published writing on file — this investor let the portfolio do the talking.</p>
          )}
        </div>

        <ResearchUpgrade />

        <OtherInvestors firm={firm} person={person} nav={nav} />
      </div>
    </PageShell>
  );
}

/* Headshot cards for the rest of the firm's investors — keeps readers moving. */
function OtherInvestors({ firm, person, nav }) {
  const others = window.peopleForFirm(firm.id).filter((p) => p.id !== person.id);
  if (!others.length) return null;
  return (
    <section className="others">
      <SectionHead n="✦" title={"Other " + firm.name + " investors"} />
      <div className="others__row">
        {others.map((p) => (
          <button className="pcard" key={p.id} onClick={() => nav.person(p.id)}>
            <span className={"pcard__portrait" + (p.noPhoto ? " pcard__portrait--named" : "")}>
              {p.headshotSrc
                ? <img src={p.headshotSrc} alt={p.name} />
                : (p.noPhoto
                  ? <span className="pcard__nameart">{p.name}</span>
                  : <span className="pcard__initials">{initialsOf(p.name)}</span>)}
            </span>
            <span className="pcard__name">{p.name}</span>
            <span className="pcard__teaser">{p.role}</span>
          </button>
        ))}
      </div>
    </section>
  );
}

Object.assign(window, { PageShell, SpecList, RelChip, FirmView, FundView, PersonView, SectionHead, smoothTo });
