= {
+ all: installed.length,
+ enabled,
+ disabled,
+ issues,
+ };
+ const segments = (
+ [
+ ["enabled", enabled],
+ ["disabled", disabled],
+ ["issues", issues],
+ ] as const
+ ).filter(([, value]) => value > 0);
+ return html`
+
+ ${segments.length > 0
+ ? html`
+
+ ${segments.map(
+ ([key, value]) => html`
+
+ `,
+ )}
+
+ `
+ : nothing}
+
+ ${INSTALLED_FILTERS.map(
+ (filter) => html`
+
+ `,
+ )}
+
+
+ `;
+}
+
+function renderInstalledRow(plugin: PluginCatalogItem, props: PluginsViewProps): TemplateResult {
+ const key = pluginRowKey(plugin.id);
+ const busy = props.busy[key];
+ return html`
+ {
+ if (!fromInteractiveChild(event)) {
+ props.onShowDetails(plugin.id);
+ }
+ }}
+ >
+ ${renderArtTile(plugin.id, plugin.name, "tile")}
+
+
+
${plugin.name}
+ ${plugin.version
+ ? html`v${plugin.version}`
+ : nothing}
+ ${plugin.state === "error"
+ ? html`${stateLabel(plugin)}`
+ : nothing}
+
+
${plugin.description || t("pluginsPage.optionalCapability")}
+
+ ${plugin.origin ? html`${originLabel(plugin.origin)}` : nothing}
+ ${plugin.packageName
+ ? html`${plugin.packageName}`
+ : nothing}
+
+
+
+ ${renderCatalogActions(plugin, props, busy, key, { details: true })}
+
+ ${plugin.error
+ ? html`
+ ${plugin.error}
+
`
+ : nothing}
+ ${renderRowMessage(key, props.messages[key], busy, props)}
+
+ `;
+}
+
+function mcpMenuItems(server: McpServerSummary, props: PluginsViewProps): PluginMenuItem[] {
+ const blocked = !props.canMutate || props.mcpBusy;
+ return [
+ {
+ key: "toggle",
+ label: server.enabled ? t("pluginsPage.disableAction") : t("pluginsPage.enableAction"),
+ icon: server.enabled ? circleIcon() : icons.check,
+ disabled: blocked,
+ onSelect: () => props.onMcpToggle(server.name, !server.enabled),
+ },
+ {
+ key: "remove",
+ label: t("pluginsPage.remove"),
+ icon: icons.trash,
+ danger: true,
+ disabled: blocked,
+ onSelect: () => props.onMcpRemove(server.name),
+ },
+ ];
+}
+
+function renderMcpSection(props: PluginsViewProps) {
+ const needle = normalizedQuery(props.query);
+ const servers = props.mcpServers?.filter(
+ (server) =>
+ !needle ||
+ server.name.toLocaleLowerCase().includes(needle) ||
+ server.target.toLocaleLowerCase().includes(needle),
+ );
+ if (needle && servers && servers.length === 0) {
+ return nothing;
+ }
+ return html`
+
+
+
${t("pluginsPage.mcpServersGroup")}
+ ${servers ? html`
${servers.length}` : nothing}
+
+
+ ${t("pluginsPage.mcpHint")}
+ ${props.mcpFormOpen ? renderMcpForm(props) : nothing}
+ ${props.mcpMessage
+ ? html`
+ ${props.mcpMessage.text}
+
`
+ : nothing}
+ ${!servers
+ ? html`${t("pluginsPage.loading")}
`
+ : servers.length === 0
+ ? html`${t("pluginsPage.mcpEmpty")}
`
+ : html`
+ ${repeat(
+ servers,
+ (server) => server.name,
+ (server) => renderMcpRow(server, props),
+ )}
+
`}
+
+ `;
+}
+
+function renderMcpRow(server: McpServerSummary, props: PluginsViewProps): TemplateResult {
+ return html`
+
+ ${renderArtTile(server.name, server.name, "tile")}
+
+
+
${server.name}
+ MCP
+ ${server.auth === "oauth" ? html`OAuth` : nothing}
+
+
${server.target}
+
${server.transport}
+
+
+ ${server.enabled ? t("pluginsPage.enabled") : t("pluginsPage.disabled")}
+ ${renderActionsMenu(
+ `mcp:${server.name}`,
+ t("pluginsPage.menuLabel", { name: server.name }),
+ mcpMenuItems(server, props),
+ props,
+ )}
+
+
+ `;
+}
+
+function renderMcpForm(props: PluginsViewProps) {
+ const submit = (event: Event) => {
+ event.preventDefault();
+ const form = event.currentTarget as HTMLFormElement;
+ const data = new FormData(form);
+ const name = data.get("mcp-name");
+ const target = data.get("mcp-target");
+ props.onMcpAdd({
+ name: typeof name === "string" ? name.trim() : "",
+ target: typeof target === "string" ? target.trim() : "",
+ });
+ };
+ return html`
+
+ `;
+}
+
+function renderInstalled(props: PluginsViewProps) {
+ const plugins = installedPlugins(props.result?.plugins ?? [], props.query, props.installedFilter);
+ const groups = groupInstalledByCategory(plugins);
+ return html`
+ ${renderInventoryPulse(props)}
+ ${groups.length === 0
+ ? renderEmpty(
+ props.query || props.installedFilter !== "all"
+ ? t("pluginsPage.noInstalledMatchTitle")
+ : t("pluginsPage.noInstalledTitle"),
+ props.query || props.installedFilter !== "all"
+ ? t("pluginsPage.noMatchBody")
+ : t("pluginsPage.noInstalledBody"),
+ )
+ : html`
+
+ ${groups.map(
+ (group) => html`
+
+
+
${group.label}
+ ${group.plugins.length}
+
+
+ ${repeat(
+ group.plugins,
+ (plugin) => plugin.id,
+ (plugin) => renderInstalledRow(plugin, props),
+ )}
+
+
+ `,
+ )}
+
+ `}
+ ${renderMcpSection(props)}
+ `;
+}
+
+/* ---------------------------------- discover tab ---------------------------------- */
+
+function renderCatalogCard(plugin: PluginCatalogItem, props: PluginsViewProps): TemplateResult {
+ const key = pluginRowKey(plugin.id);
+ const busy = props.busy[key];
+ return html`
+ {
+ if (!fromInteractiveChild(event)) {
+ props.onShowDetails(plugin.id);
+ }
+ }}
+ >
+ ${renderArtTile(plugin.id, plugin.name, "cover")}
+
+
+
${plugin.name}
+ ${plugin.version
+ ? html`v${plugin.version}`
+ : nothing}
+
+
${plugin.description || t("pluginsPage.optionalCapability")}
+
+ ${plugin.origin ? html`${originLabel(plugin.origin)}` : nothing}
+
+
+
+ ${plugin.error
+ ? html`
+ ${plugin.error}
+
`
+ : nothing}
+ ${renderRowMessage(key, props.messages[key], busy, props)}
+
+ `;
+}
+
+function renderConnectorCard(
+ connector: ConnectorSuggestion,
+ props: PluginsViewProps,
+): TemplateResult {
+ const key = connectorRowKey(connector.id);
+ const busy = props.busy[key];
+ const isMcp = connector.action.kind === "mcp";
+ const installed =
+ isMcp &&
+ Boolean(
+ props.mcpServers?.some(
+ (server) =>
+ connector.action.kind === "mcp" && server.name === connector.action.mcp.serverName,
+ ),
+ );
+ return html`
+
+ ${renderArtTile(connector.id, connector.name, "cover")}
+
+
+
${connector.name}
+
+
${connector.description}
+
+ ${isMcp
+ ? html`MCP
+ ${t("pluginsPage.connectorMcpNote")}`
+ : html`${t("pluginsPage.connectorClawHubNote")}`}
+
+
+
+ ${renderRowMessage(key, props.messages[key], busy, props)}
+
+ `;
+}
+
+function renderShelf(
+ id: string,
+ label: string,
+ hint: string | null,
+ cards: readonly TemplateResult[],
+) {
+ if (cards.length === 0) {
+ return nothing;
+ }
+ return html`
+
+
+
${label}
+ ${cards.length}
+
+ ${hint ? html`${hint}
` : nothing}
+ ${cards}
+
+ `;
+}
+
+function findInstalledSearchPlugin(
+ item: PluginSearchResult,
+ plugins: readonly PluginCatalogItem[],
+): PluginCatalogItem | undefined {
+ return plugins.find(
+ (plugin) =>
+ plugin.installed &&
+ (plugin.id === item.package.runtimeId ||
+ plugin.packageName === item.package.name ||
+ (plugin.install?.source === "clawhub" && plugin.install.packageName === item.package.name)),
+ );
+}
+
+function verificationLabel(tier: string): string {
+ return tier === "source-linked" ? t("pluginsPage.verifiedSource") : tier;
+}
+
+function renderClawHubResult(item: PluginSearchResult, props: PluginsViewProps): TemplateResult {
+ const pkg = item.package;
+ const installed = findInstalledSearchPlugin(item, props.result?.plugins ?? []);
+ const key = clawHubRowKey(pkg.name);
+ const busy = props.busy[key];
+ const artSlug = pkg.runtimeId ?? pkg.name;
+ return html`
+ {
+ if (installed && !fromInteractiveChild(event)) {
+ props.onShowDetails(installed.id);
+ }
+ }}
+ >
+ ${renderArtTile(artSlug, pkg.displayName, "tile")}
+
+
+
${pkg.displayName}
+ ${pkg.latestVersion
+ ? html`v${pkg.latestVersion}`
+ : nothing}
+
+
${pkg.summary || pkg.name}
+
+ ${pkg.isOfficial
+ ? html`${t("pluginsPage.official")}`
+ : nothing}
+ ${pkg.verificationTier
+ ? html`
+ ${icons.check}
+ ${verificationLabel(pkg.verificationTier)}
+ `
+ : nothing}
+ ${typeof pkg.downloads === "number"
+ ? html`
+ ${icons.download}
+ ${compactNumber.format(pkg.downloads)}
+ `
+ : nothing}
+ ${pkg.family === "bundle-plugin"
+ ? t("pluginsPage.bundlePlugin")
+ : t("pluginsPage.codePlugin")}
+
+
+
+ ${installed
+ ? renderCatalogActions(installed, props, busy, key, { details: true })
+ : renderInstallButton(props, busy, key, pkg.displayName, {
+ source: "clawhub",
+ packageName: pkg.name,
+ })}
+
+ ${renderRowMessage(key, props.messages[key], busy, props)}
+
+ `;
+}
+
+/** Live registry results appended below the curated shelves while searching. */
+function renderClawHubGroup(props: PluginsViewProps) {
+ const query = props.query.trim();
+ if (query.length < 2) {
+ return nothing;
+ }
+ let body: TemplateResult;
+ if (props.searchLoading || (!props.searchResults && !props.searchError)) {
+ body = html`
+ ${t("pluginsPage.searching")}
+
`;
+ } else if (props.searchError) {
+ body = html`
+ ${props.searchError}
+
`;
+ } else if (props.searchResults && props.searchResults.length === 0) {
+ body = html`
+ ${t("pluginsPage.noClawHubResultsBody", { query })}
+
`;
+ } else {
+ body = html`
+
+ ${repeat(
+ props.searchResults ?? [],
+ (item) => item.package.name,
+ (item) => renderClawHubResult(item, props),
+ )}
+
+ `;
+ }
+ return html`
+
+
+
${t("pluginsPage.fromClawHub")}
+ ${props.searchResults ? html`
${props.searchResults.length}` : nothing}
+
+
+ ${body}
+
+ `;
+}
+
+function renderDiscover(props: PluginsViewProps) {
+ const shelves = discoverShelves(props.result?.plugins ?? [], props.query);
+ const featuredCards = shelves.featured.map((plugin) => renderCatalogCard(plugin, props));
+ const officialCards = shelves.official.map((plugin) => renderCatalogCard(plugin, props));
+ const clawHub = renderClawHubGroup(props);
+ if (!featuredCards.length && !officialCards.length && !shelves.connectors.length) {
+ return html`
+ ${clawHub === nothing
+ ? renderEmpty(t("pluginsPage.noDiscoverMatchTitle"), t("pluginsPage.noMatchBody"))
+ : nothing}
+ ${clawHub}
+ `;
+ }
+ return html`
+
+ ${renderShelf("featured", t("pluginsPage.featuredGroup"), null, featuredCards)}
+ ${renderShelf("official", t("pluginsPage.officialGroup"), null, officialCards)}
+ ${renderConnectorShelves(shelves.connectors, props)} ${clawHub}
+
+ `;
+}
+
+/** Connectors shelve by use case, mirroring how people group their tools. */
+function renderConnectorShelves(
+ connectors: readonly ConnectorSuggestion[],
+ props: PluginsViewProps,
+) {
+ if (connectors.length === 0) {
+ return nothing;
+ }
+ const groups = CONNECTOR_GROUP_ORDER.map((group) => ({
+ group,
+ entries: connectors.filter((connector) => connector.group === group),
+ })).filter((entry) => entry.entries.length > 0);
+ return html`
+
+
+
${t("pluginsPage.connectorsGroup")}
+ ${connectors.length}
+
+ ${t("pluginsPage.connectorsHint")}
+ ${groups.map(
+ (entry) => html`
+
+
${connectorGroupLabel(entry.group)}
+
+ ${entry.entries.map((connector) => renderConnectorCard(connector, props))}
+
+
+ `,
+ )}
+
+ `;
+}
+
+/* ---------------------------------- detail overlay ---------------------------------- */
+
+function detailMetaRow(label: string, value: string | TemplateResult) {
+ return html`
+
+ ${label}
+ ${value}
+
+ `;
+}
+
+function renderDetailOverlay(props: PluginsViewProps) {
+ const plugin = props.detailPluginId
+ ? props.result?.plugins.find((entry) => entry.id === props.detailPluginId)
+ : undefined;
+ if (!plugin) {
+ return nothing;
+ }
+ const key = pluginRowKey(plugin.id);
+ const busy = props.busy[key];
+ return html`
+ {
+ if (event.target === event.currentTarget) {
+ props.onShowDetails(null);
+ }
+ }}
+ >
+
+
+ ${renderArtTile(plugin.id, plugin.name, "cover")}
+
+
+
${plugin.name}
+ ${plugin.version
+ ? html`v${plugin.version}`
+ : nothing}
+ ${stateChip(plugin)}
+
+
+ ${plugin.description || t("pluginsPage.optionalCapability")}
+
+
+ ${props.pendingRemoval[key]
+ ? renderRemoveConfirm(plugin, props, busy, key)
+ : html`
+ ${plugin.installed
+ ? html`
+
+ `
+ : plugin.install
+ ? renderInstallButton(props, busy, key, plugin.name, plugin.install)
+ : nothing}
+ ${plugin.removable
+ ? html`
+
+ `
+ : nothing}
+ `}
+
+ ${plugin.error
+ ? html`
+ ${plugin.error}
+
`
+ : nothing}
+ ${renderRowMessage(key, props.messages[key], busy, props)}
+
+ ${plugin.origin
+ ? detailMetaRow(t("pluginsPage.detailOrigin"), originLabel(plugin.origin))
+ : nothing}
+ ${plugin.category
+ ? detailMetaRow(t("pluginsPage.detailCategory"), pluginCategoryLabel(plugin.category))
+ : nothing}
+ ${plugin.packageName
+ ? detailMetaRow(
+ t("pluginsPage.detailPackage"),
+ html`${plugin.packageName}`,
+ )
+ : nothing}
+ ${detailMetaRow(t("pluginsPage.detailPluginId"), html`${plugin.id}`)}
+
+
+
+
+ `;
+}
+
+/* ---------------------------------- page shell ---------------------------------- */
+
+function renderEmpty(title: string, body: string) {
+ return html`
+
+
${icons.puzzle}
+
${title}
+
${body}
+
+ `;
+}
+
+function renderActivePanel(props: PluginsViewProps) {
+ switch (props.activeTab) {
+ case "installed":
+ return renderInstalled(props);
+ case "discover":
+ return renderDiscover(props);
+ default:
+ return props.activeTab satisfies never;
+ }
+}
+
+export function renderPlugins(props: PluginsViewProps) {
+ const installedCount = props.result?.plugins.filter((plugin) => plugin.installed).length ?? 0;
+ const canShowCatalog = Boolean(props.result);
+ return html`
+
+
+
+
+
+
+ ${props.mutationBlockedReason
+ ? html`
+ ${icons.alertTriangle}
+ ${props.mutationBlockedReason}
+
`
+ : nothing}
+
+
+ ${PLUGIN_TABS.map((tab) => {
+ const selected = props.activeTab === tab;
+ const count = tab === "installed" ? installedCount : null;
+ return html`
+
+ `;
+ })}
+
+
+ ${props.error
+ ? html`
+ ${props.error}
+
+
`
+ : nothing}
+ ${props.pageNotice
+ ? html`
+ ${props.pageNotice.text}
+
`
+ : nothing}
+
+
+ ${props.loading && !canShowCatalog
+ ? html`
${t("pluginsPage.loading")}
`
+ : props.error && !canShowCatalog
+ ? nothing
+ : !props.connected && !canShowCatalog
+ ? renderEmpty(t("pluginsPage.offlineTitle"), t("pluginsPage.offlineBody"))
+ : renderActivePanel(props)}
+
+ ${renderDetailOverlay(props)}
+
+ `;
+}
diff --git a/ui/src/pages/route-provenance.test.ts b/ui/src/pages/route-provenance.test.ts
index b424dec8503e..2d84d64c470c 100644
--- a/ui/src/pages/route-provenance.test.ts
+++ b/ui/src/pages/route-provenance.test.ts
@@ -8,6 +8,8 @@ import type { DreamsRouteData } from "./dreams/dreams-page.ts";
import { page as dreamsPage } from "./dreams/route.ts";
import type { NodesRouteData } from "./nodes/nodes-page.ts";
import { page as nodesPage } from "./nodes/route.ts";
+import type { PluginsRouteData } from "./plugins/plugins-page.ts";
+import { page as pluginsPage } from "./plugins/route.ts";
import { page as sessionsPage } from "./sessions/route.ts";
import type { SessionsRouteData } from "./sessions/sessions-page.ts";
import { page as skillsPage } from "./skills/route.ts";
@@ -155,6 +157,41 @@ describe("route preload gateway provenance", () => {
expect(data.agents).toBe(agents);
});
+ it("keeps plugins provenance from before its async preload", async () => {
+ const result = { plugins: [], diagnostics: [], mutationAllowed: true };
+ const response = deferred();
+ const requestMethod = vi.fn(() => response.promise);
+ const client = { request: requestMethod } as unknown as GatewayBrowserClient;
+ const originalSnapshot = snapshot(client, true);
+ const mutable = mutableGateway(originalSnapshot);
+ const request = loadRoute(pluginsPage, {
+ gateway: mutable.gateway,
+ } as unknown as ApplicationContext);
+
+ mutable.replaceSnapshot(snapshot(client, false));
+ response.resolve(result);
+ const data = await request;
+
+ expect(requestMethod).toHaveBeenCalledWith("plugins.list", {});
+ expect(data.gateway).toBe(mutable.gateway);
+ expect(data.gatewaySnapshot).toBe(originalSnapshot);
+ expect(data.result).toEqual(result);
+ });
+
+ it("does not request plugins while disconnected", async () => {
+ const requestMethod = vi.fn();
+ const client = { request: requestMethod } as unknown as GatewayBrowserClient;
+ const mutable = mutableGateway(snapshot(client, false));
+
+ const data = await loadRoute(pluginsPage, {
+ gateway: mutable.gateway,
+ } as unknown as ApplicationContext);
+
+ expect(requestMethod).not.toHaveBeenCalled();
+ expect(data.result).toBeNull();
+ expect(data.error).toBeNull();
+ });
+
it("keeps dreams provenance from before capability warmup", async () => {
const client = {} as GatewayBrowserClient;
const originalSnapshot = snapshot(client, false);
diff --git a/ui/src/styles.css b/ui/src/styles.css
index beb7d1730240..2ba13018ecd7 100644
--- a/ui/src/styles.css
+++ b/ui/src/styles.css
@@ -17,6 +17,7 @@
@import "./styles/dreams.css";
@import "./styles/lobster-pet.css";
@import "./styles/workboard.css";
+@import "./styles/plugins.css";
@import "./styles/skill-workshop.css";
@import "@create-markdown/preview/themes/system.css";
diff --git a/ui/src/styles/plugins.css b/ui/src/styles/plugins.css
new file mode 100644
index 000000000000..b4bfb4a21e34
--- /dev/null
+++ b/ui/src/styles/plugins.css
@@ -0,0 +1,1182 @@
+/* Plugins manager: inventory rows, cover-art store shelves, and MCP connectors. */
+.plugins-workspace {
+ width: 100%;
+ max-width: 1480px;
+ margin: 0 auto;
+ padding: 4px 8px 56px;
+}
+
+.plugins-content-header .page-title {
+ margin: 0;
+}
+
+.plugins-toolbar {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+}
+
+.plugins-search {
+ position: relative;
+ display: flex;
+ flex: 1 1 440px;
+ align-items: center;
+ min-width: 220px;
+}
+
+.plugins-search__label {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ margin: -1px;
+ padding: 0;
+ overflow: hidden;
+ clip: rect(0 0 0 0);
+ clip-path: inset(50%);
+ white-space: nowrap;
+}
+
+.plugins-search__icon {
+ position: absolute;
+ left: 15px;
+ z-index: 1;
+ width: 18px;
+ height: 18px;
+ color: var(--muted);
+ pointer-events: none;
+}
+
+.plugins-search__icon svg,
+.plugins-empty__icon svg,
+.plugins-readonly svg,
+.plugins-refresh svg,
+.plugins-menu__icon svg,
+.plugins-kebab svg,
+.plugins-downloads svg,
+.plugins-badge svg,
+.plugins-group__actions svg,
+.plugins-group__link svg,
+.plugins-detail__close svg,
+.plugins-detail__remove svg,
+.plugins-action-note svg {
+ width: 100%;
+ height: 100%;
+ fill: none;
+ stroke: currentColor;
+ stroke-width: 1.7px;
+ stroke-linecap: round;
+ stroke-linejoin: round;
+}
+
+.plugins-search input {
+ width: 100%;
+ height: 44px;
+ border: 1px solid var(--border-strong);
+ border-radius: var(--radius-full);
+ padding: 0 18px 0 44px;
+ background: var(--card);
+ color: var(--text-strong);
+ font-size: var(--control-ui-input-text-size);
+ box-shadow: inset 0 1px 0 var(--card-highlight);
+ transition:
+ border-color var(--duration-fast) var(--ease-out),
+ box-shadow var(--duration-fast) var(--ease-out),
+ background var(--duration-fast) var(--ease-out);
+}
+
+.plugins-search input:hover {
+ border-color: var(--border-hover);
+}
+
+.plugins-search input:focus-visible {
+ border-color: var(--ring);
+ outline: none;
+ box-shadow: var(--focus-ring);
+}
+
+.plugins-toolbar__actions {
+ display: flex;
+ flex: 0 0 auto;
+ align-items: center;
+ gap: 8px;
+}
+
+.plugins-refresh {
+ width: 44px;
+ height: 44px;
+ flex: 0 0 auto;
+}
+
+.plugins-refresh span {
+ width: 16px;
+ height: 16px;
+}
+
+.plugins-readonly {
+ display: flex;
+ align-items: center;
+ gap: 9px;
+ margin-top: 12px;
+ padding: 9px 12px;
+ border: 1px solid color-mix(in srgb, var(--warn) 28%, var(--border));
+ border-radius: var(--radius-md);
+ background: var(--warn-subtle);
+ color: var(--warn);
+ font-size: var(--control-ui-text-sm);
+ line-height: 1.45;
+}
+
+.plugins-readonly > span:first-child {
+ width: 16px;
+ height: 16px;
+ flex: 0 0 auto;
+}
+
+.plugins-tabs {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ margin-top: 18px;
+ padding-bottom: 10px;
+ border-bottom: 1px solid var(--border);
+ overflow-x: auto;
+ scrollbar-width: none;
+}
+
+.plugins-tabs::-webkit-scrollbar {
+ display: none;
+}
+
+.plugins-tabs button {
+ position: relative;
+ display: inline-flex;
+ align-items: center;
+ gap: 7px;
+ min-height: 36px;
+ border: 0;
+ border-radius: var(--radius-md);
+ padding: 0 13px;
+ background: transparent;
+ color: var(--muted);
+ font-size: var(--control-ui-text-sm);
+ font-weight: 560;
+ cursor: pointer;
+ transition:
+ color var(--duration-fast) var(--ease-out),
+ background var(--duration-fast) var(--ease-out);
+}
+
+.plugins-tabs button:hover {
+ background: var(--bg-hover);
+ color: var(--text-strong);
+}
+
+.plugins-tabs button.active {
+ background: var(--accent-subtle);
+ color: var(--text-strong);
+}
+
+.plugins-tabs button > span {
+ min-width: 20px;
+ border-radius: var(--radius-full);
+ padding: 2px 6px;
+ background: color-mix(in srgb, currentColor 11%, transparent);
+ color: inherit;
+ font-size: var(--control-ui-text-xs);
+ line-height: 1.2;
+ text-align: center;
+}
+
+.plugins-panel {
+ min-height: 280px;
+ padding-top: 20px;
+}
+
+.plugins-page-notice {
+ margin-top: 14px;
+}
+
+/* ---------- inventory pulse ---------- */
+
+.plugins-pulse {
+ display: grid;
+ gap: 10px;
+ margin-bottom: 18px;
+}
+
+.plugins-pulse__meter {
+ display: flex;
+ height: 6px;
+ gap: 3px;
+ overflow: hidden;
+ border-radius: var(--radius-full);
+}
+
+.plugins-pulse__segment {
+ min-width: 6px;
+ border-radius: var(--radius-full);
+ transition: flex-grow var(--duration-slow) var(--ease-out);
+}
+
+.plugins-pulse__segment--enabled {
+ background: var(--ok);
+}
+
+.plugins-pulse__segment--disabled {
+ background: var(--border-strong);
+}
+
+.plugins-pulse__segment--issues {
+ background: var(--danger);
+}
+
+/* ---------- filter chips ---------- */
+
+.plugins-filters {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 6px;
+}
+
+.plugins-filters button {
+ display: inline-flex;
+ align-items: center;
+ gap: 6px;
+ border: 1px solid var(--border);
+ border-radius: var(--radius-full);
+ padding: 5px 12px;
+ background: transparent;
+ color: var(--muted);
+ font-size: var(--control-ui-text-xs);
+ font-weight: 580;
+ cursor: pointer;
+ transition:
+ color var(--duration-fast) var(--ease-out),
+ background var(--duration-fast) var(--ease-out),
+ border-color var(--duration-fast) var(--ease-out);
+}
+
+.plugins-filters button:hover {
+ border-color: var(--border-hover);
+ color: var(--text-strong);
+}
+
+.plugins-filters button.active {
+ border-color: color-mix(in srgb, var(--accent) 45%, var(--border));
+ background: var(--accent-subtle);
+ color: var(--text-strong);
+}
+
+.plugins-filters__dot {
+ width: 7px;
+ height: 7px;
+ flex: 0 0 auto;
+ border-radius: 50%;
+}
+
+.plugins-filters__dot--enabled {
+ background: var(--ok);
+}
+
+.plugins-filters__dot--disabled {
+ background: var(--border-strong);
+}
+
+.plugins-filters__dot--issues {
+ background: var(--danger);
+}
+
+.plugins-filters__count {
+ color: var(--muted);
+ font-variant-numeric: tabular-nums;
+}
+
+.plugins-filters button.active .plugins-filters__count {
+ color: var(--text-strong);
+}
+
+/* ---------- groups / shelves ---------- */
+
+.plugins-groups {
+ display: grid;
+ gap: 28px;
+}
+
+/* The MCP section renders as a direct panel child after the grouped inventory. */
+.plugins-panel > .plugins-group {
+ margin-top: 28px;
+}
+
+.plugins-group__heading {
+ display: flex;
+ align-items: baseline;
+ gap: 8px;
+ margin-bottom: 11px;
+ padding: 0 2px;
+}
+
+.plugins-group__heading :is(h2, h3) {
+ margin: 0;
+ color: var(--text-strong);
+ font-size: var(--control-ui-text-md);
+ font-weight: 650;
+ letter-spacing: -0.01em;
+}
+
+.plugins-group__heading > span {
+ color: var(--muted);
+ font-size: var(--control-ui-text-xs);
+}
+
+.plugins-group__actions {
+ display: inline-flex;
+ align-items: center;
+ gap: 10px;
+ margin-left: auto;
+}
+
+.plugins-group__actions .btn span {
+ width: 14px;
+ height: 14px;
+}
+
+.plugins-group__link {
+ color: var(--muted);
+ font-size: var(--control-ui-text-xs);
+ text-decoration: none;
+}
+
+.plugins-group__link:hover {
+ color: var(--text-strong);
+ text-decoration: underline;
+}
+
+.plugins-group__link-icon {
+ display: inline-flex;
+ width: 11px;
+ height: 11px;
+ margin-left: 3px;
+ vertical-align: -1px;
+}
+
+.plugins-group__hint {
+ margin: -4px 2px 12px;
+ color: var(--muted);
+ font-size: var(--control-ui-text-xs);
+ line-height: 1.5;
+}
+
+/* ---------- art tiles + covers ---------- */
+
+.plugins-tile {
+ display: grid;
+ width: 44px;
+ height: 44px;
+ flex: 0 0 44px;
+ place-items: center;
+ overflow: hidden;
+ border: 1px solid var(--border);
+ border-radius: 12px;
+ background: var(--bg-elevated);
+ box-shadow: var(--shadow-sm);
+}
+
+.plugins-tile img {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+}
+
+.plugins-tile--fallback {
+ background: linear-gradient(135deg, var(--plugins-art-a), var(--plugins-art-b));
+ border-color: transparent;
+ color: rgb(255 255 255 / 92%);
+ font-family: var(--mono);
+ font-size: var(--control-ui-text-sm);
+ font-weight: 700;
+ letter-spacing: -0.04em;
+ text-shadow: 0 1px 2px rgb(0 0 0 / 25%);
+}
+
+.plugins-tile--fallback svg,
+.plugins-cover--fallback svg {
+ width: 21px;
+ height: 21px;
+ fill: none;
+ stroke: currentColor;
+ stroke-width: 1.6px;
+ stroke-linecap: round;
+ stroke-linejoin: round;
+}
+
+.plugins-cover {
+ display: grid;
+ width: 100%;
+ aspect-ratio: 16 / 9;
+ place-items: center;
+ overflow: hidden;
+ border-radius: calc(var(--radius-lg) - 4px);
+ background: var(--bg-elevated);
+}
+
+.plugins-cover img {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ transition: transform var(--duration-slow) var(--ease-out);
+}
+
+@media (hover: hover) {
+ .plugins-card:hover .plugins-cover img {
+ transform: scale(1.03);
+ }
+}
+
+.plugins-cover--fallback {
+ background: linear-gradient(135deg, var(--plugins-art-a), var(--plugins-art-b));
+ color: rgb(255 255 255 / 92%);
+ font-family: var(--mono);
+ font-size: 22px;
+ font-weight: 700;
+ letter-spacing: -0.03em;
+ text-shadow: 0 1px 3px rgb(0 0 0 / 25%);
+}
+
+/* ---------- store cards ---------- */
+
+.plugins-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(min(230px, 100%), 1fr));
+ gap: 12px;
+}
+
+.plugins-grid--featured {
+ grid-template-columns: repeat(auto-fill, minmax(min(264px, 100%), 1fr));
+}
+
+.plugins-card {
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+ min-width: 0;
+ border: 1px solid var(--border);
+ border-radius: var(--radius-lg);
+ padding: 10px 10px 12px;
+ background: linear-gradient(135deg, var(--card-highlight), transparent 42%), var(--card);
+ box-shadow: var(--shadow-sm);
+ transition:
+ border-color var(--duration-normal) var(--ease-out),
+ transform var(--duration-normal) var(--ease-out),
+ box-shadow var(--duration-normal) var(--ease-out);
+}
+
+@media (hover: hover) {
+ .plugins-card:hover {
+ border-color: var(--border-strong);
+ box-shadow: var(--shadow-md);
+ transform: translateY(-1px);
+ }
+}
+
+.plugins-card__body {
+ display: grid;
+ flex: 1 1 auto;
+ gap: 4px;
+ min-width: 0;
+ padding: 0 4px;
+}
+
+.plugins-card__title-row {
+ display: flex;
+ align-items: baseline;
+ gap: 7px;
+ min-width: 0;
+}
+
+.plugins-card__title-row :is(h2, h3) {
+ min-width: 0;
+ margin: 0;
+ overflow: hidden;
+ color: var(--text-strong);
+ font-size: var(--control-ui-text-md);
+ font-weight: 650;
+ letter-spacing: -0.015em;
+ line-height: 1.35;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.plugins-version {
+ flex: 0 0 auto;
+ color: var(--muted);
+ font-family: var(--mono);
+ font-size: var(--control-ui-text-xs);
+}
+
+.plugins-card__body p {
+ display: -webkit-box;
+ margin: 0;
+ overflow: hidden;
+ color: var(--muted);
+ font-size: var(--control-ui-text-sm);
+ line-height: 1.45;
+ -webkit-box-orient: vertical;
+ -webkit-line-clamp: 2;
+}
+
+.plugins-card__meta {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ margin-top: 4px;
+ overflow: hidden;
+ color: var(--muted);
+ font-size: var(--control-ui-text-xs);
+ white-space: nowrap;
+}
+
+.plugins-card__meta > span:not(.plugins-state, .plugins-badge)::before {
+ content: "·";
+ margin-right: 6px;
+ color: var(--border-hover);
+}
+
+.plugins-card__meta > span:first-child::before {
+ content: none;
+}
+
+.plugins-card__footer {
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+ padding: 0 4px;
+}
+
+/* ---------- inventory rows ---------- */
+
+.plugins-rows {
+ display: grid;
+ gap: 8px;
+ /* Two columns as soon as the panel can fit them; single column below. */
+ grid-template-columns: repeat(auto-fill, minmax(min(520px, 100%), 1fr));
+}
+
+.plugins-row {
+ display: grid;
+ grid-template-columns: auto minmax(0, 1fr) auto;
+ align-items: center;
+ gap: 12px;
+ min-width: 0;
+ border: 1px solid var(--border);
+ border-radius: var(--radius-lg);
+ padding: 10px 12px;
+ background: linear-gradient(135deg, var(--card-highlight), transparent 42%), var(--card);
+ transition: border-color var(--duration-normal) var(--ease-out);
+}
+
+.plugins-row--clickable,
+.plugins-card--clickable {
+ cursor: pointer;
+}
+
+@media (hover: hover) {
+ .plugins-row:hover {
+ border-color: var(--border-strong);
+ }
+}
+
+.plugins-row--error {
+ border-color: color-mix(in srgb, var(--danger) 45%, var(--border));
+}
+
+.plugins-row__copy {
+ min-width: 0;
+}
+
+.plugins-row__title {
+ display: flex;
+ align-items: baseline;
+ gap: 7px;
+ min-width: 0;
+}
+
+.plugins-row__title h3 {
+ min-width: 0;
+ margin: 0;
+ overflow: hidden;
+ color: var(--text-strong);
+ font-size: var(--control-ui-text-sm);
+ font-weight: 640;
+ letter-spacing: -0.01em;
+ line-height: 1.35;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.plugins-row__copy p {
+ margin: 2px 0 0;
+ overflow: hidden;
+ color: var(--muted);
+ font-size: var(--control-ui-text-xs);
+ line-height: 1.45;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.plugins-row__target {
+ font-family: var(--mono);
+}
+
+.plugins-row__meta {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ margin-top: 4px;
+ overflow: hidden;
+ color: var(--muted);
+ font-size: var(--control-ui-text-xs);
+ white-space: nowrap;
+}
+
+.plugins-row__meta > span:not(:first-child)::before {
+ content: "·";
+ margin-right: 6px;
+ color: var(--border-hover);
+}
+
+.plugins-row__package {
+ overflow: hidden;
+ font-family: var(--mono);
+ text-overflow: ellipsis;
+}
+
+.plugins-row__actions {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ justify-self: end;
+}
+
+.plugins-remove-confirm {
+ display: inline-flex;
+ align-items: center;
+ gap: 8px;
+ color: var(--danger);
+ font-size: var(--control-ui-text-xs);
+ white-space: nowrap;
+}
+
+.plugins-remove-confirm .btn.danger {
+ border-color: color-mix(in srgb, var(--danger) 55%, var(--border));
+ background: var(--danger-subtle);
+ color: var(--danger);
+}
+
+/* ---------- badges + state ---------- */
+
+.plugins-state,
+.plugins-badge {
+ display: inline-flex;
+ align-items: center;
+ gap: 4px;
+ border-radius: var(--radius-full);
+ padding: 3px 7px;
+ background: var(--bg-muted);
+ color: var(--text-strong);
+ font-size: var(--control-ui-text-xs);
+ font-weight: 620;
+ line-height: 1.1;
+}
+
+.plugins-state--enabled {
+ background: var(--ok-subtle);
+ color: var(--ok);
+}
+
+.plugins-state--error {
+ background: var(--danger-subtle);
+ color: var(--danger);
+}
+
+.plugins-badge {
+ background: var(--accent-2-subtle);
+}
+
+.plugins-badge--mcp {
+ background: var(--accent-subtle);
+ color: var(--accent);
+}
+
+.plugins-badge--verified {
+ background: var(--ok-subtle);
+ color: var(--ok);
+}
+
+.plugins-badge svg {
+ width: 11px;
+ height: 11px;
+}
+
+.plugins-downloads {
+ display: inline-flex;
+ align-items: center;
+ gap: 4px;
+}
+
+.plugins-downloads svg {
+ width: 12px;
+ height: 12px;
+}
+
+.plugins-install {
+ min-width: 78px;
+}
+
+.plugins-action-note {
+ color: var(--muted);
+ font-size: var(--control-ui-text-xs);
+}
+
+.plugins-action-note--ok {
+ display: inline-flex;
+ align-items: center;
+ gap: 5px;
+ color: var(--ok);
+ font-weight: 620;
+}
+
+.plugins-action-note--ok svg {
+ width: 13px;
+ height: 13px;
+}
+
+/* ---------- actions menu ---------- */
+
+.plugins-actions-menu {
+ position: relative;
+ display: inline-flex;
+}
+
+.plugins-kebab {
+ width: 30px;
+ height: 30px;
+ padding: 6px;
+ color: var(--muted);
+}
+
+.plugins-kebab[aria-expanded="true"] {
+ background: var(--bg-hover);
+ color: var(--text-strong);
+}
+
+.plugins-menu {
+ position: absolute;
+ top: calc(100% + 4px);
+ right: 0;
+ z-index: 30;
+ display: grid;
+ min-width: 168px;
+ gap: 2px;
+ border: 1px solid var(--border-strong);
+ border-radius: var(--radius-md);
+ padding: 4px;
+ background: var(--popover);
+ box-shadow: var(--shadow-lg);
+ animation: scale-in var(--duration-fast) var(--ease-out);
+}
+
+.plugins-menu__item {
+ display: flex;
+ align-items: center;
+ gap: 9px;
+ min-height: 32px;
+ border: 0;
+ border-radius: var(--radius-sm);
+ padding: 0 10px;
+ background: transparent;
+ color: var(--text-strong);
+ font-size: var(--control-ui-text-sm);
+ text-align: left;
+ cursor: pointer;
+ white-space: nowrap;
+}
+
+.plugins-menu__item:hover:not(:disabled),
+.plugins-menu__item:focus-visible {
+ background: var(--bg-hover);
+ outline: none;
+}
+
+.plugins-menu__item:disabled {
+ color: var(--muted);
+ cursor: not-allowed;
+ opacity: 0.55;
+}
+
+.plugins-menu__item--danger {
+ color: var(--danger);
+}
+
+.plugins-menu__item--danger:hover:not(:disabled) {
+ background: var(--danger-subtle);
+}
+
+.plugins-menu__icon {
+ display: inline-flex;
+ width: 14px;
+ height: 14px;
+ flex: 0 0 auto;
+}
+
+/* ---------- detail overlay ---------- */
+
+.plugins-detail-backdrop {
+ position: fixed;
+ inset: 0;
+ z-index: 60;
+ display: grid;
+ place-items: center;
+ padding: 24px;
+ background: color-mix(in srgb, var(--bg) 62%, transparent);
+ backdrop-filter: blur(6px);
+ animation: fade-in var(--duration-fast) var(--ease-out);
+}
+
+.plugins-detail {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ width: min(680px, 100%);
+ max-height: min(85vh, 860px);
+ overflow-y: auto;
+ border: 1px solid var(--border-strong);
+ border-radius: var(--radius-xl);
+ background: var(--popover);
+ box-shadow: var(--shadow-xl);
+ animation: scale-in var(--duration-normal) var(--ease-out);
+}
+
+.plugins-detail .plugins-cover {
+ border-radius: 0;
+ flex: 0 0 auto;
+}
+
+.plugins-detail__close {
+ position: absolute;
+ top: 12px;
+ right: 12px;
+ z-index: 2;
+ width: 32px;
+ height: 32px;
+ padding: 7px;
+ background: color-mix(in srgb, var(--bg) 55%, transparent);
+ backdrop-filter: blur(4px);
+}
+
+.plugins-detail__body {
+ display: grid;
+ gap: 14px;
+ padding: 18px 20px 22px;
+}
+
+.plugins-detail__title {
+ display: flex;
+ align-items: baseline;
+ flex-wrap: wrap;
+ gap: 9px;
+}
+
+.plugins-detail__title h2 {
+ margin: 0;
+ color: var(--text-strong);
+ font-size: 20px;
+ font-weight: 680;
+ letter-spacing: -0.02em;
+}
+
+.plugins-detail__description {
+ margin: 0;
+ color: var(--text);
+ font-size: var(--control-ui-text-sm);
+ line-height: 1.6;
+}
+
+.plugins-detail__actions {
+ display: flex;
+ align-items: center;
+ flex-wrap: wrap;
+ gap: 8px;
+}
+
+.plugins-detail__remove {
+ display: inline-flex;
+ align-items: center;
+ gap: 7px;
+ color: var(--danger);
+}
+
+.plugins-detail__remove span {
+ width: 14px;
+ height: 14px;
+}
+
+.plugins-detail__remove:hover:not(:disabled) {
+ border-color: color-mix(in srgb, var(--danger) 45%, var(--border));
+ background: var(--danger-subtle);
+}
+
+.plugins-detail__meta {
+ display: grid;
+ gap: 0;
+ border-top: 1px solid var(--border);
+}
+
+.plugins-detail__meta-row {
+ display: grid;
+ grid-template-columns: 130px minmax(0, 1fr);
+ gap: 12px;
+ border-bottom: 1px solid var(--border);
+ padding: 9px 2px;
+}
+
+.plugins-detail__meta-label {
+ color: var(--muted);
+ font-size: var(--control-ui-text-sm);
+}
+
+.plugins-detail__meta-value {
+ min-width: 0;
+ overflow: hidden;
+ color: var(--text-strong);
+ font-size: var(--control-ui-text-sm);
+ text-overflow: ellipsis;
+}
+
+.plugins-detail__meta-value code {
+ font-family: var(--mono);
+ font-size: var(--control-ui-text-xs);
+}
+
+/* ---------- MCP form ---------- */
+
+.plugins-mcp-form {
+ display: grid;
+ grid-template-columns: minmax(140px, 220px) minmax(0, 1fr) auto;
+ gap: 10px;
+ align-items: end;
+ margin-bottom: 12px;
+ border: 1px solid var(--border);
+ border-radius: var(--radius-lg);
+ padding: 12px;
+ background: var(--bg-elevated);
+}
+
+.plugins-mcp-form label {
+ display: grid;
+ gap: 5px;
+ min-width: 0;
+}
+
+.plugins-mcp-form label span {
+ color: var(--muted);
+ font-size: var(--control-ui-text-xs);
+ font-weight: 580;
+}
+
+.plugins-mcp-form input {
+ min-width: 0;
+ height: 36px;
+ border: 1px solid var(--border-strong);
+ border-radius: var(--radius-md);
+ padding: 0 10px;
+ background: var(--card);
+ color: var(--text-strong);
+ font-size: var(--control-ui-text-sm);
+}
+
+.plugins-mcp-form input:focus-visible {
+ border-color: var(--ring);
+ outline: none;
+ box-shadow: var(--focus-ring);
+}
+
+.plugins-mcp-form__actions {
+ display: flex;
+ gap: 8px;
+}
+
+.plugins-mcp-empty {
+ border: 1px dashed var(--border);
+ border-radius: var(--radius-lg);
+ padding: 18px;
+ color: var(--muted);
+ font-size: var(--control-ui-text-sm);
+ text-align: center;
+}
+
+/* ---------- messages / empty / errors ---------- */
+
+.plugins-row-message {
+ grid-column: 1 / -1;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 12px;
+ border-radius: var(--radius-md);
+ padding: 8px 10px;
+ background: var(--ok-subtle);
+ color: var(--ok);
+ font-size: var(--control-ui-text-xs);
+ line-height: 1.45;
+ white-space: pre-wrap;
+}
+
+.plugins-row-message--error {
+ background: var(--danger-subtle);
+ color: var(--danger);
+}
+
+.plugins-row-message .btn {
+ flex: 0 0 auto;
+ color: var(--text-strong);
+}
+
+.plugins-empty,
+.plugins-search-state {
+ display: grid;
+ min-height: 260px;
+ place-items: center;
+ align-content: center;
+ padding: 32px;
+ color: var(--muted);
+ text-align: center;
+}
+
+.plugins-empty__icon {
+ width: 32px;
+ height: 32px;
+ margin-bottom: 12px;
+ color: var(--border-hover);
+}
+
+.plugins-empty h2 {
+ margin: 0;
+ color: var(--text-strong);
+ font-size: var(--control-ui-text-lg);
+ font-weight: 620;
+}
+
+.plugins-empty p {
+ max-width: 420px;
+ margin: 6px 0 0;
+ font-size: var(--control-ui-text-sm);
+ line-height: 1.55;
+}
+
+.plugins-search-state {
+ font-size: var(--control-ui-text-sm);
+}
+
+.plugins-search-state--error {
+ color: var(--danger);
+}
+
+.plugins-page-error {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 12px;
+ margin-top: 14px;
+ border: 1px solid color-mix(in srgb, var(--danger) 32%, var(--border));
+ border-radius: var(--radius-md);
+ padding: 10px 12px;
+ background: var(--danger-subtle);
+ color: var(--danger);
+ font-size: var(--control-ui-text-sm);
+}
+
+/* ---------- responsive ---------- */
+
+@media (max-width: 768px) {
+ .plugins-content-header {
+ display: flex;
+ }
+
+ .plugins-workspace {
+ padding: 2px 0 40px;
+ }
+
+ .plugins-toolbar {
+ align-items: stretch;
+ flex-direction: column;
+ }
+
+ .plugins-search {
+ flex-basis: auto;
+ min-width: 0;
+ }
+
+ .plugins-toolbar__actions {
+ justify-content: space-between;
+ }
+
+ .plugins-mcp-form {
+ grid-template-columns: minmax(0, 1fr);
+ align-items: stretch;
+ }
+}
+
+@media (max-width: 560px) {
+ .plugins-detail-backdrop {
+ padding: 10px;
+ }
+
+ .plugins-row {
+ grid-template-columns: auto minmax(0, 1fr);
+ }
+
+ .plugins-row__actions {
+ grid-column: 1 / -1;
+ justify-content: space-between;
+ justify-self: stretch;
+ width: 100%;
+ }
+
+ .plugins-remove-confirm {
+ flex-wrap: wrap;
+ white-space: normal;
+ }
+
+ .plugins-row-message {
+ align-items: stretch;
+ flex-direction: column;
+ }
+
+ .plugins-row-message .btn {
+ width: 100%;
+ min-height: 40px;
+ }
+
+ .plugins-card__footer .plugins-install {
+ width: 100%;
+ min-height: 40px;
+ }
+}
+
+/* ---------- connector use-case subgroups ---------- */
+
+.plugins-subgroup {
+ margin-top: 6px;
+}
+
+.plugins-subgroup + .plugins-subgroup {
+ margin-top: 18px;
+}
+
+.plugins-subgroup__heading {
+ margin: 0 2px 9px;
+ color: var(--muted-strong);
+ font-size: var(--control-ui-text-sm);
+ font-weight: 620;
+ letter-spacing: -0.005em;
+}