// ============= "Полезное" — tools overlay (niches · analyze · ROI · templates) =============
const USE_ICONS = {
  grid: <IconGrid />, file: <IconFile />, trend: <IconTrendUp />, wand: <IconWand />,
  search: <IconSearch />, gauge: <IconGauge />, check: <IconCheck />, send: <IconSend />,
  yt: <IconYT />, chart: <IconChart />, flame: <IconFlame />, inbox: <IconInbox />, msg: <IconMsg />,
};
const U_COVERS = ["a", "b", "c", "d", "e", "f", "a", "c"];
// distinct glyphs per blog topic (tag) — RU + EN
const BLOG_GLYPH = {
  "Гайд": <IconShield />, "Guide": <IconShield />,
  "Кейс": <IconRocket />, "Case": <IconRocket />,
  "Офферы": <IconSend />, "Offers": <IconSend />,
  "Аналитика": <IconChart />, "Analytics": <IconChart />,
  "Прокси": <IconGlobe />, "Proxies": <IconGlobe />,
  "Масштаб": <IconLayers />, "Scale": <IconLayers />,
};
const blogGlyph = (tag) => BLOG_GLYPH[tag] || <IconFile />;
const DEMAND_COLOR = { "Высокий": "var(--ok)", "Средний": "var(--warn)", "Низкий": "var(--text-lo)", "High": "var(--ok)", "Medium": "var(--warn)", "Low": "var(--text-lo)" };

function pctOf(replyStr) { return Math.max(8, Math.min(100, parseFloat(String(replyStr)) * 10)); }
function nicheTrend(rank) { return "+" + (16 - rank) + "%"; }

// build a big pool of niches (deterministic) from the base list
function buildNichePool(base) {
  const SUF = ["", " · Shorts", " · до 50к", " · 50–200к", " · EN-сегмент", " · регион РФ", " · нишевые", " · топ-блогеры", " · растущие"];
  const pool = [];
  base.forEach((n) => {
    const ch0 = parseInt(String(n.channels).replace(/\D/g, "")) || 4000;
    const rp0 = parseFloat(String(n.reply)) || 6;
    SUF.forEach((suf, k) => {
      const h = (n.rank * 97 + k * 41) % 100;
      const ch = Math.max(400, Math.round(ch0 * (0.28 + (h % 70) / 50)));
      const reply = Math.max(2.4, +(rp0 - k * 0.55 + ((h % 13) - 6) / 10).toFixed(1));
      pool.push({ name: n.base ? n.base + suf : n.name + suf, channels: ch, reply });
    });
  });
  return pool.sort((a, b) => b.reply - a.reply).map((n, i) => ({ ...n, rank: i + 1 }));
}

// ---------- Топ ниши (searchable / sortable leaderboard) ----------
const NICHE_L = {
  ru: { search: "Найти нишу…", sortScore: "Скоринг", sortCh: "Каналов", sortAz: "А–Я",
        fAll: "Все", fHot: "Горячие", fWarm: "Тёплые", showAll: "Показать все", collapse: "Свернуть",
        shown: "Показано", of: "из", empty: "Ничего не нашлось — измени запрос или фильтр.",
        colNiche: "Ниша", colDemand: "Спрос", colCh: "Каналов", colReply: "Конверт", colScore: "Скоринг",
        dHot: "Горячий", dWarm: "Тёплый", dCool: "Спокойный", chTip: "активных каналов", loc: "ru-RU" },
  en: { search: "Find a niche…", sortScore: "Score", sortCh: "Channels", sortAz: "A–Z",
        fAll: "All", fHot: "Hot", fWarm: "Warm", showAll: "Show all", collapse: "Collapse",
        shown: "Showing", of: "of", empty: "Nothing found — change the query or filter.",
        colNiche: "Niche", colDemand: "Demand", colCh: "Channels", colReply: "Reply", colScore: "Score",
        dHot: "Hot", dWarm: "Warm", dCool: "Calm", chTip: "active channels", loc: "en-US" },
};
const NICHE_CAP = 16;

function TopNiches({ d }) {
  const { lang } = useApp();
  const L = NICHE_L[lang] || NICHE_L.ru;
  const pool = React.useMemo(() => buildNichePool(d.niches || []), [d]);
  const demandOf = (r) => r >= 8 ? "hot" : r >= 6 ? "warm" : "cool";
  const DC = { hot: "var(--ok)", warm: "var(--accent-bright)", cool: "var(--text-lo)" };
  const DLBL = { hot: L.dHot, warm: L.dWarm, cool: L.dCool };

  const [q, setQ] = useState("");
  const [sort, setSort] = useState("score");
  const [filter, setFilter] = useState("all");
  const [expanded, setExpanded] = useState(false);

  const totalCh = pool.reduce((s, n) => s + n.channels, 0);
  const avgReply = (pool.reduce((s, n) => s + n.reply, 0) / pool.length).toFixed(1);
  const hotCount = pool.filter((n) => n.reply >= 8).length;
  const warmCount = pool.filter((n) => n.reply >= 6 && n.reply < 8).length;
  const stats = [
    [pool.length, lang === "en" ? "niches in base" : "ниш в базе"],
    [(totalCh / 1000).toFixed(0) + "K+", lang === "en" ? "active channels" : "активных каналов"],
    [avgReply + "%", lang === "en" ? "avg. reply" : "средний конверт"],
    [hotCount, lang === "en" ? "hot right now" : "горячих прямо сейчас"],
  ];

  const query = q.trim().toLowerCase();
  let rows = pool.filter((n) => {
    if (filter === "hot" && n.reply < 8) return false;
    if (filter === "warm" && !(n.reply >= 6 && n.reply < 8)) return false;
    if (query && !n.name.toLowerCase().includes(query)) return false;
    return true;
  });
  if (sort === "channels") rows = [...rows].sort((a, b) => b.channels - a.channels);
  else if (sort === "az") rows = [...rows].sort((a, b) => a.name.localeCompare(b.name));
  // "score" keeps the pool order (already ranked by reply)

  const total = rows.length;
  const visible = expanded ? rows : rows.slice(0, NICHE_CAP);
  const maxCh = Math.max(...pool.map((n) => n.channels), 1);

  const sorts = [["score", L.sortScore], ["channels", L.sortCh], ["az", L.sortAz]];
  const filters = [["all", L.fAll, pool.length], ["hot", L.fHot, hotCount], ["warm", L.fWarm, warmCount]];

  return (
    <React.Fragment>
      <div className="use-niches__head">
        <div className="use-niches__t">{d.nichesHead}</div>
        <div className="use-niches__s">{d.nichesSub}</div>
      </div>
      <div className="nstats">
        {stats.map(([v, l], i) => (
          <div key={i} className="nstat"><div className="nstat__v">{v}</div><div className="nstat__l">{l}</div></div>
        ))}
      </div>

      {/* controls */}
      <div className="nctrl">
        <div className="nctrl__search">
          <IconSearch />
          <input value={q} placeholder={L.search} onChange={(e) => { setQ(e.target.value); setExpanded(false); }} />
          {q ? <button className="nctrl__clear" onClick={() => setQ("")} aria-label="Clear"><IconX /></button> : null}
        </div>
        <div className="nctrl__sort">
          {sorts.map(([id, lbl]) => (
            <button key={id} className={sort === id ? "on" : ""} onClick={() => setSort(id)}>{lbl}</button>
          ))}
        </div>
      </div>
      <div className="nctrl__filters">
        {filters.map(([id, lbl, c]) => (
          <button key={id} className={`nchip ${filter === id ? "on" : ""}`} onClick={() => { setFilter(id); setExpanded(false); }}>
            {id !== "all" ? <span className="nchip__dot" style={{ background: id === "hot" ? DC.hot : DC.warm }}></span> : null}
            {lbl}<span className="nchip__c">{c}</span>
          </button>
        ))}
      </div>

      {/* leaderboard */}
      {total === 0 ? (
        <div className="nlead-empty"><IconSearch />{L.empty}</div>
      ) : (
        <React.Fragment>
          <div className="nlead">
            <div className="nlrow nlrow--h">
              <span>#</span>
              <span>{L.colNiche}</span>
              <span className="nl-demand">{L.colDemand}</span>
              <span className="nl-ch">{L.colCh}</span>
              <span className="nl-reply">{L.colReply}</span>
              <span className="nl-score">{L.colScore}</span>
            </div>
            {visible.map((n) => {
              const score = Math.round(pctOf(n.reply + "%"));
              const dm = demandOf(n.reply);
              const chPct = Math.round((n.channels / maxCh) * 100);
              return (
                <div key={n.rank} className={`nlrow ${n.rank <= 3 ? "nlrow--top" : ""}`}>
                  <span className={`nlrow__rank rank--${dm}`}>{n.rank}</span>
                  <span className="nlrow__name">{n.name}</span>
                  <span className="nl-demand nlrow__demand" style={{ color: DC[dm] }}>
                    <span className="nlrow__dot" style={{ background: DC[dm] }}></span>{DLBL[dm]}
                  </span>
                  <span className="nl-ch nlrow__ch">
                    <span className="nlrow__chnum">{n.channels.toLocaleString(L.loc)}</span>
                    <span className="nlrow__chbar"><i style={{ width: chPct + "%" }}></i></span>
                  </span>
                  <span className="nl-reply nlrow__reply" style={{ color: DC[dm] }}><IconTrendUp />{n.reply}%</span>
                  <span className="nl-score nlrow__score">
                    <span className="nlrow__scbar"><i style={{ width: score + "%", background: DC[dm] }}></i></span>
                    <b>{score}</b>
                  </span>
                </div>
              );
            })}
          </div>
          <div className="nlead__foot">
            <span className="nlead__count">{L.shown} <b>{visible.length}</b> {L.of} {total}</span>
            {total > NICHE_CAP ? (
              <button className="nlead__more" onClick={() => setExpanded((v) => !v)}>
                {expanded ? L.collapse : `${L.showAll} (${total})`}
                <IconChevD style={{ transform: expanded ? "rotate(180deg)" : "none" }} />
              </button>
            ) : null}
          </div>
        </React.Fragment>
      )}
    </React.Fragment>
  );
}

// ---------- Анализ ниши (type → result) ----------
function hashStr(s) { let h = 5381; for (let i = 0; i < s.length; i++) h = ((h << 5) + h + s.charCodeAt(i)) >>> 0; return h; }
function NicheAnalyze({ d }) {
  const niches = d.niches || [];
  const [q, setQ] = useState("");
  const [res, setRes] = useState(null);
  const [loading, setLoading] = useState(false);
  const suggest = niches.slice(0, 5).map((n) => n.name.split(" ")[0]);

  const analyze = (query) => {
    const term = (query || q).trim();
    if (!term) return;
    setRes(null);
    setLoading(true);
    setTimeout(() => {
      const found = niches.find((n) => n.name.toLowerCase().includes(term.toLowerCase()) || term.toLowerCase().includes(n.name.toLowerCase().split(" ")[0]));
      let r;
      if (found) {
        r = { name: found.name, demand: found.demand, channels: found.channels, reply: found.reply, rank: found.rank, exact: true };
      } else {
        const h = hashStr(term.toLowerCase());
        const ch = 1800 + (h % 16000);
        const reply = (4.2 + (h % 60) / 10).toFixed(1);
        const dm = reply >= 8 ? (d.nicheCols && niches[0].demand) : reply >= 6 ? niches[3].demand : niches[9].demand;
        r = { name: term, demand: dm, channels: ch.toLocaleString("ru-RU"), reply: reply + "%", rank: 0, exact: false };
      }
      setRes(r);
      setLoading(false);
    }, 680);
  };

  const score = res ? pctOf(res.reply) : 0;
  const recKey = res ? (score >= 80 ? "hot" : score >= 60 ? "warm" : "cold") : null;

  return (
    <React.Fragment>
      <div className="use-niches__head">
        <div className="use-niches__t">{d.analyzeHead}</div>
        <div className="use-niches__s">{d.analyzeSub}</div>
      </div>
      <div className="anz2">
        <div className="anz2__search">
          <span className="anz2__ico"><IconSearch /></span>
          <input className="anz2__input" value={q} placeholder={d.analyzePlaceholder}
            onChange={(e) => setQ(e.target.value)} onKeyDown={(e) => { if (e.key === "Enter") analyze(); }} />
          <button className={`btn btn--primary anz2__btn ${loading ? "anz2__btn--loading" : ""}`} onClick={() => analyze()} disabled={loading}>
            {loading ? <span className="anz2__spin"><IconSpark /></span> : d.analyzeBtn}
          </button>
        </div>
        <div className="anz2__try">
          <span className="anz2__try-l">{d.analyzeTry}</span>
          {suggest.map((s, i) => <button key={i} className="anz2__chip" onClick={() => { setQ(s); analyze(s); }}>{s}</button>)}
        </div>

        {loading && (
          <div className="anz2__skeleton">
            <div className="anz2__skel-row">
              <div className="anz2__skel-block anz2__skel-block--name"></div>
              <div className="anz2__skel-block anz2__skel-block--badge"></div>
            </div>
            <div className="anz2__skel-stats">
              <div className="anz2__skel-block anz2__skel-block--stat"></div>
              <div className="anz2__skel-block anz2__skel-block--stat"></div>
              <div className="anz2__skel-block anz2__skel-block--stat"></div>
            </div>
            <div className="anz2__skel-block anz2__skel-block--bar"></div>
            <div className="anz2__skel-block anz2__skel-block--rec"></div>
          </div>
        )}

        {res && (
          <div className="anz2__result" key={res.name + res.reply}>
            <div className="anz2__rhead">
              <div>
                <div className="anz2__rname">{res.name}</div>
                <div className="anz2__rsub">{res.exact ? "" : "≈ "}{res.channels} {d.analyzeChannels.toLowerCase()}</div>
              </div>
              <span className="anz2__rdemand" style={{ color: DEMAND_COLOR[res.demand] }}><span className="bdot" style={{ background: DEMAND_COLOR[res.demand] }}></span>{res.demand}</span>
            </div>
            <div className="anz2__stats">
              <div className="anz2__stat"><div className="anz2__sl">{d.analyzeChannels}</div><div className="anz2__sv">{res.channels}</div></div>
              <div className="anz2__stat"><div className="anz2__sl">{d.analyzeReply}</div><div className="anz2__sv" style={{ color: "var(--ok)" }}>{res.reply}</div></div>
              <div className="anz2__stat"><div className="anz2__sl">{d.analyzeScore}</div><div className="anz2__sv" style={{ color: "var(--accent-bright)" }}>{Math.round(score)}<span style={{ fontSize: 14, color: "var(--text-dim)" }}>/100</span></div></div>
            </div>
            <div className="anz2__scorebar"><i style={{ width: `${score}%` }}></i></div>
            <div className="anz2__rec"><IconBolt />{d.analyzeRec[recKey]}</div>
          </div>
        )}
      </div>
    </React.Fragment>
  );
}

// ---------- ROI calculator (lag-free + expenses) ----------
function RoiRange({ label, value, display, min, max, step, onChange }) {
  const fill = Math.round((value - min) / (max - min) * 100);
  return (
    <div className="roi__row">
      <div className="roi__rowtop"><span className="roi__lbl">{label}</span><span className="roi__val">{display}</span></div>
      <input className="roi__range" type="range" min={min} max={max} step={step} value={value}
        style={{ "--fill": fill + "%" }} onChange={(e) => onChange(+e.target.value)} />
    </div>
  );
}

function RoiCalc({ d, lang }) {
  const isRu = lang !== "en";
  const cur = isRu ? "₽" : "$";
  const fmt = (n) => Math.round(n).toLocaleString(isRu ? "ru-RU" : "en-US");
  const tariffs = d.roiTariffs || [];

  const [leads, setLeads] = useState(5000);
  const [reply, setReply] = useState(9);
  const [close, setClose] = useState(12);
  const [deal, setDeal] = useState(isRu ? 500 : 8);
  const [accounts, setAccounts] = useState(3);
  const [accCost, setAccCost] = useState(isRu ? 350 : 4);
  const [proxy, setProxy] = useState(isRu ? 1500 : 18);
  const [tariff, setTariff] = useState(1);

  const replies = leads * reply / 100;
  const deals = replies * close / 100;
  const revenue = deals * deal;
  const costs = (tariffs[tariff] ? tariffs[tariff].price : 0) + accounts * accCost + proxy;
  const profit = revenue - costs;
  const roi = costs > 0 ? (profit / costs * 100) : 0;
  const costPerReply = replies > 0 ? costs / replies : 0;
  const paybackDays = profit > 0 ? Math.max(1, Math.ceil(costs / (profit / 30))) : 0;

  const dealMax = isRu ? 50000 : 1000, dealStep = isRu ? 100 : 5, dealMin = isRu ? 100 : 2;
  const accMax = isRu ? 1200 : 12, accStep = isRu ? 50 : 1, accMin = isRu ? 100 : 1;
  const pxMax = isRu ? 12000 : 150, pxStep = isRu ? 250 : 3, pxMin = 0;

  return (
    <React.Fragment>
      <div className="use-niches__head">
        <div className="use-niches__t">{d.roiHead}</div>
        <div className="use-niches__s">{d.roiSub}</div>
      </div>
      <div className="roi">
        <div className="roi__inputs">
          <div className="roi__tariff">
            <div className="roi__lbl" style={{ marginBottom: 11 }}>{d.roiTariff}</div>
            <div className="roi__cards">
              {tariffs.map((tt, i) => (
                <button key={tt.id} className={`roi__card ${tariff === i ? "on" : ""}`} onClick={() => setTariff(i)}>
                  {tariff === i ? <span className="roi__card-check"><IconCheck /></span> : null}
                  <span className="roi__card-name">{tt.name}</span>
                  <span className="roi__card-price">{fmt(tt.price)} {cur}</span>
                </button>
              ))}
            </div>
          </div>
          <RoiRange label={d.roiLeads} value={leads} display={fmt(leads)} min={500} max={25000} step={500} onChange={setLeads} />
          <RoiRange label={d.roiReply} value={reply} display={reply + "%"} min={1} max={25} step={1} onChange={setReply} />
          <RoiRange label={d.roiClose} value={close} display={close + "%"} min={2} max={40} step={1} onChange={setClose} />
          <RoiRange label={d.roiDeal} value={deal} display={fmt(deal) + " " + cur} min={dealMin} max={dealMax} step={dealStep} onChange={setDeal} />
          <RoiRange label={d.roiAccounts} value={accounts} display={accounts} min={1} max={20} step={1} onChange={setAccounts} />
          <RoiRange label={d.roiAccCost} value={accCost} display={fmt(accCost) + " " + cur} min={accMin} max={accMax} step={accStep} onChange={setAccCost} />
          <RoiRange label={d.roiProxy} value={proxy} display={fmt(proxy) + " " + cur} min={pxMin} max={pxMax} step={pxStep} onChange={setProxy} />
        </div>

        <div className="roi__out">
          <div className="roi__out-row"><span>{d.roiOutReplies}</span><b>{fmt(replies)}</b></div>
          <div className="roi__out-row"><span>{d.roiOutDeals}</span><b>{fmt(deals)}</b></div>
          <div className="roi__out-row"><span>{d.roiOutRev}</span><b style={{ color: "var(--ok)" }}>{fmt(revenue)} {cur}</b></div>
          <div className="roi__out-row"><span>{d.roiOutCost}</span><b style={{ color: "var(--bad)" }}>−{fmt(costs)} {cur}</b></div>
          <div className="roi__profit">
            <div className="roi__profit-l">{d.roiOutProfit}</div>
            <div className="roi__profit-v">{fmt(profit)} <span>{cur}</span></div>
            <div className="roi__roi"><IconTrendUp />ROI {fmt(roi)}%</div>
          </div>
          <div className="roi__extra">
            <div className="roi__xc">
              <div className="roi__xl">{isRu ? "Цена ответа" : "Cost / reply"}</div>
              <div className="roi__xv">{fmt(costPerReply)} {cur}</div>
            </div>
            <div className="roi__xc">
              <div className="roi__xl">{isRu ? "Окупаемость" : "Payback"}</div>
              <div className="roi__xv">{paybackDays ? paybackDays + (isRu ? " дн." : "d") : "—"}</div>
            </div>
          </div>
          <div className="roi__note">{d.roiNote}</div>
        </div>
      </div>
    </React.Fragment>
  );
}

// ---------- Templates ----------
function Templates({ d }) {
  const list = d.templates || [];
  const [copied, setCopied] = useState(-1);
  const doCopy = (txt, i) => {
    try { navigator.clipboard && navigator.clipboard.writeText(txt); } catch (e) {}
    setCopied(i); setTimeout(() => setCopied((c) => (c === i ? -1 : c)), 1600);
  };
  return (
    <React.Fragment>
      <div className="use-niches__head">
        <div className="use-niches__t">{d.templatesHead}</div>
        <div className="use-niches__s">{d.templatesSub}</div>
      </div>
      <div className="tpl">
        {list.map((tp, i) => (
          <div key={i} className="tpl__card">
            <div className="tpl__top">
              <span className="use-art__tag">{tp.tag}</span>
              <span className="tpl__title">{tp.title}</span>
              <button className={`tpl__copy ${copied === i ? "ok" : ""}`} onClick={() => doCopy(tp.text, i)}>
                {copied === i ? <React.Fragment><IconCheck />{d.copied}</React.Fragment> : <React.Fragment><IconFile />{d.copy}</React.Fragment>}
              </button>
            </div>
            <p className="tpl__text">{tp.text}</p>
          </div>
        ))}
      </div>
    </React.Fragment>
  );
}

const TOOL_TABS = ["niches", "analyze", "roi", "blog"];

// ---------- Обзор функций (separate block: sidebar of functions → articles) ----------
const FEAT_ARTICLES = {
  yt: [1, 0], verify: [4], outreach: [0, 2], analytics: [3], warmup: [0], crm: [5], aihelp: [2], tgparser: [1],
};
function FeaturesOverlay() {
  const { lang, setFeaturesOpen, t } = useApp();
  const d = (window.USEFUL[lang]) || window.USEFUL.ru;
  const feats = d.features || [];
  const blog = d.blog || [];
  const [sel, setSel] = useState(0);
  const [post, setPost] = useState(null);

  useEffect(() => {
    const onKey = (e) => { if (e.key === "Escape") { post ? setPost(null) : setFeaturesOpen(false); } };
    window.addEventListener("keydown", onKey);
    document.body.style.overflow = "hidden";
    return () => { window.removeEventListener("keydown", onKey); document.body.style.overflow = ""; };
  }, [post]);

  const close = () => setFeaturesOpen(false);
  const openPost = (type, item, cover) => { setPost({ type, item, cover }); const b = document.querySelector(".use-back"); if (b) b.scrollTo({ top: 0 }); };

  if (post) {
    return (
      <div className="use-back">
        <div className="use-panel use-panel--reader">
          <div className="use-rbar">
            <button className="use-back-btn" onClick={() => setPost(null)}><IconChevL />{d.back}</button>
            <button className="use-close" onClick={close} aria-label="Close"><IconX /></button>
          </div>
          <PostReader d={d} post={post} t={t} onBack={() => setPost(null)} onClose={close} />
        </div>
      </div>
    );
  }

  const f = feats[sel] || {};
  const related = (FEAT_ARTICLES[f.id] || []).map((i) => blog[i]).filter(Boolean);

  return (
    <div className="use-back" onClick={(e) => { if (e.target === e.currentTarget) close(); }}>
      <div className="use-panel">
        <div className="use-stickytop">
          <div className="use-head">
            <div className="use-head__main">
              <span className="use-head__kick">{d.kbEyebrow || "База знаний"}</span>
              <h1 className="use-head__t">{d.featKicker}</h1>
              <p className="use-head__s">{d.kbSub}</p>
            </div>
            <button className="use-close" onClick={close} aria-label="Close"><IconX /></button>
          </div>
        </div>

        <div className="fov">
          <aside className="fov__side">
            <div className="blogside__t">{d.featKicker}</div>
            {feats.map((ff, i) => (
              <button key={ff.id} className={`fov__item ${sel === i ? "on" : ""}`} onClick={() => setSel(i)}>
                <span className="fov__item-ico">{USE_ICONS[ff.ico] || <IconFile />}</span>
                <span className="fov__item-tx">{ff.title}</span>
              </button>
            ))}
          </aside>

          <div className="fov__main use-anim" key={f.id}>
            <div className="fov__hero">
              <div className={`fov__hero-cover use-cover--${U_COVERS[sel % U_COVERS.length]}`}>
                <span className="use-cover__glyph use-cover__glyph--lg">{USE_ICONS[f.ico] || <IconFile />}</span>
                <span className="use-cover__chip">{f.tag}</span>
              </div>
              <div className="fov__hero-tx">
                <div className="fov__hero-kick">{d.featKicker}</div>
                <h2 className="fov__hero-t">{f.title}</h2>
                <p className="fov__hero-d">{f.excerpt}</p>
                <button className="btn btn--primary btn--sm" onClick={() => openPost("feature", f, U_COVERS[sel % U_COVERS.length])}>{d.read}<IconArrUp style={{ transform: "rotate(45deg)" }} /></button>
              </div>
            </div>
            <div className="use-secline"><span className="use-secline__t">{d.kbAll || "Статьи по теме"}</span><span className="use-secline__c">{related.length + 1}</span></div>
            <div className="use-blog fov__grid">
              <PostCard cover={U_COVERS[sel % U_COVERS.length]} glyph={USE_ICONS[f.ico] || <IconFile />} kicker={d.featKicker}
                tag={f.tag} title={f.title} excerpt={f.excerpt} more={d.read}
                onClick={() => openPost("feature", f, U_COVERS[sel % U_COVERS.length])} />
              {related.map((a) => (
                <PostCard key={a.id} cover={a.cover} glyph={blogGlyph(a.tag)} kicker={d.blogKicker}
                  tag={a.tag} title={a.title} excerpt={a.excerpt} date={a.date} more={d.read}
                  onClick={() => openPost("blog", a, a.cover)} />
              ))}
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

// ---------- blog with topic sidebar ----------
function BlogWithTopics({ d, openPost }) {
  const topics = d.blogTopics || [{ id: "all", label: "Все", tags: null }];
  const [topic, setTopic] = useState("all");
  const all = d.blog || [];
  const count = (tp) => tp.tags ? all.filter((a) => tp.tags.includes(a.tag)).length : all.length;
  const active = topics.find((tp) => tp.id === topic) || topics[0];
  const list = active.tags ? all.filter((a) => active.tags.includes(a.tag)) : all;
  return (
    <div className="blogwrap">
      <aside className="blogside">
        <div className="blogside__t">{d.blogTopicsTitle}</div>
        {topics.map((tp) => (
          <button key={tp.id} className={`blogside__item ${topic === tp.id ? "on" : ""}`} onClick={() => setTopic(tp.id)}>
            <span>{tp.label}</span><span className="blogside__c">{count(tp)}</span>
          </button>
        ))}
      </aside>
      <div className="use-blog blogwrap__grid" key={topic}>
        {list.map((a) => (
          <PostCard key={a.id} cover={a.cover} glyph={blogGlyph(a.tag)} kicker={d.blogKicker}
            tag={a.tag} title={a.title} excerpt={a.excerpt} date={a.date} more={d.read}
            onClick={() => openPost("blog", a, a.cover)} />
        ))}
      </div>
    </div>
  );
}

// ---------- feature / blog posts ----------
function PostCard({ cover, glyph, kicker, tag, title, excerpt, date, more, onClick }) {
  return (
    <button className="use-art" onClick={onClick}>
      <div className={`use-cover use-cover--${cover}`}>
        <span className="use-cover__glyph">{glyph}</span>
        {tag ? <span className="use-cover__chip">{tag}</span> : null}
      </div>
      <div className="use-art__body">
        <div className="use-art__meta"><span className="use-art__kick">{kicker}</span>{date ? <span>· {date}</span> : null}</div>
        <div className="use-art__t">{title}</div>
        <div className="use-art__ex">{excerpt}</div>
        <div className="use-art__foot">{more}<IconArrUp style={{ transform: "rotate(45deg)" }} /></div>
      </div>
    </button>
  );
}

function ReaderBlock({ b }) {
  if (typeof b === "string") return <p>{b}</p>;
  if (b.h) return <h2 className="use-reader__h2">{b.h}</h2>;
  if (b.ul) return (
    <ul className="use-reader__ul">
      {b.ul.map((li, i) => <li key={i}>{li}</li>)}
    </ul>
  );
  if (b.ol) return (
    <ol className="use-reader__ol">
      {b.ol.map((li, i) => <li key={i}><span className="use-reader__oln">{i + 1}</span><span>{li}</span></li>)}
    </ol>
  );
  if (b.note) return (
    <div className="use-reader__note"><span className="use-reader__note-ico"><IconBolt /></span><div>{b.note}</div></div>
  );
  if (b.quote) return (
    <blockquote className="use-reader__quote">{b.quote}{b.by ? <cite>{b.by}</cite> : null}</blockquote>
  );
  return null;
}

function PostReader({ d, post, onBack, onClose, t }) {
  const { ctaHref, ctaLabel } = useApp();
  const it = post.item;
  const isBlog = post.type === "blog";
  const cover = post.cover || (isBlog ? it.cover : "a");
  const glyph = isBlog ? blogGlyph(it.tag) : (USE_ICONS[it.ico] || <IconFile />);
  return (
    <article className="use-reader use-anim" key={it.id}>
      <div className={`use-reader__cover use-cover--${cover}`}>
        <span className="use-cover__glyph use-cover__glyph--lg">{glyph}</span>
        <span className="use-reader__cover-kick">{isBlog ? d.blogKicker : d.featKicker}</span>
      </div>
      <div className="use-reader__head">
        <div className="use-reader__meta">
          <span className="use-art__tag">{it.tag}</span>
          <span>·</span><span>{isBlog ? it.date : d.featKicker}</span>
        </div>
        <h1 className="use-reader__t">{it.title}</h1>
        {it.excerpt ? <p className="use-reader__lead">{it.excerpt}</p> : null}
      </div>
      <div className="use-reader__body">
        {it.body.map((b, i) => <ReaderBlock key={i} b={b} />)}
      </div>
      <div className="use-reader__cta">
        <div className="use-reader__cta-tx">
          <div className="use-reader__cta-t">{d.ctaTitle}</div>
          <div className="use-reader__cta-s">{d.ctaSub}</div>
        </div>
        <a href={ctaHref} className="btn btn--primary btn--lg" onClick={onClose}>{ctaLabel("hero.cta")}<IconArrUp style={{ transform: "rotate(45deg)" }} /></a>
      </div>
    </article>
  );
}

function UsefulOverlay({ initialTab }) {
  const { lang, setUsefulOpen, t } = useApp();
  const d = (window.USEFUL[lang]) || window.USEFUL.ru;
  const start = (typeof initialTab === "string" && TOOL_TABS.includes(initialTab)) ? initialTab : "niches";
  const [tab, setTab] = useState(start);
  const [post, setPost] = useState(null);
  const openPost = (type, item, cover) => { setPost({ type, item, cover }); const b = document.querySelector(".use-back"); if (b) b.scrollTo({ top: 0 }); };

  useEffect(() => {
    const onKey = (e) => { if (e.key === "Escape") { post ? setPost(null) : setUsefulOpen(false); } };
    window.addEventListener("keydown", onKey);
    document.body.style.overflow = "hidden";
    return () => { window.removeEventListener("keydown", onKey); document.body.style.overflow = ""; };
  }, [post]);

  const close = () => setUsefulOpen(false);

  if (post) {
    return (
      <div className="use-back">
        <div className="use-panel use-panel--reader">
          <div className="use-rbar">
            <button className="use-back-btn" onClick={() => setPost(null)}><IconChevL />{d.back}</button>
            <button className="use-close" onClick={close} aria-label="Close"><IconX /></button>
          </div>
          <PostReader d={d} post={post} t={t} onBack={() => setPost(null)} onClose={close} />
        </div>
      </div>
    );
  }

  return (
    <div className="use-back" onClick={(e) => { if (e.target === e.currentTarget) close(); }}>
      <div className="use-panel">
        <div className="use-stickytop">
          <div className="use-head">
            <div className="use-head__main">
              <span className="use-head__kick">{d.title}</span>
              <h1 className="use-head__t">{d.headline}</h1>
              <p className="use-head__s">{d.sub}</p>
            </div>
            <button className="use-close" onClick={close} aria-label="Close"><IconX /></button>
          </div>

          <div className="use-tabs">
            {d.tabs.map((tb) => (
              <button key={tb.id} className={`use-tab ${tab === tb.id ? "active" : ""}`} onClick={() => setTab(tb.id)}>
                {USE_ICONS[tb.ico]}{tb.label}
              </button>
            ))}
          </div>
        </div>

        <div className="use-body use-anim" key={tab}>
          {tab === "niches" && <TopNiches d={d} />}
          {tab === "analyze" && <NicheAnalyze d={d} />}
          {tab === "roi" && <RoiCalc d={d} lang={lang} />}
          {tab === "blog" && <BlogWithTopics d={d} openPost={openPost} />}
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { UsefulOverlay, FeaturesOverlay });
