/* ============================================
   VELOX screens — part 1
   Login, Dashboard, Indices, Watchlist, OptionChain
   ============================================ */

/* ---------------- LOGIN ---------------- */
const LoginScreen = ({ onLogin }) => {
  // "velox" = sign in to Velox (Google / email)
  // "kotak-setup" = first time Kotak (mobile+UCC+TOTP+MPIN)
  // "kotak-connect" = returning (TOTP+MPIN only)
  const [step, setStep] = React.useState("init");
  const [authMode, setAuthMode] = React.useState("signin"); // signin | signup

  const [email, setEmail]       = React.useState("");
  const [password, setPassword] = React.useState("");
  const [confirmPw, setConfirmPw] = React.useState("");

  const [mobile, setMobile]               = React.useState("");
  const [ucc, setUcc]                     = React.useState("");
  const [consumerCode, setConsumerCode]   = React.useState("");
  const [totp, setTotp]                   = React.useState("");
  const [mpin, setMpin]                   = React.useState("");
  const [maskedMobile, setMaskedMobile]   = React.useState("");
  const [maskedUcc, setMaskedUcc]         = React.useState("");

  const [err, setErr]         = React.useState("");
  const [loading, setLoading] = React.useState(false);
  const [firebaseUser, setFirebaseUser] = React.useState(null);

  function maskMobile(m) {
    const digits = m.replace(/\D/g, "");
    if (digits.length >= 10) return `+91 ••••• ••${digits.slice(-3)}`;
    return m;
  }

  async function afterVeloxLogin(user) {
    setFirebaseUser(user);
    try {
      const connected = await API.isKotakConnected();
      if (connected) { onLogin({ uid: user.uid, name: user.displayName || user.email }); return; }
      const profile = await API.loadKotakProfile();
      if (profile?.mobile) {
        setMaskedMobile(maskMobile(profile.mobile));
        setMaskedUcc(profile.ucc ?? "");
        setStep("kotak-connect");
      } else {
        setStep("kotak-setup");
      }
    } catch (e) {
      setStep("kotak-setup");
    }
  }

  // On mount: init Firebase, check if already signed in
  React.useEffect(() => {
    API.init(FIREBASE_CONFIG)
      .then(async user => {
        if (user && !user.isAnonymous) {
          await afterVeloxLogin(user);
        } else {
          setStep("velox");
        }
      })
      .catch(e => { console.error("[Login] init failed:", e); setStep("velox"); });
  }, []);

  const submitGoogle = async () => {
    setErr(""); setLoading(true);
    try {
      const cred = await API.signInWithGoogle();
      await afterVeloxLogin(cred.user);
    } catch (ex) {
      setErr(ex?.message || "Google sign-in failed");
    } finally { setLoading(false); }
  };

  const submitEmail = async (e) => {
    e.preventDefault();
    setErr("");
    if (!email || !password) { setErr("Fill in all fields"); return; }
    if (authMode === "signup" && password !== confirmPw) { setErr("Passwords do not match"); return; }
    setLoading(true);
    try {
      const cred = authMode === "signup"
        ? await API.signUp(email, password)
        : await API.signIn(email, password);
      await afterVeloxLogin(cred.user);
    } catch (ex) {
      const msg = ex?.message ?? "";
      if (msg.includes("email-already-in-use")) setErr("Account exists — sign in instead");
      else if (msg.includes("wrong-password") || msg.includes("user-not-found")) setErr("Invalid email or password");
      else if (msg.includes("weak-password")) setErr("Password must be at least 6 characters");
      else setErr(msg || "Sign-in failed");
    } finally { setLoading(false); }
  };

  const submitKotak = async (e) => {
    e.preventDefault();
    setErr("");
    if (!totp || totp.length !== 6) { setErr("Enter the 6-digit code from your Authenticator app"); return; }
    if (!mpin) { setErr("Enter your MPIN"); return; }
    if (step === "kotak-setup" && (!mobile || !ucc)) { setErr("Mobile and UCC are required"); return; }
    setLoading(true);
    try {
      if (step === "kotak-setup") await API.kotakSaveProfile({ mobile, ucc, ...(consumerCode && { consumerCode }) });
      await API.kotakConnectDirect({ totp, mpin });
      onLogin({ uid: firebaseUser?.uid, name: firebaseUser?.displayName || firebaseUser?.email });
    } catch (ex) {
      setErr(ex?.message || "Kotak connection failed — check TOTP and MPIN");
    } finally { setLoading(false); }
  };

  const leftPanel = (
    <div className="login-left">
      <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
        <div className="side-brand-mark" style={{ background: "white", color: "var(--brand)" }}>V</div>
        <div>
          <div style={{ fontSize: 22, fontWeight: 700, letterSpacing: "-0.02em" }}>Velox</div>
          <div style={{ fontSize: 11, opacity: .85, letterSpacing: ".1em", textTransform: "uppercase", fontWeight: 600 }}>Automated Trading</div>
        </div>
      </div>
      <div>
        <div style={{ fontSize: 36, fontWeight: 700, letterSpacing: "-0.025em", lineHeight: 1.15, maxWidth: 480 }}>
          Trade smarter with algorithms that never sleep.
        </div>
        <div style={{ fontSize: 14, opacity: .9, marginTop: 16, maxWidth: 460, lineHeight: 1.55 }}>
          Connected to Kotak Neo API. Six battle-tested strategies. Real-time websocket data.
          You set the guardrails — Velox does the trading.
        </div>
        <div style={{ display: "flex", gap: 28, marginTop: 32, fontFamily: "var(--font-mono)" }}>
          <div><div style={{ fontSize: 24, fontWeight: 700 }}>62%</div><div style={{ fontSize: 11, opacity: .8, textTransform: "uppercase", letterSpacing: ".06em" }}>Avg win rate</div></div>
          <div><div style={{ fontSize: 24, fontWeight: 700 }}>6</div><div style={{ fontSize: 11, opacity: .8, textTransform: "uppercase", letterSpacing: ".06em" }}>Strategies</div></div>
          <div><div style={{ fontSize: 24, fontWeight: 700 }}>&lt;50ms</div><div style={{ fontSize: 11, opacity: .8, textTransform: "uppercase", letterSpacing: ".06em" }}>Tick latency</div></div>
        </div>
      </div>
      <div style={{ fontSize: 11, opacity: .75 }}>© 2026 Velox · Powered by Kotak Neo API · Not financial advice</div>
    </div>
  );

  if (step === "init") return (
    <div className="login-shell">
      {leftPanel}
      <div className="login-right">
        <div className="login-card" style={{ display: "flex", alignItems: "center", justifyContent: "center", minHeight: 260 }}>
          <div className="muted" style={{ fontSize: 14 }}>Initialising…</div>
        </div>
      </div>
    </div>
  );

  // ── Step 1: Velox sign in ─────────────────────────────────────────────────
  if (step === "velox") return (
    <div className="login-shell">
      {leftPanel}
      <div className="login-right">
        <div className="login-card">
          <div style={{ fontSize: 24, fontWeight: 700, letterSpacing: "-0.02em", marginBottom: 4 }}>
            {authMode === "signup" ? "Create account" : "Welcome back"}
          </div>
          <div style={{ color: "var(--text-3)", fontSize: 13, marginBottom: 22 }}>
            {authMode === "signup" ? "Sign up for Velox" : "Sign in to Velox to continue"}
          </div>

          {/* Google sign-in */}
          <button className="btn btn-secondary" style={{ width: "100%", justifyContent: "center", padding: 11, marginBottom: 16, gap: 10 }}
            onClick={submitGoogle} disabled={loading} type="button">
            <svg width="18" height="18" viewBox="0 0 48 48"><path fill="#EA4335" d="M24 9.5c3.54 0 6.71 1.22 9.21 3.6l6.85-6.85C35.9 2.38 30.47 0 24 0 14.62 0 6.51 5.38 2.56 13.22l7.98 6.19C12.43 13.08 17.74 9.5 24 9.5z"/><path fill="#4285F4" d="M46.98 24.55c0-1.57-.15-3.09-.38-4.55H24v9.02h12.94c-.58 2.96-2.26 5.48-4.78 7.18l7.73 6c4.51-4.18 7.09-10.36 7.09-17.65z"/><path fill="#FBBC05" d="M10.53 28.59c-.48-1.45-.76-2.99-.76-4.59s.27-3.14.76-4.59l-7.98-6.19C.92 16.46 0 20.12 0 24c0 3.88.92 7.54 2.56 10.78l7.97-6.19z"/><path fill="#34A853" d="M24 48c6.48 0 11.93-2.13 15.89-5.81l-7.73-6c-2.18 1.48-4.97 2.31-8.16 2.31-6.26 0-11.57-3.59-13.46-8.91l-7.98 6.19C6.51 42.62 14.62 48 24 48z"/><path fill="none" d="M0 0h48v48H0z"/></svg>
            Continue with Google
          </button>

          <div style={{ display: "flex", alignItems: "center", gap: 10, marginBottom: 16, color: "var(--text-3)", fontSize: 11 }}>
            <div style={{ flex: 1, height: 1, background: "var(--border)" }}/><span>OR</span><div style={{ flex: 1, height: 1, background: "var(--border)" }}/>
          </div>

          <form onSubmit={submitEmail}>
            <div className="field" style={{ marginBottom: 12 }}>
              <label className="field-label">Email</label>
              <input className="input" type="email" placeholder="you@example.com" value={email}
                onChange={e => setEmail(e.target.value)} autoFocus/>
            </div>
            <div className="field" style={{ marginBottom: 12 }}>
              <label className="field-label">Password</label>
              <input className="input" type="password" placeholder="••••••••" value={password}
                onChange={e => setPassword(e.target.value)}/>
            </div>
            {authMode === "signup" && (
              <div className="field" style={{ marginBottom: 12 }}>
                <label className="field-label">Confirm password</label>
                <input className="input" type="password" placeholder="••••••••" value={confirmPw}
                  onChange={e => setConfirmPw(e.target.value)}/>
              </div>
            )}
            {err && <div style={{ color: "var(--down)", fontSize: 12, marginBottom: 10 }}>{err}</div>}
            <button type="submit" className="btn btn-primary" style={{ width: "100%", justifyContent: "center", padding: 11 }}
              disabled={loading}>
              {loading ? "Please wait…" : authMode === "signup" ? "Create account" : "Sign in"}
            </button>
          </form>

          <div style={{ marginTop: 16, textAlign: "center", fontSize: 12 }}>
            {authMode === "signin"
              ? <>No account?{" "}<a href="#" style={{ color: "var(--brand)", fontWeight: 600 }} onClick={e => { e.preventDefault(); setAuthMode("signup"); setErr(""); }}>Sign up</a></>
              : <>Have an account?{" "}<a href="#" style={{ color: "var(--brand)", fontWeight: 600 }} onClick={e => { e.preventDefault(); setAuthMode("signin"); setErr(""); }}>Sign in</a></>}
          </div>

          <div style={{ marginTop: 20, borderTop: "1px solid var(--border)", paddingTop: 16, textAlign: "center" }}>
            <button className="btn btn-secondary" style={{ width: "100%", justifyContent: "center", padding: 10, gap: 8 }}
              onClick={() => onLogin({ demo: true })} type="button">
              👁 Preview with demo data
            </button>
            <div style={{ fontSize: 11, color: "var(--text-3)", marginTop: 6 }}>No login required · read-only · simulated data</div>
          </div>
        </div>
      </div>
    </div>
  );

  // ── Step 2: Kotak connect ─────────────────────────────────────────────────
  return (
    <div className="login-shell">
      {leftPanel}
      <div className="login-right">
        <div className="login-card">
          <form onSubmit={submitKotak}>
            <div style={{ fontSize: 24, fontWeight: 700, letterSpacing: "-0.02em", marginBottom: 6 }}>
              Connect Kotak Neo
            </div>
            <div style={{ color: "var(--text-3)", fontSize: 13, marginBottom: 22, lineHeight: 1.5 }}>
              {step === "kotak-connect"
                ? <>Account: <strong style={{ color: "var(--text-2)" }}>{maskedMobile}</strong> &nbsp;·&nbsp; UCC: <strong style={{ color: "var(--text-2)" }}>{maskedUcc}</strong></>
                : "Enter your Kotak Neo account details."}
            </div>

            {step === "kotak-setup" && (
              <>
                <div className="field" style={{ marginBottom: 12 }}>
                  <label className="field-label">Mobile number</label>
                  <input className="input" placeholder="+91XXXXXXXXXX" value={mobile}
                    onChange={e => setMobile(e.target.value)} autoFocus/>
                </div>
                <div className="field" style={{ marginBottom: 12 }}>
                  <label className="field-label">UCC (Client Code)</label>
                  <input className="input mono" placeholder="AB123" maxLength={6} value={ucc}
                    onChange={e => setUcc(e.target.value.toUpperCase())}/>
                </div>
                <div className="field" style={{ marginBottom: 12 }}>
                  <label className="field-label">Consumer code <span style={{ fontWeight: 400, color: "var(--text-3)", marginLeft: 6, fontSize: 11 }}>(optional)</span></label>
                  <input className="input mono" placeholder="consumer key / code" value={consumerCode}
                    onChange={e => setConsumerCode(e.target.value)}/>
                </div>
              </>
            )}

            <div className="field" style={{ marginBottom: 12 }}>
              <label className="field-label">
                TOTP
                <span style={{ fontWeight: 400, color: "var(--text-3)", marginLeft: 6, fontSize: 11 }}>6-digit code from Google / Microsoft Authenticator</span>
              </label>
              <input className="input mono" placeholder="123456" maxLength={6} inputMode="numeric"
                value={totp} onChange={e => setTotp(e.target.value.replace(/\D/g, "").slice(0, 6))}
                autoFocus={step === "kotak-connect"}/>
            </div>
            <div className="field" style={{ marginBottom: 18 }}>
              <label className="field-label">MPIN</label>
              <input className="input mono" type="password" placeholder="••••••" value={mpin}
                onChange={e => setMpin(e.target.value)}/>
            </div>

            {err && <div style={{ color: "var(--down)", fontSize: 12, marginBottom: 10 }}>{err}</div>}

            <button type="submit" className="btn btn-primary" style={{ width: "100%", justifyContent: "center", padding: 11 }}
              disabled={loading}>
              {loading ? "Connecting…" : "Connect & Enter"}
            </button>

            <div style={{ marginTop: 12, background: "var(--surface-2)", borderRadius: 8, padding: "10px 12px", fontSize: 12, color: "var(--text-3)", lineHeight: 1.5 }}>
              🔒 TOTP and MPIN are never stored. Used once to get a trading session token, then discarded.
            </div>

            {step === "kotak-connect" && (
              <div style={{ marginTop: 12, textAlign: "center", fontSize: 12 }}>
                <a href="#" style={{ color: "var(--brand)", fontWeight: 600 }}
                  onClick={e => { e.preventDefault(); setErr(""); setTotp(""); setMpin(""); setStep("kotak-setup"); }}>
                  Change account / update mobile & UCC
                </a>
              </div>
            )}

            <div style={{ marginTop: 14, textAlign: "center", fontSize: 12, color: "var(--text-3)" }}>
              <a href="#" style={{ color: "var(--text-3)" }}
                onClick={e => {
                  e.preventDefault();
                  onLogin({ uid: firebaseUser?.uid, name: firebaseUser?.displayName || firebaseUser?.email });
                }}>
                Skip for now — enter app without Kotak
              </a>
            </div>
          </form>
        </div>
      </div>
    </div>
  );
};

/* ---------------- DASHBOARD ---------------- */
const Dashboard = ({ market, holdings, positions, pnlHistory, navigate, layout, margin, algos = [], isDemo = false }) => {
  const investedTotal = holdings.reduce((s, h) => s + h.invested, 0);
  const currentTotal  = holdings.reduce((s, h) => s + h.current, 0);
  const pnlTotal      = currentTotal - investedTotal;
  const pnlPctTotal   = investedTotal ? (pnlTotal / investedTotal) * 100 : 0;
  const todayPnl      = positions.reduce((s, p) => s + p.pnl, 0);
  const cashAvail     = margin?.available ?? 0;
  const cashUsed      = margin?.used      ?? 0;
  const runningAlgos  = algos.filter(a => a.running);
  const algoTodayPnl  = runningAlgos.reduce((s, a) => s + (a.pnl || 0), 0);
  const algoTrades    = runningAlgos.reduce((s, a) => s + (a.autoTrades || 0), 0);

  // Market status for subtitle
  const now = new Date();
  const istMs = now.getTime() + (5.5 * 60 * 60 * 1000);
  const ist = new Date(istMs);
  const h = ist.getUTCHours(), m = ist.getUTCMinutes();
  const minsNow = h * 60 + m;
  const mktOpen = now.getDay() > 0 && now.getDay() < 6 && minsNow >= 9 * 60 + 15 && minsNow < 15 * 60 + 30;
  const minsAgo = mktOpen ? minsNow - (9 * 60 + 15) : null;
  const greeting = h < 12 ? "Good morning" : h < 17 ? "Good afternoon" : "Good evening";

  const holdingsBySector = {};
  holdings.forEach(h => {
    const sector = market.stocks.find(s => s.sym === h.sym)?.sector || "Other";
    holdingsBySector[sector] = (holdingsBySector[sector] || 0) + h.current;
  });
  const sectorColors = ["#00B981", "#3B82F6", "#F59E0B", "#7C3AED", "#EF4444", "#06B6D4", "#EC4899"];
  const donutSegs = Object.entries(holdingsBySector).map(([k, v], i) => ({ label: k, value: v, color: sectorColors[i % sectorColors.length] }));

  return (
    <div className="page">
      <div className="row-between" style={{ marginBottom: 22 }}>
        <div>
          <h2 className="page-title">{greeting}, Trader 👋</h2>
          <div className="page-sub">
            {mktOpen
              ? `Markets opened ${minsAgo}m ago.`
              : "Markets are closed."
            }
            {runningAlgos.length > 0 ? ` ${runningAlgos.length} algo${runningAlgos.length > 1 ? "s" : ""} running.` : " No algos running."}
            {isDemo && <span style={{ marginLeft: 6, fontSize: 11, color: "var(--text-3)" }}>[demo]</span>}
          </div>
        </div>
        <div className="row" style={{ gap: 8 }}>
          <button className="btn btn-secondary" onClick={() => navigate("watchlist")}>
            <Icon name="eye" size={15}/> Watchlist
          </button>
          <button className="btn btn-primary" onClick={() => navigate("algos")}>
            <Icon name="bot" size={15}/> Manage algos
          </button>
        </div>
      </div>

      {/* KPI tiles */}
      <div className="grid" style={{ gridTemplateColumns: "repeat(4, 1fr)", marginBottom: 16 }}>
        <div className="kpi">
          <div className="kpi-label">Portfolio value</div>
          <div className="kpi-value">{fmtINR(currentTotal)}</div>
          <div className={"kpi-foot " + (pnlTotal >= 0 ? "up" : "down")}>
            {pnlTotal >= 0 ? "+" : ""}{fmtINR(pnlTotal)} ({fmtPct(pnlPctTotal)}) overall
          </div>
        </div>
        <div className="kpi">
          <div className="kpi-label">Today's P&L</div>
          <div className="kpi-value" style={{ color: todayPnl >= 0 ? "var(--up)" : "var(--down)" }}>
            {todayPnl >= 0 ? "+" : ""}{fmtINR(todayPnl)}
          </div>
          <div className={"kpi-foot " + (todayPnl >= 0 ? "up" : "down")}>
            From {positions.length} open positions
          </div>
        </div>
        <div className="kpi">
          <div className="kpi-label">Available margin</div>
          <div className="kpi-value">{fmtINR(cashAvail)}</div>
          <div className="kpi-foot">
            <span className="muted">{fmtINR(cashUsed)} blocked</span>
          </div>
        </div>
        <div className="kpi">
          <div className="kpi-label">Algo P&L (today)</div>
          <div className="kpi-value" style={{ color: algoTodayPnl >= 0 ? "var(--up)" : "var(--down)" }}>
            {algoTodayPnl >= 0 ? "+" : ""}{fmtINR(algoTodayPnl)}
          </div>
          <div className={"kpi-foot " + (algoTodayPnl >= 0 ? "up" : "down")}>
            {algoTrades} auto-trades · {runningAlgos.length} algo{runningAlgos.length !== 1 ? "s" : ""} active
          </div>
        </div>
      </div>

      <div className="grid" style={{ gridTemplateColumns: layout === "single" ? "1fr" : "2fr 1fr", marginBottom: 16 }}>
        <div className="card">
          <div className="row-between" style={{ marginBottom: 14 }}>
            <div className="card-title" style={{ margin: 0 }}>P&L curve · Last 30 days</div>
            <div className="row" style={{ gap: 4 }}>
              <button className="btn-ghost btn-sm chip">7D</button>
              <button className="btn-ghost btn-sm chip brand">30D</button>
              <button className="btn-ghost btn-sm chip">3M</button>
              <button className="btn-ghost btn-sm chip">1Y</button>
            </div>
          </div>
          {pnlHistory && pnlHistory.length > 0
            ? <AreaChart data={pnlHistory} valueKey="cumul" labelKey="date" height={240}/>
            : <div style={{ height: 240, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", color: "var(--text-3)", gap: 8 }}>
                <Icon name="chart" size={32}/>
                <div style={{ fontSize: 13 }}>No P&L data yet</div>
                <div style={{ fontSize: 11 }}>Data will appear here after your first trades</div>
              </div>
          }
        </div>
        <div className="card">
          <div className="card-title">Holdings by sector</div>
          <div style={{ display: "flex", alignItems: "center", gap: 18, padding: "8px 0" }}>
            <Donut segments={donutSegs} size={150} thickness={20}/>
            <div style={{ flex: 1, display: "flex", flexDirection: "column", gap: 8 }}>
              {donutSegs.map((s, i) => (
                <div key={i} className="row-between" style={{ fontSize: 12 }}>
                  <div className="row" style={{ gap: 8 }}>
                    <div style={{ width: 8, height: 8, borderRadius: 2, background: s.color }}/>
                    <span>{s.label}</span>
                  </div>
                  <span className="mono muted">{fmtINR(s.value, 0)}</span>
                </div>
              ))}
            </div>
          </div>
        </div>
      </div>

      <div className="grid" style={{ gridTemplateColumns: layout === "single" ? "1fr" : "1fr 1fr", marginBottom: 16 }}>
        {/* Indices snapshot */}
        <div className="card">
          <div className="row-between" style={{ marginBottom: 12 }}>
            <div className="card-title" style={{ margin: 0 }}>Indices</div>
            <button className="btn-ghost btn-sm" onClick={() => navigate("indices")}>View all <Icon name="chevronRight" size={13}/></button>
          </div>
          <div className="grid" style={{ gridTemplateColumns: "1fr 1fr", gap: 10 }}>
            {market.indices.map(idx => (
              <IndexMiniCard key={idx.sym} idx={idx}/>
            ))}
          </div>
        </div>

        {/* Open positions */}
        <div className="card">
          <div className="row-between" style={{ marginBottom: 12 }}>
            <div className="card-title" style={{ margin: 0 }}>Open positions <span className="chip" style={{marginLeft:6}}>{positions.length}</span></div>
            <button className="btn-ghost btn-sm" onClick={() => navigate("positions")}>View all <Icon name="chevronRight" size={13}/></button>
          </div>
          <table className="tbl">
            <thead>
              <tr><th>Instrument</th><th className="num">Qty</th><th className="num">LTP</th><th className="num">P&L</th></tr>
            </thead>
            <tbody>
              {positions.slice(0, 5).map((p, i) => (
                <tr key={i}>
                  <td>
                    <div style={{ fontWeight: 600, fontSize: 13 }}>{p.sym}</div>
                    <div style={{ fontSize: 11, color: "var(--text-3)" }}>{p.algo} · {p.side}</div>
                  </td>
                  <td className="num">{p.qty}</td>
                  <td className="num">{fmtNum(p.ltp)}</td>
                  <td className="num" style={{ color: p.pnl >= 0 ? "var(--up)" : "var(--down)", fontWeight: 600 }}>
                    {p.pnl >= 0 ? "+" : ""}{fmtNum(p.pnl, 2)}
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>

      {/* Top holdings table */}
      <div className="card">
        <div className="row-between" style={{ marginBottom: 12 }}>
          <div className="card-title" style={{ margin: 0 }}>Holdings</div>
          <div className="row" style={{ gap: 6 }}>
            <button className="btn-ghost btn-sm"><Icon name="download" size={13}/> Export</button>
          </div>
        </div>
        <div style={{ overflowX: "auto" }}>
          <table className="tbl">
            <thead>
              <tr>
                <th>Stock</th>
                <th className="num">Qty</th>
                <th className="num">Avg cost</th>
                <th className="num">LTP</th>
                <th className="num">Day chg</th>
                <th className="num">Invested</th>
                <th className="num">Current</th>
                <th className="num">P&L</th>
                <th className="num">Net %</th>
              </tr>
            </thead>
            <tbody>
              {holdings.map(h => (
                <tr key={h.sym}>
                  <td>
                    <div style={{ fontWeight: 600 }}>{h.sym}</div>
                    <div style={{ fontSize: 11, color: "var(--text-3)" }}>{h.name}</div>
                  </td>
                  <td className="num">{h.qty}</td>
                  <td className="num">{fmtNum(h.avg)}</td>
                  <td className="num">{fmtNum(h.ltp)}</td>
                  <td className="num" style={{ color: h.dayChg >= 0 ? "var(--up)" : "var(--down)" }}>{fmtPct(h.dayChgPct)}</td>
                  <td className="num">{fmtNum(h.invested, 0)}</td>
                  <td className="num">{fmtNum(h.current, 0)}</td>
                  <td className="num" style={{ color: h.pnl >= 0 ? "var(--up)" : "var(--down)", fontWeight: 600 }}>
                    {h.pnl >= 0 ? "+" : ""}{fmtNum(h.pnl, 0)}
                  </td>
                  <td className="num" style={{ color: h.pnl >= 0 ? "var(--up)" : "var(--down)", fontWeight: 600 }}>
                    {fmtPct(h.pnlPct)}
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>
    </div>
  );
};

const IndexMiniCard = ({ idx }) => {
  const up = idx.dayChg >= 0;
  return (
    <div style={{ padding: 12, background: "var(--surface-2)", borderRadius: 10, border: "1px solid var(--border)" }}>
      <div className="row-between" style={{ marginBottom: 6 }}>
        <div style={{ fontSize: 11, fontWeight: 700, color: "var(--text-3)", letterSpacing: ".04em" }}>{idx.name}</div>
        <Sparkline data={idx.sparkline} width={48} height={16}/>
      </div>
      <div className="mono" style={{ fontSize: 18, fontWeight: 700, letterSpacing: "-0.01em" }}>
        {fmtNum(idx.price, 2)}
      </div>
      <div className="mono" style={{ fontSize: 11, fontWeight: 600, color: up ? "var(--up)" : "var(--down)" }}>
        {up ? "▲" : "▼"} {fmtNum(Math.abs(idx.dayChg))} ({fmtPct(idx.dayChgPct)})
      </div>
    </div>
  );
};

/* ---------------- INDICES ---------------- */
const IndicesScreen = ({ market }) => {
  const [active, setActive] = React.useState("NIFTY");
  const idx = market.indices.find(i => i.sym === active);
  return (
    <div className="page">
      <h2 className="page-title">Indices</h2>
      <div className="page-sub">Live snapshot of major Indian indices.</div>

      <div className="grid" style={{ gridTemplateColumns: "repeat(4, 1fr)", marginBottom: 16 }}>
        {market.indices.map(i => (
          <button key={i.sym}
            onClick={() => setActive(i.sym)}
            className="kpi"
            style={{
              textAlign: "left",
              cursor: "pointer",
              borderColor: active === i.sym ? "var(--brand)" : "var(--border)",
              boxShadow: active === i.sym ? "0 0 0 3px var(--brand-soft)" : "none",
              transition: "border-color .15s",
            }}>
            <div className="kpi-label">{i.name}</div>
            <div className="kpi-value">{fmtNum(i.price)}</div>
            <div className={"kpi-foot " + (i.dayChg >= 0 ? "up" : "down")}>
              {i.dayChg >= 0 ? "▲" : "▼"} {fmtNum(Math.abs(i.dayChg))} ({fmtPct(i.dayChgPct)})
            </div>
          </button>
        ))}
      </div>

      <div className="card" style={{ marginBottom: 16 }}>
        <div className="row-between" style={{ marginBottom: 12 }}>
          <div>
            <div style={{ fontSize: 18, fontWeight: 700, letterSpacing: "-0.01em" }}>{idx.name}</div>
            <div style={{ fontSize: 12, color: "var(--text-3)" }}>NSE · Live</div>
          </div>
          <div className="row" style={{ gap: 6 }}>
            {["1m", "5m", "15m", "1H", "1D"].map(tf => (
              <button key={tf} className={"chip" + (tf === "5m" ? " brand" : "")}>{tf}</button>
            ))}
          </div>
        </div>
        <Candlestick candles={idx.candles} height={320}/>
      </div>

      <div className="grid" style={{ gridTemplateColumns: "1fr 1fr", gap: 16 }}>
        <div className="card">
          <div className="card-title">Top contributors</div>
          <table className="tbl">
            <thead><tr><th>Stock</th><th className="num">Weight</th><th className="num">Chg %</th><th className="num">Contribution</th></tr></thead>
            <tbody>
              {market.stocks.slice(0, 6).map(s => (
                <tr key={s.sym}>
                  <td><div style={{ fontWeight: 600 }}>{s.sym}</div></td>
                  <td className="num">{(rand(2, 12)).toFixed(2)}%</td>
                  <td className="num" style={{ color: s.dayChg >= 0 ? "var(--up)" : "var(--down)" }}>{fmtPct(s.dayChgPct)}</td>
                  <td className="num" style={{ color: s.dayChg >= 0 ? "var(--up)" : "var(--down)" }}>
                    {s.dayChg >= 0 ? "+" : ""}{(s.dayChg * 0.4).toFixed(1)} pts
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
        <div className="card">
          <div className="card-title">Market depth</div>
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 16 }}>
            <div>
              <div style={{ fontSize: 11, fontWeight: 700, color: "var(--up)", marginBottom: 8, letterSpacing: ".04em" }}>BIDS</div>
              {[1,2,3,4,5].map(i => (
                <div key={i} className="row-between mono" style={{ fontSize: 12, padding: "5px 0" }}>
                  <span>{fmtNum(idx.price - i * 2.5)}</span>
                  <span className="muted">{fmtCompact(Math.floor(rand(20000, 200000)))}</span>
                </div>
              ))}
            </div>
            <div>
              <div style={{ fontSize: 11, fontWeight: 700, color: "var(--down)", marginBottom: 8, letterSpacing: ".04em" }}>ASKS</div>
              {[1,2,3,4,5].map(i => (
                <div key={i} className="row-between mono" style={{ fontSize: 12, padding: "5px 0" }}>
                  <span>{fmtNum(idx.price + i * 2.5)}</span>
                  <span className="muted">{fmtCompact(Math.floor(rand(20000, 200000)))}</span>
                </div>
              ))}
            </div>
          </div>
        </div>
      </div>
    </div>
  );
};

function rand(a, b) { return Math.random() * (b - a) + a; }

/* ---------------- WATCHLIST ---------------- */
const ALWAYS_SUBSCRIBED_INDICES = ["NIFTY", "BANKNIFTY", "SENSEX", "FINNIFTY"];

const WatchlistScreen = ({ market, onTrade, addToast, subscribed, setSubscribed, wsStatus }) => {
  const [q, setQ] = React.useState("");
  const [searchResults, setSearchResults] = React.useState([]);
  const [showDropdown, setShowDropdown] = React.useState(false);
  const searchRef = React.useRef(null);
  // Extra meta for stocks added from scrip master that aren't in market.stocks
  const extrasRef = React.useRef({}); // sym → { sym, name, token, exch }
  const [scripReady, setScripReady] = React.useState(() => API.searchScrips("A", 1).length > 0);

  React.useEffect(() => {
    if (scripReady) return;
    const id = setInterval(() => {
      if (API.searchScrips("A", 1).length > 0) { setScripReady(true); clearInterval(id); }
    }, 1000);
    return () => clearInterval(id);
  }, [scripReady]);

  // When scrip master is ready, backfill meta for any saved watchlist stocks not in market
  React.useEffect(() => {
    if (!scripReady) return;
    const marketSyms = new Set(market.stocks.map(s => s.sym));
    subscribed.forEach(sym => {
      if (!marketSyms.has(sym) && !extrasRef.current[sym]) {
        const _sr = API.searchScrips(sym, 20);
        const found = _sr.find(s => s.sym === sym) ?? _sr[0];
        if (found) extrasRef.current[sym] = found;
      }
    });
  }, [scripReady, subscribed]);

  // Build display list: all subscribed symbols, with market data if available
  const marketMap = {};
  market.stocks.forEach(s => { marketMap[s.sym] = s; });

  const displayStocks = subscribed
    .filter(sym => !ALWAYS_SUBSCRIBED_INDICES.includes(sym))
    .map(sym => {
      if (marketMap[sym]) return marketMap[sym];
      const meta = extrasRef.current[sym] ?? {};
      return { sym, name: meta.name ?? sym, price: 0, dayChg: 0, dayChgPct: 0, volume: 0, high: 0, low: 0, sparkline: [], lastTick: 0 };
    }).filter(s =>
      !q || s.sym.toLowerCase().includes(q.toLowerCase()) || s.name.toLowerCase().includes(q.toLowerCase())
    );

  const handleSearchChange = (e) => {
    const val = e.target.value;
    setQ(val);
    if (val.length >= 3) {
      const results = API.searchScrips(val, 20);
      setSearchResults(results);
      setShowDropdown(results.length > 0);
    } else {
      setSearchResults([]);
      setShowDropdown(false);
    }
  };

  const addFromSearch = (scrip) => {
    const sym = scrip.sym;
    extrasRef.current[sym] = scrip; // save meta so it shows in the table
    if (!subscribed.includes(sym)) {
      setSubscribed(prev => [...new Set([...prev, sym])]);
      addToast({ type: "up", title: "Added to watchlist", body: `${sym} · ${scrip.name}` });
    } else {
      addToast({ type: "info", title: "Already in watchlist", body: sym });
    }
    setQ("");
    setSearchResults([]);
    setShowDropdown(false);
  };

  const removeFromWatchlist = (sym) => {
    setSubscribed(prev => prev.filter(x => x !== sym));
    delete extrasRef.current[sym];
    // Unsubscribe from live feed — look up token same way as subscribe
    const _sr = API.searchScrips(sym, 20);
    const tok = (typeof NSE_TOKENS !== "undefined" && NSE_TOKENS[sym])
      || (_sr.find(s => s.sym === sym) ?? _sr[0])?.token;
    if (tok && typeof VeloxWs !== "undefined") VeloxWs.unsubscribe([`nse_cm|${tok}`]);
    addToast({ type: "info", title: "Removed from watchlist", body: sym });
  };

  // Close dropdown on outside click
  React.useEffect(() => {
    const handler = (e) => {
      if (searchRef.current && !searchRef.current.contains(e.target)) {
        setShowDropdown(false);
      }
    };
    document.addEventListener("mousedown", handler);
    return () => document.removeEventListener("mousedown", handler);
  }, []);

  return (
    <div className="page">
      <div className="row-between" style={{ marginBottom: 16 }}>
        <div>
          <h2 className="page-title">Watchlist</h2>
          <div className="page-sub">{subscribed.length} stocks subscribed to live websocket feed
            {!scripReady && <span style={{ marginLeft: 8, fontSize: 11, color: "var(--text-3)" }}> · Loading scrip master…</span>}
          </div>
        </div>
        <div className="row" style={{ gap: 8 }}>
          <div style={{ position: "relative" }} ref={searchRef}>
            <input className="input" placeholder="Search NSE (3+ chars)…" value={q}
              onChange={handleSearchChange}
              onFocus={() => searchResults.length > 0 && setShowDropdown(true)}
              style={{ paddingLeft: 34, width: 260 }}/>
            <span style={{ position: "absolute", left: 10, top: "50%", transform: "translateY(-50%)", color: "var(--text-3)", pointerEvents: "none" }}>
              <Icon name="search" size={15}/>
            </span>
            {showDropdown && (
              <div style={{
                position: "absolute", top: "calc(100% + 4px)", left: 0, right: 0,
                background: "var(--surface)", border: "1px solid var(--border)",
                borderRadius: 10, boxShadow: "0 8px 24px rgba(0,0,0,.18)",
                zIndex: 100, maxHeight: 320, overflowY: "auto",
              }}>
                {searchResults.map((s, i) => (
                  <div key={i}
                    onMouseDown={() => addFromSearch(s)}
                    style={{
                      padding: "9px 14px", cursor: "pointer", borderBottom: "1px solid var(--border)",
                      display: "flex", justifyContent: "space-between", alignItems: "center",
                    }}
                    onMouseEnter={e => e.currentTarget.style.background = "var(--surface-2)"}
                    onMouseLeave={e => e.currentTarget.style.background = ""}
                  >
                    <div>
                      <div style={{ fontWeight: 600, fontSize: 13 }}>{s.sym}</div>
                      <div style={{ fontSize: 11, color: "var(--text-3)" }}>{s.name}</div>
                    </div>
                    <div className="chip" style={{ fontSize: 10 }}>{s.exch}</div>
                  </div>
                ))}
              </div>
            )}
          </div>
        </div>
      </div>

      {/* Live feed status */}
      <div className="card" style={{ marginBottom: 12, padding: "12px 16px" }}>
        <div className="row-between" style={{ marginBottom: 10 }}>
          <div className="row" style={{ gap: 8 }}>
            <div style={{
              width: 8, height: 8, borderRadius: "50%", flexShrink: 0, marginTop: 1,
              background: wsStatus === "connected" ? "var(--up)" : wsStatus === "connecting" ? "#F59E0B" : "var(--down)",
              boxShadow: wsStatus === "connected" ? "0 0 6px var(--up)" : "none",
            }}/>
            <span style={{ fontSize: 13, fontWeight: 600 }}>
              Live Feed · {wsStatus === "connected" ? "Connected" : wsStatus === "connecting" ? "Connecting…" : "Disconnected"}
            </span>
            <span className="muted" style={{ fontSize: 12 }}>
              {subscribed.filter(s => !ALWAYS_SUBSCRIBED_INDICES.includes(s)).length} stocks +
              {ALWAYS_SUBSCRIBED_INDICES.length} indices
            </span>
          </div>
          <span style={{ fontSize: 11, color: "var(--text-3)" }}>
            Indices always on · Stocks from watchlist
          </span>
        </div>

        {/* Indices row — always subscribed */}
        <div style={{ marginBottom: 8 }}>
          <div style={{ fontSize: 11, color: "var(--text-3)", fontWeight: 600, marginBottom: 5, textTransform: "uppercase", letterSpacing: ".05em" }}>Indices (always on)</div>
          <div className="row" style={{ flexWrap: "wrap", gap: 6 }}>
            {ALWAYS_SUBSCRIBED_INDICES.map(sym => {
              const idx = market.indices.find(i => i.sym === sym);
              return (
                <div key={sym} style={{
                  display: "flex", alignItems: "center", gap: 6,
                  background: "var(--surface-2)", borderRadius: 8, padding: "5px 10px",
                  fontSize: 12, border: "1px solid var(--border)",
                }}>
                  <span style={{ width: 6, height: 6, borderRadius: "50%", background: wsStatus === "connected" ? "var(--up)" : "var(--text-3)", flexShrink: 0 }}/>
                  <span style={{ fontWeight: 600 }}>{sym}</span>
                  {idx && <span className="mono" style={{ color: idx.dayChg >= 0 ? "var(--up)" : "var(--down)", fontSize: 11 }}>
                    {idx.price ? fmtNum(idx.price, 2) : "—"}
                  </span>}
                </div>
              );
            })}
          </div>
        </div>

        {/* Stock subscriptions */}
        <div>
          <div style={{ fontSize: 11, color: "var(--text-3)", fontWeight: 600, marginBottom: 5, textTransform: "uppercase", letterSpacing: ".05em" }}>
            Stocks ({subscribed.filter(s => !ALWAYS_SUBSCRIBED_INDICES.includes(s)).length})
          </div>
          <div className="row" style={{ flexWrap: "wrap", gap: 6 }}>
            {subscribed.filter(s => !ALWAYS_SUBSCRIBED_INDICES.includes(s)).map(sym => {
              const stock = market.stocks.find(s => s.sym === sym);
              return (
                <div key={sym} style={{
                  display: "flex", alignItems: "center", gap: 6,
                  background: "var(--surface-2)", borderRadius: 8, padding: "5px 10px",
                  fontSize: 12, border: "1px solid var(--border)",
                }}>
                  <span style={{ width: 6, height: 6, borderRadius: "50%", background: wsStatus === "connected" ? "var(--up)" : "var(--text-3)", flexShrink: 0 }}/>
                  <span style={{ fontWeight: 600 }}>{sym}</span>
                  {stock && <span className="mono" style={{ fontSize: 11, color: "var(--text-3)" }}>
                    {stock.price ? fmtNum(stock.price, 2) : "—"}
                  </span>}
                  <button onClick={() => removeFromWatchlist(sym)}
                    style={{ background: "none", border: "none", cursor: "pointer", color: "var(--text-3)", padding: 0, lineHeight: 1, fontSize: 13 }}
                    title="Remove">×</button>
                </div>
              );
            })}
            {subscribed.filter(s => !ALWAYS_SUBSCRIBED_INDICES.includes(s)).length === 0 && (
              <span className="muted" style={{ fontSize: 12 }}>No stocks — search above to add</span>
            )}
          </div>
        </div>
      </div>

      <div className="card" style={{ padding: 0, overflow: "hidden" }}>
        <table className="tbl">
          <thead>
            <tr>
              <th style={{ width: 48 }}></th>
              <th>Stock</th>
              <th className="num">LTP</th>
              <th className="num">Chg</th>
              <th className="num">Chg %</th>
              <th className="num">Vol</th>
              <th className="num">Day H/L</th>
              <th>Trend</th>
              <th></th>
            </tr>
          </thead>
          <tbody>
            {displayStocks.map(s => (
              <tr key={s.sym}>
                <td>
                  <button className="btn-icon btn-ghost" onClick={() => removeFromWatchlist(s.sym)}
                    title="Remove from watchlist"
                    style={{ color: "var(--text-3)" }}>
                    <Icon name="x" size={14}/>
                  </button>
                </td>
                <td>
                  <div style={{ fontWeight: 600 }}>{s.sym}</div>
                  <div style={{ fontSize: 11, color: "var(--text-3)" }}>{s.name}</div>
                </td>
                <td className={"num " + (s.lastTick === 1 ? "tick-flash-up" : s.lastTick === -1 ? "tick-flash-down" : "")}>
                  {s.price ? fmtNum(s.price) : <span className="muted">—</span>}
                </td>
                <td className="num" style={{ color: s.dayChg >= 0 ? "var(--up)" : "var(--down)" }}>
                  {s.price ? (s.dayChg >= 0 ? "+" : "") + fmtNum(s.dayChg) : <span className="muted">—</span>}
                </td>
                <td className="num" style={{ color: s.dayChg >= 0 ? "var(--up)" : "var(--down)", fontWeight: 600 }}>
                  {s.price ? fmtPct(s.dayChgPct) : <span className="muted">—</span>}
                </td>
                <td className="num muted">{s.volume ? fmtCompact(s.volume) : "—"}</td>
                <td className="num muted" style={{ fontSize: 11 }}>
                  {s.high ? `${fmtNum(s.high, 1)} / ${fmtNum(s.low, 1)}` : "—"}
                </td>
                <td><Sparkline data={s.sparkline} width={70} height={22}/></td>
                <td className="num">
                  <div className="row" style={{ justifyContent: "flex-end", gap: 6 }}>
                    <button className="btn btn-buy btn-sm" onClick={() => onTrade(s, "BUY")}>Buy</button>
                    <button className="btn btn-sell btn-sm" onClick={() => onTrade(s, "SELL")}>Sell</button>
                  </div>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
};

/* ---------------- OPTION CHAIN ---------------- */
const OptionChainScreen = ({ market, onTradeOption }) => {
  const [underlying, setUnderlying] = React.useState("NIFTY");
  const [expiries, setExpiries]     = React.useState([]);
  const [expiry, setExpiry]         = React.useState("");
  const [rows, setRows]             = React.useState([]); // [{ strike, ce, pe }]
  const [ltps, setLtps]             = React.useState({}); // token → ltp
  const [loading, setLoading]       = React.useState(false);
  const subscribedTokens            = React.useRef(new Set());

  const idx = market.indices.find(i => i.sym === underlying) ?? market.indices[0];
  const spot = idx?.price ?? 0;
  const step = underlying === "BANKNIFTY" ? 100 : 50;
  const atm  = Math.round(spot / step) * step;

  // Load expiries from F&O scrip master
  React.useEffect(() => {
    let cancelled = false;
    const load = async () => {
      setLoading(true);
      let exps = API.getOptionExpiries(underlying);
      if (!exps.length) {
        await API.loadScripMaster();
        exps = API.getOptionExpiries(underlying);
      }
      if (cancelled) return;
      setExpiries(exps);
      setExpiry(exps[0] ?? "");
      setLoading(false);
    };
    load();
    return () => { cancelled = true; };
  }, [underlying]);

  // Build rows from scrip master when expiry changes
  React.useEffect(() => {
    if (!expiry) return;
    const ces = API.searchOptions(underlying, expiry, "CE", 200);
    const pes = API.searchOptions(underlying, expiry, "PE", 200);
    const ceMap = {}, peMap = {};
    ces.forEach(s => { ceMap[API.strikeFromScrip(s)] = s; });
    pes.forEach(s => { peMap[API.strikeFromScrip(s)] = s; });
    const strikes = [...new Set([...Object.keys(ceMap), ...Object.keys(peMap)].map(Number))].sort((a,b) => a-b);
    // Show 10 strikes above and below ATM
    const near = strikes.filter(s => Math.abs(s - atm) <= step * 10);
    setRows(near.map(strike => ({ strike, ce: ceMap[strike] ?? null, pe: peMap[strike] ?? null })));
    setLtps({});
    // Unsubscribe old tokens — subscribedTokens stores "exch|token" strings
    if (subscribedTokens.current.size > 0) {
      VeloxWs.unsubscribe([...subscribedTokens.current]);
      subscribedTokens.current.clear();
    }
  }, [expiry, underlying]);

  // Listen to WS ticks for subscribed option tokens
  React.useEffect(() => {
    const prev = VeloxWs.onTick;
    VeloxWs.onTick = (tick) => {
      if (prev) prev(tick);
      // subscribedTokens stores "exch|token"; tick.scrip is just the token
      const hasToken = [...subscribedTokens.current].some(t => t.endsWith(`|${tick.scrip}`));
      if (hasToken) setLtps(l => ({ ...l, [tick.scrip]: tick.ltp }));
    };
    return () => { VeloxWs.onTick = prev; };
  }, []);

  // Unsubscribe all on unmount
  React.useEffect(() => {
    return () => {
      if (subscribedTokens.current.size > 0) {
        VeloxWs.unsubscribe([...subscribedTokens.current]);
      }
    };
  }, []);

  const subscribeOption = (scrip) => {
    if (!scrip?.token) return;
    const exch = scrip.exch ?? "nse_fo";
    const key = `${exch}|${scrip.token}`;
    if (subscribedTokens.current.has(key)) return;
    subscribedTokens.current.add(key);
    VeloxWs.subscribe([key]);
  };

  const handleClick = (scrip, type) => {
    subscribeOption(scrip);
    const ltp = ltps[scrip?.token] ?? 0;
    onTradeOption(underlying, scrip?.sym, type, ltp, scrip);
  };

  return (
    <div className="page">
      <div className="row-between" style={{ marginBottom: 16 }}>
        <div>
          <h2 className="page-title">Option Chain</h2>
          <div className="page-sub">Click any LTP to trade · {underlying} · {expiry ? API.formatExpiry(expiry) : "loading…"}</div>
        </div>
        <div className="row" style={{ gap: 8 }}>
          <select className="select" value={underlying} onChange={e => setUnderlying(e.target.value)} style={{ width: 160 }}>
            {["NIFTY","BANKNIFTY","FINNIFTY","MIDCPNIFTY","SENSEX"].map(u => <option key={u}>{u}</option>)}
          </select>
          <select className="select" value={expiry} onChange={e => setExpiry(e.target.value)} style={{ width: 220 }} disabled={!expiries.length}>
            {loading && <option value="">Loading…</option>}
            {expiries.map(e => <option key={e} value={e}>{API.formatExpiry(e)}</option>)}
          </select>
        </div>
      </div>

      <div className="card" style={{ marginBottom: 16, padding: "14px 18px" }}>
        <div className="row" style={{ gap: 30, flexWrap: "wrap" }}>
          <div>
            <div className="muted" style={{ fontSize: 11, fontWeight: 600, textTransform: "uppercase", letterSpacing: ".05em" }}>Spot</div>
            <div className="mono" style={{ fontSize: 18, fontWeight: 700 }}>{fmtNum(spot)}</div>
          </div>
          <div>
            <div className="muted" style={{ fontSize: 11, fontWeight: 600, textTransform: "uppercase", letterSpacing: ".05em" }}>Day chg</div>
            <div className="mono" style={{ fontSize: 16, fontWeight: 700, color: idx?.dayChg >= 0 ? "var(--up)" : "var(--down)" }}>
              {fmtPct(idx?.dayChgPct ?? 0)}
            </div>
          </div>
          <div>
            <div className="muted" style={{ fontSize: 11, fontWeight: 600, textTransform: "uppercase", letterSpacing: ".05em" }}>ATM</div>
            <div className="mono" style={{ fontSize: 16, fontWeight: 700 }}>{atm}</div>
          </div>
        </div>
      </div>

      {loading && <div className="muted" style={{ textAlign: "center", padding: 40 }}>Loading F&O scrip master…</div>}

      {!loading && rows.length === 0 && expiry && (
        <div className="muted" style={{ textAlign: "center", padding: 40 }}>No strikes found for {underlying} · {expiry}</div>
      )}

      {rows.length > 0 && (
        <div className="card" style={{ padding: 0, overflow: "hidden" }}>
          <div style={{ overflowX: "auto" }}>
            <table className="tbl" style={{ minWidth: 700 }}>
              <thead>
                <tr>
                  <th colSpan={2} style={{ textAlign: "center", background: "var(--up-soft)", color: "var(--up)", borderRight: "1px solid var(--border)" }}>CALLS</th>
                  <th style={{ background: "var(--surface-2)", textAlign: "center" }}>STRIKE</th>
                  <th colSpan={2} style={{ textAlign: "center", background: "var(--down-soft)", color: "var(--down)", borderLeft: "1px solid var(--border)" }}>PUTS</th>
                </tr>
                <tr>
                  <th className="num">Sym</th>
                  <th className="num" style={{ borderRight: "1px solid var(--border)" }}>LTP</th>
                  <th className="num" style={{ background: "var(--surface-2)", textAlign: "center" }}>Strike</th>
                  <th className="num" style={{ borderLeft: "1px solid var(--border)" }}>LTP</th>
                  <th className="num">Sym</th>
                </tr>
              </thead>
              <tbody>
                {rows.map(r => {
                  const isAtm = r.strike === atm;
                  const ceLtp = ltps[r.ce?.token] ?? null;
                  const peLtp = ltps[r.pe?.token] ?? null;
                  return (
                    <tr key={r.strike} style={{ background: isAtm ? "var(--brand-soft)" : "transparent" }}>
                      <td className="num muted" style={{ fontSize: 11 }}>{r.ce?.sym ?? "—"}</td>
                      <td className="num" style={{ borderRight: "1px solid var(--border)" }}>
                        {r.ce ? (
                          <button onClick={() => handleClick(r.ce, "CE")}
                            style={{ padding: "2px 8px", background: "var(--up-soft)", border: "1px solid var(--up)", borderRadius: 5, color: "var(--up)", fontWeight: 700, fontFamily: "var(--font-mono)", cursor: "pointer", fontSize: 13 }}>
                            {ceLtp != null ? fmtNum(ceLtp) : "Click"}
                          </button>
                        ) : "—"}
                      </td>
                      <td className="num" style={{ background: isAtm ? "var(--brand-soft)" : "var(--surface-2)", fontWeight: 700, textAlign: "center" }}>
                        {r.strike}
                      </td>
                      <td className="num" style={{ borderLeft: "1px solid var(--border)" }}>
                        {r.pe ? (
                          <button onClick={() => handleClick(r.pe, "PE")}
                            style={{ padding: "2px 8px", background: "var(--down-soft)", border: "1px solid var(--down)", borderRadius: 5, color: "var(--down)", fontWeight: 700, fontFamily: "var(--font-mono)", cursor: "pointer", fontSize: 13 }}>
                            {peLtp != null ? fmtNum(peLtp) : "Click"}
                          </button>
                        ) : "—"}
                      </td>
                      <td className="num muted" style={{ fontSize: 11 }}>{r.pe?.sym ?? "—"}</td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </div>
        </div>
      )}
    </div>
  );
};

Object.assign(window, { LoginScreen, Dashboard, IndicesScreen, WatchlistScreen, OptionChainScreen });
