:root {
  --bg: #001400;
  --fg: #33ff66;
  --fg-dim: #1f9944;
  --fg-bright: #a6ffc1;
  --error: #ff5533;
  --title: #ffcc33;
  --image: #33ccff;
}

* {
  box-sizing: border-box;
}

/* `dvh` (dynamic viewport height) is the unit that actually shrinks with
   the on-screen keyboard on a phone — `%`/`vh` measure the layout viewport,
   which most mobile browsers leave full-size behind the keyboard instead of
   resizing. The plain `100%`/`100vh` line first is a fallback for browsers
   old enough not to know `dvh` at all; they simply ignore the line after
   it, so this needs no @supports check. Set on both html and body, the same
   pairing used for this in kira-platform's app/layout.js. */
html {
  height: 100%;
  height: 100dvh;
}

/* Set on <html> while the map popup is open — belt and suspenders against
   page-level scroll, on top of the popup's own containment. */
html.map-open, html.map-open body,
html.boss-open, html.boss-open body {
  overflow: hidden;
}

body {
  margin: 0;
  height: 100%;
  height: 100dvh;
  background: #000;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: "Courier New", ui-monospace, "Cascadia Mono", "Consolas", monospace;
}

#crt {
  width: min(900px, 96vw);
  height: min(800px, 92vh);
  background: var(--bg);
  border: 2px solid var(--fg-dim);
  border-radius: 10px;
  box-shadow:
    0 0 24px rgba(51, 255, 102, 0.35),
    inset 0 0 60px rgba(0, 0, 0, 0.7);
  padding: 20px 24px;
  display: flex;
  flex-direction: column;
  cursor: text;
  position: relative;
  overflow: hidden;
}

/* subtle scanlines + phosphor glow */
#crt::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: repeating-linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0.15) 0px,
    rgba(0, 0, 0, 0.15) 1px,
    transparent 2px,
    transparent 3px
  );
  mix-blend-mode: multiply;
}

#crt::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  box-shadow: inset 0 0 90px rgba(0, 0, 0, 0.6);
  border-radius: 10px;
}

#screen {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  color: var(--fg);
  text-shadow: 0 0 4px rgba(51, 255, 102, 0.6);
}

#output {
  position: relative;
  flex: 1;
  overflow-y: auto;
  white-space: pre-wrap;
  word-wrap: break-word;
  font-size: 15px;
  line-height: 1.5;
  padding-right: 6px;
}

#output .entry {
  margin: 0 0 14px 0;
}

#output .entry.echo {
  color: var(--fg-bright);
  opacity: 0.9;
}

#output .entry.error {
  color: var(--error);
  text-shadow: 0 0 4px rgba(255, 85, 51, 0.6);
}

/* Boot-time ASCII wordmark: exact-width art, so it scrolls horizontally on a
   narrow screen instead of wrapping (which would destroy the letterforms),
   and it skips the bold/underline/title markdown convention entirely (see
   printLogo) so the figlet art's own underscores and asterisks can't be
   misread as it. */
#output .entry.logo {
  color: var(--fg-bright);
  text-shadow: 0 0 6px rgba(166, 255, 193, 0.55);
  white-space: pre;
  overflow-x: auto;
  font-size: 6.5px;
}

/* A sector's own optional uploaded image, shown above its title
   (see printImage in app.js). Capped to a fraction of the screen's own
   height so one image can't push the text below it out of view, and
   `object-fit: contain` keeps an unusual aspect ratio from being cropped. */
#output .entry.image img {
  display: block;
  max-width: 100%;
  max-height: 50vh;
  object-fit: contain;
  margin: auto;
}

#output strong {
  color: var(--fg-bright);
  font-weight: bold;
}

#output strong.title {
  color: var(--title);
}

#output u {
  color: var(--fg-bright);
  font-weight: normal;
  text-decoration: underline;
  text-underline-offset: 3px;
}

#output a {
  color: var(--fg-bright);
  text-decoration: underline;
  text-underline-offset: 3px;
}

#output a:hover,
#output a:focus-visible {
  color: var(--title);
}

#update-banner {
  display: none;
  flex-shrink: 0;
  margin-top: 10px;
  padding: 6px 10px;
  border: 1px solid var(--title);
  border-radius: 3px;
  color: var(--title);
  font-size: 14px;
  cursor: pointer;
}

#update-banner.visible {
  display: block;
}

#update-banner-action {
  text-decoration: underline;
  text-underline-offset: 3px;
}

#promptline {
  position: relative;
  display: flex;
  align-items: center;
  padding-top: 10px;
  border-top: 1px solid var(--fg-dim);
  font-size: 15px;
  flex-shrink: 0;
}

#more-indicator {
  display: none;
  position: absolute;
  top: 0;
  right: 20px;
  transform: translateY(-50%);
  background: var(--fg);
  color: #000;
  border: 1px solid var(--fg-dim);
  border-radius: 3px;
  padding: 0 8px;
  font-size: inherit;
  text-shadow: none;
}

#more-indicator.visible {
  display: inline-block;
}

/* Set by app.js only when its own animated, pinned-to-anchor scroll is what
   left unread content below the fold — never for a badge shown because the
   reader scrolled up by hand. `visibility`, not `display`: the prompt and
   cursor still occupy their box, so #promptline never changes size and
   nothing below it jumps. */
#promptline.more-gated .prompt,
#promptline.more-gated #cursor {
  visibility: hidden;
}

#promptline .prompt {
  margin-right: 8px;
  color: var(--fg-bright);
}

#typed {
  white-space: pre-wrap;
  word-break: break-all;
}

#cursor {
  display: inline-block;
  color: var(--fg-bright);
  animation: blink 1s steps(1) infinite;
  margin-left: 1px;
}

@keyframes blink {
  0%, 49% { opacity: 1; }
  50%, 100% { opacity: 0; }
}

/* the real input is off-screen but focusable, so mobile keyboards still work */
#hidden-input {
  position: fixed;
  top: -100px;
  left: -100px;
  width: 1px;
  height: 1px;
  opacity: 0;
  border: none;
  padding: 0;
  resize: none;
}

#output::-webkit-scrollbar {
  width: 10px;
}

#output::-webkit-scrollbar-thumb {
  background: var(--fg-dim);
  border-radius: 6px;
}

#output::-webkit-scrollbar-track {
  background: transparent;
}

/* Touch devices scroll #output by swipe, so its own scrollbar is just
   clutter there — desktop (mouse-driven) keeps it. */
@media (pointer: coarse) {
  #output {
    scrollbar-width: none;
  }

  #output::-webkit-scrollbar {
    display: none;
  }
}

/* --- boss overlay ------------------------------------------------------ */

/* Unlike #map-overlay, this reads as the whole screen being taken over —
   no framed popup, no dimmed backdrop behind it — because the entire point
   is that nothing of the game is visible while it's up. */
#boss-overlay {
  position: fixed;
  inset: 0;
  z-index: 40;
  background: #000;
  color: #d8d8d8;
  display: flex;
  align-items: flex-start;
  justify-content: flex-start;
  overflow: auto;
  cursor: default;
}

#boss-overlay.hidden {
  display: none;
}

#boss-sheet {
  margin: 0;
  padding: 12px;
  font-family: "Courier New", ui-monospace, "Cascadia Mono", "Consolas", monospace;
  font-size: 14px;
  line-height: 1.25;
  white-space: pre;
}

/* --- map overlay ----------------------------------------------------- */

/* The dimmed backdrop behind the popup — fixed and full-viewport, but it's
   not itself the thing that reads as "a popup"; #map-popup is. */
#map-overlay {
  position: fixed;
  inset: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.75);
}

#map-overlay.hidden {
  display: none;
}

/* Same framed-box language as #crt — a bordered, glowing terminal panel,
   not a full-bleed wash — so opening the map reads as a popup on top of
   the terminal rather than the whole browser window going dark. Sized to
   fit the viewport outright (never larger), so unlike the scrollable grid
   inside it, this box itself never needs to scroll or grow. */
#map-popup {
  position: relative;
  width: min(900px, 96vw);
  height: min(640px, 92vh);
  background: var(--bg);
  border: 2px solid var(--fg-dim);
  border-radius: 10px;
  box-shadow:
    0 0 24px rgba(51, 255, 102, 0.35),
    inset 0 0 60px rgba(0, 0, 0, 0.7);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  color: var(--fg);
}

#map-hint {
  flex-shrink: 0;
  padding: 10px 16px;
  border-bottom: 1px solid var(--fg-dim);
  color: var(--fg-dim);
  font-size: 13px;
  letter-spacing: 0.5px;
  text-align: center;
}

#map-viewport {
  flex: 1;
  min-height: 0;
  /* Hidden, not auto — no native scrollbar. Still fully scrollable: `hidden`
     only turns off the browser's own scrollbar and wheel/touch handling,
     not scriptable scrollTop/scrollLeft, so the wheel, arrow-key and touch
     handlers below drive it directly instead. `touch-action: none` stops
     the browser's own pan/zoom gestures (and any pull-to-refresh) from
     intercepting a drag before the touchmove handler sees it. */
  touch-action: none;
  overflow: hidden;
  cursor: grab;
  /* Click-and-hold panning is a mousedown-then-drag, exactly what the
     browser's own text selection listens for — without this, dragging over
     a sector's label highlights its text instead of just panning. */
  user-select: none;
  -webkit-user-select: none;
  display: flex;
  /* Breathing room lives here, as padding on the scrollable container, not
     as margin on the grid — padding stays reachable at every scroll extreme
     once the grid overflows, where a margin would just get clipped. */
  padding: 24px;
}

#map-viewport.dragging {
  cursor: grabbing;
}

#map-stats {
  flex-shrink: 0;
  padding: 8px 16px;
  border-top: 1px solid var(--fg-dim);
  color: var(--fg-dim);
  font-size: 13px;
  letter-spacing: 0.5px;
}

#map-grid {
  /* `margin: auto` on a flex child centers it when it's smaller than the
     viewport and degrades to plain top-left-anchored, fully scrollable flow
     the moment it's bigger — unlike `align/justify-items: center`, which
     traps half the overflow behind the centering unless the browser
     supports the newer `safe` keyword. This works everywhere. */
  margin: auto;
  position: relative;
  display: grid;
  grid-template-columns: repeat(var(--map-cols), var(--map-cell));
  grid-template-rows: repeat(var(--map-rows), var(--map-cell));
  gap: 3px;
}

.map-cell {
  position: relative;
  border: 1px solid var(--fg-dim);
  background: rgba(51, 255, 102, 0.06);
  overflow: hidden;
}

.map-cell.empty {
  border-color: rgba(31, 153, 68, 0.25);
  background: transparent;
}

.map-cell.filled {
  cursor: pointer;
  color: var(--fg-bright);
}

.map-cell.filled:hover {
  background: rgba(51, 255, 102, 0.22);
  border-color: var(--fg-bright);
}

/* The sector the player is actually standing in — inverted rather than just
   highlighted, so it reads unmistakably even at a glance across a big map. */
.map-cell.current {
  background: var(--fg-bright);
  border-color: var(--fg-bright);
  color: var(--bg);
}

.map-cell.current:hover {
  background: var(--fg-bright);
}

.map-cell.current .map-cell-label strong {
  color: var(--bg);
}

.map-cell .map-cell-label {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2px;
  font-size: 11px;
  line-height: 1.2;
  text-align: center;
  overflow: hidden;
  white-space: normal;
  overflow-wrap: break-word;
  pointer-events: none;
}

.map-cell .map-cell-label strong {
  color: var(--fg-bright);
  font-weight: bold;
}

/* Tappable equivalents of the +/-/Esc keys — the popup is otherwise
   keyboard-only, which a touch device has no way to drive. Floated over the
   viewport's own top-right corner rather than added to #map-hint so they
   stay reachable by thumb regardless of scroll position. */
#map-controls {
  position: absolute;
  top: 52px;
  right: 24px;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

#map-controls button {
  width: 40px;
  height: 40px;
  border: 1px solid var(--title);
  border-radius: 6px;
  background: var(--bg);
  color: var(--title);
  font: bold 18px "Courier New", ui-monospace, monospace;
  line-height: 1;
  cursor: pointer;
  box-shadow: 0 0 8px rgba(255, 204, 51, 0.25);
}

#map-controls button:hover,
#map-controls button:active {
  background: rgba(255, 204, 51, 0.22);
  border-color: var(--title);
}

#map-controls #map-exit {
  margin-top: 8px;
}

#map-tooltip {
  position: fixed;
  z-index: 30;
  background: var(--bg);
  color: var(--fg-bright);
  border: 1px solid var(--fg-dim);
  border-radius: 3px;
  padding: 3px 8px;
  font-size: 13px;
  font-weight: bold;
  pointer-events: none;
  text-shadow: 0 0 4px rgba(51, 255, 102, 0.6);
  transform: translate(-50%, -140%);
  white-space: nowrap;
}

#map-tooltip.hidden {
  display: none;
}
