/* ============================================================
   EBTR — Article reader
   Progress bar · reading time · bookmark · author w/ role badge ·
   related · premium paywall (free preview → unlock).
   ============================================================ */
const { Stat: EBStat, Badge: EBBadgeR, Button: EBButtonR, ThreeBar: EBThreeBarR, Eyebrow: EBEyebrowR } = window.EBTHubDesignSystem_ccdc9d;

/* ---- Per-user watermark layer (faint, tiled, diagonal; non-interactive) ---- */
function ebtrWatermarkURI(text) {
  const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="340" height="210"><text x="0" y="120" transform="rotate(-28 0 120)" font-family="Michroma, sans-serif" font-size="14" letter-spacing="2" fill="rgba(255,255,255,0.05)">${text}</text></svg>`;
  return `url("data:image/svg+xml;utf8,${encodeURIComponent(svg)}")`;
}
function EBTRWatermark({ viewer }) {
  const label = `Licensed to ${viewer.name} · ${viewer.company}`;
  return <div aria-hidden="true" style={{ position: "absolute", inset: 0, pointerEvents: "none", zIndex: 2, backgroundImage: ebtrWatermarkURI(label), backgroundRepeat: "repeat" }} />;
}

/* ---- Watermarked PDF export (browser print-to-PDF; reader's name on every page) ---- */
function ebtrEscape(s) { return String(s).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;"); }
function ebtrBlockHTML(b) {
  if (b.t === "p") return `<p>${ebtrEscape(b.text)}</p>`;
  if (b.t === "h2") return `<h2>${ebtrEscape(b.text)}</h2>`;
  if (b.t === "quote") return `<blockquote>${ebtrEscape(b.text)}${b.cite ? `<cite>— ${ebtrEscape(b.cite)}</cite>` : ""}</blockquote>`;
  if (b.t === "stat") return `<div class="stat"><span class="sv">${ebtrEscape(b.value)}</span><span class="sl">${ebtrEscape(b.label)}${b.source ? `<em>${ebtrEscape(b.source)}</em>` : ""}</span></div>`;
  if (b.t === "list") return `<ul>${b.items.map((it) => `<li>${ebtrEscape(it)}</li>`).join("")}</ul>`;
  if (b.t === "callout") return `<div class="callout"><span class="cl">${ebtrEscape(b.label)}</span><p>${ebtrEscape(b.text)}</p></div>`;
  return "";
}
function ebtrExportPdf(article, viewer) {
  const data = window.EBTR_DATA;
  const cat = data.categories[article.category];
  const author = data.authors[article.author];
  const stamp = `Licensed to ${viewer.name} · ${viewer.company}`;
  const date = new Date(article.date).toLocaleDateString("en-GB", { day: "numeric", month: "long", year: "numeric" });
  const wmSvg = `<svg xmlns='http://www.w3.org/2000/svg' width='420' height='260'><text x='0' y='150' transform='rotate(-28 0 150)' font-family='Arial' font-size='15' letter-spacing='2' fill='rgba(20,20,20,0.06)'>${ebtrEscape(stamp)}</text></svg>`;
  const wm = `url("data:image/svg+xml;utf8,${encodeURIComponent(wmSvg)}")`;
  const html = `<!DOCTYPE html><html><head><meta charset="utf-8"><title>${ebtrEscape(article.title)} — EBTR</title>
<style>
  @page { margin: 22mm 18mm; }
  * { box-sizing: border-box; }
  html,body { margin:0; background:#fff; color:#1b1919; -webkit-print-color-adjust:exact; print-color-adjust:exact; }
  body { font-family: Georgia, 'Times New Roman', serif; line-height:1.6; background-image:${wm}; background-repeat:repeat; }
  .head { border-bottom:2px solid #1b1919; padding-bottom:14px; margin-bottom:24px; }
  .bars { display:flex; width:54px; height:7px; margin-bottom:14px; }
  .bars i { flex:1; } .bars i:nth-child(1){background:#FF8C03} .bars i:nth-child(2){background:#5D5DBF} .bars i:nth-child(3){background:#1D38DC}
  .brand { font-family:Arial,sans-serif; font-size:11px; letter-spacing:3px; text-transform:uppercase; color:#555; }
  .kicker { font-family:Arial,sans-serif; font-size:10px; letter-spacing:2px; text-transform:uppercase; color:#1D38DC; margin:18px 0 6px; }
  h1 { font-family:Arial,sans-serif; font-size:26px; line-height:1.18; margin:0 0 10px; }
  .dek { font-size:15px; color:#444; font-style:italic; margin:0 0 12px; }
  .by { font-family:Arial,sans-serif; font-size:11px; color:#666; letter-spacing:0.5px; }
  h2 { font-family:Arial,sans-serif; font-size:17px; margin:26px 0 8px; }
  p { font-size:13.5px; margin:0 0 13px; }
  blockquote { margin:18px 0; padding-left:16px; border-left:3px solid #FF8C03; font-size:17px; font-style:italic; }
  blockquote cite { display:block; font-family:Arial,sans-serif; font-size:10px; font-style:normal; letter-spacing:1.5px; text-transform:uppercase; color:#888; margin-top:8px; }
  .stat { display:flex; gap:16px; align-items:baseline; margin:18px 0; padding:14px 16px; background:#f4f3f2; border-left:3px solid #FF8C03; }
  .stat .sv { font-family:Arial,sans-serif; font-size:34px; font-weight:700; color:#b35e07; }
  .stat .sl { font-size:13px; } .stat .sl em { display:block; font-family:Arial,sans-serif; font-style:normal; font-size:9.5px; letter-spacing:1.5px; text-transform:uppercase; color:#888; margin-top:5px; }
  ul { padding-left:20px; } li { font-size:13.5px; margin:0 0 7px; }
  .callout { margin:18px 0; padding:14px 16px; border:1px solid #1D38DC; background:#eef1fe; }
  .callout .cl { font-family:Arial,sans-serif; font-size:9.5px; letter-spacing:2px; text-transform:uppercase; color:#1D38DC; display:block; margin-bottom:6px; }
  .lic { position:fixed; bottom:6mm; left:0; right:0; text-align:center; font-family:Arial,sans-serif; font-size:9px; letter-spacing:1px; color:#999; }
  .foot { margin-top:30px; padding-top:14px; border-top:1px solid #ccc; font-family:Arial,sans-serif; font-size:10px; color:#888; line-height:1.6; }
</style></head><body>
  <div class="head"><div class="bars"><i></i><i></i><i></i></div><div class="brand">EBT·HUB Review</div></div>
  <div class="kicker">${ebtrEscape(cat.label)}${article.premium ? " · Premium" : ""}</div>
  <h1>${ebtrEscape(article.title)}</h1>
  <div class="dek">${ebtrEscape(article.dek)}</div>
  <div class="by">${ebtrEscape(author.name)} · ${date} · ${article.readingMins} min read</div>
  <div style="margin-top:24px">${article.body.map(ebtrBlockHTML).join("")}</div>
  <div class="foot">© 2026 EBTHub — European Business Transformation Hub · Vienna, AT.<br>This copy is licensed to ${ebtrEscape(viewer.name)} (${ebtrEscape(viewer.company)}) for personal use. Redistribution is traceable to this account.</div>
  <div class="lic">${ebtrEscape(stamp)}</div>
</body></html>`;
  const w = window.open("", "_blank");
  if (!w) { alert("Allow pop-ups to download the PDF."); return; }
  w.document.open(); w.document.write(html); w.document.close();
  w.focus();
  setTimeout(() => { w.print(); }, 350);
}

/* ---- Body block renderer ---- */
function EBTRBlock({ block }) {
  const b = block;
  if (b.t === "p") return <p style={{ fontFamily: "var(--font-body)", fontSize: 19, lineHeight: 1.7, color: "var(--neutral-200)", margin: "0 0 26px", textWrap: "pretty" }}>{b.text}</p>;
  if (b.t === "h2") return <h2 style={{ fontFamily: "var(--font-body)", fontWeight: 700, fontSize: 27, lineHeight: 1.25, color: "var(--white)", margin: "44px 0 20px", letterSpacing: "-0.01em" }}>{b.text}</h2>;
  if (b.t === "quote") return (
    <blockquote style={{ margin: "38px 0", paddingLeft: 28, borderLeft: "3px solid var(--ebt-orange)" }}>
      <p style={{ fontFamily: "var(--font-body)", fontWeight: 600, fontSize: 27, lineHeight: 1.32, color: "var(--white)", margin: 0, textWrap: "balance" }}>{b.text}</p>
      {b.cite && <cite style={{ display: "block", marginTop: 14, fontFamily: "var(--font-ui)", fontSize: 11, letterSpacing: "0.12em", textTransform: "uppercase", color: "var(--text-muted)", fontStyle: "normal" }}>— {b.cite}</cite>}
    </blockquote>
  );
  if (b.t === "stat") {
    const col = b.color === "blue" ? "var(--ebt-blue)" : b.color === "purple" ? "var(--ebt-purple)" : "var(--ebt-orange)";
    return (
      <div style={{ margin: "38px 0", padding: "28px 32px", background: "var(--surface-raised)", borderLeft: `3px solid ${col}`, display: "flex", gap: 30, alignItems: "center", flexWrap: "wrap" }}>
        <span style={{ fontFamily: "var(--font-ui)", fontSize: "clamp(40px, 13vw, 60px)", lineHeight: 1, letterSpacing: "-0.01em", color: col, flex: "none" }}>{b.value}</span>
        <div style={{ flex: 1, minWidth: 220 }}>
          <div style={{ fontFamily: "var(--font-body)", fontSize: 18, lineHeight: 1.45, color: "var(--neutral-100)" }}>{b.label}</div>
          {b.source && <div style={{ fontFamily: "var(--font-ui)", fontSize: 11, letterSpacing: "0.12em", textTransform: "uppercase", color: "var(--text-muted)", marginTop: 8 }}>{b.source}</div>}
        </div>
      </div>
    );
  }
  if (b.t === "list") return (
    <ul style={{ listStyle: "none", padding: 0, margin: "8px 0 30px", display: "flex", flexDirection: "column", gap: 16 }}>
      {b.items.map((it, i) => (
        <li key={i} style={{ display: "grid", gridTemplateColumns: "24px 1fr", gap: 12, fontFamily: "var(--font-body)", fontSize: 18, lineHeight: 1.6, color: "var(--neutral-200)" }}>
          <span style={{ color: "var(--ebt-orange)", fontFamily: "var(--font-ui)", fontSize: 16 }}>→</span>
          <span>{it}</span>
        </li>
      ))}
    </ul>
  );
  if (b.t === "callout") return (
    <div style={{ margin: "38px 0", padding: "26px 28px", background: "rgba(29,56,220,0.08)", border: "1px solid rgba(29,56,220,0.4)" }}>
      <div style={{ fontFamily: "var(--font-ui)", fontSize: 10.5, letterSpacing: "0.16em", textTransform: "uppercase", color: "var(--blue-400)", marginBottom: 12 }}>{b.label}</div>
      <p style={{ fontFamily: "var(--font-body)", fontSize: 18, lineHeight: 1.6, color: "var(--neutral-100)", margin: 0 }}>{b.text}</p>
    </div>
  );
  if (b.t === "figure") return (
    <figure style={{ margin: "38px 0" }}>
      <div style={{ height: 280, border: "1px solid var(--border-hairline)" }}><EBTRCover cover={b.cover} accent={b.accent || "blue"} big /></div>
      {b.caption && <figcaption style={{ fontFamily: "var(--font-ui)", fontSize: 11, letterSpacing: "0.08em", color: "var(--text-muted)", marginTop: 12, textTransform: "uppercase" }}>{b.caption}</figcaption>}
    </figure>
  );
  return null;
}

/* ---- Author block ---- */
function EBTRAuthorCard({ authorId }) {
  const a = window.EBTR_DATA.authors[authorId];
  if (!a) return null;
  return (
    <div style={{ padding: "28px 0", borderTop: "1px solid var(--border-hairline)", borderBottom: "1px solid var(--border-hairline)", margin: "48px 0" }}>
      <div style={{ fontFamily: "var(--font-ui)", fontSize: 10.5, letterSpacing: "0.14em", textTransform: "uppercase", color: "var(--text-muted)", marginBottom: 16 }}>About the author</div>
      <div style={{ display: "flex", alignItems: "center", gap: 12, flexWrap: "wrap" }}>
        <span style={{ fontFamily: "var(--font-body)", fontWeight: 700, fontSize: 20, color: "var(--white)" }}>{a.name}</span>
        <EBBadgeR variant={a.badge.variant} shape="square" size="sm">{a.badge.label}</EBBadgeR>
      </div>
      <div style={{ fontFamily: "var(--font-ui)", fontSize: 11.5, letterSpacing: "0.06em", color: "var(--text-muted)", margin: "8px 0 14px", textTransform: "uppercase" }}>{a.title}</div>
      <p style={{ fontFamily: "var(--font-body)", fontSize: 16.5, lineHeight: 1.6, color: "var(--text-secondary)", margin: 0, maxWidth: 640 }}>{a.bio}</p>
      {a.orcid && <a href={"https://orcid.org/" + a.orcid} target="_blank" rel="noopener" style={{ display: "inline-flex", alignItems: "center", gap: 7, marginTop: 14, fontFamily: "var(--font-ui)", fontSize: 11, letterSpacing: "0.04em", color: "var(--blue-400)", textDecoration: "none" }}><svg width="13" height="13" viewBox="0 0 24 24" fill="#A6CE39"><circle cx="12" cy="12" r="12"/><path fill="#fff" d="M7.5 8.7a.9.9 0 1 1 0-1.8.9.9 0 0 1 0 1.8zM6.8 10h1.4v7H6.8v-7zm3 0h3.3c2.6 0 3.8 1.7 3.8 3.5 0 1.9-1.5 3.5-3.8 3.5h-3.3v-7zm1.4 1.3v4.4h1.8c1.6 0 2.3-1.1 2.3-2.2 0-1.2-.8-2.2-2.3-2.2h-1.8z"/></svg>ORCID {a.orcid}</a>}
    </div>
  );
}

/* ---- References (APA, 2–5) ---- */
function EBTRReferences({ refs, doi }) {
  if ((!refs || refs.length === 0) && !doi) return null;
  return (
    <div style={{ margin: "48px 0 0", paddingTop: 8 }}>
      {refs && refs.length > 0 && (
        <React.Fragment>
          <div style={{ fontFamily: "var(--font-ui)", fontSize: 10.5, letterSpacing: "0.14em", textTransform: "uppercase", color: "var(--text-muted)", marginBottom: 18 }}>References</div>
          <ol style={{ listStyle: "none", padding: 0, margin: 0, counterReset: "ref", display: "flex", flexDirection: "column", gap: 14 }}>
            {refs.map((r, i) => (
              <li key={i} style={{ display: "grid", gridTemplateColumns: "26px 1fr", gap: 10, fontFamily: "var(--font-body)", fontSize: 14.5, lineHeight: 1.55, color: "var(--text-secondary)" }}>
                <span style={{ fontFamily: "var(--font-ui)", fontSize: 12, color: "var(--text-muted)" }}>{i + 1}.</span>
                <span>{r.authors} ({r.year}). <span style={{ fontStyle: "italic", color: "var(--neutral-100)" }}>{r.title}.</span> {r.source}.{r.doi && <React.Fragment> <a href={"https://doi.org/" + r.doi} target="_blank" rel="noopener" style={{ color: "var(--blue-400)", textDecoration: "none" }}>https://doi.org/{r.doi}</a></React.Fragment>}</span>
              </li>
            ))}
          </ol>
        </React.Fragment>
      )}
      {doi && (
        <div style={{ marginTop: refs && refs.length ? 26 : 0, paddingTop: 18, borderTop: "1px solid var(--border-hairline)", fontFamily: "var(--font-ui)", fontSize: 11, letterSpacing: "0.04em", color: "var(--text-muted)" }}>
          <a href={"https://doi.org/" + doi} target="_blank" rel="noopener" style={{ color: "var(--blue-400)", textDecoration: "none" }}>https://doi.org/{doi}</a>
        </div>
      )}
    </div>
  );
}

/* ---- Paywall ---- */
/* ---- Login wall (visitors): every article stops after the preview ---- */
function EBTRLoginWall({ onSignIn, onApply }) {
  return (
    <div style={{ position: "relative", marginTop: -120 }}>
      <div style={{ height: 120, background: "linear-gradient(to bottom, transparent, var(--ebt-ink))", pointerEvents: "none" }} />
      <div style={{ border: "1px solid var(--border-hairline)", borderTop: "3px solid var(--ebt-blue)", background: "var(--surface-raised)", padding: "clamp(22px,6vw,40px) clamp(18px,5vw,40px) clamp(26px,7vw,44px)", textAlign: "center" }}>
        <div style={{ display: "flex", justifyContent: "center", marginBottom: 18 }}>
          <svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="var(--blue-400)" strokeWidth="2"><rect x="4" y="11" width="16" height="11" /><path d="M7 11V8a5 5 0 0 1 10 0v3" /></svg>
        </div>
        <h3 style={{ fontFamily: "var(--font-body)", fontWeight: 700, fontSize: 26, color: "var(--white)", margin: "0 0 12px", textWrap: "balance" }}>Sign in to keep reading</h3>
        <p style={{ fontFamily: "var(--font-body)", fontSize: 17, lineHeight: 1.6, color: "var(--text-secondary)", maxWidth: 480, margin: "0 auto 28px" }}>
          Full articles are free for EBTHub members and registered partners. Sign in to read the rest — or become a partner.
        </p>
        <div style={{ display: "flex", gap: 14, justifyContent: "center", flexWrap: "wrap" }}>
          <EBButtonR variant="primary" size="md" icon="none" onClick={onSignIn}>Sign in</EBButtonR>
          <EBButtonR variant="ghost" size="md" icon="none" onClick={onApply}>Become a partner</EBButtonR>
        </div>
      </div>
    </div>
  );
}

/* ---- Purchase wall (logged-in reader hitting a Premium paper) ---- */
function EBTRPaywall({ article, onUnlock, onSignIn }) {
  return (
    <div style={{ position: "relative", marginTop: -120 }}>
      <div style={{ height: 120, background: "linear-gradient(to bottom, transparent, var(--ebt-ink))", pointerEvents: "none" }} />
      <div style={{ border: "1px solid var(--border-hairline)", borderTop: "3px solid var(--ebt-orange)", background: "var(--surface-raised)", padding: "clamp(22px,6vw,40px) clamp(18px,5vw,40px) clamp(26px,7vw,44px)", textAlign: "center" }}>
        <div style={{ display: "flex", justifyContent: "center", marginBottom: 18 }}>
          <svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="var(--ebt-orange)" strokeWidth="2"><rect x="4" y="11" width="16" height="11" /><path d="M7 11V8a5 5 0 0 1 10 0v3" /></svg>
        </div>
        <h3 style={{ fontFamily: "var(--font-body)", fontWeight: 700, fontSize: 26, color: "var(--white)", margin: "0 0 12px", textWrap: "balance" }}>A Premium paper</h3>
        <p style={{ fontFamily: "var(--font-body)", fontSize: 17, lineHeight: 1.6, color: "var(--text-secondary)", maxWidth: 480, margin: "0 auto 28px" }}>
          This in-depth paper is available as a one-time purchase on top of your membership. Unlock it to read the full piece.
        </p>
        <div style={{ display: "flex", gap: 14, justifyContent: "center", flexWrap: "wrap" }}>
          <EBButtonR variant="primary" size="md" icon="none" onClick={onUnlock}>Buy this paper</EBButtonR>
        </div>
        <div style={{ marginTop: 22, fontFamily: "var(--font-ui)", fontSize: 10.5, letterSpacing: "0.1em", textTransform: "uppercase", color: "var(--text-muted)" }}>Secure one-time checkout · no app-store fees</div>
      </div>
    </div>
  );
}

/* ---- Share row (LinkedIn · X · copy link) ---- */
function EBTRShare({ title, onPdf }) {
  const [copied, setCopied] = React.useState(false);
  const url = typeof window !== "undefined" ? window.location.href : "";
  const ln = () => window.open("https://www.linkedin.com/sharing/share-offsite/?url=" + encodeURIComponent(url), "_blank", "noopener,width=620,height=640");
  const x = () => window.open("https://twitter.com/intent/tweet?text=" + encodeURIComponent(title) + "&url=" + encodeURIComponent(url), "_blank", "noopener,width=620,height=640");
  const copy = () => { try { navigator.clipboard.writeText(url); } catch (e) {} setCopied(true); setTimeout(() => setCopied(false), 1800); };
  const btn = { width: 38, height: 38, borderRadius: "50%", border: "1px solid var(--border-strong)", background: "none", cursor: "pointer", display: "inline-flex", alignItems: "center", justifyContent: "center", color: "var(--text-secondary)", transition: "border-color var(--dur-base), color var(--dur-base)" };
  return (
    <div style={{ display: "flex", alignItems: "center", gap: 12, margin: "22px 0 2px" }}>
      <span style={{ fontFamily: "var(--font-ui)", fontSize: 10, letterSpacing: "0.12em", textTransform: "uppercase", color: "var(--text-muted)", marginRight: 2 }}>Share</span>
      <button className="ebtr-share" style={btn} title="Share on LinkedIn" onClick={ln}>
        <svg width="15" height="15" viewBox="0 0 24 24" fill="currentColor"><path d="M20.45 20.45h-3.56v-5.57c0-1.33-.02-3.04-1.85-3.04-1.85 0-2.14 1.45-2.14 2.94v5.67H9.35V9h3.41v1.56h.05c.48-.9 1.63-1.85 3.36-1.85 3.6 0 4.27 2.37 4.27 5.45v6.29zM5.34 7.43a2.06 2.06 0 1 1 0-4.13 2.06 2.06 0 0 1 0 4.13zM7.12 20.45H3.56V9h3.56v11.45zM22.22 0H1.77C.79 0 0 .77 0 1.73v20.54C0 23.23.79 24 1.77 24h20.45c.98 0 1.78-.77 1.78-1.73V1.73C24 .77 23.2 0 22.22 0z" /></svg>
      </button>
      <button className="ebtr-share" style={btn} title="Share on X" onClick={x}>
        <svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor"><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>
      </button>
      <button className="ebtr-share" style={btn} title={copied ? "Copied" : "Copy link"} onClick={copy}>
        {copied
          ? <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="var(--blue-400)" strokeWidth="2.4"><path d="M20 6 9 17l-5-5" /></svg>
          : <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M10 13a5 5 0 0 0 7.07 0l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" /><path d="M14 11a5 5 0 0 0-7.07 0l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" /></svg>}
      </button>
      {onPdf && <button className="ebtr-share ebtr-share-pdf" style={{ ...btn, width: "auto", borderRadius: 999, padding: "0 15px", gap: 7 }} title="Download a watermarked PDF" onClick={onPdf}>
        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M12 3v12m0 0 4-4m-4 4-4-4" /><path d="M5 21h14" /></svg>
        <span style={{ fontFamily: "var(--font-ui)", fontSize: 10.5, letterSpacing: "0.1em", textTransform: "uppercase" }}>PDF</span>
      </button>}
      {copied && <span style={{ fontFamily: "var(--font-ui)", fontSize: 11, letterSpacing: "0.04em", color: "var(--blue-400)" }}>Link copied</span>}
    </div>
  );
}

/* ---- Reader ---- */
function EBTRReader({ articleId, onOpen, onBack, loggedIn, allAccess, isUnlocked, onUnlock, onSignIn, onApply, protect, watermark, viewer, motion }) {
  const data = window.EBTR_DATA;
  const article = data.articles.find((a) => a.id === articleId);
  const scrollRef = React.useRef(null);
  const [progress, setProgress] = React.useState(0);

  React.useEffect(() => { window.scrollTo(0, 0); }, [articleId]);
  React.useEffect(() => {
    if (!protect) return;
    const block = (e) => { e.preventDefault(); return false; };
    const root = scrollRef.current;
    if (root) { root.addEventListener("copy", block); root.addEventListener("cut", block); root.addEventListener("contextmenu", block); root.addEventListener("dragstart", block); }
    return () => { if (root) { root.removeEventListener("copy", block); root.removeEventListener("cut", block); root.removeEventListener("contextmenu", block); root.removeEventListener("dragstart", block); } };
  }, [protect, articleId]);
  React.useEffect(() => {
    const onScroll = () => {
      const el = scrollRef.current; if (!el) return;
      const start = el.offsetTop, total = el.offsetHeight - window.innerHeight;
      const p = total > 0 ? (window.scrollY - start + 120) / total : 0;
      setProgress(Math.max(0, Math.min(1, p)));
    };
    onScroll(); window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, [articleId]);

  if (!article) return null;
  const cat = data.categories[article.category];
  const author = data.authors[article.author];
  // Security model: every article previews then gates on LOGIN. Logged-in readers
  // get all standard articles in full; Premium papers need a purchase on top.
  const needsLogin = !loggedIn;
  const needsPurchase = loggedIn && article.premium && !isUnlocked && !allAccess;
  const locked = needsLogin || needsPurchase;
  const previewCount = needsLogin ? Math.min(3, article.body.length) : article.freeUntil;
  const blocks = locked ? article.body.slice(0, previewCount) : article.body;
  const related = (article.related || []).map((id) => data.articles.find((a) => a.id === id)).filter(Boolean).slice(0, 4);

  return (
    <React.Fragment>
      {/* progress */}
      <div style={{ position: "sticky", top: 72, zIndex: 40, height: 3, background: "var(--neutral-800)" }}>
        <div style={{ height: "100%", width: `${progress * 100}%`, background: "var(--ebt-orange)", transition: "width 80ms linear" }} />
      </div>

      <main ref={scrollRef}>
        <div style={{ maxWidth: 1600, margin: "0 auto", padding: "34px var(--space-7) 0" }}>
          <button onClick={onBack} style={{ display: "inline-flex", alignItems: "center", gap: 9, background: "none", border: "none", padding: 0, cursor: "pointer", fontFamily: "var(--font-ui)", fontSize: 11, letterSpacing: "0.12em", textTransform: "uppercase", color: "var(--text-secondary)", marginBottom: 26 }}>← The Review</button>

          <div className="ebtr-reader-grid" style={{ display: "grid", gridTemplateColumns: "240px minmax(0, 1fr) 330px", gap: 64, alignItems: "start" }}>

            {/* LEFT RAIL — Topics */}
            <aside className="ebtr-reader-left" style={{ position: "sticky", top: 100 }}>
              <EBEyebrowR>Topics</EBEyebrowR>
              <div style={{ display: "flex", flexWrap: "wrap", gap: 8, marginTop: 16 }}>
                <button onClick={() => onCategory(article.category)} style={{ display: "inline-flex", alignItems: "center", gap: 7, background: "none", border: "1px solid var(--border-strong)", padding: "7px 12px", cursor: "pointer", fontFamily: "var(--font-ui)", fontSize: 10, letterSpacing: "0.1em", textTransform: "uppercase", color: "var(--white)", borderRadius: "var(--radius-sm)", whiteSpace: "nowrap" }}>
                  <span style={{ width: 8, height: 8, background: ebtrAccentVar(cat.color) }} />{cat.label}
                </button>
                {(article.tags || []).map((tg) => (
                  <span key={tg} style={{ fontFamily: "var(--font-ui)", fontSize: 10, letterSpacing: "0.1em", textTransform: "uppercase", color: "var(--text-secondary)", border: "1px solid var(--border-hairline)", padding: "7px 12px", borderRadius: "var(--radius-sm)", whiteSpace: "nowrap" }}>{tg}</span>
                ))}
              </div>
            </aside>

            {/* CENTER — article (hero + body share this width) */}
            <article style={{ minWidth: 0, maxWidth: 800, margin: "0 auto", width: "100%" }}>
              <div style={{ display: "flex", alignItems: "center", gap: 14, marginBottom: 18 }}>
                <EBTRCategoryTag category={article.category} />
                {article.premium && <EBTRPremiumTag />}
              </div>
              <h1 style={{ fontFamily: "var(--ebtr-display)", fontSize: "clamp(24px, 3.4vw, 46px)", lineHeight: 1.1, letterSpacing: "0.015em", color: "var(--white)", margin: 0, textWrap: "balance", overflowWrap: "anywhere", textTransform: "uppercase" }}>{article.title}</h1>
              <p style={{ fontFamily: "var(--font-body)", fontSize: 21, lineHeight: 1.5, color: "var(--text-secondary)", margin: "22px 0 26px", textWrap: "pretty" }}>{article.dek}</p>

              {/* byline */}
              <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: 16, flexWrap: "wrap", paddingBottom: 24, borderBottom: "1px solid var(--border-hairline)" }}>
                <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
                  <div style={{ lineHeight: 1.3 }}>
                    <div style={{ fontFamily: "var(--font-body)", fontWeight: 700, fontSize: 15, color: "var(--white)" }}>{author.name}</div>
                    <div style={{ fontFamily: "var(--font-ui)", fontSize: 10.5, letterSpacing: "0.06em", color: "var(--text-muted)" }}>{new Date(article.date).toLocaleDateString("en-GB", { day: "numeric", month: "short", year: "numeric" })} · {article.readingMins} MIN READ</div>
                  </div>
                </div>
              </div>

              {/* share */}
              <EBTRShare title={article.title} onPdf={() => ebtrExportPdf(article, viewer || { name: "EBTR Reader", company: "EBTHub" })} />

              {/* hero — same width as the body below it */}
              <div style={{ height: 420, border: "1px solid var(--border-hairline)", margin: "28px 0 40px" }}><EBTRCover cover={article.cover} accent={cat.color} big src={article.coverUrl} /></div>

              {/* body */}
              <div className={protect ? "ebtr-protect" : undefined} style={{ position: "relative" }}>
                {watermark && viewer && <EBTRWatermark viewer={viewer} />}
                {blocks.map((b, i) => <EBTRBlock key={i} block={b} />)}
              </div>
              {locked
                ? (needsLogin
                    ? <EBTRLoginWall onSignIn={onSignIn} onApply={onApply} />
                    : <EBTRPaywall article={article} onUnlock={() => onUnlock(article.id)} onSignIn={onSignIn} />)
                : <React.Fragment><EBTRReferences refs={article.references} doi={article.doi} /><EBTRAuthorCard authorId={article.author} /></React.Fragment>}
            </article>

            {/* RIGHT RAIL — What to Read Next */}
            <aside className="ebtr-reader-right" style={{ position: "sticky", top: 100 }}>
              <div style={{ paddingBottom: 14, borderBottom: "2px solid var(--ebt-blue)", marginBottom: 8 }}>
                <span style={{ fontFamily: "var(--font-ui)", fontSize: 12, letterSpacing: "0.12em", textTransform: "uppercase", color: "var(--blue-400)" }}>What to Read Next</span>
              </div>
              {related.map((a, i) => {
                const rc = data.categories[a.category];
                return (
                  <button key={a.id} onClick={() => onOpen(a.id)} className="ebtr-next" style={{ display: "block", width: "100%", textAlign: "left", background: "none", border: "none", borderBottom: "1px solid var(--border-hairline)", padding: "20px 0", cursor: "pointer" }}>
                    <div style={{ fontFamily: "var(--font-ui)", fontSize: 15, color: ebtrAccentVar(rc.color), marginBottom: 8 }}>{String(i + 1).padStart(2, "0")}</div>
                    <div className="ebtr-next-t" style={{ fontFamily: "var(--font-body)", fontWeight: 700, fontSize: 17, lineHeight: 1.25, color: "var(--text-primary)", transition: "color var(--dur-base)" }}>{a.title}</div>
                    <div style={{ fontFamily: "var(--font-ui)", fontSize: 10, letterSpacing: "0.06em", color: "var(--text-muted)", marginTop: 8 }}>{a.readingMins} MIN{a.premium ? " · PREMIUM" : ""}</div>
                  </button>
                );
              })}
            </aside>
          </div>
        </div>
      </main>
    </React.Fragment>
  );
}

Object.assign(window, { EBTRReader });
