/* ==========================================================================
   The battle map. Everything is measured in squares: --cell is the only place
   pixels appear, so zooming is one number and nobody moves.
   ========================================================================== */

.panel.map-panel { max-width: none; display: flex; flex-direction: column; gap: 10px; }

.map-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  padding: 8px 10px;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.map-num { font-size: 11px; color: var(--ink-3); display: inline-flex; align-items: center; gap: 4px; }

.map-num input {
  width: 54px;
  padding: 2px 5px;
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  color: var(--ink);
}

.map-scroll {
  flex: 1;
  min-height: 0;
  overflow: auto;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 14px;
  /* the board is the thing being panned, so let the browser do it natively */
  -webkit-overflow-scrolling: touch;
}

/* Parchment rather than a dark panel: an empty board should read as a sheet of
   paper on the table, not as a hole in the page. The mottling is three soft
   radial washes - cheap, resolution-independent, and it prints. */
.map-board {
  position: relative;
  background-color: #e4d5b1;
  background-image:
    radial-gradient(ellipse at 20% 18%, rgba(255, 252, 240, .55), transparent 55%),
    radial-gradient(ellipse at 78% 72%, rgba(140, 106, 58, .20), transparent 55%),
    radial-gradient(ellipse at 58% 8%, rgba(140, 106, 58, .13), transparent 45%),
    linear-gradient(155deg, #f0e4c6 0%, #e2d0a8 55%, #d6c194 100%);
  box-shadow: 0 0 0 1px #a98f60, 0 2px 14px rgba(0, 0, 0, .45),
    inset 0 0 60px rgba(120, 90, 48, .18);
  user-select: none;
}

.map-bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: fill;          /* the DM sets cols/rows to match the image */
  pointer-events: none;
}

/* five-foot squares, drawn rather than tiled so zoom stays crisp */
.map-grid {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image:
    repeating-linear-gradient(to right, rgba(92, 68, 34, .28) 0 1px, transparent 1px var(--cell)),
    repeating-linear-gradient(to bottom, rgba(92, 68, 34, .28) 0 1px, transparent 1px var(--cell));
}

/* over a photograph the same lines would disappear, so they lift */
.map-board:has(.map-bg) .map-grid {
  background-image:
    repeating-linear-gradient(to right, rgba(20, 14, 4, .38) 0 1px, transparent 1px var(--cell)),
    repeating-linear-gradient(to bottom, rgba(20, 14, 4, .38) 0 1px, transparent 1px var(--cell));
}

/* -------------------------------------------------------------------- ink */

/* The drawing. Its viewBox is the grid, so a stroke is measured in feet and
   scales with the zoom rather than against it. */
.map-ink {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  overflow: visible;
}

/* while a pen is out the tokens step aside, so a line can cross a goblin */
.map-board.inking { touch-action: none; cursor: crosshair; }
.map-board.inking .token { pointer-events: none; }
.map-board[data-tool="erase"] { cursor: cell; }

/* -------------------------------------------------------------------- fog

   What the players cannot see yet. Opaque for them - it should look like
   nothing is there rather than like something is being kept from them - and
   see-through for the DM, who has to move creatures around in there before
   anyone is allowed to look. */

.map-fog {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  overflow: visible;
}

.map-fog .fog-cells rect { fill: #0e1013; }

/* the DM sees through it, and the hatch says it is cover rather than terrain */
.map-fog.dm .fog-cells rect { fill: #0e1013; fill-opacity: .62; }

.map-fog.dm { --hatch: rgba(120, 190, 255, .16); }
.map-board[data-tool="cover"] .map-fog.dm .fog-cells rect,
.map-board[data-tool="reveal"] .map-fog.dm .fog-cells rect { fill-opacity: .5; }

/* the box being dragged out, snapped to whole squares */
.fog-pick { fill-opacity: .3; stroke-width: .06; }
.fog-pick.cover { fill: #0e1013; stroke: var(--accent); }
.fog-pick.reveal { fill: #ffe9a8; stroke: var(--accent-2); }

.fog-set { display: inline-flex; gap: 4px; padding-left: 6px; border-left: 1px solid var(--line); }

/* -------------------------------------------------------------------- hud

   The ruler and the eraser's footprint: on the board while a hand is on it,
   gone the moment it lifts. Nothing here is ever saved or sent. Over the
   tokens rather than under them - measuring past a creature is the point. */

.map-hud {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  overflow: visible;
}

/* the square it left, so a move can be judged against where it started */
.map-hud .rule-from {
  fill: none;
  stroke: var(--accent);
  stroke-width: .06;
  stroke-dasharray: .18 .14;
  opacity: .85;
}

.map-hud .rule-line {
  stroke: var(--accent);
  stroke-width: .075;
  stroke-dasharray: .3 .18;
  stroke-linecap: round;
}

.map-hud .rule-end { fill: var(--accent); }

/* the distance has to read over parchment, a photograph and a token alike,
   so it carries its own outline rather than a background it has to be sized
   against - paint-order puts the stroke behind the fill */
.map-hud .rule-ft {
  fill: var(--accent-2);
  stroke: rgba(10, 8, 4, .85);
  stroke-width: .17;
  font-family: var(--sans);
  font-weight: 700;
}

/* a move the table's movement limit would refuse */
.map-hud .rule.over .rule-line,
.map-hud .rule.over .rule-from { stroke: var(--red); }
.map-hud .rule.over .rule-end { fill: var(--red); }
.map-hud .rule.over .rule-ft { fill: #ffb4a6; }

.map-hud .rub {
  fill: rgba(255, 255, 255, .2);
  stroke: rgba(20, 14, 4, .7);
  stroke-width: .05;
  stroke-dasharray: .14 .1;
}

/* ----------------------------------------------------------------- tokens */

/* Placed by the middle of its cell rather than by a row and a column: a hex
   board's rows are staggered and sit closer together than they are wide, so
   an index times a cell is not where anything is. Squares hand over the same
   centres they always had. */
.token {
  position: absolute;
  left: calc(var(--cx) * var(--cell) - var(--cells, 1) * var(--cell) / 2);
  top: calc(var(--cy) * var(--cell) - var(--cells, 1) * var(--cell) / 2);
  width: calc(var(--cells, 1) * var(--cell));
  height: calc(var(--cells, 1) * var(--cell));
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 2px solid var(--line-2);
  background: var(--bg-3);
  overflow: visible;
  cursor: default;
  box-shadow: 0 1px 4px rgba(40, 26, 6, .45);
}

/* A finger on a token is moving it, not scrolling the board; a finger
   anywhere else on the board still pans, which a `touch-action` on the whole
   board would have taken away. */
.token.movable { touch-action: none; }

/* while a finger has hold of it, the token follows the pointer freely */
.token.dragging { left: auto; top: auto; z-index: 5; cursor: grabbing; }
.token.dragging, .token[style*="--free"] { transition: none; }
.token:not(.dragging) { transition: left .12s ease, top .12s ease; }

.token img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 50%;
  pointer-events: none;
}

.tk-initial { font-family: var(--serif); font-size: calc(var(--cell) * .45); color: var(--ink); }

.tk-name {
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  margin-top: 1px;
  padding: 0 4px;
  border-radius: 3px;
  background: rgba(0, 0, 0, .6);
  color: #fff;
  font-size: 10px;
  line-height: 1.5;
  white-space: nowrap;
  pointer-events: none;
}

.token.pc { border-color: var(--green); }
.token.npc { border-color: var(--red); }
.token.movable { cursor: grab; }
.token.movable:hover { box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 60%, transparent); }
.token.movable:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* a druid in Wild Shape: still the party's green, with a paw so the wolf is
   read as somebody rather than as a wolf */
.token.pc.shaped { border-style: dashed; }
.token.pc.shaped::after {
  content: '🐾';
  position: absolute;
  top: -4px;
  right: -4px;
  font-size: max(10px, calc(var(--cell) * .26));
  line-height: 1;
  filter: drop-shadow(0 1px 1px rgba(0, 0, 0, .5));
  pointer-events: none;
}

.map-empty { max-width: 380px; margin: 40px auto; text-align: center; }
.map-hint { margin: 0; }

/* --------------------------------------------------------------- the pens */

.draw-bar { gap: 10px; }
.tool-set, .ink-set, .nib-set { display: flex; align-items: center; gap: 4px; }
.tool-set { flex-wrap: wrap; }

.btn.tool { display: inline-flex; align-items: center; gap: 5px; }
.btn.tool .tool-i { font-size: 13px; line-height: 1; }
.btn.tool.on {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
  font-weight: 600;
}

.ink-set { padding-left: 6px; border-left: 1px solid var(--line); }

.ink-swatch {
  width: 22px;
  height: 22px;
  padding: 0;
  border-radius: 50%;
  border: 2px solid var(--line-2);
  background: var(--sw);
  cursor: pointer;
}

.ink-swatch:hover { border-color: var(--ink-2); }
.ink-swatch.on { border-color: var(--ink); box-shadow: 0 0 0 2px var(--accent); }

.nib-set { padding-left: 6px; border-left: 1px solid var(--line); }
.btn.nib { display: grid; place-items: center; width: 30px; padding: 6px 0; }
.btn.nib i { display: block; width: 15px; height: var(--h, 3px); min-height: 2px; background: currentColor; border-radius: 3px; }
.btn.nib.on { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }

/* ------------------------------------------------------------ saved maps */

.map-save { display: flex; gap: 8px; align-items: center; }
.map-lib { margin-top: 12px; display: flex; flex-direction: column; gap: 6px; }

.lib-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 9px;
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.lib-thumb {
  width: 62px;
  height: 42px;
  flex: none;
  display: grid;
  place-items: center;
  border-radius: 4px;
  border: 1px solid var(--line);
  background: #d9c9a4;
  overflow: hidden;
}

.lib-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.lib-thumb .muted { color: #7a6642; }
.lib-what { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.lib-what b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---------------------------------------------------------------- tablets

   A tablet is the machine this actually gets used on: propped up beside the
   dice. The bars stop wrapping into four rows that eat the board, and scroll
   sideways instead. */

@media (max-width: 1000px) {
  .panel.map-panel { padding: 10px 10px 14px; gap: 8px; }
  .map-bar {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: thin;
    padding: 7px 8px;
  }
  .map-bar > * { flex: none; }
  .map-bar .grow { flex: 1 0 8px; }
  .tool-set { flex-wrap: nowrap; }
  .map-scroll { padding: 8px; }
}

/* icons alone below this: with labels the pen bar does not fit an iPad held
   upright, and a toolbar you have to scroll is a toolbar you lose things in */
@media (max-width: 900px) {
  .btn.tool .tool-l { display: none; }
  .btn.tool .tool-i { font-size: 15px; }
  .btn.tool { padding: 6px 9px; }
}

@media (max-width: 720px) {
  .map-num, .map-hint { display: none; }
}

@media print {
  .map-bar, .map-hint, .topbar { display: none !important; }
  .map-scroll { overflow: visible; border: 0; padding: 0; }
  .map-board { box-shadow: none; border: 1px solid #999; }
}

/* a summon is on the party's side of the fight, and its token says so: the
   party's green, ringed, so it is not read as one more goblin */
.token.npc.summon {
  border-color: var(--green);
  /* the ring goes over the token's own shadow rather than instead of it,
     or a summon would sit flatter on the board than everything beside it */
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--green) 45%, transparent),
    0 1px 4px rgba(40, 26, 6, .45);
}

/* ------------------------------------------------------------------ hexes

   A hex board draws its lattice as an SVG rather than with a repeating
   gradient, because a staggered lattice is not something a gradient can
   describe. One path for the whole grid: sixty by sixty is 3,600 hexes, and
   3,600 elements is a slow thing to draw and a slower thing to keep. */

.map-hexgrid {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  overflow: visible;
}

.map-hexgrid path {
  fill: none;
  stroke: rgba(92, 68, 34, .38);
  /* `non-scaling-stroke` takes the width out of the viewBox's units and into
     device pixels - so this is a one-pixel line, the same hairline the square
     grid draws with its gradients, and it stays one pixel at every zoom.
     Written as cell widths it would be six hundredths of a pixel, which is
     the same as not drawing it. */
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}

/* over a photograph the same lines would disappear, so they lift */
.map-board:has(.map-bg) .map-hexgrid path { stroke: rgba(20, 14, 4, .55); }

/* cover on a hex board is a path rather than merged rectangles */
.map-fog .fog-cells path { fill: #0e1013; }
.map-fog.dm .fog-cells path { fill: #0e1013; fill-opacity: .62; }
.map-board[data-tool="cover"] .map-fog.dm .fog-cells path,
.map-board[data-tool="reveal"] .map-fog.dm .fog-cells path { fill-opacity: .5; }

/* The hex a token came from, outlined in its own shape. Measured in cell
   widths like the square version beside it - no `non-scaling-stroke` here,
   because this one is meant to thicken as the board is zoomed in, the way the
   dashed square outline always has. */
.map-hud path.rule-from {
  fill: rgba(201, 162, 39, .12);
  stroke: var(--accent);
  stroke-width: .06;
  stroke-dasharray: .18 .14;
  opacity: .85;
}

/* squares or hexes, as a pair of pressed buttons */
.grid-set { display: inline-flex; gap: 2px; }
.grid-set .btn.on {
  background: var(--accent);
  border-color: var(--accent);
  color: #201802;
  font-weight: 600;
}

/* ------------------------------------------------ view controls and docking

   The zoom, Fit and board-only buttons are a group of their own at the right
   end of the bar, so they never scroll away with the setup buttons. */

.map-setup { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; flex: 1; min-width: 0; }
.map-view-ctl { display: flex; align-items: center; gap: 4px; flex: none; margin-left: auto; }
.map-view-ctl .map-size { margin-right: 6px; }
.map-view-ctl .btn.on {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
  font-weight: 600;
}

/* Every touch on the board is ours: one finger pans, two pinch (board-zoom.js).
   Left to the browser, a pinch zoomed the whole page, menus and all. */
.map-scroll { touch-action: none; overscroll-behavior: contain; }
/* a fitted board narrower than the room sits in the middle of it */
.map-board { margin: 0 auto; }

/* On a desk both wrappers step aside and the panels float as they always
   have; tablet.css turns them into a real layout. */
/* The tracker and the summary have a column of their own beside the board at
   every size (tablet.css moves it under the board held upright). Floating,
   they covered the zoom buttons and a third of the board. */
.panel.map-panel {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 260px;
  grid-template-rows: minmax(0, 1fr);
  gap: 10px;
  overflow: hidden;
}
.panel.map-panel:not(:has(.map-dock .float-pip)) { grid-template-columns: minmax(0, 1fr); }
.map-stage { display: flex; flex-direction: column; gap: 8px; min-width: 0; min-height: 0; }
.map-dock { display: flex; flex-direction: column; gap: 8px; min-height: 0; overflow-y: auto; }
.map-dock .float-pip {
  position: relative !important;
  inset: auto !important;
  width: auto !important;
  max-width: none;
  max-height: none;
  flex: none;
  box-shadow: none;
}
.map-dock .pip-grip { cursor: default; }
.map-dock .pip-dots { display: none; }

/* ------------------------------------------------------------- board only

   Everything but the board and its view buttons goes, and those float over
   the board's corner so the board has the whole screen. */

body.map-focus #app { grid-template-rows: minmax(0, 1fr); }
body.map-focus .topbar,
body.map-focus .draw-bar,
body.map-focus .map-hint,
body.map-focus .map-dock,
body.map-focus .map-setup,
body.map-focus .map-size { display: none !important; }
body.map-focus .panel.map-panel { display: flex; padding: 0; }
body.map-focus .map-stage { display: flex; flex-direction: column; flex: 1; min-height: 0; min-width: 0; position: relative; }
body.map-focus .map-scroll { border: 0; border-radius: 0; }
body.map-focus .map-bar {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 6;
  padding: 4px;
  background: color-mix(in srgb, var(--bg-2) 88%, transparent);
  box-shadow: 0 6px 18px rgb(0 0 0 / 40%);
}
body.map-focus .map-focus-btn { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }


/* ------------------------------------------------------------ board menu */

.board-menu { position: relative; }
.board-menu > summary { list-style: none; cursor: pointer; }
.board-menu > summary::-webkit-details-marker { display: none; }
.board-menu[open] > summary { background: var(--bg-4); }
.board-pop {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 20;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  width: max-content;
  max-width: min(560px, 80vw);
  padding: 10px;
  background: var(--bg-2);
  border: 1px solid var(--line-2);
  border-radius: 8px;
  box-shadow: 0 10px 26px rgb(0 0 0 / 45%);
}
.map-bar:has(.board-menu[open]) { overflow: visible !important; }
.map-setup:has(.board-menu[open]) { overflow: visible !important; }

/* ------------------------------------------------------ tokens: who is who

   Names show under the pointer, on a focused or moving token, and for all of
   them when the board asks (Names); side by side they used to run together.
   A character with no portrait wears a colour of its own. */

.tk-name { opacity: 0; transition: opacity .12s; }
.token:hover .tk-name, .token:focus-visible .tk-name, .token.dragging .tk-name,
.map-board.show-names .tk-name { opacity: 1; }
.token.pc[style*="--pc-hue"] {
  background: hsl(var(--pc-hue) 38% 32%);
  border-color: hsl(var(--pc-hue) 60% 62%);
}
.token.pc[style*="--pc-hue"] .tk-initial { color: hsl(var(--pc-hue) 80% 90%); }
.token.unplaced { border-style: dashed; opacity: .8; }

/* beside the dock the pens do not fit with their words; icons, with the
   word in the tooltip */
@media (max-width: 1400px) {
  .btn.tool .tool-l { display: none; }
  .btn.tool .tool-i { font-size: 15px; }
}
.draw-bar { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: thin; }
.draw-bar > * { flex: none; }

/* the pen: colours and nibs inline where there is room, one button that
   opens them where there is not (map.js drawBar) */
.pen-menu { display: none; position: relative; }
.pen-menu > summary { list-style: none; cursor: pointer; display: inline-flex; align-items: center; gap: 6px; }
.pen-menu > summary::-webkit-details-marker { display: none; }
.pen-sw { width: 16px; height: 16px; border-radius: 50%; background: var(--sw); border: 2px solid var(--line-2); }
.pen-nib { display: block; width: 14px; height: var(--h, 3px); min-height: 2px; background: currentColor; border-radius: 3px; }
.pen-pop {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 20;
  display: flex; flex-direction: column; gap: 8px; padding: 10px;
  background: var(--bg-2); border: 1px solid var(--line-2); border-radius: 8px;
  box-shadow: 0 10px 26px rgb(0 0 0 / 45%);
}
.pen-pop .ink-set, .pen-pop .nib-set { padding-left: 0; border-left: 0; }
@media (max-width: 1400px) {
  .draw-bar > .ink-set, .draw-bar > .nib-set { display: none; }
  .pen-menu { display: block; }
}
.draw-bar:has(.pen-menu[open]) { overflow: visible; }

/* ------------------------------------------------------------------- tray

   Creatures added but not yet set down (map.js inTray), above the board. */
.map-tray {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 10px;
  background: var(--bg-2);
  border: 1px dashed var(--line-2);
  border-radius: var(--radius);
}
.tray-label { flex: none; display: flex; flex-direction: column; line-height: 1.2; max-width: 190px; }
.tray-list { display: flex; gap: 6px; overflow-x: auto; flex: 1; min-width: 0; padding: 2px; scrollbar-width: thin; }
.tray-tok {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 10px 3px 3px;
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: 99px;
  color: inherit;
  font: inherit;
  font-size: 12.5px;
  cursor: grab;
  touch-action: none;
  user-select: none;
}
.tray-tok:hover { border-color: var(--line-2); }
.tray-tok.armed { border-color: var(--accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 40%, transparent); }
.tray-face {
  width: 26px; height: 26px; border-radius: 50%; overflow: hidden;
  display: grid; place-items: center; background: var(--bg-4);
  border: 2px solid var(--red); font: 700 12px/1 var(--serif);
}
.tray-face img, .tray-ghost img { width: 100%; height: 100%; object-fit: cover; pointer-events: none; }
.tray-ghost {
  position: fixed; z-index: 90; pointer-events: none;
  border-radius: 50%; overflow: hidden; display: grid; place-items: center;
  border: 2px solid var(--red); background: var(--bg-3); opacity: .85;
  box-shadow: 0 6px 16px rgb(0 0 0 / 45%); font: 700 14px/1 var(--serif);
}
body.tray-arming .map-board { cursor: copy; outline: 2px dashed var(--accent); outline-offset: 2px; }
@media (max-width: 600px) {
  .tray-label .tiny { display: none; }
  .map-tray { flex-wrap: wrap; }
}

/* ------------------------------------------------------ movement limit */

.move-line {
  margin: 0 0 8px;
  padding: 6px 9px;
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
  border-radius: 6px;
}
.move-line.out { border-left-color: var(--red); }
.loot-ctl { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }

/* --------------------------------------------- reach and range circles */

.map-hud .aim-ring { fill: none; stroke-width: .07; }
.map-hud .aim-ring.reach { fill: rgba(201, 162, 39, .16); stroke: var(--accent); }
.map-hud .aim-ring.range { fill: rgba(79, 158, 99, .10); stroke: #4f9e63; }
.map-hud .aim-ring.move  { fill: rgba(90, 140, 220, .08); stroke: #5a8cdc; }
.map-hud .aim-ring.long  { fill: rgba(217, 140, 60, .06); stroke: #d98c3c; stroke-dasharray: .3 .2; }

.aim-panel { margin: 0 0 8px; }
.aim-panel .mini-h { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.aim-set { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 4px; }
.aim-opt i { font-style: normal; opacity: .65; margin-left: 4px; }
.aim-key { margin-top: 4px; display: flex; flex-wrap: wrap; align-items: center; gap: 4px; }
.aim-swatch { display: inline-block; width: 10px; height: 10px; border-radius: 50%; border: 2px solid; margin-right: 2px; }
.aim-swatch.move { border-color: #5a8cdc; }
.aim-swatch.reach { border-color: var(--accent); }
.aim-swatch.range { border-color: #4f9e63; }
.aim-swatch.long { border-color: #d98c3c; border-style: dashed; }

/* ---------------------------------------------------------------- corpses */

/* A creature at nought hit points stays where it fell. The picture greys out
   and a red cross goes over it, so what is dead is plain from across the
   table; it sits under the living so a body can be stood on. */
.token.dead { z-index: 0; border-color: #6d2a20; box-shadow: none; }
.token.dead img,
.token.dead .tk-initial { filter: grayscale(1) brightness(.55); }
.token.dead .tk-x {
  position: absolute;
  inset: -8%;
  width: 116%;
  height: 116%;
  overflow: visible;
  pointer-events: none;
}
.token.dead .tk-x path {
  fill: none;
  stroke: #e23b26;
  stroke-width: 3;
  vector-effect: non-scaling-stroke;
  stroke-linecap: round;
  filter: drop-shadow(0 0 .4px #000);
}
.token.dead .tk-name { text-decoration: line-through; opacity: .8; }
.token.searchable { cursor: pointer; }
.token.searchable:hover,
.token.searchable:focus-visible { box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 70%, transparent); }
.token:not(.dead):not(.dragging) { z-index: 1; }

/* the DM's loot list, on a creature's card */
.mon-loot { margin-top: 12px; border-top: 1px solid var(--line); padding-top: 12px; }
.mon-loot summary { cursor: pointer; }
.mon-loot[open] > summary { margin-bottom: 8px; }
.loot-list { list-style: none; margin: 8px 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.loot-list li { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 12px; }
.loot-add { gap: 8px; margin-top: 8px; }
.loot-add input[type="text"] { flex: 1; min-width: 0; }
.loot-add input[type="number"] { width: 56px; }
/* the purse sits on its own line, clear of the form above it */
.loot-gold { display: flex; align-items: center; gap: 8px; margin-top: 12px; }
.loot-gold input { width: 72px; text-align: center; }
.loot-gold .btn.sm { min-width: 28px; padding: 3px 0; text-align: center; }

/* --------------------------------------------- allies and targeting */

.ally { padding: 6px 0; border-bottom: 1px solid var(--line); }
.ally:last-child { border-bottom: 0; }
.ally.down .ally-head b { color: var(--red); }
.ally-head { display: flex; align-items: baseline; gap: 6px; }
.ally-hp { margin-left: auto; font-weight: 700; font-variant-numeric: tabular-nums; }
.ally-hp i { font-style: normal; font-weight: 400; opacity: .6; }
.ally-hp em { font-style: normal; color: var(--blue); font-weight: 600; }
.ally-fx { display: flex; flex-wrap: wrap; gap: 3px; margin-top: 4px; }

/* an enemy inside the range of what the player is aiming */
.token.aimable { cursor: crosshair; box-shadow: 0 0 0 3px rgba(226, 59, 38, .75); }
.token.aimable:hover { box-shadow: 0 0 0 4px rgba(226, 59, 38, 1); }
.aim-spell { width: 100%; margin-top: 6px; }
.foe-spell input { width: 64px; }

/* an opportunity attack on offer: a strip above the board, hard to miss and quick to dismiss */
.opp-banner { display: grid; gap: 6px; padding: 8px 12px; border: 1px solid var(--accent); border-radius: 8px; background: rgba(201, 162, 39, .12); }
.opp-row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
