/* Wumpus (Wumpus Survey until 2026-10-06): an icon map with readable, plain-language clues.
 * Quiet controls frame the cave; room knowledge stays beside its symbols. */

@font-face {
  font-family: "Plex Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("./fonts/IBMPlexMono-500.woff2") format("woff2");
}
@font-face {
  font-family: "Plex Sans";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("./fonts/IBMPlexSans-400.woff2") format("woff2");
}


:root{
 color-scheme:light;--bg:#ffffff;--ink:#000000;--text:#111111;--sub:#5e5e5e;--line:#d4d4d4;--guide:#8f8f8f;
 --frame:#1c1c1c;--band:rgba(0,0,0,.05);--scrim:rgba(255,255,255,.84);
 --mono:"Plex Mono",ui-monospace,monospace;--sans:"Plex Sans",system-ui,sans-serif;
}
@media(prefers-color-scheme:dark){:root:not([data-theme="light"]){color-scheme:dark;--bg:#000000;--ink:#ffffff;--text:#ededed;--sub:#a6a6a6;--line:#2f2f2f;--guide:#8f8f8f;--frame:#ededed;--band:rgba(255,255,255,.06);--scrim:rgba(0,0,0,.8)}}
:root[data-theme="dark"]{color-scheme:dark;--bg:#000000;--ink:#ffffff;--text:#ededed;--sub:#a6a6a6;--line:#2f2f2f;--guide:#8f8f8f;--frame:#ededed;--band:rgba(255,255,255,.06);--scrim:rgba(0,0,0,.8)}
*,*::before,*::after{box-sizing:border-box}
html{height:100%;overflow:hidden;overscroll-behavior:none;background:var(--bg);color:var(--text);font:16px/1.4 var(--sans);-webkit-text-size-adjust:100%}
body{margin:0;height:100%;overflow:hidden;overscroll-behavior:none;background:var(--bg);color:var(--text);font-size:18px}
button,input{font:inherit;color:inherit}button{cursor:pointer;touch-action:manipulation}button:disabled{cursor:default;opacity:.45}
button,a,summary{ -webkit-tap-highlight-color:transparent }
[hidden]{display:none!important}
.sr-only{position:absolute!important;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}
:focus-visible{outline:2px solid var(--ink);outline-offset:2px}
.skip{position:fixed;z-index:20;top:12px;left:16px;padding:10px;background:var(--bg);color:var(--text)}
.skip:not(:focus){width:1px;height:1px;overflow:hidden;clip-path:inset(50%)}

/* The map is the page: a fixed SVG under the whole viewport. Everything else
   floats over it, and the plate is the rectangle that chrome leaves clear.
   Every reserve is px, so the plate depends only on the viewport. */
:root{--top:48px;--strip:112px;--bar:60px;--side:0px;--right:0px;--pad:0px}
#map{position:fixed;inset:0;width:100%;height:100%;display:block;touch-action:manipulation;user-select:none;-webkit-user-select:none}
#map:focus{outline:none}
#map.pannable{touch-action:pinch-zoom;cursor:grab}#map.dragging,#map.dragging .room{cursor:grabbing}
#plate{position:fixed;visibility:hidden;pointer-events:none;
  top:calc(var(--top) + var(--pad) + env(safe-area-inset-top));
  bottom:calc(var(--bar) + var(--strip) + var(--pad) + env(safe-area-inset-bottom));
  left:calc(var(--side) + env(safe-area-inset-left));
  right:calc(var(--right) + env(safe-area-inset-right))}
main:has(#map:focus-visible) #plate{visibility:visible;outline:2px solid var(--ink);outline-offset:-2px}

/* The readout: one quiet mono line at the top centre of the plate. Its
   band fades into the map below it. */
.hud{position:fixed;z-index:3;top:0;left:calc(var(--side) + env(safe-area-inset-left));right:calc(var(--right) + env(safe-area-inset-right));
  height:calc(var(--top) + env(safe-area-inset-top));padding-top:env(safe-area-inset-top);
  display:flex;align-items:center;justify-content:center;gap:1.2em;white-space:nowrap;pointer-events:none;
  font:500 13px/1 var(--mono);letter-spacing:.02em;font-variant-numeric:tabular-nums;color:var(--sub);
  background:linear-gradient(var(--bg) calc(100% - 12px),transparent)}
.hud b{font-weight:inherit;color:inherit}

/* Chrome never swallows map taps: only its buttons take pointer events. */
.strip{pointer-events:none}
.strip button{pointer-events:auto}

/* The strip rests on the toolbar and is only as tall as what it says
   (at most 112px: 8 + one 44px control row + 6 + two 22px lines + 10). */
.strip{position:fixed;z-index:3;left:0;right:0;margin:0 auto;width:min(100%,560px);
  bottom:calc(var(--bar) + env(safe-area-inset-bottom));
  display:flex;flex-direction:column;justify-content:flex-end;gap:6px;
  padding:8px max(16px,env(safe-area-inset-right)) 10px max(16px,env(safe-area-inset-left));
  background:linear-gradient(transparent,var(--bg) 8px);font-size:17px;line-height:22px}
.strip p{margin:0}
#caption{order:1}#strip-text,.movement-feedback{order:2}#bow-panel{order:3}
#strip-text{font-size:17px;line-height:22px;color:var(--sub);text-wrap:pretty}
.strip:has(#movement-status:not(:empty)) #strip-text{display:none}
.movement-feedback{display:flex;align-items:center;gap:8px}
.movement-feedback:has(#movement-status:empty):has(#skip-movement[hidden]){display:none}
#movement-status{flex:1;min-width:0;font-size:17px;line-height:22px;color:var(--text)}#movement-status:empty{display:none}
.movement-button{flex:none;min-height:44px;min-width:44px;margin-left:auto;border:0;padding:0 10px;background:none;color:var(--text);text-decoration:underline;text-underline-offset:4px;font-size:16px}

/* Warning chips: one 44px row that never wraps. Long names give way to
   short names, then to icons alone (fitChips in survey.js). */
#caption{display:flex;gap:8px;flex-wrap:nowrap;overflow:hidden}
#caption:empty{display:none}
.caption-clue{flex:none;display:inline-flex;align-items:center;gap:6px;min-height:44px;margin:0;padding:0 12px 0 6px;border:1px solid var(--ink);border-radius:0;background:var(--bg);color:var(--text);font-size:16px;line-height:1.2;white-space:nowrap}
.caption-clue>.clue-icon{width:28px;height:28px;flex:none;padding:0;overflow:visible}
.caption-clue[aria-pressed=true],.caption-clue[aria-pressed=true]:hover{background:var(--ink);color:var(--bg)}
.caption-clue[aria-pressed=true] .sense,.caption-clue[aria-pressed=true] .stale-strike{stroke:var(--bg)}
.caption-clue:disabled{opacity:1;color:var(--sub);border-color:var(--sub)}
.clue-short{display:none}
#caption.compact .clue-name{display:none}#caption.compact .clue-short{display:inline}
#caption.icons .clue-short{display:none}#caption.icons .caption-clue{width:44px;padding:0;justify-content:center}
.caption-clue[data-pulse=true]>svg{animation:clue-pulse 650ms ease-in-out 2;transform-origin:center}
@keyframes clue-pulse{0%,100%{transform:scale(1);opacity:.8}50%{transform:scale(1.14);opacity:1}}
.guide-icons>svg.clue-icon{width:44px;height:44px;flex:0 0 44px;padding:0;overflow:visible}
.room.clue-neighbor .rim{stroke:var(--ink);stroke-width:2}
.room.clue-source .focus-ring{visibility:visible;stroke-width:1.5;stroke-dasharray:2 4}.clue-selected .sense{stroke-width:2}

/* Aim: the path line is the strip text; Shoot and Clear sit under it. */
#bow-panel{display:flex;gap:8px}
#bow-panel .ib{display:inline-flex;align-items:center;justify-content:center;gap:8px;min-height:44px;padding:0 14px;font:500 15px/1.2 var(--mono);border:1px solid var(--line);color:var(--text)}
#loose:not(:disabled){background:var(--ink);color:var(--bg);border-color:var(--ink)}

/* Find me: the plate's bottom-right corner, only when your room is off the plate. */
.map-btn{position:fixed;z-index:3;right:calc(var(--right) + env(safe-area-inset-right) + 8px);
  bottom:calc(var(--bar) + var(--strip) + var(--pad) + env(safe-area-inset-bottom) + 8px);
  min-height:44px;min-width:44px;padding:0 14px;border:1px solid var(--ink);border-radius:0;background:var(--bg);color:var(--text);font-size:16px}

.edge{position:fixed;pointer-events:none}
/* ?probe=1 only: measurements for the Simulator check. */
#probe{position:fixed;z-index:4;top:calc(var(--top) + var(--pad) + env(safe-area-inset-top) + 4px);left:calc(var(--side) + env(safe-area-inset-left) + 4px);
  margin:0;padding:4px 6px;background:var(--scrim);color:var(--text);font:500 12px/1.35 var(--mono);pointer-events:none;white-space:pre}
#probe-insets{position:fixed;top:0;left:0;visibility:hidden;pointer-events:none;
  padding:env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left)}

/* Bottom bar: play on the left (three tools and Undo), Settings and Help on
   the right. Icons only; names live in aria-label. */
.bar{position:fixed;z-index:3;left:0;right:0;bottom:0;margin:0 auto;width:min(100%,560px);
  height:calc(var(--bar) + env(safe-area-inset-bottom));
  padding:0 max(4px,env(safe-area-inset-right)) env(safe-area-inset-bottom) max(4px,env(safe-area-inset-left));
  display:flex;justify-content:space-between;align-items:center;background:var(--bg)}
.group,.tools{display:flex;align-items:center;gap:2px}
.ib{display:grid;place-items:center;gap:3px;min-width:48px;min-height:48px;padding:0;border:0;border-radius:0;background:none;color:var(--sub);transition:opacity .15s,transform .1s}
.ib:active:not(:disabled){transform:scale(.94)}
.ib svg{width:24px;height:24px}.bar .ib{position:relative;width:48px;height:48px}
.tool[aria-checked=true]{color:var(--ink)}.tool[aria-checked=true]::after{content:"";position:absolute;bottom:2px;width:22px;height:2px;background:var(--ink)}
@media(hover:hover){button:hover:not(:disabled){background:var(--band)}#loose:hover:not(:disabled),.caption-clue[aria-pressed=true]:hover{background:var(--ink)}}

@media(max-width:360px){#strip-text,#movement-status{font-size:16px;line-height:21px}#caption{gap:6px}.caption-clue{gap:4px;padding:0 10px 0 4px}}
@media(max-width:340px){.hud-word{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}}
@media(min-width:900px){
  :root{--top:64px;--strip:116px;--bar:68px}
  #strip-text,#movement-status{font-size:18px;line-height:24px}
}

/* Sheets: Settings and How to play, plus two small confirmations. The
   header stays put; only the body scrolls. */
dialog.sheet{width:min(32rem,calc(100vw - 16px));max-width:none;max-height:calc(100dvh - 16px - env(safe-area-inset-top) - env(safe-area-inset-bottom));
  height:fit-content;padding:0;margin:auto;border:1px solid var(--frame);border-radius:0;background:var(--bg);color:var(--text);overflow:hidden}
dialog.sheet[open]{display:block}
dialog.sheet::backdrop{background:var(--scrim)}
.sheet-in{max-height:calc(100dvh - 18px - env(safe-area-inset-top) - env(safe-area-inset-bottom));display:flex;flex-direction:column;min-height:0;width:100%;font:400 16px/1.45 var(--sans)}
.sheet-head{display:flex;flex:none;align-items:center;justify-content:space-between;gap:12px;padding:8px 16px;border-bottom:1px solid var(--line)}
.sheet-head form{margin:0}
.sheet h2{margin:0;font:500 16px/1.3 var(--mono)}
.sheet-x{display:grid;place-items:center;width:44px;height:44px;padding:0;border:0;background:none;color:var(--text)}
.sheet-x svg{width:24px;height:24px}
.sheet-body{min-height:0;overflow:auto;overscroll-behavior:contain;padding:20px 24px;scroll-padding:12px}
.sheet p{margin:0 0 16px;max-width:60ch}
.sheet h3{margin:0 0 4px;font:400 16px/1.4 var(--sans);color:var(--sub)}
.sheet section+section{border-top:1px solid var(--line);margin-top:16px;padding-top:16px}
.value{color:var(--sub);font:500 14px/1.3 var(--mono);font-variant-numeric:tabular-nums}
.setting-row{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:4px 16px;min-height:48px;margin:0}
.text-action{appearance:none;min-width:44px;min-height:44px;padding:8px 12px;border:1px solid var(--line);border-radius:0;background:none;color:var(--text);font:500 16px/1.3 var(--mono)}
.text-action[aria-checked=true]{border-color:var(--frame);color:var(--ink)}
.pan{display:flex;gap:2px}.pan .ib{color:var(--text);font:500 18px/1 var(--mono)}
.row{display:flex;align-items:center;justify-content:space-between;gap:12px;width:100%;min-height:48px;margin:0;padding:8px 0;border:0;background:none;text-align:left;font:400 16px/1.3 var(--sans)}
.row:disabled .value{display:none}
details summary{min-height:48px;padding:12px 0;cursor:pointer}
.exits{list-style:none;margin:0;padding:0}.exits button{display:flex;align-items:center;gap:12px;width:100%;min-height:52px;padding:6px 0;border:0;text-align:left;background:none;font-size:16px}.exits svg{width:24px;height:24px;flex:none}.exits small{display:block;font-size:14px;color:var(--sub)}
#journal{max-height:220px;overflow:auto;margin:0;padding-left:28px;font-size:15px;color:var(--sub)}#journal li{padding:4px 0}.bad{color:var(--text)}
.controls{margin:0;display:grid;grid-template-columns:max-content minmax(0,1fr);align-items:center;gap:10px 16px}
.controls div{display:contents}
.controls dt{display:inline-flex;align-items:center;gap:8px;color:var(--text)}
.controls dt svg{width:24px;height:24px;flex:none}
.controls dd{margin:0;color:var(--sub)}
kbd{font:500 14px/1 var(--mono);color:var(--sub)}
.sheet-foot{display:flex;flex-wrap:wrap;align-items:center;gap:0 16px;border-top:1px solid var(--line);padding-top:8px;margin-top:20px;font-size:14px;color:var(--sub)}
.foot-btn{display:inline-flex;align-items:center;min-height:44px;color:var(--sub);text-underline-offset:3px}
.confirm-actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px}.confirm-actions form{margin:0}
@media(max-width:480px){.sheet-body{padding:16px}.sheet-head{padding:8px 12px}}
.tunnel, .ex-tunnel { fill: none; stroke: var(--ink); stroke-width: 1.2; vector-effect: non-scaling-stroke; }
:is(.tunnel, .ex-tunnel).ghost { stroke: var(--sub); stroke-dasharray: 3 5; }
.tunnel.reveal { stroke: var(--sub); stroke-dasharray: 1 4; }
.tunnel.draw { animation: draw .3s ease-out; stroke-dasharray: var(--len); }
@keyframes draw { from { stroke-dashoffset: var(--len); } to { stroke-dashoffset: 0; } }
.room { outline: none; }
.room .hit { fill: transparent; }
:is(.room, .ex-room) .rim { fill: var(--bg); stroke: var(--ink); stroke-width: 1.2; vector-effect: non-scaling-stroke; }
:is(.room, .ex-room).glimpsed .rim { stroke: var(--sub); stroke-dasharray: 3 4; }
.room.revealed .rim { stroke: var(--sub); stroke-dasharray: 1 3; }
:is(.room, .ex-room).here .rim { fill: var(--ink); stroke: var(--ink); stroke-dasharray: none; }
.room .focus-ring { fill: none; stroke: var(--ink); stroke-width: 2; vector-effect: non-scaling-stroke; visibility: hidden; pointer-events: none; }
.room:focus-visible .focus-ring { visibility: visible; }
.room.target, #map.picking { cursor: pointer; }
.room.target.hover .rim { stroke-width: 2; }
/* Unexplored-room dots: positions only. Opacity comes from STATION_OPACITY. */
.station { fill: var(--guide); stroke: none; pointer-events: none; }
/* A pressed chip: a solid 3px ring 5px outside each candidate's rim, and
   solid 2.5px tunnels from your room to them. */
.cand { fill: none; stroke: var(--ink); stroke-width: 3; stroke-dasharray: none; vector-effect: non-scaling-stroke; pointer-events: none; }
.tunnel.clue-connection { stroke: var(--ink); stroke-width: 2.5; stroke-dasharray: none; animation: none; }
.layer-notes, .layer-flight { pointer-events: none; }
.sense, .stale-strike { fill: none; stroke: var(--ink); stroke-width: 1.5; vector-effect: non-scaling-stroke; stroke-linecap: round; stroke-linejoin: round; }
.stale { opacity: .45; }
.flight { fill: none; stroke: var(--ink); stroke-width: 1.5; vector-effect: non-scaling-stroke; stroke-dasharray: 5 4; }
.flight.loosed { stroke-dasharray: var(--len); animation: draw var(--dur) ease-out; }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}
@media (forced-colors: active) {
  :root { --ink: CanvasText; --text: CanvasText; --bg: Canvas; --sub: CanvasText; --frame: CanvasText; --line: GrayText; }
  #map { forced-color-adjust: none; }
}

.room-symbol, .exit-direction, .flight-tip {
  fill: none;
  stroke: var(--ink);
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  pointer-events: none;
}
.room-symbol path, .room-symbol circle, .room-symbol ellipse,
.exit-direction, .flight-tip { vector-effect: non-scaling-stroke; }
:is(.room, .ex-room).here .room-symbol { stroke: var(--bg); }
.room-symbol[data-certainty="guess"] { stroke: var(--sub); }
.guess-badge circle { fill: var(--bg); stroke: none; }
.guess-badge path { stroke: var(--sub); stroke-width: 1.2; }
.aim-ring { fill: none; stroke: var(--ink); stroke-width: 1.5; stroke-dasharray: 2 3; vector-effect: non-scaling-stroke; pointer-events: none; }
.flight-tip { paint-order: stroke; stroke-width: 2; }
/* Causal movement: temporary aerial traces never become map tunnels. */
.layer-movement { pointer-events: none; }
.walk-route, .bat-route, .movement-ring { fill: none; stroke: var(--ink); vector-effect: non-scaling-stroke; }
.walk-route { stroke-width: 2.5; }
.bat-route { stroke-width: 1.5; stroke-dasharray: 1 7; stroke-linecap: round; }
.movement-ring { stroke-width: 1.5; }
.movement-ring.departure { stroke-dasharray: 3 4; }
.movement-ring.arrival { stroke-width: 2; }
.movement-label { fill: var(--ink); font-family: var(--mono); text-anchor: middle; paint-order: stroke; stroke: var(--bg); stroke-width: 5px; stroke-linejoin: round; }
.traveler-disc { fill: var(--ink); stroke: var(--bg); stroke-width: 2; }
.traveler .room-symbol { stroke: var(--bg); }
.traveler [data-symbol="bats"] { stroke: var(--ink); paint-order: stroke; }
#map[data-moving] .room.here .rim { fill: var(--bg); }
#map[data-moving] .room.here > .room-symbol { opacity: 0; }

@media(prefers-reduced-motion:reduce){*,*::before,*::after{animation:none!important;transition:none!important}}
@media(forced-colors:active){.caption-clue{border-color:ButtonText}.caption-clue[aria-pressed=true]{outline:2px solid Highlight}.tunnel.clue-connection,.cand,.room.clue-neighbor .rim,.clue-selected .sense{stroke:Highlight}.tool[aria-checked=true]{outline:1px solid Highlight}}

#end-actions{order:3;display:flex;gap:6px}
#end-actions button{flex:1 1 auto;min-height:44px;padding:4px 8px;font:500 15px/1.2 var(--mono);border:1px solid var(--line);border-radius:0;background:var(--bg)}
.edge{z-index:2}
.edge[data-side=top]{top:calc(var(--top) + var(--pad) + env(safe-area-inset-top));left:calc(var(--side) + env(safe-area-inset-left));right:calc(var(--right) + env(safe-area-inset-right));height:14px;background:linear-gradient(var(--bg),transparent)}
.edge[data-side=bottom]{bottom:calc(var(--bar) + var(--strip) + var(--pad) + env(safe-area-inset-bottom));left:calc(var(--side) + env(safe-area-inset-left));right:calc(var(--right) + env(safe-area-inset-right));height:14px;background:linear-gradient(transparent,var(--bg))}
.edge[data-side=left],.edge[data-side=right]{top:calc(var(--top) + var(--pad) + env(safe-area-inset-top));bottom:calc(var(--bar) + var(--strip) + var(--pad) + env(safe-area-inset-bottom));width:14px}
.edge[data-side=left]{left:calc(var(--side) + env(safe-area-inset-left));background:linear-gradient(90deg,var(--bg),transparent)}
.edge[data-side=right]{right:calc(var(--right) + env(safe-area-inset-right));background:linear-gradient(90deg,transparent,var(--bg))}
@media(max-height:500px) and (orientation:landscape){
 :root{--top:28px;--bar:0px;--strip:0px;--side:232px;--right:64px;--pad:8px}
 .strip{left:0;right:auto;width:calc(var(--side) + env(safe-area-inset-left));bottom:env(safe-area-inset-bottom);padding:8px 12px 10px max(12px,env(safe-area-inset-left));font-size:16px;line-height:21px}
 #strip-text,#movement-status{font-size:16px;line-height:21px}
 #caption{flex-wrap:wrap;gap:4px}.caption-clue{padding:0 5px;gap:4px}
 .bar{left:auto;right:0;top:0;width:calc(64px + env(safe-area-inset-right));height:100dvh;flex-direction:column;
   padding:max(4px,env(safe-area-inset-top)) env(safe-area-inset-right) max(4px,env(safe-area-inset-bottom)) 0}
 .bar .group,.bar .tools{flex-direction:column}
 #end-actions{flex-wrap:wrap}
}

/* Recorded clues near another room retain an explicit source attachment. */
.clue-source-leader{fill:none;stroke:var(--sub);stroke-width:1;vector-effect:non-scaling-stroke;pointer-events:none}
