/* Folclore — LP Data Room (pre-launch family office room) */

const { useState, useEffect, useMemo, useCallback, useRef } = React;

const DR_SECTION_IDS = [
  "opportunity", "fund-overview", "verticals", "cases", "scenarios", "markets",
  "returns", "models", "firm", "articles", "documents", "onboarding",
  "strategy", "return-model", "fund-pacing", "media", "questions",
];

const FUND_PACING_VIEWS = ["portfolio", "j-curve", "sensitivity", "reading"];

const SECTION_ALIASES = {
  overview: "opportunity",
  team: "firm",
  pipeline: "scenarios",
  library: "articles",
};

const CORE_VERTICAL_IDS = ["fashion", "leather-goods", "swimwear", "beauty", "jewelry", "spirits-and-wine"];
const SECONDARY_VERTICAL_IDS = [
  "home-goods",
  "eyewear",
  "hospitality-and-travel",
  "aviation-and-yachting",
  "automobiles",
  "real-estate",
  "gastronomy-and-fine-dining",
  "selective-retailing",
  "watches",
];

/* Appointment booking. NDA is an in-app signature block (see NdaFormModal). */
const APPOINTMENT_URL = "https://calendar.google.com/calendar/appointments/schedules/AcZssZ2vLm41kFm_SBQqopirhHrL0ZTbEO7tDj0umKGFq37HKvHTHwxxHB67AWQGx6JeH_Aez3tbCCTc";
const NDA_COPY_URL = "https://drive.google.com/file/d/1B_IUBmEFoiwMWcluPqlvrY3dUsx2KtuW/view?usp=sharing";

function nyCalendarDate() {
  return new Intl.DateTimeFormat("en-CA", {
    timeZone: "America/New_York",
    year: "numeric",
    month: "2-digit",
    day: "2-digit",
  }).format(new Date());
}

function emptyScheduleRow() {
  return { name: "", organization_role: "", email: "" };
}

const SUPPORT_EMAIL = "support@folclore.capital";
const MOBILE_NOTICE_KEY = "folclore_dr_mobile_notice";

/* Phones only. An iPad — including split view — is a supported screen. */
function isIpadDevice() {
  const ua = navigator.userAgent || "";
  if (/iPad/.test(ua)) return true;
  const platform = navigator.platform || "";
  const touch = navigator.maxTouchPoints || 0;
  return platform === "MacIntel" && touch > 1;
}

function isPhoneDataRoom() {
  if (typeof window === "undefined" || !window.matchMedia) return false;
  if (isIpadDevice()) return false;
  if (window.matchMedia("(max-width: 767px)").matches) return true;
  return window.matchMedia("(orientation: landscape) and (max-height: 500px) and (pointer: coarse)").matches;
}

function mobileNoticeDismissed() {
  try {
    return sessionStorage.getItem(MOBILE_NOTICE_KEY) === "1";
  } catch (e) {
    return false;
  }
}

function rememberMobileNoticeDismissed() {
  try {
    sessionStorage.setItem(MOBILE_NOTICE_KEY, "1");
  } catch (e) {}
}

function MobileRoomNotice({ copy }) {
  const notice = copy || {};
  const [open, setOpen] = useState(() => isPhoneDataRoom() && !mobileNoticeDismissed());
  const dialogRef = useRef(null);

  const close = useCallback(() => {
    rememberMobileNoticeDismissed();
    setOpen(false);
  }, []);

  useEffect(() => {
    if (!window.matchMedia) return undefined;
    const queries = [
      window.matchMedia("(max-width: 767px)"),
      window.matchMedia("(orientation: landscape) and (max-height: 500px) and (pointer: coarse)"),
    ];
    const sync = () => {
      if (mobileNoticeDismissed()) return;
      setOpen(isPhoneDataRoom());
    };
    queries.forEach((q) => {
      if (q.addEventListener) q.addEventListener("change", sync);
      else if (q.addListener) q.addListener(sync);
    });
    return () => {
      queries.forEach((q) => {
        if (q.removeEventListener) q.removeEventListener("change", sync);
        else if (q.removeListener) q.removeListener(sync);
      });
    };
  }, []);

  useEffect(() => {
    if (!open) return undefined;
    const onKey = (e) => {
      if (e.key === "Escape") close();
    };
    window.addEventListener("keydown", onKey);
    const prevOverflow = document.body.style.overflow;
    document.body.style.overflow = "hidden";
    if (dialogRef.current) dialogRef.current.focus();
    return () => {
      window.removeEventListener("keydown", onKey);
      document.body.style.overflow = prevOverflow;
    };
  }, [open, close]);

  if (!open) return null;

  return (
    <div className="dr-mobile-notice-overlay">
      <div
        className="dr-mobile-notice"
        role="dialog"
        aria-modal="true"
        aria-labelledby="dr-mobile-notice-title"
        tabIndex={-1}
        ref={dialogRef}
      >
        <div className="dr-mobile-notice-mark" aria-hidden="true">
          <svg viewBox="0 0 64 64" fill="none">
            <rect x="22" y="8" width="20" height="48" rx="3" stroke="currentColor" strokeWidth="1.75" />
            <path d="M29 14h6" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" />
            <path d="M28.5 49.5h7" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" />
            <path d="M14 14l36 36" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" />
          </svg>
        </div>
        <p className="dr-nda-kicker">{notice.kicker}</p>
        <h2 id="dr-mobile-notice-title" className="dr-nda-title">{notice.title}</h2>
        <p className="dr-mobile-notice-body">{notice.body}</p>
        <p className="dr-mobile-notice-body">{notice.follow}</p>
        <a className="dr-mobile-notice-mail" href={"mailto:" + SUPPORT_EMAIL}>{SUPPORT_EMAIL}</a>
        <button type="button" className="dr-confidentiality-enter" onClick={close}>
          {notice.continueLabel || "Continue"}
        </button>
      </div>
    </div>
  );
}

function linkifySupportEmail(text) {
  if (!text || typeof text !== "string" || !text.includes(SUPPORT_EMAIL)) return text;
  const parts = text.split(SUPPORT_EMAIL);
  return parts.flatMap((part, i) =>
    i === 0
      ? [part]
      : [
          <a key={"support-mail-" + i} className="dr-nav-contact-mail" href={"mailto:" + SUPPORT_EMAIL}>
            {SUPPORT_EMAIL}
          </a>,
          part,
        ]
  );
}

/**
 * Minimum access level (1–4) for each Fund I section.
 * Change a number here to move a whole page. A new section is a new line.
 * Documents stay at 1 so the directory is browsable; each file has its own level in dataroom-manifest.jsx.
 * LP onboarding is its own section, and it is the last step.
 */
const FUND_I_SECTION_LEVELS = {
  opportunity: 1,
  "fund-overview": 1,
  strategy: 1,
  "return-model": 1,
  "fund-pacing": 2,
  firm: 1,
  media: 1,
  articles: 1,
  documents: 1,
  verticals: 1,
  cases: 2,
  markets: 2,
  returns: 2,
  models: 2,
  questions: 3,
  scenarios: 1,
  onboarding: 4,
};

function sectionAccessLevel(section) {
  const n = FUND_I_SECTION_LEVELS[section];
  return typeof n === "number" ? n : 1;
}

function canAccessLevel(userLevel, required) {
  return Number(userLevel || 1) >= Number(required || 1);
}

function folderIdForFile(path) {
  if (!path || typeof DATAROOM_TREE === "undefined") return null;
  const folder = DATAROOM_TREE.find((f) => f.files.some((file) => file.path === path));
  return folder ? folder.id : null;
}

function dataroomFileByPath(path) {
  if (!path || typeof DATAROOM_TREE === "undefined") return null;
  for (let i = 0; i < DATAROOM_TREE.length; i++) {
    const file = DATAROOM_TREE[i].files.find((f) => f.path === path);
    if (file) return file;
  }
  return null;
}

/* Fund documents live at the bottom of the menu, as a directory.
   LP onboarding is not a folder in that directory. */
const DOCUMENT_DIRECTORY_ITEMS = (typeof DATAROOM_TREE === "undefined" ? [] : DATAROOM_TREE)
  .filter((folder) => folder.id !== "onboarding")
  .map((folder) => {
    const match = String(folder.name).match(/^(\d+)\s+[—–-]\s+(.+)$/);
    return {
      key: "doc-" + folder.id,
      section: "documents",
      folder: folder.id,
      label: match ? match[2] : folder.name,
    };
  })
  .sort((a, b) => a.label.localeCompare(b.label, "en", { sensitivity: "base" }));

const ROOM_NAV = [
  {
    id: "fund",
    labelKey: "fund",
    items: [
      { key: "overview", section: "opportunity" },
      { key: "fundOverview", section: "fund-overview" },
      { key: "team", section: "firm" },
      { key: "strategy", section: "strategy" },
      { key: "returnModel", section: "return-model" },
      { key: "fundPacing", section: "fund-pacing" },
      { key: "pipeline", section: "scenarios" },
      { key: "questions", section: "questions" },
    ],
  },
  {
    id: "core",
    labelKey: "verticalsCore",
    items: CORE_VERTICAL_IDS.map((id) => ({ key: id, section: "verticals", vertical: id })),
  },
  {
    id: "secondary",
    labelKey: "verticalsSecondary",
    items: SECONDARY_VERTICAL_IDS.map((id) => ({ key: id, section: "verticals", vertical: id })),
  },
  {
    id: "cases",
    labelKey: "caseStudies",
    items: [
      { key: "casesOverview", section: "cases", caseSlug: null },
      { key: "casesCompare", section: "cases", caseSlug: "compare" },
      {
        kind: "collapse",
        key: "caseEurope",
        labelKey: "caseEurope",
        items: [
          { key: "case-lvmh", section: "cases", caseSlug: "lvmh", caseN: "01" },
          { key: "case-tods", section: "cases", caseSlug: "tods", caseN: "02" },
          { key: "case-ferragamo", section: "cases", caseSlug: "ferragamo", caseN: "03" },
        ],
      },
      {
        kind: "collapse",
        key: "caseBrazil",
        labelKey: "caseBrazil",
        items: [
          { key: "case-sdj", section: "cases", caseSlug: "sdj", caseN: "04" },
          { key: "case-osklen", section: "cases", caseSlug: "osklen", caseN: "05" },
        ],
      },
      {
        kind: "collapse",
        key: "caseUsa",
        labelKey: "caseUsa",
        items: [
          { key: "case-tiffany", section: "cases", caseSlug: "tiffany", caseN: "06", label: "Tiffany's" },
        ],
      },
    ],
  },
  {
    id: "also",
    labelKey: "also",
    items: [
      { key: "media", section: "media" },
      { key: "articles", section: "articles" },
    ],
  },
  {
    id: "documents",
    labelKey: "documentsDirectory",
    items: DOCUMENT_DIRECTORY_ITEMS,
  },
  {
    id: "onboarding",
    labelKey: "finalStep",
    items: [
      { key: "onboarding", section: "onboarding" },
    ],
  },
];

function caseRegionKey(slug) {
  if (!slug) return null;
  const cases = ROOM_NAV.find((g) => g.id === "cases");
  if (!cases) return null;
  const region = cases.items.find((item) => item.kind === "collapse" && item.items.some((child) => child.caseSlug === slug));
  return region ? region.key : null;
}

const COMPANY_FINANCIALS = {
  "casa-aurelia": { revenue: [12, 18, 26, 34], years: [2022, 2023, 2024, 2025], ebitdaMargin: 22, entryMultiple: 11.5, exitMultiple: 13.2 },
  "andina-spirits": { revenue: [8, 14, 21, 29], years: [2022, 2023, 2024, 2025], ebitdaMargin: 28, entryMultiple: 10.2, exitMultiple: 12.8 },
  "pacifica-home": { revenue: [15, 22, 31, 42], years: [2022, 2023, 2024, 2025], ebitdaMargin: 19, entryMultiple: 12.1, exitMultiple: 14.0 },
  "vistamar-logistics": { revenue: [20, 27, 35, 44], years: [2022, 2023, 2024, 2025], ebitdaMargin: 24, entryMultiple: 9.8, exitMultiple: 11.5 },
  "terra-fina": { revenue: [10, 16, 23, 30], years: [2022, 2023, 2024, 2025], ebitdaMargin: 31, entryMultiple: 10.5, exitMultiple: 12.2 },
  "lumen-atelier": { revenue: [5, 9, 14, 20], years: [2022, 2023, 2024, 2025], ebitdaMargin: 18, entryMultiple: 11.0, exitMultiple: 13.5 },
};

/* ---------- Hash helpers ---------- */
function parseFundHash() {
  const raw = (window.location.hash || "").replace(/^#/, "");
  if (!raw.startsWith("fund-i")) {
    return {
      section: "opportunity",
      vertical: null,
      caseSlug: null,
      pacingView: null,
      folder: null,
      article: null,
      company: null,
      file: null,
      a: null,
      b: null,
      query: {},
    };
  }
  const qi = raw.indexOf("?");
  const path = qi >= 0 ? raw.slice(0, qi) : raw;
  const q = {};
  if (qi >= 0) {
    new URLSearchParams(raw.slice(qi + 1)).forEach((v, k) => { q[k] = v; });
  }
  const parts = path.split("/").filter(Boolean);
  /* fund-i | fund-i/section | fund-i/verticals/slug | fund-i/cases | fund-i/cases/slug | fund-i/fund-pacing/view | fund-i/documents/folder */
  let section = "opportunity";
  let vertical = null;
  let caseSlug = null;
  let pacingView = null;
  let folder = null;
  if (parts[1]) {
    const named = SECTION_ALIASES[parts[1]] || parts[1];
    if (DR_SECTION_IDS.includes(named)) section = named;
  }
  if (parts[1] === "verticals" && parts[2]) {
    section = "verticals";
    vertical = parts[2].split("?")[0];
  }
  if (parts[1] === "cases") {
    section = "cases";
    if (parts[2]) caseSlug = parts[2].split("?")[0];
  }
  if (parts[1] === "fund-pacing") {
    section = "fund-pacing";
    if (parts[2] && FUND_PACING_VIEWS.includes(parts[2].split("?")[0])) {
      pacingView = parts[2].split("?")[0];
    } else {
      pacingView = "portfolio";
    }
  }
  if (parts[1] === "documents") {
    section = "documents";
    const requested = parts[2] ? parts[2].split("?")[0] : "";
    if (requested && requested !== "onboarding" && DOCUMENT_DIRECTORY_ITEMS.some((item) => item.folder === requested)) {
      folder = requested;
    }
  }
  if (parts[1] === "onboarding" || (parts[1] === "documents" && parts[2] && parts[2].split("?")[0] === "onboarding")) {
    section = "onboarding";
    folder = null;
  }
  const file = q.file || null;
  const fileFolder = folderIdForFile(file);
  if (fileFolder === "onboarding") {
    section = "onboarding";
    folder = null;
  } else if (section === "documents") {
    folder = fileFolder || folder || "offering";
  }
  return {
    section,
    vertical,
    caseSlug,
    pacingView,
    folder,
    article: q.article || null,
    company: q.company || null,
    file: file,
    a: q.a || null,
    b: q.b || null,
    query: q,
  };
}

function writeFundHash(section, opts) {
  opts = opts || {};
  let path = "fund-i/" + section;
  if (section === "verticals" && opts.vertical) path += "/" + opts.vertical;
  if (section === "cases" && opts.caseSlug) path += "/" + opts.caseSlug;
  if (section === "documents" && opts.folder && opts.folder !== "onboarding") path += "/" + opts.folder;
  if (section === "fund-pacing") {
    const view = opts.pacingView && FUND_PACING_VIEWS.includes(opts.pacingView)
      ? opts.pacingView
      : "portfolio";
    if (view !== "portfolio") path += "/" + view;
  }
  const params = new URLSearchParams();
  if (opts.article) params.set("article", opts.article);
  if (opts.company) params.set("company", opts.company);
  if (opts.file) params.set("file", opts.file);
  if (opts.filter) params.set("filter", opts.filter);
  if (section === "cases" && opts.caseSlug === "compare") {
    if (opts.a) params.set("a", opts.a);
    if (opts.b) params.set("b", opts.b);
  }
  const qs = params.toString();
  const next = "#" + path + (qs ? "?" + qs : "");
  if (window.location.hash !== next) {
    history.replaceState(null, "", window.location.pathname + window.location.search + next);
  }
}

/* ---------- Shared UI ---------- */
function Kpi({ label, value, sub, onClick, hint }) {
  const Tag = onClick ? "button" : "div";
  return (
    <Tag
      type={onClick ? "button" : undefined}
      className={"dr-kpi" + (onClick ? " dr-kpi-link" : "")}
      onClick={onClick}
      title={hint}
    >
      <div className="dr-kpi-label">{label}</div>
      <div className="dr-kpi-value dr-mono">{value}</div>
      {sub && <div className="dr-kpi-sub">{sub}</div>}
    </Tag>
  );
}

function PendingPanel({ d, name, folder, path }) {
  return (
    <div className="dr-panel dr-pending-panel">
      <h3 className="dr-panel-title">{d.pendingTitle}</h3>
      <p className="dr-body" style={{ maxWidth: "none", marginBottom: 12 }}>{d.pendingBody}</p>
      {name && <p style={{ fontFamily: "var(--font-serif)", fontSize: "1rem", color: "var(--alabaster)", margin: "0 0 6px" }}>{name}</p>}
      {folder && <p style={{ fontFamily: "var(--font-sans)", fontSize: "0.6875rem", letterSpacing: "0.08em", textTransform: "uppercase", color: "var(--sapphire-200)", margin: "0 0 12px" }}>{folder}</p>}
      {path && (
        <p className="dr-mono" style={{ fontSize: "0.75rem", color: "var(--gold-400)", margin: 0, wordBreak: "break-all" }}>
          <span style={{ color: "var(--sapphire-200)" }}>{d.pendingPathLabel}: </span>{path}
        </p>
      )}
    </div>
  );
}

function HypotheticalNote({ text }) {
  return <p className="dr-hypo-note">{text}</p>;
}

function sparklinePath(data, w, h, pad) {
  const min = Math.min(...data), max = Math.max(...data), range = max - min || 1;
  const pts = data.map((v, i) => {
    const x = pad + (i / (data.length - 1)) * (w - pad * 2);
    const y = h - pad - ((v - min) / range) * (h - pad * 2);
    return x + "," + y;
  });
  return "M" + pts.join(" L");
}

function Sparkline({ data, color = "#C5A059" }) {
  const d = sparklinePath(data, 120, 40, 4);
  return (
    <svg className="dr-sparkline" viewBox="0 0 120 40" preserveAspectRatio="none">
      <path d={d} fill="none" stroke={color} strokeWidth="1.5" vectorEffect="non-scaling-stroke" />
    </svg>
  );
}

function BarChart({ rows, maxVal, activeLabel, onHover, onLeave }) {
  const m = maxVal || Math.max(...rows.map((r) => r.value), 1);
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
      {rows.map((r) => (
        <div
          key={r.label}
          onMouseEnter={() => onHover && onHover(r)}
          onMouseLeave={() => onLeave && onLeave()}
          style={{ opacity: activeLabel && activeLabel !== r.label ? 0.45 : 1, cursor: onHover ? "pointer" : "default" }}
        >
          <div style={{ display: "flex", justifyContent: "space-between", marginBottom: 6, fontSize: "0.75rem" }}>
            <span style={{ fontFamily: "var(--font-sans)", color: "var(--alabaster)" }}>{r.label}</span>
            <span className="dr-mono" style={{ color: "var(--gold-400)" }}>{r.display}</span>
          </div>
          <div style={{ height: 6, background: "rgba(76,91,122,0.35)" }}>
            <div style={{ height: "100%", width: (r.value / m * 100) + "%", background: "var(--gold-500)" }} />
          </div>
        </div>
      ))}
    </div>
  );
}

function ForecastLineChart({ series, labels, height = 300, yMin = 0, yMax, cursorIndex, onCursor, dimmed }) {
  const w = 720;
  const pad = { top: 28, right: 20, bottom: 40, left: 52 };
  const chartW = w - pad.left - pad.right;
  const chartH = height - pad.top - pad.bottom;
  const allVals = series.flatMap((s) => s.data);
  const maxY = yMax ?? Math.max(1, ...allVals) * 1.1;
  const minY = yMin;
  const xAt = (i) => pad.left + (labels.length <= 1 ? 0 : (i / (labels.length - 1)) * chartW);
  const yAt = (v) => pad.top + chartH - ((v - minY) / (maxY - minY || 1)) * chartH;
  const gridSteps = 4;
  const [hover, setHover] = useState(null);

  const nearestIndex = (clientX, rect) => {
    const x = ((clientX - rect.left) / rect.width) * w;
    let best = 0, bestD = Infinity;
    for (let i = 0; i < labels.length; i++) {
      const d = Math.abs(xAt(i) - x);
      if (d < bestD) { bestD = d; best = i; }
    }
    return best;
  };

  const activeIdx = hover != null ? hover : cursorIndex;
  const readout = activeIdx != null ? series.filter((s) => s.active !== false && !(dimmed && dimmed[s.label])).map((s) => ({
    label: s.label, color: s.color, value: s.data[activeIdx],
  })) : null;

  return (
    <div>
      <div
        style={{ position: "relative" }}
        onMouseMove={(e) => {
          const rect = e.currentTarget.getBoundingClientRect();
          const i = nearestIndex(e.clientX, rect);
          setHover(i);
          if (onCursor) onCursor(i);
        }}
        onMouseLeave={() => setHover(null)}
      >
        <svg viewBox={"0 0 " + w + " " + height} style={{ width: "100%", height: "auto", display: "block" }}>
          {Array.from({ length: gridSteps + 1 }, (_, i) => {
            const v = minY + ((maxY - minY) * i) / gridSteps;
            const y = yAt(v);
            return (
              <g key={i}>
                <line x1={pad.left} y1={y} x2={w - pad.right} y2={y} stroke="rgba(76,91,122,0.35)" strokeWidth="1" />
                <text x={pad.left - 10} y={y + 4} textAnchor="end" fill="var(--sapphire-200)" fontSize="11" fontFamily="ui-monospace, monospace">
                  {v.toFixed(2)}x
                </text>
              </g>
            );
          })}
          {labels.map((label, i) => (
            <text key={label} x={xAt(i)} y={height - 10} textAnchor="middle" fill="var(--sapphire-200)" fontSize="11" fontFamily="var(--font-sans)">
              {label}
            </text>
          ))}
          {series.map((s) => {
            const off = dimmed && dimmed[s.label];
            const d = s.data.map((v, i) => (i === 0 ? "M" : "L") + xAt(i).toFixed(1) + "," + yAt(v).toFixed(1)).join(" ");
            return (
              <path key={s.label} d={d} fill="none" stroke={s.color} strokeWidth={s.active ? 2.5 : 1.75}
                strokeDasharray={s.dashed ? "6 4" : undefined} opacity={off ? 0.15 : (s.active === false ? 0.45 : 1)} />
            );
          })}
          {activeIdx != null && (
            <line x1={xAt(activeIdx)} y1={pad.top} x2={xAt(activeIdx)} y2={pad.top + chartH} stroke="rgba(197,160,89,0.45)" strokeWidth="1" strokeDasharray="4 3" />
          )}
          {series.filter((s) => s.active && !(dimmed && dimmed[s.label])).map((s) => {
            const i = activeIdx != null ? activeIdx : s.data.length - 1;
            return <circle key={s.label + "-dot"} cx={xAt(i)} cy={yAt(s.data[i])} r={4} fill={s.color} />;
          })}
        </svg>
        {readout && (
          <div className="dr-chart-tooltip">
            <div className="dr-mono" style={{ marginBottom: 6, color: "var(--gold-400)" }}>{labels[activeIdx]}</div>
            {readout.map((r) => (
              <div key={r.label} style={{ display: "flex", gap: 10, justifyContent: "space-between", fontSize: "0.6875rem" }}>
                <span style={{ color: r.color }}>{r.label}</span>
                <span className="dr-mono">{r.value.toFixed(2)}x</span>
              </div>
            ))}
          </div>
        )}
      </div>
      <div style={{ display: "flex", flexWrap: "wrap", gap: 16, marginTop: 12 }}>
        {series.map((s) => (
          <button
            key={s.label}
            type="button"
            className="dr-legend-btn"
            style={{ opacity: dimmed && dimmed[s.label] ? 0.35 : 1 }}
            onClick={() => s.onToggle && s.onToggle(s.label)}
          >
            <span style={{ width: 20, height: 2, background: s.color }} />
            {s.label}
          </button>
        ))}
      </div>
    </div>
  );
}

function DonutChart({ segments, size = 160, onSelect }) {
  const total = segments.reduce((s, x) => s + x.value, 0) || 1;
  let angle = -90;
  const r = size / 2 - 8;
  const cx = size / 2, cy = size / 2;
  const paths = segments.map((seg) => {
    const sweep = (seg.value / total) * 360;
    const a0 = angle * Math.PI / 180;
    angle += sweep;
    const a1 = angle * Math.PI / 180;
    const x0 = cx + r * Math.cos(a0), y0 = cy + r * Math.sin(a0);
    const x1 = cx + r * Math.cos(a1), y1 = cy + r * Math.sin(a1);
    const large = sweep > 180 ? 1 : 0;
    const d = "M" + cx + "," + cy + " L" + x0 + "," + y0 + " A" + r + "," + r + " 0 " + large + ",1 " + x1 + "," + y1 + " Z";
    return { ...seg, d };
  });
  return (
    <svg width={size} height={size} viewBox={"0 0 " + size + " " + size}>
      {paths.map((p) => (
        <path
          key={p.label}
          d={p.d}
          fill={p.color}
          stroke="var(--sapphire-900)"
          strokeWidth="1"
          style={{ cursor: onSelect ? "pointer" : "default" }}
          onClick={() => onSelect && onSelect(p)}
        />
      ))}
      <circle cx={cx} cy={cy} r={r * 0.55} fill="var(--sapphire-900)" />
    </svg>
  );
}

/* ---------- Access levels ---------- */
function AccessLevelMark({ level, label }) {
  return (
    <span className="dr-access-mark" title={label || ("Level " + level)}>
      <i data-lucide="lock" aria-hidden="true"></i>
      <span>{"Level " + level}</span>
    </span>
  );
}

function accessCopy(t) {
  const d = (t && t.dataroom) || {};
  return d.access || (I18N.en.dataroom && I18N.en.dataroom.access) || {};
}

function levelMeta(access, level) {
  const levels = (access && access.levels) || [];
  return levels.find((L) => L.id === level) || { id: level, name: "Level " + level, audience: "", materials: "" };
}

function upgradeActionText(access, level) {
  const copy = access || {};
  if (level === 2) return copy.signNda || "Sign the NDA";
  if (level === 3) return copy.scheduleCall || "Schedule a call";
  if (level === 4) return copy.byInvitation || "By invitation only";
  return "";
}

function upgradeCtaLabel(access, level) {
  const template = (access && access.upgradeCta) || "Upgrade · {action}";
  return template.replace("{action}", upgradeActionText(access, level));
}

function laterCtaLabel(access, level) {
  const template = (access && access.laterCta) || "Then · {action}";
  return template.replace("{action}", upgradeActionText(access, level));
}

function NdaCopyLink({ label }) {
  return (
    <a
      className="dr-nda-copy-link"
      href={NDA_COPY_URL}
      target="_blank"
      rel="noopener noreferrer"
    >
      {label || "Preview & download a copy of the NDA"}
    </a>
  );
}

function UpgradeAccessButton({ access, accessLevel }) {
  const copy = access && typeof access === "object" ? access : {};
  const next = Number(accessLevel || 1) + 1;
  const [open, setOpen] = useState(false);
  const wrapRef = useRef(null);

  useEffect(() => {
    if (!open) return undefined;
    const onPointer = (e) => {
      if (wrapRef.current && !wrapRef.current.contains(e.target)) setOpen(false);
    };
    const onKey = (e) => {
      if (e.key === "Escape" && !document.querySelector(".dr-nda-overlay")) setOpen(false);
    };
    document.addEventListener("pointerdown", onPointer);
    document.addEventListener("keydown", onKey);
    return () => {
      document.removeEventListener("pointerdown", onPointer);
      document.removeEventListener("keydown", onKey);
    };
  }, [open]);

  if (next > 4) return null;

  const meta = levelMeta(copy, next);
  const label = upgradeCtaLabel(copy, next);
  const toLabel = (copy.upgradeTo || "To reach Level {level} — {name}")
    .replace("{level}", String(next))
    .replace("{name}", meta.name || "");

  if (next !== 2 && next < 4) {
    return (
      <div className="dr-upgrade">
        <AccessActionButton level={next} access={copy} label={label} prominent title={toLabel} />
      </div>
    );
  }

  return (
    <div className="dr-upgrade" ref={wrapRef}>
      <button
        type="button"
        className="dr-upgrade-btn"
        aria-haspopup="dialog"
        aria-expanded={open}
        aria-controls="dr-upgrade-panel"
        onClick={() => setOpen((v) => !v)}
      >
        {label}
      </button>
      {open && (
        <div className="dr-upgrade-panel" id="dr-upgrade-panel" role="dialog" aria-label={label}>
          <p className="dr-upgrade-kicker">{toLabel}</p>
          {meta.audience ? <p className="dr-upgrade-audience">{meta.audience}</p> : null}
          <AccessActionButton level={next} access={copy} prominent={next === 2} />
          {next === 2 && copy.ndaNote ? <p className="dr-upgrade-note">{copy.ndaNote}</p> : null}
          {next === 2 ? <NdaCopyLink label={copy.ndaCopyLink} /> : null}
        </div>
      )}
    </div>
  );
}

function NdaFormModal({ onClose, copyLink }) {
  const [recipientType, setRecipientType] = useState("entity");
  const [legalName, setLegalName] = useState("");
  const [jurisdiction, setJurisdiction] = useState("");
  const [title, setTitle] = useState("");
  const [individualName, setIndividualName] = useState("");
  const [noticesAddress, setNoticesAddress] = useState("");
  const [signature, setSignature] = useState("");
  const [scheduleUsers, setScheduleUsers] = useState([emptyScheduleRow()]);
  const [busy, setBusy] = useState(false);
  const [error, setError] = useState("");
  const [receipt, setReceipt] = useState(null);
  const effectiveDate = useMemo(() => nyCalendarDate(), []);
  const dialogRef = useRef(null);

  useEffect(() => {
    if (typeof folcloreTrack === "function") folcloreTrack("nda_started", "nda started", { room: "fund-i" });
  }, []);

  useEffect(() => {
    const onKey = (e) => {
      if (e.key === "Escape" && !busy) onClose();
    };
    document.addEventListener("keydown", onKey);
    const prev = document.body.style.overflow;
    document.body.style.overflow = "hidden";
    if (dialogRef.current) dialogRef.current.focus();
    return () => {
      document.removeEventListener("keydown", onKey);
      document.body.style.overflow = prev;
    };
  }, [onClose, busy]);

  const updateSchedule = (index, field, value) => {
    setScheduleUsers((rows) => rows.map((row, i) => (i === index ? { ...row, [field]: value } : row)));
  };

  const addScheduleRow = () => {
    setScheduleUsers((rows) => [...rows, emptyScheduleRow()]);
  };

  const removeScheduleRow = (index) => {
    setScheduleUsers((rows) => (rows.length <= 1 ? [emptyScheduleRow()] : rows.filter((_, i) => i !== index)));
  };

  const onSubmit = async (e) => {
    e.preventDefault();
    if (busy) return;
    setError("");
    setBusy(true);
    try {
      if (typeof submitNda !== "function") {
        throw new Error("NDA submission is not available.");
      }
      const data = await submitNda({
        recipient_type: recipientType,
        legal_name: legalName,
        jurisdiction,
        title,
        individual_name: individualName,
        notices_address: noticesAddress,
        signature,
        schedule_users: scheduleUsers,
        room: "fund-i",
      });
      setReceipt(data);
    } catch (err) {
      if (typeof folcloreTrack === "function") folcloreTrack("nda_failed", "nda failed", { room: "fund-i" }, "error");
      setError((err && err.message) || "Could not submit the NDA.");
    } finally {
      setBusy(false);
    }
  };

  return (
    <div className="dr-nda-overlay" role="presentation" onMouseDown={(e) => {
      if (e.target === e.currentTarget && !busy && !receipt) onClose();
    }}>
      <div
        className="dr-nda-modal"
        role="dialog"
        aria-modal="true"
        aria-labelledby="dr-nda-title"
        tabIndex={-1}
        ref={dialogRef}
      >
        <div className="dr-nda-modal-head">
          <div>
            <p className="dr-nda-kicker">Folclore Latin Fund I</p>
            <h2 id="dr-nda-title" className="dr-nda-title">Data Room NDA — signature block</h2>
            <NdaCopyLink label={copyLink} />
          </div>
          <button type="button" className="dr-scenario-tab" onClick={onClose} disabled={busy}>Close</button>
        </div>

        {receipt ? (
          <div className="dr-nda-receipt">
            <p className="dr-nda-receipt-label">Received</p>
            <p className="dr-nda-receipt-time">{receipt.received_at_ny || receipt.received_at}</p>
            <p className="dr-muted" style={{ marginTop: 12 }}>
              Effective date: {receipt.effective_date || effectiveDate}. A copy was sent to your signed-in email
              {receipt.confirm_sent === false ? " when email delivery is available" : ""}, with dataroom@folclore.capital on copy.
              Access is raised after we review this submission.
            </p>
            <button type="button" className="dr-upgrade-btn" style={{ marginTop: 18 }} onClick={onClose}>Done</button>
          </div>
        ) : (
          <form className="dr-nda-form" onSubmit={onSubmit}>
            <fieldset className="dr-nda-fieldset">
              <legend>Recipient</legend>
              <div className="dr-nda-type-row">
                <label className={"dr-nda-type" + (recipientType === "entity" ? " active" : "")}>
                  <input
                    type="radio"
                    name="recipient_type"
                    value="entity"
                    checked={recipientType === "entity"}
                    onChange={() => setRecipientType("entity")}
                  />
                  Entity
                </label>
                <label className={"dr-nda-type" + (recipientType === "individual" ? " active" : "")}>
                  <input
                    type="radio"
                    name="recipient_type"
                    value="individual"
                    checked={recipientType === "individual"}
                    onChange={() => setRecipientType("individual")}
                  />
                  Individual
                </label>
              </div>
            </fieldset>

            <label className="dr-nda-field">
              <span>Effective Date</span>
              <input type="text" value={effectiveDate} readOnly />
              <span className="dr-nda-hint">New York calendar date of receipt. Set by the server when you submit.</span>
            </label>

            {recipientType === "entity" ? (
              <div className="dr-nda-grid">
                <label className="dr-nda-field">
                  <span>Legal name</span>
                  <input type="text" required value={legalName} onChange={(e) => setLegalName(e.target.value)} autoComplete="organization" />
                </label>
                <label className="dr-nda-field">
                  <span>Jurisdiction of organization</span>
                  <input type="text" required value={jurisdiction} onChange={(e) => setJurisdiction(e.target.value)} />
                </label>
                <label className="dr-nda-field">
                  <span>Title</span>
                  <input type="text" required value={title} onChange={(e) => setTitle(e.target.value)} autoComplete="organization-title" />
                </label>
              </div>
            ) : (
              <div className="dr-nda-grid">
                <label className="dr-nda-field">
                  <span>Name</span>
                  <input type="text" required value={individualName} onChange={(e) => setIndividualName(e.target.value)} autoComplete="name" />
                </label>
                <label className="dr-nda-field dr-nda-field-wide">
                  <span>Address and email for notices</span>
                  <textarea required rows={3} value={noticesAddress} onChange={(e) => setNoticesAddress(e.target.value)} />
                </label>
              </div>
            )}

            <label className="dr-nda-field">
              <span>Signature</span>
              <input
                type="text"
                required
                value={signature}
                onChange={(e) => setSignature(e.target.value)}
                placeholder="Type your full legal name"
                autoComplete="off"
              />
              <span className="dr-nda-hint">Type your full legal name to sign.</span>
            </label>

            <fieldset className="dr-nda-fieldset">
              <legend>Schedule 1 — Authorized Data Room Users</legend>
              <p className="dr-nda-hint" style={{ marginBottom: 12 }}>
                Each individual listed below will receive personal Data Room credentials under Section 3.1.
                Recipient may update this list by email to dataroom@folclore.capital. Optional.
              </p>
              {scheduleUsers.map((row, index) => (
                <div key={index} className="dr-nda-schedule-row">
                  <label className="dr-nda-field">
                    <span>Name</span>
                    <input type="text" value={row.name} onChange={(e) => updateSchedule(index, "name", e.target.value)} />
                  </label>
                  <label className="dr-nda-field">
                    <span>Organization and role</span>
                    <input type="text" value={row.organization_role} onChange={(e) => updateSchedule(index, "organization_role", e.target.value)} />
                  </label>
                  <label className="dr-nda-field">
                    <span>Email (for Data Room credentials)</span>
                    <input type="email" value={row.email} onChange={(e) => updateSchedule(index, "email", e.target.value)} />
                  </label>
                  <button type="button" className="dr-scenario-tab" onClick={() => removeScheduleRow(index)}>Remove</button>
                </div>
              ))}
              <button type="button" className="dr-scenario-tab" onClick={addScheduleRow}>Add person</button>
            </fieldset>

            {error && <p className="dr-nda-error" role="alert">{error}</p>}

            <div className="dr-nda-actions">
              <button type="button" className="dr-scenario-tab" onClick={onClose} disabled={busy}>Cancel</button>
              <button type="submit" className="dr-upgrade-btn" disabled={busy}>
                {busy ? "Submitting…" : "Submit signature"}
              </button>
            </div>
          </form>
        )}
      </div>
    </div>
  );
}

function NdaSignFlow({ access, label, className, title }) {
  const [open, setOpen] = useState(false);
  return (
    <React.Fragment>
      <button type="button" className={className || "dr-scenario-tab"} title={title} onClick={() => setOpen(true)}>
        {label || access.signNda}
      </button>
      {open && <NdaFormModal onClose={() => setOpen(false)} copyLink={access && access.ndaCopyLink} />}
    </React.Fragment>
  );
}

function AccessActionButton({ level, access, label, prominent, title }) {
  const className = prominent ? "dr-upgrade-btn" : "dr-scenario-tab";
  if (level === 2) {
    return <NdaSignFlow access={access} label={label} className={className} title={title} />;
  }
  if (level === 3) {
    const text = label || access.scheduleCall;
    const href = APPOINTMENT_URL;
    if (!href) {
      return <button type="button" className={className} title={title} disabled>{text}</button>;
    }
    return (
      <a
        href={href}
        target="_blank"
        rel="noopener noreferrer"
        className={className}
        title={title}
        onClick={() => { if (typeof folcloreTrack === "function") folcloreTrack("schedule_call_clicked", "schedule call clicked", { room: "fund-i" }); }}
      >
        {text}
      </a>
    );
  }
  if (level === 4) {
    const text = label || access.byInvitation;
    return (
      <div className="dr-access-invite">
        <button type="button" className={className} title={title} disabled>{text}</button>
        <p className="dr-muted" style={{ margin: "10px 0 0" }}>{linkifySupportEmail(access.invitationNote)}</p>
      </div>
    );
  }
  return null;
}

function AccessLevelsPanel({ t, accessLevel }) {
  const access = accessCopy(t);
  const levels = access.levels || [];
  const level = Number(accessLevel || 1);
  const atTop = level >= 4;
  const [open, setOpen] = useState(!atTop);
  const currentMeta = levelMeta(access, level);
  const summary = (access.levelPill || "Level {level} · {name}")
    .replace("{level}", String(level))
    .replace("{name}", currentMeta.name || "");

  useEffect(() => {
    setOpen(level < 4);
  }, [level]);

  useEffect(() => {
    if (window.lucide) window.lucide.createIcons();
  }, [level, open]);

  return (
    <div className={"dr-access-panel" + (atTop ? " collapsible" : "") + (atTop && open ? " open" : "")} style={{ marginTop: 28 }}>
      {atTop ? (
        <button
          type="button"
          className="dr-access-toggle"
          aria-expanded={open}
          aria-controls="dr-access-ladder"
          onClick={() => setOpen((v) => !v)}
        >
          <span className="dr-access-toggle-copy">
            <span className="dr-panel-title">{access.panelTitle}</span>
            {!open && <span className="dr-access-toggle-summary">{summary}</span>}
          </span>
          <span className="dr-nav-chevron" aria-hidden="true" />
        </button>
      ) : (
        <React.Fragment>
          <h3 className="dr-panel-title">{access.panelTitle}</h3>
          <p className="dr-muted" style={{ marginBottom: 16 }}>{linkifySupportEmail(access.panelIntro)}</p>
        </React.Fragment>
      )}
      {(!atTop || open) && (
      <div id="dr-access-ladder" className="dr-access-levels">
        {levels.map((L) => {
          const current = L.id === level;
          const locked = L.id > level;
          const isNext = L.id === level + 1;
          return (
            <article key={L.id} className={"dr-access-card" + (current ? " current" : "") + (isNext ? " next" : "") + (locked ? " locked" : "")}>
              <div className="dr-access-card-head">
                <span className="dr-access-card-level">{"Level " + L.id}</span>
                {current && <span className="dr-access-card-badge">{access.currentBadge}</span>}
                {isNext && <span className="dr-access-card-next">{access.nextBadge || "Your next step"}</span>}
                {locked && !isNext && <AccessLevelMark level={L.id} label={L.name} />}
              </div>
              <h4 className="dr-access-card-name">{L.name}</h4>
              <p className="dr-access-card-audience">{L.audience}</p>
              <p className="dr-muted" style={{ margin: "8px 0 0" }}>{L.materials}</p>
              {isNext && (
                <div className="dr-access-card-action">
                  <AccessActionButton level={L.id} access={access} label={upgradeCtaLabel(access, L.id)} prominent />
                  {L.id === 2 && access.ndaNote ? (
                    <p className="dr-muted" style={{ margin: "8px 0 0", fontSize: "0.75rem" }}>{access.ndaNote}</p>
                  ) : null}
                  {L.id === 2 ? <NdaCopyLink label={access.ndaCopyLink} /> : null}
                </div>
              )}
              {locked && !isNext && (
                <div className="dr-access-card-action">
                  <p className="dr-access-card-later">{laterCtaLabel(access, L.id)}</p>
                  {L.id === 4 ? (
                    <p className="dr-muted" style={{ margin: "8px 0 0", fontSize: "0.75rem" }}>{linkifySupportEmail(access.invitationNote)}</p>
                  ) : null}
                </div>
              )}
            </article>
          );
        })}
      </div>
      )}
    </div>
  );
}

function AccessLockPanel({ t, requiredLevel }) {
  const access = accessCopy(t);
  const meta = levelMeta(access, requiredLevel);
  useEffect(() => {
    if (window.lucide) window.lucide.createIcons();
  }, [requiredLevel]);

  return (
    <div className="dr-access-lock">
      <div className="dr-access-lock-icon" aria-hidden="true">
        <i data-lucide="lock"></i>
      </div>
      <Eyebrow color="var(--gold-400)">{access.lockEyebrow}</Eyebrow>
      <h2 className="dr-title">{(access.lockTitle || "").replace("{level}", String(requiredLevel)).replace("{name}", meta.name)}</h2>
      <p className="dr-lead">{meta.audience}</p>
      <p className="dr-body">{meta.materials}</p>
      <div className="dr-access-lock-action" style={{ marginTop: 24 }}>
        <AccessActionButton level={requiredLevel} access={access} />
        {requiredLevel === 2 && (
          <React.Fragment>
            <p className="dr-muted" style={{ margin: "12px 0 0" }}>{access.ndaNote}</p>
            <NdaCopyLink label={access.ndaCopyLink} />
          </React.Fragment>
        )}
      </div>
    </div>
  );
}

/* ---------- Sections ---------- */
function OpportunityView({ t, navigate, accessLevel }) {
  const d = t.dataroom;
  const o = d.opportunity;
  const core = d.verticals.categories.filter((c) => c.tier !== "secondary");
  const level = Number(accessLevel || 1);

  return (
    <div>
      <Eyebrow color="var(--gold-400)">{o.eyebrow}</Eyebrow>
      <h2 className="dr-title">{o.title}</h2>
      <p className="dr-lead">{o.lead}</p>

      <AccessLevelsPanel t={t} accessLevel={level} />

      <div style={{ marginTop: 28 }}>
        <h3 className="dr-panel-title">{d.navGroups.verticalsCore}</h3>
        <div className="dr-cat-grid">
          {core.map((c) => (
            <button key={c.id} type="button" className="dr-door-card" onClick={() => navigate("verticals", { vertical: c.id })}>
              <span className="dr-door-eyebrow">{c.name}</span>
              <span className="dr-door-body">{c.blurb}</span>
            </button>
          ))}
        </div>
      </div>

      <div style={{ marginTop: 28 }}>
        <h3 className="dr-panel-title">{o.doorsTitle}</h3>
        <div className="dr-door-row">
          <button type="button" className="dr-door-card" onClick={() => navigate("fund-overview")}>
            <span className="dr-door-eyebrow">{d.nav.fundOverview}</span>
            <span className="dr-door-body">{d.fundOverview.doorBody}</span>
          </button>
          <button type="button" className="dr-door-card" onClick={() => navigate("strategy")}>
            <span className="dr-door-eyebrow">{d.nav.strategy}</span>
            <span className="dr-door-body">{d.strategy.lead}</span>
          </button>
          <button type="button" className="dr-door-card" onClick={() => navigate("documents")}>
            <span className="dr-door-eyebrow">{d.navGroups.documentsDirectory}</span>
            <span className="dr-door-body">{d.documents.intro}</span>
          </button>
          <button type="button" className="dr-door-card" onClick={() => navigate("articles")}>
            <span className="dr-door-eyebrow">{d.nav.articles}</span>
            <span className="dr-door-body">{d.articles.intro}</span>
          </button>
        </div>
      </div>
    </div>
  );
}

function FundOverviewView({ t }) {
  const d = t.dataroom;
  const o = d.opportunity;
  const page = d.fundOverview;
  const summaryUrl = typeof EXECUTIVE_SUMMARY_URL === "string" ? EXECUTIVE_SUMMARY_URL : "";

  return (
    <div>
      <Eyebrow color="var(--gold-400)">{page.eyebrow}</Eyebrow>
      <h2 className="dr-title">{page.title}</h2>
      <p className="dr-lead">{page.lead}</p>

      <div className="dr-panel" style={{ marginTop: 28 }}>
        <h3 className="dr-panel-title">{o.termsTitle}</h3>
        <p className="dr-muted" style={{ marginBottom: 16 }}>{o.termsNote}</p>
        <div className="dr-kpi-grid">
          {o.terms.map((m) => <Kpi key={m.label} label={m.label} value={m.value} />)}
        </div>
      </div>

      <div className="dr-panel" style={{ marginTop: 20 }}>
        <h3 className="dr-panel-title">{page.snapshotTitle}</h3>
        <p className="dr-muted" style={{ marginBottom: 16 }}>{page.snapshotNote}</p>
        <table className="dr-table">
          <tbody>
            {page.snapshot.map((row) => (
              <tr key={row.label}>
                <td style={{ width: "22%", color: "var(--sapphire-200)" }}>{row.label}</td>
                <td>{row.value}</td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>

      <div className="dr-panel" style={{ marginTop: 20 }}>
        <h3 className="dr-panel-title">{page.execSummaryTitle}</h3>
        <p className="dr-muted">{page.execSummaryNote}</p>
        {summaryUrl && (
          <a className="dr-exec-btn" href={summaryUrl} target="_blank" rel="noopener noreferrer">
            {page.execSummaryCta}
          </a>
        )}
      </div>
    </div>
  );
}

function StrategyView({ t, navigate }) {
  const d = t.dataroom;
  const o = d.opportunity;
  const s = d.strategy;
  return (
    <div>
      <Eyebrow color="var(--gold-400)">{s.eyebrow}</Eyebrow>
      <h2 className="dr-title">{s.title}</h2>
      <p className="dr-lead">{s.lead}</p>

      <div className="dr-panel" style={{ marginTop: 28 }}>
        <h3 className="dr-panel-title">{o.nestingTitle}</h3>
        <div className="dr-nesting">
          {o.nesting.map((n) => (
            <div key={n.step} className="dr-nesting-step">
              <span className="dr-nesting-num dr-mono">{n.step}</span>
              <div>
                <div className="dr-nesting-title">{n.title}</div>
                <p className="dr-muted" style={{ margin: "6px 0 0" }}>{n.body}</p>
              </div>
            </div>
          ))}
        </div>
      </div>

      <div className="dr-two-col" style={{ marginTop: 20 }}>
        <div className="dr-panel">
          <h3 className="dr-panel-title">{o.screenTitle}</h3>
          <ul className="dr-check-list">
            {o.screen.map((line) => <li key={line}>{line}</li>)}
          </ul>
        </div>
        <div className="dr-panel">
          <h3 className="dr-panel-title">{o.outOfScopeTitle}</h3>
          <ul className="dr-check-list dr-check-list-out">
            {o.outOfScope.map((line) => <li key={line}>{line}</li>)}
          </ul>
        </div>
      </div>

      <div className="dr-door-row" style={{ marginTop: 20 }}>
        <button type="button" className="dr-door-card" onClick={() => navigate("returns")}>
          <span className="dr-door-eyebrow">{s.modelTitle}</span>
          <span className="dr-door-body">{s.modelBody}</span>
        </button>
        <button type="button" className="dr-door-card" onClick={() => navigate("markets")}>
          <span className="dr-door-eyebrow">{s.marketsTitle}</span>
          <span className="dr-door-body">{s.marketsBody}</span>
        </button>
        <button type="button" className="dr-door-card" onClick={() => navigate("models")}>
          <span className="dr-door-eyebrow">{s.caseTitle}</span>
          <span className="dr-door-body">{s.caseBody}</span>
        </button>
      </div>
    </div>
  );
}

function MediaView({ t, navigate }) {
  const d = t.dataroom;
  const m = d.media;
  const firm = d.firm;
  return (
    <div>
      <Eyebrow color="var(--gold-400)">{m.eyebrow}</Eyebrow>
      <h2 className="dr-title">{m.title}</h2>
      <p className="dr-lead">{m.lead}</p>
      <div className="dr-panel" style={{ marginTop: 28 }}>
        <h3 className="dr-panel-title">{firm.podcastTitle}</h3>
        <p className="dr-muted">{firm.podcastBody}</p>
        <a href={PODCAST_URL} target="_blank" rel="noopener noreferrer" className="dr-scenario-tab" style={{ display: "inline-block", textDecoration: "none", marginTop: 14 }}>
          {firm.podcastCta} →
        </a>
      </div>
      <div className="dr-panel" style={{ marginTop: 20 }}>
        <p className="dr-muted">{m.libraryNote}</p>
        <button type="button" className="dr-scenario-tab" style={{ marginTop: 14 }} onClick={() => navigate("articles")}>{m.libraryCta}</button>
      </div>
    </div>
  );
}

function QuestionsView({ t, navigate }) {
  const q = t.dataroom.questions;
  return (
    <div>
      <Eyebrow color="var(--gold-400)">{q.eyebrow}</Eyebrow>
      <h2 className="dr-title">{q.title}</h2>
      <p className="dr-lead">{q.lead}</p>
      <div className="dr-questions">
        {q.items.map((item) => (
          <article key={item.q} className="dr-panel">
            <h3 className="dr-question">{item.q}</h3>
            <p className="dr-muted" style={{ margin: 0 }}>{item.a}</p>
          </article>
        ))}
      </div>
      <div className="dr-door-row" style={{ marginTop: 8 }}>
        <button type="button" className="dr-door-card" onClick={() => navigate("documents")}>
          <span className="dr-door-eyebrow">{t.dataroom.navGroups.documentsDirectory}</span>
          <span className="dr-door-body">{t.dataroom.documents.intro}</span>
        </button>
        <button type="button" className="dr-door-card" onClick={() => navigate("strategy")}>
          <span className="dr-door-eyebrow">{t.dataroom.nav.strategy}</span>
          <span className="dr-door-body">{t.dataroom.strategy.lead}</span>
        </button>
      </div>
    </div>
  );
}

function VerticalsView({ t, navigate, verticalSlug, accessLevel }) {
  return <VerticalPage t={t} navigate={navigate} verticalSlug={verticalSlug} accessLevel={accessLevel} />;
}

function FirmView({ navigate, accessLevel, userEmail }) {
  return <TeamPage navigate={navigate} accessLevel={accessLevel} userEmail={userEmail} />;
}

function FundReturnsModel({ t }) {
  const d = t.dataroom.fundReturns;
  const [scenario, setScenario] = useState("base");
  const [assumptions, setAssumptions] = useState({ ...FUND_DEFAULTS });
  const [dimmed, setDimmed] = useState({});
  const [cursor, setCursor] = useState(null);
  const [fileError, setFileError] = useState(null);
  const setA = useCallback((key, val) => setAssumptions((p) => ({ ...p, [key]: val })), []);

  const results = useMemo(() => computeFundReturns(assumptions, scenario), [assumptions, scenario]);
  const allScenarios = useMemo(() => ({
    bear: computeFundReturns(assumptions, "bear"),
    base: computeFundReturns(assumptions, "base"),
    bull: computeFundReturns(assumptions, "bull"),
  }), [assumptions]);

  const chartLabels = results.rows.map((r) => String(r.vintage));
  const chartSeries = ["bear", "base", "bull"].map((s) => ({
    label: FUND_SCENARIOS[s].label,
    color: s === "bear" ? "#4C5B7A" : s === "bull" ? "#D4B679" : "#C5A059",
    data: allScenarios[s].rows.map((r) => r.tvpi),
    active: scenario === s,
    onToggle: (label) => setDimmed((p) => ({ ...p, [label]: !p[label] })),
  }));

  return (
    <div>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", flexWrap: "wrap", gap: 16 }}>
        <div>
          <Eyebrow color="var(--gold-400)">{d.eyebrow}</Eyebrow>
          <h2 className="dr-title">{d.title}</h2>
          <p className="dr-body">{d.intro}</p>
          <HypotheticalNote text={t.dataroom.hypotheticalNote} />
        </div>
        <div style={{ display: "flex", gap: 8, marginTop: 8 }}>
          <button type="button" className="dr-scenario-tab" onClick={() => { setAssumptions({ ...FUND_DEFAULTS }); setScenario("base"); setDimmed({}); }}>
            {t.dataroom.resetAssumptions}
          </button>
          <button type="button" className="dr-scenario-tab" onClick={() => {
            setFileError(null);
            openDataroomFile(FUND_MODEL_FILE).catch((err) => setFileError({ name: d.downloadXlsx, path: FUND_MODEL_FILE, message: err.message }));
          }}>↓ {d.downloadXlsx}</button>
        </div>
      </div>

      {fileError && <div style={{ marginTop: 16 }}><PendingPanel d={t.dataroom} name={fileError.name} path={fileError.path} /></div>}

      <div className="dr-scenario-tabs" style={{ marginTop: 20 }}>
        {["bear", "base", "bull"].map((s) => (
          <button key={s} type="button" className={"dr-scenario-tab" + (scenario === s ? " active" : "")} onClick={() => setScenario(s)}>
            {FUND_SCENARIOS[s].label}
          </button>
        ))}
      </div>

      <div className="dr-kpi-grid" style={{ margin: "24px 0" }}>
        <Kpi label={d.metrics.netIrr} value={(results.netIrr * 100).toFixed(1) + "%"} />
        <Kpi label={d.metrics.netMoic} value={results.netMoic.toFixed(2) + "x"} />
        <Kpi label={d.metrics.terminalDpi} value={results.terminalDpi.toFixed(2) + "x"} />
        <Kpi label={d.metrics.grossMoic} value={results.grossMoic.toFixed(2) + "x"} />
      </div>

      <div className="dr-panel" style={{ marginBottom: 24 }}>
        <h3 className="dr-panel-title">{d.chartTitle}</h3>
        <p className="dr-muted" style={{ margin: "0 0 20px" }}>{d.chartNote}</p>
        <ForecastLineChart series={chartSeries} labels={chartLabels} cursorIndex={cursor} onCursor={setCursor} dimmed={dimmed} />
      </div>

      <div className="dr-two-col" style={{ marginBottom: 24 }}>
        <div className="dr-panel">
          <h3 className="dr-panel-title">{d.assumptionsTitle}</h3>
          {[
            ["fundSize", d.sliders.fundSize, 100, 400, 10, "M"],
            ["committed", d.sliders.committed, 100, 300, 5, "M"],
            ["deploymentYears", d.sliders.deploymentYears, 3, 7, 1, " yr"],
            ["fundLife", d.sliders.fundLife, 8, 12, 1, " yr"],
            ["mgmtFee", d.sliders.mgmtFee, 0.01, 0.025, 0.0025, ""],
            ["carry", d.sliders.carry, 0.10, 0.25, 0.025, ""],
            ["preferredReturn", d.sliders.preferredReturn, 0.05, 0.12, 0.005, ""],
          ].map(([key, label, min, max, step, unit]) => (
            <div key={key} className="dr-slider-row">
              <label>{label}</label>
              <input type="range" min={min} max={max} step={step} value={assumptions[key]}
                onChange={(e) => setA(key, parseFloat(e.target.value))} />
              <span className="dr-slider-val">
                {key === "mgmtFee" || key === "carry" || key === "preferredReturn"
                  ? (assumptions[key] * 100).toFixed(1) + "%"
                  : assumptions[key] + unit}
              </span>
            </div>
          ))}
        </div>
        <div className="dr-panel">
          <h3 className="dr-panel-title">{d.scenarioCompare}</h3>
          <table className="dr-table">
            <thead>
              <tr>
                <th>Case</th>
                <th style={{ textAlign: "right" }}>Net IRR</th>
                <th style={{ textAlign: "right" }}>Net MOIC</th>
                <th style={{ textAlign: "right" }}>Gross MOIC</th>
              </tr>
            </thead>
            <tbody>
              {["bear", "base", "bull"].map((s) => (
                <tr key={s} style={{ background: scenario === s ? "rgba(197,160,89,0.08)" : "transparent" }}>
                  <td>{FUND_SCENARIOS[s].label}</td>
                  <td className="num">{(allScenarios[s].netIrr * 100).toFixed(1)}%</td>
                  <td className="num">{allScenarios[s].netMoic.toFixed(2)}x</td>
                  <td className="num">{allScenarios[s].grossMoic.toFixed(2)}x</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>

      <div className="dr-panel">
        <h3 className="dr-panel-title">{d.projectionTitle} — {FUND_SCENARIOS[scenario].label}</h3>
        <table className="dr-table">
          <thead>
            <tr>
              <th>{d.cols.year}</th>
              <th style={{ textAlign: "right" }}>{d.cols.called}</th>
              <th style={{ textAlign: "right" }}>{d.cols.nav}</th>
              <th style={{ textAlign: "right" }}>{d.cols.distributed}</th>
              <th style={{ textAlign: "right" }}>{d.cols.tvpi}</th>
              <th style={{ textAlign: "right" }}>{d.cols.dpi}</th>
            </tr>
          </thead>
          <tbody>
            {results.rows.map((r, i) => (
              <tr
                key={r.year}
                style={{ background: cursor === i || r.year === assumptions.currentYear ? "rgba(197,160,89,0.08)" : "transparent", cursor: "pointer" }}
                onClick={() => setCursor(i)}
              >
                <td>{r.vintage}</td>
                <td className="num">{r.called.toFixed(0)}</td>
                <td className="num">{r.nav.toFixed(0)}</td>
                <td className="num">{r.distributed.toFixed(0)}</td>
                <td className="num">{r.tvpi.toFixed(2)}x</td>
                <td className="num">{r.dpi.toFixed(2)}x</td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}

function LNInvestmentModel({ t }) {
  const d = t.dataroom.lnModel;
  const [scenario, setScenario] = useState("base");
  const [assumptions, setAssumptions] = useState({ ...LN_DEFAULTS });
  const [exitMultipleOverride, setExitMultipleOverride] = useState(null);
  const [fileError, setFileError] = useState(null);
  const setA = useCallback((key, val) => setAssumptions((p) => ({ ...p, [key]: val })), []);
  const overrides = exitMultipleOverride != null ? { brazilExitMultiple: exitMultipleOverride } : {};
  const results = useMemo(() => computeLNReturns(assumptions, scenario, overrides), [assumptions, scenario, overrides]);
  const allScenarios = useMemo(() => ({
    bear: computeLNReturns(assumptions, "bear", overrides),
    base: computeLNReturns(assumptions, "base", overrides),
    bull: computeLNReturns(assumptions, "bull", overrides),
  }), [assumptions, overrides]);

  const [sensCagr, setSensCagr] = useState(3);
  const [sensMult, setSensMult] = useState(3);

  const applyHeatmap = (ri, ci) => {
    setSensCagr(ri);
    setSensMult(ci);
    setExitMultipleOverride(LN_SENSITIVITY_MOIC.multiples[ci]);
  };

  return (
    <div>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", flexWrap: "wrap", gap: 16 }}>
        <div>
          <Eyebrow color="var(--gold-400)">{d.eyebrow}</Eyebrow>
          <h2 className="dr-title">{d.title}</h2>
          <p className="dr-body">{d.intro}</p>
          <p className="dr-muted" style={{ marginTop: 10 }}>{d.nestingNote}</p>
          <HypotheticalNote text={t.dataroom.hypotheticalNote} />
        </div>
        <div style={{ display: "flex", gap: 8, marginTop: 8 }}>
          <button type="button" className="dr-scenario-tab" onClick={() => { setAssumptions({ ...LN_DEFAULTS }); setExitMultipleOverride(null); setScenario("base"); }}>
            {t.dataroom.resetAssumptions}
          </button>
          <button type="button" className="dr-scenario-tab" onClick={() => {
            setFileError(null);
            openDataroomFile(LN_MODEL_FILE).catch((err) => setFileError({ name: d.downloadXlsx, path: LN_MODEL_FILE }));
          }}>↓ {d.downloadXlsx}</button>
        </div>
      </div>

      {fileError && <div style={{ marginTop: 16 }}><PendingPanel d={t.dataroom} name={fileError.name} path={fileError.path} /></div>}

      <div className="dr-scenario-tabs" style={{ marginTop: 20 }}>
        {["bear", "base", "bull"].map((s) => (
          <button key={s} type="button" className={"dr-scenario-tab" + (scenario === s ? " active" : "")} onClick={() => setScenario(s)}>
            {LN_SCENARIOS[s].label}
          </button>
        ))}
      </div>

      <div className="dr-kpi-grid" style={{ margin: "24px 0" }}>
        <Kpi label="MOIC (incl. dividends)" value={results.moicWithDivs} />
        <Kpi label="Gross IRR (8yr)" value={results.irr} />
        <Kpi label="Total investment" value={"$" + results.totalInvestment + "M"} />
        <Kpi label="Total proceeds" value={"$" + results.totalWithDivs + "M"} />
      </div>

      <div className="dr-two-col" style={{ marginBottom: 24 }}>
        <div className="dr-panel">
          <h3 className="dr-panel-title">{d.dealStructure}</h3>
          {[
            ["entryMultiple", d.sliders.entryMultiple, 6, 12, 0.5, "x"],
            ["ebitda2024", d.sliders.ebitda2024, 12, 24, 0.1, " R$M"],
            ["stake", d.sliders.stake, 0.15, 0.40, 0.01, ""],
            ["fxEntry", d.sliders.fxEntry, 4.5, 7, 0.1, ""],
            ["fxDepreciation", d.sliders.fxDepreciation, 0, 0.08, 0.005, ""],
            ["intlBudget", d.sliders.intlBudget, 10, 35, 1, "M"],
            ["holdYears", d.sliders.holdYears, 5, 10, 1, " yr"],
          ].map(([key, label, min, max, step, unit]) => (
            <div key={key} className="dr-slider-row">
              <label>{label}</label>
              <input type="range" min={min} max={max} step={step} value={assumptions[key]}
                onChange={(e) => setA(key, parseFloat(e.target.value))} />
              <span className="dr-slider-val">
                {key === "stake" ? (assumptions[key] * 100).toFixed(0) + "%" : assumptions[key] + unit}
              </span>
            </div>
          ))}
          <div className="dr-slider-row">
            <label>{d.sliders.exitMultiple}</label>
            <input type="range" min={6} max={20} step={1}
              value={exitMultipleOverride ?? LN_SCENARIOS[scenario].brazilExitMultiple}
              onChange={(e) => setExitMultipleOverride(parseFloat(e.target.value))} />
            <span className="dr-slider-val">{(exitMultipleOverride ?? LN_SCENARIOS[scenario].brazilExitMultiple) + "x"}</span>
          </div>
        </div>
        <div className="dr-panel">
          <h3 className="dr-panel-title">{d.returnsTitle}</h3>
          <table className="dr-table">
            <tbody>
              {[
                [d.rows.entryEv, "R$" + results.entryEv + "M"],
                [d.rows.costStake, "$" + results.costStakeUsd + "M"],
                [d.rows.exitEbitda, "R$" + results.exitEbitda + "M"],
                [d.rows.ebitdaCagr, results.ebitdaCagr],
                [d.rows.strikeMultiple, results.strikeMult + "x"],
                [d.rows.brazilProceeds, "$" + results.brazilProceeds + "M"],
                [d.rows.optionValue, "$" + results.optionValueUsd + "M"],
                [d.rows.intlProceeds, "$" + results.intlProceeds + "M"],
                [d.rows.dividends, "$" + results.cumulativeDivs + "M"],
              ].map(([k, v]) => (
                <tr key={k}><td>{k}</td><td className="num">{v}</td></tr>
              ))}
            </tbody>
          </table>
          <h3 className="dr-panel-title" style={{ marginTop: 20 }}>{d.ratchetTitle}</h3>
          <table className="dr-table">
            <thead><tr><th>EBITDA CAGR</th><th style={{ textAlign: "right" }}>Strike Multiple</th></tr></thead>
            <tbody>
              {[["<8%", 10], ["8–12%", 9], ["12–16%", 8], ["16–20%", 7], [">20%", 6]].map(([r, m]) => (
                <tr key={r}><td>{r}</td><td className="num">{m}x</td></tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>

      <div className="dr-panel" style={{ marginBottom: 24 }}>
        <h3 className="dr-panel-title">{d.projectionTitle}</h3>
        <table className="dr-table">
          <thead>
            <tr><th>Year</th><th style={{ textAlign: "right" }}>EBITDA (R$M)</th><th style={{ textAlign: "right" }}>EBITDA ($M)</th><th style={{ textAlign: "right" }}>FX</th><th style={{ textAlign: "right" }}>Margin</th></tr>
          </thead>
          <tbody>
            {results.projection.map((r) => (
              <tr key={r.year}>
                <td>{r.year}</td>
                <td className="num">{r.ebitda.toFixed(1)}</td>
                <td className="num">{r.ebitdaUsd.toFixed(1)}</td>
                <td className="num">{r.fx.toFixed(2)}</td>
                <td className="num">{(r.margin * 100).toFixed(1)}%</td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>

      <div className="dr-two-col" style={{ marginBottom: 24 }}>
        <div className="dr-panel">
          <h3 className="dr-panel-title">{d.scenarioCompare}</h3>
          <table className="dr-table">
            <thead><tr><th>Case</th><th style={{ textAlign: "right" }}>MOIC</th><th style={{ textAlign: "right" }}>IRR</th><th style={{ textAlign: "right" }}>Proceeds</th></tr></thead>
            <tbody>
              {["bear", "base", "bull"].map((s) => (
                <tr key={s} style={{ background: scenario === s ? "rgba(197,160,89,0.08)" : "transparent" }}>
                  <td>{LN_SCENARIOS[s].label}</td>
                  <td className="num">{allScenarios[s].moicWithDivs}</td>
                  <td className="num">{allScenarios[s].irr}</td>
                  <td className="num">${allScenarios[s].totalWithDivs}M</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
        <div className="dr-panel">
          <h3 className="dr-panel-title">{d.holdSensitivity}</h3>
          <p className="dr-muted" style={{ marginBottom: 12 }}>{d.holdSensitivityNote}</p>
          <table className="dr-table">
            <thead><tr><th>Hold</th><th style={{ textAlign: "right" }}>MOIC</th><th style={{ textAlign: "right" }}>IRR</th></tr></thead>
            <tbody>
              {LN_HOLD_SENSITIVITY.map((r) => (
                <tr key={r.years}><td>{r.years} years</td><td className="num">{r.moic.toFixed(2)}x</td><td className="num">{r.irr.toFixed(1)}%</td></tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>

      <div className="dr-panel">
        <h3 className="dr-panel-title">{d.sensitivityTitle}</h3>
        <p className="dr-muted" style={{ margin: "0 0 16px" }}>{d.sensitivityNote}</p>
        <div className="dr-heatmap-wrap">
          <table className="dr-heatmap">
            <thead>
              <tr>
                <th>EBITDA CAGR ↓ / Exit →</th>
                {LN_SENSITIVITY_MOIC.multiples.map((m) => <th key={m}>{m}x</th>)}
              </tr>
            </thead>
            <tbody>
              {LN_SENSITIVITY_MOIC.cagrs.map((cagr, ri) => (
                <tr key={cagr}>
                  <th>{(cagr * 100).toFixed(0)}%</th>
                  {LN_SENSITIVITY_MOIC.grid[ri].map((val, ci) => (
                    <td key={ci}
                      className={"dr-heatmap-cell" + (sensCagr === ri && sensMult === ci ? " active" : "")}
                      style={{ background: "rgba(197,160,89," + (val / 8 * 0.45) + ")" }}
                      onClick={() => applyHeatmap(ri, ci)}
                    >{val.toFixed(2)}x</td>
                  ))}
                </tr>
              ))}
            </tbody>
          </table>
        </div>
        <p style={{ fontFamily: "var(--font-sans)", fontSize: "0.75rem", color: "var(--gold-400)", marginTop: 12 }}>
          Selected: {(LN_SENSITIVITY_MOIC.cagrs[sensCagr] * 100).toFixed(0)}% CAGR × {LN_SENSITIVITY_MOIC.multiples[sensMult]}x exit = {LN_SENSITIVITY_MOIC.grid[sensCagr][sensMult].toFixed(2)}x MOIC
          {exitMultipleOverride != null ? " · Exit multiple set to " + exitMultipleOverride + "x" : ""}
        </p>
      </div>
    </div>
  );
}

function ArticleLibrary({ t, initialArticleId }) {
  const d = t.dataroom.articles;
  const articles = useMemo(() => getArticles(), []);
  const [query, setQuery] = useState("");
  const [category, setCategory] = useState("All");
  const [activeId, setActiveId] = useState(() => {
    if (initialArticleId && articles.find((a) => a.id === initialArticleId && a.status === "ready")) return initialArticleId;
    const ready = articles.find((a) => a.status === "ready");
    return ready ? ready.id : null;
  });
  const [signedUrl, setSignedUrl] = useState("");
  const [viewerError, setViewerError] = useState("");

  useEffect(() => {
    if (initialArticleId && articles.find((a) => a.id === initialArticleId && a.status === "ready")) {
      setActiveId(initialArticleId);
    }
  }, [initialArticleId]);

  const filtered = useMemo(() => {
    const q = query.trim().toLowerCase();
    return articles.filter((a) => {
      if (category !== "All" && a.category !== category) return false;
      if (!q) return true;
      return a.title.toLowerCase().includes(q) || a.source.toLowerCase().includes(q) ||
        a.tags.some((tag) => tag.toLowerCase().includes(q));
    });
  }, [articles, query, category]);

  const active = articles.find((a) => a.id === activeId);
  const readyCount = articles.filter((a) => a.status === "ready").length;

  useEffect(() => {
    let cancelled = false;
    setSignedUrl("");
    setViewerError("");
    if (!(active && active.status === "ready")) return undefined;
    createDataroomSignedUrl(active.path)
      .then((url) => { if (!cancelled) setSignedUrl(url); })
      .catch((err) => { if (!cancelled) setViewerError(err.message || String(err)); });
    return () => { cancelled = true; };
  }, [active && active.path, active && active.status]);

  return (
    <div>
      <Eyebrow color="var(--gold-400)">{d.eyebrow}</Eyebrow>
      <h2 className="dr-title">{d.title}</h2>
      <p className="dr-body">{d.intro}</p>

      <div className="dr-article-layout">
        <aside className="dr-article-sidebar">
          <input type="search" value={query} onChange={(e) => setQuery(e.target.value)} placeholder={d.searchPlaceholder}
            className="dr-article-search" />
          <div className="dr-article-filters">
            <button type="button" className={"dr-scenario-tab" + (category === "All" ? " active" : "")} onClick={() => setCategory("All")}>All</button>
            {ARTICLE_CATEGORIES.map((c) => (
              <button key={c} type="button" className={"dr-scenario-tab" + (category === c ? " active" : "")} onClick={() => setCategory(c)}>{c}</button>
            ))}
          </div>
          <div className="dr-article-count dr-mono">{readyCount} / {articles.length} {d.available}</div>
          <ul className="dr-article-list">
            {filtered.length === 0 && <li className="dr-muted" style={{ padding: 12 }}>{d.emptySearch}</li>}
            {filtered.map((a) => (
              <li key={a.id}>
                <button type="button" className={"dr-article-item" + (activeId === a.id ? " active" : "") + (a.status !== "ready" ? " pending" : "")}
                  onClick={() => {
                    if (a.status !== "ready") return;
                    setActiveId(a.id);
                    logRoomEvent("articles", a.path);
                  }}>
                  <span className="dr-article-item-title">{a.title}</span>
                  <span className="dr-article-item-meta">{a.source} · {a.date}</span>
                  {a.status !== "ready" && <span className="dr-tag">{d.pending}</span>}
                </button>
              </li>
            ))}
          </ul>
        </aside>

        <div className="dr-article-main">
          {active && active.status === "ready" ? (
            <>
              <div className="dr-article-header">
                <div>
                  <h3 className="dr-article-heading">{active.title}</h3>
                  <p className="dr-article-meta">{active.source} · {active.date} · {active.category}</p>
                  <p className="dr-article-excerpt">{active.excerpt}</p>
                  <div className="dr-article-tags">
                    {active.tags.map((tag) => <span key={tag} className="dr-tag">{tag}</span>)}
                  </div>
                </div>
                <div style={{ display: "flex", gap: 8, flexShrink: 0 }}>
                  <button type="button" className="dr-scenario-tab" disabled={!signedUrl}
                    onClick={() => signedUrl && window.open(signedUrl, "_blank", "noopener,noreferrer")}>{d.openNew}</button>
                  <a href={signedUrl || "#"} download={active.file} className="dr-scenario-tab"
                    style={{ textDecoration: "none", pointerEvents: signedUrl ? "auto" : "none", opacity: signedUrl ? 1 : 0.5 }}
                    onClick={(e) => { if (!signedUrl) e.preventDefault(); }}>{d.download}</a>
                </div>
              </div>
              {viewerError ? (
                <PendingPanel d={t.dataroom} name={active.title} path={active.path} />
              ) : signedUrl ? (
                <div className="dr-pdf-viewer">
                  <iframe title={active.title} src={signedUrl + "#toolbar=1&navpanes=0"} />
                </div>
              ) : (
                <div className="dr-panel dr-article-empty"><p>…</p></div>
              )}
            </>
          ) : (
            <div className="dr-panel dr-article-empty">
              <p>{d.selectArticle}</p>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

function companyFiles(companyId) {
  const tree = DATAROOM_TREE;
  const folder = tree.find((f) => f.id === "portfolio");
  if (!folder) return [];
  const slug = companyId + "/";
  return folder.files.filter((f) => f.file.indexOf(slug) === 0 || f.file.indexOf(companyId) === 0);
}

function PortfolioView({ t, navigate, initialCompanyId, sectorFilter }) {
  const d = t.dataroom.portfolio;
  const companies = d.companies;
  const startIdx = Math.max(0, companies.findIndex((c) => c.id === initialCompanyId));
  const [active, setActive] = useState(startIdx >= 0 ? startIdx : 0);
  const [filter, setFilter] = useState(sectorFilter || null);

  useEffect(() => {
    if (initialCompanyId) {
      const i = companies.findIndex((c) => c.id === initialCompanyId);
      if (i >= 0) setActive(i);
    }
  }, [initialCompanyId]);

  useEffect(() => {
    if (sectorFilter) setFilter(sectorFilter);
  }, [sectorFilter]);

  const list = filter
    ? companies.filter((c) => c.sector.toLowerCase().includes(filter.toLowerCase()) || (c.verticals || []).some((v) => v.includes(filter.toLowerCase().replace(/\s+/g, "-"))))
    : companies;
  const activeIdx = list.length ? Math.min(active, list.length - 1) : 0;
  const co = list[activeIdx] || companies[0];
  const fin = COMPANY_FINANCIALS[co.id] || { revenue: [1, 2, 3, 4], years: [2022, 2023, 2024, 2025], ebitdaMargin: 0, entryMultiple: 0, exitMultiple: 0 };
  const files = companyFiles(co.id);
  const vertNames = (co.verticals || []).map((id) => {
    const cat = t.dataroom.verticals.categories.find((c) => c.id === id);
    return cat ? { id, name: cat.name } : null;
  }).filter(Boolean);

  return (
    <div>
      <Eyebrow color="var(--gold-400)">{d.eyebrow}</Eyebrow>
      <h2 className="dr-title">{d.title}</h2>
      <p className="dr-body">{d.intro}</p>
      <HypotheticalNote text={t.dataroom.hypotheticalNote} />
      {filter && (
        <button type="button" className="dr-scenario-tab" style={{ marginTop: 12 }} onClick={() => setFilter(null)}>Clear filter: {filter}</button>
      )}
      <div className="dr-portfolio-grid dr-two-col" style={{ marginTop: 24 }}>
        <div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
          {list.map((c, i) => (
            <button key={c.id} type="button" onClick={() => setActive(i)} className={"dr-company-btn" + (co.id === c.id ? " active" : "")}>
              <div style={{ fontFamily: "var(--font-serif)", fontSize: "1rem", color: "var(--alabaster)" }}>{c.name}</div>
              <div style={{ fontFamily: "var(--font-sans)", fontSize: "0.625rem", letterSpacing: "0.1em", textTransform: "uppercase", color: "var(--sapphire-200)", marginTop: 4 }}>
                {c.sector} · {c.country}
              </div>
            </button>
          ))}
        </div>
        <div className="dr-panel">
          <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", gap: 12, flexWrap: "wrap" }}>
            <h3 style={{ fontFamily: "var(--font-display)", fontSize: "1.5rem", color: "var(--alabaster)", margin: 0 }}>{co.name}</h3>
            <span className="dr-tag">{co.status}</span>
          </div>
          <p style={{ fontFamily: "var(--font-serif)", fontSize: "0.9375rem", lineHeight: 1.6, color: "var(--sapphire-200)", margin: "16px 0 0" }}>{co.description}</p>
          {vertNames.length > 0 ? (
            <div style={{ marginTop: 14, display: "flex", flexWrap: "wrap", gap: 8, alignItems: "center" }}>
              <span className="dr-muted">{d.verticalLink}:</span>
              {vertNames.map((v) => (
                <button key={v.id} type="button" className="dr-scenario-tab" onClick={() => navigate("verticals", { vertical: v.id })}>{v.name}</button>
              ))}
            </div>
          ) : (
            <p className="dr-muted" style={{ marginTop: 14 }}>{d.noVertical}</p>
          )}
          <div className="dr-kpi-grid" style={{ marginTop: 24 }}>
            <Kpi label={d.investedLabel} value={co.invested} sub={t.dataroom.illustrativeLabel} />
            <Kpi label={d.ownershipLabel} value={co.ownership} />
            <Kpi label={d.vintageLabel} value={co.vintage} />
            <Kpi label={d.marketLabel} value={co.country} />
            <Kpi label={d.ebitdaLabel} value={fin.ebitdaMargin + "%"} />
            <Kpi label={d.entryLabel} value={fin.entryMultiple + "x"} />
            <Kpi label={d.exitLabel} value={fin.exitMultiple + "x"} />
          </div>
          <div style={{ marginTop: 20 }}>
            <div className="dr-panel-title">{d.revenueTitle}</div>
            <div style={{ display: "flex", justifyContent: "space-between", fontSize: "0.6875rem", color: "var(--sapphire-200)", marginBottom: 6, fontFamily: "var(--font-sans)" }}>
              {fin.years.map((y, i) => <span key={y}>{y}: <span className="dr-mono" style={{ color: "var(--gold-400)" }}>${fin.revenue[i]}M</span></span>)}
            </div>
            <Sparkline data={fin.revenue} />
          </div>
          {files.length > 0 && (
            <div style={{ marginTop: 24 }}>
              <div className="dr-panel-title">{d.relatedDocs}</div>
              <ul className="dr-article-list">
                {files.map((f) => (
                  <li key={f.path}>
                    <button type="button" className="dr-article-item" onClick={() => navigate("documents", { file: f.path })}>
                      <span className="dr-article-item-title">{f.name}</span>
                      <span className="dr-article-item-meta">{f.status === "ready" ? t.dataroom.documents.statusReady : t.dataroom.documents.statusPending}</span>
                    </button>
                  </li>
                ))}
              </ul>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

function AnalyticsView({ t, navigate }) {
  const d = t.dataroom.analytics;
  const [market, setMarket] = useState(0);
  const [hoverBar, setHoverBar] = useState(null);
  const m = t.dataroom.markets.countries[market];
  const holdings = t.dataroom.portfolio.companies.filter((c) => c.country === m.name);

  return (
    <div>
      <Eyebrow color="var(--gold-400)">{d.eyebrow}</Eyebrow>
      <h2 className="dr-title">{d.title}</h2>
      <p className="dr-body">{d.intro}</p>
      <HypotheticalNote text={t.dataroom.hypotheticalNote} />
      <div className="dr-two-col" style={{ margin: "24px 0" }}>
        <div className="dr-panel">
          <h3 className="dr-panel-title">{d.deploymentTitle}</h3>
          <BarChart rows={t.dataroom.performance.deployments.map((r) => ({
            label: r.year, value: r.pct, display: r.amount,
          }))} />
        </div>
        <div className="dr-panel">
          <h3 className="dr-panel-title">{d.geoTitle}</h3>
          {hoverBar && <p className="dr-mono" style={{ fontSize: "0.75rem", color: "var(--gold-400)", margin: "0 0 10px" }}>{hoverBar.label}: {hoverBar.display}</p>}
          <BarChart
            rows={t.dataroom.markets.countries.map((c) => ({
              label: c.name, value: parseInt(c.exposure, 10), display: c.exposure,
            }))}
            activeLabel={m.name}
            onHover={(r) => setHoverBar(r)}
            onLeave={() => setHoverBar(null)}
          />
        </div>
      </div>
      <div className="dr-panel">
        <h3 className="dr-panel-title">{d.marketIntelTitle}</h3>
        <div style={{ display: "flex", flexWrap: "wrap", gap: 8, marginBottom: 16 }}>
          {t.dataroom.markets.countries.map((c, i) => (
            <button key={c.name} type="button" className={"dr-scenario-tab" + (market === i ? " active" : "")} onClick={() => setMarket(i)}>{c.name}</button>
          ))}
        </div>
        <p style={{ fontFamily: "var(--font-serif)", fontSize: "0.9375rem", lineHeight: 1.6, color: "var(--sapphire-200)", margin: "0 0 20px" }}>{m.thesis}</p>
        <div className="dr-kpi-grid">
          <Kpi label={t.dataroom.markets.gdpLabel} value={m.gdp} />
          <Kpi label={t.dataroom.markets.exposureLabel} value={m.exposure} sub={t.dataroom.illustrativeLabel} />
          <Kpi label={t.dataroom.markets.dealsLabel} value={m.deals} />
          <Kpi label={t.dataroom.markets.focusLabel} value={m.focus} />
        </div>
        <h3 className="dr-panel-title" style={{ marginTop: 24 }}>{d.holdingsTitle}</h3>
        {holdings.length === 0 ? (
          <p className="dr-muted">{d.noHoldings}</p>
        ) : (
          <ul className="dr-article-list">
            {holdings.map((c) => (
              <li key={c.id}>
                <button type="button" className="dr-article-item" onClick={() => navigate("scenarios")}>
                  <span className="dr-article-item-title">{c.name}</span>
                  <span className="dr-article-item-meta">{c.sector} · {c.status}</span>
                </button>
              </li>
            ))}
          </ul>
        )}
      </div>
    </div>
  );
}

function DocumentsView({ t, folderId, initialFilePath, initialFilter, accessLevel, heading, navigate }) {
  const d = t.dataroom.documents;
  const tree = DATAROOM_TREE;
  const level = Number(accessLevel || 1);
  const [query, setQuery] = useState("");
  const [statusFilter, setStatusFilter] = useState(initialFilter || "all");
  const [activePath, setActivePath] = useState(initialFilePath || null);
  const [signedUrl, setSignedUrl] = useState("");
  const [viewerError, setViewerError] = useState("");

  const folder = tree.find((f) => f.id === folderId) || tree.find((f) => f.id !== "onboarding") || tree[0];

  useEffect(() => {
    setQuery("");
    setStatusFilter(initialFilter || "all");
  }, [folder && folder.id]);

  useEffect(() => {
    if (!folder) return;
    setActivePath((current) => {
      if (current && folder.files.some((file) => file.path === current)) return current;
      if (initialFilePath && folder.files.some((file) => file.path === initialFilePath)) return initialFilePath;
      return null;
    });
  }, [folder && folder.id, initialFilePath]);

  useEffect(() => {
    if (window.lucide) window.lucide.createIcons();
  }, [folder && folder.id, activePath, level]);

  const folderFiles = folder ? folder.files : [];
  const totalFiles = folderFiles.length;
  const readyFiles = folderFiles.filter((x) => x.status === "ready").length;
  const q = query.trim().toLowerCase();

  const files = folderFiles.filter((f) => {
    if (statusFilter === "ready" && f.status !== "ready") return false;
    if (statusFilter === "pending" && f.status === "ready") return false;
    if (!q) return true;
    return f.name.toLowerCase().includes(q);
  });

  const active = folder
    ? folder.files.map((file) => ({ ...file, folderName: folder.name })).find((f) => f.path === activePath)
    : null;
  const activeLocked = active && !canAccessLevel(level, active.level);
  const hasEmbeds = !!(active && active.embeds && active.embeds.length);
  const onPage = active && active.onPage;
  const external = !!(active && !activeLocked && active.status === "ready" && active.url);
  const isPdf = active && !activeLocked && !hasEmbeds && !onPage && !external && /\.pdf$/i.test(active.file);
  const isSheet = active && !activeLocked && !hasEmbeds && !onPage && !external && /\.(xlsx|xls|csv)$/i.test(active.file);

  useEffect(() => {
    let cancelled = false;
    setSignedUrl("");
    setViewerError("");
    if (!(active && !activeLocked && active.status === "ready" && isPdf)) return undefined;
    createDataroomSignedUrl(active.path)
      .then((url) => { if (!cancelled) setSignedUrl(url); })
      .catch((err) => { if (!cancelled) setViewerError(err.message || String(err)); });
    return () => { cancelled = true; };
  }, [active && active.path, active && active.status, activeLocked, isPdf]);

  return (
    <div>
      <Eyebrow color="var(--gold-400)">{(heading && heading.eyebrow) || d.eyebrow}</Eyebrow>
      <h2 className="dr-title">{(heading && heading.title) || (folder && folder.name) || d.title}</h2>
      <p className="dr-body">{(heading && heading.intro) || (folder && folder.description) || d.intro}</p>

      <div className="dr-panel" style={{ marginTop: 24, display: "flex", flexWrap: "wrap", gap: 16, alignItems: "center" }}>
        <Kpi label={d.statsLabel} value={readyFiles + " / " + totalFiles} sub={d.statsReady} />
        <input type="search" value={query} onChange={(e) => setQuery(e.target.value)} placeholder={d.searchPlaceholder}
          className="dr-article-search" style={{ flex: "1 1 240px" }} />
        <div className="dr-article-filters">
          {[["all", d.filterAll], ["ready", d.filterReady], ["pending", d.filterPending]].map(([id, label]) => (
            <button key={id} type="button" className={"dr-scenario-tab" + (statusFilter === id ? " active" : "")} onClick={() => setStatusFilter(id)}>{label}</button>
          ))}
        </div>
      </div>

      <div className="dr-article-layout" style={{ marginTop: 20 }}>
        <aside className="dr-article-sidebar">
          <ul className="dr-article-list">
            {files.length === 0 && <li className="dr-muted" style={{ padding: 12 }}>{d.emptySearch}</li>}
            {files.map((file) => {
              const locked = !canAccessLevel(level, file.level);
              return (
                <li key={file.path}>
                  <button type="button" className={"dr-article-item" + (activePath === file.path ? " active" : "") + (file.status !== "ready" ? " pending" : "") + (locked ? " locked" : "")}
                    onClick={() => {
                      setActivePath(file.path);
                      if (!locked && file.status === "ready") logRoomEvent(folder.id === "onboarding" ? "onboarding" : "documents", file.path);
                    }}>
                    <span className="dr-article-item-title">
                      {file.name}
                      {locked && <AccessLevelMark level={file.level} />}
                    </span>
                    <span className="dr-article-item-meta">{locked ? ("Level " + file.level) : (file.status === "ready" ? d.statusReady : d.statusPending)}</span>
                  </button>
                </li>
              );
            })}
          </ul>
        </aside>

        <div className="dr-article-main">
          {!active ? (
            <div className="dr-panel dr-article-empty"><p>{d.selectFile}</p></div>
          ) : activeLocked ? (
            <AccessLockPanel t={t} requiredLevel={active.level} />
          ) : active.status !== "ready" ? (
            <PendingPanel d={t.dataroom} name={active.name} folder={active.folderName + " · " + d.formationNote} path={active.path} />
          ) : onPage ? (
            <div className="dr-panel">
              <h3 className="dr-article-heading">{active.name}</h3>
              <p className="dr-muted">Shown on the Team page with the three Fund I partners.</p>
              {navigate && (
                <button type="button" className="dr-scenario-tab" style={{ marginTop: 16 }}
                  onClick={() => navigate(onPage)}>View on Team page</button>
              )}
            </div>
          ) : external ? (
            <>
              <div className="dr-article-header">
                <div>
                  <h3 className="dr-article-heading">{active.name}</h3>
                  <p className="dr-article-meta">{active.folderName}</p>
                </div>
                <a className="dr-scenario-tab" href={active.url} target="_blank" rel="noopener noreferrer">Open</a>
              </div>
              <div className="dr-pdf-viewer">
                <iframe title={active.name} src={active.preview || active.url} allow="autoplay" />
              </div>
            </>
          ) : hasEmbeds ? (
            <>
              <div className="dr-article-header">
                <div>
                  <h3 className="dr-article-heading">{active.name}</h3>
                  <p className="dr-article-meta">{active.folderName}</p>
                </div>
                {active.embeds.length === 1 && active.embeds[0].url && (
                  <a className="dr-scenario-tab" href={active.embeds[0].url} target="_blank" rel="noopener noreferrer">Open</a>
                )}
              </div>
              <div className="dr-embed-stack">
                {active.embeds.map((item) => (
                  <div key={item.name} className="dr-embed-card">
                    {active.embeds.length > 1 && (
                      <div className="dr-embed-card-head">
                        <h4 className="dr-article-heading">{item.name}</h4>
                        {item.url && (
                          <a className="dr-scenario-tab" href={item.url} target="_blank" rel="noopener noreferrer">Open</a>
                        )}
                      </div>
                    )}
                    <div className="dr-pdf-viewer dr-pdf-viewer-embed">
                      <iframe title={item.name} src={item.preview || item.url} allow="autoplay" />
                    </div>
                  </div>
                ))}
              </div>
            </>
          ) : isPdf ? (
            <>
              <div className="dr-article-header">
                <div>
                  <h3 className="dr-article-heading">{active.name}</h3>
                  <p className="dr-article-meta">{active.folderName}</p>
                </div>
                <div style={{ display: "flex", gap: 8 }}>
                  <button type="button" className="dr-scenario-tab" disabled={!signedUrl}
                    onClick={() => signedUrl && window.open(signedUrl, "_blank", "noopener,noreferrer")}>Open</button>
                  <button type="button" className="dr-scenario-tab" disabled={!signedUrl}
                    onClick={() => signedUrl && openDataroomFile(active.path).catch(() => {})}>Download</button>
                </div>
              </div>
              {viewerError ? <PendingPanel d={t.dataroom} name={active.name} path={active.path} /> : signedUrl ? (
                <div className="dr-pdf-viewer"><iframe title={active.name} src={signedUrl + "#toolbar=1&navpanes=0"} /></div>
              ) : <div className="dr-panel dr-article-empty"><p>…</p></div>}
            </>
          ) : (
            <div className="dr-panel">
              <h3 className="dr-article-heading">{active.name}</h3>
              <p className="dr-muted">{isSheet ? d.spreadsheetNote : active.folderName}</p>
              <button type="button" className="dr-scenario-tab" style={{ marginTop: 16 }}
                onClick={() => openDataroomFile(active.path).catch((err) => setViewerError(err.message))}>↓ Download</button>
              {viewerError && <p className="dr-muted" style={{ marginTop: 12 }}>{viewerError}</p>}
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

/* ---------- Shell ---------- */
function mergeDataroom(t) {
  const en = I18N.en.dataroom;
  const loc = t.dataroom || {};
  return {
    ...en, ...loc,
    nav: { ...en.nav, ...(loc.nav || {}) },
    navGroups: { ...en.navGroups, ...(loc.navGroups || {}) },
    opportunity: { ...en.opportunity, ...(loc.opportunity || {}) },
    fundOverview: { ...en.fundOverview, ...(loc.fundOverview || {}) },
    verticals: { ...en.verticals, ...(loc.verticals || {}), categories: (loc.verticals && loc.verticals.categories) || en.verticals.categories },
    firm: { ...en.firm, ...(loc.firm || {}) },
    dashboard: { ...en.dashboard, ...(loc.dashboard || {}) },
    fundReturns: { ...en.fundReturns, ...(loc.fundReturns || {}) },
    returnModel: { ...en.returnModel, ...(loc.returnModel || {}) },
    fundPacing: { ...en.fundPacing, ...(loc.fundPacing || {}) },
    lnModel: { ...en.lnModel, ...(loc.lnModel || {}) },
    articles: { ...en.articles, ...(loc.articles || {}) },
    analytics: { ...en.analytics, ...(loc.analytics || {}) },
    overview: { ...en.overview, ...(loc.overview || {}) },
    documents: { ...en.documents, ...(loc.documents || {}) },
    onboarding: { ...en.onboarding, ...(loc.onboarding || {}) },
    access: {
      ...(en.access || {}),
      ...(loc.access || {}),
      levels: (loc.access && loc.access.levels) || (en.access && en.access.levels) || [],
    },
    portfolio: loc.portfolio || en.portfolio,
    markets: loc.markets || en.markets,
    performance: loc.performance || en.performance,
  };
}

const HEADER_CLOCKS_COMPACT = 1720;
const HEADER_SEARCH_COMPACT = 1640;
const HEADER_ACCOUNT_COMPACT = 1560;

const CITY_CLOCKS = [
  { id: "rio", label: "Rio", title: "Rio de Janeiro", timeZone: "America/Sao_Paulo" },
  { id: "nyc", label: "NYC", title: "New York", timeZone: "America/New_York" },
  { id: "paris", label: "Paris", title: "Paris", timeZone: "Europe/Paris" },
  { id: "london", label: "London", title: "London", timeZone: "Europe/London" },
];

function useMaxWidth(px) {
  const query = "(max-width: " + px + "px)";
  const [matches, setMatches] = useState(() => typeof window !== "undefined" && window.matchMedia(query).matches);
  useEffect(() => {
    const mq = window.matchMedia(query);
    const onChange = () => setMatches(mq.matches);
    onChange();
    mq.addEventListener("change", onChange);
    return () => mq.removeEventListener("change", onChange);
  }, [query]);
  return matches;
}

function cityClockTime(date, timeZone) {
  return new Intl.DateTimeFormat("en-GB", {
    hour: "2-digit",
    minute: "2-digit",
    hourCycle: "h23",
    timeZone,
  }).format(date);
}

function CityClocks() {
  const [now, setNow] = useState(() => new Date());
  const twoOnly = useMaxWidth(HEADER_CLOCKS_COMPACT);
  useEffect(() => {
    const id = setInterval(() => setNow(new Date()), 1000);
    return () => clearInterval(id);
  }, []);
  return (
    <div className="dr-clocks" aria-label={twoOnly ? "Rio and New York" : "Rio, New York, Paris, and London"}>
      <span className="dr-live-dot" aria-hidden="true" />
      {CITY_CLOCKS.map((city, i) => (
        <div key={city.id} className={"dr-clock" + (i >= 2 ? " dr-clock-extra" : "")} title={city.title}>
          <span className="dr-clock-city">{city.label}</span>
          <time className="dr-clock-time dr-mono">{cityClockTime(now, city.timeZone)}</time>
        </div>
      ))}
    </div>
  );
}

function emailInitials(email) {
  const raw = String(email || "").trim();
  const at = raw.indexOf("@");
  const local = (at >= 0 ? raw.slice(0, at) : raw);
  const domain = at >= 0 ? raw.slice(at + 1) : "";
  const parts = local.split(/[._+\-]+/).filter(Boolean);
  let letters = "";
  if (parts.length >= 2) letters = parts[0].charAt(0) + parts[1].charAt(0);
  else if (parts.length === 1) {
    const domainLabel = (domain.split(".")[0] || "");
    letters = parts[0].charAt(0) + (domainLabel.charAt(0) || parts[0].charAt(1) || "");
  }
  return letters.toUpperCase();
}

function HeaderAccountMenu({ userEmail, signedInTitle, onBack, backLabel, onLogout, logoutLabel }) {
  const [open, setOpen] = useState(false);
  const ref = useRef(null);

  useEffect(() => {
    if (!open) return undefined;
    const onPointer = (e) => {
      if (ref.current && !ref.current.contains(e.target)) setOpen(false);
    };
    const onKey = (e) => {
      if (e.key === "Escape") setOpen(false);
    };
    document.addEventListener("pointerdown", onPointer);
    document.addEventListener("keydown", onKey);
    return () => {
      document.removeEventListener("pointerdown", onPointer);
      document.removeEventListener("keydown", onKey);
    };
  }, [open]);

  return (
    <div className="dr-account-menu" ref={ref}>
      <button
        type="button"
        className="dr-account-menu-btn"
        aria-haspopup="menu"
        aria-expanded={open}
        title={signedInTitle}
        onClick={() => setOpen((v) => !v)}
      >
        <span className="dr-header-avatar" aria-hidden="true">{emailInitials(userEmail)}</span>
      </button>
      {open && (
        <div className="dr-account-menu-panel" role="menu">
          {userEmail && <p className="dr-account-menu-email">{userEmail}</p>}
          {onBack && (
            <button
              type="button"
              role="menuitem"
              className="dr-account-menu-item"
              onClick={() => { setOpen(false); onBack(); }}
            >
              {backLabel}
            </button>
          )}
          <button
            type="button"
            role="menuitem"
            className="dr-account-menu-item"
            onClick={() => { setOpen(false); onLogout(); }}
          >
            {logoutLabel}
          </button>
        </div>
      )}
    </div>
  );
}

function RoomHeader({ badge, title, crumb, onBack, backLabel, onLogout, logoutLabel, searchSlot, userEmail, accessLevel, accessLabel }) {
  const accountCompact = useMaxWidth(HEADER_ACCOUNT_COMPACT);
  const access = accessLabel || {};
  const level = Number(accessLevel || 1);
  const levelName = access.levelName || "";
  const levelPill = access.levelPill || "Level {level} · {name}";
  const levelText = levelName
    ? levelPill.replace("{level}", String(level)).replace("{name}", levelName)
    : ("Level " + level);
  const levelShort = levelPill.split(" · ")[0].replace("{level}", String(level));
  const levelTitle = (access.yourLevel || "Your level of access is Level {level} — {name}")
    .replace("{level}", String(level))
    .replace("{name}", levelName);
  const signedInTitle = (access.loggedInAs || "You are logged in as {email}").replace("{email}", userEmail || "");
  return (
    <header className="dr-header">
      <div className="dr-header-brand">
        <img src="assets/logo-mark-gold.png" alt="Folclore" />
        <div className="dr-header-brand-copy">
          <div style={{ fontFamily: "var(--font-sans)", fontSize: "0.625rem", fontWeight: 600, letterSpacing: "0.16em", textTransform: "uppercase", color: "var(--gold-400)" }}>{badge}</div>
          <div style={{ fontFamily: "var(--font-display)", fontSize: "1.2rem", color: "var(--alabaster)" }}>{title}</div>
          {crumb && crumb.length > 0 && (
            <div className="dr-crumb">
              {crumb.map((part, i) => (
                <span key={part.label}>
                  {i > 0 && <span className="dr-crumb-sep"> / </span>}
                  <span className={part.current ? "dr-crumb-current" : undefined}>{part.label}</span>
                </span>
              ))}
            </div>
          )}
        </div>
      </div>
      <div className="dr-header-tools">
        {searchSlot}
        <CityClocks />
        {userEmail && (
          <div className="dr-header-account">
            <span className="dr-level-pill" title={levelTitle}>
              <span className="dr-level-pill-full">{levelText}</span>
              <span className="dr-level-pill-short">{levelShort}</span>
            </span>
            <UpgradeAccessButton access={access} accessLevel={level} />
            {accountCompact ? (
              <HeaderAccountMenu
                userEmail={userEmail}
                signedInTitle={signedInTitle}
                onBack={onBack}
                backLabel={backLabel}
                onLogout={onLogout}
                logoutLabel={logoutLabel}
              />
            ) : (
              <React.Fragment>
                <span className="dr-header-account-rule" aria-hidden="true" />
                <span className="dr-header-user" title={signedInTitle}>
                  <span className="dr-header-avatar" aria-hidden="true">{emailInitials(userEmail)}</span>
                  <span className="dr-header-user-email">{userEmail}</span>
                </span>
                {onBack && (
                  <button type="button" onClick={onBack} className="dr-header-link">{backLabel}</button>
                )}
                <button type="button" onClick={onLogout} className="dr-header-link">{logoutLabel}</button>
              </React.Fragment>
            )}
          </div>
        )}
        {!userEmail && onBack && (
          <button type="button" onClick={onBack} className="dr-scenario-tab">{backLabel}</button>
        )}
        {!userEmail && (
          <button type="button" onClick={onLogout} className="dr-scenario-tab">{logoutLabel}</button>
        )}
      </div>
    </header>
  );
}

function GeneralFundRoom({ t, onBack, onLogout }) {
  useEffect(() => {
    logRoomEvent("general", "general");
  }, []);

  const p = t.portal || I18N.en.portal;
  const d = t.dataroom || I18N.en.dataroom;
  const mission = t.mission || I18N.en.mission;
  const team = t.team || I18N.en.team;
  const contact = t.contact || I18N.en.contact;

  return (
    <div className="dr-app">
      <RoomHeader
        badge={p.generalBadge}
        title={p.generalName}
        onBack={onBack}
        backLabel={p.allRooms}
        onLogout={onLogout}
        logoutLabel={p.signOut || d.logout}
      />
      <main className="dr-main dr-room">
        <Eyebrow color="var(--gold-400)">{p.generalSubtitle}</Eyebrow>
        <h2 className="dr-title">{p.generalTitle}</h2>
        <p className="dr-body">{p.generalIntro}</p>

        <div className="dr-panel" style={{ marginTop: 28 }}>
          <h3 className="dr-panel-title">{mission.eyebrow}</h3>
          <div style={{ display: "flex", flexDirection: "column", gap: "1.15em" }}>
            {mission.body.map((para, i) => (
              <p key={i} style={{
                fontFamily: "var(--font-serif)", margin: 0,
                fontSize: i === 0 ? "clamp(1.15rem, 1.76vw, 1.35rem)" : "1.05rem",
                lineHeight: 1.6, color: i === 0 ? "var(--alabaster)" : "var(--sapphire-200)",
              }}>{para}</p>
            ))}
          </div>
        </div>

        <div className="dr-panel" style={{ marginTop: 20 }}>
          <h3 className="dr-panel-title">{team.eyebrow}</h3>
          <p style={{ fontFamily: "var(--font-serif)", fontSize: "1rem", lineHeight: 1.6, color: "var(--sapphire-200)", margin: "0 0 8px" }}>{team.standfirst}</p>
          <ul className="dr-team-list">
            {team.members.map((m) => (
              <li key={m.name}>
                <span className="dr-team-name">
                  {m.name}
                  {(m.bio || m.linkedin) && (
                    <span className="dr-team-links">
                      {m.bio && <a href={m.bio} target="_blank" rel="noopener noreferrer">{team.bioDownload || "Download biography"}</a>}
                      {m.linkedin && <a href={m.linkedin} target="_blank" rel="noopener noreferrer">LinkedIn</a>}
                    </span>
                  )}
                </span>
                <span className="dr-team-role">{m.role}</span>
                <span className="dr-team-place">{m.place}</span>
              </li>
            ))}
          </ul>
          {(team.advisors || []).length > 0 && (
            <React.Fragment>
              <p style={{
                fontFamily: "var(--font-sans)", fontSize: "0.75rem", fontWeight: 500,
                letterSpacing: "0.14em", textTransform: "uppercase", color: "var(--gold-400)",
                margin: "28px 0 0",
              }}>{team.advisorsLabel || "Advisors"}</p>
              <ul className="dr-team-list">
                {team.advisors.map((m) => (
                  <li key={m.name}>
                    <span className="dr-team-name">
                      {m.name}
                      {(m.bio || m.linkedin) && (
                        <span className="dr-team-links">
                          {m.bio && <a href={m.bio} target="_blank" rel="noopener noreferrer">{team.bioDownload || "Download biography"}</a>}
                          {m.linkedin && <a href={m.linkedin} target="_blank" rel="noopener noreferrer">LinkedIn</a>}
                        </span>
                      )}
                    </span>
                    <span className="dr-team-role">{m.role}</span>
                    <span className="dr-team-place">{m.place}</span>
                  </li>
                ))}
              </ul>
            </React.Fragment>
          )}
        </div>

        <div className="dr-panel" style={{ marginTop: 20 }}>
          <h3 className="dr-panel-title">{contact.eyebrow}</h3>
          <p className="dr-muted" style={{ margin: "0 0 12px" }}>{contact.offices}</p>
          <a href="mailto:hello@folclore.capital" className="dr-email-link">hello@folclore.capital</a>
        </div>

        <p className="dr-disclaimer">{d.disclaimer}</p>
      </main>
    </div>
  );
}

function RoomSearch({ d, onNavigate, accessLevel }) {
  const compact = useMaxWidth(HEADER_SEARCH_COMPACT);
  const [q, setQ] = useState("");
  const [open, setOpen] = useState(false);
  const [expanded, setExpanded] = useState(false);
  const inputRef = useRef(null);
  const wrapRef = useRef(null);
  const level = Number(accessLevel || 1);
  const hits = useMemo(() => {
    const query = q.trim().toLowerCase();
    if (!query) return [];
    const out = [];
    if (canAccessLevel(level, sectionAccessLevel("fund-overview"))) {
      const page = d.fundOverview || {};
      const blob = [d.nav.fundOverview, page.lead, page.execSummaryTitle, "fund terms", "executive summary", "snapshot"]
        .filter(Boolean)
        .join(" ")
        .toLowerCase();
      if (blob.includes(query)) {
        out.push({ type: "Fund", label: d.nav.fundOverview, go: () => onNavigate("fund-overview") });
      }
    }
    if (canAccessLevel(level, sectionAccessLevel("firm"))) {
      [["Nick Walker", "Managing partner"], ["Dolly Moorhead", "Head of investor relations"], ["Henrique Lamim", "Partner"], ["Camila Pierotti", "Advisor"], ["Denis O’Flynn O’Brien", "Advisor"], ["Michele Levy", "Advisor"]].forEach(([label, type]) => {
        const fold = (s) => s.toLowerCase().replace(/['’]/g, "");
        if (fold(label).includes(fold(query)) || fold(type).includes(fold(query))) {
          out.push({ type: "Team", label: label, go: () => onNavigate("firm") });
        }
      });
    }
    if (canAccessLevel(level, sectionAccessLevel("verticals"))) {
      d.verticals.categories.forEach((c) => {
        if (c.name.toLowerCase().includes(query) || c.blurb.toLowerCase().includes(query) || c.id.replace(/-/g, " ").includes(query)) {
          out.push({ type: "Vertical", label: c.name, go: () => onNavigate("verticals", { vertical: c.id }) });
        }
      });
    }
    if (canAccessLevel(level, sectionAccessLevel("cases")) && typeof CASE_STUDIES !== "undefined") {
      if (query.includes("case") || query.includes("benchmark") || "case studies".includes(query)) {
        out.push({ type: "Cases", label: "Case studies overview", go: () => onNavigate("cases") });
      }
      if (query.includes("compare") || "side by side".includes(query)) {
        out.push({ type: "Cases", label: "Compare two", go: () => onNavigate("cases", { caseSlug: "compare", a: "lvmh", b: "ferragamo" }) });
      }
      CASE_STUDIES.houses.forEach((h) => {
        if (h.name.toLowerCase().includes(query) || h.role.toLowerCase().includes(query) || h.id.includes(query)) {
          out.push({ type: "Case", label: h.n + " · " + h.name, go: () => onNavigate("cases", { caseSlug: h.id }) });
        }
      });
      if ("tiffany's".includes(query)) {
        out.push({ type: "Case", label: "06 · Tiffany's", go: () => onNavigate("cases", { caseSlug: "tiffany" }) });
      }
    }
    if (canAccessLevel(level, sectionAccessLevel("scenarios"))) {
      if (level >= 2 && typeof PIPELINE_HOUSES !== "undefined") {
        PIPELINE_HOUSES.forEach((h) => {
          const hay = ("project " + h.cn + " " + h.v + " " + h.city + " " + h.ctry).toLowerCase();
          const houseOpen = level >= 4 && h.name.toLowerCase().includes(query);
          if (hay.includes(query) || houseOpen) {
            out.push({
              type: "Pipeline",
              label: level >= 4 ? ("Project " + h.cn + " · " + h.name) : ("Project " + h.cn),
              go: () => onNavigate("scenarios", { company: h.id }),
            });
          }
        });
      } else if (query.includes("pipeline") || query.includes("deal") || query.includes("funnel") || query.includes("screened")) {
        out.push({ type: "Pipeline", label: d.nav.pipeline || "Pipeline", go: () => onNavigate("scenarios") });
      }
    }
    if (canAccessLevel(level, sectionAccessLevel("articles"))) {
      getArticles().filter((a) => a.status === "ready").forEach((a) => {
        if (a.title.toLowerCase().includes(query) || a.tags.some((t) => t.toLowerCase().includes(query))) {
          out.push({ type: "Article library", label: a.title, go: () => onNavigate("articles", { article: a.id }) });
        }
      });
    }
    if (canAccessLevel(level, sectionAccessLevel("documents"))) {
      DATAROOM_TREE.forEach((folder) => {
        if (folder.id === "onboarding") return;
        folder.files.forEach((f) => {
          if (!canAccessLevel(level, f.level)) return;
          if (f.name.toLowerCase().includes(query) || folder.name.toLowerCase().includes(query)) {
            out.push({ type: "Material", label: f.name, go: () => onNavigate("documents", { folder: folder.id, file: f.path }) });
          }
        });
      });
    }
    if (canAccessLevel(level, sectionAccessLevel("onboarding"))) {
      const folder = DATAROOM_TREE.find((f) => f.id === "onboarding");
      if (folder) {
        folder.files.forEach((f) => {
          if (!canAccessLevel(level, f.level)) return;
          if (f.name.toLowerCase().includes(query) || folder.name.toLowerCase().includes(query)) {
            out.push({ type: "LP onboarding", label: f.name, go: () => onNavigate("onboarding", { file: f.path }) });
          }
        });
      }
    }
    return out.slice(0, 8);
  }, [q, d, onNavigate, level]);

  useEffect(() => {
    if (!compact) setExpanded(false);
  }, [compact]);

  useEffect(() => {
    if (compact && expanded && inputRef.current) inputRef.current.focus();
  }, [compact, expanded]);

  useEffect(() => {
    if (!compact || !expanded) return undefined;
    const onKey = (e) => {
      if (e.key === "Escape") {
        setExpanded(false);
        setOpen(false);
      }
    };
    const onPointer = (e) => {
      if (wrapRef.current && wrapRef.current.contains(e.target)) return;
      setOpen(false);
      if (!q.trim()) setExpanded(false);
    };
    document.addEventListener("keydown", onKey);
    document.addEventListener("pointerdown", onPointer);
    return () => {
      document.removeEventListener("keydown", onKey);
      document.removeEventListener("pointerdown", onPointer);
    };
  }, [compact, expanded, q]);

  const fieldHidden = compact && !expanded;

  return (
    <div
      className={"dr-search-wrap" + (compact ? " is-compact" : "") + (expanded ? " is-open" : "")}
      ref={wrapRef}
    >
      {compact && (
        <button
          type="button"
          className="dr-search-loupe"
          aria-label={d.searchPlaceholder || "Search"}
          aria-expanded={expanded}
          onClick={() => {
            if (expanded) {
              setExpanded(false);
              setOpen(false);
            } else {
              setExpanded(true);
              if (q.trim()) setOpen(true);
            }
          }}
        >
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
            <circle cx="11" cy="11" r="8" />
            <path d="m21 21-4.3-4.3" />
          </svg>
        </button>
      )}
      <input
        ref={inputRef}
        type="search"
        className="dr-header-search"
        placeholder={d.searchPlaceholder}
        value={q}
        aria-hidden={fieldHidden ? true : undefined}
        tabIndex={fieldHidden ? -1 : 0}
        onChange={(e) => { setQ(e.target.value); setOpen(true); }}
        onFocus={() => setOpen(true)}
        onBlur={() => setTimeout(() => setOpen(false), 180)}
      />
      {open && q.trim() && !fieldHidden && (
        <ul className="dr-search-results">
          {hits.length === 0 && <li className="dr-muted" style={{ padding: "10px 12px" }}>{d.searchEmpty}</li>}
          {hits.map((h, i) => (
            <li key={i}>
              <button type="button" onMouseDown={(e) => { e.preventDefault(); h.go(); setQ(""); setOpen(false); setExpanded(false); }}>
                <span className="dr-search-type">{h.type}</span>
                <span>{h.label}</span>
              </button>
            </li>
          ))}
        </ul>
      )}
    </div>
  );
}

function DataRoom({ t, theme, onBack, onLogout, accessLevel, userEmail }) {
  const initial = parseFundHash();
  const [section, setSection] = useState(initial.section);
  const [verticalSlug, setVerticalSlug] = useState(initial.vertical);
  const [caseSlug, setCaseSlug] = useState(initial.caseSlug);
  const [pacingView, setPacingView] = useState(initial.pacingView || "portfolio");
  const [casePairA, setCasePairA] = useState(initial.a);
  const [casePairB, setCasePairB] = useState(initial.b);
  const [articleId, setArticleId] = useState(initial.article);
  const [companyId, setCompanyId] = useState(initial.company);
  const [folderId, setFolderId] = useState(initial.folder);
  const [filePath, setFilePath] = useState(initial.file);
  const [sectorFilter, setSectorFilter] = useState(null);
  const [secondaryOpen, setSecondaryOpen] = useState(() => SECONDARY_VERTICAL_IDS.indexOf(initial.vertical) >= 0);
  const [documentsOpen, setDocumentsOpen] = useState(() => initial.section === "documents");
  const [openCaseRegions, setOpenCaseRegions] = useState(() => {
    const key = caseRegionKey(initial.caseSlug);
    return key ? { [key]: true } : {};
  });
  const d = useMemo(() => mergeDataroom(t), [t]);
  const p = t.portal || I18N.en.portal;
  const level = Number(accessLevel || 1);
  const access = d.access || I18N.en.dataroom.access || {};
  const currentMeta = levelMeta(access, level);

  const navigate = useCallback((sec, opts) => {
    opts = opts || {};
    const target = resolveRoomTarget(sec, opts);
    setSection(target.section);
    setVerticalSlug(opts.vertical || null);
    setCaseSlug(target.section === "cases" ? (opts.caseSlug || null) : null);
    setPacingView(target.section === "fund-pacing" ? (opts.pacingView || "portfolio") : "portfolio");
    setCasePairA(opts.a || null);
    setCasePairB(opts.b || null);
    setArticleId(opts.article || null);
    setCompanyId(opts.company || null);
    setFolderId(target.folder);
    setFilePath(target.file);
    if (opts.sector) setSectorFilter(opts.sector);
    writeFundHash(target.section, Object.assign({}, opts, { folder: target.folder, file: target.file }));
    window.scrollTo(0, 0);
    const main = document.querySelector(".dr-main");
    if (main) main.scrollTop = 0;
  }, []);

  useEffect(() => {
    const sync = () => {
      const h = parseFundHash();
      setSection(h.section);
      setVerticalSlug(h.vertical);
      setCaseSlug(h.caseSlug);
      setPacingView(h.pacingView || "portfolio");
      setCasePairA(h.a);
      setCasePairB(h.b);
      setArticleId(h.article);
      setCompanyId(h.company);
      setFolderId(h.folder);
      setFilePath(h.file);
    };
    window.addEventListener("hashchange", sync);
    if (!window.location.hash || window.location.hash === "#fund-i") {
      writeFundHash("opportunity");
    }
    return () => window.removeEventListener("hashchange", sync);
  }, []);

  useEffect(() => {
    logRoomEvent(section, "fund-i");
  }, [section]);

  useEffect(() => {
    if (window.lucide) window.lucide.createIcons();
  }, [section, verticalSlug, caseSlug, level]);

  useEffect(() => {
    if (verticalSlug && SECONDARY_VERTICAL_IDS.indexOf(verticalSlug) >= 0) setSecondaryOpen(true);
  }, [verticalSlug]);

  useEffect(() => {
    if (section === "documents") setDocumentsOpen(true);
  }, [section]);

  useEffect(() => {
    const key = caseRegionKey(caseSlug);
    if (!key) return;
    setOpenCaseRegions((prev) => (prev[key] ? prev : Object.assign({}, prev, { [key]: true })));
  }, [caseSlug]);

  const tt = { ...t, dataroom: d };
  const crumb = roomCrumb(d, section, verticalSlug, caseSlug, pacingView, folderId);
  const selectValue = navSelectValue(section, verticalSlug, caseSlug, folderId);
  const required = sectionAccessLevel(section);
  const sectionLocked = !canAccessLevel(level, required);

  const onNavSelect = (value) => {
    if (value.indexOf("verticals:") === 0) navigate("verticals", { vertical: value.slice("verticals:".length) });
    else if (value.indexOf("documents:") === 0) navigate("documents", { folder: value.slice("documents:".length) });
    else if (value === "cases") navigate("cases");
    else if (value.indexOf("cases:") === 0) {
      const slug = value.slice("cases:".length);
      if (slug === "compare") navigate("cases", { caseSlug: "compare", a: "lvmh", b: "ferragamo" });
      else navigate("cases", { caseSlug: slug });
    }
    else navigate(value);
  };

  const navRequired = (item) => sectionAccessLevel(item.section);

  let body = null;
  if (sectionLocked) {
    body = <AccessLockPanel t={tt} requiredLevel={required} />;
  } else if (section === "opportunity") body = <OpportunityView t={tt} navigate={navigate} accessLevel={level} />;
  else if (section === "fund-overview") body = <FundOverviewView t={tt} />;
  else if (section === "strategy") body = <StrategyView t={tt} navigate={navigate} />;
  else if (section === "cases") body = <CasesView navigate={navigate} caseSlug={caseSlug} pairA={casePairA} pairB={casePairB} />;
  else if (section === "return-model") body = <ReturnModelView t={tt} navigate={navigate} />;
  else if (section === "fund-pacing") body = (
    <FundPacingView
      t={tt}
      navigate={navigate}
      view={pacingView || "portfolio"}
      onViewChange={(nextView) => {
        setPacingView(nextView);
        writeFundHash("fund-pacing", { pacingView: nextView });
      }}
    />
  );
  else if (section === "verticals") body = <VerticalsView t={tt} navigate={navigate} verticalSlug={verticalSlug} accessLevel={level} />;
  else if (section === "scenarios") body = (
    typeof PipelinePage === "function"
      ? <PipelinePage t={tt} accessLevel={level} initialCompanyId={companyId} />
      : <PortfolioView t={tt} navigate={navigate} initialCompanyId={companyId} sectorFilter={sectorFilter} />
  );
  else if (section === "markets") body = (
    <div>
      <button type="button" className="dr-back-link" onClick={() => navigate("strategy")}>{d.nav.strategy}</button>
      <AnalyticsView t={tt} navigate={navigate} />
    </div>
  );
  else if (section === "returns") body = (
    <div>
      <button type="button" className="dr-back-link" onClick={() => navigate("strategy")}>{d.nav.strategy}</button>
      <FundReturnsModel t={tt} />
    </div>
  );
  else if (section === "models") body = (
    <div>
      <button type="button" className="dr-back-link" onClick={() => navigate("verticals", { vertical: "swimwear" })}>Swimwear</button>
      <LNInvestmentModel t={tt} />
    </div>
  );
  else if (section === "firm") body = <FirmView navigate={navigate} accessLevel={level} userEmail={userEmail} />;
  else if (section === "media") body = <MediaView t={tt} navigate={navigate} />;
  else if (section === "questions") body = <QuestionsView t={tt} navigate={navigate} />;
  else if (section === "articles") body = <ArticleLibrary t={tt} initialArticleId={articleId} />;
  else if (section === "documents") body = <DocumentsView t={tt} folderId={folderId || "offering"} initialFilePath={filePath} accessLevel={level} navigate={navigate} />;
  else if (section === "onboarding") body = (
    <DocumentsView
      t={tt}
      folderId="onboarding"
      initialFilePath={filePath}
      accessLevel={level}
      heading={{
        eyebrow: d.onboarding.eyebrow,
        title: d.onboarding.title,
        intro: d.onboarding.intro,
      }}
    />
  );
  else body = <OpportunityView t={tt} navigate={navigate} accessLevel={level} />;

  return (
    <div className="dr-app">
      <RoomHeader
        badge={d.badge}
        title={d.fundName}
        crumb={crumb}
        onBack={onBack}
        backLabel={p.allRooms}
        onLogout={onLogout}
        logoutLabel={p.signOut || d.logout}
        userEmail={userEmail}
        accessLevel={level}
        accessLabel={{
          ...access,
          levelName: currentMeta.name,
        }}
        searchSlot={<RoomSearch d={d} onNavigate={navigate} accessLevel={level} />}
      />

      <div className="dr-layout">
        <nav className="dr-nav" aria-label="Data room">
          <div className="dr-nav-mobile">
            <label className="dr-nav-mobile-label" htmlFor="dr-section-select">Section</label>
            <select
              id="dr-section-select"
              className="dr-nav-select"
              value={selectValue}
              onChange={(e) => onNavSelect(e.target.value)}
            >
              {ROOM_NAV.map((g) => (
                <optgroup key={g.id} label={d.navGroups[g.labelKey]}>
                  {g.items.flatMap((item) => {
                    const rows = item.kind === "collapse"
                      ? [{ kind: "sub", key: item.key, labelKey: item.labelKey }].concat(item.items)
                      : [item];
                    return rows.map((row) => {
                      if (row.kind === "sub") {
                        return <option key={row.key} disabled value={"sub-" + row.key}>{d.navGroups[row.labelKey]}</option>;
                      }
                      const value = navItemValue(row);
                      const need = navRequired(row);
                      const locked = !canAccessLevel(level, need);
                      const label = navItemLabel(d, row);
                      return <option key={row.key} value={value}>{locked ? (label + " · Level " + need) : label}</option>;
                    });
                  })}
                </optgroup>
              ))}
            </select>
          </div>
          <div className="dr-nav-desktop">
            {ROOM_NAV.map((g) => {
              const collapsible = g.id === "secondary" || g.id === "documents";
              const open = g.id === "secondary" ? secondaryOpen : g.id === "documents" ? documentsOpen : true;
              const groupActive = collapsible && g.items.some((item) => navItemActive(item, section, verticalSlug, caseSlug, folderId));
              const listId = g.id === "documents" ? "dr-nav-documents-list" : "dr-nav-secondary-list";
              const renderNavButton = (item, indented) => {
                const label = navItemLabel(d, item);
                const active = navItemActive(item, section, verticalSlug, caseSlug, folderId);
                const need = navRequired(item);
                const locked = !canAccessLevel(level, need);
                return (
                  <button
                    key={item.key}
                    type="button"
                    className={"dr-nav-btn" + (active ? " active" : "") + (locked ? " locked" : "") + (item.caseN && !indented ? " nested" : "") + (indented ? " indented" : "")}
                    aria-current={active ? "page" : undefined}
                    onClick={() => navigate(item.section, navItemOpts(item))}
                  >
                    <span className="dr-nav-btn-label">
                      {item.caseN && <span className="dr-nav-case-n">{item.caseN}</span>}
                      <span>{label}</span>
                    </span>
                    {locked && <AccessLevelMark level={need} />}
                  </button>
                );
              };
              const items = g.items.map((item) => {
                if (item.kind === "collapse") {
                  const regionOpen = !!openCaseRegions[item.key];
                  const regionActive = item.items.some((child) => navItemActive(child, section, verticalSlug, caseSlug, folderId));
                  return (
                    <div key={item.key} className={"dr-nav-region" + (regionOpen ? " open" : "")}>
                      <button
                        type="button"
                        className={"dr-nav-region-toggle" + (regionActive ? " has-active" : "")}
                        aria-expanded={regionOpen}
                        aria-controls={"dr-nav-" + item.key}
                        onClick={() => setOpenCaseRegions((prev) => Object.assign({}, prev, { [item.key]: !prev[item.key] }))}
                      >
                        <span>{d.navGroups[item.labelKey]}</span>
                        <span className="dr-nav-chevron" aria-hidden="true" />
                      </button>
                      {regionOpen && (
                        <div id={"dr-nav-" + item.key} className="dr-nav-collapse-list">
                          {item.items.map((child) => renderNavButton(child, true))}
                        </div>
                      )}
                    </div>
                  );
                }
                if (item.kind === "sub") {
                  return <div key={item.key} className="dr-nav-sublabel">{d.navGroups[item.labelKey]}</div>;
                }
                return renderNavButton(item, collapsible);
              });
              return (
                <div key={g.id} className={"dr-nav-group" + (g.id === "documents" ? " dr-nav-group-directory" : "") + (g.id === "onboarding" ? " dr-nav-group-final" : "") + (collapsible ? " dr-nav-group-collapse" : "") + (collapsible && open ? " open" : "")}>
                  {collapsible ? (
                    <button
                      type="button"
                      className={"dr-nav-group-toggle" + (groupActive ? " has-active" : "")}
                      aria-expanded={open}
                      aria-controls={listId}
                      onClick={() => (g.id === "documents" ? setDocumentsOpen((v) => !v) : setSecondaryOpen((v) => !v))}
                    >
                      <span>{d.navGroups[g.labelKey]}</span>
                      <span className="dr-nav-chevron" aria-hidden="true" />
                    </button>
                  ) : (
                    <div className="dr-nav-group-label">{d.navGroups[g.labelKey]}</div>
                  )}
                  {collapsible ? (
                    open && <div id={listId} className="dr-nav-collapse-list">{items}</div>
                  ) : items}
                </div>
              );
            })}
          </div>
          <div className="dr-nav-contact">
            <p className="dr-nav-contact-label">Investor Relations</p>
            <p className="dr-nav-contact-name">Dolly Moorhead</p>
            <a className="dr-nav-contact-mail" href="mailto:dolly.moorheard@folclore.capital">dolly.moorheard@folclore.capital</a>
            <p className="dr-nav-contact-label">Support</p>
            <a className="dr-nav-contact-mail" href="mailto:support@folclore.capital">support@folclore.capital</a>
          </div>
        </nav>
        <main
          className={
            "dr-main" +
            (section === "firm" && !sectionLocked ? " dr-main-team dr-main-rail" : "") +
            (section === "return-model" && !sectionLocked ? " dr-main-rail" : "")
          }
        >
          {body}
          {section !== "verticals" && section !== "cases" && !sectionLocked && <p className="dr-disclaimer">{d.disclaimer}</p>}
        </main>
      </div>
      <MobileRoomNotice copy={d.mobileNotice} />
    </div>
  );
}

function resolveRoomTarget(sec, opts) {
  opts = opts || {};
  const fileFolder = opts.file ? folderIdForFile(opts.file) : null;
  let section = sec;
  let folder = opts.folder || fileFolder || null;
  let file = opts.file || null;
  if (folder === "onboarding" || fileFolder === "onboarding") {
    section = "onboarding";
    folder = null;
    if (fileFolder !== "onboarding") file = null;
  } else if (section === "documents") {
    if (!folder || !DOCUMENT_DIRECTORY_ITEMS.some((item) => item.folder === folder)) folder = "offering";
    if (file && fileFolder && fileFolder !== folder) file = null;
  } else {
    folder = null;
  }
  return { section: section, folder: folder, file: file };
}

function navItemLabel(d, item) {
  if (item.label) return item.label;
  if (item.vertical) {
    return (d.verticals.categories.find((c) => c.id === item.vertical) || {}).name || item.key;
  }
  if (item.section === "cases" && item.caseSlug && item.caseSlug !== "compare") {
    const h = typeof getCaseHouse === "function" ? getCaseHouse(item.caseSlug) : null;
    return h ? h.name : (d.nav[item.key] || item.caseSlug);
  }
  return d.nav[item.key] || item.key;
}

function navItemValue(item) {
  if (item.folder) return "documents:" + item.folder;
  if (item.vertical) return "verticals:" + item.vertical;
  if (item.section === "cases") {
    if (!item.caseSlug) return "cases";
    return "cases:" + item.caseSlug;
  }
  return item.section;
}

function navItemOpts(item) {
  if (item.folder) return { folder: item.folder };
  if (item.vertical) return { vertical: item.vertical };
  if (item.section === "cases") {
    if (!item.caseSlug) return {};
    if (item.caseSlug === "compare") return { caseSlug: "compare", a: "lvmh", b: "ferragamo" };
    return { caseSlug: item.caseSlug };
  }
  return undefined;
}

function roomCrumb(d, section, verticalSlug, caseSlug, pacingView, folderId) {
  if (section === "fund-pacing") {
    const viewLabels = {
      portfolio: d.nav.fundPacing || "Return Model (/w Pacing)",
      "j-curve": "Pacing & J-Curve",
      sensitivity: "Sensitivity",
      reading: "Reading",
    };
    const view = pacingView && pacingView !== "portfolio" ? pacingView : null;
    if (view) {
      return [
        { label: "Fund I" },
        { label: d.nav.fundPacing || "Return Model (w/ Pacing)" },
        { label: viewLabels[view] || view, current: true },
      ];
    }
    return [
      { label: "Fund I" },
      { label: d.nav.fundPacing || "Return Model (w/ Pacing)", current: true },
    ];
  }
  if (section === "verticals") {
    const cat = d.verticals.categories.find((c) => c.id === verticalSlug);
    if (cat) {
      return [
        { label: "Strategy" },
        { label: "Verticals" },
        { label: cat.name, current: true },
      ];
    }
    return [
      { label: "Strategy" },
      { label: "Verticals", current: true },
    ];
  }
  if (section === "cases") {
    if (caseSlug === "compare") {
      return [
        { label: "Fund I" },
        { label: d.nav.casesOverview || "Case Studies" },
        { label: d.nav.casesCompare || "Compare Two", current: true },
      ];
    }
    if (caseSlug) {
      const h = typeof getCaseHouse === "function" ? getCaseHouse(caseSlug) : null;
      const name = caseSlug === "tiffany" ? "Tiffany's" : (h ? h.name : caseSlug);
      return [
        { label: "Fund I" },
        { label: d.nav.casesOverview || "Case Studies" },
        { label: name, current: true },
      ];
    }
    return [
      { label: "Fund I" },
      { label: d.nav.casesOverview || "Case Studies", current: true },
    ];
  }
  if (section === "documents") {
    const folder = (typeof DATAROOM_TREE !== "undefined" && DATAROOM_TREE.find((f) => f.id === folderId)) || null;
    const short = DOCUMENT_DIRECTORY_ITEMS.find((item) => item.folder === folderId);
    return [
      { label: "Fund I" },
      { label: d.navGroups.documentsDirectory || "Fund Documents Directory" },
      { label: short ? short.label : (folder ? folder.name : d.nav.documents), current: true },
    ];
  }
  if (section === "onboarding") {
    return [
      { label: "Fund I" },
      { label: d.nav.onboarding || "LP Onboarding", current: true },
    ];
  }
  const labels = {
    opportunity: d.nav.overview,
    "fund-overview": d.nav.fundOverview,
    documents: d.nav.documents,
    onboarding: d.nav.onboarding,
    firm: d.nav.team,
    strategy: d.nav.strategy,
    "return-model": d.nav.returnModel,
    "fund-pacing": d.nav.fundPacing,
    returns: d.nav.returns,
    markets: d.nav.markets,
    models: d.nav.models,
    scenarios: d.nav.pipeline,
    media: d.nav.media,
    questions: d.nav.questions,
    articles: d.nav.articles,
  };
  return [
    { label: "Fund I" },
    { label: labels[section] || section, current: true },
  ];
}

function navItemActive(item, section, verticalSlug, caseSlug, folderId) {
  if (item.folder) return section === "documents" && folderId === item.folder;
  if (item.section === "onboarding") return section === "onboarding";
  if (item.vertical) {
    if (section === "models" && item.vertical === "swimwear") return true;
    return section === "verticals" && verticalSlug === item.vertical;
  }
  if (item.section === "cases") {
    if (section !== "cases") return false;
    const slug = caseSlug || null;
    if (!item.caseSlug) return !slug;
    return slug === item.caseSlug;
  }
  if (item.section === "strategy" && (section === "strategy" || section === "returns" || section === "markets")) return true;
  return section === item.section;
}

function navSelectValue(section, verticalSlug, caseSlug, folderId) {
  if (section === "documents") return "documents:" + (folderId || "offering");
  if (section === "onboarding") return "onboarding";
  if (section === "verticals" && verticalSlug) return "verticals:" + verticalSlug;
  if (section === "cases") {
    if (caseSlug) return "cases:" + caseSlug;
    return "cases";
  }
  if (section === "returns" || section === "markets") return "strategy";
  if (section === "models") return "verticals:swimwear";
  return section;
}

Object.assign(window, {
  DataRoom,
  GeneralFundRoom,
  parseFundHash,
  writeFundHash,
  FUND_I_SECTION_LEVELS,
  APPOINTMENT_URL,
  NDA_COPY_URL,
  AccessLevelMark,
  AccessActionButton,
  NdaCopyLink,
  canAccessLevel,
  accessCopy,
});
