/* TickProof verification page — presentational components.
   All pieces are pure/presentational; data + orchestration live in app.jsx.
   Reuses site.css classes (.proof, .dcal, .vbadge, .ptag, .btn) + verify.css. */

/* ---------------- icons (Lucide, 1.5 stroke) ---------------- */
const I = {
  check: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M20 6 9 17l-5-5"/></svg>,
  shield: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10Z"/><path d="m9 12 2 2 4-4"/></svg>,
  lock: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" {...p}><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>,
  refresh: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M3 12a9 9 0 0 1 15-6.7L21 8"/><path d="M21 3v5h-5"/><path d="M21 12a9 9 0 0 1-15 6.7L3 16"/><path d="M3 21v-5h5"/></svg>,
  info: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" {...p}><circle cx="12" cy="12" r="10"/><path d="M12 16v-4M12 8h.01"/></svg>,
  link: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M10 13a5 5 0 0 0 7.5.5l3-3a5 5 0 0 0-7-7l-1.7 1.7"/><path d="M14 11a5 5 0 0 0-7.5-.5l-3 3a5 5 0 0 0 7 7l1.7-1.7"/></svg>,
  share: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" {...p}><circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/><path d="m8.6 13.5 6.8 4M15.4 6.5 8.6 10.5"/></svg>,
  x: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M18 6 6 18M6 6l12 12"/></svg>,
  download: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><path d="M7 10l5 5 5-5M12 15V3"/></svg>,
  cleft: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="m15 18-6-6 6-6"/></svg>,
  cright: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="m9 18 6-6-6-6"/></svg>,
  ext: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M15 3h6v6M10 14 21 3M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/></svg>,
  xlogo: (p) => <svg viewBox="0 0 24 24" fill="currentColor" {...p}><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24h-6.66l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231 5.45-6.231Zm-1.161 17.52h1.833L7.084 4.126H5.117L17.083 19.77Z"/></svg>,
  copy: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" {...p}><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>,
};

const TYPE_MAP = {
  live: { cls: "live", label: "Live funded", short: "Live" },
  eval: { cls: "eval", label: "Evaluation", short: "Eval" },
  sim:  { cls: "sim",  label: "Paper", short: "Paper" },
};

const BrandMark = () => (
  <div className="proof-brand"><span className="m"></span><span className="wm">TICK<span className="ac">PROOF</span></span></div>
);

/* ---------------- 1 · status ribbon ---------------- */
function StatusBar({ type, broker, refreshed, onHow }) {
  const t = TYPE_MAP[type];
  return (
    <div className="vbar">
      <div className="vbar-in">
        <span className="seg">
          <span className="v-ok"><span className="tick">{I.check()}</span>Verified</span>
        </span>
        <span className="seg">
          <span className={"atag " + t.cls}><span className="ad live-pulse"></span>{t.label}</span>
        </span>
        <span className="seg hide-sm">
          <span className="k">Source</span><span className="val">{broker}</span>
        </span>
        <span className="seg hide-sm">
          <span className="k">Refreshed</span><span className="val">{refreshed}</span>
        </span>
        <span className="seg">
          <button className="howlink" onClick={onHow}>{I.info()} <span className="howlbl">How verification works</span></button>
        </span>
      </div>
    </div>
  );
}

/* ---------------- calendar grid (April 2026, weekday-only) ---------------- */
function CalGrid({ data }) {
  const firstDay = new Date(2026, 3, 1).getDay();
  const daysInMonth = new Date(2026, 4, 0).getDate();
  let lead = (firstDay + 6) % 7; lead = lead > 4 ? 0 : lead;
  const cells = [];
  for (let i = 0; i < lead; i++) cells.push(null);
  for (let d = 1; d <= daysInMonth; d++) {
    const dow = new Date(2026, 3, d).getDay();
    if (dow === 0 || dow === 6) continue;
    cells.push(d);
  }
  while (cells.length % 5 !== 0) cells.push(null);

  const rows = [];
  for (let w = 0; w < cells.length / 5; w++) {
    const week = cells.slice(w * 5, w * 5 + 5);
    if (week.every((c) => c == null)) continue;
    let wp = 0, wd = 0;
    const cellEls = week.map((day, ci) => {
      if (day == null) return <div className="dcell empty" key={ci}></div>;
      const dd = data[day];
      if (!dd) return <div className="dcell off" key={ci}><span className="dn">{day}</span></div>;
      wp += dd.p; wd += 1;
      const tone = dd.p >= 0 ? "pos" : "neg";
      const sign = dd.p >= 0 ? "+" : "–";
      return (
        <div className={"dcell " + tone} key={ci}>
          <span className="dn">{day}</span>
          <span className="dp">{sign}${Math.abs(dd.p).toLocaleString()}</span>
          <span className="dm">{dd.t}t · {dd.w}%</span>
        </div>
      );
    });
    const wtone = wp > 0 ? "pos" : wp < 0 ? "neg" : "flat";
    const wsign = wp >= 0 ? "+" : "–";
    rows.push(
      <React.Fragment key={w}>
        {cellEls}
        <div className="dwktot"><span className="wkl">Wk</span><span className={"wkv " + wtone}>{wd === 0 ? "—" : wsign + "$" + Math.abs(wp).toLocaleString()}</span></div>
      </React.Fragment>
    );
  }
  return (
    <div className="dcal">
      <div className="dow">M</div><div className="dow">T</div><div className="dow">W</div><div className="dow">T</div><div className="dow">F</div><div className="dow wk">P&amp;L</div>
      {rows}
    </div>
  );
}

/* ---------------- 2 · hero — the scanned card ---------------- */
function qrFor(shareUrl) {
  return "https://api.qrserver.com/v1/create-qr-code/?data=" + encodeURIComponent("https://" + shareUrl) + "&size=200x200&qzone=0&margin=0&ecc=M";
}

/* Renders children at a fixed design width and scales the WHOLE thing down to
   fit the available width (transform: scale) instead of letting it reflow —
   same technique site.js uses for the homepage proof cards. */
function FitCard({ width, children }) {
  const outer = React.useRef(null);
  const inner = React.useRef(null);
  const [scale, setScale] = React.useState(1);
  const [h, setH] = React.useState(null);
  React.useLayoutEffect(() => {
    function fit() {
      if (!outer.current || !inner.current) return;
      const avail = outer.current.clientWidth;
      const s = Math.min(1, avail / width);
      setScale(s);
      setH(inner.current.offsetHeight * s);
    }
    fit();
    window.addEventListener("resize", fit, { passive: true });
    let ro = null;
    if (window.ResizeObserver) {
      ro = new ResizeObserver(fit);
      if (outer.current) ro.observe(outer.current);
      if (inner.current) ro.observe(inner.current);
    }
    const imgs = inner.current ? inner.current.querySelectorAll("img") : [];
    imgs.forEach((im) => { if (!im.complete) im.addEventListener("load", fit); });
    return () => { window.removeEventListener("resize", fit); if (ro) ro.disconnect(); };
  }, [width]);
  return (
    <div ref={outer} className="fitcard" style={{ height: h != null ? h : undefined }}>
      <div ref={inner} className="fitcard-in" style={{ width: width, transform: "scale(" + scale + ")", transformOrigin: "top left" }}>
        {children}
      </div>
    </div>
  );
}

/* Calendar share (single account) — mirrors the embedded homepage card */
function CalendarHero({ type, share, V }) {
  const t = TYPE_MAP[type];
  const total = share.hero.net;
  const sign = total >= 0 ? "+" : "–";
  return (
    <div className="vcardwrap cal">
      <div className="halo"></div>
      <FitCard width={496}>
      <div className="proof">
        <div className="scan"></div>
        <div className="proof-head">
          <BrandMark />
          <span className="vbadge"><span className="vd"></span>Verified</span>
        </div>
        <div className="proof-title">April 2026 · <span className={total >= 0 ? "pos" : "neg"}>{sign}${Math.abs(total).toLocaleString()}</span></div>
        <div className="proof-tags">
          <span className={"ptag acct " + t.cls}><span className="ad"></span>{t.label}</span>
          <span className="ptag">Apex 50K</span>
          <span className="ptag">{share.hero.days} days</span>
        </div>

        <CalGrid data={V.DAYS} />

        <div className="proof-foot">
          <div className="proof-src">
            <div className="src" style={{ font: "500 12px var(--font-mono)", color: "var(--fg-secondary)" }}>{share.accounts[0]} · Tradovate</div>
            <div className="url">{I.link()}{share.url}</div>
          </div>
          <div className="qrbox">
            <div className="qr"><img src={qrFor(share.url)} alt="Scan to verify on TickProof" /></div>
            <div className="qr-cap">Scan to verify</div>
          </div>
        </div>
      </div>
      </FitCard>
    </div>
  );
}

/* 30-day summary share (aggregate) — mirrors the homepage hero proof card */
function SummaryHero({ type, share, V }) {
  const t = TYPE_MAP[type];
  const h = share.hero;
  const apexN = share.accounts.filter((id) => id.indexOf("APEX") === 0).length;
  const mffN = share.accounts.length - apexN;
  return (
    <div className="vcardwrap summ">
      <div className="halo"></div>
      <FitCard width={496}>
      <div className="proof">
        <div className="scan"></div>
        <div className="proof-head">
          <BrandMark />
          <span className="vbadge"><span className="vd"></span>Verified</span>
        </div>
        <div className="proof-title">30 days · <span className="pos">+${h.net.toLocaleString()}</span> net</div>
        <div className="proof-tags">
          <span className={"ptag acct " + t.cls}><span className="ad"></span>{t.label}</span>
          <span className="ptag">{apexN} × Apex 50K</span>
          {mffN ? <span className="ptag">{mffN} × MFF 50K</span> : null}
          <span className="ptag">ES · NQ</span>
        </div>

        <div className="proof-stats">
          <div><div className="lab">Net P&L</div><div className="val pos">+${h.net.toLocaleString()}</div></div>
          <div><div className="lab">Win rate</div><div className="val">{h.winRate}</div></div>
          <div><div className="lab">Max DD</div><div className="val">{h.maxDD}</div></div>
          <div><div className="lab">Trades</div><div className="val">{h.trades}</div></div>
        </div>

        <div className="proof-foot">
          <div className="proof-src">
            <div className="lab">Source · {apexN} Apex{mffN ? " + " + mffN + " MFF" : ""}</div>
            <div className="acctlist">
              {h.rows.map((r) => (
                <div className="al-row" key={r.id}>
                  <span className="al-code">{r.id} · Tradovate · Mar 1 – 29 · {r.trades} trades</span>
                  <span className="al-pnl pos">{V.fmtMoney(r.net, true)}</span>
                </div>
              ))}
            </div>
            <div className="url">{I.link()}{share.url}</div>
          </div>
          <div className="qrbox">
            <div className="qr"><img src={qrFor(share.url)} alt="Scan to verify on TickProof" /></div>
            <div className="qr-cap">Scan to verify</div>
          </div>
        </div>
      </div>
      </FitCard>
    </div>
  );
}

/* ---------------- 3 · share strip ---------------- */
function ShareStrip({ shareUrl, onCopy }) {
  return (
    <div className="vshare">
      <button className="vchip primary" onClick={onCopy}>{I.copy()} Copy share link</button>
      <a className="vchip" href={"https://twitter.com/intent/tweet?url=" + encodeURIComponent("https://" + shareUrl)} target="_blank" rel="noopener" style={{ textDecoration: "none" }}>{I.xlogo()} Share on X</a>
      <button className="vchip" onClick={onCopy}>{I.share()} More</button>
    </div>
  );
}

/* ---------------- 4 · attribution ---------------- */
function Attribution({ shareCount }) {
  return (
    <div className="vattr">
      <div className="av">DM</div>
      <div className="id">
        <span className="nm">Dale Morrison {I.shield()}</span>
        <span className="hd">@dalefutures</span>
      </div>
      <div className="links">
        <a href="https://x.com/dalefutures" target="_blank" rel="noopener">{I.xlogo()} Profile</a>
        <a href="#">{shareCount} verified shares {I.cright()}</a>
      </div>
    </div>
  );
}

/* ---------------- scope bar ---------------- */
function ScopeBar({ scopeMode, accounts }) {
  const apexN = accounts.filter((a) => a.firm === "Apex").length;
  const mffN = accounts.filter((a) => a.firm !== "Apex").length;
  return (
    <div className="scopebar">
      <span className="sl">Accounts in scope</span>
      <div className="accs">
        {accounts.map((a) => <span className="acc" key={a.id}>{a.id}</span>)}
      </div>
      <span className="summ">{scopeMode === "multi" ? accounts.length + " accounts · Apex ×" + apexN + (mffN ? ", MFF ×" + mffN : "") + " · Tradovate" : "Single account · Tradovate"}</span>
    </div>
  );
}

/* ---------------- 4b · track record stats ---------------- */
function TrackRecord({ stats, windowVal, windowSub, V }) {
  const tiles = [
    { l: "Net P&L", v: V.fmtMoney(Math.round(stats.net), true), cls: stats.net >= 0 ? "pos" : "neg", d: "after commissions" },
    { l: "Win rate", v: stats.winRate.toFixed(1) + "%", d: stats.wins + "W · " + stats.losses + "L" },
    { l: "Total trades", v: stats.trades.toLocaleString(), d: stats.daysTraded + " days traded" },
    { l: "Avg win", v: V.fmtMoney(Math.round(stats.avgWin), true), cls: "pos", d: "per winning trade" },
    { l: "Avg loss", v: V.fmtMoney(Math.round(stats.avgLoss), true), cls: "neg", d: "per losing trade" },
    { l: "Max drawdown", v: "–" + V.fmtMoney(Math.round(stats.maxDD)).replace("$", "$"), cls: "neg", d: "peak-to-trough" },
    { l: "Commissions", v: V.fmtMoney(Math.round(stats.commission)), d: "total paid" },
    { l: "Window", v: windowVal, d: windowSub },
  ];
  return (
    <div className="statgrid">
      {tiles.map((t, i) => (
        <div className="st" key={i}>
          <span className="l">{t.l}</span>
          <span className={"v " + (t.cls || "")}>{t.v}</span>
          <span className="d">{t.d}</span>
        </div>
      ))}
    </div>
  );
}

/* ---------------- 5 · equity curve ---------------- */
function EquityCurve({ pts, axis, periodLabel, V }) {
  const W = 920, H = 220, padL = 8, padR = 8, padT = 14, padB = 10;
  const plotW = W - padL - padR, plotH = H - padT - padB;
  const vals = pts.map((p) => p.v);
  let vMin = Math.min.apply(null, vals), vMax = Math.max.apply(null, vals);
  const pad = (vMax - vMin) * 0.12 || 100; vMin -= pad; vMax += pad;
  const n = pts.length - 1;
  const xf = (i) => padL + (i / n) * plotW;
  const yf = (v) => padT + plotH - ((v - vMin) / (vMax - vMin)) * plotH;
  const line = pts.map((p, i) => xf(i) + "," + yf(p.v)).join(" ");
  const area = line + " " + xf(n) + "," + (padT + plotH) + " " + xf(0) + "," + (padT + plotH);
  const grid = [];
  for (let g = 0; g < 4; g++) { const gy = padT + (plotH * g) / 3; grid.push(gy); }
  const last = pts[pts.length - 1].v;
  return (
    <div className="eqpanel">
      <div className="eqh">
        <span className="t">Cumulative P&L · {periodLabel}</span>
        <span className={"r " + (last >= 0 ? "pos" : "neg")}>{V.fmtMoney(Math.round(last), true)}</span>
      </div>
      <div className="eqbody">
        <svg viewBox={"0 0 " + W + " " + H} preserveAspectRatio="none" style={{ height: 200 }}>
          <defs><linearGradient id="veqg" x1="0" x2="0" y1="0" y2="1"><stop offset="0" stopColor="rgba(0,224,138,0.26)" /><stop offset="1" stopColor="rgba(0,224,138,0)" /></linearGradient></defs>
          {grid.map((gy, i) => <line key={i} x1={padL} x2={padL + plotW} y1={gy} y2={gy} stroke="var(--chart-grid)" strokeWidth="1" vectorEffect="non-scaling-stroke" />)}
          <line x1={padL} x2={padL + plotW} y1={yf(0)} y2={yf(0)} stroke="var(--fg-muted)" strokeWidth="1" strokeDasharray="3 3" opacity="0.7" vectorEffect="non-scaling-stroke" />
          <polygon fill="url(#veqg)" points={area} />
          <polyline fill="none" stroke="var(--brand-green)" strokeWidth="2" strokeLinejoin="round" vectorEffect="non-scaling-stroke" points={line} />
        </svg>
        <div className="eqaxis">{(axis || []).map((a, i) => <span key={i}>{a}</span>)}</div>
      </div>
    </div>
  );
}

/* ---------------- 6 · trade table (9-column) ---------------- */
const PAGE_SIZE = 25;
function TradeTable({ trades, scopeMode, page, setPage, onXlsx, periodLabel, V }) {
  const total = trades.length;
  const pages = Math.ceil(total / PAGE_SIZE);
  const startI = page * PAGE_SIZE;
  const rows = trades.slice(startI, startI + PAGE_SIZE);
  const netAll = trades.reduce((s, t) => s + t.pnl, 0);
  const pageBtns = [];
  for (let i = 0; i < pages; i++) {
    if (i === 0 || i === pages - 1 || Math.abs(i - page) <= 1) {
      pageBtns.push(<button key={i} className={"pgbtn" + (i === page ? " cur" : "")} onClick={() => setPage(i)}>{i + 1}</button>);
    } else if (Math.abs(i - page) === 2) {
      pageBtns.push(<span key={i} style={{ alignSelf: "center", color: "var(--fg-muted)", font: "600 12px var(--font-mono)" }}>…</span>);
    }
  }
  return (
    <>
      <div className="tradehead">
        <span className="meta">{total.toLocaleString()} trades · full record for the {scopeMode === "multi" ? "accounts" : "account"} in scope · no filtering</span>
      </div>
      <div className="tradescroll">
        <table className="ttable">
          <thead>
            <tr>
              <th>Instrument</th>
              {scopeMode === "multi" && <th>Account</th>}
              <th>Entry Date</th><th className="r">Entry</th><th>Dir</th><th className="r">Size</th>
              <th>Exit Date</th><th className="r">Exit</th><th className="r">Comm.</th><th className="r">PnL ($)</th>
            </tr>
          </thead>
          <tbody>
            {rows.map((t) => (
              <tr key={t.id}>
                <td className="inst">{t.instrument}</td>
                {scopeMode === "multi" && <td className="acccell">{t.account}</td>}
                <td>{V.fmtTradeDate(t.entryDate)}</td>
                <td className="r">{V.fmtPrice(t.entryPrice, t.dec)}</td>
                <td className={t.direction === "Buy" ? "dir-buy" : "dir-sell"}>{t.direction}</td>
                <td className="r">{t.size}</td>
                <td>{V.fmtTradeDate(t.exitDate)}</td>
                <td className="r">{V.fmtPrice(t.exitPrice, t.dec)}</td>
                <td className="r">{t.commission.toFixed(2)}</td>
                <td className={"r pnl " + (t.pnl >= 0 ? "pos" : "neg")}>{V.fmtMoney2(t.pnl, true)}</td>
              </tr>
            ))}
          </tbody>
          <tfoot>
            <tr>
              <td colSpan={scopeMode === "multi" ? 9 : 8}><span className="fl">Total · {total.toLocaleString()} trades · {periodLabel}</span></td>
              <td className="r" style={{ color: netAll >= 0 ? "var(--pnl-positive)" : "var(--pnl-negative)" }}>{V.fmtMoney2(netAll, true)}</td>
            </tr>
          </tfoot>
        </table>
      </div>
      <div className="pager">
        <span className="pinfo">Showing {startI + 1}–{Math.min(startI + PAGE_SIZE, total)} of {total.toLocaleString()}</span>
        <div className="pbtns">
          <button className="pgbtn" disabled={page === 0} onClick={() => setPage(page - 1)}>{I.cleft()}</button>
          {pageBtns}
          <button className="pgbtn" disabled={page >= pages - 1} onClick={() => setPage(page + 1)}>{I.cright()}</button>
        </div>
      </div>
    </>
  );
}

/* ---------------- 7 · verify it yourself ---------------- */
function HowItWorks() {
  const cards = [
    { ic: I.refresh(), h: "Straight from the broker", p: "Trades import directly from the trader's broker over an authorised API. Nothing is typed by hand." },
    { ic: I.lock(), h: "Signed at creation", p: "P&L, win rate and drawdown are hashed against the source data the moment the share is created. Edit a figure and the signature breaks." },
    { ic: I.shield(), h: "Refreshes or expires", p: "The page re-checks the source account. If it can't, the share expires after 90 days -so what you see may always be traced back to live data." },
  ];
  return (
    <div className="howgrid">
      {cards.map((c, i) => (
        <div className="howcard" key={i}>
          <span className="ic">{c.ic}</span>
          <h4>{c.h}</h4>
          <p>{c.p}</p>
        </div>
      ))}
    </div>
  );
}

/* ---------------- 8 · disclosures ---------------- */
function Disclosures() {
  return (
    <div className="disc">
      <p><strong>Risk disclosure.</strong> Futures and forex trading contains substantial risk and is not for every investor. An investor could potentially lose all or more than the initial investment. Risk capital is money that can be lost without jeopardizing ones' financial security or life style. Only risk capital should be used for trading and only those with sufficient risk capital should consider trading. Past performance is not necessarily indicative of future results.</p>
      <p><strong>NinjaTrader affiliation.</strong> NinjaTrader® is a registered trademark of NinjaTrader Group, LLC. No NinjaTrader company has any affiliation with the owner, developer, or provider of the products or services described herein, or any interest, ownership or otherwise, in any such product or service, or endorses, recommends or approves any such product or service. Tradovate is part of the NinjaTrader Group.</p>
      <p>Results shown are from the account(s) named above and may not be representative of other traders. Your results may vary. Read the full <a href="/risk-disclosure">risk disclosure</a>.</p>
    </div>
  );
}

/* ---------------- 9 · conversion CTA ---------------- */
function ConversionCTA() {
  const [ok, setOk] = React.useState(false);
  const [busy, setBusy] = React.useState(false);
  const onSubmit = (e) => {
    e.preventDefault();
    if (busy || ok) return; // guard against double-submit
    const i = e.currentTarget.querySelector("input");
    const v = ((i && i.value) || "").trim();
    if (!/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(v)) { if (i) { i.focus(); i.style.borderColor = "var(--status-danger)"; } return; }
    if (i) i.style.borderColor = "";
    setBusy(true);
    fetch("/api/subscribe", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ email: v })
    })
      .then((resp) => resp.json().catch(() => ({ ok: resp.ok })))
      .then((data) => {
        if (data && data.ok) {
          setBusy(false);
          setOk(true);
          if (i) { i.value = ""; i.placeholder = "Confirmation sent to your inbox"; i.blur(); }
        } else {
          throw new Error("subscribe failed");
        }
      })
      .catch(() => {
        setBusy(false);
        if (i) { i.placeholder = "Something went wrong — try again"; i.style.borderColor = "var(--status-danger)"; }
      });
  };
  const label = ok ? "You're on the list ✓" : busy ? "Joining…" : "Join the waitlist";
  return (
    <div className="vcta">
      <h3>Build your own<br />verified track record</h3>
      <p>Connect your broker, follow every prop firm rule, and share results that scan back to live data. Free for traders.</p>
      <form className={"capture" + (ok ? " ok" : "")} onSubmit={onSubmit} noValidate>
        <input type="email" placeholder="you@email.com" aria-label="Email address" disabled={ok || busy} onInput={(e) => { e.target.style.borderColor = ""; e.target.placeholder = "you@email.com"; }} />
        <button className="btn" type="submit" disabled={ok || busy} style={busy ? { opacity: 0.85 } : undefined}>{label}</button>
      </form>
      <p className="cap-note">Free for traders · No card required</p>
    </div>
  );
}

/* ---------------- modal + toast ---------------- */
function HowModal({ onClose }) {
  const steps = [
    ["1", <span><b>Connect once.</b> The trader links their broker to TickProof over an authorised, read-only API. Every fill imports automatically.</span>],
    ["2", <span><b>Sign the numbers.</b> When a share is created, the P&L, win rate and drawdown are hashed against the source account data and timestamped.</span>],
    ["3", <span><b>Scan to verify.</b> The QR on the card resolves here. Editing the card image breaks the signature — the figures shown are the ones that match the source.</span>],
    ["4", <span><b>Stays current.</b> This page re-checks the source account and shows when it last refreshed. If it can't refresh, it expires after 90 days.</span>],
  ];
  React.useEffect(() => {
    const onKey = (e) => { if (e.key === "Escape") onClose(); };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, []);
  return (
    <div className="vmodal-bd" onClick={onClose}>
      <div className="vmodal" onClick={(e) => e.stopPropagation()}>
        <div className="vmodal-h"><span className="t">How verification works</span><button className="vmodal-x" onClick={onClose}>{I.x()}</button></div>
        <div className="vmodal-b">
          {steps.map((s, i) => <div className="vmodal-step" key={i}><span className="n">{s[0]}</span><span className="bd">{s[1]}</span></div>)}
        </div>
      </div>
    </div>
  );
}

function Toast({ msg, show }) {
  return <div className={"vtoast" + (show ? " show" : "")}>{I.check()}{msg}</div>;
}

Object.assign(window, {
  I, TYPE_MAP, StatusBar, CalGrid, CalendarHero, SummaryHero, ShareStrip, Attribution,
  ScopeBar, TrackRecord, EquityCurve, TradeTable, HowItWorks, Disclosures,
  ConversionCTA, HowModal, Toast,
});
