const D2 = window.PERROTTI_DATA;

const TWEAKS_DEFAULTS_V2 = /*EDITMODE-BEGIN*/{
  "theme": "light",
  "accent": "green"
}/*EDITMODE-END*/;

function AppV2() {
  const { useState, useEffect } = React;
  const [tweaks, setTweak] = useTweaks(TWEAKS_DEFAULTS_V2);
  const [section, setSection] = useState("about");
  const [editorOpen, setEditorOpen] = useState(false);

  useEffect(() => {
    document.documentElement.setAttribute("data-theme", tweaks.theme);
    document.documentElement.setAttribute("data-accent", tweaks.accent);
  }, [tweaks]);

  // Hidden editor: enabled when URL hash contains editor=Piponero10,
  // or when localStorage already has the unlock flag from a previous visit.
  useEffect(() => {
    const EDITOR_KEY = "Piponero10";
    const checkUnlock = () => {
      const m = (location.hash || "").match(/editor=([^&]+)/);
      if (m && decodeURIComponent(m[1]) === EDITOR_KEY) {
        try { localStorage.setItem("dp-editor-unlocked", "1"); } catch {}
        // strip the secret from the URL for hygiene; keep section if any
        const cleanHash = (location.hash || "").replace(/[#&]?editor=[^&]+/, "").replace(/^&/, "#");
        history.replaceState(null, "", location.pathname + (cleanHash || ""));
        setEditorOpen(true);
        return;
      }
      try {
        if (localStorage.getItem("dp-editor-unlocked") === "1") setEditorOpen(true);
      } catch {}
    };
    checkUnlock();
  }, []);

  useEffect(() => {
    const apply = () => {
      const h = (location.hash || "#about").replace("#", "").split("&")[0];
      if (["about", "publications", "opeds", "resume"].includes(h)) setSection(h);
    };
    apply();
    window.addEventListener("hashchange", apply);
    return () => window.removeEventListener("hashchange", apply);
  }, []);

  const go = (id) => { location.hash = "#" + id; setSection(id); window.scrollTo({ top: 0, behavior: "smooth" }); };

  return (
    <>
      <Masthead />
      <Nav section={section} go={go} />
      <main>
        {section === "about" && <About go={go} />}
        {section === "publications" && <Publications />}
        {section === "opeds" && <OpEds editorEnabled={editorOpen} onLockEditor={() => { try { localStorage.removeItem("dp-editor-unlocked"); } catch {} setEditorOpen(false); }} />}
        {section === "resume" && <Resume />}
      </main>
      <Footer go={go} />
      <TweaksPanel title="Tweaks">
        <TweakSection label="Mode">
          <TweakRadio label="Theme" value={tweaks.theme}
            onChange={v => setTweak("theme", v)}
            options={[{ value: "light", label: "Light" }, { value: "dark", label: "Dark" }]} />
        </TweakSection>
        <TweakSection label="Terminal accent">
          <TweakRadio label="Color" value={tweaks.accent}
            onChange={v => setTweak("accent", v)}
            options={[
              { value: "green", label: "Green" },
              { value: "amber", label: "Amber" },
              { value: "cyan", label: "Cyan" },
              { value: "red", label: "Red" }
            ]} />
        </TweakSection>
      </TweaksPanel>
    </>
  );
}

/* ——————— MASTHEAD ——————— */
function Masthead() {
  return (
    <header className="masthead">
      <div className="shell masthead-grid">
        <div className="logo">
          <span className="logo-mark">[ DP ]</span>
          <span className="logo-name">danielperrotti.com</span>
        </div>
        <div className="masthead-meta">
          <span><strong>Daniel E. Perrotti</strong></span>
          <span>Economist · Trade · Finance · Infrastructure · Development</span>
        </div>

      </div>
    </header>
  );
}

/* ——————— NAV ——————— */
function Nav({ section, go }) {
  const items = [
    { id: "about", num: "01", label: "About" },
    { id: "publications", num: "02", label: "Publications" },
    { id: "opeds", num: "03", label: "Op-Eds" },
    { id: "resume", num: "04", label: "Resume" }
  ];
  return (
    <nav className="nav">
      <div className="shell" style={{display:"flex", width:"100%", padding:0}}>
        <div style={{display:"flex"}}>
          {items.map(it => (
            <button key={it.id} aria-current={section === it.id} onClick={() => go(it.id)}>
              <span className="nav-num">{it.num}</span>{it.label}
            </button>
          ))}
        </div>
        <div className="nav-spacer"></div>
        <button className="nav-action" onClick={() => location.href = "mailto:daniel@danielperrotti.com"}>
          <span style={{color:"var(--accent)"}}>›</span> Contact
        </button>
      </div>
    </nav>
  );
}

/* ——————— ABOUT ——————— */
function About({ go }) {
  const { useMemo } = React;
  const p = D2.profile;
  const topicCounts = useMemo(() => {
    const counts = {};
    D2.topics.forEach(t => counts[t.id] = 0);
    D2.publications.forEach(pub => pub.topics.forEach(t => { if (counts[t] != null) counts[t]++; }));
    return counts;
  }, []);

  return (
    <>
      <section className="hero">
        <div className="shell">
          <div className="hero-row1">
            <div className="hero-tag">
              <span className="live">LIVE</span><br/>
              Index of Research Output
            </div>
            <h1 className="hero-headline">
              An economist's record of work on <span className="em">infrastructure,</span> trade and the long arc of Latin American development.
            </h1>
            <div className="hero-stamp">
              Maintained since
              <strong>2011 — present</strong>
            </div>
          </div>
        </div>
        <div className="shell">
          <div className="kpi-strip">
            <div className="kpi">
              <div className="kpi-lab">Publications</div>
              <div className="kpi-val">50<span className="delta">+</span></div>
              <div className="kpi-sub">Across 7 topics</div>
            </div>
            <div className="kpi">
              <div className="kpi-lab">Affiliation</div>
              <div className="kpi-val" style={{fontSize:"15px", letterSpacing:0}}>UN ECLAC</div>
              <div className="kpi-sub">Washington, D.C.</div>
            </div>
            <div className="kpi">
              <div className="kpi-lab">Teaching</div>
              <div className="kpi-val" style={{fontSize:"15px", letterSpacing:0}}>UBA</div>
              <div className="kpi-sub">Assoc. Professor (on leave)</div>
            </div>
            <div className="kpi">
              <div className="kpi-lab">Latest</div>
              <div className="kpi-val" style={{fontSize:"15px", letterSpacing:0}}>2026</div>
              <div className="kpi-sub">5 forthcoming</div>
            </div>
          </div>
        </div>
      </section>

      <div className="shell">
        <div className="about-body">
          <h2><span className="num">§01</span>BIO</h2>
          <div className="about-prose">
            {p.bio_long.map((para, i) => <p key={i}>{para}</p>)}
          </div>
          <div>
            <div className="about-side">
              <h3>// Research areas</h3>
              <ul className="topic-list">
                {D2.topics.map(t => (
                  <li key={t.id} onClick={() => go("publications")}>
                    <span>{t.label}</span>
                    <span className="topic-count">{String(topicCounts[t.id]).padStart(2, "0")}</span>
                  </li>
                ))}
              </ul>
            </div>
            <div className="about-side">
              <h3>// Profiles</h3>
              <ul className="topic-list">
                {p.socials.map(s => (
                  <li key={s.label} onClick={() => window.open(s.href, "_blank")}>
                    <span>{s.label}</span>
                    <span className="topic-count">↗</span>
                  </li>
                ))}
              </ul>
            </div>
          </div>
        </div>
      </div>
    </>
  );
}

/* ——————— PUBLICATIONS ——————— */
function Publications() {
  const { useState, useMemo } = React;
  const [topic, setTopic] = useState("all");
  const [type, setType] = useState("all");
  const [q, setQ] = useState("");
  const [openIdx, setOpenIdx] = useState(null);

  const filtered = useMemo(() => {
    const ql = q.trim().toLowerCase();
    return D2.publications
      .filter(p => topic === "all" || p.topics.includes(topic))
      .filter(p => type === "all" || p.type === type)
      .filter(p => !ql
        || p.title.toLowerCase().includes(ql)
        || (p.venue || "").toLowerCase().includes(ql)
        || p.authors.toLowerCase().includes(ql)
        || (p.coauthors || "").toLowerCase().includes(ql)
        || (p.abstract || "").toLowerCase().includes(ql));
  }, [topic, type, q]);

  // Reset open row when filters change
  React.useEffect(() => { setOpenIdx(null); }, [topic, type, q]);

  const typeLabel = (id) => D2.types.find(t => t.id === id)?.label || id;
  const topicLabel = (id) => D2.topics.find(t => t.id === id)?.label || id;

  // Build a stable identity for each row so open-state survives filtering
  const rowKey = (p) => `${p.year}-${p.type}-${p.title}`;

  return (
    <section className="section">
      <div className="shell">
        <div className="section-head">
          <div className="section-id">
            <strong>§ 02 / PUBLICATIONS</strong>
          </div>
          <h2 className="section-title">Publications</h2>
          <div className="section-stat"><strong>{filtered.length}</strong> / {D2.publications.length} entries</div>
        </div>

        <div className="filters">
          <h4>// Filter</h4>
          <div>
            <div className="search">
              <span className="search-prompt">$</span>
              <input
                type="text"
                placeholder="Search by title, author or venue…"
                value={q}
                onChange={e => setQ(e.target.value)}
              />
            </div>

            <div className="filter-row">
              <button className="chip chip-accent" aria-pressed={topic === "all"} onClick={() => setTopic("all")}>ALL TOPICS</button>
              {D2.topics.map(t => (
                <button key={t.id} className="chip chip-accent" aria-pressed={topic === t.id} onClick={() => setTopic(t.id)}>{t.label}</button>
              ))}
            </div>
            <div className="filter-row">
              <button className="chip" aria-pressed={type === "all"} onClick={() => setType("all")}>ALL TYPES</button>
              {D2.types.map(t => (
                <button key={t.id} className="chip" aria-pressed={type === t.id} onClick={() => setType(t.id)}>{t.label}</button>
              ))}
            </div>
          </div>
        </div>

        <table className="pubs-table">
          <thead>
            <tr>
              <th className="num-col">#</th>
              <th className="year-col">Year</th>
              <th className="type-col">Type</th>
              <th>Title / Authors / Venue</th>
            </tr>
          </thead>
          <tbody>
            {filtered.map((p, i) => {
              const k = rowKey(p);
              const isOpen = openIdx === k;
              const hasAbstract = !!p.abstract;
              return (
                <React.Fragment key={k}>
                  <tr
                    className={`pub-row${isOpen ? " is-open" : ""}${hasAbstract ? " has-abstract" : ""}`}
                    onClick={() => hasAbstract && setOpenIdx(isOpen ? null : k)}
                  >
                    <td className="num">{String(filtered.length - i).padStart(2, "0")}</td>
                    <td className="year">{p.forthcoming ? "—" : p.year}</td>
                    <td className="type">{typeLabel(p.type)}</td>
                    <td className="title">
                      <span className="title-row">
                        {p.link
                          ? <a href={p.link} target="_blank" rel="noopener" onClick={(e) => e.stopPropagation()} style={{color:"inherit", borderBottom:"1px dotted var(--ink-faint)"}}>{p.title}</a>
                          : p.title}
                        {p.forthcoming && <span className="forthcoming-tag">Forthcoming</span>}
                        {hasAbstract && (
                          <span className="abstract-toggle" aria-hidden="true">{isOpen ? "[ −  hide abstract ]" : "[ +  read abstract ]"}</span>
                        )}
                      </span>
                      <span className="authors">{p.authors}</span>
                      {p.venue && <span className="venue">In: {p.venue}</span>}
                      {p.link && (
                        <span className="pub-link-line">
                          <a
                            href={p.link}
                            target="_blank"
                            rel="noopener"
                            onClick={(e) => e.stopPropagation()}
                            className="pub-link"
                          >
                            ↗ {p.link.replace(/^https?:\/\//, '').replace(/\/.*$/, '')}
                          </a>
                        </span>
                      )}
                    </td>
                  </tr>
                  {isOpen && hasAbstract && (
                    <tr className="pub-abstract-row">
                      <td></td>
                      <td colSpan="3">
                        <div className="pub-abstract">
                          <div className="abstract-label">// Abstract</div>
                          <p>{p.abstract}</p>
                          {p.link && (
                            <a className="abstract-link" href={p.link} target="_blank" rel="noopener" onClick={(e) => e.stopPropagation()}>
                              Read full text ↗
                            </a>
                          )}
                        </div>
                      </td>
                    </tr>
                  )}
                </React.Fragment>
              );
            })}
            {filtered.length === 0 && (
              <tr><td colSpan="5" className="empty-row">No matches. Try broadening the filters.</td></tr>
            )}
          </tbody>
        </table>
      </div>
    </section>
  );
}

/* ——————— OP-EDS ——————— */
function OpEds({ editorEnabled, onLockEditor }) {
  const { useState, useMemo } = React;
  const [openSlug, setOpenSlug] = useState(null);
  const [lang, setLang] = useState("all");
  const [showEditor, setShowEditor] = useState(false);

  const all = D2.opeds || [];
  const filtered = useMemo(() => all.filter(o => lang === "all" || o.lang === lang), [all, lang]);
  const open = openSlug ? all.find(o => o.slug === openSlug) : null;

  const fmtDate = (s) => {
    if (!s) return "";
    const [y, m, d] = s.split("-");
    const months = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
    return `${months[parseInt(m,10)-1] || m} ${parseInt(d,10) || ""}, ${y}`;
  };

  return (
    <section className="section">
      <div className="shell">
        <div className="section-head">
          <div className="section-id">
            <strong>§ 03 / OP-EDS</strong>
            Personal essays
          </div>
          <h2 className="section-title">Op-Eds &amp; commentary</h2>
          <div className="section-stat"><strong>{filtered.length}</strong> / {all.length} entries</div>
        </div>

        <div className="oped-disclaimer">
          <div className="oped-disclaimer-tag">// Disclaimer</div>
          <p>
            The texts in this section are <strong>personal opinion pieces</strong> by Daniel E. Perrotti.
            They do <strong>not represent the position</strong> of UN ECLAC, the University of Buenos Aires,
            or any other institution to which the author is or has been affiliated. They are published here
            for the record of public debate, not as institutional commentary.
          </p>
        </div>

        {!open && (
          <>
            <div className="filters" style={{marginTop: "20px"}}>
              <h4>// Filter</h4>
              <div>
                <div className="filter-row">
                  <button className="chip chip-accent" aria-pressed={lang === "all"} onClick={() => setLang("all")}>ALL LANGUAGES</button>
                  <button className="chip chip-accent" aria-pressed={lang === "es"} onClick={() => setLang("es")}>Español</button>
                  <button className="chip chip-accent" aria-pressed={lang === "en"} onClick={() => setLang("en")}>English</button>
                </div>
              </div>
            </div>

            <ul className="oped-list">
              {filtered.map((o) => (
                <li key={o.slug} className="oped-item" onClick={() => setOpenSlug(o.slug)}>
                  <div className="oped-meta">
                    <span className="oped-date">{fmtDate(o.date)}</span>
                    <span className="oped-lang">{o.lang === "es" ? "Español" : "English"}</span>
                  </div>
                  <h3 className="oped-title">{o.title}</h3>
                  {o.dek && <p className="oped-dek">{o.dek}</p>}
                  <span className="oped-cta">Read essay →</span>
                </li>
              ))}
              {filtered.length === 0 && (
                <li className="oped-empty">No essays in this language yet.</li>
              )}
            </ul>
          </>
        )}

        {open && (
          <article className="oped-reader">
            <button className="oped-back" onClick={() => setOpenSlug(null)}>← Back to all op-eds</button>
            <div className="oped-reader-meta">
              <span>{fmtDate(open.date)}</span>
              <span>·</span>
              <span>{open.lang === "es" ? "Español" : "English"}</span>
            </div>
            <h1 className="oped-reader-title">{open.title}</h1>
            {open.dek && <p className="oped-reader-dek">{open.dek}</p>}
            <div className="oped-reader-body">
              {(open.body || "").split(/\n{2,}/).map((para, i) => (
                <p key={i}>{para.split('\n').map((ln, j, arr) => (
                  <React.Fragment key={j}>{renderInline(ln)}{j < arr.length - 1 ? <br/> : null}</React.Fragment>
                ))}</p>
              ))}
            </div>
          </article>
        )}



        {editorEnabled && (
          <div className="oped-editor-bar">
            <button className="btn ghost" onClick={() => setShowEditor(s => !s)}>
              {showEditor ? "Hide editor" : "[ + Draft new op-ed ]"}
            </button>
            <button className="oped-lock" onClick={onLockEditor}>Lock editor</button>
          </div>
        )}
        {editorEnabled && showEditor && <OpEdEditor />}
      </div>
    </section>
  );
}

// Minimal italics support: *foo* -> <em>foo</em>
function renderInline(text) {
  const parts = [];
  let rest = text;
  let key = 0;
  const re = /\*([^*]+)\*/g;
  let last = 0, m;
  while ((m = re.exec(text)) !== null) {
    if (m.index > last) parts.push(text.slice(last, m.index));
    parts.push(<em key={key++}>{m[1]}</em>);
    last = m.index + m[0].length;
  }
  if (last < text.length) parts.push(text.slice(last));
  return parts.length ? parts : text;
}

/* ——————— OP-ED HIDDEN EDITOR ——————— */
function OpEdEditor() {
  const { useState, useMemo } = React;
  const today = new Date().toISOString().slice(0, 10);
  const [date, setDate] = useState(today);
  const [lang, setLang] = useState("es");
  const [title, setTitle] = useState("");
  const [dek, setDek] = useState("");
  const [body, setBody] = useState("");
  const [copied, setCopied] = useState("");

  const slug = useMemo(() => {
    const base = (title || "untitled")
      .toLowerCase()
      .normalize("NFD").replace(/[\u0300-\u036f]/g, "")
      .replace(/[^a-z0-9]+/g, "-")
      .replace(/^-+|-+$/g, "")
      .slice(0, 60);
    const yyMm = (date || today).slice(0, 7);
    return `${yyMm}-${base}`;
  }, [title, date]);

  const escapeYaml = (s) => {
    if (!s) return "";
    if (/[:#&*!|>'"%@`\n]/.test(s) || s.startsWith(" ") || s.endsWith(" ")) {
      return JSON.stringify(s);
    }
    return s;
  };
  const markdown = `---
date: ${date}
lang: ${lang}
title: ${escapeYaml(title)}
dek: ${escapeYaml(dek)}
---

${body.trim()}
`;
  const indexEntry = JSON.stringify({ slug, date, lang, title, dek }, null, 2) + ",";

  const copy = async (text, label) => {
    try {
      await navigator.clipboard.writeText(text);
      setCopied(label);
      setTimeout(() => setCopied(""), 2000);
    } catch (e) {
      setCopied("copy failed");
    }
  };

  return (
    <div className="oped-editor">
      <div className="oped-editor-head">
        <h3>// Draft editor <span>(local — nothing is published until you commit the files)</span></h3>
      </div>
      <div className="oped-editor-grid">
        <label>
          <span>Date</span>
          <input type="date" value={date} onChange={e => setDate(e.target.value)} />
        </label>
        <label>
          <span>Language</span>
          <select value={lang} onChange={e => setLang(e.target.value)}>
            <option value="es">Español</option>
            <option value="en">English</option>
          </select>
        </label>
        <label className="full">
          <span>Title</span>
          <input type="text" value={title} onChange={e => setTitle(e.target.value)} placeholder="Title of the op-ed" />
        </label>
        <label className="full">
          <span>Dek (1-2 line summary)</span>
          <input type="text" value={dek} onChange={e => setDek(e.target.value)} placeholder="One-sentence summary that appears in the list" />
        </label>
        <label className="full">
          <span>Body (Markdown — separate paragraphs with blank lines, *italic* with asterisks)</span>
          <textarea rows={14} value={body} onChange={e => setBody(e.target.value)} placeholder="Write the essay here…" />
        </label>
        <div className="full oped-editor-slug">
          <span>Filename</span>
          <code>op-eds/{slug}.md</code>
        </div>
      </div>

      <div className="oped-editor-output">
        <div className="oped-editor-block">
          <div className="oped-editor-block-head">
            <h4>// {slug}.md</h4>
            <button className="btn-mini" onClick={() => copy(markdown, "markdown")}>
              {copied === "markdown" ? "✓ copied" : "Copy"}
            </button>
          </div>
          <pre>{markdown}</pre>
        </div>
        <div className="oped-editor-block">
          <div className="oped-editor-block-head">
            <h4>// add this entry to op-eds/index.json</h4>
            <button className="btn-mini" onClick={() => copy(indexEntry, "json")}>
              {copied === "json" ? "✓ copied" : "Copy"}
            </button>
          </div>
          <pre>{indexEntry}</pre>
        </div>
      </div>

      <div className="oped-editor-help">
        <strong>To publish:</strong>
        1) Save the markdown block as <code>op-eds/{slug}.md</code> in the repo. ·
        2) Add the JSON entry to the start of the array in <code>op-eds/index.json</code>. ·
        3) Commit + push. Cloudflare Pages rebuilds.
      </div>
    </div>
  );
}

/* ——————— RESUME ——————— */
function Resume() {
  const p = D2.profile;
  return (
    <section className="section">
      <div className="shell">
        <div className="section-head">
          <div className="section-id">
            <strong>§ 04 / CV</strong>
            Resume
          </div>
          <h2 className="section-title">Curriculum vitæ</h2>
          <div className="section-stat">Updated <strong>2026</strong></div>
        </div>

        <div className="cv-grid">
          <div></div>
          <div>
            <div className="cv-block">
              <h4>// Experience</h4>
              {D2.experience.map((e, i) => (
                <div key={i} className="cv-row">
                  <span className="cv-period">{e.period}</span>
                  <div>
                    <h3 className="cv-role">{e.role}</h3>
                    <p className="cv-org">{e.org}<span className="loc">{e.location}</span></p>
                    <p className="cv-note">{e.note}</p>
                  </div>
                </div>
              ))}
            </div>

            <div className="cv-block">
              <h4>// Education</h4>
              {D2.education.map((e, i) => (
                <div key={i} className="cv-row">
                  <span className="cv-period">{e.period}</span>
                  <div>
                    <h3 className="cv-role">{e.school}</h3>
                    <p className="cv-org"><span className="loc">{e.location}</span></p>
                    {e.note && <p className="cv-note">{e.note}</p>}
                  </div>
                </div>
              ))}
            </div>

            <div className="cv-block">
              <h4>// Peer reviewer</h4>
              {D2.peer_reviewer.map((j, i) => (
                <div key={i} className="cv-row" style={{gridTemplateColumns:"1fr"}}>
                  <span className="cv-org">{j}</span>
                </div>
              ))}
            </div>

            <div className="cv-block">
              <h4>// Selected presentations</h4>
              {D2.presentations.map((pres, i) => (
                <div key={i} className="cv-row">
                  <span className="cv-period">{pres.year}</span>
                  <div>
                    <p className="cv-note" style={{fontStyle:"normal", color:"var(--ink)", marginBottom:"2px"}}>{pres.title}</p>
                    <p className="cv-org">{pres.venue}{pres.location && <span className="loc">{pres.location}</span>}</p>
                  </div>
                </div>
              ))}
            </div>
          </div>

          <aside>
            <div className="cv-side">
              <div className="cv-side-row">
                <span className="lab">Name</span>
                <span className="val">{p.name}</span>
              </div>
              <div className="cv-side-row">
                <span className="lab">Role</span>
                <span className="val">{p.title}</span>
              </div>
              <div className="cv-side-row">
                <span className="lab">Org</span>
                <span className="val">UN ECLAC</span>
              </div>
              <div className="cv-side-row">
                <span className="lab">Loc</span>
                <span className="val">{p.location}</span>
              </div>
              <div className="cv-side-row">
                <span className="lab">Email</span>
                <span className="val"><a href={`mailto:${p.email}`}>{p.email}</a></span>
              </div>
              <div className="cv-side-row">
                <span className="lab">Languages</span>
                <span className="val">{D2.languages.map(l => `${l.lang} (${l.level})`).join(" · ")}</span>
              </div>
            </div>
            <div className="cv-cta">
              <button className="btn" onClick={(e) => e.preventDefault()}>
                CV.PDF <span>↓</span>
              </button>
              <button className="btn ghost" onClick={() => location.href = `mailto:${p.email}`}>
                Email <span>→</span>
              </button>
            </div>
          </aside>
        </div>
      </div>
    </section>
  );
}

/* ——————— FOOTER ——————— */
function Footer({ go }) {
  return (
    <footer className="shell">
      <div className="foot">

        <div className="foot-col">
          <h6>// Sections</h6>
          <a href="#about" onClick={(e) => { e.preventDefault(); go("about"); }}>01 · About</a>
          <a href="#publications" onClick={(e) => { e.preventDefault(); go("publications"); }}>02 · Publications</a>
          <a href="#opeds" onClick={(e) => { e.preventDefault(); go("opeds"); }}>03 · Op-Eds</a>
          <a href="#resume" onClick={(e) => { e.preventDefault(); go("resume"); }}>04 · Resume</a>
        </div>
        <div className="foot-col">
          <h6>// Elsewhere</h6>
          {D2.profile.socials.map(s => (
            <a key={s.label} href={s.href} target="_blank" rel="noopener">{s.label} ↗</a>
          ))}
        </div>
      </div>
      <div className="shell foot-bottom">
        <span>© {new Date().getFullYear()} D. Perrotti</span>
        <span>Opinions are the author's own — not those of affiliated institutions.</span>
      </div>
    </footer>
  );
}

Promise.all([
  window.loadPublications().catch(e => { console.warn('CSV load failed, using empty list:', e); }),
  window.loadOpEds().catch(e => { console.warn('Op-eds load failed, using empty list:', e); })
]).finally(() => {
  ReactDOM.createRoot(document.getElementById("root")).render(<AppV2 />);
});
