/* Look and feel follows the "Data modeling for Defenders" deck: near-black teal, mint/amber/violet, Space Grotesk + JetBrains Mono. */
:root {
  --sans: "Space Grotesk", system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --bg: #0e1418; --bg2: #121a20; --surface: #151e25; --raised: #1a252d; --ink: #e7e6e1; --muted: #8b99a3; --line: #243039;
  --seen: #3ddc97; --notseen: #ffb454; --rogue: #ff6b6b; --accent: #b796ff; --flow: #5f7280;
  --grid: rgba(255,255,255,.035); --glow: 0 0 0 1px rgba(61,220,151,.0);
  --h-aws: #ee6fcf; --h-azure: #5aa9ff; --h-dc0: #a6f5f1; --h-dc1: #3fcdc7; --h-dc2: #1c908b; --h-saas: #e5d85c; --h-external: #8b99a3;
}
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    --bg: #f4f3ee; --bg2: #ecebe4; --surface: #ffffff; --raised: #f7f6f1; --ink: #14201f; --muted: #627078; --line: #d8d6cc;
    --seen: #0f9f66; --notseen: #b9730a; --rogue: #d23f3f; --accent: #7a52d6; --flow: #8a97a3; --grid: rgba(0,0,0,.04);
    --h-aws: #c2318f; --h-azure: #1f6fd1; --h-dc0: #5fcfc9; --h-dc1: #139a95; --h-dc2: #0a5f5c; --h-saas: #9a8a06; --h-external: #627078;
  }
}
:root[data-theme="light"] {
  --bg: #f4f3ee; --bg2: #ecebe4; --surface: #ffffff; --raised: #f7f6f1; --ink: #14201f; --muted: #627078; --line: #d8d6cc;
  --seen: #0f9f66; --notseen: #b9730a; --rogue: #d23f3f; --accent: #7a52d6; --flow: #8a97a3; --grid: rgba(0,0,0,.04);
  --h-aws: #c2318f; --h-azure: #1f6fd1; --h-dc0: #5fcfc9; --h-dc1: #139a95; --h-dc2: #0a5f5c; --h-saas: #9a8a06; --h-external: #627078;
}
* { box-sizing: border-box; }
body {
  margin: 0; color: var(--ink); font: 14px/1.5 var(--sans); -webkit-font-smoothing: antialiased;
  background: radial-gradient(1200px 500px at 15% -10%, color-mix(in srgb, var(--seen) 7%, transparent), transparent 70%), var(--bg);
}
::selection { background: color-mix(in srgb, var(--accent) 40%, transparent); }

header {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px 24px;
  padding: 16px 24px; border-bottom: 1px solid var(--line); background: color-mix(in srgb, var(--bg) 80%, transparent);
  backdrop-filter: blur(6px); position: sticky; top: 0; z-index: 5;
}
h1 { margin: 0; font-size: 20px; font-weight: 700; letter-spacing: -.01em; display: flex; align-items: baseline; gap: 12px; }
h1::before { content: ""; width: 9px; height: 9px; border-radius: 50%; background: var(--seen); box-shadow: 0 0 10px var(--seen); align-self: center; }
h1 .sub { color: var(--muted); font: 400 12px var(--mono); letter-spacing: .02em; }
.legend { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; font: 12px var(--mono); color: var(--muted); }
.legend > span { display: inline-flex; align-items: center; gap: 7px; padding: 3px 10px; border: 1px solid var(--line); border-radius: 999px; background: var(--surface); }
.legend > span.stamp { border-color: transparent; background: none; font-variant-numeric: tabular-nums; }
.dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; background: var(--muted); }
.dot.h-aws { background: var(--h-aws); } .dot.h-azure { background: var(--h-azure); } .dot.h-dc0 { background: var(--h-dc0); } .dot.h-dc1 { background: var(--h-dc1); } .dot.h-dc2 { background: var(--h-dc2); } .dot.h-saas { background: var(--h-saas); } .dot.h-external { background: var(--h-external); }
.dot.seen { background: var(--seen); box-shadow: 0 0 8px var(--seen); } .dot.notseen { background: var(--notseen); } .dot.rogue { background: var(--rogue); box-shadow: 0 0 8px var(--rogue); }

main { display: grid; grid-template-columns: minmax(0, 1fr) 360px; gap: 20px; padding: 20px 24px; align-items: start; }
@media (max-width: 1000px) { main { grid-template-columns: 1fr; padding: 16px; } }
#topology, #panel { background: var(--surface); border: 1px solid var(--line); border-radius: 12px; }
#topology {
  padding: 12px; overflow-x: auto;
  background-image: radial-gradient(var(--grid) 1px, transparent 1px); background-size: 18px 18px; background-color: var(--surface);
}
svg { display: block; min-width: 960px; width: 100%; height: auto; }
svg text { font-family: var(--mono); }

.zone rect { fill: color-mix(in srgb, var(--bg2) 55%, transparent); stroke: var(--line); }
.zone text.zname { fill: var(--muted); font-size: 10px; letter-spacing: .12em; text-transform: uppercase; }
.node rect { fill: var(--raised); stroke: var(--line); rx: 6; cursor: pointer; transition: stroke .15s, fill .15s; }
.node:hover rect, .node.sel rect { stroke: var(--accent); stroke-width: 1.5; fill: color-mix(in srgb, var(--accent) 10%, var(--raised)); }
.node:focus-visible { outline: none; } .node:focus-visible rect { stroke: var(--accent); stroke-width: 2; }
.node text { fill: var(--ink); font-size: 11.5px; pointer-events: none; }
.node.jewel rect { stroke: var(--notseen); stroke-width: 1.2; }
.flow { fill: none; stroke: var(--flow); stroke-width: var(--w, .8px); opacity: var(--o, .3); transition: opacity .15s; stroke-linecap: round; }
.flow.hl { stroke: var(--accent); opacity: .95; stroke-width: calc(var(--w, .8px) + 1px); }
.dim .flow:not(.hl) { opacity: .06; }
.axis line { stroke: var(--line); stroke-width: 1; } .axis path { fill: var(--line); }
.axis text { fill: var(--muted); font-size: 9.5px; letter-spacing: .16em; text-transform: uppercase; }
.zone.t-untrusted rect { stroke: var(--rogue); stroke-dasharray: 5 4; }
.zone.t-low rect { stroke: var(--notseen); stroke-opacity: .7; }
.zone.t-critical rect { stroke: var(--seen); stroke-opacity: .8; stroke-width: 1.4; }

#unmodelled { margin-top: 12px; border-top: 1px solid var(--line); padding-top: 12px; }
#unmodelled h2 { font: 600 11px var(--mono); letter-spacing: .1em; text-transform: uppercase; color: var(--rogue); margin: 0 0 6px; }
#unmodelled ul { margin: 0; padding-left: 16px; } #unmodelled li { font: 12px var(--mono); }

#panel { padding: 18px; position: sticky; top: 84px; max-height: calc(100vh - 104px); overflow-y: auto; scrollbar-width: thin; scrollbar-color: var(--line) transparent; }
#panel h2 { margin: 0 0 4px; font-size: 20px; font-weight: 700; letter-spacing: -.01em; }
#panel .meta { color: var(--muted); font: 12px var(--mono); margin-bottom: 8px; }
#panel h3 { font: 600 10.5px var(--mono); text-transform: uppercase; letter-spacing: .14em; color: var(--muted); margin: 18px 0 6px; padding-top: 12px; border-top: 1px solid var(--line); }
#panel ul { margin: 0; padding-left: 16px; } #panel li { margin: 2px 0; } #panel li::marker { color: var(--line); }
#panel code, code { font: 12px var(--mono); color: var(--accent); word-break: break-all; }
#panel a { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; text-decoration-color: color-mix(in srgb, var(--accent) 45%, transparent); }
#panel a:hover { text-decoration-color: var(--accent); }
#panel a code { text-decoration: none; }
.pill { display: inline-block; padding: 0 9px; border-radius: 999px; font: 11px var(--mono); border: 1px solid currentColor; background: color-mix(in srgb, currentColor 12%, transparent); }
.pill.seen { color: var(--seen); } .pill.notseen { color: var(--notseen); } .pill.rogue { color: var(--rogue); }
.hint { color: var(--muted); }

.logbtn { display: flex; align-items: center; gap: 10px; width: 100%; padding: 7px 12px; background: var(--raised); color: var(--ink); border: 1px solid var(--line); border-radius: 8px; cursor: pointer; font: inherit; transition: border-color .15s; }
.logbtn:hover:not(:disabled) { border-color: var(--accent); }
.logbtn:disabled { opacity: .6; cursor: default; }
.logbtn .lbl { color: var(--muted); font: 12px var(--mono); white-space: nowrap; } .logbtn .cnt { font: 12px var(--mono); font-variant-numeric: tabular-nums; white-space: nowrap; }
.logbtn svg { flex: 1; height: 28px; min-width: 0; } .logbtn rect.on { fill: var(--seen); } .logbtn rect.off { fill: var(--line); }
.logbtn.quiet rect.off { fill: var(--notseen); opacity: .6; }
.logbtn rect.hit { fill: var(--rogue); } .alertbtn.fired { border-color: var(--rogue); box-shadow: 0 0 14px color-mix(in srgb, var(--rogue) 35%, transparent); }
table.logs { width: 100%; border-collapse: collapse; margin-top: 8px; font: 12px var(--mono); }
table.logs th { text-align: left; color: var(--muted); font-weight: 400; padding: 3px 4px; } table.logs td { padding: 3px 4px; border-top: 1px solid var(--line); }
table.logs td.n, table.logs th:last-child { text-align: right; font-variant-numeric: tabular-nums; } table.logs tr.nodata td { color: var(--notseen); }
table.logs tr.fired td { color: var(--rogue); }
.sev { text-transform: uppercase; font: 600 10px var(--mono); letter-spacing: .06em; }
.sev.low { color: var(--muted); } .sev.medium { color: var(--notseen); } .sev.high, .sev.critical { color: var(--rogue); }

.dot.accent { background: var(--accent); } .node.na { opacity: .45; } .node.na.sel, .node.na:hover { opacity: 1; }

/* panel accordion: summary chips show what needs attention, problems start open */
#panel details { border-top: 1px solid var(--line); margin-top: 10px; padding-top: 8px; }
#panel summary { display: flex; align-items: center; gap: 8px; cursor: pointer; list-style: none; user-select: none; }
#panel summary::-webkit-details-marker { display: none; }
#panel summary::before { content: "▸"; color: var(--muted); font-size: 10px; transition: transform .15s; }
#panel details[open] > summary::before { transform: rotate(90deg); }
#panel summary .t { font: 600 10.5px var(--mono); text-transform: uppercase; letter-spacing: .14em; color: var(--muted); }
#panel summary:hover .t { color: var(--ink); }
#panel summary .sum { margin-left: auto; font: 11px var(--mono); color: var(--muted); }
#panel summary .sum.ok { color: var(--seen); } #panel summary .sum.warn { color: var(--notseen); } #panel summary .sum.bad { color: var(--rogue); }
#panel .dbody { padding: 8px 0 2px 16px; }
#panel .dbody > .meta { margin: 6px 0 2px; }

/* one type scale for the panel: 13px text, 11.5px mono data, 11px chips/labels */
#panel { font-size: 13px; }
#panel .meta, #panel code, #panel table.logs, #panel .logbtn .lbl, #panel .logbtn .cnt { font-size: 11.5px; }
#panel .hint { font-size: 12px; }
#panel .pill { font-size: 11px; }
#panel h2 { font-size: 19px; }

/* details drawer: slides over the right edge on select, so the map keeps the full width */
main { grid-template-columns: minmax(0, 1fr); }
#panel {
  position: fixed; top: 76px; right: 16px; bottom: 16px; width: min(var(--dw), calc(100vw - 32px)); max-height: none; z-index: 4;
  background: color-mix(in srgb, var(--surface) 94%, transparent); backdrop-filter: blur(8px); box-shadow: 0 12px 40px rgba(0,0,0,.45);
  transform: translateX(calc(100% + 24px)); visibility: hidden; transition: transform .22s ease, visibility 0s linear .22s;
}
#panel.open { transform: none; visibility: visible; transition-delay: 0s; }
#panel .close { position: sticky; top: 0; float: right; width: 26px; height: 26px; margin: -4px -4px 0 8px; padding: 0; border: 1px solid var(--line); border-radius: 50%; background: var(--raised); color: var(--muted); font: 16px/1 var(--sans); cursor: pointer; }
#panel .close:hover { color: var(--ink); border-color: var(--accent); }
@media (prefers-reduced-motion: reduce) { #panel { transition: none; } }

/* wide screens: the map makes room for the drawer instead of sitting under it */
main { transition: padding-right .22s ease; }
@media (min-width: 1001px) {
  body.drawer main { padding-right: calc(var(--dw) + 36px); }
  body.drawer #svg { min-width: 620px; }
}
@media (prefers-reduced-motion: reduce) { main { transition: none; } }

/* connections open their flow logs in Kibana: the visible line stays thin, a wide transparent twin takes the click */
.flowhit { fill: none; stroke: transparent; stroke-width: 8; pointer-events: stroke; cursor: pointer; }
.flow.hover { stroke: var(--accent); opacity: .95; stroke-width: 1.8; }
.dim .flow.hover { opacity: .95; }

/* per-connection traffic in the Flows section */
#panel .fl { white-space: nowrap; } #panel .fl .fspark { width: 60px; height: 12px; vertical-align: -1px; }
#panel .fl rect.on { fill: var(--seen); } #panel .fl rect.off { fill: var(--line); } #panel .fl rect.hit { fill: var(--rogue); }
#panel .fl .fc { font: 11.5px var(--mono); font-variant-numeric: tabular-nums; } #panel .fl .fd { font: 11px var(--mono); color: var(--rogue); }
#panel .fl.quiet .fc { color: var(--notseen); }

/* flow health, shown by the Flows lens: quiet = modelled but no traffic for an hour; ghost = blocked or allowed traffic the model does not list */
.flow.ghost, .flowhit.ghost { display: none; } .lens-flows .flow.ghost, .lens-flows .flowhit.ghost { display: inline; }
.lens-flows .flow.quiet { stroke: var(--notseen); stroke-dasharray: 4 3; opacity: .8; }
.lens-flows .flow.blocked, .lens-flows .flow.ghost { stroke: var(--rogue); opacity: .85; stroke-width: 1.4; }
.lens-flows .flow.ghost.dropped { stroke-dasharray: 2 3; }
.lens-flows.dim .flow.ghost, .lens-flows.dim .flow.quiet { opacity: .5; }
#unflows { margin-top: 12px; border-top: 1px solid var(--line); padding-top: 12px; }
#unflows h2 { font: 600 11px var(--mono); letter-spacing: .1em; text-transform: uppercase; color: var(--rogue); margin: 0 0 6px; }
#unflows ul { margin: 0; padding-left: 16px; } #unflows li { font: 12px var(--mono); }
#unflows a { color: var(--accent); text-underline-offset: 2px; }

/* attack lens: the lane right of the datacenter holds secrets, identities and the SaaS directory stand-in; hops are drawn above the map,
   coloured by coverage (green: a rule covers it, amber: logged only, red: blind) and styled by kind (solid flow, dashed secret, dotted identity) */
.lane { display: none; } .lens-attack .lane { display: inline; }
.zone.t-lane rect { stroke: var(--accent); stroke-opacity: .45; stroke-dasharray: 2 4; }
.lens-attack .flow { opacity: .1; }
.lens-attack .node:not(.onpath):not(.imp) { opacity: .4; }
.lens-attack .node.onpath rect { stroke: var(--accent); stroke-width: 1.5; }
.lanenode.imp rect { stroke: var(--notseen); stroke-width: 1.5; stroke-dasharray: 3 2; }
.lanenode.imp { opacity: 1; }
.lens-attack .lanetile { opacity: .8; cursor: pointer; } .lens-attack .lanetile text { fill: var(--muted); font-size: 11px; font-style: italic; }
.lanetile rect { stroke-dasharray: 2 3; fill: transparent; } .lens-attack .lanetile:hover, .lens-attack .lanetile.sel { opacity: 1; }
.linkbtn { font: 11px var(--mono); color: var(--accent); background: none; border: 0; padding: 0 0 0 8px; cursor: pointer; text-decoration: underline; text-underline-offset: 2px; }
.dot.imp { background: transparent; border: 1.5px dashed var(--notseen); }
.atk { pointer-events: none; }
.atkhop { fill: none; stroke-width: 2.4; stroke-linecap: round; opacity: .9; }
.atkhop.k-secret-theft, .atkhop.k-secret-use { stroke-dasharray: 7 4; }
.atkhop.k-identity-assume, .atkhop.k-identity-forge, .atkhop.k-identity-use, .atkhop.k-idp-admin, .atkhop.k-idp-phish { stroke-dasharray: .1 5; stroke-width: 3; }
.atkmark { pointer-events: all; cursor: help; }
.atkmark .mn { fill: var(--ink); font: 600 10.5px var(--mono); }
.atkmark .mw { font: 600 8.5px var(--mono); letter-spacing: .08em; text-transform: uppercase; paint-order: stroke; stroke: var(--bg); stroke-width: 3px; }

#panel select { font: 12px var(--mono); color: var(--ink); background: var(--raised); border: 1px solid var(--line); border-radius: 6px; padding: 1px 6px; }
.atkt, .atkp { display: flex; flex-wrap: wrap; gap: 6px; }
.atkt button, .atkp button { display: inline-flex; align-items: center; gap: 7px; font: 12px var(--mono); color: var(--ink); background: var(--raised); border: 1px solid var(--line); border-radius: 8px; padding: 4px 10px; cursor: pointer; }
.atkt button:hover, .atkp button:hover { border-color: var(--accent); }
.atkt button[aria-pressed="true"], .atkp button[aria-pressed="true"] { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 16%, var(--raised)); }
.atkt .meta, .atkp .meta { margin: 0; }
.atkp { flex-direction: column; } .atkp button { justify-content: flex-start; width: 100%; text-align: left; }
.strip { display: inline-flex; gap: 3px; } .strip .dot { width: 9px; height: 9px; box-shadow: none; }
.atkhops { list-style: none; margin: 0; padding: 0; counter-reset: none; }
.atkhops li { padding: 6px 0 6px 10px; border-left: 2px solid var(--line); margin: 0 0 6px 4px; }
.atkhops li.lv-covered { border-left-color: var(--seen); } .atkhops li.lv-seen { border-left-color: var(--notseen); } .atkhops li.lv-blind { border-left-color: var(--rogue); }
.atkhops .top { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.atkhops .mk { display: inline-grid; place-items: center; width: 18px; height: 18px; border-radius: 50%; border: 2px solid currentColor; font: 600 10px var(--mono); }
.atkhops .lw { font: 600 10px var(--mono); letter-spacing: .08em; text-transform: uppercase; }
.atkhops .seen { color: var(--seen); } .atkhops .notseen { color: var(--notseen); } .atkhops .rogue { color: var(--rogue); }
#panel .atkhops .meta { margin: 1px 0 0; } #panel .meta.gap { color: var(--notseen); }
.atkp button > span:not(.strip) { white-space: nowrap; } .atkp button .meta { white-space: normal; flex: 1; }
.atkt button .nm { white-space: nowrap; }
.atkp button { flex-wrap: wrap; } .atkp button .meta { flex-basis: 100%; }
/* attack lens: every service that is a possible target gets a dashed ring, the chosen one a solid ring */
.lens-attack .node.tgt rect { stroke: var(--accent); stroke-width: 1.2; stroke-dasharray: 3 2; }
.lens-attack .node.tgtcur rect { stroke: var(--accent); stroke-width: 2.4; stroke-dasharray: none; }
.atkt .sev { white-space: nowrap; }
.atkt button .meta { white-space: nowrap; }

/* service tiles: kind icon, short name, lens badge underneath */
.node.tile text.nm { font-size: 9.5px; }
.node.tile text.jw { fill: var(--notseen); font-size: 10px; }
.node.tile .ico { fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; color: var(--muted); pointer-events: none; }
.iconkey { margin: 0 0 8px; font: 11px var(--mono); color: var(--muted); }
.iconkey summary { cursor: pointer; width: fit-content; }
.iconkey div { display: flex; flex-wrap: wrap; gap: 4px 12px; padding: 8px 0 0; }
.iconkey span { display: inline-flex; align-items: center; gap: 5px; }
svg.kico { min-width: 0; width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }

/* focus and context: the hovered, focused or selected service keeps full colour with its neighbours; the rest recedes */
.focusing .node:not(.foc):not(.nb):not(.hop1):not(.hop2):not(.hop3) { opacity: .35; }
.node.nb rect { stroke: var(--accent); stroke-opacity: .55; }
/* reach: shading by distance from the selected service; ◆ paths are bold; a dashed outline means the last step was a secret, not a flow */
.node.hop1 rect { stroke: var(--accent); stroke-opacity: .9; stroke-width: 1.6; } .node.hop2 rect { stroke: var(--accent); stroke-opacity: .7; } .node.hop3 rect { stroke: var(--accent); stroke-opacity: .5; }
.node.hotn rect { stroke-width: 2; } .node.viaid rect { stroke-dasharray: 3 2; }
.reaching .flow.hl:not(.hot) { opacity: .55; } .flow.hot { stroke-width: 2.6; opacity: 1 !important; }
.reachkey { display: inline-flex; gap: 10px; align-items: center; margin-left: 12px; font: 11px var(--mono); color: var(--muted); } .reachkey[hidden] { display: none; }
.reachkey b { color: var(--ink); font-weight: 600; } .reachkey span { display: inline-flex; align-items: center; gap: 4px; } .reachkey .jw { color: var(--notseen); }
.hopsw { width: 10px; height: 10px; border-radius: 3px; border: 1.6px solid var(--accent); display: inline-block; } .hopsw.hop2 { border-color: color-mix(in srgb, var(--accent) 70%, transparent); } .hopsw.hop3 { border-color: color-mix(in srgb, var(--accent) 50%, transparent); }
.toggles { display: flex; gap: 6px; margin-bottom: 6px; }
#panel .miss { color: var(--rogue); }

/* shared services: their inbound edges are drawn on demand; the strip above the map lists them */
.noshared .flow.shared, .noshared .flowhit.shared { display: none; }
.noshared .flow.shared.hl, .noshared .flowhit.shared.hl, .noshared.lens-flows .flow.shared.blocked, .noshared.lens-flows .flowhit.shared.blocked { display: inline; }
.node.shared rect { stroke: var(--accent); stroke-opacity: .45; }
#panel .chips { display: flex; flex-wrap: wrap; gap: 2px 10px; margin: 2px 0 6px; }

/* pan and zoom */
#topology { position: relative; }
#svg { cursor: grab; } #svg.panning { cursor: grabbing; } #svg .node, #svg .flowhit { cursor: pointer; }

/* soft edges; connections inside one zone show for the service in focus (or with the switch above the map) */
.hidezone .flow.inz:not(.hl), .hidezone .flowhit.inz:not(.hl) { display: none; }
.hidezone.lens-flows .flow.inz.blocked, .hidezone.lens-flows .flow.inz.quiet, .hidezone.lens-flows .flowhit.inz.blocked, .hidezone.lens-flows .flowhit.inz.quiet { display: inline; }
.node.tile text.nm { font-size: 8px; letter-spacing: -.1px; }
.node.tile text.jw { font-size: 7.5px; }
.flowhit { stroke-width: 8; }
/* kind colours: the icon (and a faint tint of the tile) carry the kind in the status lens; other lenses recolour by their own question */
:root { --p0: #6aa5ff; --p1: #ff8a5c; --p2: #3ddc97; --p3: #c78bff; --p4: #f2d14b; --p5: #ff6b9a; }
@media (prefers-color-scheme: light) { :root:not([data-theme="dark"]) { --p0: #2a6fe0; --p1: #d5551f; --p2: #0f9f66; --p3: #8a4fd1; --p4: #b08f00; --p5: #d6336c; } }
:root[data-theme="light"] { --p0: #2a6fe0; --p1: #d5551f; --p2: #0f9f66; --p3: #8a4fd1; --p4: #b08f00; --p5: #d6336c; }
.dot.p0 { background: var(--p0); } .dot.p1 { background: var(--p1); } .dot.p2 { background: var(--p2); } .dot.p3 { background: var(--p3); } .dot.p4 { background: var(--p4); } .dot.p5 { background: var(--p5); }
:root { --k-front: #4f9cf5; --k-app: #1fb5b0; --k-data: #e5719f; --k-identity: #9aa83a; --k-ops: #8f9bb3; --k-outside: #d98462; }
.lens-status .node.tile:not(:hover):not(.sel) rect { fill: color-mix(in srgb, var(--kc) 9%, var(--raised)); }
/* a click on stacked connections lets you choose */
.edgemenu { position: absolute; z-index: 3; max-width: 340px; max-height: 260px; overflow: auto; padding: 6px; font: 11px var(--mono); background: var(--raised); border: 1px solid var(--accent); border-radius: 8px; box-shadow: 0 8px 24px rgba(0,0,0,.35); }
.edgemenu .hd { padding: 2px 6px 4px; color: var(--muted); }
.edgemenu a { display: block; overflow: hidden; text-overflow: ellipsis; padding: 3px 6px; border-radius: 5px; color: var(--ink); text-decoration: none; white-space: nowrap; }
.edgemenu a:hover, .edgemenu a:focus-visible { background: color-mix(in srgb, var(--accent) 16%, transparent); outline: none; }
.edgemenu a span { color: var(--muted); }

.scoped .node.out { opacity: .15; }
.scoped .node.in rect { stroke: var(--accent); stroke-width: 1.5; }
.scoped .flow:not(.scopeflow) { opacity: .04; }

/* map controls: every bar above the map is built from the same parts.
   .row = label column + controls; .seg = segmented choice (lens, exposure, zoom); .chip = one toggle (filters, shared services, view options) */
.toolbar, .scopebar, .sharedbar { --h: 24px; font: 11px var(--mono); color: var(--muted); }
.scopebar { display: flex; flex-direction: column; gap: 4px; margin: 0; }
#topology > .row, .scopebar { margin-bottom: 6px; }
.row[hidden], .chip[hidden] { display: none; }
.row { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; min-height: var(--h); }
.row > .lbl { flex: none; width: 66px; font-size: 10px; letter-spacing: .12em; text-transform: uppercase; }
.row .chips { display: inline-flex; flex-wrap: wrap; gap: 4px; flex: 1 1 0; min-width: 0; }
.row .crit.chips { flex: none; }
.row > * + .seg, .row > * + .chips, .row > * + select { margin-left: 8px; } .row > .lbl + * { margin-left: 0; }
.toolbar #zoomctl { margin-left: auto; } .toolbar > .chip { margin-left: 4px; }
.opts { display: inline-flex; flex-wrap: wrap; gap: 4px; }
.seg { display: inline-flex; flex-wrap: wrap; gap: 2px; padding: 2px; border: 1px solid var(--line); border-radius: 999px; background: var(--bg2); }
.seg button, .seg .chip { height: calc(var(--h) - 6px); padding: 0 10px; font: inherit; color: var(--muted); background: none; border: 0; border-radius: 999px; cursor: pointer; transition: color .15s, background .15s; }
.chip { display: inline-flex; align-items: center; gap: 6px; height: var(--h); padding: 0 10px; font: inherit; color: var(--ink); background: var(--raised); border: 1px solid var(--line); border-radius: 999px; cursor: pointer; transition: border-color .15s, background .15s; }
.chip .cnt { color: var(--muted); }
.seg button:hover:not(:disabled), .seg .chip:hover:not(:disabled) { color: var(--ink); } .chip:hover:not(:disabled) { border-color: var(--accent); }
.chip:disabled { opacity: .35; cursor: default; }
.seg button[aria-pressed="true"], .seg .chip[aria-pressed="true"], .chip[aria-pressed="true"], .chip.tog:has(input:checked) { color: var(--ink); background: color-mix(in srgb, var(--accent) 22%, var(--raised)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 55%, transparent); }
.seg .chip[aria-pressed="true"] { border: 0; }
.chip.tog { color: var(--muted); } .chip.tog input { appearance: none; display: none; }
.seg button:focus-visible, .chip:focus-visible, .chip.tog:has(input:focus-visible), .scopebar select:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.scopebar select { height: var(--h); font: inherit; color: var(--ink); background: var(--raised); border: 1px solid var(--line); border-radius: 999px; padding: 0 8px; }
.scopebar .funnel { display: inline-flex; flex-wrap: wrap; align-items: baseline; gap: 2px 8px; font-size: 12px; }
.scopebar .step b { color: var(--ink); font-size: 16px; font-weight: 600; } .scopebar .step.last b { color: var(--accent); }
.scopebar .arrow { color: var(--muted); } .scopebar .err { color: var(--rogue); }
.scopebar .top [data-clear], .scopebar .top [data-clear] ~ .chip { margin-left: 0; } .scopebar .top .funnel { margin-right: auto; }
.facets { display: flex; flex-direction: column; gap: 4px; }
.facets[hidden] { display: none; }
.toolbar > .chip:first-of-type { margin-left: 8px; } .toolbar .chip .cnt:empty { display: none; }
.sharedbar .kico { width: 14px; height: 14px; }
.iconkey summary::marker { color: var(--muted); }

/* controls on a connection */
.ctl { display: inline-block; margin-left: 2px; padding: 0 6px; font: 10px var(--mono); font-style: normal; letter-spacing: .04em; color: var(--accent); border: 1px solid color-mix(in srgb, var(--accent) 45%, transparent); border-radius: 999px; }

.ctl.waf { color: #ff8bd1; } .ctl.mfa { color: #ffb454; } .ctl.edr { color: #3ddc97; }
/* attack lens with a scope: members of the set marked, the rest of the path stays visible */
.lens-attack.scoped .node.out, .lens-attack.scoped .flow:not(.scopeflow) { opacity: 1; }
.lens-attack .node.viaset rect { stroke: var(--accent); stroke-width: 2.4; }
.rank { margin: 4px 0 8px; padding-left: 18px; } .rank li { margin: 2px 0; }
.chip[hidden] { display: none; } a.chip { text-decoration: none; }

/* a thing we know exists but cannot yet name or locate */
.unk { font-size: .75em; padding: 0 .4em; border: 1px dashed currentColor; border-radius: 3px; opacity: .8; }

/* people view: who administers what */

/* Katakri lens: a failing connection is red, the rest recede; findings in the panel */
.lens-compliance .flow { opacity: .22; }
.lens-compliance .flow.noncompliant { stroke: var(--rogue); opacity: .95; stroke-width: 2; }
.ckl { list-style: none; padding: 0; margin: 0 0 6px; } .ckl li { margin: 0 0 8px; }
.ck { display: inline-block; font-size: 10px; padding: 0 6px; border-radius: 8px; border: 1px solid var(--notseen); color: var(--notseen); }
.ck.fail { border-color: var(--rogue); color: var(--rogue); font-weight: 600; }

/* people lens: a tile that is part of a separation-of-duties finding gets an amber outline; the same set as the Scope bar's chip */
.node.sod rect { stroke: var(--notseen); stroke-width: 2; stroke-opacity: 1; }
.dot.sod { background: transparent; border: 1.5px solid var(--notseen); }
#panel .find { margin: 6px 0; padding: 4px 8px; border-left: 3px solid var(--notseen); background: color-mix(in srgb, var(--notseen) 8%, transparent); font-size: 12px; } #panel .find > b { display: block; font-size: 11px; color: var(--muted); }

/* people: the share bar above the map, and the cards in the panel */
.peoplebar { margin: 0 0 6px; flex-wrap: nowrap; gap: 8px; align-items: center; }
.share { flex: 1; min-width: 0; display: flex; gap: 2px; height: 30px; }
.sg { min-width: 0; overflow: hidden; display: flex; align-items: center; justify-content: space-between; gap: 6px; padding: 0 8px; border: 0; border-radius: 5px; font: 600 11px var(--mono); color: var(--bg); cursor: pointer; white-space: nowrap; }
.sg .n { font-weight: 400; opacity: .85; } .sg:hover { filter: brightness(1.12); } .sg.sel { outline: 2px solid var(--ink); outline-offset: 1px; }
.sg.p0 { background: var(--p0); } .sg.p1 { background: var(--p1); } .sg.p2 { background: var(--p2); } .sg.p3 { background: var(--p3); } .sg.p4 { background: var(--p4); } .sg.p5 { background: var(--p5); }
div.sg.none { background: var(--line); color: var(--muted); cursor: default; }
#panel .big { font: 600 22px var(--mono); } #panel .grp { display: flex; flex-wrap: wrap; gap: 2px 8px; margin: 2px 0 6px; } #panel .find.high { border-left-color: var(--rogue); background: color-mix(in srgb, var(--rogue) 8%, transparent); }
#panel a[data-sel], #panel a[data-card] { color: var(--ink); }

.ckh { margin: 10px 0 4px; font-size: 12px; font-weight: 600; color: var(--muted, #888); }
.ckt-root { font-size: 12.5px; } .ckt { margin: 2px 0 2px 10px; border-left: 3px solid var(--axis, #888); padding-left: 6px; }
.ckt > summary { cursor: pointer; } .ckt .ckl { margin: 2px 0 2px 4px; } .ckt .ckl li { margin: 0 0 2px; }
.ckt.st-fail { border-left-color: #d03b3b; } .ckt.st-met { border-left-color: #0ca30c; } .ckt.st-partial { border-left-color: #2a78d6; }
.ckt li.fail { color: #d03b3b; }
#panel details.ckt { border-top: 0; margin: 2px 0 2px 8px; padding: 0 0 0 6px; border-left: 3px solid var(--line); }
#panel details.ckt > summary { display: block; gap: 0; } #panel details.ckt > summary::before { content: none; }
#panel details.ckt > summary .g { display: inline-block; width: 1.2em; }
#panel .ckt .meta { margin: 1px 0 2px; } #panel .ckt-root { margin-left: -8px; }
#panel details.ckt.st-fail { border-left-color: #d03b3b; } #panel details.ckt.st-met { border-left-color: #0ca30c; } #panel details.ckt.st-partial { border-left-color: #2a78d6; }

/* drawer width: 400px, 480 in the attack lens (hops and paths wrap badly narrower); dragging the grip sets --drawer-user and is remembered */
:root { --dw: var(--drawer-user, 400px); } body.atk-drawer { --dw: var(--drawer-user, 480px); }
#panelgrip { display: none; position: fixed; top: 76px; bottom: 16px; right: calc(16px + min(var(--dw), 100vw - 32px) - 4px); width: 8px; z-index: 5; cursor: ew-resize; touch-action: none; border-radius: 4px; }
#panelgrip::after { content: ""; position: absolute; left: 3px; top: 50%; width: 2px; height: 36px; margin-top: -18px; border-radius: 1px; background: var(--line); transition: background .15s; }
#panelgrip:hover::after, #panelgrip:focus-visible::after, body.resizing #panelgrip::after { background: var(--accent); }
body.drawer #panelgrip { display: block; } body.resizing { user-select: none; cursor: ew-resize; } body.resizing main, body.resizing #panel { transition: none; }

/* attack panel: sections like the details drawer, compact hop rows with the evidence behind them */
.asec > summary .t { flex: none; } .asec > summary .sum { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#panel .asec > .dbody > h3:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
#panel details.hop { border-top: 0; margin: 0; padding: 0; }
#panel details.hop > summary { gap: 8px; flex-wrap: wrap; } #panel details.hop > summary::before { content: "▸"; font-size: 9px; }
#panel details.hop > summary b { font-weight: 600; min-width: 0; overflow-wrap: anywhere; }
#panel .hopbody { padding: 2px 0 0 24px; }
.atkhops li { padding: 5px 0 5px 10px; margin-bottom: 4px; }
