/* eagle-demo.jsx — run engine + Model ("the black box") and Application
   ("the pipeline") screens. Each consumes the runX(alert, emit, shouldStop)
   seam and renders a visually distinct experience. */

function _initRun() {
  return {
    events: [], response: "", responseStarted: false, responseDone: false, forgotten: false,
    nav: { tokIn: 0, tokOut: 0, cost: 0, latency: 0, tps: 0 },
    stages: {}, ragDocs: [], ctx: null,
    agents: {}, agentFind: {}, mcp: [], mcpPending: null, actions: [], a2a: [], report: null, summary: null,
  };
}
function _apply(s, ev, t0) {
  const ts = (performance.now() - t0) / 1000;
  switch (ev.t) {
    case "nav": return { ...s, nav: { tokIn: ev.tokIn, tokOut: ev.tokOut, cost: ev.cost, latency: ev.latency, tps: ev.tps } };
    case "telem": return { ...s, events: [...s.events, { ...ev, _id: window.eagleEid(), ts }] };
    case "token": return { ...s, response: s.response + ev.text };
    case "respStart": return { ...s, responseStarted: true, responseDone: false };
    case "respDone": return { ...s, responseDone: true };
    case "forgotten": return { ...s, forgotten: true };
    case "stage": return { ...s, stages: { ...s.stages, [ev.id]: ev.status } };
    case "ragdoc": return { ...s, ragDocs: [...s.ragDocs, ev.doc] };
    case "ctx": return { ...s, ctx: ev.parts };
    case "agent": return { ...s, agents: { ...s.agents, [ev.id]: ev.status } };
    case "agentfind": return { ...s, agentFind: { ...s.agentFind, [ev.id]: { sev: ev.sev, cat: ev.cat } } };
    case "mcpstart": return { ...s, mcpPending: ev.tool };
    case "mcp": return { ...s, mcp: [...s.mcp, { ...ev, _id: window.eagleEid() }], mcpPending: null };
    case "action": {
      const i = s.actions.findIndex((a) => a.id === ev.id);
      if (i >= 0) { const n = [...s.actions]; n[i] = { ...ev }; return { ...s, actions: n }; }
      return { ...s, actions: [...s.actions, { ...ev }] };
    }
    case "a2a": return { ...s, a2a: [...s.a2a, { ...ev, _id: window.eagleEid() }] };
    case "report": return { ...s, report: ev };
    case "summary": return { ...s, summary: ev };
    default: return s;
  }
}
function useEagleRun(runner) {
  const [state, setState] = React.useState(_initRun);
  const [running, setRunning] = React.useState(false);
  const idRef = React.useRef(0); const t0Ref = React.useRef(0);
  function clearTelem() { setState((s) => ({ ...s, events: [] })); }
  function reset() { idRef.current++; setRunning(false); setState(_initRun()); }
  async function run(alert) {
    const myId = ++idRef.current; const shouldStop = () => idRef.current !== myId;
    t0Ref.current = performance.now(); setState(_initRun()); setRunning(true);
    const emit = (ev) => { if (!shouldStop()) setState((s) => _apply(s, ev, t0Ref.current)); };
    try { await runner(alert, emit, shouldStop); } catch (e) { console.error("eagle run", e); }
    if (!shouldStop()) setRunning(false);
  }
  return { state, running, run, reset, clearTelem };
}
function fmtMeters(nav, extra = 0) {
  const tot = nav.tokIn + nav.tokOut;
  return { tokens: tot ? nav.tokIn.toLocaleString() + " / " + nav.tokOut : "0", cost: window.eagleFmtCost(nav.cost + extra), latency: nav.latency ? (nav.latency >= 1000 ? (nav.latency / 1000).toFixed(2) + "s" : nav.latency + "ms") : "—" };
}
// cmd+enter to run, scoped to the *visible* screen (all live screens stay mounted)
function useRunHotkey(onRun, running, active = true) {
  React.useEffect(() => {
    if (!active) return;
    const h = (e) => { if ((e.metaKey || e.ctrlKey) && e.key === "Enter") { e.preventDefault(); if (!running) onRun(); } };
    window.addEventListener("keydown", h); return () => window.removeEventListener("keydown", h);
  }, [onRun, running, active]);
}

/* ---- streaming response block ------------------------------- */
function ResponseBlock({ state, layerKey, emptyHint }) {
  const E = useE(); const lc = E[layerKey];
  const showCursor = state.responseStarted && !state.responseDone;
  if (!state.responseStarted && !state.response) {
    return <div className="flex flex-col items-center justify-center rounded-xl px-6 py-10 text-center" style={{ background: E.surface, border: `1px dashed ${E.border}`, color: E.muted }}>
      <window.Icon name="Sparkles" size={20} style={{ color: lc }} /><p className="mt-2 max-w-xs text-[12.5px] leading-relaxed">{emptyHint}</p>
    </div>;
  }
  return (
    <div className="rounded-xl" style={{ background: E.surface, border: `1px solid ${E.border}` }}>
      <div className="flex items-center justify-between border-b px-3.5 py-2" style={{ borderColor: E.border }}>
        <span className="inline-flex items-center gap-2 text-[11px] font-semibold uppercase tracking-[0.14em]" style={{ color: E.muted, fontFamily: E.mono }}><window.Icon name="MessageSquare" size={13} /> Response {state.responseDone && <window.Icon name="Check" size={13} style={{ color: E.success }} />}</span>
        {state.responseDone && <window.CopyBtn getText={() => state.response} />}
      </div>
      <div className="px-4 py-3"><div style={{ maxWidth: "78ch" }}><window.Markdown text={state.response} />{showCursor && <span className="ml-0.5 inline-block h-4 w-[7px] translate-y-0.5" style={{ background: lc, animation: "lr-fade .8s steps(2) infinite" }} />}</div></div>
    </div>
  );
}

/* ---- run summary strip -------------------------------------- */
function RunSummary({ s, layerKey }) {
  const E = useE(); const lc = E[layerKey]; const items = [];
  if (s.steps != null) items.push(["Steps", s.steps]);
  if (s.tools != null) items.push(["Tools", s.tools]);
  if (s.mcp != null) items.push(["MCP calls", s.mcp]);
  if (s.a2a != null) items.push(["A2A msgs", s.a2a]);
  if (s.actions != null) items.push(["Actions", s.actions]);
  if (s.calls != null) items.push(["API calls", s.calls]);
  items.push(["Tokens", s.tokens.toLocaleString()], ["Cost", s.cost], ["Time", s.time]);
  return (
    <div className="grid grid-cols-3 gap-px overflow-hidden rounded-xl sm:grid-cols-4 a-fade-up" style={{ background: E.border, border: `1px solid ${E.border}` }}>
      {items.map(([k, v], i) => <div key={i} className="px-3 py-2.5" style={{ background: E.surface }}><div className="text-[9.5px] uppercase tracking-[0.14em]" style={{ color: E.muted }}>{k}</div><div className="mt-0.5 text-[15px] font-bold tabular-nums" style={{ fontFamily: E.mono, color: i === items.length - 2 ? lc : E.text }}>{v}</div></div>)}
    </div>
  );
}

/* ============================================================
   MODEL — "the black box"
   ============================================================ */
function BlackBox({ phase, lc }) {
  const E = useE();
  const thinking = phase === "thinking";
  return (
    <div className="relative flex flex-col items-center">
      <div className="relative flex h-36 w-36 items-center justify-center rounded-2xl" style={{ background: E.isDark ? "#0a0a10" : "#0f172a", border: `1px solid ${thinking ? lc : E.borderStrong}`, boxShadow: thinking ? `0 0 0 1px ${lc}55, 0 0 40px -6px ${lc}` : "none", transition: "box-shadow .4s, border-color .4s" }}>
        {thinking && <span className="absolute inset-0 rounded-2xl" style={{ border: `1px solid ${lc}`, animation: "eagle-ping 1.6s ease-out infinite" }} />}
        <div className="text-center">
          <window.Icon name="Box" size={30} style={{ color: lc }} />
          <div className="mt-1.5 text-[10px] font-bold uppercase tracking-[0.18em]" style={{ color: "#e8e8f2", fontFamily: E.mono }}>Raw model</div>
          <div className="text-[9px] uppercase tracking-[0.12em]" style={{ color: "#7676a8", fontFamily: E.mono }}>{thinking ? "thinking…" : "stateless"}</div>
        </div>
      </div>
    </div>
  );
}

const MODEL_LACKS = [
  ["Memory", "Brain", "stateless — forgets every request"],
  ["Tools / MCP", "Wrench", "cannot call any tool or system"],
  ["RAG retrieval", "Database", "no access to runbooks or history"],
  ["Guardrails", "ShieldCheck", "input & output are unfiltered"],
  ["Gateway policy", "RouteOff", "no routing, limits or logging"],
  ["Agent identity", "Fingerprint", "unauthenticated, no scoped creds"],
];
function CapabilitiesPanel() {
  const E = useE();
  return (
    <div className="rounded-xl" style={{ background: E.surface, border: `1px solid ${E.border}` }}>
      <div className="border-b px-3.5 py-2.5" style={{ borderColor: E.border }}>
        <div className="flex items-center gap-2 text-[11px] font-bold uppercase tracking-[0.16em]" style={{ color: E.muted, fontFamily: E.mono }}><window.Icon name="Layers" size={13} /> Capabilities</div>
        <div className="mt-0.5 text-[11px]" style={{ color: E.muted }}>what a raw model lacks — the contrast is the point</div>
      </div>
      <div className="divide-y" style={{ borderColor: E.border }}>
        {MODEL_LACKS.map(([label, icon, note]) => (
          <div key={label} className="flex items-center gap-2.5 px-3.5 py-2.5" style={{ borderColor: E.border }}>
            <span className="flex h-6 w-6 shrink-0 items-center justify-center rounded-md" style={{ background: E.guard + "14", color: E.guard }}><window.Icon name="X" size={13} /></span>
            <window.Icon name={icon} size={14} style={{ color: E.muted }} />
            <div className="min-w-0 flex-1">
              <div className="text-[12.5px] font-semibold line-through" style={{ color: E.muted, textDecorationColor: E.guard }}>{label}</div>
              <div className="text-[10.5px]" style={{ color: E.muted }}>{note}</div>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}
function ModelScreen({ alert, onBack, onPickAlert, mode, onToggleTheme, onGo, active }) {
  const E = useE(); const L = window.LAYERS.model; const lc = E.model;
  const { state, running, run, reset, clearTelem } = useEagleRun(window.runModel);
  const started = running || state.responseStarted || state.forgotten;
  const phase = running && !state.responseStarted ? "thinking" : "idle";
  const meters = fmtMeters(state.nav);
  const doRun = React.useCallback(() => run(alert), [alert]);
  useRunHotkey(doRun, running, active);
  React.useEffect(() => { reset(); }, [alert.id]);

  return (
    <div className="flex h-full flex-col" style={{ background: E.bg }}>
      <EagleNav layer={L} meters={meters} running={running} onBack={onBack} mode={mode} onToggleTheme={onToggleTheme} current="model" onGo={onGo}
        center={<span className="ml-1 inline-flex shrink-0 items-center gap-2 whitespace-nowrap rounded-lg px-2.5 py-1.5 text-[11px] font-bold uppercase tracking-[0.12em]" style={{ color: E.guard, background: E.guard + "14", border: `1px solid ${E.guard}33`, fontFamily: E.mono }}><span className="inline-block h-2 w-2 rounded-full" style={{ background: E.guard, animation: "lr-pulse-ring 1.6s infinite", boxShadow: `0 0 8px ${E.guard}` }} /> No memory</span>} />

      <div className="lr-scroll flex-1 overflow-y-auto px-6 py-5 lg:px-8">
        <div className="w-full space-y-5">
          <RunBar layer={L} alert={alert} running={running} started={started} onRun={doRun} onReset={reset} onPickAlert={onPickAlert} runLabel="Send to model" />

          <div className="grid items-start gap-5 lg:grid-cols-5">
            {/* main column */}
            <div className="space-y-5 lg:col-span-3">
              <div className="flex flex-col items-center gap-2.5 rounded-xl py-7" style={{ background: E.surface, border: `1px solid ${E.border}`, backgroundImage: `radial-gradient(${E.grid} 1px, transparent 1px)`, backgroundSize: "18px 18px" }}>
                <div className="rounded-lg px-3 py-1.5 text-[11px]" style={{ fontFamily: E.mono, color: E.muted, background: E.fill, border: `1px solid ${E.border}` }}>{alert.code} · alert in →</div>
                <BlackBox phase={phase} lc={lc} />
                <window.Icon name="ChevronDown" size={16} style={{ color: E.muted }} />
                <div className="text-[11px]" style={{ color: E.muted, fontFamily: E.mono }}>one-shot answer ↓</div>
              </div>

              <div className="relative">
                <ResponseBlock state={state} layerKey="model" emptyHint="A raw model has no system prompt, no tools and no memory. Send the alert to see its one-shot answer." />
                {state.forgotten && (
                  <div className="mt-2.5 flex items-start gap-2 rounded-lg px-3 py-2.5 a-fade" style={{ background: E.guard + "10", border: `1px solid ${E.guard}33` }}>
                    <window.Icon name="EyeOff" size={15} style={{ color: E.guard, marginTop: 1 }} />
                    <div className="text-[12px] leading-relaxed" style={{ color: E.text2 }}>
                      <span className="font-bold" style={{ color: E.text }}>No memory.</span> The answer above is all you get — the model keeps no state, so the next request starts cold with zero recollection of this one.
                    </div>
                  </div>
                )}
              </div>

              {state.summary && <RunSummary s={state.summary} layerKey="model" />}
            </div>

            {/* rail: capabilities (the lacks) + sparse telemetry */}
            <div className="space-y-5 lg:col-span-2">
              <CapabilitiesPanel />
              <div className="rounded-xl" style={{ background: E.surface, border: `1px solid ${E.border}` }}>
                <div className="flex items-center justify-between border-b px-3.5 py-2.5" style={{ borderColor: E.border }}>
                  <span className="inline-flex items-center gap-2 text-[11px] font-bold uppercase tracking-[0.16em]" style={{ color: E.muted, fontFamily: E.mono }}><window.Icon name="Activity" size={13} /> Under the hood</span>
                  <span className="text-[10.5px]" style={{ color: E.muted, fontFamily: E.mono }}>{state.events.length} events</span>
                </div>
                <div className="space-y-2 px-3.5 py-3">
                  {state.events.length === 0 ? <p className="py-3 text-center text-[12px]" style={{ color: E.muted }}>No telemetry until you run — and there won't be much.</p> : state.events.map((ev) => <ModelTelemRow key={ev._id} ev={ev} />)}
                  {(state.summary || state.forgotten) && <div className="mt-2 rounded-lg px-3 py-2.5 text-[12px] leading-relaxed" style={{ background: E.fill, color: E.muted }}><window.Icon name="Info" size={13} style={{ color: lc, display: "inline", verticalAlign: "-2px" }} /> That's all there is — one API call, no retrieval, no tools, no memory. The emptiness <em>is</em> the point.</div>}
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}
// compact telem row for the model rail
function ModelTelemRow({ ev }) {
  const E = useE(); const c = E[ev.ck] || E.muted;
  return (
    <div className="flex items-center gap-2.5">
      <span className="text-[10px] tabular-nums" style={{ color: E.muted, fontFamily: E.mono, minWidth: 42 }}>+{ev.ts.toFixed(2)}s</span>
      <span className="h-1.5 w-1.5 rounded-full" style={{ background: c }} />
      <span className="flex-1 text-[12px]" style={{ color: E.text }}>{ev.label}</span>
      {ev.value && <span className="text-[11px] font-semibold" style={{ fontFamily: E.mono, color: c }}>{ev.value}</span>}
      {ev.ok && <window.Icon name="Check" size={12} style={{ color: E.success }} />}
    </div>
  );
}

/* ============================================================
   APPLICATION — "the pipeline"
   ============================================================ */
const APP_NODES = [
  { id: "guard_in", label: "Input Guardrails", icon: "ShieldCheck", ck: "guard" },
  { id: "rag", label: "RAG Retrieval", icon: "Database", ck: "rag" },
  { id: "ctx", label: "Context Assembly", icon: "Layers", ck: "app" },
  { id: "model", label: "Model", icon: "Box", ck: "model" },
  { id: "guard_out", label: "Output Guardrails", icon: "ShieldCheck", ck: "guard" },
];
function PipelineStrip({ stages }) {
  const E = useE();
  return (
    <div className="lr-scroll overflow-x-auto rounded-xl px-4 py-4" style={{ background: E.surface, border: `1px solid ${E.border}` }}>
      <div className="flex items-center gap-1" style={{ minWidth: 640 }}>
        {APP_NODES.map((n, i) => {
          const st = stages[n.id]; const c = E[n.ck]; const on = st === "active" || st === "done";
          return (
            <React.Fragment key={n.id}>
              <div className="flex flex-1 flex-col items-center gap-1.5 text-center">
                <div className="relative flex h-11 w-11 items-center justify-center rounded-xl transition-all" style={{ background: on ? c + "1f" : E.fill, color: on ? c : E.muted, border: `1px solid ${st === "active" ? c : on ? c + "55" : E.border}`, boxShadow: st === "active" ? `0 0 16px -2px ${c}` : "none" }}>
                  <window.Icon name={n.icon} size={18} />
                  {st === "active" && <span className="absolute inset-0 rounded-xl" style={{ border: `1px solid ${c}`, animation: "eagle-ping 1.4s ease-out infinite" }} />}
                  {st === "done" && <span className="absolute -right-1 -top-1 flex h-4 w-4 items-center justify-center rounded-full" style={{ background: E.success, color: E.isDark ? "#04110f" : "#fff" }}><window.Icon name="Check" size={10} /></span>}
                </div>
                <span className="text-[10px] font-semibold leading-tight" style={{ color: on ? E.text : E.muted }}>{n.label}</span>
              </div>
              {i < APP_NODES.length - 1 && <div className="mb-4 h-[2px] w-8 shrink-0 rounded" style={{ background: stages[APP_NODES[i + 1].id] || stages[n.id] === "done" ? E.app : E.border, transition: "background .4s" }} />}
            </React.Fragment>
          );
        })}
      </div>
    </div>
  );
}
function ContextBar({ ctx }) {
  const E = useE();
  if (!ctx) return null;
  const segs = [["system", "system", E.gateway], ["history", "history", E.cost], ["rag", "RAG docs", E.rag], ["alert", "alert", E.high]];
  const total = ctx.system + ctx.history + ctx.rag + ctx.alert;
  return (
    <div className="rounded-xl p-3.5 a-fade-up" style={{ background: E.surface, border: `1px solid ${E.border}` }}>
      <div className="mb-2 flex items-center justify-between">
        <span className="text-[11px] font-bold uppercase tracking-[0.14em]" style={{ color: E.muted, fontFamily: E.mono }}>Context composition</span>
        <span className="text-[12px] font-bold tabular-nums" style={{ fontFamily: E.mono, color: E.app }}>{total.toLocaleString()} input tok</span>
      </div>
      <div className="flex h-5 overflow-hidden rounded-md">
        {segs.map(([k, , c]) => <div key={k} style={{ width: (ctx[k] / total * 100) + "%", background: c, transition: "width .8s cubic-bezier(.22,1,.36,1)" }} title={k + ": " + ctx[k]} />)}
      </div>
      <div className="mt-2 flex flex-wrap gap-x-4 gap-y-1">
        {segs.map(([k, label, c]) => <span key={k} className="inline-flex items-center gap-1.5 text-[11px]" style={{ color: E.text2 }}><span className="h-2 w-2 rounded-sm" style={{ background: c }} /> {label} <span className="tabular-nums" style={{ fontFamily: E.mono, color: E.muted }}>{ctx[k]}</span></span>)}
      </div>
    </div>
  );
}
function RagDocCard({ doc }) {
  const E = useE(); const [open, setOpen] = React.useState(false);
  return (
    <div className="rounded-xl a-fade-up" style={{ background: E.surface, border: `1px solid ${E.rag}33` }}>
      <button onClick={() => setOpen((v) => !v)} className="flex w-full items-center gap-2.5 px-3 py-2.5 text-left">
        <window.Icon name="FileText" size={15} style={{ color: E.rag }} />
        <span className="min-w-0 flex-1 truncate text-[12.5px] font-medium" style={{ color: E.text }}>{doc.title}</span>
        <span className="rounded px-1.5 py-0.5 text-[10px] font-bold tabular-nums" style={{ fontFamily: E.mono, color: E.rag, background: E.rag + "1f" }}>{doc.score.toFixed(2)}</span>
        <window.Icon name={open ? "ChevronDown" : "ChevronRight"} size={14} style={{ color: E.muted }} />
      </button>
      {open && <div className="border-t px-3 py-2.5 text-[12px] leading-relaxed" style={{ borderColor: E.border, color: E.muted }}>{doc.snippet}</div>}
    </div>
  );
}

function GuardrailChips({ stages }) {
  const E = useE();
  const checks = [["Input validation", "guard_in"], ["Injection scan", "guard_in"], ["PII detection", "guard_in"], ["IP-range check", "guard_out"], ["Destructive-action", "guard_out"], ["Confidence ≥ 0.9", "guard_out"]];
  const stat = (s) => stages[s] === "done" ? "pass" : stages[s] === "active" ? "run" : "idle";
  return (
    <div className="rounded-xl p-3.5" style={{ background: E.surface, border: `1px solid ${E.border}` }}>
      <div className="mb-2 flex items-center gap-2 text-[11px] font-bold uppercase tracking-[0.14em]" style={{ color: E.guard, fontFamily: E.mono }}><window.Icon name="ShieldCheck" size={13} /> Guardrails</div>
      <div className="flex flex-wrap gap-1.5">
        {checks.map(([label, s]) => { const st = stat(s); const c = st === "pass" ? E.success : st === "run" ? E.guard : E.muted; return (
          <span key={label} className="inline-flex items-center gap-1 rounded-md px-2 py-1 text-[11px] font-medium" style={{ color: c, background: c + "14", border: `1px solid ${c}33` }}>
            {st === "pass" ? <window.Icon name="Check" size={11} /> : st === "run" ? <window.Icon name="Loader" size={11} className="animate-spin" /> : <window.Icon name="Minus" size={11} />} {label}
          </span>
        ); })}
      </div>
    </div>
  );
}
function ConversationHistory({ turns }) {
  const E = useE(); const [open, setOpen] = React.useState(false);
  const past = [
    { q: "Summarise tonight's open Finance-department alerts.", a: "3 open · 2 HIGH (Tor exit, priv-esc on workstation-043), 1 MEDIUM. workstation-043 is the common host." },
    { q: "What changed on workstation-043 in the last hour?", a: "New admin account svc_helpdesk2, outbound to a Tor exit node, and 2.3 MB egress." },
  ];
  const shown = past.slice(0, Math.max(1, turns - 1));
  return (
    <div className="rounded-xl" style={{ background: E.surface, border: `1px solid ${E.border}` }}>
      <button onClick={() => setOpen((v) => !v)} className="flex w-full items-center gap-2 px-3.5 py-2.5 text-left">
        <window.Icon name="History" size={14} style={{ color: E.app }} />
        <span className="flex-1 text-[12px] font-semibold uppercase tracking-[0.12em]" style={{ color: E.muted, fontFamily: E.mono }}>Conversation memory · {turns} turns</span>
        <window.Icon name={open ? "ChevronDown" : "ChevronRight"} size={14} style={{ color: E.muted }} />
      </button>
      {open && <div className="space-y-2.5 border-t px-3.5 py-3" style={{ borderColor: E.border }}>{shown.map((t, i) => (
        <div key={i} className="space-y-1">
          <div className="flex gap-2"><span className="shrink-0 text-[10px] font-bold uppercase" style={{ color: E.muted, fontFamily: E.mono }}>You</span><span className="text-[12px]" style={{ color: E.text }}>{t.q}</span></div>
          <div className="flex gap-2"><span className="shrink-0 text-[10px] font-bold uppercase" style={{ color: E.app, fontFamily: E.mono }}>App</span><span className="text-[12px]" style={{ color: E.muted }}>{t.a}</span></div>
        </div>
      ))}</div>}
    </div>
  );
}
function EvidenceRail({ state, alert, clearTelem }) {
  const E = useE();
  const docs = state.ragDocs.length ? state.ragDocs : null;
  return (
    <div className="space-y-4">
      <GuardrailChips stages={state.stages} />
      {/* retrieved knowledge / corpus preview */}
      <div className="rounded-xl" style={{ background: E.surface, border: `1px solid ${E.border}` }}>
        <div className="flex items-center justify-between border-b px-3.5 py-2.5" style={{ borderColor: E.border }}>
          <span className="inline-flex items-center gap-2 text-[11px] font-bold uppercase tracking-[0.14em]" style={{ color: E.rag, fontFamily: E.mono }}><window.Icon name="Database" size={13} /> {docs ? "Retrieved knowledge · " + docs.length : "Knowledge base"}</span>
          {!docs && <span className="text-[10px]" style={{ color: E.muted, fontFamily: E.mono }}>available</span>}
        </div>
        <div className="space-y-2 px-3 py-3">
          {docs ? docs.map((d, i) => <RagDocCard key={i} doc={d} />)
            : alert.rag.map((d, i) => (
              <div key={i} className="flex items-center gap-2.5 rounded-lg px-2.5 py-2" style={{ background: E.elevated, border: `1px solid ${E.border}` }}>
                <window.Icon name="FileText" size={13} style={{ color: E.muted }} />
                <span className="flex-1 truncate text-[12px]" style={{ color: E.text2 }}>{d.title}</span>
                <span className="text-[10px]" style={{ color: E.muted, fontFamily: E.mono }}>indexed</span>
              </div>
            ))}
        </div>
      </div>
      {state.ctx ? <ContextBar ctx={state.ctx} /> : (
        <div className="rounded-xl px-3.5 py-3 text-[11.5px]" style={{ background: E.surface, border: `1px solid ${E.border}`, color: E.muted }}>
          <window.Icon name="Layers" size={13} style={{ color: E.app, display: "inline", verticalAlign: "-2px" }} /> Context window assembles at run time — system + history + RAG + alert.
        </div>
      )}
      <div style={{ height: 300 }}><window.TelemetryPanel events={state.events} onClear={clearTelem} /></div>
    </div>
  );
}

function AppScreen({ alert, onBack, onPickAlert, mode, onToggleTheme, onGo, active }) {
  const E = useE(); const L = window.LAYERS.app; const lc = E.app;
  const [turns, setTurns] = React.useState(1);
  const [priorCost, setPriorCost] = React.useState(0.0072);
  const { state, running, run, reset, clearTelem } = useEagleRun(window.runApp);
  const started = running || state.responseStarted || state.summary;
  const meters = fmtMeters(state.nav, priorCost);
  const doRun = React.useCallback(() => { setPriorCost((c) => c + state.nav.cost); run(alert); }, [alert, state.nav.cost]);
  useRunHotkey(doRun, running, active);
  const wasDone = React.useRef(false);
  React.useEffect(() => { reset(); wasDone.current = false; }, [alert.id]);
  React.useEffect(() => {
    if (state.responseDone && state.summary && !wasDone.current) { wasDone.current = true; setTurns((t) => t + 1); }
    if (!state.responseDone) wasDone.current = false;
  }, [state.responseDone, state.summary]);

  return (
    <div className="flex h-full flex-col" style={{ background: E.bg }}>
      <EagleNav layer={L} meters={meters} running={running} onBack={onBack} mode={mode} onToggleTheme={onToggleTheme} current="app" onGo={onGo}
        center={<span className="ml-1 inline-flex shrink-0 items-center gap-2 whitespace-nowrap rounded-lg px-2.5 py-1.5 text-[11px] font-bold uppercase tracking-[0.12em]" style={{ color: lc, background: lc + "14", border: `1px solid ${lc}33`, fontFamily: E.mono }}><window.Icon name="Database" size={13} /> Session · {turns} turns</span>} />

      <div className="lr-scroll flex-1 overflow-y-auto px-6 py-4 lg:px-8">
        <div className="w-full space-y-4">
          <RunBar layer={L} alert={alert} running={running} started={started} onRun={doRun} onReset={reset} onPickAlert={onPickAlert} runLabel="Run pipeline" />
          <PipelineStrip stages={state.stages} />
          <div className="grid items-start gap-4 lg:grid-cols-5">
            {/* left: history + response */}
            <div className="space-y-4 lg:col-span-3">
              <ConversationHistory turns={turns} />
              <ResponseBlock state={state} layerKey="app" emptyHint="The same model — now wrapped with guardrails, RAG retrieval, conversation memory and context assembly. Run the pipeline to watch each stage light up and the evidence fill the rail." />
              {state.summary && <RunSummary s={state.summary} layerKey="app" />}
            </div>
            {/* right: evidence rail */}
            <div className="lg:col-span-2">
              <EvidenceRail state={state} alert={alert} clearTelem={clearTelem} />
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { useEagleRun, fmtMeters, useRunHotkey, ResponseBlock, RunSummary, ModelScreen, AppScreen });
