/* Hallmark · component: world-map hero · genre: editorial atlas · theme: tokens.css (obsidian + gold)
 * states: ranked (gold/silver/copper) · floor · nodata · locked · hidden · hover · focus · pulse
 * contrast: labels var(--text-primary) on a dark stroke, legend var(--text-muted) >= 4.5:1 on --map-felt
 *
 * css/modules/world-map.css: styles for js/modules/world-map.js. Only var(--token) values from css/tokens.css; motion is
 * transform / opacity only (CSS transitions re-tween when the JS repaints --s / --o, so a market change never re-ignites).
 *
 * HOTSPOT STATES (.wm-zone[data-state], set by rank.rankZones through world-map.js):
 *   ranked  [data-tier=gold|silver|copper]  filled disc in the coin colour; scale and opacity from --hot-<tier>-scale / --hot-<tier>-opacity;
 *                                           the top three carry the unit label and pulse once after ignition (.is-top).
 *   floor                                   hairline ring, stroke --hot-ring, no fill: every eligible unit is at vendor floor today.
 *   nodata                                  dashed ring, stroke --hot-ring-nodata: no scan priced anything here yet.
 *   locked                                  grey ring at --hot-locked-opacity: the zone starts more than 5 levels above the player.
 *   hidden                                  no ring, no core, label at 35%: no material here matches the chosen professions.
 *   before ignition ([data-lit] absent)     halo at scale .6 and opacity 0; the core and label are invisible.
 * LABELS (.wm-label, HTML over the art so they stay 14px at every width): placed in rank order; a label that would overlap
 *   one already placed gets [data-collide] (visibility hidden) until its hotspot is hovered or focused (.is-hot).
 * LAYOUT RESERVE: [data-module="world-map"]:empty holds the stage's aspect before the module renders, so the hero shifts nothing.
 */

[data-module="world-map"]:empty { aspect-ratio: 3 / 4.2; }
@media (min-width: 900px) { [data-module="world-map"]:empty { aspect-ratio: 3 / 1.25; } }
html[data-version="midnight"] [data-module="world-map"]:empty { aspect-ratio: 3 / 4.8; }
@media (min-width: 700px) { html[data-version="midnight"] [data-module="world-map"]:empty { aspect-ratio: 3 / 1.6; } }

.wm { display: block; }
.wm-figure { margin: 0; }
.wm-empty { padding: var(--space-6) 0; }

/* ---------- stage: two continents, stacked under 900px ---------- */
.wm-stage { display: grid; gap: var(--space-3); }
@media (min-width: 900px) { .wm-stage { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--space-4); } }

.wm-panel {
  position: relative; min-width: 0; overflow: clip; isolation: isolate;
  background: var(--map-felt); border: 1px solid var(--border-subtle); border-radius: var(--radius-card);
}
.wm-panel::after { content: ""; position: absolute; inset: 0; pointer-events: none; background: var(--map-vignette); z-index: 2; }
.wm-art {
  display: block; width: 100%; height: auto; aspect-ratio: 3 / 2;
  opacity: 0; transition: opacity var(--dur-base) var(--ease-out);
}
.wm-art[data-loaded] { opacity: 1; }
.wm-panel .wm-art { filter: brightness(0.72) saturate(0.9); } /* the felt dims the parchment so the coin glows and labels carry */
.wm-continent {
  position: absolute; left: var(--space-3); top: var(--space-2); z-index: 4;
  font-family: var(--font-mono); color: var(--text-secondary); pointer-events: none;
}

/* ---------- SVG overlay ---------- */
.wm-overlay { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 3; overflow: visible; }
.wm-zone { cursor: pointer; outline: none; }
.wm-zone[data-state="hidden"] { pointer-events: none; }
.wm-zone > circle { transform-box: fill-box; transform-origin: center; }
.wm-hit { fill: transparent; stroke: none; }
.wm-halo {
  --s: 1; --o: var(--hot-silver-opacity); --coin: var(--coin-silver);
  fill: url(#wm-glow-silver); stroke: none;
  transform: scale(0.6); opacity: 0;
  transition: transform var(--dur-base) var(--ease-out), opacity var(--dur-base) var(--ease-out);
}
.wm-core {
  fill: var(--coin-silver); stroke: var(--bg-app); stroke-width: 2; opacity: 0;
  transition: opacity var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
}
.wm-zone[data-lit] .wm-halo { transform: scale(var(--s)); opacity: var(--o); }
.wm-zone[data-lit] .wm-core { opacity: 1; }

/* ranked: coin colour, tier scale and opacity */
.wm-zone[data-tier="gold"] .wm-halo { --coin: var(--coin-gold); --s: var(--hot-gold-scale); --o: var(--hot-gold-opacity); fill: url(#wm-glow-gold); }
.wm-zone[data-tier="silver"] .wm-halo { --coin: var(--coin-silver); --s: var(--hot-silver-scale); --o: var(--hot-silver-opacity); fill: url(#wm-glow-silver); }
.wm-zone[data-tier="copper"] .wm-halo { --coin: var(--coin-copper); --s: var(--hot-copper-scale); --o: var(--hot-copper-opacity); fill: url(#wm-glow-copper); }
.wm-zone[data-tier="gold"] .wm-core { fill: var(--coin-gold); }
.wm-zone[data-tier="copper"] .wm-core { fill: var(--coin-copper); }

/* floor: hairline ring */
.wm-zone[data-state="floor"] .wm-halo { --s: 0.5; --o: 1; fill: none; stroke: var(--hot-ring); stroke-width: 1.5; }
.wm-zone[data-state="floor"] .wm-core { fill: var(--hot-ring); }
/* nodata: dashed ring */
.wm-zone[data-state="nodata"] .wm-halo { --s: 0.5; --o: 1; fill: none; stroke: var(--hot-ring-nodata); stroke-width: 1.5; stroke-dasharray: 5 5; }
.wm-zone[data-state="nodata"] .wm-core { fill: var(--hot-ring-nodata); }
/* locked: faint grey ring */
.wm-zone[data-state="locked"] .wm-halo { --s: 0.45; --o: var(--hot-locked-opacity); fill: none; stroke: var(--hot-ring); stroke-width: 1.5; }
.wm-zone[data-state="locked"] .wm-core { fill: var(--hot-ring); opacity: var(--hot-locked-opacity); }
.wm-zone[data-state="locked"][data-lit] .wm-core { opacity: var(--hot-locked-opacity); }
/* hidden: nothing drawn */
.wm-zone[data-state="hidden"] .wm-halo, .wm-zone[data-state="hidden"] .wm-core { opacity: 0; }

/* hover / focus: the ring brightens, never lifts; focus ring is instant */
.wm-zone:hover .wm-halo, .wm-zone:focus-visible .wm-halo { opacity: 1; }
.wm-zone:focus-visible .wm-core { stroke: var(--color-gold); stroke-width: 3; transition: none; }

/* pulse once after ignition (top three) and once on tap; transform + opacity only */
@keyframes wm-pulse {
  0% { transform: scale(1); opacity: 0.8; }
  100% { transform: scale(2.2); opacity: 0; }
}
.wm-zone.is-top[data-lit] .wm-hit, .wm-zone.is-pulse .wm-hit {
  fill: none; stroke: var(--coin-gold); stroke-width: 2; transform-box: fill-box; transform-origin: center;
  animation: wm-pulse var(--dur-slow) var(--ease-out) 1 both;
  animation-delay: var(--dur-base);
}
.wm-zone.is-pulse .wm-hit { animation-delay: 0ms; }

/* ---------- labels: HTML over the art, 14px at every width ---------- */
.wm-labels { position: absolute; inset: 0; z-index: 4; pointer-events: none; }
.wm-label {
  position: absolute; transform: translate(-50%, 4px); display: grid; justify-items: center; gap: 1px;
  padding: 2px 4px; pointer-events: auto; text-decoration: none; text-align: center; max-width: 11em;
  font-size: var(--text-map-label); line-height: 1.2; font-weight: 600; color: var(--text-primary);
  -webkit-text-stroke: 3px var(--bg-app); paint-order: stroke fill;
  text-shadow: 0 0 2px var(--bg-app), 0 0 6px var(--bg-app);
  opacity: 0; transition: opacity var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
}
.wm-label[data-lit] { opacity: 1; transform: translate(-50%, -2px); }
.wm-label[data-state="floor"], .wm-label[data-state="nodata"], .wm-label[data-state="locked"] { font-weight: 500; color: var(--text-secondary); }
.wm-label[data-state="locked"][data-lit] { opacity: 0.55; }
.wm-label[data-state="hidden"][data-lit] { opacity: 0.35; }
.wm-label-name { display: block; }
.wm-label-unit {
  display: none; font-family: var(--font-mono); font-weight: 500; font-size: var(--text-xs); color: var(--coin-gold);
  -webkit-text-stroke: 2px var(--bg-app);
}
.wm-label.has-unit .wm-label-unit { display: block; }
.wm-label.has-unit { margin-top: 6px; }
.wm-label:hover, .wm-label:focus-visible, .wm-label.is-hot { color: var(--color-gold-hover); opacity: 1; z-index: 1; }
.wm-label:focus-visible { outline: 2px solid var(--color-gold); outline-offset: 0; border-radius: var(--radius-control); }

/* density: a label that collides with a higher-ranked one stays hidden until its hotspot is hot */
.wm-label[data-collide] { visibility: hidden; }
.wm-label[data-collide].is-hot { visibility: visible; z-index: 2; }

/* ---------- Midnight: six tiles, tinted by rank ---------- */
.wm-mosaic { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--space-2); }
@media (min-width: 700px) { .wm-mosaic { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-3); } }
.wm-tile {
  position: relative; display: block; min-width: 0; overflow: clip; isolation: isolate; text-decoration: none;
  background: var(--map-felt); border: 1px solid var(--border-subtle); border-radius: var(--radius-card);
}
.wm-tile .wm-art { opacity: 0; }
.wm-tile .wm-art[data-loaded] { opacity: 0.55; }
.wm-tile[data-state="ranked"] .wm-art[data-loaded] { opacity: 0.85; }
.wm-tint {
  position: absolute; inset: 0; z-index: 1; pointer-events: none; mix-blend-mode: screen;
  --coin: var(--coin-silver); background: var(--coin);
  opacity: 0; transition: opacity var(--dur-base) var(--ease-out);
}
.wm-tile[data-lit][data-tier="gold"] .wm-tint { --coin: var(--coin-gold); opacity: calc(var(--hot-inner-alpha) * 0.6); }
.wm-tile[data-lit][data-tier="silver"] .wm-tint { --coin: var(--coin-silver); opacity: calc(var(--hot-inner-alpha) * 0.35); }
.wm-tile[data-lit][data-tier="copper"] .wm-tint { --coin: var(--coin-copper); opacity: calc(var(--hot-inner-alpha) * 0.3); }
.wm-tile[data-state="locked"] .wm-art[data-loaded], .wm-tile[data-state="hidden"] .wm-art[data-loaded] { opacity: var(--hot-locked-opacity); }
.wm-tile[data-state="nodata"] { border-style: dashed; border-color: var(--hot-ring-nodata); }
.wm-tile[data-state="floor"] { border-color: var(--hot-ring); }
.wm-tile-text {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 2; display: grid; gap: 2px; padding: var(--space-2) var(--space-3);
  background: linear-gradient(to top, var(--map-felt) 0%, transparent 100%);
}
.wm-tile-name { font-weight: 700; color: var(--text-primary); font-size: var(--text-sm); overflow-wrap: anywhere; }
.wm-tile-stamp { justify-self: start; padding: 1px 6px; font-family: var(--font-mono); }
.wm-tile-stamp.v-worth { color: var(--v-worth); }
.wm-tile-stamp.v-thin { color: var(--v-thin); }
.wm-tile-stamp.v-floor { color: var(--v-floor); }
.wm-tile-stamp.v-nodata { color: var(--v-nodata); }
.wm-tile-unit { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--coin-gold); }
.wm-tile-unit:empty { display: none; }
.wm-tile:hover .wm-art[data-loaded], .wm-tile:focus-visible .wm-art[data-loaded] { opacity: 1; }
.wm-panel .wm-art { filter: brightness(0.72) saturate(0.9); } /* the felt dims the parchment so the coin glows and labels carry */
.wm-tile:focus-visible { outline: 2px solid var(--color-gold); outline-offset: 2px; }

/* ---------- caption: lede, key, credit (always visible) ---------- */
.wm-caption { display: grid; gap: var(--space-2); padding-top: var(--space-3); }
.wm-lede { margin: 0; min-height: 1.6em; font-family: var(--font-mono); }
.wm-legend { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-4); }
.wm-key { display: inline-flex; align-items: center; gap: 6px; font-size: var(--text-xs); color: var(--text-muted); }
.wm-key-dot { width: 10px; height: 10px; border-radius: var(--radius-full); flex: none; box-sizing: border-box; }
.wm-key[data-key="gold"] .wm-key-dot { background: var(--coin-gold); }
.wm-key[data-key="silver"] .wm-key-dot { background: var(--coin-silver); }
.wm-key[data-key="copper"] .wm-key-dot { background: var(--coin-copper); }
.wm-key[data-key="floor"] .wm-key-dot { border: 1.5px solid var(--hot-ring); }
.wm-key[data-key="nodata"] .wm-key-dot { border: 1.5px dashed var(--hot-ring-nodata); }
.wm-key[data-key="locked"] .wm-key-dot { border: 1.5px solid var(--hot-ring); opacity: var(--hot-locked-opacity); }
.wm .art-credit { margin: 0; }

/* ---------- reduced motion: final state at first paint, nothing moves ---------- */
@media (prefers-reduced-motion: reduce) {
  .wm-art, .wm-halo, .wm-core, .wm-label, .wm-tint { transition: none; }
  .wm-zone.is-top[data-lit] .wm-hit, .wm-zone.is-pulse .wm-hit { animation: none; }
  .wm-label[data-lit] { transform: translate(-50%, -2px); }
}
