/* ==========================================================================
   Map — the world as a halftone on the page, with two floating layers:
   the countries panel (left) and the shared zoom control (bottom right).
   The ground is a canvas drawn by map.js in --ink at rising density where work
   has been done; an open country turns its land to --stroke and the rest to
   --stroke-faint. Marks are HTML: one per site, sized by power and toned by
   stage in ink and stroke; one count per country while its sites are gathered,
   its area their summed power (map.js sets --dz).
   The dark-red dot is the needs-you marker, once per thing that waits.
   ========================================================================== */
@property --mp-sc { syntax: "<number>"; inherits: true; initial-value: 1; }

.view-map { overflow: hidden; }
.mp { position: absolute; inset: 0; overflow: hidden; }

/* ---------- Canvas ---------- */
.mp-canvas { position: absolute; inset: 0; isolation: isolate; cursor: grab; touch-action: none; user-select: none; -webkit-user-select: none; }
.mp.is-over-country .mp-canvas { cursor: pointer; }
.mp.is-dragging .mp-canvas { cursor: grabbing; }
.mp-ground { position: absolute; inset: 0; width: 100%; height: 100%; }

/* ---------- Marks: a site, or a country's gathered sites ---------- */
.mp-marks { position: absolute; inset: 0; pointer-events: none; }
.mp-mark, .mp-cluster {
  --mp-sc: 1;
  position: absolute; left: 0; top: 0; width: 0; height: 0; padding: 0; border: 0; background: none;
  pointer-events: auto; cursor: pointer; outline: none;
  transition: --mp-sc var(--dur-2) var(--ease), opacity var(--dur-3) var(--ease);
}
.mp-mark {
  --d: 12px; --tone: var(--stroke); --halo: 0 0 0 2px var(--surface);
  --dz: calc(var(--d) * var(--mp-z, 1)); /* the drawn diameter: power, eased by the zoom */
  z-index: var(--z, 1);
}
.mp.is-ready .mp-mark, .mp.is-ready .mp-cluster { animation: mp-in 480ms var(--ease) backwards; }
@keyframes mp-in { from { opacity: 0; --mp-sc: .3; } }
/* Gathering: map.js sets --mp-g from 0 (inside its country's count) to 1 (in its place). */
.mp-g { position: absolute; left: 0; top: 0; opacity: var(--mp-g, 1); transform: scale(calc(.45 + .55 * var(--mp-g, 1))); transform-origin: 0 0; }
/* A comfortable target even for the smallest mark. */
.mp-mark::before { content: ""; position: absolute; left: 0; top: 0; width: max(var(--dz), 26px); height: max(var(--dz), 26px); border-radius: 50%; transform: translate(-50%, -50%); }
.mp-disc {
  position: absolute; left: 0; top: 0; width: var(--dz); height: var(--dz); border-radius: 50%;
  background: var(--tone); box-shadow: var(--halo);
  transform: translate(-50%, -50%) scale(var(--mp-sc));
  transition: width var(--dur-3) var(--ease), height var(--dur-3) var(--ease), background var(--dur-2) var(--ease), box-shadow var(--dur-2) var(--ease);
}
/* The further along, the more ink: new, researching, in conversation; acquisition is ink with a ring. */
.mp-mark.s-new { --tone: var(--stroke-faint); --halo: inset 0 0 0 1px var(--stroke), 0 0 0 2px var(--surface); }
.mp-mark.s-researching { --tone: var(--stroke); }
.mp-mark.s-conversation { --tone: var(--ink); }
.mp-mark.s-acquisition { --tone: var(--ink); --halo: 0 0 0 2px var(--surface), 0 0 0 3.5px var(--ink); }
/* Needs a person: ink, lifted like everything that waits, with the one needs-you marker. */
.mp-mark.s-person { --tone: var(--ink); --halo: 0 0 0 2px var(--surface), var(--raise); }
/* Set aside: hollow. The places worth a second look. */
.mp-mark.s-aside { --tone: var(--surface); --halo: inset 0 0 0 1.5px var(--ink), 0 0 0 1.5px var(--surface); }

.mp-mark.is-hover, .mp-mark:focus-visible { --mp-sc: 1.16; z-index: 100; }
.mp-mark:focus-visible .mp-disc { box-shadow: 0 0 0 2px var(--surface), 0 0 0 3.5px var(--ink); }
/* Another country's sites while one is open: opaque faint discs, cut out of the dots. Quiet, never see-through. */
.mp-mark.is-dim { --tone: var(--stroke-faint); --halo: 0 0 0 1.5px var(--bg); }
.mp-cluster.is-dim .mp-cluster-n { background: var(--stroke-faint); color: var(--ink); box-shadow: 0 0 0 1.5px var(--bg); }
.mp-mark.is-hidden { opacity: 0; --mp-sc: .3; }
.mp-mark.is-hidden, .mp-mark.is-gathered, .mp-cluster.is-open { pointer-events: none; }
.mp-mark.is-hidden::before, .mp-mark.is-gathered::before { display: none; }

/* Corners. Bottom right: an agent at work (an ink dot breathing by size, always full ink) or research a person stopped
   (a still square). Top right: the needs-you marker. The badge sits at its corner through `translate`, so the shared
   breathe-dot (a transform) scales it in place. */
.mp-badge {
  display: none; position: absolute; left: 0; top: 0; width: 7px; height: 7px; pointer-events: none;
  box-shadow: 0 0 0 2px var(--surface);
  translate: calc(var(--dz) * .36 * var(--mp-sc) - 50%) calc(var(--dz) * .36 * var(--mp-sc) - 50%);
}
.mp-mark.is-live .mp-badge { display: block; border-radius: 50%; background: var(--ink); animation: breathe-dot var(--breath) var(--ease-io) infinite; }
.mp-mark.is-stopped .mp-badge { display: block; border-radius: 2px; background: var(--ink); }
.mp-flag.dot {
  display: none; position: absolute; left: 0; top: 0; pointer-events: none;
  box-shadow: 0 0 0 2px var(--surface);
  transform: translate(calc(var(--dz) * .36 * var(--mp-sc) - 50%), calc(var(--dz) * -.36 * var(--mp-sc) - 50%));
}
.mp-mark.is-waiting .mp-flag, .mp-cluster.is-waiting .mp-flag { display: block; }
.mp-mark.is-dim .mp-badge, .mp-mark.is-dim .mp-flag, .mp-cluster.is-dim .mp-flag { visibility: hidden; }

/* A country's sites, gathered: how many, in ink, on a disc whose area is their power. It opens as you come closer or choose the country. */
.mp-cluster { --dz: 22px; z-index: 200; }
.mp-cluster-n {
  position: absolute; left: 0; top: 0; display: grid; place-items: center; width: var(--dz); height: var(--dz); border-radius: 50%;
  background: var(--ink); color: var(--on-ink); box-shadow: 0 0 0 2px var(--surface);
  font-size: var(--fs-meta); font-weight: 400; line-height: 1;
  transform: translate(-50%, -50%) scale(var(--mp-sc));
}
.mp-cluster.is-hover, .mp-cluster:focus-visible { --mp-sc: 1.12; z-index: 201; }
.mp-cluster:focus-visible .mp-cluster-n { box-shadow: 0 0 0 2px var(--surface), 0 0 0 3.5px var(--ink); }

/* The country under the pointer: the shared tooltip, beside the pointer. */
.mp-tip { white-space: nowrap; }

/* ---------- Hover card: name and stage, place, the power facts, then what is happening ---------- */
.mp-card {
  position: absolute; left: 0; top: 0; z-index: 6; width: 320px;
  display: flex; flex-direction: column; gap: 12px; padding: 16px;
  border-radius: var(--r-3); background: var(--surface); box-shadow: var(--shadow-3);
  pointer-events: none; animation: fade-in var(--dur-1) var(--ease);
}
.mp-card-head { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: start; column-gap: 12px; }
.mp-card-name { font-weight: 500; line-height: 20px; }
.mp-card-head > .stage { margin-top: -2px; }
.mp-card-place { grid-column: 1 / -1; line-height: 20px; }
/* Small card: an open fact keeps its words and mark; the next step lives in the site record. */
.mp-card .attr-a.is-open .attr-by { display: none; }
/* Why a site was set aside: the reason, in words, under the facts. */
.mp-card-reason { margin: 0; line-height: 1.5; }

/* ---------- Panel ---------- */
.mp-panel {
  position: absolute; left: 16px; top: 16px; z-index: 5; width: 320px; max-height: calc(100% - 32px);
  display: flex; flex-direction: column; padding: 20px 8px 8px;
  background: var(--surface); border-radius: var(--r-4); box-shadow: var(--shadow-2);
  animation: rise var(--dur-3) var(--ease) both;
}
.mp-body { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.mp-panel.is-switching .mp-head, .mp-panel.is-switching .mp-scroll { animation: swap var(--dur-3) var(--ease); }
.mp-head { display: flex; flex-direction: column; gap: 4px; padding: 0 12px 12px; }
.mp-title-row { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.mp-total { white-space: nowrap; }
.mp-back { align-self: flex-start; margin: -2px 0 8px -2px; }
.mp-back:hover .ic { transform: translateX(-2px); }
.mp-sub { font-size: var(--fs-body); line-height: 1.45; }

.mp-scroll { flex: 1 1 auto; min-height: 0; overflow: auto; padding: 0 4px 6px; margin: 0 -4px; }
.mp-list { gap: 2px; }
/* A country: its name and its power in writing, then how many sites it holds. */
.mp-row { width: 100%; border: 0; background: none; text-align: left; padding: 10px 12px; }
.mp-row .list-row-main { gap: 2px; }
.mp-row.is-hover { background: var(--hover); }
.mp-n { flex: none; min-width: 20px; font-weight: 500; text-align: right; }
.mp-chev { width: 16px; height: 16px; margin: 0 -4px; color: var(--stroke); transition: transform var(--dur-2) var(--ease), color var(--dur-1) var(--ease); }
.mp-row:hover .mp-chev, .mp-row.is-hover .mp-chev { color: var(--ink); transform: translateX(2px); }

/* A site: the needs-you marker when it waits · name · power · certainty mark (its own column, as in the facts), then place
   and stage in words. Everything on the first line sits on one 20 px line; a long name wraps rather than losing its end. */
.mp-site {
  display: grid; grid-template-columns: 10px minmax(0, 1fr) auto 14px; grid-template-areas: "sw name val mk" ". sub sub sub";
  align-items: start; column-gap: 12px; row-gap: 2px; width: 100%; padding: 10px 12px; border: 0; border-radius: var(--r-2);
  background: none; color: inherit; text-align: left; line-height: 20px; cursor: pointer; transition: background var(--dur-1) var(--ease), box-shadow var(--dur-1) var(--ease);
}
.mp-site:hover, .mp-site.is-hover { background: var(--hover); }
.mp-site > .mp-status { grid-area: sw; display: grid; place-items: center; height: 20px; }
.mp-site-name { grid-area: name; min-width: 0; font-weight: 500; overflow-wrap: break-word; }
.mp-val { grid-area: val; font-weight: 500; white-space: nowrap; }
.mp-val.is-open { font-weight: 400; }
.mp-site > .src { grid-area: mk; justify-self: end; margin-top: 4px; }
.mp-site-sub { grid-area: sub; min-width: 0; font-size: var(--fs-meta); line-height: 1.4; }
/* A site that waits for a person: first in the list, a white row lifted with --raise, the needs-you marker in front. */
.mp-site.is-waiting { background: var(--surface); box-shadow: var(--raise); }
.mp-site.is-waiting:hover, .mp-site.is-waiting.is-hover { background: var(--press); }
.mp-site.is-waiting + .mp-site:not(.is-waiting) { margin-top: 6px; }

.mp-note { display: flex; align-items: center; gap: 8px; margin: 12px 12px 4px; font-size: var(--fs-meta); line-height: 1.4; }
.mp-note .ic { flex: none; width: 14px; height: 14px; color: var(--stroke); }

/* Controls that stay put: label left, the shared control right, on one centre line. */
.mp-controls { display: flex; flex-direction: column; gap: 8px; margin: 8px 12px 0; padding: 12px 0 4px; border-top: 1px solid var(--line); }
.mp-control { display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: 32px; }
label.mp-control { cursor: pointer; }
.mp-control-label { display: inline-flex; align-items: center; gap: 8px; white-space: nowrap; }
.mp-control .seg { flex: none; }

/* ---------- Zoom: the shared control, arriving a beat after the panel ---------- */
.mp .zoomctl { animation: rise var(--dur-3) var(--ease) both; animation-delay: 120ms; }
