/*
 * app.css -- the project-specific layer on top of Bootstrap.
 *
 * Two jobs:
 *
 *  1. Pin a dark palette explicitly. The markup sets data-bs-theme="dark",
 *     which Bootstrap 5.3 honours on its own -- but the vendored copy on this
 *     box may be an earlier 5.x, where that attribute means nothing. Rather
 *     than depend on the version, the palette below states its own colours, so
 *     the site looks the same either way.
 *  2. The pieces Bootstrap has no opinion about: the CRT screen frame, the
 *     frame strip, the hex dump.
 */

:root {
  --sc-ink: #0a0d10;
  --sc-panel: #171b20;
  --sc-panel-2: #1f242b;
  --sc-line: #333c46;
  --sc-text: #e8edf2;
  --sc-muted: #93a1ae;
  --sc-green: #60d394;
  --sc-amber: #f7c948;
  --sc-cyan: #63cdda;
}

body.sc-body {
  min-height: 100vh;
  background:
    radial-gradient(circle at 12% 6%, rgba(96, 211, 148, 0.10), transparent 30rem),
    radial-gradient(circle at 88% 18%, rgba(99, 205, 218, 0.08), transparent 28rem),
    linear-gradient(160deg, #090b0d 0%, #12171e 55%, #08090b 100%);
  background-attachment: fixed;
  color: var(--sc-text);
  display: flex;
  flex-direction: column;
}

.sc-main {
  flex: 1 0 auto;
}

/* --- chrome -------------------------------------------------------------- */

.sc-navbar {
  background: rgba(12, 15, 19, 0.92);
  border-color: var(--sc-line) !important;
  backdrop-filter: blur(6px);
}

.sc-navbar .navbar-brand,
.sc-navbar .nav-link {
  color: var(--sc-text);
}

.sc-navbar .nav-link:hover,
.sc-navbar .nav-link.active {
  color: var(--sc-green);
}

.sc-navbar .navbar-toggler {
  border-color: var(--sc-line);
}

.sc-navbar .navbar-toggler-icon {
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='%23e8edf2' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");
}

.sc-brand-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--sc-green);
  box-shadow: 0 0 14px rgba(96, 211, 148, 0.9);
}

.sc-brand-text {
  font-weight: 700;
  letter-spacing: -0.01em;
}

/* The public site's full title, "Slade Collins and the Secret of Tahawus",
   does not fit one line on a phone, and Bootstrap's navbar-brand is nowrap:
   it ran 3 px past a 390 px screen and 33 px past a 360 px one, so the whole
   page scrolled sideways. Let it wrap beside the toggle instead. */
@media (max-width: 575.98px) {
  .sc-navbar .navbar-brand {
    flex: 1 1 0;
    min-width: 0;
    white-space: normal;
  }
}

.sc-footer {
  background: rgba(10, 13, 16, 0.85);
  border-color: var(--sc-line) !important;
  flex-shrink: 0;
}

/* --- surfaces ------------------------------------------------------------ */

.card {
  background-color: rgba(23, 27, 32, 0.92);
  border-color: var(--sc-line);
  color: var(--sc-text);
}

.card-header,
.card-footer {
  background-color: rgba(31, 36, 43, 0.85);
  border-color: var(--sc-line);
  color: var(--sc-text);
  font-weight: 600;
}

.sc-hero {
  background:
    linear-gradient(135deg, rgba(96, 211, 148, 0.10), rgba(99, 205, 218, 0.06) 60%, transparent),
    rgba(23, 27, 32, 0.92);
  border-color: var(--sc-line) !important;
}

.sc-eyebrow {
  text-transform: uppercase;
  letter-spacing: 0.14em;
  font-size: 0.7rem;
  color: var(--sc-green);
}

.sc-stat-label {
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 0.68rem;
  color: var(--sc-muted);
}

.sc-stat-value {
  font-size: 1.4rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* Bootstrap's text utilities, pinned for pre-5.3 builds. */
.text-body-secondary {
  color: var(--sc-muted) !important;
}

/* --- forms --------------------------------------------------------------- */

.form-control,
.form-select {
  background-color: rgba(12, 15, 19, 0.85);
  border-color: var(--sc-line);
  color: var(--sc-text);
}

.form-control:focus,
.form-select:focus {
  background-color: rgba(12, 15, 19, 0.95);
  border-color: var(--sc-green);
  color: var(--sc-text);
  box-shadow: 0 0 0 0.2rem rgba(96, 211, 148, 0.2);
}

.form-control::placeholder {
  color: #64707c;
}

.form-select option {
  background-color: #12171e;
  color: var(--sc-text);
}

kbd {
  background: #232a32;
  border: 1px solid var(--sc-line);
  border-radius: 4px;
  padding: 0.05rem 0.35rem;
  font-size: 0.8em;
  color: var(--sc-text);
}

/* Keyboard legend under the game screen: one row per NES button, the
   button's name on the left and the key that presses it on the right. */
.sc-key-legend-title {
  font-weight: 600;
  color: var(--sc-text);
  margin-bottom: 0.25rem;
}

.sc-key-legend {
  display: grid;
  grid-template-columns: max-content auto;
  column-gap: 0.75rem;
  row-gap: 0.2rem;
  margin: 0;
}

.sc-key-legend dt {
  font-weight: 400;
}

.sc-key-legend dd {
  margin: 0;
}

.sc-key-legend kbd + kbd {
  margin-left: 0.15rem;
}

/* --- tables -------------------------------------------------------------- */

.table {
  --bs-table-color: var(--sc-text);
  --bs-table-bg: transparent;
  --bs-table-border-color: var(--sc-line);
  --bs-table-hover-color: var(--sc-text);
  --bs-table-hover-bg: rgba(96, 211, 148, 0.07);
  color: var(--sc-text);
}

.table > thead {
  color: var(--sc-muted);
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.sc-report-table tr[data-href] {
  cursor: pointer;
}

/* The description column's width floor lives in a min-width media query near
   the bottom of this file: below lg the list is not a table at all. */

.sc-description-cell a {
  color: var(--sc-text);
  text-decoration: none;
}

.sc-description-cell a:hover {
  color: var(--sc-green);
}

.sc-revision-cell {
  max-width: 26rem;
  overflow-wrap: anywhere;
  white-space: pre-wrap;
}

.sc-sort {
  color: var(--sc-muted);
  text-decoration: none;
}

.sc-sort:hover {
  color: var(--sc-text);
}

.sc-sort.active {
  color: var(--sc-green);
}

.sc-scroll-tall {
  max-height: 22rem;
  overflow-y: auto;
}

.sc-scroll-tall thead th {
  background: #1f242b;
}

/* --- the screen ---------------------------------------------------------- */

.sc-screen-frame {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  aspect-ratio: 256 / 240;
  max-height: 70vh;
  margin: 0 auto;
  background: #000;
  border: 1px solid #000;
  border-radius: 6px;
  overflow: hidden;
}

.sc-screen-frame::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: repeating-linear-gradient(
    to bottom,
    rgba(255, 255, 255, 0.035) 0,
    rgba(255, 255, 255, 0.035) 1px,
    transparent 1px,
    transparent 4px
  );
  mix-blend-mode: screen;
}

.sc-screen {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  /* Nearest-neighbour: an NES frame upscaled with bilinear smoothing is
     actively misleading in a bug report. */
  image-rendering: pixelated;
  image-rendering: crisp-edges;
  background: #000;
}

.sc-screen-small {
  max-width: 320px;
  margin: 0 auto;
}

.sc-screen-paused {
  filter: saturate(0.75) brightness(0.8);
}

.sc-paused-veil {
  position: absolute;
  inset: auto 0 0 0;
  padding: 0.75rem;
  background: linear-gradient(to top, rgba(10, 13, 16, 0.95), rgba(10, 13, 16, 0));
  color: var(--sc-amber);
  z-index: 3;
}

.sc-build-frame {
  background: linear-gradient(150deg, #0d1116, #161c24);
}

/* --- frame strip --------------------------------------------------------- */

.sc-thumbstrip {
  display: flex;
  gap: 4px;
  overflow-x: auto;
  padding-bottom: 6px;
}

.sc-thumb {
  flex: 0 0 auto;
  width: 64px;
  height: 60px;
  border: 2px solid transparent;
  border-radius: 3px;
  background: #000;
  image-rendering: pixelated;
  cursor: pointer;
  opacity: 0.65;
  transition: opacity 120ms ease, border-color 120ms ease;
}

.sc-thumb:hover {
  opacity: 1;
}

.sc-thumb.active {
  opacity: 1;
  border-color: var(--sc-green);
}

/* --- hex dump ------------------------------------------------------------ */

.sc-hexdump {
  background: rgba(8, 10, 13, 0.9);
  border: 1px solid var(--sc-line);
  border-radius: 5px;
  padding: 0.6rem 0.7rem;
  font-size: 0.74rem;
  line-height: 1.5;
  overflow-x: auto;
  color: var(--sc-text);
  margin: 0;
}

.sc-hexrow {
  white-space: pre;
  font-family: Consolas, "Liberation Mono", "Courier New", monospace;
}

.sc-hexaddr {
  color: var(--sc-cyan);
}

.sc-hexascii {
  color: var(--sc-muted);
}

.sc-hexbyte-changed {
  color: #0a0d10;
  background: var(--sc-amber);
  border-radius: 2px;
}

/* --- input log correlation ----------------------------------------------- */

#sc-input-table tbody tr {
  opacity: 0.45;
}

#sc-input-table tbody tr.sc-input-past {
  opacity: 1;
}

#sc-input-table tbody tr.sc-input-here {
  background: rgba(96, 211, 148, 0.14);
}

/* --- misc ---------------------------------------------------------------- */

.sc-package-summary {
  border-color: var(--sc-line) !important;
  background: rgba(12, 15, 19, 0.6);
}

.sc-report-card textarea {
  resize: vertical;
}

.min-w-0 {
  min-width: 0;
}

.list-group-item {
  background-color: transparent;
  border-color: var(--sc-line);
  color: var(--sc-text);
}

.list-group-item-action:hover {
  background-color: rgba(96, 211, 148, 0.08);
  color: var(--sc-text);
}

.page-link {
  background-color: rgba(23, 27, 32, 0.9);
  border-color: var(--sc-line);
  color: var(--sc-text);
}

.page-item.active .page-link {
  background-color: var(--sc-green);
  border-color: var(--sc-green);
  color: #08120c;
}

.page-item.disabled .page-link {
  background-color: rgba(23, 27, 32, 0.5);
  color: #5c6773;
}

.alert-info {
  background-color: rgba(99, 205, 218, 0.12);
  border-color: rgba(99, 205, 218, 0.35);
  color: #cfeff4;
}

.alert-secondary {
  background-color: rgba(147, 161, 174, 0.12);
  border-color: var(--sc-line);
  color: var(--sc-text);
}

@media (prefers-reduced-motion: reduce) {
  .progress-bar-animated {
    animation: none;
  }
}

/* ==========================================================================
   On-screen controller
   --------------------------------------------------------------------------
   Layout is a three-column grid with a full-width action row above it:

       [        Freeze & report        ]
       [ d-pad ] [ Select/Start ] [ B A ]

   The sizes are clamped against the viewport rather than fixed, so the same
   markup is a thumb-sized pad on a 390 px phone and a comfortable one on an
   820 px tablet without a second set of rules.

   `touch-action: none` is the load-bearing declaration here: without it the
   browser claims the gesture for scrolling before the page ever sees a
   touchmove, and the pad pans the page instead of playing the game.
   gamepad.js also calls preventDefault(), which covers double-tap zoom, the
   long-press callout and browsers that ignore touch-action.
   ========================================================================== */

.sc-touchpad {
  --sc-dpad-size: clamp(8rem, 33vw, 11rem);
  --sc-face-size: clamp(3.25rem, 13.5vw, 4.5rem);

  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-areas:
    "action action action"
    "dpad   middle faces";
  align-items: center;
  justify-items: center;
  gap: 0.75rem;
  margin-top: 0.75rem;
  padding: 0.75rem 0.5rem;
  border: 1px solid var(--sc-line);
  border-radius: 10px;
  background: linear-gradient(180deg, rgba(24, 29, 35, 0.95), rgba(13, 16, 20, 0.95));

  /* No page pan, no pinch, no double-tap zoom over the pad. */
  touch-action: none;
  /* No text selection or drag ghost from a thumb held on a label. */
  user-select: none;
  -webkit-user-select: none;
  /* No iOS long-press callout menu. */
  -webkit-touch-callout: none;
  /* No blue flash on every tap. */
  -webkit-tap-highlight-color: transparent;
}

.sc-pad-action {
  grid-area: action;
  width: 100%;
  max-width: 30rem;
}

.sc-pad-dpad-wrap {
  grid-area: dpad;
}

.sc-pad-middle {
  grid-area: middle;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 0.5rem;
  min-width: 0;
  width: 100%;
  max-width: 12rem;
}

.sc-pad-faces {
  grid-area: faces;
  display: flex;
  align-items: center;
  gap: clamp(0.5rem, 3vw, 1rem);
}

/* --- d-pad --------------------------------------------------------------- */

.sc-dpad {
  position: relative;
  width: var(--sc-dpad-size);
  height: var(--sc-dpad-size);
}

.sc-dpad-cell,
.sc-dpad-hub {
  position: absolute;
  background: #262d36;
  border: 1px solid var(--sc-line);
  transition: background-color 60ms linear;
}

.sc-dpad-up    { left: 33%; width: 34%; top: 0;    height: 38%; border-radius: 8px 8px 0 0; border-bottom: none; }
.sc-dpad-down  { left: 33%; width: 34%; bottom: 0; height: 38%; border-radius: 0 0 8px 8px; border-top: none; }
.sc-dpad-left  { top: 33%; height: 34%; left: 0;   width: 38%;  border-radius: 8px 0 0 8px; border-right: none; }
.sc-dpad-right { top: 33%; height: 34%; right: 0;  width: 38%;  border-radius: 0 8px 8px 0; border-left: none; }

.sc-dpad-hub {
  left: 33%;
  top: 33%;
  width: 34%;
  height: 34%;
  border: none;
  background: #262d36;
}

.sc-dpad-hub::after {
  content: "";
  position: absolute;
  inset: 28%;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.06);
}

/* Arrow glyphs, drawn rather than typed so they cannot be selected. */
.sc-dpad-cell::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  border: 0.42rem solid transparent;
  opacity: 0.75;
}

.sc-dpad-up::after    { transform: translate(-50%, -70%); border-bottom-color: var(--sc-text); border-top-width: 0; }
.sc-dpad-down::after  { transform: translate(-50%, -30%); border-top-color: var(--sc-text); border-bottom-width: 0; }
.sc-dpad-left::after  { transform: translate(-70%, -50%); border-right-color: var(--sc-text); border-left-width: 0; }
.sc-dpad-right::after { transform: translate(-30%, -50%); border-left-color: var(--sc-text); border-right-width: 0; }

.sc-dpad-cell.is-down {
  background: var(--sc-green);
}

.sc-dpad-cell.is-down::after {
  opacity: 1;
}

.sc-dpad-up.is-down::after    { border-bottom-color: #08120c; }
.sc-dpad-down.is-down::after  { border-top-color: #08120c; }
.sc-dpad-left.is-down::after  { border-right-color: #08120c; }
.sc-dpad-right.is-down::after { border-left-color: #08120c; }

/* --- face buttons -------------------------------------------------------- */

.sc-pad-face {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--sc-face-size);
  height: var(--sc-face-size);
  border-radius: 50%;
  border: 1px solid var(--sc-line);
  background: radial-gradient(circle at 34% 30%, #3a444f, #232a32 70%);
  color: var(--sc-text);
  font-weight: 700;
  font-size: 1.05rem;
  line-height: 1;
  transition: background-color 60ms linear, color 60ms linear;
}

/* B sits low and left of A, the way the hardware has it. */
.sc-pad-face-b {
  transform: translateY(0.7rem);
}

.sc-pad-face.is-down {
  background: var(--sc-green);
  color: #08120c;
  border-color: var(--sc-green);
}

.sc-pad-pill {
  display: block;
  padding: 0.45rem 0.4rem;
  border-radius: 999px;
  border: 1px solid var(--sc-line);
  background: #232a32;
  color: var(--sc-muted);
  font-size: 0.68rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-align: center;
  line-height: 1;
  transition: background-color 60ms linear, color 60ms linear;
}

.sc-pad-pill.is-down {
  background: var(--sc-green);
  color: #08120c;
  border-color: var(--sc-green);
}

/* Room for two pills side by side once there is room for them. */
@media (min-width: 576px) {
  .sc-pad-middle {
    flex-direction: row;
    justify-content: center;
  }

  .sc-pad-pill {
    flex: 1 1 0;
    padding: 0.55rem 0.5rem;
    font-size: 0.74rem;
  }
}

/* ==========================================================================
   On-screen controller: the NES skin (public preview)
   --------------------------------------------------------------------------
   `.sc-touchpad--nes` dresses the same pad as the original NES controller:
   a grey shell around a black faceplate, a black cross d-pad, grey stripes
   over SELECT and START printed in red, black pill buttons in grey wells, and
   red round B and A buttons in grey square wells with their letters printed
   on the faceplate beside them.

   It is a modifier so the tracker's pad, which also carries a full-width
   Freeze & report row, keeps its own look until someone decides otherwise.

   VISUAL ONLY. gamepad.js hit-tests against each control's rendered rect,
   so everything decorative here -- the wells, the printed letters and labels
   -- is a pseudo-element drawn OUTSIDE or BEHIND a control, never a box that
   changes one. Touch targets stay what the base rules make them: the face
   buttons are the same clamped circles, and a pill's target is its whole
   grey well, not the thin black capsule drawn inside it.
   ========================================================================== */

.sc-touchpad--nes {
  --sc-nes-shell: #c3c3c0;
  --sc-nes-shell-edge: #85857f;
  --sc-nes-faceplate: #1b1b1b;
  --sc-nes-stripe: #9d9d99;
  --sc-nes-well: #c9c9c6;
  --sc-nes-well-shade: #a9a9a5;
  --sc-nes-black: #0f0f0f;
  --sc-nes-black-down: #343434;
  --sc-nes-red: #c8171f;
  --sc-nes-red-light: #ee4046;
  --sc-nes-red-dark: #860b11;
  /* Red print on the black faceplate. Lighter than the button red so the
     small letters clear 4.5:1 against #1b1b1b. */
  --sc-nes-print: #ff5b50;

  /* No Freeze & report row on this page, so no empty first row either. */
  grid-template-areas: "dpad middle faces";
  gap: 0.5rem;
  padding: 0.85rem 0.55rem 0.95rem;
  /* The shell shows more above the faceplate than around it, as it does on
     the real controller. */
  border: 0.45rem solid var(--sc-nes-shell);
  border-top-width: 0.9rem;
  border-radius: 14px;
  background: var(--sc-nes-faceplate);
  box-shadow:
    0 0 0 1px var(--sc-nes-shell-edge),
    inset 0 0 0 1px #000,
    0 8px 18px rgba(0, 0, 0, 0.45);
}

/* --- d-pad: one black cross ---------------------------------------------- */

.sc-touchpad--nes .sc-dpad {
  /* One shadow for the whole cross, not one per arm, so the seams between
     arms and hub never show. */
  filter: drop-shadow(0 0 1px #6b6b67) drop-shadow(0 3px 0 #000);
}

.sc-touchpad--nes .sc-dpad-cell,
.sc-touchpad--nes .sc-dpad-hub {
  background: var(--sc-nes-black);
  border-color: #454542;
}

.sc-touchpad--nes .sc-dpad-hub::after {
  inset: 26%;
  background: radial-gradient(circle at 50% 40%, #050505, #262626);
}

/* The arrows are moulded into the plastic, not printed in white. */
.sc-touchpad--nes .sc-dpad-up::after    { border-bottom-color: #55554f; }
.sc-touchpad--nes .sc-dpad-down::after  { border-top-color: #55554f; }
.sc-touchpad--nes .sc-dpad-left::after  { border-right-color: #55554f; }
.sc-touchpad--nes .sc-dpad-right::after { border-left-color: #55554f; }

.sc-touchpad--nes .sc-dpad-cell.is-down {
  background: var(--sc-nes-black-down);
}

.sc-touchpad--nes .sc-dpad-up.is-down::after    { border-bottom-color: #b5b5ae; }
.sc-touchpad--nes .sc-dpad-down.is-down::after  { border-top-color: #b5b5ae; }
.sc-touchpad--nes .sc-dpad-left.is-down::after  { border-right-color: #b5b5ae; }
.sc-touchpad--nes .sc-dpad-right.is-down::after { border-left-color: #b5b5ae; }

/* --- SELECT and START ---------------------------------------------------- */

/* The grey stripes across the top of the centre, above the labels. */
.sc-touchpad--nes .sc-pad-middle {
  gap: 0.35rem;
  padding-top: 1.35rem;
  background:
    repeating-linear-gradient(
      to bottom,
      var(--sc-nes-stripe) 0 0.2rem,
      transparent 0.2rem 0.45rem
    )
    top center / 100% 0.9rem no-repeat;
}

/* The element is the grey well (and the touch target); the black capsule is
   drawn inside it and the red label is printed above it. The element's own
   text stays in the DOM for anything that reads it, but is not painted. */
.sc-touchpad--nes .sc-pad-pill {
  position: relative;
  min-width: 2.75rem;
  min-height: 2.4rem;
  margin-top: 0.95rem;
  border: none;
  border-radius: 0.45rem;
  background: linear-gradient(180deg, var(--sc-nes-well), var(--sc-nes-well-shade));
  color: transparent;
}

.sc-touchpad--nes .sc-pad-pill::before {
  content: attr(aria-label);
  position: absolute;
  /* Centred on the well and never wrapped: a label narrower than its text
     broke mid-word ("SELE / CT") rather than overhanging. */
  left: 50%;
  transform: translateX(-50%);
  white-space: nowrap;
  bottom: 100%;
  margin-bottom: 0.2rem;
  color: var(--sc-nes-print);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  line-height: 1;
  text-align: center;
  text-transform: uppercase;
}

.sc-touchpad--nes .sc-pad-pill::after {
  content: "";
  position: absolute;
  left: 0.4rem;
  right: 0.4rem;
  top: 50%;
  height: 0.9rem;
  transform: translateY(-50%);
  border-radius: 999px;
  background: var(--sc-nes-black);
  box-shadow: 0 2px 0 rgba(0, 0, 0, 0.45);
}

.sc-touchpad--nes .sc-pad-pill.is-down {
  background: linear-gradient(180deg, var(--sc-nes-well-shade), var(--sc-nes-well));
  color: transparent;
}

.sc-touchpad--nes .sc-pad-pill.is-down::after {
  background: var(--sc-nes-black-down);
  box-shadow: none;
}

/* --- B and A ------------------------------------------------------------- */

.sc-touchpad--nes .sc-pad-faces {
  /* The wells are drawn with z-index -1; this keeps them above the faceplate
     and below their own buttons. */
  isolation: isolate;
  gap: clamp(0.85rem, 3.6vw, 1.35rem);
  /* Room for the letters printed under the wells. */
  padding: 0.3rem 0.3rem 1.25rem;
}

.sc-touchpad--nes .sc-pad-face {
  position: relative;
  border: none;
  background: radial-gradient(
    circle at 36% 30%,
    var(--sc-nes-red-light) 0,
    var(--sc-nes-red) 48%,
    var(--sc-nes-red-dark) 100%
  );
  box-shadow: 0 3px 0 #4f060a, 0 4px 6px rgba(0, 0, 0, 0.45);
  color: transparent;
}

/* The NES has B and A level with each other. */
.sc-touchpad--nes .sc-pad-face-b {
  transform: none;
}

/* The grey square well each button sits in. */
.sc-touchpad--nes .sc-pad-face::before {
  content: "";
  position: absolute;
  inset: -0.3rem;
  z-index: -1;
  border-radius: 0.5rem;
  background: linear-gradient(180deg, var(--sc-nes-well), var(--sc-nes-well-shade));
}

/* The letter, printed on the faceplate below and to the right of the well. */
.sc-touchpad--nes .sc-pad-face::after {
  content: attr(data-pad-button);
  position: absolute;
  right: -0.3rem;
  top: 100%;
  margin-top: 0.4rem;
  color: var(--sc-nes-print);
  font-size: 0.95rem;
  font-weight: 800;
  line-height: 1;
}

.sc-touchpad--nes .sc-pad-face.is-down {
  background: radial-gradient(circle at 50% 55%, var(--sc-nes-red) 0, var(--sc-nes-red-dark) 100%);
  box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.55);
  border-color: transparent;
  color: transparent;
}

/* Up to 400 px there is no room for SELECT and START between the d-pad and
   the face buttons without squeezing them to a sliver (15 px wide at 360 px,
   30 px at 375). Shrinking the d-pad and the faces instead would cost the
   controls that are pressed most, so the pills move under them, side by
   side. 400 rather than 375 because 375 is itself a common phone width (the
   SE and the minis), and by 401 px the middle column is 44 px wide.

   Below ~350 px even the top row does not fit: a full-size d-pad and two
   full-size face buttons pushed A's well and its printed letter off the
   faceplate. So the shell and padding thin out and the d-pad shrinks with
   the viewport, down to 7.25rem (116 px, arms 39 x 44) at 320 px; the face
   buttons keep their clamped size, because they are the ones held down. */
@media (max-width: 400px) {
  .sc-touchpad--nes {
    --sc-dpad-size: clamp(7.25rem, 36vw, 8rem);
    border-left-width: 0.35rem;
    border-right-width: 0.35rem;
    padding-left: 0.4rem;
    padding-right: 0.4rem;
    grid-template-columns: auto auto;
    grid-template-areas:
      "dpad   faces"
      "middle middle";
    justify-content: space-between;
    row-gap: 0.25rem;
  }

  .sc-touchpad--nes .sc-pad-middle {
    flex-direction: row;
    justify-content: center;
    max-width: 14rem;
  }

  .sc-touchpad--nes .sc-pad-pill {
    flex: 1 1 0;
  }
}

/* ==========================================================================
   Small screens
   --------------------------------------------------------------------------
   The tracker is used from a phone in the room where the bug happened, so
   every page has to work at ~390 px rather than merely survive it.
   ========================================================================== */

/* The screen must not eat the viewport, or the pad under it is below the fold
   and the page is unplayable without scrolling mid-game. */
@media (max-width: 1199.98px) {
  .sc-screen-frame {
    max-height: 56vh;
  }
}

@media (max-width: 575.98px) {
  .sc-screen-frame {
    max-height: 42vh;
  }

  .sc-play-container {
    padding-left: 0.5rem;
    padding-right: 0.5rem;
  }

  .card-body {
    padding: 0.75rem;
  }

  .card-header,
  .card-footer {
    padding: 0.6rem 0.75rem;
  }

  .sc-stat-value {
    font-size: 1.15rem;
  }

  .display-6 {
    font-size: 1.75rem;
  }
}

/* A phone held sideways has ~390 px of height, and an NES screen plus a pad
   plus a navbar do not fit in it stacked -- no amount of shrinking gets there,
   and a game pad below the fold is not a game pad. So in that orientation the
   two sit side by side, the way a handheld actually looks.

   The pad's track is `auto`, not a fraction: when the pad is hidden (a laptop
   with a mouse, at a short window) its grid item is display:none, the track
   collapses to zero and the screen takes the whole width, with no separate rule
   needed to say so. */
@media (orientation: landscape) and (max-height: 560px) {
  .sc-screen-body {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 0.75rem;
    align-items: center;
  }

  .sc-screen-body > #sc-build-panel,
  .sc-screen-body > .sc-screen-meta {
    grid-column: 1 / -1;
  }

  .sc-screen-body > .sc-screen-meta {
    margin-top: 0;
  }

  .sc-screen-frame {
    max-height: 64vh;
  }

  .sc-touchpad {
    --sc-dpad-size: clamp(5.5rem, 15vw, 8.5rem);
    --sc-face-size: clamp(2.5rem, 6.5vw, 3.5rem);
    gap: 0.5rem;
    padding: 0.5rem;
    margin-top: 0;
  }

  .sc-pad-middle {
    max-width: 9rem;
  }

  .sc-pad-action .btn {
    --bs-btn-padding-y: 0.25rem;
    font-size: 0.85rem;
  }
}

/* ==========================================================================
   Report list: a table on a wide screen, cards on a narrow one
   --------------------------------------------------------------------------
   The report table has eight columns and a description that wants 20+ rem.
   Sideways scrolling would technically work and would be miserable: the
   description is the only column anyone reads first, and it is the one that
   would be off-screen. Below md the same rows are rendered as cards instead,
   description leading, everything else demoted to one metadata line.
   ========================================================================== */

/* Only constrain the description column where the table exists at all.

   The ceiling matters more than the floor here, and it is the reason the old
   flat `max-width: 46rem` did not hold: an auto-layout table gives a cell its
   max-width when the content wants more, so a column of long descriptions was
   736 px wide whatever the window was, and pushed status and owner off the
   right-hand edge at every size below about 1600 px. Tying the ceiling to the
   viewport as well keeps the other columns on screen; `.table-responsive` is
   still there as the fallback for a freakishly long reporter name. */
@media (min-width: 992px) {
  .sc-description-cell {
    min-width: 16rem;
    max-width: min(46rem, 38vw);
  }
}

@media (min-width: 1200px) {
  .sc-description-cell {
    min-width: 22rem;
  }
}

.sc-report-card-item {
  display: block;
  padding: 0.75rem 0.9rem;
  color: var(--sc-text);
  text-decoration: none;
}

.sc-report-card-item + .sc-report-card-item {
  border-top: 1px solid var(--sc-line);
}

.sc-report-card-item:hover,
.sc-report-card-item:focus {
  background: rgba(96, 211, 148, 0.07);
  color: var(--sc-text);
}

.sc-report-card-title {
  overflow-wrap: anywhere;
}

.sc-report-card-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 0.75rem;
  font-size: 0.78rem;
  color: var(--sc-muted);
}

/* Edit history: two long free-text columns cannot share a phone screen with
   three metadata columns, so below md each revision is a stacked block. */
.sc-revision-item {
  padding: 0.75rem 0.9rem;
}

.sc-revision-item + .sc-revision-item {
  border-top: 1px solid var(--sc-line);
}

.sc-revision-value {
  overflow-wrap: anywhere;
  white-space: pre-wrap;
}

@media (max-width: 991.98px) {
  .sc-revision-cell {
    max-width: none;
  }

  /* The input log stays a table -- it is a machine record and its columns are
     narrow -- but it scrolls inside its own box rather than widening the page,
     and it gives up height it does not need on a phone. */
  .sc-scroll-tall {
    max-height: 16rem;
  }
}

.sc-hexdump,
.table-responsive {
  -webkit-overflow-scrolling: touch;
}

/* Anything a thumb has to hit needs to be about 44 px. */
@media (pointer: coarse) {
  .btn,
  .form-control,
  .form-select {
    min-height: 2.75rem;
  }

  .btn-sm,
  .form-select-sm,
  .form-control-sm {
    min-height: 2.25rem;
  }

  .btn-link {
    min-height: 0;
  }

  .sc-thumb {
    width: 72px;
    height: 68px;
  }
}

/* ---------------------------------------------------------------------------
 * The "what should we call you?" dialog (assets/identity.js)
 *
 * Built by hand rather than with a Bootstrap modal, because only Bootstrap's
 * stylesheet is vendored on this box and none of its JavaScript components are
 * available -- the same constraint the navbar collapse works around in nav.js.
 *
 * Two code paths need styling, and they need it to look identical:
 *
 *   <dialog>, where the browser supplies the top layer, the focus trap and the
 *   backdrop. Only ::backdrop needs colouring, and `dialog` needs its default
 *   white background and border removed.
 *
 *   A plain <div> fallback, which has none of that and therefore has to be
 *   positioned, layered and dimmed by hand.
 * ------------------------------------------------------------------------ */

.sc-identity-dialog {
  width: min(26rem, calc(100vw - 2rem));
  padding: 1.25rem;
  border: 1px solid var(--sc-line);
  border-radius: 0.75rem;
  background: var(--sc-panel);
  color: var(--sc-text);
  box-shadow: 0 1.5rem 3rem rgba(0, 0, 0, 0.55);
}

.sc-identity-dialog::backdrop {
  background: rgba(4, 6, 8, 0.72);
}

/* The fallback: <div> gets none of <dialog>'s behaviour, so it is centred and
   layered here. `[hidden]` is not enough on its own once display is set. */
div.sc-identity-dialog {
  position: fixed;
  inset: 0;
  z-index: 1080;
  margin: auto;
  height: fit-content;
  display: none;
}

div.sc-identity-dialog.sc-identity-open {
  display: block;
}

/* And its backdrop, which a <div> has no ::backdrop for. */
div.sc-identity-dialog.sc-identity-open::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  background: rgba(4, 6, 8, 0.72);
}

.sc-identity-form .form-control {
  background: var(--sc-panel-2);
  border-color: var(--sc-line);
  color: var(--sc-text);
}

/* Rewind is pressed and held (play.js): no scroll, zoom or text selection
   may take the finger away from it on a touch screen. */
.sc-rewind-button {
  touch-action: none;
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}
