/* ============================================================
   WORLD MAP — a chart of the zones, laid out by walking the real
   portal graph (shared/src/worldMapGrid.ts). READ ONLY: no tile
   is a button, because travel is a road you walk.

   The LAYOUT is the previous version of this game's world map —
   a sparse grid inside a click-dragged viewport, empty cells
   drawn as flat boxes so the thing reads as a board rather than
   as a list. The PALETTE is this game's: the same carved panel,
   gold keylines and violet well as the craft and inventory
   ledgers next door.
   ============================================================ */
/* Wide enough for the ten-cell board at its default zoom (626px of tiles) plus the panel's
   own padding — see `ZOOM_DEFAULT`. */
/* WIDE ENOUGH FOR FOUR CREATURE CARDS ON ONE LINE (owner's call). The starting vale has four
   monsters, and at 760px the fourth wrapped onto a second row the moment a player had discovered
   all of them — which grew the panel, moved the board under the cursor and put a scrollbar on the
   side. The window changing shape as a REWARD for progress is exactly backwards.
   Four is the largest pool any zone has (`zoneMonsters.ts`), so this is the whole requirement
   rather than a number that will need raising next zone. */
.rpg-panel--map { width: min(880px, 94vw); }
/* NO SCROLLBAR ON THE MAP. The board inside pans by DRAG, and its own bar is already hidden for
   that reason (`.rpg-map-viewport` below) — but the panel that contains it kept one, because the
   viewport plus the title, the legend and the footnote add up to a little more than `max-height`
   at most window sizes. So there were two scrolling surfaces stacked, one of which showed a bar
   the player must not use: dragging the board and dragging the bar move different things.
   The panel still scrolls (a very short window must be able to reach the footnote); it just does
   not advertise it, and the viewport is trimmed so the overflow is a few pixels rather than a
   reason to scroll at all. */
.rpg-panel--map { scrollbar-width: none; -ms-overflow-style: none; }
.rpg-panel--map::-webkit-scrollbar { width: 0; height: 0; display: none; }
/* The tile size is a variable because the grid's track sizes are written from it in JS
   (`repeat(cols, var(--map-tile))`) — one number, set here, read there. 108px shows a zone's
   read (lake, plaza, road) at a glance without making a five-tile map need scrolling to see. */
/* `--map-tile` is the ZOOM, written from JS (`applyZoom`) and read by the tiles, the empty cells
   and the grid's own track template. One number, one place. The value here is only the fallback
   for a viewport that has not been rendered into yet. */
.rpg-map-viewport { --map-tile: 52px; --map-gap: 6px;
  position: relative; height: min(56vh, 560px); overflow: auto; cursor: grab;
  /* FLEX, so the board can be centred by `margin: auto` on the grid below. Five zones do not fill
     a 650px viewport, and left-aligned they read as a list that ran out rather than as a map with
     room around it. `justify-content: center` was the other option and is the wrong one: in a
     scroll container it centres by clipping the leading overflow, so the moment the world grows
     past the viewport the top-left zones become unreachable. Auto margins do not clip. */
  display: flex;
  user-select: none; -webkit-user-select: none;
  border-radius: var(--r-3); border: 1px solid var(--glass-stroke);
  /* The WELL the map sits in: the same recessed dark the search fields and scroll tracks use, with
     a soft violet bloom at the middle so the centre of the world reads as lit rather than as a flat
     hole cut in the panel. */
  background:
    radial-gradient(120% 80% at 50% 45%, rgba(120,100,200,.16), transparent 65%),
    rgba(10, 8, 26, .55);
  box-shadow: inset 0 2px 10px -4px rgba(0,0,0,.8); }
/* NO SCROLLBARS ON THE MAP (owner's call). `overflow: auto` is kept because the pan gesture drives
   `scrollLeft`/`scrollTop` and a `hidden` container has neither — but the BARS are furniture here:
   the board is dragged, not scrolled, and a browser scrollbar down the edge of a world map reads as
   a document that overflowed rather than as a map with more of it in that direction. Hidden in both
   engines, because Firefox and Chromium do not share a property for it. */
.rpg-map-viewport { scrollbar-width: none; -ms-overflow-style: none; }
.rpg-map-viewport::-webkit-scrollbar { width: 0; height: 0; display: none; }
.rpg-map-viewport.is-dragging { cursor: grabbing; }
/* The stage exists only to give the zoom buttons something to sit ON TOP of: the viewport itself
   scrolls, so a control inside it would slide away with the board. */
.rpg-map-stage { position: relative; }
.rpg-map-zoom { position: absolute; right: 10px; bottom: 10px; z-index: 2;
  display: flex; gap: 4px; }
.rpg-map-zoom-btn { width: 26px; height: 26px; padding: 0; line-height: 1;
  border-radius: var(--r-1, 5px); border: 1px solid var(--glass-stroke);
  background: linear-gradient(180deg, #2b2360, #16113a); color: var(--gold-hi);
  font: 600 15px var(--font-body); cursor: pointer; }
.rpg-map-zoom-btn:hover:not(:disabled) { border-color: var(--gold); }
/* Disabled at the ends of the ladder rather than hidden: a control that vanishes at the limit makes
   the player wonder what they did to lose it. */
.rpg-map-zoom-btn:disabled { opacity: .4; cursor: default; }
.rpg-map-grid { display: grid; gap: var(--map-gap); padding: calc(var(--map-tile) / 2);
  /* POSITIONED, so the dungeon-link overlay can be an absolutely-placed child of it and share its
     zoom transform and its scroll. `offsetLeft` on a tile is measured against this box, which is
     also what makes the measured line ends correct. */
  position: relative;
  margin: auto; }
/* PADDING OF HALF A TILE, and it is not decoration: `centreOnHere` scrolls the current tile to the
   middle of the viewport, and a tile on the map's edge cannot reach the middle unless there is
   scrollable room beyond it. Without this the corner zones open flush against the frame. */

/* UNEXPLORED GROUND. Flat, unlit, no border of its own — the gaps must read as "nothing charted
   here", which means they must not compete with the tiles for attention. */
.rpg-map-empty { display: block; width: var(--map-tile); height: var(--map-tile);
  border-radius: var(--r-2); background: rgba(255,255,255,.025);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.03); }

.rpg-map-tile { position: relative; display: block; overflow: hidden;
  width: var(--map-tile); height: var(--map-tile);
  border-radius: var(--r-2); border: 1px solid var(--glass-stroke-hi, rgba(154,134,232,.28));
  background: rgba(13, 17, 48, .55); color: var(--ink); }
.rpg-map-img { position: absolute; inset: 0; display: block; }
.rpg-map-img img { width: 100%; height: 100%; object-fit: cover; display: block;
  /* The thumbnails are rendered from the game's own sunlit terrain and are BRIGHTER than anything
     else in this panel. Pulled down a touch so a grid of them sits inside the ledger rather than
     glowing off it; the current tile gets its full value back below. */
  filter: saturate(.92) brightness(.86); }
.rpg-map-tile.is-here .rpg-map-img img { filter: none; }

/* The name sits on a scrim over the bottom of the art, not beneath it: a label bar under every
   tile would halve the picture, and the picture is the reason the tile exists. */
.rpg-map-label { position: absolute; left: 0; right: 0; bottom: 0; z-index: 1;
  display: flex; flex-direction: column; gap: 1px; padding: 14px 6px 5px;
  background: linear-gradient(180deg, transparent, rgba(8,6,20,.88) 55%); }
.rpg-map-name { font: 600 11px var(--font-banner); letter-spacing: .04em;
  color: var(--ink); text-shadow: 0 1px 3px rgba(0,0,0,.9);
  /* One line, clipped: a wrapped name would grow the scrim up over the art. */
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* NAMES OFF ON A SMALL BOARD. Below half the largest tile size the label is an ellipsised fragment
   sitting on a scrim that covers a third of the art — see LABEL_MIN_TILE. The pin is a sibling of
   the label, not a child, so it is untouched by this. */
.rpg-map-viewport.is-unlabelled .rpg-map-label { display: none; }

/* THE PIN — where you are standing. Sized off the tile so it is a mark at 40px and a mark at 168px
   rather than a speck at one end and a poster at the other, and floored so the smallest rung still
   shows a readable glyph. Centred on the art; `pointer-events: none` so it never eats the click
   that picks the tile. */
.rpg-map-pin { position: absolute; left: 50%; top: 50%; z-index: 2;
  width: clamp(16px, calc(var(--map-tile) * 0.30), 34px); height: auto;
  transform: translate(-50%, -55%); pointer-events: none;
  color: var(--gold-hi);
  filter: drop-shadow(0 1px 2px rgba(0,0,0,.85)) drop-shadow(0 0 6px var(--gold-glow, rgba(201,164,110,.55))); }
.rpg-map-pin-glyph { display: block; width: 100%; height: auto; }
/* Two-tone: the body is gold, the bead punched out of it dark, so the glyph reads as a pin and not
   as a blob at the sizes it is smallest. */
.rpg-map-pin-glyph path { fill: currentColor; stroke: rgba(8,6,20,.85); stroke-width: 1.1; }
.rpg-map-pin-glyph circle { fill: rgba(8,6,20,.9); }

/* THE KEY. Opposite corner to the zoom buttons, over the board's own top edge — it is a caption for
   the mark, so it sits with the board rather than in the panel's chrome. */
.rpg-map-key { position: absolute; right: 10px; top: 10px; z-index: 2;
  display: flex; align-items: center; gap: 6px;
  padding: 4px 9px 4px 6px; border-radius: var(--r-2);
  border: 1px solid var(--glass-stroke-hi, rgba(154,134,232,.28));
  background: rgba(13, 17, 48, .82);
  font: 600 11px var(--font-banner); letter-spacing: .04em; color: var(--ink);
  pointer-events: none; }
/* In the key the pin is an inline chip, not an overlay on a tile — the position rules above are
   for the board. */
.rpg-map-key .rpg-map-pin { position: static; transform: none; width: 14px; }

/* YOU ARE HERE. Gold, because gold is the one colour in this interface that already means "this is
   live" — the same mark the toolbar's active button and the craft bench's ready recipe carry. The
   glow is what finds it after a drag, when the tile may be anywhere in the viewport. */
/* THE GLOW BELONGS TO THE SELECTION, NOT TO THE FACT (owner's call). The pin is true whether
   or not you are looking at that tile, and lighting it up while you read about somewhere else meant
   two tiles competing to be the one you had chosen. The here-tile keeps its gold BORDER and its
   pin, which are the parts that are a fact — but the ring and the glow only appear when it is also
   the picked one. */
.rpg-map-tile.is-here { border-color: var(--gold); }
.rpg-map-tile.is-here.is-picked {
  box-shadow: 0 0 0 1px var(--gold), 0 0 18px -2px var(--gold-glow, rgba(201,164,110,.55)); }

/* OFF THE ROAD — the zones with no gate, so no cell (see UNGATED_MAP_ZONES). Below the board and
   under their own heading: they are real places with real art, and the only thing the separation
   says is that no road connects them. */
.rpg-map-loose { --map-tile: 108px; display: flex; flex-wrap: wrap; align-items: flex-end;
  gap: var(--sp-3); margin-top: var(--sp-4); }
.rpg-map-loose .rpg-group-title { flex-basis: 100%; }

.rpg-map-foot { display: none; margin: var(--sp-3) 0 0;
  font: italic 13px var(--font-quill); color: var(--ink-quill, #b9aed2); }
.rpg-map-foot.is-shown { display: block; }

/* NO SCROLLBARS (owner's call). The map is DRAGGED, not scrolled — there is a grab cursor on it and
   a pan gesture wired to it — so a pair of bars down the edges was a second, worse way to do the
   same thing, and on a board that is now ten cells square they were on screen permanently.
   The scroll MECHANICS stay: `centreOnHere` and the drag both move `scrollLeft`/`scrollTop`, and
   replacing that with a transform would mean re-deriving the clamping that overflow gives free.
   Only the chrome is hidden — one rule per engine, as before. */
.rpg-map-viewport { scrollbar-width: none; -ms-overflow-style: none; }
.rpg-map-viewport::-webkit-scrollbar { width: 0; height: 0; display: none; }
.rpg-map-viewport::-webkit-scrollbar-button { width: 0; height: 0; display: none; }
.rpg-map-viewport::-webkit-scrollbar-corner { background: transparent; }

