/* The maps and what sits on them. A map is an SVG (the land, drawn in WORLD units, ≈ 1 km) under an overlay of HTML buttons (the seals of the regions, the pins of the cities,
   the dots of the missions), so the buttons can be real buttons: focus, labels, glass. Both follow one camera (js/map/camera.js, js/map/view.js).
   Colours and paints come from the design system (tokens, and the ids ds-sea, ds-gloss and ds-waves defined by its defs.js). */

.map { position: absolute; inset: 0; overflow: hidden; touch-action: none; -webkit-user-select: none; user-select: none; cursor: grab; background: var(--map-sea-1); }
.map.dragging { cursor: grabbing; }
.map.is-fitting > svg, .map.is-fitting > .ov-layer { visibility: hidden; }
.map > svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.ds-defs { position: absolute; width: 0; height: 0; overflow: hidden; }
.map:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; border-radius: 0; }

/* ---- the land, as SVG. Strokes keep their width on screen whatever the zoom (vector-effect). */
.m-sea { fill: var(--map-sea-1); fill: url(#ds-sea); }
.m-waves { fill: url(#ds-waves); pointer-events: none; }
.m-ctx { fill: var(--map-land); fill-opacity: .6; stroke: var(--map-edge); stroke-width: 1; vector-effect: non-scaling-stroke; stroke-linejoin: round; pointer-events: none; }
.m-region { fill: var(--lv); fill-opacity: .55; stroke: var(--map-edge); stroke-width: 1.4; vector-effect: non-scaling-stroke; stroke-linejoin: round; cursor: pointer;
  transition: fill-opacity var(--d3) var(--ease), opacity var(--d3) var(--ease); }
.m-region[data-state="open"] { fill-opacity: 1; }
.m-region[data-state="done"] { fill-opacity: 1; }
.m-region.is-solo { cursor: default; }
.m-gloss { fill: url(#ds-gloss); stroke: none; pointer-events: none; }
.m-gloss.is-locked { opacity: .35; }
/* a level touched in the bar: its regions stay, the others step back */
.map[data-hl] .m-region, .map[data-hl] .m-gloss { opacity: .2; }
.map[data-hl="A1"] .m-region[data-level="A1"], .map[data-hl="A1"] .m-gloss[data-level="A1"],
.map[data-hl="A2"] .m-region[data-level="A2"], .map[data-hl="A2"] .m-gloss[data-level="A2"],
.map[data-hl="B1"] .m-region[data-level="B1"], .map[data-hl="B1"] .m-gloss[data-level="B1"],
.map[data-hl="B2"] .m-region[data-level="B2"], .map[data-hl="B2"] .m-gloss[data-level="B2"],
.map[data-hl="M"] .m-region[data-level="M"], .map[data-hl="M"] .m-gloss[data-level="M"] { opacity: 1; }
.map[data-hl="A1"] .m-region[data-level="A1"], .map[data-hl="A2"] .m-region[data-level="A2"], .map[data-hl="B1"] .m-region[data-level="B1"],
.map[data-hl="B2"] .m-region[data-level="B2"], .map[data-hl="M"] .m-region[data-level="M"] { fill-opacity: 1; stroke-width: 2.4; }
.map[data-hl] .ov.is-seal { opacity: .35; }
.map[data-hl="A1"] .ov.is-seal[data-level="A1"], .map[data-hl="A2"] .ov.is-seal[data-level="A2"], .map[data-hl="B1"] .ov.is-seal[data-level="B1"],
.map[data-hl="B2"] .ov.is-seal[data-level="B2"], .map[data-hl="M"] .ov.is-seal[data-level="M"] { opacity: 1; }
.m-journey { fill: none; stroke: var(--map-route); stroke-width: 1.6; stroke-dasharray: 2 7; stroke-linecap: round; vector-effect: non-scaling-stroke; opacity: .35; pointer-events: none; }
/* the route between the cities: a light halo under dots. Dots are a dash of length 0 with round ends. */
.m-halo { fill: none; stroke: var(--map-halo); stroke-width: 8; stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke; pointer-events: none; }
.m-route { fill: none; stroke: var(--map-route); stroke-width: 3.6; stroke-dasharray: 0.1 9; stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke; pointer-events: none; }
.m-route.is-done { stroke: var(--map-route-done); }
.m-glow { fill: none; stroke: var(--glass-edge-hi); stroke-width: 3; vector-effect: non-scaling-stroke; stroke-linejoin: round; pointer-events: none; opacity: .9; }

/* ---- the overlay: an HTML layer over the SVG. Each .ov is an anchor (a point, moved with a transform by view.js); its children sit around that point. */
.ov-layer { position: absolute; inset: 0; pointer-events: none; overflow: hidden; }
.ov { position: absolute; left: 0; top: 0; width: 0; height: 0; will-change: transform; pointer-events: none; }
.ov > * { pointer-events: auto; }
.seal, .pin, .node { --size: 30px; position: absolute; left: calc(var(--size) / -2); top: calc(var(--size) / -2); width: var(--size); height: var(--size); display: grid; place-items: center; border-radius: 50%;
  font-weight: 800; font-variant-numeric: tabular-nums; line-height: 1; color: var(--text); background: var(--surface); user-select: none;
  box-shadow: 0 0 0 2.5px var(--lv, var(--border)), 0 0 0 4.5px var(--glass-edge-hi), var(--shadow-sm);
  transition: transform var(--d2) var(--ease-spring), box-shadow var(--d2) var(--ease), background var(--d2) var(--ease); }
.seal { font-size: 13px; }
.pin { --size: calc(var(--pin) * var(--k, 1)); font-size: calc(15px * var(--k, 1)); }
.node { --size: calc(var(--node) * var(--k, 1)); font-size: calc(19px * var(--k, 1)); }       /* --k: the city's stage is smaller on a narrow phone, and so are its dots (set by the screen) */
.seal:active, .pin:active, .node:active { transform: scale(.9); }
/* locked: frosted, with a lock; done: the "ok" colour, with a check; open: white with the level's ring (and a pulse for the one to do next).
   On the map of Italy a locked region has only a small lock on its tile, so the small northern regions are not buried under badges. */
.seal[data-state="locked"], .pin[data-state="locked"], .node[data-state="locked"] { background: var(--node-locked); color: var(--node-locked-ink);
  box-shadow: 0 0 0 2px var(--glass-edge), var(--shadow-sm); }
.seal[data-state="locked"] { --size: 22px; background: var(--glass-reg-bg); box-shadow: 0 0 0 1.5px var(--glass-edge), var(--shadow-sm); }
.seal[data-state="done"], .pin[data-state="done"], .node[data-state="done"] { background: var(--ok); color: var(--ok-contrast);
  box-shadow: 0 0 0 2.5px var(--glass-edge-hi), var(--shadow-sm); }
.seal.is-current { --size: 36px; font-size: 15px; }
.seal svg, .pin svg, .node svg { stroke-width: 2.2; }
.seal[data-state="locked"] svg { width: 12px; height: 12px; stroke-width: 2.4; }
.seal.is-current::after, .pin.is-current::after, .node.is-current::after { content: ''; position: absolute; inset: -9px; border-radius: 50%; border: 3px solid var(--lv, var(--accent)); opacity: 0; animation: ring 1.9s var(--ease) infinite; pointer-events: none; }
@keyframes ring { 0% { transform: scale(.72); opacity: .9; } 100% { transform: scale(1.18); opacity: 0; } }
.shake { animation: shake .42s var(--ease); }
@keyframes shake { 20% { transform: translateX(-5px); } 40% { transform: translateX(5px); } 60% { transform: translateX(-3px); } 80% { transform: translateX(3px); } }
.ov { --half: 16px; }
.ov.is-seal { --half: 19px; }
.ov.is-pin { --half: calc(var(--pin) / 2); }
.lbl { position: absolute; width: max-content; max-width: 132px; text-align: center; font-size: 12px; font-weight: 700; line-height: 1.15; color: var(--map-label);
  text-shadow: 0 0 3px var(--map-halo), 0 0 6px var(--map-halo), 0 0 9px var(--map-halo); pointer-events: none; }
.lbl small { display: block; font-size: 11px; font-weight: 600; opacity: .8; }
.lbl, .lbl.s-below { left: 0; top: calc(var(--half) + 6px); transform: translateX(-50%); }
.lbl.s-above { top: auto; bottom: calc(var(--half) + 6px); left: 0; transform: translateX(-50%); }
.lbl.s-right { left: calc(var(--half) + 6px); top: 0; transform: translateY(-50%); text-align: left; }
.lbl.s-left { left: auto; right: calc(var(--half) + 6px); top: 0; transform: translateY(-50%); text-align: right; }
.lbl.s-below-right { left: calc(var(--half) * .7 + 3px); top: calc(var(--half) * .7 + 3px); transform: none; text-align: left; }
.lbl.s-below-left { left: auto; right: calc(var(--half) * .7 + 3px); top: calc(var(--half) * .7 + 3px); transform: none; text-align: right; }
.lbl.s-above-right { left: calc(var(--half) * .7 + 3px); top: auto; bottom: calc(var(--half) * .7 + 3px); transform: none; text-align: left; }
.lbl.s-above-left { left: auto; right: calc(var(--half) * .7 + 3px); top: auto; bottom: calc(var(--half) * .7 + 3px); transform: none; text-align: right; }
/* the names: always for what is to do next, for all of them once the map is zoomed in (data-labels, set by the screen) */
.map .lbl { transition: opacity var(--d2) var(--ease); }
.map .lbl:not(.keep) { opacity: 0; }
.map:not([data-labels]) .lbl small { display: none; }
.map[data-labels] .lbl.fits, .map .lbl.keep { opacity: 1; }
.hint { position: absolute; left: 24px; top: -42px; width: max-content; max-width: 190px; padding: var(--s2) var(--s3); border-radius: var(--r-l); font-size: var(--t-sm); font-weight: 600; text-align: center; line-height: 1.25;
  animation: bob 2.2s var(--ease) infinite; pointer-events: none; }
@keyframes bob { 0%, 100% { translate: 0 0; } 50% { translate: 4px 0; } }

/* ---- the city: a drawn map of the town in a portrait stage; the stage is sized by js (the largest 9:16 box that fits), the mission dots are placed in percentages of it */
.c-wrap { position: absolute; left: 0; right: 0; top: var(--c-top, 0px); bottom: var(--c-bottom, 0px); display: grid; place-items: center; }
.c-stage { position: relative; width: var(--c-w, 100%); height: var(--c-h, 100%); border-radius: var(--r-xl); overflow: hidden; box-shadow: var(--glass-shadow), 0 0 0 1px var(--glass-edge); background: var(--city-land); }
.c-art { position: absolute; inset: 0; width: 100%; height: 100%; }
.c-stage .ov { transform: none; }
.c-land { fill: var(--city-land); }
.c-water { fill: var(--city-water); }
.c-shore { fill: none; stroke: var(--map-halo); stroke-width: 3; opacity: .8; }
.c-road { fill: none; stroke: var(--city-road); stroke-linecap: round; stroke-linejoin: round; }
.c-roadbg { fill: var(--city-road); }
.c-plaza { fill: var(--city-land); stroke: var(--city-road); stroke-width: 7; }
.c-river { fill: none; stroke: var(--city-water); stroke-linecap: round; stroke-linejoin: round; }
.c-bank { fill: none; stroke: var(--map-halo); stroke-linecap: round; stroke-linejoin: round; opacity: .85; }
.c-block-1 { fill: var(--city-block-1); } .c-block-2 { fill: var(--city-block-2); } .c-block-3 { fill: var(--city-block-3); }
.c-park { fill: var(--city-park); }
.c-tree { fill: var(--city-park); stroke: var(--glass-edge-lo); stroke-width: .6; }
.c-lm { fill: var(--city-landmark); } .c-lm2 { fill: var(--city-landmark-2); }
.c-lm-line { fill: none; stroke: var(--city-landmark); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.c-lm-ground { fill: var(--glass-edge-lo); }
.c-bridge { fill: none; stroke: var(--city-road); stroke-width: 11; stroke-linecap: butt; }
.c-bridge-edge { fill: none; stroke: var(--city-block-3); stroke-width: 14; stroke-linecap: butt; }
.c-mountain { fill: var(--city-block-3); stroke: var(--glass-edge-hi); stroke-width: 1; stroke-linejoin: round; }
.c-route .m-halo { stroke-width: 11; }
.c-route .m-route { stroke-width: 4.2; stroke-dasharray: 0.1 11; vector-effect: none; }
.c-route .m-halo { vector-effect: none; }
.c-flag { font-size: 11px; font-weight: 800; letter-spacing: .02em; fill: var(--map-label); paint-order: stroke; stroke: var(--map-halo); stroke-width: 4px; stroke-linejoin: round; }
.char { display: flex; align-items: center; gap: var(--s3); }
.avatar-slot { width: 56px; height: 56px; flex: none; border-radius: 50%; display: grid; place-items: center; background: var(--accent-soft); color: var(--accent); box-shadow: inset 0 0 0 2px var(--glass-edge-hi), var(--shadow-sm); }
.char-text { min-width: 0; display: grid; gap: 2px; }
.char-text .title { font-size: 19px; }
.char-text .meta { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; }
