/* ============================================================================
   DIVONCI WORLD — SCREENS: SKILL TREE · ACTIVITY LOG · NEXUS
   ========================================================================== */

/* ----------------------------------------------------------- SKILL TREE - */
function skillTreeGen(a) {
  if (DW.SKILLS[a.id]) return DW.SKILLS[a.id];
  const ok = a.tools.filter(t => t.ok), locked = a.tools.filter(t => !t.ok);
  return { tiers: [
    [{ n: a.domain + " Core", s: "lit" }],
    (ok.length ? ok : [{ n: "Operate" }]).slice(0, 3).map((t, i) => ({ n: t.n, s: i < 2 ? "lit" : "avail" })),
    [{ n: "Autonomy L3", s: "locked", why: "Diego grant" }].concat(locked.map(t => ({ n: t.n, s: "locked", why: t.why || "doctrine" }))).slice(0, 3),
  ] };
}
function SkillTree({ agentId, nav }) {
  const a = DW.agent(agentId);
  const tree = skillTreeGen(a);
  const [sel, setSel] = useState(null);
  const tiers = tree.tiers;
  return (
    <div className="screen">
      <div className="screen-head">
        <div className="title"><span className="sub">{a.name} · Capabilities</span>Skill Tree</div>
        <div className="screen-actions">
          <button className="btn ghost" onClick={() => nav(a.id)}>← Profile</button>
          <div className="seg">
            {DW.AGENTS.map(ag => <button key={ag.id} className={agentId === ag.id ? "on" : ""} onClick={() => nav("skill:" + ag.id)}>{ag.name}</button>)}
          </div>
        </div>
      </div>

      <Panel style={{ "--ac": a.ac }}>
        <PHead icon="skill" eyebrow="Capability circuit" title={`${a.name} — left to right unlock path`} right={
          <div style={{ display: "flex", gap: 12 }}>
            <span style={{ fontFamily: "var(--font-mono)", fontSize: 9.5, color: "var(--ink-3)", display: "inline-flex", gap: 5, alignItems: "center" }}><span style={{ width: 8, height: 8, borderRadius: 99, background: a.ac, boxShadow: `0 0 8px ${a.ac}` }} />lit</span>
            <span style={{ fontFamily: "var(--font-mono)", fontSize: 9.5, color: "var(--ink-3)", display: "inline-flex", gap: 5, alignItems: "center" }}><span style={{ width: 8, height: 8, borderRadius: 99, background: "var(--ink-3)" }} />available</span>
            <span style={{ fontFamily: "var(--font-mono)", fontSize: 9.5, color: "var(--ink-4)", display: "inline-flex", gap: 5, alignItems: "center" }}><Icon name="lock" style={{ width: 11, height: 11 }} />locked</span>
          </div>} />
        <div className="pbody" style={{ position: "relative" }}>
          <svg width="100%" height="280" viewBox="0 0 1000 280" preserveAspectRatio="none" style={{ position: "absolute", inset: "var(--s-6)", width: "calc(100% - 48px)", height: 280, pointerEvents: "none" }}>
            <g fill="none" stroke="var(--violet)" strokeWidth="1.5" opacity="0.45" strokeDasharray="4 6" style={{ animation: "dash 20s linear infinite" }}>
              <path d="M120,140 C250,140 250,60 380,60" />
              <path d="M120,140 C250,140 250,140 380,140" />
              <path d="M120,140 C250,140 250,220 380,220" />
              <path d="M500,60 C620,60 620,110 720,110" />
              <path d="M500,140 C620,140 620,130 720,130" />
              <path d="M500,220 C620,220 620,150 720,150" />
              <path d="M840,130 L920,130" strokeDasharray="0" opacity="0.25" />
            </g>
          </svg>
          <div style={{ position: "relative", zIndex: 2, display: "grid", gridTemplateColumns: `repeat(${tiers.length}, 1fr)`, gap: "var(--s-6)", minHeight: 280, alignItems: "center" }}>
            {tiers.map((tier, ti) => (
              <div key={ti} style={{ display: "flex", flexDirection: "column", gap: 14, alignItems: "center", justifyContent: "center" }}>
                <div style={{ fontFamily: "var(--font-mono)", fontSize: 9, color: "var(--ink-4)", letterSpacing: "0.1em", textTransform: "uppercase" }}>Tier {ti + 1}</div>
                {tier.map((node, ni) => {
                  const lit = node.s === "lit", locked = node.s === "locked";
                  return (
                    <button key={ni} className="focusable" onClick={() => setSel({ ...node, tier: ti + 1 })}
                      style={{
                        display: "inline-flex", alignItems: "center", gap: 8, padding: "10px 14px", borderRadius: 99, fontSize: 12.5, cursor: "pointer",
                        border: `1px solid ${lit ? `color-mix(in srgb, ${a.ac} 55%, transparent)` : "var(--hairline-2)"}`,
                        background: sel && sel.n === node.n ? "var(--panel-3)" : "var(--panel-2)",
                        color: locked ? "var(--ink-4)" : "var(--ink)",
                        boxShadow: lit ? `0 0 16px color-mix(in srgb, ${a.ac} 30%, transparent)` : "none",
                      }}>
                      {locked ? <Icon name="lock" style={{ width: 12, height: 12 }} />
                        : <span style={{ width: 8, height: 8, borderRadius: 99, background: lit ? a.ac : "var(--ink-3)", boxShadow: lit ? `0 0 8px ${a.ac}` : "none" }} />}
                      {node.n}
                    </button>
                  );
                })}
              </div>
            ))}
          </div>
        </div>
      </Panel>

      <div className="cols c-2" style={{ marginTop: "var(--s-6)" }}>
        <Panel>
          <PHead icon="skill" eyebrow="Node detail" />
          <div className="pbody">
            {sel ? (
              <div>
                <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
                  {sel.s === "locked" ? <Icon name="lock" style={{ width: 18, height: 18, color: "var(--ink-4)" }} /> : <span style={{ width: 12, height: 12, borderRadius: 99, background: sel.s === "lit" ? a.ac : "var(--ink-3)", boxShadow: sel.s === "lit" ? `0 0 10px ${a.ac}` : "none" }} />}
                  <h3 style={{ margin: 0, fontFamily: "var(--font-display)", fontSize: 18 }}>{sel.n}</h3>
                </div>
                <div className="chips" style={{ marginTop: 12 }}>
                  <span className="sbadge" style={{ color: sel.s === "lit" ? "var(--violet-ink)" : sel.s === "locked" ? "var(--ink-4)" : "var(--ink-2)" }}>{sel.s === "lit" ? "Unlocked" : sel.s === "locked" ? "Locked" : "Available"}</span>
                  <span className="evchip">Tier {sel.tier}</span>
                </div>
                {sel.why && <div style={{ marginTop: 14 }}><span className="todochip">requires · {sel.why}</span></div>}
                <p className="body" style={{ marginTop: 14, fontSize: 13 }}>{sel.s === "lit" ? "This capability is active and contributes to the agent's live telemetry." : sel.s === "locked" ? "Locked capability. Unlock requires the listed grant — escalate to Diego." : "Reachable next. No glow until unlocked."}</p>
              </div>
            ) : <div className="emptystate"><div className="ring"><Icon name="skill" style={{ width: 20, height: 20 }} /></div><div className="note">Select a node to inspect its capability</div></div>}
          </div>
        </Panel>
        <Panel>
          <PHead icon="shield" eyebrow="Unlock policy" />
          <div className="pbody">
            <p className="body" style={{ fontSize: 13 }}>Capabilities unlock left-to-right. A node only lights once every predecessor is lit. Tier-3 autonomy and self-approval are <b style={{ color: "var(--ink)" }}>locked by doctrine</b> — they require an explicit grant from Diego.</p>
            <div className="kv" style={{ marginTop: 14 }}>
              <dt>Lit</dt><dd>unlocked · glows · counts toward telemetry</dd>
              <dt>Available</dt><dd>reachable next · no glow</dd>
              <dt>Locked</dt><dd>needs Diego grant or upstream node</dd>
            </div>
            <div style={{ marginTop: 14 }}><span className="todochip">grant flow · TODO</span></div>
          </div>
        </Panel>
      </div>
    </div>
  );
}

/* --------------------------------------------------------- ACTIVITY LOG - */
const LOG_STATES = ["all", "active", "crisis", "caution", "clear", "focus", "standby"];
function ActivityLog({ nav }) {
  const [agentFilter, setAgentFilter] = useState("all");
  const [stateFilter, setStateFilter] = useState("all");
  const rows = DW.LOG.filter(e =>
    (agentFilter === "all" || e.agent === agentFilter) &&
    (stateFilter === "all" || e.state === stateFilter));
  return (
    <div className="screen">
      <div className="screen-head">
        <div className="title"><span className="sub">Auditable · time-ordered</span>Activity Log</div>
        <div className="meta">The cockpit heartbeat. Newest first. Each LED uses the semantic state system so the column scans as a vertical state-ribbon.</div>
      </div>

      <Panel className="tight">
        <div className="phead" style={{ flexWrap: "wrap", gap: 12 }}>
          <div className="eyebrow"><Icon name="filter" style={{ width: 13, height: 13 }} />Filters</div>
          <div className="right" style={{ flexWrap: "wrap", gap: 10 }}>
            <div className="seg">
              <button className={agentFilter === "all" ? "on" : ""} onClick={() => setAgentFilter("all")}>All agents</button>
              {DW.AGENTS.map(a => <button key={a.id} className={agentFilter === a.name ? "on" : ""} onClick={() => setAgentFilter(a.name)}>{a.name}</button>)}
            </div>
            <div className="seg">
              {LOG_STATES.map(s => <button key={s} className={stateFilter === s ? "on" : ""} onClick={() => setStateFilter(s)} style={{ display: "inline-flex", alignItems: "center", gap: 5 }}>{s !== "all" && <Led state={s} size={6} />}{s}</button>)}
            </div>
          </div>
        </div>
        <div className="log">
          <div style={{ display: "grid", gridTemplateColumns: "92px 12px 1fr 130px 110px", gap: "var(--s-5)", padding: "10px 16px", borderBottom: "1px solid var(--hairline-2)", fontFamily: "var(--font-mono)", fontSize: 9, letterSpacing: "0.12em", textTransform: "uppercase", color: "var(--ink-4)" }}>
            <span>Time</span><span></span><span>Event</span><span>Agent · domain</span><span>State</span>
          </div>
          {rows.map((e, i) => (
            <div key={i} style={{ display: "grid", gridTemplateColumns: "92px 12px 1fr 130px 110px", gap: "var(--s-5)", alignItems: "center", padding: "11px 16px", borderBottom: "1px solid var(--hairline)" }} className="rowlink">
              <span style={{ fontFamily: "var(--font-mono)", fontSize: 11, color: "var(--ink-3)" }}>{e.t}</span>
              <Led state={e.state} />
              <span style={{ fontSize: 13, color: "var(--ink-2)" }}><b style={{ color: "var(--ink)", fontWeight: 600 }}>{e.agent}</b> {e.msg}</span>
              <span style={{ fontFamily: "var(--font-mono)", fontSize: 10, color: "var(--ink-3)", textTransform: "uppercase", letterSpacing: "0.06em" }}>{e.domain}</span>
              <span><span className="sbadge" style={{ color: DW.STATE_META[e.state].c }}>{e.kind}</span></span>
            </div>
          ))}
          {rows.length === 0 && <div className="emptystate"><div className="ring"><Icon name="log" style={{ width: 20, height: 20 }} /></div><div className="note">No events match these filters</div></div>}
        </div>
      </Panel>

      <div className="cols c-4" style={{ marginTop: "var(--s-6)" }}>
        {[["Running", "active"], ["Blocked", "caution"], ["Escalated", "crisis"], ["Completed", "clear"]].map(([k, s]) => (
          <Panel key={k}><div className="mtile"><div className="k"><Led state={s} size={7} />{k}</div><div className="v" style={{ color: DW.STATE_META[s].c }}>{DW.LOG.filter(e => e.kind === k).length}</div><div className="d">last 24 events</div></div></Panel>
        ))}
      </div>
    </div>
  );
}

/* --------------------------------------------------------- COUNCIL COMMS - */
const COMMS_REPLIES = {
  viiera:  "Acknowledged. I will weigh it and command accordingly.",
  vv:      "On it. I'll stage the work and hold for your clearance.",
  claws:   "Understood. I'll shape the message and route it right.",
  brodex:  "Copy. Running the checks before anyone moves.",
  nova:    "Ooh — I have three ideas already. Want the wild one?",
  optimus: "Logged. I'll find the faster path and report the time saved.",
};
function CommsAvatar({ id, size = 34 }) {
  if (id === "diego") return (
    <div style={{ width: size, height: size, borderRadius: size * 0.28, flex: "none", display: "grid", placeItems: "center", fontFamily: "var(--font-display)", fontWeight: 700, fontSize: size * 0.42, color: "var(--ink-on-gold)", background: "linear-gradient(150deg, var(--gold-bright), var(--gold))", boxShadow: "0 0 12px color-mix(in srgb, var(--gold-bright) 40%, transparent)" }}>D</div>
  );
  const a = DW.agent(id);
  return <img src={a.head} alt={a.name} style={{ width: size, height: size, borderRadius: size * 0.28, objectFit: "cover", flex: "none", border: `1px solid color-mix(in srgb, ${a.ac} 55%, transparent)` }} />;
}
function commsName(id) { return id === "diego" ? "Diego" : DW.agent(id).name; }
function commsColor(id) { return id === "diego" ? "var(--gold-bright)" : DW.agent(id).ac; }

function CommsScreen({ nav }) {
  const [msgs, setMsgs] = useState(() => DW.CHAT.slice().reverse());
  const [target, setTarget] = useState("all");
  const [draft, setDraft] = useState("");
  const feedRef = useRef(null);
  const last = msgs[msgs.length - 1];

  useEffect(() => { if (feedRef.current) feedRef.current.scrollTop = feedRef.current.scrollHeight; }, [msgs.length]);

  function send() {
    const text = draft.trim();
    if (!text) return;
    const t = new Date();
    const stamp = `${String(t.getHours()).padStart(2,"0")}:${String(t.getMinutes()).padStart(2,"0")}:${String(t.getSeconds()).padStart(2,"0")}`;
    setMsgs(m => [...m, { t: stamp, from: "diego", to: target, state: "active", msg: text }]);
    setDraft("");
    const responder = target === "all" ? "viiera" : target;
    setTimeout(() => {
      const t2 = new Date();
      const stamp2 = `${String(t2.getHours()).padStart(2,"0")}:${String(t2.getMinutes()).padStart(2,"0")}:${String(t2.getSeconds()).padStart(2,"0")}`;
      setMsgs(m => [...m, { t: stamp2, from: responder, to: "diego", state: DW.agent(responder).state, msg: COMMS_REPLIES[responder] || "Received." }]);
    }, 950);
  }

  return (
    <div className="screen comms-screen">
      <div className="screen-head">
        <div className="title"><span className="sub">Council channel</span>Council Comms</div>
        <div className="meta">The live channel between every member of the Council — and where you speak to them directly. Formal approvals still live in the War Room; this is the conversation around them.</div>
      </div>

      <div className="cols c-8-4">
        {/* chat column */}
        <Panel className="tight" style={{ display: "flex", flexDirection: "column", height: "100%", minHeight: 0, overflow: "hidden" }}>
          <PHead icon="comms" eyebrow="Council channel" title="All members · live" right={<span style={{ display: "inline-flex", alignItems: "center", gap: 6, fontFamily: "var(--font-mono)", fontSize: 10, color: "var(--ink-3)" }}><Led state="active" size={7} />{DW.AGENTS.length} online</span>} />
          {/* feed */}
          <div ref={feedRef} className="comms-scroll" style={{ flex: 1, overflowY: "auto", padding: "16px 18px", display: "flex", flexDirection: "column", gap: 14 }}>
            {msgs.map((m, i) => {
              const mine = m.from === "diego";
              return (
                <div key={i} style={{ display: "flex", gap: 10, flexDirection: mine ? "row-reverse" : "row", alignItems: "flex-start" }}>
                  <CommsAvatar id={m.from} size={34} />
                  <div style={{ maxWidth: "76%", display: "flex", flexDirection: "column", alignItems: mine ? "flex-end" : "flex-start" }}>
                    <div style={{ display: "flex", alignItems: "baseline", gap: 8, flexDirection: mine ? "row-reverse" : "row", marginBottom: 4 }}>
                      <b style={{ fontSize: 12.5, color: commsColor(m.from), fontFamily: "var(--font-display)" }}>{commsName(m.from)}</b>
                      <span style={{ fontFamily: "var(--font-mono)", fontSize: 9, color: "var(--ink-4)", letterSpacing: "0.06em" }}>{m.to === "all" ? "→ all" : "→ " + commsName(m.to)} · {m.t}</span>
                    </div>
                    <div style={{ fontSize: 13, lineHeight: 1.5, color: "var(--ink)", padding: "9px 13px", borderRadius: 12, borderTopLeftRadius: mine ? 12 : 3, borderTopRightRadius: mine ? 3 : 12, background: mine ? "color-mix(in srgb, var(--gold-bright) 13%, var(--panel-2))" : "var(--panel-2)", border: `1px solid ${mine ? "color-mix(in srgb, var(--gold-bright) 28%, transparent)" : "var(--hairline)"}`, borderLeft: mine ? undefined : `2px solid ${commsColor(m.from)}` }}>{m.msg}</div>
                  </div>
                </div>
              );
            })}
          </div>
          {/* composer */}
          <div style={{ borderTop: "1px solid var(--hairline)", padding: "12px 14px", background: "var(--panel)" }}>
            <div style={{ display: "flex", gap: 6, flexWrap: "wrap", marginBottom: 10 }}>
              <button onClick={() => setTarget("all")} className="focusable" style={{ cursor: "pointer", fontFamily: "var(--font-mono)", fontSize: 10, letterSpacing: "0.04em", padding: "5px 10px", borderRadius: 99, border: `1px solid ${target === "all" ? "var(--violet-bright)" : "var(--hairline-2)"}`, background: target === "all" ? "var(--active-dim)" : "var(--panel-2)", color: target === "all" ? "var(--ink)" : "var(--ink-3)", display: "inline-flex", alignItems: "center", gap: 6 }}>All council</button>
              {DW.AGENTS.map(a => (
                <button key={a.id} onClick={() => setTarget(a.id)} className="focusable" style={{ cursor: "pointer", fontFamily: "var(--font-mono)", fontSize: 10, letterSpacing: "0.04em", padding: "5px 10px 5px 6px", borderRadius: 99, border: `1px solid ${target === a.id ? `color-mix(in srgb, ${a.ac} 70%, transparent)` : "var(--hairline-2)"}`, background: target === a.id ? `color-mix(in srgb, ${a.ac} 16%, var(--panel-2))` : "var(--panel-2)", color: target === a.id ? "var(--ink)" : "var(--ink-3)", display: "inline-flex", alignItems: "center", gap: 6 }}>
                  <img src={a.head} alt="" style={{ width: 16, height: 16, borderRadius: 5, objectFit: "cover" }} />{a.name}
                </button>
              ))}
            </div>
            <div style={{ display: "flex", gap: 9, alignItems: "center" }}>
              <input value={draft} onChange={e => setDraft(e.target.value)} onKeyDown={e => { if (e.key === "Enter") send(); }}
                placeholder={`Message ${target === "all" ? "the Council" : commsName(target)}… (task, question, directive)`}
                style={{ flex: 1, fontFamily: "var(--font-ui)", fontSize: 13, color: "var(--ink)", background: "var(--panel-2)", border: "1px solid var(--hairline-2)", borderRadius: 9, padding: "11px 14px", outline: "none" }} />
              <button className="btn primary" onClick={send} style={{ padding: "10px 18px" }}>Send</button>
            </div>
          </div>
        </Panel>

        {/* sidebar — own scroll region, page itself never moves */}
        <div className="comms-scroll" style={{ display: "flex", flexDirection: "column", gap: "var(--s-6)", height: "100%", minHeight: 0, overflowY: "auto", paddingRight: 4 }}>
          <Panel glow>
            <PHead icon="bolt" eyebrow="Who's talking" right={<Led state={last.state} size={7} />} />
            <div className="pbody" style={{ display: "flex", flexDirection: "column", alignItems: "center", textAlign: "center" }}>
              <div style={{ position: "relative" }}>
                <CommsAvatar id={last.from} size={86} />
                <span className="pulse" style={{ position: "absolute", inset: -5, borderRadius: 28, border: `1.5px solid ${commsColor(last.from)}`, boxShadow: `0 0 22px color-mix(in srgb, ${commsColor(last.from)} 45%, transparent)` }} />
              </div>
              <div style={{ fontFamily: "var(--font-display)", fontSize: 18, fontWeight: 600, marginTop: 14, color: commsColor(last.from) }}>{commsName(last.from)}</div>
              <div style={{ fontFamily: "var(--font-mono)", fontSize: 9.5, color: "var(--ink-4)", textTransform: "uppercase", letterSpacing: "0.1em", marginTop: 3 }}>speaking now · {last.t}</div>
              <p style={{ fontSize: 12.5, color: "var(--ink-2)", marginTop: 12, lineHeight: 1.5 }}>{last.msg}</p>
            </div>
          </Panel>
          <Panel>
            <PHead icon="comms" eyebrow="Pressure · 10-cycle" right={<StateChip state="caution" label="Rising" />} />
            <div className="pbody">
              <div style={{ display: "flex", alignItems: "baseline", gap: 8, marginBottom: 12 }}><span style={{ fontFamily: "var(--font-mono)", fontSize: 30, fontWeight: 600, color: "var(--state-caution)" }}>62</span><span style={{ fontSize: 12, color: "var(--ink-3)" }}>% capacity · south relay degraded</span></div>
              <MicroBars data={[4,5,5,6,7,6,8,7,9,8]} peak={8} h={64} />
            </div>
          </Panel>
          <Panel>
            <PHead icon="comms" eyebrow="Model routing" />
            <div className="pbody" style={{ display: "flex", flexDirection: "column", gap: 8 }}>
              {[["Eagle / Opus","focus","12 routes"],["Falcon / Sonnet","active","38 routes"],["Hawk / Haiku","clear","64 routes"]].map(([n,s,d],i)=>(
                <div key={i} style={{ display: "flex", justifyContent: "space-between", alignItems: "center", padding: "9px 11px", borderRadius: 8, background: "var(--panel-2)", border: "1px solid var(--hairline)" }}>
                  <b style={{ fontSize: 12.5 }}>{n}</b>
                  <span style={{ display: "inline-flex", alignItems: "center", gap: 7, fontFamily: "var(--font-mono)", fontSize: 10, color: "var(--ink-3)" }}>{d}<Led state={s} size={7} /></span>
                </div>
              ))}
            </div>
          </Panel>
        </div>
      </div>
    </div>
  );
}

/* ----------------------------------------------------- COUNCIL RELATIONS - */
/* Viiera at the centre; the other five orbit her. Edges = AGENT_LINKS.       */
const COUNCIL_RING = {
  viiera:  { x: 0.5,  y: 0.5 },
  nova:    { x: 0.5,  y: 0.13 },
  claws:   { x: 0.85, y: 0.40 },
  brodex:  { x: 0.72, y: 0.87 },
  vv:      { x: 0.28, y: 0.87 },
  optimus: { x: 0.15, y: 0.40 },
};
function CouncilNexus() {
  const wrapRef = useRef(null);
  const [size, setSize] = useState({ w: 800, h: 480 });
  const [hover, setHover] = useState(null);        // transient — drives the highlight/dim, cleared on mouse-out
  const [selected, setSelected] = useState("viiera"); // persists the inspector panel at rest
  const links = DW.AGENT_LINKS;
  useEffect(() => {
    const ro = new ResizeObserver(() => { const r = wrapRef.current.getBoundingClientRect(); setSize({ w: r.width, h: 480 }); });
    if (wrapRef.current) ro.observe(wrapRef.current);
    return () => ro.disconnect();
  }, []);
  const px = (id) => ({ x: COUNCIL_RING[id].x * size.w, y: COUNCIL_RING[id].y * size.h });
  const focus = hover;                              // who the graph is currently emphasising (null = neutral)
  const insp = hover || selected;                   // inspector follows the cursor, falls back to selection
  const linkedToFocus = (id) => links.some(l => (l.a === focus && l.b === id) || (l.b === focus && l.a === id));
  const hoverAgent = insp ? DW.agent(insp) : null;
  const hoverLinks = insp ? links.filter(l => l.a === insp || l.b === insp).map(l => ({ other: DW.agent(l.a === insp ? l.b : l.a), label: l.label })) : [];
  const hc = focus ? DW.agent(focus).ac : "var(--violet)";
  return (
    <div className="cols c-8-4" style={{ marginTop: "var(--s-6)" }}>
      <Panel className="tight" style={{ overflow: "hidden" }}>
        <PHead icon="council" eyebrow="Council relations" title="Viiera at the centre" right={<span style={{ fontFamily: "var(--font-mono)", fontSize: 10, color: "var(--ink-4)" }}>{DW.AGENTS.length} agents · {links.length} ties</span>} />
        <div ref={wrapRef} style={{ position: "relative", height: 480 }}>
          <svg width="100%" height="480" style={{ position: "absolute", inset: 0 }}>
            {links.map((l, i) => {
              const pa = px(l.a), pb = px(l.b), active = focus && (l.a === focus || l.b === focus);
              const dimLine = focus && !active;
              return <line key={i} x1={pa.x} y1={pa.y} x2={pb.x} y2={pb.y} stroke={active ? hc : "var(--violet)"} strokeWidth={active ? 2.2 : 1} opacity={active ? 0.85 : dimLine ? 0.05 : 0.26} strokeDasharray={active ? "0" : "3 6"} style={{ transition: "all .22s var(--ease-out)" }} />;
            })}
            {links.map((l, i) => {
              const pa = px(l.a), pb = px(l.b), active = focus && (l.a === focus || l.b === focus);
              return <circle key={"p" + i} r="2.4" fill={active ? hc : "transparent"} opacity={active ? 0.9 : 0}>
                <animate attributeName="cx" values={`${pa.x};${pb.x}`} dur="2.4s" repeatCount="indefinite" />
                <animate attributeName="cy" values={`${pa.y};${pb.y}`} dur="2.4s" repeatCount="indefinite" />
              </circle>;
            })}
          </svg>
          {DW.AGENTS.map(a => {
            const p = px(a.id), isC = a.id === "viiera", on = focus === a.id, sel = insp === a.id;
            const dim = focus && !on && !linkedToFocus(a.id);
            const sz = isC ? 72 : 54;
            return (
              <button key={a.id} className="focusable" onMouseEnter={() => setHover(a.id)} onMouseLeave={() => setHover(null)} onFocus={() => setHover(a.id)} onBlur={() => setHover(null)} onClick={() => setSelected(a.id)}
                style={{ position: "absolute", left: p.x, top: p.y, transform: "translate(-50%,-50%)", background: "none", border: "none", cursor: "pointer", display: "flex", flexDirection: "column", alignItems: "center", gap: 6, opacity: dim ? 0.22 : 1, transition: "opacity .22s var(--ease-out)", zIndex: on ? 5 : sel ? 4 : 3 }}>
                <div style={{ width: sz, height: sz, borderRadius: sz * 0.28, overflow: "hidden", flex: "none", border: `1.5px solid color-mix(in srgb, ${a.ac} ${on ? 90 : sel ? 65 : 50}%, var(--hairline-2))`, boxShadow: on ? `0 0 28px color-mix(in srgb, ${a.ac} 60%, transparent)` : sel ? `0 0 14px color-mix(in srgb, ${a.ac} 30%, transparent)` : "0 0 0 1px var(--hairline)", background: "var(--graphite)", transition: "all .22s var(--ease-out)" }}>
                  <img src={a.head} alt={a.name} style={{ width: "100%", height: "100%", objectFit: "cover", display: "block" }} />
                </div>
                <span style={{ fontFamily: "var(--font-mono)", fontSize: 10, color: (on || sel) ? "var(--ink)" : "var(--ink-2)", letterSpacing: "0.04em", whiteSpace: "nowrap" }}>{a.name}{isC ? " · centre" : ""}</span>
              </button>
            );
          })}
        </div>
      </Panel>
      <Panel>
        <PHead icon="council" eyebrow="Relationship inspector" />
        <div className="pbody">
          {hoverAgent && (<div>
            <div style={{ display: "flex", alignItems: "center", gap: 11 }}>
              <img src={hoverAgent.head} alt={hoverAgent.name} style={{ width: 40, height: 40, borderRadius: 12, objectFit: "cover", border: `1px solid color-mix(in srgb, ${hoverAgent.ac} 55%, transparent)` }} />
              <div><div style={{ fontFamily: "var(--font-display)", fontSize: 17 }}>{hoverAgent.name}</div><div style={{ fontFamily: "var(--font-mono)", fontSize: 10, color: "var(--ink-4)", textTransform: "uppercase", letterSpacing: "0.08em" }}>{hoverAgent.domain} · {hoverLinks.length} ties</div></div>
            </div>
            <div style={{ display: "flex", flexDirection: "column", gap: 7, marginTop: 16 }}>
              {hoverLinks.map((l, i) => (
                <div key={i} style={{ display: "flex", alignItems: "center", gap: 10, padding: "8px 10px", borderRadius: 8, background: "var(--panel-2)", border: "1px solid var(--hairline)" }}>
                  <img src={l.other.head} alt={l.other.name} style={{ width: 26, height: 26, borderRadius: 8, objectFit: "cover", flex: "none", border: `1px solid color-mix(in srgb, ${l.other.ac} 50%, transparent)` }} />
                  <div style={{ minWidth: 0 }}>
                    <div style={{ fontSize: 12.5, fontWeight: 600 }}>{l.other.name}</div>
                    <div style={{ fontFamily: "var(--font-mono)", fontSize: 10, color: "var(--ink-3)", marginTop: 1 }}>{l.label}</div>
                  </div>
                </div>
              ))}
            </div>
            <div className="note" style={{ marginTop: 14, color: "var(--ink-4)" }}>hover any portrait to trace its ties · click to pin</div>
          </div>)}
        </div>
      </Panel>
    </div>
  );
}

/* ---------------------------------------------------------------- NEXUS - */
function Nexus({ nav }) {
  const wrapRef = useRef(null);
  const [size, setSize] = useState({ w: 800, h: 460 });
  const [hover, setHover] = useState(null);
  const [sel, setSel] = useState(null);
  const [tab, setTab] = useState("knowledge");
  const { nodes, edges } = DW.NEXUS;

  useEffect(() => {
    const ro = new ResizeObserver(() => {
      const r = wrapRef.current.getBoundingClientRect();
      setSize({ w: r.width, h: 460 });
    });
    if (wrapRef.current) ro.observe(wrapRef.current);
    return () => ro.disconnect();
  }, []);

  const px = (n) => ({ x: n.x * size.w, y: n.y * size.h });
  const kindIcon = { root: "crown", doc: "evidence", module: "studio", group: "council", data: "nexus", risk: "risk", ops: "ops" };

  return (
    <div className="screen">
      <div className="screen-head">
        <div className="title"><span className="sub">{tab === "knowledge" ? "Knowledge graph" : "Council graph"}</span>Nexus</div>
        <div className="screen-actions">
          <div className="seg">
            <button className={tab === "knowledge" ? "on" : ""} onClick={() => setTab("knowledge")}><Icon name="nexus" style={{ width: 12, height: 12, marginRight: 6, verticalAlign: "-2px" }} />Knowledge</button>
            <button className={tab === "council" ? "on" : ""} onClick={() => setTab("council")}><Icon name="council" style={{ width: 12, height: 12, marginRight: 6, verticalAlign: "-2px" }} />Council relations</button>
          </div>
        </div>
      </div>
      <div className="meta" style={{ marginTop: "calc(-1 * var(--s-4))", marginBottom: "var(--s-6)", maxWidth: "70ch" }}>{tab === "knowledge" ? "How the empire's knowledge connects. Nodes are concepts, modules, evidence and risks; edges preserve relationship context. Hover to trace, click to inspect." : "The agent relation map. Viiera sits at the centre — every domain reads through her. Hover a portrait to trace its ties across the Council."}</div>

      {tab === "knowledge" && (
      <div className="cols c-8-4">
        <Panel className="tight" style={{ overflow: "hidden" }}>
          <PHead icon="nexus" eyebrow="Relationship graph" right={<span style={{ fontFamily: "var(--font-mono)", fontSize: 10, color: "var(--ink-4)" }}>{nodes.length} nodes · {edges.length} edges</span>} />
          <div ref={wrapRef} style={{ position: "relative", height: 460 }}>
            <svg width="100%" height="460" style={{ position: "absolute", inset: 0 }}>
              {edges.map(([a, b], i) => {
                const na = nodes.find(n => n.id === a), nb = nodes.find(n => n.id === b);
                const pa = px(na), pb = px(nb);
                const active = hover && (hover === a || hover === b);
                return <line key={i} x1={pa.x} y1={pa.y} x2={pb.x} y2={pb.y} stroke={active ? DW.STATE_META[nb.state].c : "var(--violet)"} strokeWidth={active ? 1.6 : 1} opacity={active ? 0.7 : 0.22} strokeDasharray={active ? "0" : "3 5"} style={{ transition: "all .2s" }} />;
              })}
              {edges.map(([a, b], i) => {
                const na = nodes.find(n => n.id === a), nb = nodes.find(n => n.id === b);
                const pa = px(na), pb = px(nb);
                return <circle key={"p" + i} r="2" fill={DW.STATE_META[nb.state].c} opacity={hover && (hover === a || hover === b) ? 0.9 : 0}>
                  <animate attributeName="cx" values={`${pa.x};${pb.x}`} dur="2.2s" repeatCount="indefinite" />
                  <animate attributeName="cy" values={`${pa.y};${pb.y}`} dur="2.2s" repeatCount="indefinite" />
                </circle>;
              })}
            </svg>
            {nodes.map(n => {
              const p = px(n), c = DW.STATE_META[n.state].c, isRoot = n.kind === "root";
              const dim = hover && hover !== n.id && !edges.some(([a, b]) => (a === hover && b === n.id) || (b === hover && a === n.id));
              return (
                <button key={n.id} className="focusable" onMouseEnter={() => setHover(n.id)} onMouseLeave={() => setHover(null)} onClick={() => setSel(n)}
                  style={{
                    position: "absolute", left: p.x, top: p.y, transform: "translate(-50%,-50%)", cursor: "pointer",
                    display: "flex", flexDirection: "column", alignItems: "center", gap: 6, background: "none", border: "none",
                    opacity: dim ? 0.35 : 1, transition: "opacity .2s", zIndex: hover === n.id ? 4 : 2,
                  }}>
                  <span style={{ width: isRoot ? 52 : 40, height: isRoot ? 52 : 40, borderRadius: isRoot ? 16 : 12, display: "grid", placeItems: "center", background: `radial-gradient(circle at 35% 30%, color-mix(in srgb, ${c} 40%, transparent), var(--panel-3))`, border: `1px solid color-mix(in srgb, ${c} 55%, transparent)`, boxShadow: hover === n.id ? `0 0 22px color-mix(in srgb, ${c} 50%, transparent)` : "none" }}>
                    <Icon name={kindIcon[n.kind] || "nexus"} style={{ width: isRoot ? 22 : 17, height: isRoot ? 22 : 17, color: c }} />
                  </span>
                  <span style={{ fontFamily: "var(--font-mono)", fontSize: 10, color: "var(--ink-2)", letterSpacing: "0.04em", whiteSpace: "nowrap" }}>{n.label}</span>
                </button>
              );
            })}
          </div>
        </Panel>

        <Panel>
          <PHead icon="nexus" eyebrow="Node inspector" />
          <div className="pbody">
            {sel ? (() => {
              const c = DW.STATE_META[sel.state].c;
              const linked = edges.filter(([a, b]) => a === sel.id || b === sel.id).map(([a, b]) => nodes.find(n => n.id === (a === sel.id ? b : a)));
              return <div>
                <div style={{ display: "flex", alignItems: "center", gap: 11 }}>
                  <span style={{ width: 38, height: 38, borderRadius: 11, display: "grid", placeItems: "center", background: `color-mix(in srgb, ${c} 18%, var(--panel-3))`, border: `1px solid color-mix(in srgb, ${c} 50%, transparent)` }}><Icon name={kindIcon[sel.kind]} style={{ width: 18, height: 18, color: c }} /></span>
                  <div><div style={{ fontFamily: "var(--font-display)", fontSize: 18 }}>{sel.label}</div><div style={{ fontFamily: "var(--font-mono)", fontSize: 10, color: "var(--ink-4)", textTransform: "uppercase", letterSpacing: "0.08em" }}>{sel.kind}</div></div>
                </div>
                <div style={{ marginTop: 12 }}><StateChip state={sel.state} /></div>
                <div className="eyebrow" style={{ marginTop: 18 }}>Linked nodes · {linked.length}</div>
                <div style={{ display: "flex", flexDirection: "column", gap: 7, marginTop: 10 }}>
                  {linked.map((l, i) => <button key={i} className="rowlink focusable" onClick={() => setSel(l)} style={{ display: "flex", alignItems: "center", gap: 9, padding: "8px 10px", borderRadius: 7, background: "var(--panel-2)", border: "1px solid var(--hairline)", cursor: "pointer", textAlign: "left" }}>
                    <Led state={l.state} size={7} /><span style={{ fontSize: 12.5, flex: 1 }}>{l.label}</span><Icon name="chevron" style={{ width: 13, height: 13, color: "var(--ink-4)" }} />
                  </button>)}
                </div>
                {sel.kind === "risk" && <div style={{ marginTop: 14 }}><button className="btn danger" onClick={() => nav("risk")}>Open in Risk Console →</button></div>}
              </div>;
            })() : <div className="emptystate"><div className="ring"><Icon name="nexus" style={{ width: 20, height: 20 }} /></div><div className="note">Select a node to trace its relationships</div></div>}
          </div>
        </Panel>
      </div>
      )}

      {tab === "council" && <CouncilNexus />}
    </div>
  );
}

Object.assign(window, { SkillTree, ActivityLog, Nexus, CouncilNexus, CommsScreen });
