body {
  background-color: black;
  color: #aaa;
  margin: 0;
  padding: 0;
}

.hidden {
  display: none;
}

.fullScreen {
  height: 100%;
  margin: 0;
  overflow: hidden;
  padding: 0;
  position: absolute;
  width: 100%;
}

.build-info {
  bottom: 0;
  font-size: 14px;
  position: fixed;
}

/* Main Menu */
.MainMenu {
  align-items: center;
  display: flex;
  flex-direction: column;
  height: 100%;
  justify-content: center;
  text-align: center;
}

.mainMenuOption {
  /* Start invisible (black against the black body); `.ready` fades them to light-grey, so the
     options animate in once the async saved-game check resolves. */
  color: #000;
  cursor: default;
  font-size: 0.9em;
  margin: 0.3em 0;
  transition: color 0.4s ease-in;
  user-select: none;
}

.mainMenuOption.ready {
  color: #aaa;
  cursor: pointer;
}

.mainMenuOption.ready:hover {
  color: #fff;
}

.inGameTable {
  border-spacing: 10px;
  height: 97%;
  width: 99%;
}

/* --status-panel-height is set by StatusLog.ts (collapsed by default, toggled taller by its
   expand/collapse button) — both this and canvas#viewport below read the same variable so they
   never disagree about how much of .inGameTable's height the status panel actually occupies
   (see StatusLog.ts's HEIGHT_PROPERTY doc comment; a mismatch here is what used to overflow the
   page and grow a scrollbar). Falls back to the collapsed height before StatusLog.ts's first
   setExpanded(false) call sets it explicitly. */
#statusPanel {
  display: flex;
  flex-direction: column;
  font-size: 0.5em;
  height: var(--status-panel-height, 2.2em);
  overflow: hidden;
}

.status-log-header {
  display: flex;
  flex: none;
  justify-content: center;
}

.status-log-toggle {
  background: none;
  border: none;
  color: inherit;
  cursor: pointer;
  font: inherit;
  line-height: 1;
  padding: 0.1em 0.6em;
}

.status-log-messages {
  flex: 1;
  overflow-y: auto;
}

canvas#viewport {
  border: solid 1px red;
  height: calc(100% - var(--status-panel-height, 2.2em));
  width: calc(100% - 1em);
}

div#buttons {
  background-color: #555;
  margin-right: 0.1em;
  position: absolute;
  right: 0;
  top: 0;
  width: 1em;
}

.viewportCanvasPanning {
  cursor: move;
}

/* Debug: fgr.debug.tileInspect hover overlay */
.tileInspector {
  background-color: rgba(0, 0, 0, 0.85);
  border: 1px solid #6c6;
  color: #cfc;
  font-family: monospace;
  font-size: 12px;
  line-height: 1.35;
  padding: 4px 6px;
  pointer-events: none;
  position: fixed;
  white-space: pre;
  z-index: 1000;
}

/* Debug: fgr.debug.showRenderDetails overlay, anchored top-left (lands in the gutter / negative space) */
.renderDetailsOverlay {
  background-color: rgba(0, 0, 0, 0.85);
  color: rgb(255, 134, 68);
  font-family: monospace;
  font-size: 12px;
  left: 0;
  line-height: 1.35;
  padding: 4px 6px;
  pointer-events: none;
  position: fixed;
  top: 0;
  white-space: pre;
  z-index: 1000;
}

.pdg-flat-button {
  cursor: pointer;
  outline: none;
  user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  -webkit-user-select: none;
}

.pdg-flat-button:focus-visible {
  outline: 2px solid white;
  outline-offset: 2px;
}

.helpList {
  font-size: 0.5em;
}

/** Styles for Button Panel */

button.mainButton {
  background-color: #888;
  border: solid 1px #aaa;
  cursor: pointer;
  font-size: 0.75em;
  margin: 0.1em;
  user-select: none;
  width: 1.1em;
}

button.mainButton:focus,
button.mainButton:hover {
  background-color: #aaa;
  border: solid 1px white;
}

/* Styles for Dialogs */

.pdg-dialog-wait {
  cursor: wait;
}

.pdg-dialog-base {
  background-color: #888;
  border: 0.1em solid black;
  border-radius: 0.2em;
  color: black;
  font-family: chiller;
  font-size: 1em;
  left: 25%;
  padding: 0.25em;
  position: absolute;
  right: 25%;
  text-align: center;
  /* Dead-center vertically regardless of natural (content-driven) height: translateY(-50%) shifts
     the box up by exactly half its own rendered height. Plain `top: X%` can't do this — it anchors
     the top edge, so a short dialog and a tall one land at different visual centers. `bottom: auto`
     cancels the UA dialog:modal stylesheet's implicit bottom:0, which otherwise centers the box in
     the leftover space below `top` instead of the full viewport.
     Deliberately NOT setting `margin: 0` here: with `top`/`bottom` both non-auto, the browser
     already resolves auto margins to 0 for this axis on its own. But a fixed `margin: 0` would also
     zero out margin-left/margin-right — and those need to stay `auto` for a fit-content-width
     dialog (no explicit `width`, like the info panel or item-selection dialogs) to center between
     `left`/`right`; forcing them to 0 makes the box over-constrained and it collapses against
     `left` instead. See pdg-dialog-wide below, which sizes explicitly and centers via translateX,
     so it never depended on this auto-margin behavior either way. */
  top: 50%;
  bottom: auto;
  transform: translateY(-50%);
}

ul.custom-dialog {
  list-style: none;
  padding: 0;
}

ul.custom-dialog:bover {
  background-color: palegoldenrod;
}

.pdg-dialog-base.pdg-dialog-wide {
  /* The ambient 1em is huge here (body's font-size is a viewport-width percentage, not a fixed
     size — see App.tsx resizeApp()); custom (wide) dialogs render real content, not a couple of
     short lines, so they need a normal, readable size rather than inheriting that. */
  font-size: 0.5em;
  /* Capped and centered via transform rather than left/right percentages, so a paragraph of prose
     wraps at a readable line length instead of stretching edge-to-edge on a wide viewport. Combined
     with the base rule's translateY(-50%) (a single `transform` declaration replaces the base's
     entirely, so both axes must be listed here). */
  left: 50%;
  max-width: 50%;
  right: auto;
  transform: translateX(-50%) translateY(-50%);
  width: 80%;
}

/* The Player Info dialog's content (hand row, skill rows) is much narrower than the shared wide
   box above, which left a large empty gap between the hands and stretched the Skills tab wider
   than it needed — shrink-to-fit instead, still capped by pdg-dialog-wide's max-width above. */
.pdg-dialog-base.player-info-dialog {
  width: auto;
}

/* The Load Game dialog's rows are a single line of text (save name + timestamp) — the shared wide
   box's 50% max-width left far too much empty space either side. Narrow it by about a third. */
.pdg-dialog-base.load-game-dialog {
  max-width: 33%;
}

/* The craft-quantity slider dialog (see CraftDialog.ts showCraftQuantityDialog) has even less
   content than Load Game's rows — half the shared wide box's bounds. */
.pdg-dialog-base.craft-quantity-dialog {
  max-width: 25%;
  width: 40%;
}

/* The batched notification dialog's multi-item list (see NotificationDialog.ts) — left-aligned and
   bulleted, unlike the base dialog's centered text, since a list of several unrelated grants reads
   better that way than a wall of centered prose. */
.notification-list {
  margin: 0;
  padding-left: 1.2em;
  text-align: left;
}

.notification-list li {
  margin-bottom: 0.6em;
}

.notification-heading {
  font-weight: bold;
}

/* Respects an author's embedded '\n' (e.g. SkillDef.description) as a real line break, still
   wrapping/collapsing other whitespace normally — plain textContent alone would collapse it. */
.pdg-dialog-body {
  white-space: pre-line;
}

.pdg-dialog-title {
  font-weight: bold;
}

.pdg-dialog-buttons {
  padding-top: 0.25em;
}

div.pdg-dialog-buttons div.pdg-flat-button {
  display: inline-block;
  margin-right: 1em;
}

div.pdg-dialog-buttons div.pdg-flat-button-disabled {
  cursor: none;
  opacity: 0.5;
}

/* Styles for the Player Info dialog (see Dialogs.ts showPlayerInfoDialog) */

.player-info-header {
  font-weight: bold;
  margin-bottom: 0.6em;
}

/* Left/right hints flank the tab group, pinned to the dialog's edges; the group itself stays
   centered between them (see Dialogs.ts renderTabBar). */
.player-info-tabs {
  align-items: center;
  display: flex;
  justify-content: space-between;
  margin-bottom: 0.6em;
}

.player-info-tab-group {
  display: flex;
  gap: 0.4em;
}

.player-info-tab {
  padding: 3px 12px;
}

.player-info-tab.selected {
  background-color: #007acc;
  border-color: #005a9e;
  color: white;
}

/* A/D switch-tab hints — a visual reminder only, never focusable or interactive. */
.player-info-tab-hint {
  border: 1px solid rgba(0, 0, 0, 0.3);
  border-radius: 0.2em;
  font-size: 0.75em;
  padding: 2px 6px;
}

/* Both tabs' lists are always rendered (see Dialogs.ts showPlayerInfoDialog), stacked in the same
   grid cell so the container's height is the taller of the two regardless of which is hidden —
   `visibility: hidden` (not `display: none`) keeps a box's height counted in the grid's sizing while
   still hiding and unfocusing it. This is a stopgap until the dialog has a real fixed height. */
.player-info-tab-content {
  display: grid;
}

.player-info-tab-content > * {
  grid-area: 1 / 1;
}

.inventory-list, .skills-list {
  list-style: none;
  margin: 0.4em 0;
  padding: 0;
  text-align: left;
}

.inventory-row, .skills-row {
  align-items: center;
  border-bottom: 1px solid rgba(0, 0, 0, 0.15);
  display: flex;
  gap: 0.5em;
  padding: 5px 2px;
}

.inventory-row-label, .skills-row-label {
  flex: 1;
}

/* Progress toward a skill's next level (see PlayerInfoDialog.ts's renderSkillsTab) — a small
   fixed-width track so rows stay aligned regardless of how far along any given skill is. */
.skill-progress-track {
  background-color: rgba(0, 0, 0, 0.25);
  border: 1px solid rgba(0, 0, 0, 0.4);
  height: 0.6em;
  overflow: hidden;
  width: 6em;
}

.skill-progress-fill {
  background-color: #3a3;
  height: 100%;
}

/* Fixed width + right-aligned so the level number lines up the same across every skill row,
   regardless of how many digits it has (see PlayerInfoDialog.ts's renderSkillsTab). */
.skills-row-level {
  text-align: right;
  white-space: nowrap;
  width: 4.5em;
}

/* An explicit gap rather than `justify-content: space-between`: now that the dialog shrinks to fit
   its content (see .player-info-dialog above), space-between's distance would just be whatever
   width the widest sibling row happens to demand — not something we can tune directly. This value
   is the actual, adjustable knob for "space between the hands" going forward. */
.inventory-hands-row {
  gap: 4em;
}

.inventory-hand-cell {
  align-items: center;
  display: flex;
  gap: 0.4em;
}

/* cursor: grab hints at future drag-and-drop (not yet implemented — see PlayerInfoDialog.ts TODO). */
.inventory-item-image {
  border: 1px solid rgba(0, 0, 0, 0.4);
  cursor: grab;
  height: 2em;
  object-fit: contain;
  width: 2em;
}

/* Native <button> elements don't inherit font-size/font-family from ancestors by default (unlike
   the div-based FlatButton), so every button rendered into a dialog body needs `font: inherit`
   explicitly, or it renders at the browser's fixed default size and ignores the resize-driven
   ambient sizing (see App.tsx resizeApp()) everything else here tracks. */
.player-info-tab, .drop-btn, .skill-detail-btn, .item-choice {
  font: inherit;
}

.drop-btn, .skill-detail-btn {
  font-size: 0.85em;
  padding: 2px 8px;
}

.skill-detail-heading {
  font-weight: bold;
  margin-bottom: 0.4em;
}

.skill-detail-body {
  margin: 0;
  text-align: left;
}

/* Styles for the item-selection dialog (see Dialogs.ts showItemSelectionDialog) */

.item-choice {
  background: none;
  border: 1px solid transparent;
  cursor: pointer;
  display: block;
  margin: 2px 0;
  padding: 8px 12px;
  text-align: left;
  width: 100%;
}

/* Wraps a Load Game row (see LoadGameDialog.ts) so its delete button sits to the right of the
   save's .item-choice button instead of below it — .item-choice defaults to a block, full-width
   row, so it needs an explicit override here to share the row with a sibling. */
.save-row {
  align-items: center;
  display: flex;
  gap: 8px;
}

.save-row .item-choice {
  flex: 1;
  width: auto;
}

/* Deleting a save is destructive and irreversible (unlike e.g. .drop-btn's reversible inventory
   drop), so it gets a more visually weighted warning treatment than a plain text button. */
.delete-save-button {
  background-color: #c0392b;
  border: 1px solid #922b21;
  border-radius: 50%;
  color: white;
  cursor: pointer;
  flex-shrink: 0;
  font: inherit;
  height: 1.07em;
  line-height: 1;
  width: 1.07em;
}

.delete-save-button:hover {
  background-color: #e74c3c;
}

.item-choice.selected {
  background-color: #007acc;
  border-color: #005a9e;
  color: white;
}

.item-choice:hover {
  background-color: #e0e0e0;
}

.item-choice.selected:hover {
  background-color: #005a9e;
}

.item-choice.disabled {
  /* Dialogs sit on a mid-gray (#888) background (see .pdg-dialog-base) — a lighter "washed out"
     gray for disabled text nearly vanishes against it, so disabled rows go darker instead. */
  color: #3a3a3a;
  cursor: default;
}

.item-choice.disabled:hover {
  background-color: transparent;
}

.item-choice-name {
  font-weight: bold;
}

.item-choice-description {
  color: #555;
  font-size: 0.85em;
}

.item-choice.selected .item-choice-description {
  color: #dceaff;
}

.item-choice.disabled .item-choice-description {
  color: #555;
}

/* Styles for the craft-quantity slider dialog (see CraftDialog.ts showCraftQuantityDialog) */

.craft-quantity-label {
  font-size: 1.4em;
  font-weight: bold;
  margin-bottom: 0.3em;
}

.craft-quantity-row {
  align-items: center;
  display: flex;
  gap: 8px;
  margin-bottom: 0.6em;
}

.craft-quantity-bound {
  color: #555;
  font-size: 0.85em;
}

/* A plain <input type="range"> renders as a barely-visible track with a tiny circular thumb —
   not obviously draggable. Styled explicitly as a visible track plus a large, rectangular,
   grippable thumb instead (thumb pseudo-elements can't be styled together; each engine needs its
   own rule with identical values). */
.craft-quantity-slider {
  -webkit-appearance: none;
  appearance: none;
  background: transparent;
  flex: 1;
  height: 36px;
}

/* WebKit has no native "filled portion" pseudo-element (unlike Firefox's ::-moz-range-progress
   below), so the fill is faked with a gradient reading the --pct custom property CraftDialog.ts
   sets on every input event. */
.craft-quantity-slider::-webkit-slider-runnable-track {
  background: linear-gradient(
      to right, #007acc 0%, #007acc var(--pct, 0%), #555 var(--pct, 0%), #555 100%);
  border-radius: 4px;
  height: 8px;
}

.craft-quantity-slider::-moz-range-track {
  background: #555;
  border-radius: 4px;
  height: 8px;
}

.craft-quantity-slider::-moz-range-progress {
  background-color: #007acc;
  border-radius: 4px;
  height: 8px;
}

.craft-quantity-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  background-color: #007acc;
  border: 1px solid #005a9e;
  border-radius: 4px;
  cursor: grab;
  height: 36px;
  margin-top: -14px;
  width: 22px;
}

.craft-quantity-slider::-moz-range-thumb {
  background-color: #007acc;
  border: 1px solid #005a9e;
  border-radius: 4px;
  cursor: grab;
  height: 36px;
  width: 22px;
}

.craft-quantity-confirm {
  /* See the .item-choice font note above — form controls need this explicitly. */
  font: inherit;
}
