/* The code map (js/map.js): shared by every page that draws one -- the website's incident
   stories, Try it and the report viewer, and the VS Code extension's map panel (copied
   there by editors/vscode/sync.js). It uses the page's colour variables (--text, --muted,
   --surface, --accent, --hot, --font, --mono) and sets its own --map-* ones. */

.map { display: block; width: 100%; height: auto; }
.map-box { --map-bg: var(--surface); --map-text: var(--text); --map-muted: var(--muted); --map-dot: #9aa8b8; --map-edge: #9aa8b8; }
.story-stage .map-box { --map-bg: #070c12; --map-text: #dce4ee; --map-muted: #7d8b9c; --map-dot: #5d6d80; --map-edge: #52637a; }
.map .node, .map .edge { transition: opacity .35s ease; }
.map.playing .node:not(.in), .map.playing .edge:not(.in) { opacity: 0; }
.map .col-head {
  font: 700 9.5px var(--font); fill: var(--map-muted); text-anchor: middle;
  text-transform: uppercase; letter-spacing: .08em;
}
.map .edge { fill: none; stroke: var(--map-edge); stroke-width: 1.4; opacity: .5; }
.map .edge.reads { stroke-dasharray: 4 3; }
.map .edge.guess { stroke-dasharray: 1 3; opacity: .35; }
.map .edge.impact.lit {
  stroke: var(--hot); stroke-width: 2.4; opacity: .95; stroke-dasharray: 7 5;
  animation: flow .9s linear infinite;
}
@keyframes flow { to { stroke-dashoffset: -24; } }   /* left to right: the change reaching its callers */
.map .dot { fill: var(--map-dot); stroke: var(--map-bg); stroke-width: 2; transition: fill .4s; }
.map .halo { fill: transparent; transform-box: fill-box; transform-origin: center; }
.map .label {
  font: 600 11.5px var(--font); fill: var(--map-text); text-anchor: middle;
  paint-order: stroke; stroke: var(--map-bg); stroke-width: 4px; stroke-linejoin: round;
}
.map .file {
  font: 9.5px var(--mono); fill: var(--map-muted); text-anchor: middle;
  paint-order: stroke; stroke: var(--map-bg); stroke-width: 4px; stroke-linejoin: round;
}
.map .node.context .label { fill: var(--map-muted); font-weight: 500; }
.map .node.context .dot { opacity: .7; }
.map .score {
  font: 700 10px var(--mono); fill: var(--hot); opacity: 0; transition: opacity .4s;
  paint-order: stroke; stroke: var(--map-bg); stroke-width: 4px;
}
.map .node.changed.lit .dot { fill: var(--accent); }
.map .node.changed.lit .halo { fill: color-mix(in srgb, var(--accent) 25%, transparent); animation: grow 1.4s ease-out 2; }
.map .node.removed .dot { fill: var(--map-bg); stroke: var(--accent); stroke-dasharray: 3 2; }
.map .node.removed .label { text-decoration: line-through; opacity: .75; }
.map .node.affected.lit .dot { fill: var(--hot); fill-opacity: var(--heat); }
.map .node.affected.lit .halo { fill: rgba(255, 107, 94, .14); }
.map .node.affected.lit .score { opacity: 1; }
.map .badge { opacity: 0; transition: opacity .3s; }
.map .badge circle { fill: #ff3b30; }
.map .badge text { fill: #fff; font: 800 10px var(--font); text-anchor: middle; }
.map .node.finding.lit .badge { opacity: 1; }
.map .node.by.lit .dot { fill: var(--who); }                     /* a team map: whose change */
.map .node.by.lit .halo { fill: color-mix(in srgb, var(--who) 25%, transparent); }
.map .node.by-many.lit .dot { stroke: var(--who2); stroke-width: 3; }
.map .node.pickable { cursor: pointer; }
.map .node.pickable:hover .halo, .map .node.pickable:focus-visible .halo { stroke: var(--map-text); stroke-width: 1.5; }
.map .node.pickable:focus { outline: none; }
.map .node.picked .halo { stroke: var(--map-text); stroke-width: 2.5; }
.map .node.finding.lit .halo { stroke: #ff3b30; stroke-width: 2; animation: ring 1.5s ease-out infinite; }
@keyframes grow { from { transform: scale(.4); } to { transform: scale(1); } }
@keyframes ring { from { transform: scale(.5); opacity: 1; } to { transform: scale(1.5); opacity: 0; } }
.map-legend { display: flex; flex-wrap: wrap; gap: 4px 14px; padding: 6px 6px 2px; color: var(--muted); font-size: .74rem; }
.story-stage .map-legend { color: var(--stage-muted); }
.lg { display: inline-block; width: 10px; height: 10px; margin-right: 5px; border-radius: 50%; vertical-align: -1px; }
.lg.changed { background: var(--accent); }
.lg.person { background: var(--who); }
.lg.affected { background: var(--hot); }
.lg.finding { border: 2px solid #ff3b30; }
.lg.spread { width: 18px; height: 0; border-radius: 0; border-top: 2px dashed var(--hot); vertical-align: 3px; }
.map-empty { color: var(--muted); padding: 20px; text-align: center; margin: 0; }

@media (prefers-reduced-motion: reduce) {
  .map .edge.impact.lit, .map .node.finding.lit .halo, .map .node.changed.lit .halo { animation: none; }
}
