// portfolio-screen.jsx — the full Portfolio screen, themeable
// Exports to window: PortfolioScreen, THEMES
// Правки относительно дизайн-исходника (минимальные):
//   • PortfolioScreen принимает props data/onRefresh (живые данные + реальный refresh)
//   • RangeBar считает позицию маркера из реальной цены пула; V2 (без диапазона) скрыт
//   • группы рендерятся только если в них есть данные; строка «Долг» — только если есть

const { useState: useStateS, useEffect: useEffectS } = React;

// ---------------- themes ----------------
const THEMES = {
  slate: {
    name: "A · Слейт",
    desc: "Тёмная · приглушённый слейт-акцент · сводка сеткой",
    layout: "grid",
    dark: true,
    vars: {
      "--bg": "#0d1117",
      "--card": "#161b22",
      "--card2": "#1b2230",
      "--border": "#2b3441",
      "--border-soft": "#21262d",
      "--text": "#e6edf3",
      "--muted": "#8b949e",
      "--dim": "#5e6772",
      "--accent": "oklch(0.70 0.045 250)",
      "--accent-soft": "oklch(0.70 0.045 250 / 0.16)",
      "--pos": "#3fb950",
      "--neg": "#f85149",
      "--pos-soft": "rgba(63,185,80,0.14)",
      "--neg-soft": "rgba(248,81,73,0.14)",
      "--pos-line": "rgba(63,185,80,0.30)",
      "--neg-line": "rgba(248,81,73,0.32)",
      "--shadow": "none"
    },
    font: "ui-sans-serif, -apple-system, 'Segoe UI', system-ui, sans-serif",
    radius: 12
  },
  taupe: {
    name: "B · Биржа",
    desc: "Тёмная almost-black · белые тикеры · серые полосы",
    layout: "hero",
    dark: true,
    vars: {
      "--bg": "#0b0e11",
      "--card": "#181a20",
      "--card2": "#1e2329",
      "--border": "#2b3139",
      "--border-soft": "#232830",
      "--text": "#eaecef",
      "--muted": "#848e9c",
      "--dim": "#5e6673",
      "--accent": "#eaecef",
      "--accent-soft": "rgba(132,142,156,0.18)",
      "--bar": "#5e6673",
      "--pos": "#0ecb81",
      "--neg": "#f6465d",
      "--pos-soft": "rgba(14,203,129,0.14)",
      "--neg-soft": "rgba(246,70,93,0.14)",
      "--pos-line": "rgba(14,203,129,0.32)",
      "--neg-line": "rgba(246,70,93,0.34)",
      "--shadow": "none"
    },
    font: "ui-sans-serif, -apple-system, 'Segoe UI', system-ui, sans-serif",
    radius: 14
  },
  sage: {
    name: "C · Шалфей",
    desc: "Светлая тема · серо-зелёный акцент · воздушно",
    layout: "airy",
    dark: false,
    vars: {
      "--bg": "#f5f7f8",
      "--card": "#ffffff",
      "--card2": "#f0f3f4",
      "--border": "#e2e7e9",
      "--border-soft": "#eef1f2",
      "--text": "#1b2630",
      "--muted": "#5d6c76",
      "--dim": "#94a0a8",
      "--accent": "oklch(0.55 0.045 168)",
      "--accent-soft": "oklch(0.55 0.045 168 / 0.12)",
      "--pos": "oklch(0.54 0.13 150)",
      "--neg": "oklch(0.55 0.18 28)",
      "--pos-soft": "oklch(0.54 0.13 150 / 0.12)",
      "--neg-soft": "oklch(0.55 0.18 28 / 0.12)",
      "--pos-line": "oklch(0.54 0.13 150 / 0.28)",
      "--neg-line": "oklch(0.55 0.18 28 / 0.30)",
      "--shadow": "0 1px 2px rgba(20,40,60,0.04), 0 4px 16px rgba(20,40,60,0.05)"
    },
    font: "ui-sans-serif, -apple-system, 'Segoe UI', system-ui, sans-serif",
    radius: 16
  },
  exchangeLight: {
    name: "B · Биржа · светлая",
    desc: "Светлая тема · нейтральные тикеры · серые полосы · крупная цифра PnL",
    layout: "hero",
    dark: false,
    vars: {
      "--bg": "#f5f7fa",
      "--card": "#ffffff",
      "--card2": "#f0f2f5",
      "--border": "#e6e8ec",
      "--border-soft": "#eef0f3",
      "--text": "#1e2026",
      "--muted": "#707a8a",
      "--dim": "#aeb4bf",
      "--accent": "#1e2026",
      "--accent-soft": "rgba(112,122,138,0.16)",
      "--bar": "#aeb4bf",
      "--pos": "#0a9e63",
      "--neg": "#d6304a",
      "--pos-soft": "rgba(10,158,99,0.12)",
      "--neg-soft": "rgba(214,48,74,0.12)",
      "--pos-line": "rgba(10,158,99,0.28)",
      "--neg-line": "rgba(214,48,74,0.30)",
      "--shadow": "0 1px 2px rgba(30,32,38,0.04), 0 4px 16px rgba(30,32,38,0.05)"
    },
    font: "ui-sans-serif, -apple-system, 'Segoe UI', system-ui, sans-serif",
    radius: 14
  }
};

// ---------------- helpers ----------------
function agoText(ms) {
  const s = Math.floor((Date.now() - ms) / 1000);
  if (s < 60) return "только что";
  const m = Math.floor(s / 60);
  if (m < 60) return `${m} мин назад`;
  const h = Math.floor(m / 60);
  return `${h} ч назад`;
}

// ---------------- small pieces ----------------
function RefreshBtn({ onClick, spinning }) {
  return (
    <button
      onClick={onClick}
      style={{
        display: "inline-flex",
        alignItems: "center",
        justifyContent: "center",
        width: 34,
        height: 34,
        borderRadius: 10,
        border: "1px solid var(--border)",
        background: "var(--card2)",
        color: "var(--muted)",
        cursor: "pointer",
        flex: "none",
        padding: 0
      }}
      aria-label="Обновить">

      <svg
        width="16" height="16" viewBox="0 0 24 24" fill="none"
        stroke="currentColor" strokeWidth="2.1" strokeLinecap="round" strokeLinejoin="round"
        style={{ animation: spinning ? "pf-spin 0.7s linear" : "none" }}>

        <path d="M21 12a9 9 0 1 1-2.64-6.36" />
        <path d="M21 3v6h-6" />
      </svg>
    </button>);

}

function Header({ updatedAt, onRefresh, layout, headerExtra }) {
  const [, force] = useStateS(0);
  const [spin, setSpin] = useStateS(false);
  const [ts, setTs] = useStateS(updatedAt);
  useEffectS(() => {
    const t = setInterval(() => force((x) => x + 1), 15000);
    return () => clearInterval(t);
  }, []);
  // синхронизируем отметку времени при приходе новых данных от родителя
  useEffectS(() => { setTs(updatedAt); }, [updatedAt]);
  const refresh = () => {
    setSpin(true);
    if (onRefresh) onRefresh();         // реальный refetch
    setTimeout(() => {
      setTs(Date.now());
      setSpin(false);
    }, 750);
  };
  return (
    <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: 12 }}>
      <div style={{ display: "flex", flexDirection: "column", gap: 3 }}>
        <div style={{ fontSize: 19, fontWeight: 700, letterSpacing: -0.3, color: "var(--text)" }}>
          Портфель
        </div>
        <div style={{ display: "flex", alignItems: "center", gap: 6, fontSize: 12.5, color: "var(--dim)" }}>
          <window.Dot color="var(--pos)" size={6} />
          обновлено {agoText(ts)}
        </div>
      </div>
      <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
        {headerExtra}
        <RefreshBtn onClick={refresh} spinning={spin} />
      </div>
    </div>);

}

// ---- Summary layouts ----
function Stat({ label, children, sub, big, accentValue }) {
  return (
    <div
      style={{
        display: "flex",
        flexDirection: "column",
        gap: 5,
        padding: "13px 14px",
        background: "var(--card)",
        border: "1px solid var(--border-soft)",
        borderRadius: 12,
        boxShadow: "var(--shadow)"
      }}>

      <div style={{ fontSize: 11.5, color: "var(--muted)", textTransform: "uppercase", letterSpacing: 0.6, fontWeight: 600 }}>
        {label}
      </div>
      <div style={{ fontSize: big ? 22 : 18, fontWeight: 700, color: accentValue || "var(--text)", fontVariantNumeric: "tabular-nums", letterSpacing: -0.4 }}>
        {children}
      </div>
      {sub && <div style={{ fontSize: 12.5, color: "var(--muted)", fontVariantNumeric: "tabular-nums" }}>{sub}</div>}
    </div>);

}

function SummaryGrid({ s, fx }) {
  return (
    <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 9 }}>
      <Stat label="Вложено">{window.fmt.money(s.investedEur, s.cur, { dec: 0 })}</Stat>
      <Stat label="Стоимость" sub={window.fmt.money(s.valueEur, s.cur, { dec: 0 })}>
        {window.fmt.money(s.valueUsd, "$", { dec: 0 })}
      </Stat>
      <Stat label="PnL" accentValue={s.pnlEur >= 0 ? "var(--pos)" : "var(--neg)"} sub={
      <window.Pnl v={s.pnlPct}>{window.fmt.pct(s.pnlPct, { sign: true })}</window.Pnl>
      }>
        {window.fmt.money(s.pnlEur, s.cur, { dec: 0, sign: true })}
      </Stat>
      <Stat label={`Курс ${s.curCode}/USD`}>{window.fmt.rate(fx)}</Stat>
    </div>);

}

function SummaryHero({ s, fx }) {
  return (
    <div
      style={{
        background: "var(--card)",
        border: "1px solid var(--border-soft)",
        borderRadius: 18,
        padding: "20px 18px 16px",
        boxShadow: "var(--shadow)"
      }}>

      <div style={{ fontSize: 11.5, color: "var(--muted)", textTransform: "uppercase", letterSpacing: 0.7, fontWeight: 600 }}>
        Прибыль / убыток
      </div>
      <div style={{ display: "flex", alignItems: "baseline", gap: 12, marginTop: 6, flexWrap: "wrap" }}>
        <span style={{ fontSize: 38, fontWeight: 800, letterSpacing: -1.2, color: s.pnlEur >= 0 ? "var(--pos)" : "var(--neg)", fontVariantNumeric: "tabular-nums" }}>
          {window.fmt.money(s.pnlEur, s.cur, { dec: 0, sign: true })}
        </span>
        <span style={{ fontSize: 17, fontWeight: 700, color: s.pnlEur >= 0 ? "var(--pos)" : "var(--neg)" }}>
          {window.fmt.pct(s.pnlPct, { sign: true })}
        </span>
      </div>
      <div style={{ height: 1, background: "var(--border-soft)", margin: "16px -18px 14px" }} />
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 4 }}>
        <MiniStat label="Вложено" value={window.fmt.money(s.investedEur, s.cur, { dec: 0 })} />
        <MiniStat label="Стоимость" value={window.fmt.money(s.valueUsd, "$", { dec: 0 })} sub={window.fmt.money(s.valueEur, s.cur, { dec: 0 })} />
        <MiniStat label={`${s.curCode}/USD`} value={window.fmt.rate(fx)} />
      </div>
    </div>);

}
function MiniStat({ label, value, sub }) {
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 3 }}>
      <div style={{ fontSize: 11, color: "var(--muted)", fontWeight: 600 }}>{label}</div>
      <div style={{ fontSize: 16, fontWeight: 700, color: "var(--text)", fontVariantNumeric: "tabular-nums", letterSpacing: -0.3 }}>{value}</div>
      {sub && <div style={{ fontSize: 11.5, color: "var(--muted)", fontVariantNumeric: "tabular-nums" }}>{sub}</div>}
    </div>);

}

function SummaryAiry({ s, fx }) {
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
      <div
        style={{
          background: "var(--card)",
          border: "1px solid var(--border-soft)",
          borderRadius: 18,
          padding: "18px 18px",
          boxShadow: "var(--shadow)",
          display: "flex",
          flexDirection: "column",
          gap: 10
        }}>

        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline" }}>
          <span style={{ fontSize: 13, color: "var(--muted)", fontWeight: 600 }}>Чистая прибыль</span>
          <span style={{ fontSize: 13, color: "var(--muted)", fontVariantNumeric: "tabular-nums" }}>{s.curCode}/USD {window.fmt.rate(fx)}</span>
        </div>
        <div style={{ display: "flex", alignItems: "baseline", gap: 11 }}>
          <span style={{ fontSize: 34, fontWeight: 800, letterSpacing: -1, color: s.pnlEur >= 0 ? "var(--pos)" : "var(--neg)", fontVariantNumeric: "tabular-nums" }}>
            {window.fmt.money(s.pnlEur, s.cur, { dec: 0, sign: true })}
          </span>
          <span style={{ fontSize: 16, fontWeight: 700, color: s.pnlEur >= 0 ? "var(--pos)" : "var(--neg)" }}>
            {window.fmt.pct(s.pnlPct, { sign: true })}
          </span>
        </div>
      </div>
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
        <Stat label="Вложено">{window.fmt.money(s.investedEur, s.cur, { dec: 0 })}</Stat>
        <Stat label="Стоимость" sub={window.fmt.money(s.valueEur, s.cur, { dec: 0 })}>
          {window.fmt.money(s.valueUsd, "$", { dec: 0 })}
        </Stat>
      </div>
    </div>);

}

// ---- group header ----
function GroupHeader({ title, total, share }) {
  return (
    <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", padding: "2px 4px 0" }}>
      <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
        <span style={{ fontSize: 12.5, fontWeight: 700, color: "var(--muted)", textTransform: "uppercase", letterSpacing: 0.8 }}>
          {title}
        </span>
        {share != null &&
        <span style={{ fontSize: 12, color: "var(--dim)", fontVariantNumeric: "tabular-nums" }}>
            {window.fmt.pct(share)}
          </span>
        }
      </div>
      {total != null &&
      <span style={{ fontSize: 13, fontWeight: 700, color: "var(--text)", fontVariantNumeric: "tabular-nums" }}>
          {window.fmt.money(total, "$", { dec: 0 })}
        </span>
      }
    </div>);

}

// ---- coin row (expandable) ----
function CoinRow({ c, first, last }) {
  const [open, setOpen] = useStateS(false);
  return (
    <div
      style={{
        background: "var(--card)",
        borderTop: first ? "1px solid var(--border-soft)" : "none",
        borderBottom: "1px solid var(--border-soft)",
        borderLeft: "1px solid var(--border-soft)",
        borderRight: "1px solid var(--border-soft)",
        borderTopLeftRadius: first ? 12 : 0,
        borderTopRightRadius: first ? 12 : 0,
        borderBottomLeftRadius: last ? 12 : 0,
        borderBottomRightRadius: last ? 12 : 0,
        boxShadow: first ? "var(--shadow)" : "none"
      }}>

      <button
        onClick={() => setOpen((o) => !o)}
        style={{
          width: "100%",
          display: "flex",
          alignItems: "center",
          gap: 11,
          padding: "11px 13px",
          background: "transparent",
          border: "none",
          cursor: "pointer",
          textAlign: "left",
          color: "inherit"
        }}>

        <window.Ticker sym={c.ticker} size={30} />
        <div style={{ flex: 1, minWidth: 0, display: "flex", alignItems: "center", gap: 8 }}>
          <span style={{ fontSize: 15, fontWeight: 700, color: "var(--accent)", letterSpacing: 0.2 }}>{c.ticker}</span>
          <window.ShareBar pct={c.share} width={44} />
        </div>
        <div style={{ display: "flex", flexDirection: "column", alignItems: "flex-end", gap: 4 }}>
          <span style={{ fontSize: 15, fontWeight: 700, color: "var(--text)", fontVariantNumeric: "tabular-nums" }}>
            {window.fmt.money(c.value, "$", { dec: 0 })}
          </span>
          <window.Pnl v={c.pnl} size={12.5}>
            {window.fmt.money(c.pnl, "$", { dec: 0, sign: true })} · {window.fmt.pct(c.pnlPct, { sign: true })}
          </window.Pnl>
        </div>
        <Chevron open={open} />
      </button>
      {open &&
      <div
        style={{
          display: "grid",
          gridTemplateColumns: "1fr 1fr 1fr",
          gap: "11px 10px",
          padding: "4px 13px 14px 54px"
        }}>

          <Detail label="Вложено" value={window.fmt.money(c.invested, "$", { dec: 0 })} />
          <Detail label="Средняя" value={window.fmt.price(c.avg)} />
          <Detail label="Текущая" value={window.fmt.price(c.price)} />
          <Detail label="Кол-во" value={window.fmt.qty(c.qty)} />
          <Detail label="Стоимость" value={window.fmt.money(c.value, "$", { dec: 0 })} />
          <Detail label="PnL" value={
        <window.Pnl v={c.pnl}>{window.fmt.money(c.pnl, "$", { dec: 0, sign: true })}</window.Pnl>
        } />
        </div>
      }
    </div>);

}
function Chevron({ open }) {
  return (
    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="var(--dim)" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"
    style={{ transform: open ? "rotate(180deg)" : "none", transition: "transform .18s", flex: "none" }}>
      <path d="M6 9l6 6 6-6" />
    </svg>);

}
function Detail({ label, value }) {
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 2 }}>
      <span style={{ fontSize: 10.5, color: "var(--dim)", textTransform: "uppercase", letterSpacing: 0.4, fontWeight: 600 }}>{label}</span>
      <span style={{ fontSize: 13.5, fontWeight: 600, color: "var(--text)", fontVariantNumeric: "tabular-nums" }}>{value}</span>
    </div>);

}

// ---- cash block ----
function CashBlock({ cash }) {
  return (
    <div style={{ background: "var(--card)", border: "1px solid var(--border-soft)", borderRadius: 12, padding: "12px 13px", boxShadow: "var(--shadow)", display: "flex", flexDirection: "column", gap: 11 }}>
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
        <div style={{ display: "flex", alignItems: "center", gap: 9 }}>
          <window.Ticker sym="USDC" size={30} />
          <div style={{ display: "flex", flexDirection: "column", gap: 3 }}>
            <span style={{ fontSize: 14.5, fontWeight: 700, color: "var(--text)" }}>Стейблкоины</span>
            <window.ShareBar pct={cash.share} width={44} />
          </div>
        </div>
        <span style={{ fontSize: 16, fontWeight: 700, color: "var(--text)", fontVariantNumeric: "tabular-nums" }}>
          {window.fmt.money(cash.total, "$", { dec: 0 })}
        </span>
      </div>
      <div style={{ display: "flex", gap: 7, flexWrap: "wrap" }}>
        {cash.items.map((it) =>
        <span key={it.ticker} style={{ display: "inline-flex", alignItems: "center", gap: 6, padding: "5px 10px", borderRadius: 999, background: "var(--card2)", border: "1px solid var(--border-soft)", fontSize: 12.5 }}>
            <span style={{ color: "var(--muted)", fontWeight: 600 }}>{it.ticker}</span>
            <span style={{ color: "var(--text)", fontWeight: 600, fontVariantNumeric: "tabular-nums" }}>{window.fmt.money(it.amount, "$", { dec: 0 })}</span>
          </span>
        )}
      </div>
    </div>);

}

// ---- LP card ----
// neutral бейдж для V2 (full-range, нет диапазона)
function FullRangeBadge() {
  return (
    <span style={{ display: "inline-flex", alignItems: "center", gap: 6, padding: "3px 9px", borderRadius: 999, fontSize: 11.5, fontWeight: 600, color: "var(--muted)", background: "var(--card2)", border: "1px solid var(--border-soft)", whiteSpace: "nowrap" }}>
      полный диапазон
    </span>);
}

function LpCard({ lp }) {
  // красная рамка только если V3 и реально вне диапазона
  const danger = lp.isV3 && lp.inRange === false;
  return (
    <div style={{ background: "var(--card)", border: `1px solid ${danger ? "var(--neg-line)" : "var(--border-soft)"}`, borderRadius: 14, padding: "14px 14px 13px", boxShadow: "var(--shadow)", display: "flex", flexDirection: "column", gap: 13 }}>
      <div style={{ display: "flex", alignItems: "flex-start", justifyContent: "space-between", gap: 10 }}>
        <div style={{ display: "flex", flexDirection: "column", gap: 4 }}>
          <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
            <span style={{ fontSize: 15, fontWeight: 700, color: "var(--accent)" }}>{lp.pair}</span>
            <window.ShareBar pct={lp.share} width={40} showNum={true} />
          </div>
          <span style={{ fontSize: 12, color: "var(--dim)", fontWeight: 500 }}>{lp.venue} · LP #{lp.id}</span>
        </div>
        {lp.isV3 ? <window.RangeBadge inRange={lp.inRange} /> : <FullRangeBadge />}
      </div>

      {/* range bar — только для V3 (concentrated liquidity) */}
      {lp.isV3 && <RangeBar lp={lp} />}

      {/* composition */}
      <div style={{ display: "flex", flexDirection: "column", gap: 7 }}>
        {lp.composition.map((t) =>
        <div key={t.ticker} style={{ display: "flex", alignItems: "center", gap: 9 }}>
            <window.Ticker sym={t.ticker} size={22} />
            <span style={{ fontSize: 13, fontWeight: 600, color: "var(--text)", minWidth: 52 }}>{t.ticker}</span>
            <span style={{ fontSize: 12.5, color: "var(--muted)", fontVariantNumeric: "tabular-nums", flex: 1 }}>
              {window.fmt.qty(t.qty)}
            </span>
            <span style={{ fontSize: 13, fontWeight: 600, color: "var(--text)", fontVariantNumeric: "tabular-nums" }}>
              {window.fmt.money(t.value, "$", { dec: 0 })}
            </span>
            <span style={{ fontSize: 12, color: "var(--dim)", fontVariantNumeric: "tabular-nums", minWidth: 34, textAlign: "right" }}>
              {t.weight}%
            </span>
          </div>
        )}
      </div>

      <div style={{ height: 1, background: "var(--border-soft)", margin: "0 -14px" }} />

      {/* metrics row */}
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr 1fr", gap: 8 }}>
        <Detail label="Вложено" value={window.fmt.money(lp.invested, "$", { dec: 0 })} />
        <Detail label="Стоимость" value={window.fmt.money(lp.value, "$", { dec: 0 })} />
        <Detail label="IL" value={<window.Pnl v={lp.il}>{window.fmt.pct(lp.il, { sign: true })}</window.Pnl>} />
        <Detail label="PnL" value={<window.Pnl v={lp.pnl}>{window.fmt.money(lp.pnl, "$", { dec: 0, sign: true })}</window.Pnl>} />
      </div>
    </div>);

}
function RangeBar({ lp }) {
  // Полоса: диапазон [rangeLow..rangeHigh] визуально занимает 12%..88%.
  // Маркер — реальная позиция текущей цены пула внутри/около диапазона.
  const lowL = 12, highL = 88;
  let cur;
  if (lp.rangeLow != null && lp.rangeHigh != null && lp.rangeHigh > lp.rangeLow && lp.curPrice != null) {
    let frac = (lp.curPrice - lp.rangeLow) / (lp.rangeHigh - lp.rangeLow);
    frac = Math.max(-0.16, Math.min(1.16, frac)); // допускаем небольшой выход за края
    cur = Math.max(2, Math.min(98, lowL + frac * (highL - lowL)));
  } else {
    cur = lp.inRange === false ? 96 : 50;
  }
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
      <div style={{ position: "relative", height: 6, borderRadius: 999, background: "var(--card2)" }}>
        <div style={{ position: "absolute", left: lowL + "%", right: 100 - highL + "%", top: 0, bottom: 0, borderRadius: 999, background: "var(--accent-soft)" }} />
        <div style={{ position: "absolute", left: cur + "%", top: -3, width: 3, height: 12, borderRadius: 2, background: lp.inRange === false ? "var(--neg)" : "var(--pos)", transform: "translateX(-50%)" }} />
      </div>
      <div style={{ display: "flex", justifyContent: "space-between", fontSize: 11.5, color: "var(--muted)", fontVariantNumeric: "tabular-nums" }}>
        <span>{window.fmt.price(lp.rangeLow)}</span>
        <span style={{ color: "var(--dim)" }}>диапазон цен</span>
        <span>{window.fmt.price(lp.rangeHigh)}</span>
      </div>
    </div>);

}

// ---- loans ----
function LoansBlock({ loans, total }) {
  return (
    <div style={{ background: "var(--card)", border: "1px solid var(--border-soft)", borderRadius: 12, padding: "12px 13px", boxShadow: "var(--shadow)", display: "flex", flexDirection: "column", gap: 10 }}>
      {loans.map((l) =>
      <div key={l.id} style={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: 10 }}>
          <div style={{ display: "flex", alignItems: "center", gap: 9 }}>
            <span style={{ fontSize: 12, color: "var(--dim)", fontWeight: 700 }}>#{l.id}</span>
            <span style={{ fontSize: 13.5, color: "var(--text)", fontWeight: 600 }}>{l.ticker}</span>
            <span style={{ fontSize: 12, color: "var(--muted)" }}>залог: {l.collateral}</span>
          </div>
          <span style={{ fontSize: 14, fontWeight: 700, color: "var(--text)", fontVariantNumeric: "tabular-nums" }}>
            {window.fmt.money(l.amount, "$", { dec: 0 })}
          </span>
        </div>
      )}
    </div>);

}

// ---- total block ----
function TotalBlock({ s, fx, dark }) {
  return (
    <div
      style={{
        background: dark ? "var(--card2)" : "var(--text)",
        color: dark ? "var(--text)" : "var(--bg)",
        border: dark ? "1px solid var(--border)" : "none",
        borderRadius: 16,
        padding: "16px 16px 17px",
        display: "flex",
        flexDirection: "column",
        gap: 9
      }}>

      <div style={{ fontSize: 12, fontWeight: 700, letterSpacing: 1, textTransform: "uppercase", opacity: 0.6 }}>Итого</div>
      <TotalRow label="Вложено" value={window.fmt.money(s.investedEur, s.cur, { dec: 0 })} faint />
      <TotalRow label="Активы" value={window.fmt.money(s.valueUsd, "$", { dec: 0 })} faint />
      {s.debtUsd > 0 &&
      <TotalRow label="Долг" value={window.fmt.money(-s.debtUsd, "$", { dec: 0, sign: true })} faint neg />}
      <TotalRow label="Чистая стоимость" value={`${window.fmt.money(s.netUsd, "$", { dec: 0 })} (${window.fmt.money(s.netEur, s.cur, { dec: 0 })})`} bold />
      <div style={{ height: 1, background: "currentColor", opacity: 0.14, margin: "4px 0 2px" }} />
      <div style={{ display: "flex", alignItems: "baseline", justifyContent: "space-between" }}>
        <span style={{ fontSize: 14, fontWeight: 700 }}>PnL</span>
        <span style={{ display: "flex", alignItems: "baseline", gap: 9, color: s.pnlEur >= 0 ? "var(--pos)" : "var(--neg)" }}>
          <span style={{ fontSize: 24, fontWeight: 800, fontVariantNumeric: "tabular-nums", letterSpacing: -0.6 }}>
            {window.fmt.money(s.pnlEur, s.cur, { dec: 0, sign: true })}
          </span>
          <span style={{ fontSize: 15, fontWeight: 700 }}>{window.fmt.pct(s.pnlPct, { sign: true })}</span>
        </span>
      </div>
      <div style={{ display: "flex", justifyContent: "space-between", fontSize: 12.5, opacity: 0.6, marginTop: 2 }}>
        <span>Курс {s.curCode}/USD</span>
        <span style={{ fontVariantNumeric: "tabular-nums" }}>{window.fmt.rate(fx)}</span>
      </div>
    </div>);

}
function TotalRow({ label, value, faint, bold, neg }) {
  return (
    <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline" }}>
      <span style={{ fontSize: 13.5, opacity: faint ? 0.62 : 1, fontWeight: bold ? 700 : 500 }}>{label}</span>
      <span style={{ fontSize: bold ? 15 : 13.5, fontWeight: bold ? 700 : 600, fontVariantNumeric: "tabular-nums", color: neg ? "var(--neg)" : "inherit" }}>{value}</span>
    </div>);

}

// ---------------- main screen ----------------
function PortfolioScreen({ theme = "slate", width = 390, headerExtra, data, onRefresh }) {
  const t = THEMES[theme];
  const d = data || window.PF; // живые данные; fallback на мок для офлайн-превью
  const SummaryEl = t.layout === "hero" ? SummaryHero : t.layout === "airy" ? SummaryAiry : SummaryGrid;
  const hasCash = d.cash && d.cash.total > 0;
  return (
    <div
      style={{
        ...t.vars,
        width,
        fontFamily: t.font,
        background: "var(--bg)",
        color: "var(--text)",
        padding: "18px 15px 22px",
        display: "flex",
        flexDirection: "column",
        gap: 16,
        boxSizing: "border-box",
        WebkitFontSmoothing: "antialiased"
      }}>

      <Header updatedAt={d.updatedAt} onRefresh={onRefresh} layout={t.layout} headerExtra={headerExtra} />
      <SummaryEl s={d.summary} fx={d.fx} />

      {/* coins group */}
      {d.coins.length > 0 &&
      <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
        <GroupHeader title="Монеты" total={d.coins.reduce((a, c) => a + c.value, 0)} share={d.coins.reduce((a, c) => a + c.share, 0)} />
        <div style={{ width: "100%" }}>
          {d.coins.map((c, i) =>
          <CoinRow key={c.ticker} c={c} first={i === 0} last={i === d.coins.length - 1} />
          )}
        </div>
      </div>
      }

      {/* cash group */}
      {hasCash &&
      <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
        <GroupHeader title="Кеш" total={d.cash.total} share={d.cash.share} />
        <CashBlock cash={d.cash} />
      </div>
      }

      {/* LP group */}
      {d.lp.length > 0 &&
      <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
        <GroupHeader title="LP-позиции" total={d.lp.reduce((a, l) => a + l.value, 0)} share={d.lp.reduce((a, l) => a + l.share, 0)} />
        {d.lp.map((lp) => <LpCard key={lp.id} lp={lp} />)}
      </div>
      }

      {/* loans group */}
      {d.loans.length > 0 &&
      <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
        <GroupHeader title="Займы" total={d.debtTotal} />
        <LoansBlock loans={d.loans} total={d.debtTotal} />
      </div>
      }

      <TotalBlock s={d.summary} fx={d.fx} dark={t.dark} />
    </div>);

}

Object.assign(window, { PortfolioScreen, THEMES });
