/* Page specific layout. */
.cols-2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
.chr-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(360px, 1fr)); gap: 16px; }
.chr-card { container: card / inline-size; }
.chr-head, .chead { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-block-end: 10px; flex-wrap: wrap; }
.chr-name { font-size: 16px; font-weight: 600; color: var(--accent); }
.chr-card .kv { margin-block-start: 8px; }
.chr-keys { display: grid; grid-template-columns: repeat(auto-fill, minmax(380px, 1fr)); gap: 16px; }
.feed li { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 12px; padding: 8px 0; border-block-end: 1px solid rgba(27, 42, 77, .6); }
.feed li:last-child { border: 0; }
.feed-name { font-weight: 600; margin-inline-end: auto; }
.rolls { display: grid; gap: 8px; }
.rolls li { display: flex; flex-wrap: wrap; gap: 6px 14px; align-items: center; }

/* map */
.topo-host { min-block-size: 120px; }
.topo { display: block; inline-size: 100%; block-size: auto; overflow: visible; }
.topo text { unicode-bidi: plaintext; font-family: var(--font); }
.topo .frame { fill: var(--surface-2); stroke: var(--line); stroke-width: 1; }
.topo .node.ext .frame { fill: transparent; stroke: var(--idle); stroke-dasharray: 5 4; opacity: .85; }
.topo .node.head .frame, .topo .node.chr .frame, .topo .node.routers .frame { stroke: #27407a; }
.topo .bracket { fill: none; stroke: var(--violet); stroke-width: 2; }
.topo .n-title { font-size: 14px; font-weight: 600; fill: var(--text); text-anchor: middle; }
.topo .n-title.small { font-size: 13px; }
.topo .n-big { font-size: 30px; font-weight: 700; fill: var(--accent); text-anchor: middle; }
.topo .n-sub { font-size: 12px; fill: var(--text-dim); text-anchor: middle; }
.topo .n-sub.st-ok { fill: var(--ok); } .topo .n-sub.st-warn { fill: var(--warn); } .topo .n-sub.st-bad { fill: var(--bad); } .topo .n-sub.st-idle { fill: var(--idle); }
.topo .sdot { fill: var(--tone); }
.topo .sbar { fill: var(--idle); }
.topo .sbar.s-online { fill: var(--ok); } .topo .sbar.s-stale { fill: var(--warn); } .topo .sbar.s-offline { fill: var(--bad); } .topo .sbar.s-never { fill: var(--idle); }
.topo .lnk { fill: none; stroke-width: 2; }
.topo .lnk.live { stroke: var(--ok); } .topo .lnk.down { stroke: var(--bad); } .topo .lnk.unknown { stroke: var(--idle); }
.topo .lnk.planned { stroke: var(--idle); stroke-dasharray: 5 5; stroke-width: 1.5; opacity: .7; }
.topo .lnk-flow { fill: none; stroke: #eafff6; stroke-opacity: .85; stroke-width: 2; stroke-dasharray: 3 15; animation: flow 1.5s linear infinite; }
@keyframes flow { to { stroke-dashoffset: -18; } }
.topo .lbl { font-size: 11px; fill: var(--text-faint); }
.topo .lbl.down { fill: var(--bad); }
.map-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 20px; margin-block-end: 14px; }
.dotwrap { position: relative; }
.dotmap { position: relative; inline-size: 100%; }
.dotmap-canvas { display: block; inline-size: 100%; }
.dotmap-canvas.hit { cursor: pointer; }

/* router page */
.router-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; align-items: start; }
.col { display: grid; gap: 16px; min-inline-size: 0; align-content: start; }
.spark-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 16px 14px; }
.act-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; }
.btn.act { flex-direction: column; gap: 0; padding: 8px 10px; min-block-size: 58px; align-items: flex-start; text-align: start; }
.btn.act .kind { font-weight: 600; color: var(--accent); }
.btn.act.danger .kind { color: var(--bad); }
.btn.act small { color: var(--text-dim); }
.ssh .fake-term { direction: ltr; min-block-size: 92px; padding: 14px; margin-block-end: 12px; background: #02050d; border: 1px dashed var(--line); border-radius: 3px; opacity: .5; font: 13px var(--mono); color: var(--text-faint); user-select: none; }
.caret { display: inline-block; inline-size: 8px; block-size: 15px; background: var(--text-faint); vertical-align: middle; animation: blink 1.1s steps(2, start) infinite; }
@keyframes blink { to { visibility: hidden; } }
.ssh .badge { margin-block-start: 8px; }
.pkgs { display: block; max-block-size: 5em; overflow: auto; }

/* rollouts */
.ro-list { display: grid; gap: 14px; }
.ro-card { padding: 14px; background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--r); display: grid; gap: 10px; }
.ro-head { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 12px; }
.ro-name { font-weight: 600; font-size: 15px; }
.ro-meta { display: flex; flex-wrap: wrap; gap: 4px 20px; font-size: 13px; }
.stages { display: grid; gap: 12px; }
.stage { display: grid; gap: 4px; }
.stage-head { display: flex; justify-content: space-between; gap: 8px; }
.stackbar { display: flex; block-size: 14px; background: var(--bg); border: 1px solid var(--line); border-radius: 3px; overflow: hidden; }
.stackbar.empty { background: transparent; border-style: dashed; }
.piece.s-done, .sw.s-done { background: var(--ok); } .piece.s-failed, .sw.s-failed { background: var(--bad); }
.piece.s-leased, .sw.s-leased { background: var(--accent); } .piece.s-queued, .sw.s-queued { background: var(--warn); } .piece.s-other, .sw.s-other { background: var(--idle); }
.stackbar .piece { display: block; block-size: 100%; min-inline-size: 2px; border: 0; padding: 0; }
.legend { display: flex; flex-wrap: wrap; gap: 4px 14px; color: var(--text-dim); }
.lg { display: inline-flex; align-items: center; gap: 5px; }
.sw { display: inline-block; inline-size: 9px; block-size: 9px; border-radius: 2px; }

@media (max-width: 1099px) {
  .router-grid, .cols-2 { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 719px) {
  .chr-cards, .chr-keys { grid-template-columns: minmax(0, 1fr); }
  .tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .tile-n { font-size: 24px; }
  .spark-grid { grid-template-columns: minmax(0, 1fr); }
  .map-bar { gap: 12px; }
  .stats { gap: 20px; }
}
