Elnor Repo Reader

skills_connectors_mockup_v2.jsx

Design Mockups/DOC20 Mockups/skills_connectors_mockup_v2.jsx

Short text page 68eb083b7574. Generated 2026-06-09T01:23:58.539Z from commit dbaa25962edc11ab30e8d4ca1715f9ae5bf77331. Worktree: clean.

Open readable HTML page · Open raw txt · Open path URL

ELNOR REPO READER TEXT MIRROR
Original path: Design Mockups/DOC20 Mockups/skills_connectors_mockup_v2.jsx
Source repo: /Users/OpenClaw1/Elnor/Elnor Specs
Git branch: main
Git commit: dbaa25962edc11ab30e8d4ca1715f9ae5bf77331
Generated: 2026-06-09T01:23:58.539Z

---

import { useState } from "react";

const CAPS = [
  { id: "p1", name: "Create Caption Page for Brief", type: "learned_procedure", app: "Microsoft Word", status: "active", confidence: 0.82, lane: "approved_workspace", origin: "demonstration", uses: 47, lastUsed: "2h ago", desc: "Creates a formatted caption page with case name, court, and filing date for litigation briefs.", tags: ["litigation"], steps: [
    { intent: "Navigate to caption page location", nature: "mechanical", detail: "Position cursor at the beginning of the document before any existing content." },
    { intent: "Insert page break and section header", nature: "mechanical", detail: "Insert a page break, then add centered text with the court name in [Court Name] format." },
    { intent: "Add case caption block", nature: "cognitive", detail: "Format the caption with [Plaintiff] v. [Defendant], Case No. [Case Number], aligned per court rules." },
    { intent: "Add filing metadata", nature: "mechanical", detail: "Below caption, add filing date, document title, and attorney information block." },
  ], triggers: ["caption page", "brief cover", "create caption"] },
  { id: "p2", name: "Format Table of Authorities", type: "learned_procedure", app: "Microsoft Word", status: "active", confidence: 0.71, lane: "experimental_private", origin: "demonstration", uses: 12, lastUsed: "1d ago", desc: "Formats TOA entries with proper indentation, short citations, and page references per Bluebook style.", tags: ["citations"], steps: [], triggers: ["TOA", "table of authorities"] },
  { id: "p3", name: "Draft Opposition Brief Structure", type: "learned_procedure", app: "Microsoft Word", status: "experimental", confidence: 0.58, lane: "experimental_private", origin: "demonstration", uses: 3, lastUsed: "5d ago", desc: "Creates the skeleton structure for an opposition brief with standard sections.", tags: ["drafting"], steps: [], triggers: ["opposition brief"] },
  { id: "p4", name: "Extract Docket Entries", type: "learned_procedure", app: "Chrome", status: "stale", confidence: 0.64, lane: "approved_workspace", origin: "demonstration", uses: 28, lastUsed: "14d ago", desc: "Navigates court docket system and extracts relevant entries into a structured format.", tags: ["research"], steps: [], triggers: ["docket entries", "pull docket"] },
  { id: "s1", name: "image-lab", type: "native_skill", app: "global", status: "active", confidence: null, lane: null, origin: "clawhub_installed", uses: 8, lastUsed: "3d ago", desc: "Generate or edit images via Gemini provider-backed image workflow.", tags: ["media"], steps: [], triggers: [] },
  { id: "s2", name: "summarize", type: "native_skill", app: "global", status: "unavailable", confidence: null, lane: null, origin: "openclaw_bundled", uses: 0, lastUsed: null, desc: "Summarize documents, web pages, or conversation history. Requires: summarize CLI.", tags: ["productivity"], steps: [], triggers: [] },
  { id: "m1", name: "linear.search_issues", type: "mcp_tool", app: "Linear", status: "active", confidence: null, lane: null, origin: "mcp_discovered", uses: 34, lastUsed: "4h ago", desc: "Search Linear issues by query, status, assignee, or label.", tags: ["project mgmt"], steps: [], triggers: [] },
  { id: "m2", name: "gmail.send_email", type: "mcp_tool", app: "Gmail", status: "active", confidence: null, lane: null, origin: "mcp_discovered", uses: 19, lastUsed: "1d ago", desc: "Send email via connected Gmail account.", tags: ["email"], steps: [], triggers: [] },
  { id: "t1", name: "exec", type: "system_tool", app: "global", status: "active", confidence: null, lane: null, origin: "system_builtin", uses: 312, lastUsed: "12m ago", desc: "Run shell commands and manage background processes.", tags: ["runtime"], steps: [], triggers: [] },
  { id: "t2", name: "browser", type: "system_tool", app: "global", status: "active", confidence: null, lane: null, origin: "system_builtin", uses: 89, lastUsed: "1h ago", desc: "Control Chromium browser — navigate, click, screenshot, extract.", tags: ["web"], steps: [], triggers: [] },
  { id: "d1", name: "Always use Bluebook citation format", type: "memory_directive", app: "Microsoft Word", status: "active", confidence: null, lane: null, origin: "demonstration", uses: null, lastUsed: null, desc: "When formatting citations in any legal document, always use Bluebook 21st Edition style.", tags: ["preference"], steps: [], triggers: [] },
  { id: "sp1", name: "Auto-file incoming court notices", type: "standing_procedure", app: "Outlook", status: "active", confidence: null, lane: null, origin: "demonstration", uses: 15, lastUsed: "6h ago", desc: "When an email arrives from a court clerk, extract case number and file to the appropriate matter folder.", tags: ["automation"], steps: [], triggers: ["court notice"] },
];

const TY = {
  learned_procedure: { l: "Learned", c: "#185FA5", bg: "#E6F1FB" },
  native_skill: { l: "Skill", c: "#0F6E56", bg: "#E1F5EE" },
  mcp_tool: { l: "MCP", c: "#534AB7", bg: "#EEEDFE" },
  system_tool: { l: "System", c: "#5F5E5A", bg: "#F1EFE8" },
  plugin_tool: { l: "Plugin", c: "#993C1D", bg: "#FAECE7" },
  standing_procedure: { l: "Standing", c: "#854F0B", bg: "#FAEEDA" },
  memory_directive: { l: "Memory", c: "#993556", bg: "#FBEAF0" },
};

const ST = {
  active: { d: "#1D9E75", l: "Active" }, degraded: { d: "#BA7517", l: "Degraded" },
  stale: { d: "#BA7517", l: "Stale" }, disabled: { d: "#888780", l: "Disabled" },
  experimental: { d: "#378ADD", l: "Experimental" }, unavailable: { d: "#E24B4A", l: "Unavailable" },
};

const TABS = ["My capabilities", "Connectors & accounts", "OpenClaw tools", "Expose Elnor", "Learn & teach", "Hub"];

const CONF_EVENTS = [
  { d: "Apr 1", e: "Demonstrated", delta: "+0.95 α", up: true },
  { d: "Apr 2", e: "Used successfully", delta: "+0.75 α", up: true },
  { d: "Apr 3", e: "Used successfully", delta: "+0.75 α", up: true },
  { d: "Apr 4", e: "Used successfully", delta: "+0.75 α", up: true },
  { d: "Apr 5", e: "Correction after failure", delta: "+1.0 β", up: false },
  { d: "Apr 6", e: "Fix validated", delta: "+0.25 α", up: true },
  { d: "Apr 7", e: "Used successfully", delta: "+0.75 α", up: true },
  { d: "Apr 8", e: "Used successfully", delta: "+0.75 α", up: true },
];

const USAGE = [
  { t: "2 hours ago", o: "success", ctx: "Paramount v. LA brief prep" },
  { t: "Yesterday", o: "success", ctx: "Brooge Energy filing" },
  { t: "2 days ago", o: "success", ctx: "Caption page for motion" },
  { t: "3 days ago", o: "failure", ctx: "Template mismatch — wrong court" },
  { t: "4 days ago", o: "success", ctx: "Opposition brief caption" },
  { t: "5 days ago", o: "success", ctx: "Reply brief caption" },
];

function Badge({ type }) {
  const t = TY[type];
  return <span style={{ fontSize: 10, fontWeight: 500, fontFamily: "var(--font-mono)", padding: "2px 6px", borderRadius: 4, background: t.bg, color: t.c, textTransform: "uppercase", letterSpacing: "0.02em" }}>{t.l}</span>;
}

function Dot({ status }) {
  const s = ST[status] || ST.active;
  return <span style={{ display: "inline-flex", alignItems: "center", gap: 4 }}><span style={{ width: 6, height: 6, borderRadius: "50%", background: s.d, display: "inline-block" }} /><span style={{ fontSize: 11, color: "var(--color-text-secondary)" }}>{s.l}</span></span>;
}

function CBar({ v }) {
  const p = Math.round(v * 100);
  const c = v >= 0.7 ? "#1D9E75" : v >= 0.5 ? "#BA7517" : "#E24B4A";
  return <div style={{ display: "flex", alignItems: "center", gap: 6 }}>
    <div style={{ flex: 1, height: 3, background: "var(--color-border-tertiary)", borderRadius: 2, overflow: "hidden" }}>
      <div style={{ width: `${p}%`, height: "100%", background: c, borderRadius: 2 }} />
    </div>
    <span style={{ fontSize: 11, fontFamily: "var(--font-mono)", color: "var(--color-text-secondary)", minWidth: 28 }}>{p}%</span>
  </div>;
}

function Card({ cap, onClick, selected }) {
  return <div onClick={onClick} style={{
    background: selected ? "var(--color-background-secondary)" : "var(--color-background-primary)",
    border: selected ? "1.5px solid var(--color-border-primary)" : "0.5px solid var(--color-border-tertiary)",
    borderRadius: "var(--border-radius-lg)", padding: "14px 16px", cursor: "pointer",
    display: "flex", flexDirection: "column", gap: 8, transition: "border-color 0.12s",
  }}>
    <div style={{ display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap" }}>
      <span style={{ fontSize: 13, fontWeight: 500, color: "var(--color-text-primary)", flex: "1 1 auto", minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{cap.name}</span>
    </div>
    <div style={{ display: "flex", alignItems: "center", gap: 6, flexWrap: "wrap" }}>
      <Badge type={cap.type} />
      <Dot status={cap.status} />
      {cap.app !== "global" && <span style={{ fontSize: 11, color: "var(--color-text-tertiary)" }}>{cap.app}</span>}
    </div>
    <p style={{ fontSize: 12, color: "var(--color-text-secondary)", margin: 0, lineHeight: 1.4, display: "-webkit-box", WebkitLineClamp: 2, WebkitBoxOrient: "vertical", overflow: "hidden" }}>{cap.desc}</p>
    <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginTop: "auto" }}>
      <span style={{ fontSize: 11, color: "var(--color-text-tertiary)", fontFamily: "var(--font-mono)" }}>
        {cap.uses !== null ? `${cap.uses} uses` : "—"}{cap.lastUsed ? ` · ${cap.lastUsed}` : ""}
      </span>
      {cap.confidence !== null && <div style={{ width: 80 }}><CBar v={cap.confidence} /></div>}
    </div>
    {cap.lane === "experimental_private" && (
      <span style={{ fontSize: 10, color: "#854F0B", background: "#FAEEDA", padding: "2px 6px", borderRadius: 3, alignSelf: "flex-start", fontFamily: "var(--font-mono)" }}>experimental</span>
    )}
  </div>;
}

function Drawer({ cap, onClose }) {
  const [sec, setSec] = useState("contract");
  const isProc = cap.type === "learned_procedure";
  const isEditable = ["learned_procedure", "standing_procedure", "memory_directive"].includes(cap.type);
  const tabs = isProc ? ["contract", "confidence", "usage", "provenance", "linked"] :
    cap.type === "memory_directive" ? ["contract", "provenance"] :
    cap.type === "native_skill" ? ["content", "usage", "provenance"] :
    ["details", "usage"];

  return <div style={{ background: "var(--color-background-primary)", border: "0.5px solid var(--color-border-tertiary)", borderRadius: "var(--border-radius-lg)", marginTop: 16, overflow: "hidden" }}>
    {/* Header */}
    <div style={{ padding: "16px 20px", borderBottom: "0.5px solid var(--color-border-tertiary)" }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", marginBottom: 6 }}>
        <h3 style={{ margin: 0, fontSize: 16, fontWeight: 500, color: "var(--color-text-primary)" }}>{cap.name}</h3>
        <button onClick={onClose} style={{ background: "none", border: "none", cursor: "pointer", color: "var(--color-text-secondary)", padding: "2px 6px", fontSize: 16 }}>×</button>
      </div>
      <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 8 }}>
        <Badge type={cap.type} />
        <Dot status={cap.status} />
        {cap.app !== "global" && <span style={{ fontSize: 12, color: "var(--color-text-tertiary)" }}>{cap.app}</span>}
        {cap.lane && <span style={{ fontSize: 10, fontFamily: "var(--font-mono)", color: "var(--color-text-tertiary)", background: "var(--color-background-secondary)", padding: "2px 6px", borderRadius: 3 }}>{cap.lane.replace("_", " ")}</span>}
      </div>
      <p style={{ fontSize: 13, color: "var(--color-text-secondary)", margin: 0, lineHeight: 1.5 }}>{cap.desc}</p>
    </div>

    {/* Section tabs */}
    <div style={{ display: "flex", borderBottom: "0.5px solid var(--color-border-tertiary)", padding: "0 20px", overflowX: "auto" }}>
      {tabs.map(t => <button key={t} onClick={() => setSec(t)} style={{
        background: "none", border: "none", borderBottom: sec === t ? "2px solid var(--color-text-primary)" : "2px solid transparent",
        padding: "10px 12px", fontSize: 12, fontWeight: sec === t ? 500 : 400,
        color: sec === t ? "var(--color-text-primary)" : "var(--color-text-secondary)",
        cursor: "pointer", textTransform: "capitalize", whiteSpace: "nowrap",
      }}>{t}</button>)}
    </div>

    {/* Content */}
    <div style={{ padding: "16px 20px" }}>
      {sec === "contract" && isProc && <>
        <div style={{ marginBottom: 16 }}>
          <div style={{ fontSize: 11, fontWeight: 500, color: "var(--color-text-secondary)", marginBottom: 6, textTransform: "uppercase", letterSpacing: "0.05em" }}>Trigger phrases</div>
          <div style={{ display: "flex", gap: 4, flexWrap: "wrap" }}>
            {(cap.triggers || []).map((t, i) => <span key={i} style={{ fontSize: 12, padding: "3px 8px", background: "var(--color-background-secondary)", borderRadius: 4, fontFamily: "var(--font-mono)" }}>"{t}"</span>)}
          </div>
        </div>
        <div style={{ fontSize: 11, fontWeight: 500, color: "var(--color-text-secondary)", marginBottom: 8, textTransform: "uppercase", letterSpacing: "0.05em" }}>Steps ({cap.steps?.length || 0})</div>
        {(cap.steps || []).map((s, i) => <div key={i} style={{ borderLeft: "2px solid var(--color-border-tertiary)", paddingLeft: 12, marginBottom: 12, marginLeft: 4 }}>
          <div style={{ display: "flex", alignItems: "center", gap: 6, marginBottom: 3 }}>
            <span style={{ fontSize: 10, fontFamily: "var(--font-mono)", color: "var(--color-text-tertiary)", minWidth: 14 }}>{i + 1}.</span>
            <span style={{ fontSize: 13, fontWeight: 500, color: "var(--color-text-primary)" }}>{s.intent}</span>
            <span style={{ fontSize: 9, padding: "1px 5px", borderRadius: 3, background: s.nature === "cognitive" ? "#EEEDFE" : "#F1EFE8", color: s.nature === "cognitive" ? "#534AB7" : "#5F5E5A", fontFamily: "var(--font-mono)", textTransform: "uppercase" }}>{s.nature}</span>
          </div>
          <p style={{ fontSize: 12, color: "var(--color-text-secondary)", margin: 0, lineHeight: 1.4, paddingLeft: 20 }}>{s.detail}</p>
        </div>)}
      </>}

      {sec === "contract" && cap.type === "memory_directive" && <div style={{ background: "var(--color-background-secondary)", borderRadius: 8, padding: 14, fontFamily: "var(--font-mono)", fontSize: 12, color: "var(--color-text-secondary)", lineHeight: 1.7 }}>
        type: preference{"\n"}assertion_class: constraint{"\n"}scope: app_specific (Microsoft Word){"\n"}priority: absolute{"\n"}applies_when: formatting citations in legal documents{"\n"}injection_format: imperative
      </div>}

      {sec === "confidence" && <>
        <div style={{ display: "flex", alignItems: "baseline", gap: 8, marginBottom: 4 }}>
          <span style={{ fontSize: 32, fontWeight: 500, fontFamily: "var(--font-mono)", color: "var(--color-text-primary)" }}>{Math.round(cap.confidence * 100)}%</span>
          <span style={{ fontSize: 12, color: "var(--color-text-tertiary)", fontFamily: "var(--font-mono)" }}>α: 5.70 · β: 1.25</span>
        </div>
        <div style={{ marginBottom: 20 }}><CBar v={cap.confidence} /></div>
        <div style={{ height: 50, background: "var(--color-background-secondary)", borderRadius: 8, marginBottom: 16, display: "flex", alignItems: "flex-end", padding: "8px 8px", gap: 2 }}>
          {[48,56,62,67,71,74,70,65,68,72,75,78,80,82].map((v, i) => <div key={i} style={{ flex: 1, background: v >= 70 ? "#1D9E75" : "#BA7517", height: `${v * 0.5}px`, borderRadius: "2px 2px 0 0", opacity: 0.5 + (i / 20) }} />)}
        </div>
        <div style={{ fontSize: 11, fontWeight: 500, color: "var(--color-text-secondary)", marginBottom: 8, textTransform: "uppercase", letterSpacing: "0.05em" }}>Confidence events</div>
        {CONF_EVENTS.map((ev, i) => <div key={i} style={{ display: "flex", alignItems: "center", gap: 8, padding: "6px 0", borderBottom: i < CONF_EVENTS.length - 1 ? "0.5px solid var(--color-border-tertiary)" : "none" }}>
          <span style={{ fontSize: 11, color: "var(--color-text-tertiary)", fontFamily: "var(--font-mono)", minWidth: 40 }}>{ev.d}</span>
          <span style={{ fontSize: 12, color: "var(--color-text-primary)", flex: 1 }}>{ev.e}</span>
          <span style={{ fontSize: 11, fontFamily: "var(--font-mono)", color: ev.up ? "#1D9E75" : "#E24B4A", fontWeight: 500 }}>{ev.delta}</span>
        </div>)}
      </>}

      {sec === "usage" && <>
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 8, marginBottom: 16 }}>
          {[{ l: "Total uses", v: cap.uses || 0 }, { l: "Success rate", v: "87%" }, { l: "Last used", v: cap.lastUsed || "Never" }].map((m, i) =>
            <div key={i} style={{ background: "var(--color-background-secondary)", borderRadius: 8, padding: "10px 12px" }}>
              <div style={{ fontSize: 10, color: "var(--color-text-tertiary)", textTransform: "uppercase", letterSpacing: "0.05em", marginBottom: 4 }}>{m.l}</div>
              <div style={{ fontSize: 18, fontWeight: 500, fontFamily: "var(--font-mono)", color: "var(--color-text-primary)" }}>{m.v}</div>
            </div>
          )}
        </div>
        <div style={{ fontSize: 11, fontWeight: 500, color: "var(--color-text-secondary)", marginBottom: 8, textTransform: "uppercase", letterSpacing: "0.05em" }}>Recent invocations</div>
        {USAGE.map((u, i) => <div key={i} style={{ display: "flex", alignItems: "flex-start", gap: 8, padding: "8px 0", borderBottom: i < USAGE.length - 1 ? "0.5px solid var(--color-border-tertiary)" : "none" }}>
          <div style={{ width: 6, height: 6, borderRadius: "50%", marginTop: 5, flexShrink: 0, background: u.o === "success" ? "#1D9E75" : "#E24B4A" }} />
          <div style={{ flex: 1 }}>
            <div style={{ display: "flex", justifyContent: "space-between" }}>
              <span style={{ fontSize: 12, color: "var(--color-text-primary)" }}>{u.ctx}</span>
              <span style={{ fontSize: 11, color: "var(--color-text-tertiary)", fontFamily: "var(--font-mono)", whiteSpace: "nowrap", marginLeft: 8 }}>{u.t}</span>
            </div>
            <div style={{ fontSize: 11, color: "var(--color-text-tertiary)", marginTop: 2 }}>Elnor · {u.o}</div>
          </div>
        </div>)}
      </>}

      {sec === "provenance" && <>
        <div style={{ background: "var(--color-background-secondary)", borderRadius: 8, padding: 14, marginBottom: 16 }}>
          <div style={{ fontSize: 11, color: "var(--color-text-tertiary)", textTransform: "uppercase", letterSpacing: "0.05em", marginBottom: 8 }}>Created via</div>
          <div style={{ fontSize: 13, color: "var(--color-text-primary)", marginBottom: 4 }}>Demonstration session</div>
          <div style={{ fontSize: 12, color: "var(--color-text-secondary)", fontFamily: "var(--font-mono)", lineHeight: 1.7 }}>
            Date: Apr 1, 2026{"\n"}Target: Microsoft Word 16.94{"\n"}Fidelity: 0.78 (amber){"\n"}Quick promoted: No{"\n"}Reviewed: Yes — full review{"\n"}Session: learn-abc-123
          </div>
        </div>
        <div style={{ fontSize: 11, fontWeight: 500, color: "var(--color-text-secondary)", marginBottom: 8, textTransform: "uppercase", letterSpacing: "0.05em" }}>Edit history</div>
        <div style={{ fontSize: 12, color: "var(--color-text-secondary)", lineHeight: 1.8 }}>
          <div style={{ padding: "4px 0", borderBottom: "0.5px solid var(--color-border-tertiary)" }}>Apr 3 — Step 3 edited (user_explicitly_stated)</div>
          <div style={{ padding: "4px 0", borderBottom: "0.5px solid var(--color-border-tertiary)" }}>Apr 4 — Trigger phrase added: "brief cover"</div>
          <div style={{ padding: "4px 0" }}>Apr 5 — Promoted to approved_workspace</div>
        </div>
      </>}

      {sec === "linked" && <>
        <div style={{ fontSize: 11, fontWeight: 500, color: "var(--color-text-secondary)", marginBottom: 8, textTransform: "uppercase", letterSpacing: "0.05em" }}>Goals served</div>
        <div style={{ background: "var(--color-background-secondary)", borderRadius: 8, padding: "10px 14px", marginBottom: 16, cursor: "pointer" }}>
          <span style={{ fontSize: 13, color: "var(--color-text-info)" }}>Produce court-ready litigation documents</span>
          <span style={{ fontSize: 11, color: "var(--color-text-tertiary)", display: "block", marginTop: 2 }}>3 procedures linked</span>
        </div>
        <div style={{ fontSize: 11, fontWeight: 500, color: "var(--color-text-secondary)", marginBottom: 8, textTransform: "uppercase", letterSpacing: "0.05em" }}>Related procedures</div>
        {["Format Table of Authorities", "Draft Opposition Brief Structure"].map((n, i) =>
          <div key={i} style={{ background: "var(--color-background-secondary)", borderRadius: 8, padding: "8px 14px", marginBottom: 6, cursor: "pointer" }}>
            <span style={{ fontSize: 12, color: "var(--color-text-primary)" }}>{n}</span>
            <span style={{ fontSize: 10, color: "var(--color-text-tertiary)", marginLeft: 8 }}>{i === 0 ? "same app" : "requires this"}</span>
          </div>
        )}
        <div style={{ fontSize: 11, fontWeight: 500, color: "var(--color-text-secondary)", marginBottom: 8, marginTop: 16, textTransform: "uppercase", letterSpacing: "0.05em" }}>Related memory directives</div>
        <div style={{ background: "var(--color-background-secondary)", borderRadius: 8, padding: "8px 14px", cursor: "pointer" }}>
          <span style={{ fontSize: 12, color: "var(--color-text-primary)" }}>Always use Bluebook citation format</span>
          <span style={{ fontSize: 10, color: "var(--color-text-tertiary)", marginLeft: 8 }}>Microsoft Word</span>
        </div>
      </>}

      {(sec === "details" || sec === "content") && <div style={{ background: "var(--color-background-secondary)", borderRadius: 8, padding: 14, fontFamily: "var(--font-mono)", fontSize: 12, color: "var(--color-text-secondary)", lineHeight: 1.7, whiteSpace: "pre-wrap" }}>
        {cap.type === "system_tool" ? `Tool: ${cap.name}\nGroup: group:runtime\nProfiles: coding, full\nStatus: Allowed\n\nConfigure in Settings → Tools` : cap.type === "mcp_tool" ? `Server: ${cap.app}\nTool: ${cap.name}\nHealth: Healthy\nLast check: 3 min ago` : `Source: ${cap.origin.replace("_", " ")}\nVersion: 1.2.0\nRequirements: uv, GEMINI_API_KEY\nStatus: ${cap.status}`}
      </div>}
    </div>

    {/* Actions */}
    <div style={{ padding: "12px 20px", borderTop: "0.5px solid var(--color-border-tertiary)", display: "flex", gap: 8, flexWrap: "wrap" }}>
      {isEditable && <button style={{ fontSize: 12, padding: "6px 14px", borderRadius: 6, background: "var(--color-text-primary)", color: "var(--color-background-primary)", border: "none", cursor: "pointer", fontWeight: 500 }}>Edit</button>}
      {cap.lane === "experimental_private" && <button style={{ fontSize: 12, padding: "6px 14px", borderRadius: 6, border: "0.5px solid var(--color-border-secondary)", background: "none", cursor: "pointer", color: "var(--color-text-primary)" }}>Promote to approved</button>}
      {isProc && <button style={{ fontSize: 12, padding: "6px 14px", borderRadius: 6, border: "0.5px solid var(--color-border-secondary)", background: "none", cursor: "pointer", color: "var(--color-text-primary)" }}>Export SKILL.md</button>}
      {cap.type === "native_skill" && <button style={{ fontSize: 12, padding: "6px 14px", borderRadius: 6, border: "0.5px solid var(--color-border-secondary)", background: "none", cursor: "pointer", color: "var(--color-text-primary)" }}>Uninstall</button>}
      {cap.type === "mcp_tool" && <button style={{ fontSize: 12, padding: "6px 14px", borderRadius: 6, border: "0.5px solid var(--color-border-secondary)", background: "none", cursor: "pointer", color: "var(--color-text-primary)" }}>Manage connector</button>}
      {cap.type === "system_tool" && <button style={{ fontSize: 12, padding: "6px 14px", borderRadius: 6, border: "0.5px solid var(--color-border-secondary)", background: "none", cursor: "pointer", color: "var(--color-text-primary)" }}>Open settings</button>}
      <div style={{ flex: 1 }} />
      {isEditable && <button style={{ fontSize: 12, padding: "6px 14px", borderRadius: 6, border: "0.5px solid var(--color-border-secondary)", background: "none", cursor: "pointer", color: "#A32D2D" }}>Archive</button>}
    </div>
  </div>;
}

function ConnectorsTab() {
  const conns = [
    { name: "Gmail", id: "will@schallfirm.com", tools: 8, icon: "✉", status: "connected" },
    { name: "Microsoft 365", id: "will@schallfirm.com", tools: 14, icon: "◆", status: "connected" },
    { name: "Linear", id: "will@schallfirm.com", tools: 6, icon: "◇", status: "connected" },
  ];
  return <div>
    <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 16 }}>
      <span style={{ fontSize: 13, color: "var(--color-text-secondary)" }}>3 services connected</span>
      <button style={{ fontSize: 12, padding: "6px 14px", borderRadius: 6, background: "var(--color-text-primary)", color: "var(--color-background-primary)", border: "none", cursor: "pointer", fontWeight: 500 }}>+ Add connector</button>
    </div>
    {conns.map((c, i) => <div key={i} style={{ background: "var(--color-background-primary)", border: "0.5px solid var(--color-border-tertiary)", borderRadius: "var(--border-radius-lg)", padding: "14px 16px", marginBottom: 8, display: "flex", alignItems: "center", gap: 12 }}>
      <div style={{ width: 36, height: 36, borderRadius: 8, background: "var(--color-background-secondary)", display: "flex", alignItems: "center", justifyContent: "center", fontSize: 16 }}>{c.icon}</div>
      <div style={{ flex: 1 }}>
        <div style={{ fontSize: 13, fontWeight: 500, color: "var(--color-text-primary)" }}>{c.name}</div>
        <div style={{ fontSize: 11, color: "var(--color-text-tertiary)", fontFamily: "var(--font-mono)" }}>{c.id} · {c.tools} tools</div>
      </div>
      <Dot status="active" />
      <button style={{ fontSize: 11, padding: "4px 10px", borderRadius: 4, border: "0.5px solid var(--color-border-tertiary)", background: "none", cursor: "pointer", color: "var(--color-text-secondary)" }}>Configure</button>
    </div>)}
  </div>;
}

function LearnTab() {
  return <div>
    <div style={{ fontSize: 11, fontWeight: 500, color: "var(--color-text-secondary)", marginBottom: 12, textTransform: "uppercase", letterSpacing: "0.05em" }}>Start learning</div>
    <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8, marginBottom: 24 }}>
      {[
        { t: "Watch me do this", d: "Demonstrate a task while Elnor observes" },
        { t: "Let me coach you", d: "Guide Elnor through a task step by step" },
        { t: "Import a skill", d: "Import a SKILL.md file or paste content" },
        { t: "Import from clipboard", d: "Paste a skill definition directly" },
      ].map((a, i) => <div key={i} style={{ background: "var(--color-background-primary)", border: "0.5px solid var(--color-border-tertiary)", borderRadius: "var(--border-radius-lg)", padding: 14, cursor: "pointer" }}>
        <div style={{ fontSize: 13, fontWeight: 500, color: "var(--color-text-primary)", marginBottom: 4 }}>{a.t}</div>
        <div style={{ fontSize: 11, color: "var(--color-text-tertiary)", lineHeight: 1.4 }}>{a.d}</div>
      </div>)}
    </div>
    <div style={{ fontSize: 11, fontWeight: 500, color: "var(--color-text-secondary)", marginBottom: 12, textTransform: "uppercase", letterSpacing: "0.05em" }}>Pending review (2)</div>
    {[{ n: "Auto-generate email summary", c: 72 }, { n: "Excel pivot table from template", c: 61 }].map((p, i) =>
      <div key={i} style={{ background: "var(--color-background-primary)", border: "0.5px solid var(--color-border-tertiary)", borderRadius: 8, padding: "10px 14px", marginBottom: 6, display: "flex", alignItems: "center", justifyContent: "space-between" }}>
        <div>
          <div style={{ fontSize: 13, color: "var(--color-text-primary)" }}>{p.n}</div>
          <div style={{ fontSize: 11, color: "var(--color-text-tertiary)", fontFamily: "var(--font-mono)" }}>Confidence: {p.c}%</div>
        </div>
        <div style={{ display: "flex", gap: 6 }}>
          <button style={{ fontSize: 11, padding: "4px 10px", borderRadius: 4, border: "0.5px solid var(--color-border-tertiary)", background: "none", cursor: "pointer", color: "var(--color-text-primary)" }}>Review</button>
          <button style={{ fontSize: 11, padding: "4px 10px", borderRadius: 4, background: "var(--color-text-primary)", color: "var(--color-background-primary)", border: "none", cursor: "pointer" }}>Quick promote</button>
        </div>
      </div>
    )}
  </div>;
}

export default function App() {
  const [tab, setTab] = useState(0);
  const [sel, setSel] = useState(null);
  const [tf, setTf] = useState("all");
  const [sq, setSq] = useState("");

  const filtered = CAPS.filter(c => {
    if (tf !== "all" && c.type !== tf) return false;
    if (sq && !c.name.toLowerCase().includes(sq.toLowerCase()) && !c.desc.toLowerCase().includes(sq.toLowerCase())) return false;
    return true;
  });

  return <div style={{ maxWidth: 900, margin: "0 auto", padding: "1rem 0" }}>
    <div style={{ marginBottom: 20 }}>
      <h2 style={{ fontSize: 20, fontWeight: 500, color: "var(--color-text-primary)", margin: "0 0 4px" }}>Skills & connectors</h2>
      <p style={{ fontSize: 13, color: "var(--color-text-tertiary)", margin: 0 }}>Browse, manage, and extend Elnor's capabilities</p>
    </div>

    <div style={{ display: "flex", gap: 0, borderBottom: "0.5px solid var(--color-border-tertiary)", marginBottom: 20, overflowX: "auto" }}>
      {TABS.map((t, i) => <button key={i} onClick={() => { setTab(i); setSel(null); }} style={{
        background: "none", border: "none",
        borderBottom: tab === i ? "2px solid var(--color-text-primary)" : "2px solid transparent",
        padding: "10px 14px", fontSize: 13, fontWeight: tab === i ? 500 : 400,
        color: i === 5 ? "var(--color-text-tertiary)" : tab === i ? "var(--color-text-primary)" : "var(--color-text-secondary)",
        cursor: i === 5 ? "default" : "pointer", whiteSpace: "nowrap", opacity: i === 5 ? 0.5 : 1,
      }}>{t}{i === 2 && <span style={{ fontSize: 9, marginLeft: 4, padding: "1px 5px", borderRadius: 8, background: "#E24B4A", color: "#fff", fontWeight: 500 }}>2</span>}</button>)}
    </div>

    {tab === 0 && <>
      <div style={{ display: "flex", gap: 8, marginBottom: 16, flexWrap: "wrap" }}>
        <input type="text" placeholder="Search capabilities..." value={sq} onChange={e => setSq(e.target.value)}
          style={{ flex: "1 1 200px", minWidth: 0 }} />
        <select value={tf} onChange={e => setTf(e.target.value)}>
          <option value="all">All types</option>
          <option value="learned_procedure">Learned procedures</option>
          <option value="native_skill">Native skills</option>
          <option value="mcp_tool">MCP tools</option>
          <option value="system_tool">System tools</option>
          <option value="standing_procedure">Standing procedures</option>
          <option value="memory_directive">Memory directives</option>
        </select>
      </div>
      <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(260px, 1fr))", gap: 10 }}>
        {filtered.map(c => <Card key={c.id} cap={c} selected={sel?.id === c.id} onClick={() => setSel(sel?.id === c.id ? null : c)} />)}
      </div>
      {filtered.length === 0 && <div style={{ textAlign: "center", padding: "40px 0", color: "var(--color-text-tertiary)" }}>
        <p style={{ fontSize: 14, margin: "0 0 8px" }}>No capabilities match your filters.</p>
        <button onClick={() => { setTf("all"); setSq(""); }}>Clear filters</button>
      </div>}
      {sel && <Drawer cap={sel} onClose={() => setSel(null)} />}
    </>}

    {tab === 1 && <ConnectorsTab />}
    {tab === 4 && <LearnTab />}
    {tab === 2 && <div style={{ textAlign: "center", padding: "40px 0", color: "var(--color-text-tertiary)" }}>
      <p style={{ fontSize: 14, margin: "0 0 4px", fontWeight: 500 }}>OpenClaw tool catalog</p>
      <p style={{ fontSize: 12, margin: "0 0 16px" }}>Browse 13,700+ skills on ClawHub, manage installed plugins</p>
      <div style={{ display: "flex", justifyContent: "center", gap: 8 }}>
        <button style={{ fontSize: 12 }}>Browse ClawHub</button>
        <button style={{ fontSize: 12 }}>Installed (4 plugins)</button>
      </div>
    </div>}
    {tab === 3 && <div style={{ padding: "20px 0" }}>
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 16 }}>
        <div>
          <div style={{ fontSize: 14, fontWeight: 500, color: "var(--color-text-primary)" }}>Elnor MCP server</div>
          <div style={{ fontSize: 12, color: "var(--color-text-tertiary)" }}>Let external AI models access your capabilities</div>
        </div>
        <div style={{ width: 40, height: 22, borderRadius: 11, background: "var(--color-border-tertiary)", cursor: "pointer", position: "relative" }}>
          <div style={{ width: 18, height: 18, borderRadius: "50%", background: "var(--color-background-primary)", position: "absolute", top: 2, left: 2, border: "0.5px solid var(--color-border-secondary)" }} />
        </div>
      </div>
      <div style={{ background: "var(--color-background-secondary)", borderRadius: 8, padding: 16, fontSize: 13, color: "var(--color-text-secondary)", lineHeight: 1.6 }}>
        When enabled, external LLMs (Claude, ChatGPT, Cursor) can connect to Elnor via MCP and access your approved capabilities. You control what's exposed, what knowledge scope is visible, and whether external models can execute actions or only read.
      </div>
    </div>}
    {tab === 5 && <div style={{ textAlign: "center", padding: "60px 0", color: "var(--color-text-tertiary)" }}>
      <p style={{ fontSize: 14, fontWeight: 500, margin: "0 0 8px" }}>Coming soon</p>
      <p style={{ fontSize: 12, margin: 0 }}>Community capabilities, curated packs, and third-party plugins.</p>
    </div>}
  </div>;
}