/* Mahaan Cards. Plain CSS, no preprocessor. */

:root {
  --bg: #16171a;
  --panel: #1e2024;
  --card: #23262b;
  --ink: #e6e2d8;
  --muted: #8f8a80;
  --line: #33363c;
  --accent: #d9b35a;
  /* dev mode's highlight: the mist grey of the setting guide's landing title, sampled from its
     cover. The guide's own stylesheet uses the same name. */
  --dev-accent: #9fbabd;
  /* the line under the top bar's selected tab; the same mist grey, but not a dev-mode mark */
  --tab-accent: #9fbabd;

  /* one colour per card type */
  /* one colour per type; the new ones are placeholders until chosen */
  --c-npc: #5aa0d9;
  --c-pc: #5ad0c8;
  --c-monster: #d95a5a;
  --c-item: #d9d15a;
  --c-location: #6cbf7a;
  --c-organization: #8fb3a0;
  --c-plan: #d9b35a;
  --c-encounter: #b08ad9;
  --c-clock: #d97a5a;
  --c-rule: #8f8a80;
  --c-action: #d98ab0;
  --c-property: #a3c46a;
  --c-info: #c9a27a;
  --c-spell: #9fa8ff;
  /* status of a person or group towards the party */
  --c-ally: #6cbf7a;
  --c-neutral: #8f8a80;
  --c-enemy: #d95a5a;
}

* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; background: var(--bg); color: var(--ink); font: 14px/1.4 system-ui, -apple-system, "Segoe UI", sans-serif; }
a { color: var(--accent); text-decoration: none; }
button { font: inherit; }

/* The bar across the top: a tab per page, each an icon and a label; the selected tab is
   underlined. The bar and the footer are overlays on the window's top and bottom edges with no
   background: what lies under them shows through, but they still take the clicks in their area.
   Their heights are measured into --bar-h and --footer-h on the root element by app.js; the
   card table and the map keep between them, and the guide's pages read the same two to pad
   themselves. The values here hold until the first measurement. The edge lines are transparent,
   kept so the heights do not change when dev mode colours them. */
:root { --bar-h: 34px; --footer-h: 33px; }
.topbar { position: fixed; top: 0; left: 0; right: 0; z-index: 40; height: 34px; box-sizing: border-box; display: flex; align-items: stretch; gap: 2px; padding: 0 12px; border-bottom: 1px solid transparent; }
.topbar.dev { border-bottom-color: var(--dev-accent); }
.topbar .tab { display: flex; align-items: center; gap: 7px; padding: 0 12px; background: none; border: 0; border-bottom: 2px solid transparent; color: var(--muted); font-size: 13px; cursor: pointer; }
/* a slight shadow under each tab's icon and label, so they read over bright mist; a filter rather
   than a text shadow, because the icon is a mask and would mask its own shadow away */
.topbar .tab { filter: drop-shadow(0 1px 2px rgba(0, 0, 0, .75)); }
/* the icon is its file used as a mask over the label's colour */
.topbar .tab .tabicon { flex: none; width: 16px; height: 16px; background: currentColor; -webkit-mask: var(--icon) center / contain no-repeat; mask: var(--icon) center / contain no-repeat; }
.topbar .tab:hover { color: var(--ink); }
.topbar .tab.on { color: var(--ink); border-bottom-color: var(--tab-accent); cursor: default; }

/* The card table lies between the bar and the footer, so nothing on it is ever under them; when a
   portrait window is too short for the hand it scrolls there, not the page. Landscape: sidebar 280
   on the left, the table in the middle, the console 250 on the right. The table is a fixed hand
   of 3 x 2 cards. */
:root { --card-w: 272px; --card-h: 380px; --card-r: 13px; }  /* 63 x 88 mm card, 3 mm corners, scaled */
.layout { position: fixed; top: var(--bar-h); bottom: var(--footer-h); left: 0; right: 0; z-index: 0; overflow: auto; display: grid; grid-template-columns: 280px minmax(0, 1fr) 250px; grid-template-rows: minmax(0, 1fr); }
/* The guide and map tabs: the guide's frame or the map covers the whole window, under the bar and
   the footer. The sidebar, table and console stay laid out beneath, hidden and not scrollable, so
   they are unchanged on return. The frame and the map stay too once loaded, each hidden off its
   own tab, and are the window's size on every tab, so the guide keeps its page and scroll. The
   guide's pages scroll inside the frame. */
.layout.away { overflow: clip; }
.layout.away > .sidebar, .layout.away > .table, .layout.away > .console { visibility: hidden; }
.layout:not(.tab-guide) > .guide { visibility: hidden; }
.guide { position: fixed; inset: 0; z-index: 25; overflow: hidden; background: var(--bg); }
.guide iframe { display: block; width: 100%; height: 100%; border: 0; }
/* The map: MapLibre's canvas covers the window, with the bar's and the footer's heights as its padding. It is created
   the first time the Map tab opens and stays, hidden on the other tabs. */
.layout:not(.tab-map) > .map2view { visibility: hidden; }
.map2view { position: fixed; inset: 0; z-index: 25; overflow: hidden; background: var(--bg); touch-action: none; overscroll-behavior: none; }
/* The Session tab (DM only; app/session/session.css is linked when it first opens): the planner covers the window like the map and
   stays once made, hidden off its tab. Nothing inside it may ever set `visibility: visible`, in CSS or inline: it would show
   through this rule over the other tabs (the 1.6.1 lesson); show with '' or a class. */
.layout:not(.tab-session) > .sessionview { visibility: hidden; }
.sessionview { position: fixed; inset: 0; z-index: 25; overflow: hidden; background: var(--bg); touch-action: none; overscroll-behavior: none; }
.map2view .map2canvas { position: absolute; inset: 0; }
.map2view .maplibregl-canvas { outline: none; }
/* The ground (behind the canvas) is placed by Map2Panel on every move; see its comment. It is the map's own sea as a
   seamless tile, repeated, and takes no pointer. The vignette over it is not a DOM element: it is a layer in MapLibre. */
.map2view .map2ground { position: absolute; left: 0; top: 0; pointer-events: none; transform-origin: 0 0; will-change: transform; }
.map2view .map2ground { background: url(map/sea-ground.webp) repeat; }
/* The four edge strips (between the ground and the canvas): the picture's own outermost sea, mirrored about each edge and
   fading out, so the picture's edge has no seam against the ground; placed and sized by app.js, at 1 CSS px per image
   strip px before the transform. */
.map2view .map2edge { position: absolute; left: 0; top: 0; pointer-events: none; transform-origin: 0 0; will-change: transform; background-size: 100% 100%; background-repeat: no-repeat; }
.map2view .map2edge.l { background-image: url(map/sea-edge-left.webp); }
.map2view .map2edge.r { background-image: url(map/sea-edge-right.webp); }
.map2view .map2edge.t { background-image: url(map/sea-edge-top.webp); }
.map2view .map2edge.b { background-image: url(map/sea-edge-bottom.webp); }
/* Its scale bar (bottom left) and compass (bottom right) sit above the footer, in the setting guide's palette: its
   body text's near-white (--text), its mist greys (--mist, --mist-deep) and the dark teal of its rules (--rule), from
   guide/style.css, where they were sampled from the cover (guide/wiki/MODEL.md). A dark halo keeps them readable over
   sea and land alike. The bar is drawn after the map's old one: a band of segments, mist and dark teal by turns, in a
   thin near-white outline, as long as the labelled distance (app.js sets the width); ticks and small labels under it
   at 0, at the midpoint where it fits, and at the end, with "miles" once. */
:root { --map-ink: #eef5f6; --map-mist: #9fbabd; --map-mist-deep: #5e848c; --map-teal: #2a454a; --map-edge: #0d1d1d; }
.map2scale, .map2compass { position: absolute; bottom: calc(var(--footer-h) + 14px); pointer-events: none; filter: drop-shadow(0 0 1px rgb(0 0 0 / .9)) drop-shadow(0 1px 2px rgb(0 0 0 / .6)); }
.map2scale { left: 16px; height: 24px; }
.map2scale .segs { position: absolute; left: 0; right: 0; top: 0; height: 6px; display: flex; outline: 1px solid var(--map-ink); }
.map2scale .segs i { flex: 1 1 0; background: var(--map-mist); }
.map2scale .segs i.dark { background: var(--map-teal); }
.map2scale .tick { position: absolute; top: 7px; width: 1px; height: 4px; margin-left: -.5px; background: var(--map-ink); }
.map2scale .lbl { position: absolute; top: 12px; transform: translateX(-50%); color: var(--map-ink); font-size: 11px; line-height: 12px; white-space: nowrap; font-variant-numeric: tabular-nums; }
.map2scale .lbl .unit { position: absolute; left: 100%; margin-left: .3em; }
.map2compass { right: 16px; width: 56px; height: 67px; overflow: visible; }
.map2compass .lit { fill: var(--map-ink); }
.map2compass .shade { fill: var(--map-mist-deep); }
.map2compass path { stroke: var(--map-edge); stroke-width: .7; stroke-linejoin: round; }
.map2compass circle { fill: none; stroke: var(--map-mist); stroke-width: 1.4; }
.map2compass text { fill: var(--map-ink); font: 600 10px system-ui, -apple-system, "Segoe UI", sans-serif; text-anchor: middle; }
/* The feature editor (dev mode; app/map/editor.js), styled like the setting guide's sidebar (guide/style.css --nav-*):
   no colour of its own, a backdrop blur, a faint shadow under the text, rules in the cover's teal, markers in the mist
   grey, raised rows in a faint warm white. It sits at the right edge between the bar and the footer (never over the
   footer's dev tools) and slides in when it first shows; the compass moves to its left while it is there. */
:root { --ed-w: 320px; --ed-ink: #eef5f6; --ed-line: #2a454a; --ed-accent: #9fbabd; --ed-raised: rgb(230 226 216 / .08); --ed-blur: 16px;
  --ed-shadow: 0 0 2px rgb(0 0 0 / .6), 0 1px 3px rgb(0 0 0 / .5); --ed-danger: #d98a8a;
  --ed-default: #d95a5a; --ed-outline: 0 0 1px rgb(0 0 0 / .9), 0 0 1px rgb(0 0 0 / .9); }   /* the panel's own text (captions, hints, placeholders): the app's red with a thin dark edge */
.map2view .map2compass { transition: right .25s ease; }
.map2view.editing .map2compass { right: calc(var(--ed-w) + 16px); }
.m2panel { position: absolute; top: var(--bar-h); bottom: var(--footer-h); right: 0; width: var(--ed-w); box-sizing: border-box; z-index: 2; color: var(--ed-ink); text-shadow: var(--ed-shadow);
  -webkit-backdrop-filter: blur(var(--ed-blur)); backdrop-filter: blur(var(--ed-blur)); transform: translateX(100%); transition: transform .25s ease; touch-action: pan-y; font-size: 14px; line-height: 1.4; }
.m2panel.in { transform: none; }
.m2panel .ed-in { height: 100%; overflow: auto; padding: 10px; box-sizing: border-box; }
.m2panel .ed-tools { display: flex; align-items: center; gap: 8px; }
.m2panel .ed-spacer { flex: 1; }
.m2panel .ed-segs { display: flex; }
.m2panel .ed-seg, .m2panel .ed-btn { font: inherit; color: var(--ed-ink); text-shadow: inherit; background: transparent; border: 1px solid var(--ed-line); padding: 5px 10px; cursor: pointer; }
.m2panel .ed-seg { border-radius: 0; margin-left: -1px; }
.m2panel .ed-seg:first-child { border-radius: 6px 0 0 6px; margin-left: 0; }
.m2panel .ed-seg:last-child { border-radius: 0 6px 6px 0; }
.m2panel .ed-btn { border-radius: 6px; }
.m2panel .ed-btn.small { padding: 2px 8px; font-size: 13px; }
.m2panel .ed-btn.danger { border-color: var(--ed-danger); }
.m2panel .ed-seg.on { background: var(--ed-raised); border-color: var(--ed-accent); position: relative; }
.m2panel .ed-seg:hover, .m2panel .ed-btn:hover:not(:disabled) { background: var(--ed-raised); }
.m2panel .ed-btn:disabled { opacity: .45; cursor: default; }
.m2panel button:focus-visible, .m2panel input:focus, .m2panel textarea:focus, .m2panel select:focus { outline: 1px solid var(--ed-accent); outline-offset: 0; }
.m2panel .ed-dirty { width: 8px; height: 8px; border-radius: 50%; background: var(--ed-accent); }
.m2panel .ed-status { margin: 8px 0 10px; font-size: 12px; }
.m2panel .ed-status, .m2panel .ed-dim, .m2panel .ed-sub, .m2panel .ed-field > span:first-child, .m2panel .ed-cap, .m2panel .ed-unit, .m2panel .ed-note { color: var(--ed-default); text-shadow: var(--ed-outline); }
.m2panel ::placeholder { color: var(--ed-default); text-shadow: var(--ed-outline); opacity: 1; }
.m2panel .ed-err { margin: 8px 0; padding: 6px 8px; border: 1px solid var(--ed-danger); border-radius: 6px; font-size: 13px; color: var(--ed-ink); overflow-wrap: anywhere; }
.m2panel .ed-small { font-size: 12px; margin: 4px 0; }
.m2panel .ed-hint { margin: 0; }
.m2panel input[type=text], .m2panel input[type=number], .m2panel select, .m2panel textarea { font: inherit; color: var(--ed-ink); text-shadow: inherit; background: transparent; border: 1px solid var(--ed-line); border-radius: 6px; padding: 5px 8px; box-sizing: border-box; min-width: 0; }
.m2panel select option { color: #111; text-shadow: none; }
.m2panel textarea { width: 100%; resize: vertical; display: block; }
.m2panel .ed-head { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.m2panel .ed-glyph { flex: none; display: inline-flex; align-items: center; justify-content: center; min-width: 40px; }
.m2panel .ed-name { flex: 1; font-size: 20px; font-weight: 600; padding: 3px 8px; border-color: transparent; }
.m2panel .ed-name:hover { border-color: var(--ed-line); }
.m2panel .ed-title { margin: 0; font-size: 20px; font-weight: 600; }
.m2panel .ed-sub { margin: 0 0 8px; }
.m2panel .ed-fields { display: grid; gap: 6px; margin-bottom: 10px; }
.m2panel .ed-field { display: grid; grid-template-columns: 82px 1fr; align-items: center; gap: 8px; }
.m2panel .ed-field > span:first-child, .m2panel .ed-cap { font-size: 12px; }
.m2panel .ed-field select { width: 100%; }
.m2panel .ed-inline { display: flex; align-items: center; gap: 6px; }
.m2panel .ed-inline input { width: 72px; }
.m2panel .ed-unit { font-size: 12px; }
.m2panel .ed-pic { margin: 0 0 8px; position: relative; }
.m2panel .ed-pic img { display: block; width: 100%; border-radius: 6px; }
.m2panel .ed-pic .ed-btn { position: absolute; top: 6px; right: 6px; background: rgb(13 29 29 / .7); }
.m2panel .ed-addpic { width: 100%; margin-bottom: 8px; }
.m2panel .ed-view > .ed-row { margin-bottom: 8px; justify-content: flex-start; }   /* Add picture, then the folder's list */
.m2panel .ed-view > .ed-row .ed-addpic { flex: 1; width: auto; margin-bottom: 0; }
.m2panel .ed-block { display: block; margin-bottom: 10px; }
.m2panel .ed-text { margin: 0 0 8px; }
.m2panel .ed-dm { margin: 0 0 10px; padding: 8px; border: 1px dashed var(--ed-accent); border-radius: 6px; background: var(--ed-raised); }
.m2panel .ed-dm .ed-cap { display: block; margin-bottom: 4px; text-transform: uppercase; letter-spacing: .06em; }
.m2panel .ed-foot { display: grid; gap: 8px; padding-top: 8px; border-top: 1px solid var(--ed-line); }
.m2panel .ed-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.m2panel .ed-note { margin: 0; font-size: 13px; }
.m2panel .ed-confirm { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.m2panel .ed-confirm span { flex: 1 1 auto; overflow-wrap: anywhere; }
/* A region marker's colour: one swatch per palette entry, then "auto"; the chosen one is ringed. */
.m2panel .ed-swatches { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.m2panel .ed-swatch { box-sizing: border-box; width: 22px; height: 22px; padding: 0; border: 1px solid var(--ed-line); border-radius: 50%; cursor: pointer; }
.m2panel .ed-swatch.auto { width: auto; min-width: 22px; padding: 0 8px; border-radius: 11px; background: transparent; color: var(--ed-ink); font: inherit; font-size: 12px; text-shadow: inherit; }
.m2panel .ed-swatch:hover { border-color: var(--ed-ink); }
.m2panel .ed-swatch.on { border-color: var(--ed-ink); box-shadow: 0 0 0 2px var(--ed-accent); }
.m2panel .ed-swatch.auto.on { background: var(--ed-raised); }
/* The Regions layer's warnings (a border with a gap, a marker not on land), above the status line. */
.m2panel .ed-warn { list-style: none; margin: 8px 0 0; padding: 0; display: grid; gap: 4px; }
.m2panel .ed-warn button { display: block; width: 100%; text-align: left; font: inherit; font-size: 13px; color: var(--ed-ink); text-shadow: inherit; background: transparent;
  border: 1px solid var(--ed-danger); border-radius: 6px; padding: 5px 8px; cursor: pointer; overflow-wrap: anywhere; }
.m2panel .ed-warn button:hover { background: var(--ed-raised); }
/* The info panel (app/map/info.js): the reading panel, in the editor's shell (`m2panel`) and colours. The name is set in the
   map's label font (Alegreya SC Medium; the players' server serves the file); the type line has the editor's `.ed-sub` layout
   but the panel's own ink, not the editor's red (which marks editable defaults);
   the compass moves to its left while it is in. */
@font-face { font-family: 'Alegreya SC'; font-weight: 500; font-style: normal; font-display: swap;
  src: url(map/fonts/alegreya-sc/alegreya-sc-latin-500-normal.woff2) format('woff2'); }
.map2view:has(> .map2info.in) .map2compass { right: calc(var(--ed-w) + 16px); }
.map2info .inf-name { margin: 0 0 4px; font: 500 26px/1.2 'Alegreya SC', serif; overflow-wrap: anywhere; }
.map2info .inf-type { display: flex; align-items: center; gap: 6px; margin: 0 0 10px; color: var(--ed-ink); text-shadow: var(--ed-shadow); }
.map2info .inf-type .ed-glyph { min-width: 0; }
.map2info .ed-text { white-space: pre-line; }
/* its close button: a small, quiet ×, floated top right so the name wraps around it; its tooltip is the tools' (below), to its left */
.map2info .inf-close { float: right; position: relative; width: 26px; height: 26px; margin: -3px -3px 4px 8px; padding: 0; box-sizing: border-box;
  display: inline-flex; align-items: center; justify-content: center; border-radius: 50%; border: 1px solid transparent; background: transparent;
  color: var(--ed-ink); cursor: pointer; }
.map2info .inf-close svg { width: 12px; height: 12px; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round;
  filter: drop-shadow(0 0 1px rgb(0 0 0 / .9)) drop-shadow(0 1px 2px rgb(0 0 0 / .5)); }
.map2info .inf-close:hover { background: var(--ed-raised); border-color: var(--ed-line); }
.map2info .inf-close .inf-tip { left: auto; right: calc(100% + 8px); }
/* Map 2.0's tools (app/map/tools.js): a quiet cluster top left, under the bar: the search field, then a column of round
   buttons in the scale bar's palette (near-white line work on dark teal, a thin near-white outline), the active one marked */
.map2tools { position: absolute; top: calc(var(--bar-h) + 12px); left: 16px; z-index: 2; display: flex; flex-direction: column; align-items: flex-start; gap: 10px; font-size: 14px; line-height: 1.4; }
.map2tools .m2t-btns { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; }
.map2tools .m2t-row { position: relative; display: flex; align-items: center; gap: 8px; }
.map2tools .m2t-btn { width: 30px; height: 30px; padding: 0; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; box-sizing: border-box;
  background: var(--map-teal); color: var(--map-ink); border: 1px solid var(--map-ink); cursor: pointer; box-shadow: 0 0 1px rgb(0 0 0 / .9), 0 1px 2px rgb(0 0 0 / .6); }
.map2tools .m2t-btn svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.4; stroke-linecap: round; stroke-linejoin: round; }
.map2tools .m2t-btn.on { background: var(--map-mist); color: var(--map-edge); }
.map2tools .m2t-btn:focus-visible { outline: 1px solid var(--map-mist); outline-offset: 2px; }
.map2tools .m2t-trash { width: 24px; height: 24px; color: #d95a5a; border-color: #d95a5a; }
.map2tools .m2t-trash svg { width: 15px; height: 15px; }
.map2tools .m2t-btn:hover:not(.on) { background: #34555b; }
/* the search: the guide's landing field (quiet, outlined, transparent, 14px system font), in the map's ink with its dark edge */
.map2tools .m2t-search { position: relative; }
.map2tools .m2t-q { width: 240px; box-sizing: border-box; padding: 8px 10px; border-radius: 6px; font: 14px/1.4 system-ui, -apple-system, "Segoe UI", sans-serif;
  background: transparent; color: var(--map-ink); border: 1px solid rgb(238 245 246 / .6); text-shadow: 0 0 1px rgb(0 0 0 / .9), 0 1px 2px rgb(0 0 0 / .6);
  box-shadow: 0 0 1px rgb(0 0 0 / .9), inset 0 0 1px rgb(0 0 0 / .9); }
.map2tools .m2t-q::placeholder { color: rgb(238 245 246 / .6); opacity: 1; }
.map2tools .m2t-q:focus { outline: none; border-color: var(--map-ink); }
.map2tools .m2t-results { position: absolute; z-index: 3; top: calc(100% + 4px); left: 0; width: 100%; box-sizing: border-box; margin: 0; padding: 4px; list-style: none;
  border: 1px solid rgb(238 245 246 / .6); border-radius: 6px; color: var(--map-ink); text-shadow: 0 0 1px rgb(0 0 0 / .9), 0 1px 2px rgb(0 0 0 / .6);
  background: rgb(13 29 29 / .35); -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px); box-shadow: 0 0 1px rgb(0 0 0 / .9), 0 1px 3px rgb(0 0 0 / .5); }
.map2tools .m2t-results li { display: flex; align-items: center; gap: 8px; padding: 4px 6px; border: 1px solid transparent; border-radius: 4px; cursor: pointer; }
.map2tools .m2t-results li.sel { border-color: var(--map-mist); background: rgb(230 226 216 / .08); }
.map2tools .m2t-glyph { flex: none; display: inline-flex; width: 18px; height: 18px; }
.map2tools .m2t-glyph svg { width: 18px; height: 18px; display: block; }
.map2tools .m2t-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.map2tools .m2t-type { flex: none; font-size: 12px; color: var(--map-mist); }
/* the layer menu */
/* the layer panel lies beside its button, out of the cluster's flow, so opening it moves nothing */
.map2tools .m2t-layers { position: absolute; left: calc(100% + 8px); top: 0; z-index: 3; width: max-content; padding: 6px 10px; border: 1px solid rgb(238 245 246 / .6); border-radius: 6px; color: var(--map-ink); text-shadow: 0 0 1px rgb(0 0 0 / .9), 0 1px 2px rgb(0 0 0 / .6);
  background: rgb(13 29 29 / .35); -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px); box-shadow: 0 0 1px rgb(0 0 0 / .9), 0 1px 3px rgb(0 0 0 / .5); }
.map2tools .m2t-layers label { display: flex; align-items: center; gap: 8px; padding: 2px 0; cursor: pointer; white-space: nowrap; }
.map2tools .m2t-layers input { margin: 0; accent-color: var(--map-mist); }
.map2tools .m2t-layers label.locked { cursor: default; opacity: .6; }
/* the zoom box's marquee and the search hit's flash ring, in the section beside the cluster */
.map2view .m2t-marquee { position: absolute; z-index: 1; pointer-events: none; box-sizing: border-box; border: 1px solid var(--map-ink); background: rgb(159 186 189 / .15);
  box-shadow: 0 0 1px rgb(0 0 0 / .9), inset 0 0 1px rgb(0 0 0 / .9); }
.map2view .m2t-flash { position: absolute; z-index: 1; pointer-events: none; box-sizing: border-box; border-radius: 50%; border: 2px solid var(--map-ink);
  box-shadow: 0 0 1px 1px rgb(0 0 0 / .9), inset 0 0 1px 1px rgb(0 0 0 / .9); transform: translate(-50%, -50%); animation: m2t-flash 1.2s ease-out forwards; }
@keyframes m2t-flash { 0% { opacity: 0; scale: .5; } 15% { opacity: 1; } 55% { opacity: 1; scale: 1; } 100% { opacity: 0; scale: 1.5; } }
/* the buttons' tooltips: small, to the right, after a short delay on hover and at once on keyboard focus; none for a
   button whose panel is open */
.map2tools .m2t-btn { position: relative; }
.map2tools .m2t-tip, .map2info .inf-tip { position: absolute; left: calc(100% + 8px); top: 50%; transform: translateY(-50%); z-index: 4; pointer-events: none; white-space: nowrap;
  padding: 3px 8px; border: 1px solid rgb(238 245 246 / .6); border-radius: 4px; background: rgb(13 29 29 / .88); color: var(--map-ink);
  font: 12px/1.3 system-ui, -apple-system, "Segoe UI", sans-serif; text-shadow: none; box-shadow: 0 0 1px rgb(0 0 0 / .9), 0 1px 3px rgb(0 0 0 / .5);
  opacity: 0; visibility: hidden; transition: opacity .08s ease, visibility 0s linear .08s; }
.map2tools .m2t-btn:hover .m2t-tip, .map2info .inf-close:hover .inf-tip { opacity: 1; visibility: visible; transition: opacity .08s ease .15s, visibility 0s linear .15s; }
.map2tools .m2t-btn:focus-visible .m2t-tip, .map2info .inf-close:focus-visible .inf-tip { opacity: 1; visibility: visible; transition: none; }
.map2tools .m2t-btn.open .m2t-tip { display: none; }
/* end of the tools' block */
/* Map 2.0's ruler (app/map/ruler.js) */
.map2view .m2ruler { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 1; pointer-events: none; overflow: hidden; user-select: none; }
.m2ruler .m2r-casing { fill: none; stroke: var(--map-edge); stroke-opacity: .8; stroke-width: 4.5; stroke-linecap: round; stroke-linejoin: round; }
.m2ruler .m2r-line { fill: none; stroke: var(--map-ink); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.m2ruler .m2r-node { fill: rgb(13 29 29 / .45); stroke: var(--map-ink); stroke-width: 1.5; paint-order: stroke; }
.m2ruler .m2r-snap { fill: none; stroke: var(--map-ink); stroke-width: 1.5; }
.m2ruler text { font-family: 'Alegreya SC', serif; font-weight: 500; fill: var(--map-ink); stroke: rgb(13 29 29 / .8); stroke-width: 3px; stroke-linejoin: round; paint-order: stroke; dominant-baseline: central; }
.m2ruler .m2r-seg { font-size: 13px; }
.m2ruler .m2r-total { font-size: 15px; }
/* end of the ruler's block */
.sidebar { grid-column: 1; grid-row: 1; width: 280px; box-sizing: border-box; background: var(--panel); border-right: 1px solid var(--line); overflow: auto; padding: 10px; }
.table { grid-column: 2; grid-row: 1; position: relative; overflow: hidden; display: grid; grid-template-columns: repeat(var(--cols, 3), var(--card-w)); grid-template-rows: repeat(var(--rows, 2), var(--card-h)); justify-content: space-evenly; align-content: space-evenly; }
.footer { position: fixed; left: 0; right: 0; bottom: 0; z-index: 30; border-top: 1px solid transparent; padding: 6px 12px; display: flex; gap: 14px; align-items: center; flex-wrap: wrap; color: var(--muted); }
.layout.dev > .footer { border-top-color: var(--dev-accent); }
.footer .version, .footer .licences { color: var(--muted); }
.footer .licences:hover, .footer .licences:focus-visible { color: var(--ink); }
.footer .devtools { margin-left: auto; display: flex; gap: 14px; align-items: center; }
.footer .dev { color: var(--muted); }
.footer .dev.on, .footer .devtool { color: var(--dev-accent); }
.footer .problemcount { color: var(--muted); }
.footer .problemcount.errors { color: #d95a5a; }

/* lint problems popup (dev mode): grouped by card; the one popup allowed to scroll */
.card.popup.text.problems { overflow: auto; }
.problems .probgroup { margin: 0 0 10px; }
.problems .probgroup ul { list-style: none; margin: 4px 0 0; padding: 0; font-size: 13px; }
.problems .probgroup li { padding: 1px 0 1px 10px; margin: 0 0 2px; border-left: 2px solid var(--line); }
.problems .probgroup li.error { border-left-color: #d95a5a; }
.problems .probgroup li.warn { border-left-color: var(--accent); }
/* dev mode recolours every separator as a visual cue */
.layout.dev { --line: var(--dev-accent); }
.console { grid-column: 3; grid-row: 1; box-sizing: border-box; background: var(--panel); border-left: 1px solid var(--line); display: flex; flex-direction: column; overflow: hidden; padding: 10px; font-size: 12px; font-family: ui-monospace, Menlo, Consolas, monospace; }
.console .label { color: var(--muted); text-transform: uppercase; font-size: 11px; letter-spacing: .06em; padding: 6px 4px; }
.console .log { list-style: none; margin: 0; padding: 0; flex: 1; min-height: 0; overflow: auto; display: flex; flex-direction: column-reverse; }
.console .log li { padding: 2px 4px; word-break: break-word; }

/* sidebar */
.search { width: 100%; padding: 8px 10px; border-radius: 6px; border: 1px solid var(--line); background: var(--bg); color: var(--ink); margin-bottom: 8px; }
.search:focus { outline: 1px solid var(--accent); }
.group summary { cursor: pointer; padding: 6px 4px; color: var(--muted); text-transform: uppercase; font-size: 11px; letter-spacing: .06em; }
.group .count { float: right; }
.list { list-style: none; margin: 0 0 6px; padding: 0; }
.row { display: flex; align-items: center; gap: 8px; padding: 5px 6px; border-radius: 5px; cursor: pointer; }
.row:hover { background: var(--card); }
.row.open { background: var(--card); box-shadow: inset 2px 0 0 var(--accent); }
.row.active { background: var(--card); outline: 1px solid var(--accent); outline-offset: -1px; }
.dot { width: 8px; height: 8px; border-radius: 50%; background: var(--type-colour, var(--muted)); flex: none; }
.rowtitle { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bad { color: var(--c-monster); font-weight: bold; margin-left: auto; }
.empty { color: var(--muted); padding: 6px; }

/* type colours resolve through one custom property */
[data-type="npc"] { --type-colour: var(--c-npc); }
[data-type="pc"] { --type-colour: var(--c-pc); }
[data-type="monster"] { --type-colour: var(--c-monster); }
[data-type="item"] { --type-colour: var(--c-item); }
[data-type="location"] { --type-colour: var(--c-location); }
[data-type="organization"] { --type-colour: var(--c-organization); }
[data-type="plan"] { --type-colour: var(--c-plan); }
[data-type="encounter"] { --type-colour: var(--c-encounter); }
[data-type="clock"] { --type-colour: var(--c-clock); }
[data-type="rule"] { --type-colour: var(--c-rule); }
[data-type="action"] { --type-colour: var(--c-action); }
[data-type="property"] { --type-colour: var(--c-property); }
[data-type="info"] { --type-colour: var(--c-info); }
[data-type="spell"] { --type-colour: var(--c-spell); }

/* cards */
.card { width: var(--card-w); height: var(--card-h); box-sizing: border-box; background: var(--card); border: 1px solid var(--type-colour, var(--line)); border-top-width: 3px; border-radius: var(--card-r); padding: 10px 12px; overflow: hidden; }
.table > .card { transition: transform .18s ease; touch-action: none; }
.card.dragging { transition: none; z-index: 10; box-shadow: 0 12px 28px rgba(0, 0, 0, .45); cursor: grabbing; }
.card.dropping { z-index: 10; }
body.dragging { user-select: none; cursor: grabbing; }
.card.template { border-style: dashed; }
/* the four-band layout, drawn as frames on the NPC template: header 30, art 147, main 147, footer 18, 8px between */
.card .band { border: 1px dashed var(--type-colour, var(--muted)); border-radius: 6px; display: grid; place-items: center; color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: .08em; box-sizing: border-box; }
.card .band-art { height: 147px; margin-top: 4px; }
.card .band-main { height: 147px; margin-top: 8px; }
.card .band-footer { height: 18px; margin-top: 8px; }
/* the art box: 246 x 172 (keep in step with ART_W / ART_H in app.js) */
.card .art { position: relative; height: 147px; margin: 4px 0 8px; border-radius: 6px; overflow: hidden; background: var(--bg); cursor: zoom-in; }
.card .art .alt { position: absolute; right: 6px; bottom: 6px; width: 22px; height: 22px; padding: 0; border: 0; border-radius: 5px; background: rgba(0, 0, 0, .55); color: #fff; display: grid; place-items: center; cursor: pointer; }
.card .art .alt:hover { background: rgba(0, 0, 0, .8); }
.card .art img { display: block; -webkit-user-drag: none; user-select: none; }
.card .art img.cover { width: 100%; height: 100%; object-fit: cover; }
.card .art img.cropped { position: absolute; left: 0; top: 0; transform-origin: 0 0; }
.card .art.placeholder { border: 1px dashed var(--type-colour, var(--muted)); background: transparent; cursor: default; display: grid; place-items: center; color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: .08em; }
.refs { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 6px; }
.dot.hollow { background: transparent; border: 1px dashed var(--type-colour, var(--muted)); box-sizing: border-box; }
.templaterow .rowtitle { color: var(--muted); }

/* popups: one at a time, centred over the table, table blurred behind */
.popup-layer { position: absolute; inset: 0; z-index: 20; display: grid; place-items: center; background: rgba(0, 0, 0, .25); backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px); cursor: pointer; }
.card.popup { box-shadow: 0 16px 40px rgba(0, 0, 0, .5); }
.popup-layer.artlayer { display: flex; align-items: stretch; justify-content: center; gap: 24px; padding: 24px; box-sizing: border-box; cursor: default; overflow: hidden; touch-action: none; }
.map2view > .popup-layer.artlayer { padding: calc(var(--bar-h) + 24px) 24px calc(var(--footer-h) + 24px); }   /* the whole map blurred, the picture fitted between bar and footer */
.map2info .ed-pic img { cursor: zoom-in; }
.artlayer .pane { flex: 1 1 0; min-width: 0; display: flex; align-items: center; justify-content: center; overflow: hidden; transition: flex-grow .2s ease; }
/* a zoomed pane takes centre stage: it grows and the others shrink beside it */
.artlayer .pane.zoomed { cursor: grab; flex-grow: 6; }
.artlayer img { max-width: 100%; max-height: 100%; object-fit: contain; transform-origin: 0 0; box-shadow: 0 16px 40px rgba(0, 0, 0, .5); -webkit-user-drag: none; user-select: none; }
.card.flash { animation: flash .6s; }
@keyframes flash { from { box-shadow: 0 0 0 3px var(--accent); } to { box-shadow: none; } }
.card header { display: flex; align-items: center; gap: 8px; height: 22px; margin-bottom: 4px; }
.card header h2 { font-size: 16px; margin: 0; flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.icon { background: none; border: none; color: var(--muted); cursor: pointer; padding: 0 3px; }
.icon:hover { color: var(--ink); }
.aliases { color: var(--muted); font-size: 12px; margin-bottom: 4px; }
.fields { display: grid; grid-template-columns: max-content 1fr; gap: 2px 10px; margin: 6px 0; font-size: 13px; }
.fields dt { color: var(--muted); }
.fields dd { margin: 0; }
.body h2 { font-size: 11px; text-transform: uppercase; letter-spacing: .08em; color: var(--muted); margin: 10px 0 2px; }
.body p { margin: 0 0 6px; }
.body ul { margin: 0 0 6px; padding-left: 18px; }
.wl { border-bottom: 1px dotted var(--accent); }
.wl.missing { color: var(--muted); border-bottom-style: dashed; }
.tags { margin-top: 6px; }
.tag { display: inline-block; font-size: 11px; color: var(--muted); background: var(--bg); border-radius: 4px; padding: 1px 6px; margin-right: 4px; }
.backlinks { margin-top: 8px; display: flex; flex-wrap: wrap; gap: 4px; align-items: center; }
.backlinks .label { font-size: 11px; color: var(--muted); margin-right: 4px; }
.chip { font-size: 12px; background: var(--bg); border-radius: 12px; padding: 1px 8px; border: 0; border-left: 3px solid var(--type-colour, var(--muted)); color: var(--ink); font-family: inherit; line-height: 16px; white-space: nowrap; cursor: pointer; }
.chip.missing { color: var(--muted); cursor: default; }
.chip.status-ally { --type-colour: var(--c-ally); }
.chip.status-neutral { --type-colour: var(--c-neutral); }
.chip.status-enemy { --type-colour: var(--c-enemy); }
/* the footer band: one row of chips at the bottom of the card, clipped to the band */
.card { position: relative; }
.cardfoot { position: absolute; left: 12px; right: 12px; bottom: 12px; height: 18px; display: flex; gap: 4px; align-items: center; overflow: hidden; }
.cardfoot .chip { flex: none; }
.band.band-footer.cardfoot { position: static; border: 0; display: flex; justify-content: flex-start; text-transform: none; letter-spacing: 0; }
.band.band-main.main { border: 0; display: block; text-transform: none; letter-spacing: 0; font-size: 13px; color: var(--ink); }

/* the main band of an NPC: 147 tall, a grid, voice, wants, then the section chips */
.main { height: 147px; overflow: hidden; display: flex; flex-direction: column; gap: 3px; }
.main .line { display: flex; gap: 6px; font-size: 13px; line-height: 18px; white-space: nowrap; }
.main .k { flex: none; font-weight: 600; color: var(--muted); }
.main .v { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.main .sections { display: flex; flex-wrap: wrap; gap: 4px; margin: auto 0; }   /* centred in the space under the lines */
.chip.empty { color: var(--muted); }
.chip:disabled { cursor: default; }
/* a card's subtitle: one italic line under the title */
.card .subtitle { font-style: italic; font-size: 13px; color: var(--muted); margin: -2px 0 6px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* encounter timeline: in the art band's place, phases as dots on a line, scaled to fit */
.card .timeline { position: relative; height: 147px; margin: 4px 0 8px; border-radius: 6px; background: var(--bg); overflow: hidden; }
.card .timeline.placeholder { display: grid; place-items: center; box-sizing: border-box; background: transparent; border: 1px dashed var(--type-colour, var(--muted)); color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: .08em; }
.timeline .phases { position: absolute; left: 50%; top: 50%; width: max-content; display: grid; grid-template-columns: 18px auto auto; column-gap: 8px; transform-origin: center; }
.timeline .phase { display: contents; }
.timeline .phase > span { height: 26px; display: flex; align-items: center; font-size: 13px; white-space: nowrap; }
.timeline .rail { position: relative; }
.timeline .rail::before { content: ''; position: absolute; left: 8px; top: 0; bottom: 0; width: 2px; background: var(--type-colour, var(--muted)); opacity: .5; }
.timeline .phase:first-child .rail::before { top: 13px; }
.timeline .phase:last-child .rail::before { bottom: 13px; }
.timeline .node { position: absolute; left: 4px; top: 8px; width: 10px; height: 10px; border-radius: 50%; background: var(--type-colour, var(--muted)); box-shadow: 0 0 0 3px var(--bg); }
.timeline .pk { font-weight: 600; color: var(--muted); }
.timeline .pv { color: var(--ink); }
.encounterfoot { justify-content: space-between; }
/* encounter main: 10px padding plus the 8px margins make a blank line of 18px under the
   timeline and above the footer. Details are a grid with a shared title column; content
   wraps in its column, and whatever does not fit is clipped above the chips. */
.main.encountermain { padding: 10px 0; box-sizing: border-box; }
.encountermain .details { flex: 0 1 auto; min-height: 0; overflow: hidden; display: grid; grid-template-columns: max-content minmax(0, 1fr); column-gap: 6px; row-gap: 3px; align-content: start; font-size: 13px; line-height: 18px; }
.encountermain .details .v { overflow-wrap: anywhere; }
.encountermain .sections { flex: none; }
.layout.dev .card.clipped { outline: 2px dashed #d95a5a; outline-offset: 3px; }
.encounterfoot .xp { font-size: 12px; color: var(--muted); }

/* numbered items and tables inside text popups */
.card.popup.text .body ol { margin: 0; padding-left: 20px; }
.card.popup.text .body table { border-collapse: collapse; font-size: 13px; margin: 0 0 8px; }
.card.popup.text .body th { font-size: 11px; letter-spacing: .06em; color: var(--muted); text-align: left; padding: 2px 12px 2px 0; border-bottom: 1px solid var(--line); }
.card.popup.text .body td { padding: 3px 12px 3px 0; vertical-align: top; }

/* a text popup grows with its longest line up to two cards wide and the table's height */
.card.popup.text { width: max-content; min-width: var(--card-w); max-width: calc(2 * var(--card-w)); height: auto; min-height: 0; max-height: calc(100% - 48px); cursor: default; }
.card.popup.text header { margin-bottom: 12px; }
.card.popup.text header h2 { white-space: normal; }
.card.popup.text .body { font-size: 13px; }
.card.popup.text .body p, .card.popup.text .body li { margin: 0 0 8px; }
.filterchip { display: flex; align-items: center; gap: 6px; padding: 6px 4px; }

/* monster main: labels that open the stat block, chips capped at two rows */
.main .k.link { background: none; border: 0; padding: 0; font: inherit; font-weight: 600; color: var(--muted); cursor: pointer; border-radius: 3px; }
.main .k.link:hover { color: var(--ink); background: var(--bg); }
.main .sections { max-height: 40px; overflow: hidden; }
.card.popup.text .body.phb { font-size: 13px; }
.card.popup.text .phbline { font-size: 13px; margin: 0 0 8px; }
.card.popup.text .phbline b { color: var(--muted); }
.abil { border-collapse: collapse; font-size: 13px; margin: 4px 0 10px; }
.abil th { font-size: 11px; letter-spacing: .06em; color: var(--muted); padding: 2px 8px; text-align: center; border-bottom: 1px solid var(--line); }
.abil td { padding: 3px 8px; text-align: center; white-space: nowrap; }
.abil.portrait td:first-child { color: var(--muted); font-size: 11px; letter-spacing: .06em; text-align: left; }
.abil.portrait td { padding: 1px 8px; }
.twin { align-items: flex-start; }
.abil.portrait td:last-child { text-align: right; }
.twin { display: flex; gap: 24px; }

/* monster footer: HP on the left, duplicate on the right */
.monsterfoot { justify-content: space-between; }
.monsterfoot .hp { display: flex; align-items: center; gap: 5px; font-size: 13px; }
.monsterfoot .hp .k { font-weight: 600; color: var(--muted); font-size: 11px; letter-spacing: .04em; }
.monsterfoot .hp .cur { font-size: 13px; font-weight: 600; color: var(--ink); padding: 0; }
.card.bloodied .hp .cur { color: #d95a5a; }
.monsterfoot .hpin { width: 40px; height: 18px; box-sizing: border-box; font: inherit; font-size: 13px; font-weight: 600; text-align: center; background: var(--bg); color: var(--ink); border: 1px solid var(--accent); border-radius: 4px; padding: 0 2px; }
.monsterfoot .icon.small { font-size: 12px; padding: 0 2px; }
.monsterfoot .k.step { background: none; border: 0; padding: 0 3px; font: inherit; font-size: 13px; font-weight: 600; color: var(--muted); cursor: pointer; border-radius: 3px; line-height: 16px; }
.monsterfoot .k.step:hover { color: var(--ink); background: var(--bg); }
.chip.copy { --type-colour: var(--c-monster); }
span.chip.copy { cursor: default; color: var(--muted); }

/* half HP or less: the bloodied frame over the art; zero: the art drains of colour and a
   skull sits over its centre (the skull itself keeps its black and white) */
.card .art::after { content: ''; position: absolute; inset: 0; pointer-events: none; background: url('./bloodied.svg') center / 100% 100% no-repeat; opacity: 0; transition: opacity .25s ease; }
.card.bloodied .art::after { opacity: 1; }
.card.dead .art::after { opacity: 1; background: url('./skull.svg') center / 64px 64px no-repeat; filter: drop-shadow(0 2px 6px rgba(0, 0, 0, .6)); }
.card.dead .art img { filter: grayscale(1) brightness(.6); }
/* monster block */
.stat { background: var(--bg); border-radius: 6px; padding: 8px; margin: 6px 0; font-size: 13px; }
.statline { display: flex; gap: 14px; flex-wrap: wrap; align-items: center; }
.hp input { width: 52px; background: var(--card); color: var(--ink); border: 1px solid var(--line); border-radius: 4px; padding: 2px 4px; text-align: center; }
.hp .max { color: var(--muted); }
.abilities { display: flex; gap: 10px; margin-top: 6px; color: var(--muted); }
.abilities b { color: var(--ink); }
.statlist { margin-top: 6px; }
.statlist .label { font-size: 11px; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); }
.statlist ul { margin: 2px 0 0; padding-left: 16px; }

/* clock block */
.clock { display: flex; align-items: center; gap: 10px; margin: 6px 0; }
.segments { display: flex; gap: 3px; flex-wrap: wrap; }
.seg { width: 14px; height: 14px; border-radius: 3px; border: 1px solid var(--c-clock); cursor: pointer; }
.seg.on { background: var(--c-clock); }
.clocklabel { color: var(--muted); font-size: 12px; }

/* misc */
.hint { color: var(--muted); padding: 20px; margin-top: var(--bar-h); }
.fatal { color: var(--c-monster); padding: 20px; margin-top: var(--bar-h); }
.linkish { background: none; border: none; color: var(--accent); cursor: pointer; padding: 0; }
.muted { color: var(--muted); }

/* Portrait: the table on top, sized to its rows; below it the nav (one column, scrolling)
   beside the console. Chosen by orientation. */
.layout.portrait { grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); grid-template-rows: auto minmax(0, 1fr); }
.layout.portrait .table { grid-column: 1 / -1; grid-row: 1; height: calc(var(--rows, 3) * var(--card-h) + (var(--rows, 3) + 1) * 18px); border-bottom: 1px solid var(--line); }
.layout.portrait .sidebar { grid-column: 1; grid-row: 2; width: auto; }
.layout.portrait .console { grid-column: 2; grid-row: 2; }
