// Visual language aligned with SilverBullet's configuration-manager plug // — color tokens, section header style, button style, and border radii // match `silverbullet/plugs/configuration-manager/ui/configuration.scss`. // Dark mode is driven by both `prefers-color-scheme` (for iframes that // don't see the parent's data-theme) AND `html[data-theme="dark"]` (for // when SilverBullet propagates its explicit theme into the iframe). *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } html { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; font-size: 14px; // Chrome colors (background, text, borders, sections, hover, accent) come // from the shared panel-surface palette in components.css. Only the // graph-specific node/edge palette below is defined locally. // Graph palette — node-color tokens are object-graph specific. --gv-node: #111; --gv-node-current: #1e63d8; --gv-node-dim: #9e4705; // missing-link rust --gv-label: #333; --gv-label-dim: #777; --gv-link: #c8c8c8; --gv-link-dim: #e6e6e6; --gv-link-hot: #464cfc; --gv-accent: #650007; // SB meta-color — current-page ring --gv-label-halo: rgba(255, 255, 255, 0.78); --gv-tag-bg: #4070d0; --gv-tag-fg: #ffffff; --gv-tag-border: #2a5099; --gv-untagged: #9e9e9e; } // Dark tokens — same values configuration-manager uses, applied for either // the explicit theme attribute or the user's system preference. @mixin gv-dark-tokens { color-scheme: dark; --gv-node: #fff; --gv-node-current: #6e9bff; --gv-node-dim: #c97c4a; --gv-label: #d8d8d8; --gv-label-dim: #888; --gv-link: #555; --gv-link-dim: #333; --gv-link-hot: #6e74ff; --gv-accent: #d6222e; --gv-label-halo: rgba(30, 30, 30, 0.78); --gv-tag-bg: #5b85e8; --gv-tag-fg: #ffffff; --gv-tag-border: #3868c8; --gv-untagged: #6e6e6e; } html[data-theme="dark"] { @include gv-dark-tokens; } @media (prefers-color-scheme: dark) { html:not([data-theme="light"]) { @include gv-dark-tokens; } } html, body { height: 100%; background: var(--ui-surface-background-color); color: var(--ui-surface-color); } #graph-root { position: absolute; inset: 0; display: flex; flex-direction: column; background: var(--ui-surface-background-color); color: var(--ui-surface-color); // No border/radius: the host modal panel already frames the iframe. overflow: hidden; outline: none; } .graph-root-inner { position: absolute; inset: 0; display: flex; flex-direction: column; outline: none; } .graph-app { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0; } .graph-canvas { position: absolute; inset: 0; } // Floating controls overlay (bottom-right of the canvas stage). // Pan pad on the left, zoom in/out stacked on the right. .graph-controls { position: absolute; bottom: 12px; right: 12px; display: flex; flex-direction: row; align-items: stretch; gap: 8px; z-index: 2; pointer-events: none; // children opt in button { pointer-events: auto; background: var(--ui-surface-background-color); color: var(--ui-surface-color); border: 1px solid var(--ui-surface-border-color); border-radius: 6px; cursor: pointer; width: 28px; height: 28px; display: inline-flex; align-items: center; justify-content: center; font-size: 14px; line-height: 1; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08); &:hover { background: var(--ui-surface-hover-background-color); } &:active { background: var(--ui-surface-section-background-color); } } } .graph-zoom { display: flex; flex-direction: column; gap: 4px; button { flex: 1 1 0; height: auto; // let flex stretch determine the height } } // 3x3 directional pad — middle row has ←, center, →; top/bottom rows // have just the up/down arrow in the middle column. .graph-pan { display: grid; grid-template-columns: repeat(3, 28px); grid-template-rows: repeat(3, 28px); gap: 4px; .graph-pan-up { grid-column: 2; grid-row: 1; } .graph-pan-left { grid-column: 1; grid-row: 2; } .graph-pan-center{ grid-column: 2; grid-row: 2; } .graph-pan-right { grid-column: 3; grid-row: 2; } .graph-pan-down { grid-column: 2; grid-row: 3; } } .gv-app { display: flex; flex-direction: column; height: 100vh; background: var(--ui-surface-background-color); color: var(--ui-surface-color); } .gv-body { display: grid; grid-template-columns: var(--gv-sidebar-width, 230px) 5px minmax(0, 1fr); flex: 1 1 auto; min-height: 0; overflow: hidden; } .gv-resizer { cursor: col-resize; background: transparent; border-left: 1px solid var(--ui-surface-border-color); user-select: none; transition: background 120ms ease; } .gv-resizer:hover, .gv-resizer.dragging { background: var(--ui-accent-color, rgba(70, 76, 252, 0.25)); } .gv-canvas-wrap { position: relative; min-width: 0; min-height: 0; overflow: hidden; } .gv-canvas-wrap .graph-canvas { position: absolute; inset: 0; } /* Object section inside the sidebar (selected node attributes). */ .gv-object-section { margin-top: auto; padding: 6px 14px 10px; border-top: 1px solid var(--ui-surface-border-color); background: var(--ui-surface-background-color); } .gv-object-section .gv-object-header { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding-bottom: 4px; margin-bottom: 4px; border-bottom: 1px solid var(--ui-surface-border-color); font-size: 13px; font-weight: 600; color: var(--ui-surface-color); } .gv-object-section .gv-object-title { display: inline-flex; align-items: center; gap: 8px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .gv-object-section .gv-object-title-link { cursor: pointer; color: var(--ui-accent-color); text-decoration: none; } .gv-object-section .gv-object-title-link:hover { text-decoration: underline; } .gv-object-section .gv-object-body { margin: 0; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px; line-height: 1.45; white-space: pre-wrap; word-break: break-word; color: var(--ui-surface-color); } /* Header — sized roughly like configuration-manager's #cfg-header. */ .gv-header { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 10px 16px; border-bottom: 1px solid var(--ui-surface-border-color); flex-shrink: 0; } .gv-header-title { font-size: 18px; font-weight: 600; margin: 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .gv-header-actions { display: flex; align-items: center; gap: 8px; flex-shrink: 0; } // Toolbar buttons + checkboxes now use the shared `.sb-button` / `.sb-checkbox` // components; only the toggle-label layout and close-button positioning remain // graph-specific. .gv-header-toggle { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: var(--ui-surface-color); user-select: none; cursor: pointer; } // Close button uses the `.sb-button-icon` component; keep only positioning and // the larger glyph size for the `×`. .gv-close-button { margin-left: auto; font-size: 18px; line-height: 1; } /* Ghost-node hover tooltip */ .gv-ghost-tooltip { position: absolute; z-index: 20; max-width: 280px; background: var(--ui-surface-background-color); border: 1px solid var(--ui-surface-border-color); border-radius: 6px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.18); padding: 5px 8px; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; font-size: 12px; color: var(--ui-surface-color); pointer-events: none; line-height: 1.35; } /* Edge hover tooltip */ .gv-edge-tooltip { position: absolute; z-index: 20; max-width: 360px; background: var(--ui-surface-background-color); border: 1px solid var(--ui-surface-border-color); border-radius: 6px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.18); padding: 6px 8px; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; font-size: 12px; color: var(--ui-surface-color); pointer-events: none; line-height: 1.4; } .gv-edge-tooltip-label { font-weight: 600; margin-bottom: 4px; } .gv-edge-tooltip-snippet { font-family: ui-monospace, Menlo, monospace; font-size: 11px; color: var(--ui-surface-color); white-space: pre-wrap; word-break: break-word; max-height: 8em; overflow: hidden; } .gv-edge-tooltip-empty { color: var(--ui-surface-subtle-color); font-style: italic; } /* Sidebar */ .gv-sidebar { border-right: 1px solid var(--ui-surface-border-color); overflow: auto; font-size: 13px; } // Filter sections — title underline matches configuration-manager's // .lib-section-header / .cfg-category-title pattern. .gv-section { padding: 12px 14px 6px; } .gv-section + .gv-section { padding-top: 14px; } .gv-section-header { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding-bottom: 6px; margin-bottom: 4px; border-bottom: 1px solid var(--ui-surface-border-color); font-size: 13px; font-weight: 600; color: var(--ui-surface-subtle-color); cursor: pointer; user-select: none; } .gv-section-title { display: inline-flex; align-items: center; } .gv-twisty { display: inline-block; transition: transform 0.12s; margin-right: 6px; font-size: 10px; color: var(--ui-surface-subtle-color); } .gv-twisty.open { transform: rotate(90deg); } .gv-section-actions { font-size: 11px; letter-spacing: 0.5px; } .gv-section-actions a { cursor: pointer; color: var(--ui-surface-subtle-color); text-decoration: none; } .gv-section-actions a:hover { color: var(--ui-surface-color); text-decoration: underline; } .gv-section-body { padding: 0; } .gv-forces-body { display: flex; flex-direction: column; gap: 8px; padding: 4px 0; } .gv-force-row { display: flex; flex-direction: column; gap: 2px; font-size: 12px; } .gv-force-row input[type="range"] { width: 100%; } .gv-force-label { display: flex; justify-content: space-between; color: var(--ui-surface-subtle-color); } .gv-force-value { font-variant-numeric: tabular-nums; } // Search field uses the shared `.sb-input`; keep only layout here. .gv-section-search { width: 100%; margin: 4px 0 8px; } .gv-row { display: flex; align-items: center; gap: 8px; padding: 3px 0; font-size: 13px; } .gv-count { margin-left: auto; color: var(--ui-surface-subtle-color); font-size: 12px; } .gv-swatch { width: 10px; height: 10px; border-radius: 50%; display: inline-block; flex-shrink: 0; } .gv-tag-row { display: inline-flex; align-items: center; gap: 6px; } .gv-more { display: block; margin-top: 6px; cursor: pointer; font-size: 12px; color: var(--ui-accent-color); } .gv-more:hover { text-decoration: underline; } /* Object view */ .gv-object-view { border-left: 1px solid var(--ui-surface-border-color); background: var(--ui-surface-background-color); overflow: auto; display: flex; flex-direction: column; } .gv-object-view-empty { align-items: center; justify-content: center; color: var(--ui-surface-subtle-color); font-size: 12px; padding: 18px; } .gv-object-header { display: flex; align-items: center; justify-content: space-between; padding: 10px 12px; border-bottom: 1px solid var(--ui-surface-border-color); } .gv-object-title { display: inline-flex; align-items: center; gap: 8px; font-weight: 600; } .gv-object-body { margin: 0; padding: 10px 12px; font-family: ui-monospace, Menlo, monospace; font-size: 12px; line-height: 1.5; white-space: pre-wrap; color: var(--ui-surface-color); } /* Empty graph overlay */ .gv-empty { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; color: var(--ui-surface-subtle-color); font-size: 13px; }