diff --git a/src/psyc/cockpit/static/cockpit.css b/src/psyc/cockpit/static/cockpit.css index 35125f7..a6d5934 100644 --- a/src/psyc/cockpit/static/cockpit.css +++ b/src/psyc/cockpit/static/cockpit.css @@ -1244,3 +1244,313 @@ body.wide #federation-network-graph { height: 720px; } .fn-status-badge-vouched { color: #c4b5fd; border-color: #a78bfa; background: rgba(167,139,250,0.10); } .fn-status-badge-unknown { color: var(--muted); border-color: var(--muted); } .fn-status-badge-blocked { color: var(--red); border-color: var(--red); background: rgba(248,113,113,0.10); } + +/* ---------- federation network — enriched detail layer ---------------- */ + +/* Per-node stat badge: small monospace pill sitting just below the + sublabel ("8 sig · 2 vch · 1 quo"). SVG styled, not a real + HTML pill — we keep it inline with the node group for layout. */ +.fn-stat-badge { + fill: var(--accent); + font-family: ui-monospace, Menlo, Consolas, monospace; + font-size: 11px; + text-anchor: middle; + pointer-events: none; + opacity: 0.85; + letter-spacing: 0.02em; +} +.fn-distance-2 .fn-stat-badge { display: none; } + +/* Corroboration edges — dotted faint accent, lower z visually. */ +.fn-kind-corroborate .fn-edge { + stroke: var(--accent); + stroke-width: 1.1; + stroke-dasharray: 1 5; + stroke-linecap: round; + opacity: 0.28; + animation: fn-corr-pulse 3.2s ease-in-out infinite; +} +.fn-kind-corroborate .fn-edge-label { + fill: rgba(170, 220, 255, 0.55); + font-size: 8.5px; + display: none; /* surfaced via tooltip; chart stays calm */ +} +.fn-kind-corroborate .fn-edge-grp { pointer-events: none; } +@keyframes fn-corr-pulse { + 0%, 100% { stroke-opacity: 0.22; } + 50% { stroke-opacity: 0.45; } +} +@media (prefers-reduced-motion: reduce) { + .fn-kind-corroborate .fn-edge { animation: none; } +} +#federation-network-graph.flow-off .fn-kind-corroborate .fn-edge { animation: none; } + +/* Hover tooltip — absolutely positioned, accent-bordered HUD pill. */ +.fn-tooltip { + position: absolute; + z-index: 50; + background: rgba(15, 17, 21, 0.96); + border: 1px solid var(--accent); + border-radius: 6px; + box-shadow: 0 0 18px var(--accent-glow), 0 6px 22px rgba(0,0,0,0.55); + padding: 8px 10px; + font-family: ui-monospace, Menlo, Consolas, monospace; + font-size: 11px; + color: var(--text); + line-height: 1.45; + pointer-events: none; + max-width: 320px; + white-space: nowrap; + display: none; +} +.fn-tooltip.is-visible { display: block; } +.fn-tooltip-title { + color: var(--accent); + font-family: var(--font-display); + font-size: 12px; + margin-bottom: 4px; + letter-spacing: 0.05em; +} +.fn-tooltip-row { display: flex; gap: 10px; } +.fn-tooltip-row .k { color: var(--muted); min-width: 70px; } +.fn-tooltip-row .v { color: var(--text); } + +/* Search/filter bar above the graph. */ +.fn-search-bar { + display: flex; + align-items: center; + gap: 10px; + margin: 0 0 10px; +} +.fn-search-bar label { + color: var(--muted); + font-size: 11px; + text-transform: uppercase; + letter-spacing: 0.08em; +} +.fn-search-input { + flex: 1; + max-width: 460px; + background: var(--panel-2); + color: var(--text); + border: 1px solid var(--border); + border-radius: 4px; + padding: 6px 10px; + font-family: ui-monospace, Menlo, Consolas, monospace; + font-size: 12px; + transition: border-color 0.15s, box-shadow 0.15s; +} +.fn-search-input:focus { + outline: none; + border-color: var(--accent); + box-shadow: 0 0 0 3px var(--accent-glow); +} +.fn-search-count { color: var(--muted); font-size: 11px; font-family: ui-monospace, Menlo, Consolas, monospace; } + +/* Search dim/highlight states. */ +.fn-node.dimmed { opacity: 0.15; } +.fn-node.match circle, .fn-node.match rect { stroke: var(--amber); stroke-width: 2.4; filter: drop-shadow(0 0 8px rgba(251,191,36,0.55)); } +.fn-edge-grp.dimmed { opacity: 0.08; } + +/* Rich detail card — sits in the existing .topo-detail container. */ +.fn-detail-card { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); + gap: 12px; + margin-top: 10px; +} +.fn-detail-sec { + background: var(--panel-2); + border: 1px solid var(--border); + border-radius: 6px; + padding: 10px 12px; + min-width: 0; /* allow children to wrap */ +} +.fn-detail-sec h4 { + margin: 0 0 8px; + font-size: 11px; + font-family: var(--font-display); + color: var(--muted); + text-transform: uppercase; + letter-spacing: 0.10em; + font-weight: 600; +} +.fn-detail-sec .row { display: flex; justify-content: space-between; gap: 8px; font-size: 12px; padding: 2px 0; } +.fn-detail-sec .row .k { color: var(--muted); } +.fn-detail-sec .row .v { color: var(--text); font-family: ui-monospace, Menlo, Consolas, monospace; word-break: break-all; } +.fn-detail-sec code { + font-size: 11px; + background: var(--panel); + border: 1px solid var(--border); + border-radius: 3px; + padding: 2px 5px; + word-break: break-all; + display: inline-block; +} +.fn-detail-sec .full-fp { font-size: 11px; line-height: 1.55; } +.fn-copy-btn { + display: inline-block; + background: transparent; + color: var(--accent); + border: 1px solid var(--border); + border-radius: 3px; + font-size: 10px; + padding: 1px 6px; + margin-left: 6px; + font-family: ui-monospace, Menlo, Consolas, monospace; + cursor: pointer; + letter-spacing: 0.04em; +} +.fn-copy-btn:hover { border-color: var(--accent); box-shadow: 0 0 8px var(--accent-glow); } + +/* Severity chips inside the Signals section. */ +.fn-sev-row { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 6px; } +.fn-sev-chip { + display: inline-flex; + align-items: center; + gap: 4px; + padding: 2px 8px; + border-radius: 10px; + font-size: 10px; + font-family: ui-monospace, Menlo, Consolas, monospace; + border: 1px solid var(--border); + background: var(--panel); + text-transform: uppercase; + letter-spacing: 0.05em; +} +.fn-sev-chip .n { font-weight: 700; } +.fn-sev-critical { color: var(--red); border-color: var(--red); background: rgba(248,113,113,0.10); } +.fn-sev-high { color: var(--amber); border-color: var(--amber); background: rgba(251,191,36,0.10); } +.fn-sev-medium { color: #fde68a; border-color: rgba(253,224,71,0.55); background: rgba(253,224,71,0.06); } +.fn-sev-low { color: var(--muted); border-color: var(--border); } + +/* IOC-type chips reuse the chip shell with muted accents. */ +.fn-ioc-chip { + display: inline-flex; gap: 4px; padding: 2px 8px; + border-radius: 10px; font-size: 10px; + font-family: ui-monospace, Menlo, Consolas, monospace; + border: 1px solid var(--border); background: var(--panel); + color: var(--text); +} +.fn-ioc-chip .k { color: var(--accent); } +.fn-ioc-chip .n { color: var(--text); font-weight: 700; } + +/* Quorum progress bar. */ +.fn-quorum-bar { + position: relative; + height: 8px; + background: var(--panel); + border: 1px solid var(--border); + border-radius: 4px; + overflow: hidden; + margin-top: 6px; +} +.fn-quorum-fill { + position: absolute; inset: 0 auto 0 0; + background: linear-gradient(90deg, var(--accent), var(--green)); + box-shadow: 0 0 8px var(--accent-glow); +} + +/* Translog list inside the detail card. */ +.fn-trans-list { + list-style: none; margin: 0; padding: 0; + font-family: ui-monospace, Menlo, Consolas, monospace; + font-size: 11px; + max-height: 180px; + overflow-y: auto; +} +.fn-trans-list li { + display: flex; gap: 8px; padding: 3px 0; + border-bottom: 1px dashed var(--border); +} +.fn-trans-list .id { color: var(--muted); min-width: 38px; } +.fn-trans-list .type { color: var(--accent); min-width: 50px; } +.fn-trans-list .ts { color: var(--muted); } +.fn-trans-list .hash { color: var(--text); } + +/* Clickable fingerprint chip — jumps to that peer in the graph. */ +.fn-fp-jump { + font-family: ui-monospace, Menlo, Consolas, monospace; + font-size: 11px; + color: var(--accent); + background: var(--panel); + border: 1px solid var(--border); + border-radius: 3px; + padding: 1px 5px; + cursor: pointer; + margin: 2px 4px 2px 0; + display: inline-block; +} +.fn-fp-jump:hover { border-color: var(--accent); text-shadow: 0 0 8px var(--accent-glow); } + +/* Action buttons inside the detail card. */ +.fn-actions { display: flex; flex-wrap: wrap; gap: 8px; } +.fn-action-btn { + display: inline-block; + padding: 5px 10px; + border: 1px solid var(--border); + border-radius: 4px; + color: var(--accent); + background: var(--panel); + font-size: 12px; + font-family: ui-monospace, Menlo, Consolas, monospace; + cursor: pointer; + text-decoration: none; +} +.fn-action-btn:hover { border-color: var(--accent); box-shadow: 0 0 10px var(--accent-glow); text-decoration: none; } + +/* 24h timeline strip. */ +.fn-timeline-wrap { + margin-top: 18px; + padding: 12px 14px; + background: var(--panel-2); + border: 1px solid var(--border); + border-radius: 6px; +} +.fn-timeline-head { + display: flex; justify-content: space-between; align-items: baseline; + margin-bottom: 8px; +} +.fn-timeline-head h3 { + margin: 0; font-size: 12px; color: var(--muted); + text-transform: uppercase; letter-spacing: 0.10em; font-weight: 600; + font-family: var(--font-display); +} +.fn-timeline-head .meta { color: var(--muted); font-size: 11px; font-family: ui-monospace, Menlo, Consolas, monospace; } +.fn-timeline { + display: flex; + align-items: flex-end; + gap: 2px; + height: 90px; + border-bottom: 1px solid var(--border); + padding-bottom: 2px; +} +.fn-timeline-bar { + flex: 1; + display: flex; + flex-direction: column-reverse; /* segments stack from bottom up */ + align-items: stretch; + min-width: 6px; + height: 100%; + position: relative; + background: rgba(125,133,151,0.04); + border-bottom: 1px solid transparent; + cursor: default; +} +.fn-timeline-bar:hover { background: rgba(30,200,255,0.08); } +.fn-timeline-bar-seg { + width: 100%; + min-height: 1px; + transition: filter 0.15s; +} +.fn-timeline-bar:hover .fn-timeline-bar-seg { filter: brightness(1.25); } +.fn-timeline-axis { + display: flex; gap: 2px; margin-top: 4px; + font-family: ui-monospace, Menlo, Consolas, monospace; + font-size: 9px; color: var(--muted); +} +.fn-timeline-axis span { flex: 1; text-align: center; min-width: 6px; } +.fn-timeline-empty { + color: var(--muted); font-size: 12px; font-style: italic; + text-align: center; padding: 22px 0; +} diff --git a/src/psyc/cockpit/templates/admin_federation_network.html b/src/psyc/cockpit/templates/admin_federation_network.html index 98487cf..5b27c63 100644 --- a/src/psyc/cockpit/templates/admin_federation_network.html +++ b/src/psyc/cockpit/templates/admin_federation_network.html @@ -19,6 +19,12 @@
quorum-met
{{ stats.quorum_met_count }}
+ +
@@ -33,9 +39,10 @@ unknown blocked - drag · scroll to zoom + drag · scroll to zoom · hover for tooltip
+
loading federation network…
@@ -44,6 +51,15 @@

Click any node in the graph above to inspect it.

+
+
+

signals · last 24h

+ +
+
+
+
+

Self fingerprint: {{ fingerprint }}