|
|
@@ -330,7 +330,7 @@
|
|
|
#topo .cluster-frame:hover .frame { stroke-width: 2.2; }
|
|
|
#topo .fchip { cursor: pointer; }
|
|
|
#topo .fchip:hover rect { stroke-width: 2; }
|
|
|
- #topo .fchip.down rect, #topo .fchip.down text { opacity: .55; }
|
|
|
+ #topo .fchip.down { filter: saturate(.5); }
|
|
|
#topo .frame { stroke-width: 1.5; transition: opacity .4s; }
|
|
|
#topo .cluster-frame.down .frame { stroke-dasharray: 5 4; opacity: .5; }
|
|
|
#topo .fchip rect { fill: var(--panel); stroke-width: 1.2; }
|
|
|
@@ -927,11 +927,11 @@ function topoFrames(snap) {
|
|
|
for (const r of rects) {
|
|
|
state.topoGroupTitles[r.g.clusters[0].name] = r.g.clusters.map((c) => c.name).join(" · ");
|
|
|
}
|
|
|
- // pass 1: frame rectangles (all of them first — no frame edge ever
|
|
|
- // crosses a chip); pass 2: chips on top
|
|
|
- let out = "";
|
|
|
+ // two layers: frame rects (below cables/devices) and chips (topmost —
|
|
|
+ // opaque badges, nothing shows through, always clickable)
|
|
|
+ let frames = "", chips = "";
|
|
|
for (const r of rects) {
|
|
|
- out += `<g class="cluster-frame" data-cluster="${esc(r.g.clusters[0].name)}">
|
|
|
+ frames += `<g class="cluster-frame" data-cluster="${esc(r.g.clusters[0].name)}">
|
|
|
<title>${esc(r.g.clusters.map((c) => c.name).join(" · "))}</title>
|
|
|
<rect class="frame" style="stroke:${r.hue};fill:color-mix(in srgb, ${r.hue} 6%, transparent)"
|
|
|
x="${r.x}" y="${r.y}" width="${r.w}" height="${r.h}" rx="14"/>
|
|
|
@@ -940,7 +940,7 @@ function topoFrames(snap) {
|
|
|
for (const r of rects) {
|
|
|
for (const c of r.g.clusters) {
|
|
|
const chip = bands.get(r.y).find((x) => x.c === c);
|
|
|
- out += `<g class="fchip" data-cluster="${esc(c.name)}" transform="translate(${chip.x},${r.y - 8})">
|
|
|
+ chips += `<g class="fchip" data-cluster="${esc(c.name)}" transform="translate(${chip.x},${r.y - 8})">
|
|
|
<title>${esc(c.name)}</title>
|
|
|
<rect width="${chip.cw}" height="16" rx="8" style="stroke:${c._hue}"/>
|
|
|
<circle class="cdot" cx="10" cy="8" r="3.5"/>
|
|
|
@@ -948,7 +948,7 @@ function topoFrames(snap) {
|
|
|
</g>`;
|
|
|
}
|
|
|
}
|
|
|
- return out;
|
|
|
+ return { frames, chips };
|
|
|
}
|
|
|
|
|
|
function cablesSvg(t) {
|
|
|
@@ -1062,8 +1062,9 @@ function renderTopo(snap) {
|
|
|
const sig = topoSig(t);
|
|
|
if (state.topoSig !== sig) {
|
|
|
state.topoSig = sig;
|
|
|
+ const tf = topoFrames(snap);
|
|
|
host.innerHTML = `<svg viewBox="0 0 ${TG_W} ${TG_H}" preserveAspectRatio="xMidYMid meet">
|
|
|
- ${topoFrames(snap)}${cablesSvg(t)}${switchesSvg(t)}${devsSvg(t)}${legendSvg()}
|
|
|
+ ${tf.frames}${cablesSvg(t)}${switchesSvg(t)}${devsSvg(t)}${legendSvg()}${tf.chips}
|
|
|
</svg>`;
|
|
|
for (const g of host.querySelectorAll("[data-cluster]")) {
|
|
|
g.onclick = () => {
|