:root {
  /* Tells the browser this page is designed for light mode, so it doesn't
     apply its own dark-mode styling to native form controls (inputs,
     etc.) when the OS/browser prefers dark - that can otherwise silently
     make an input's text render in a color that clashes with our own
     background, even though our CSS never asked for that. */
  color-scheme: light;

  --gb-body: #c4c4b0;
  --gb-body-dark: #9a9a88;
  --gb-body-edge: #6e6e5e;
  --gb-screen-frame: #6b7353;
  --gb-screen-bg: #0f380f;
  --gb-purple: #8b1e5a;
  --gb-purple-dark: #5c123c;
  --gb-ink: #2a2a22;
  --gb-muted: #4a4a3a;
}

* {
  box-sizing: border-box;
  -webkit-tap-highlight-color: transparent;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}

html,
body {
  margin: 0;
  min-height: 100%;
  height: 100%;
  touch-action: none;
  overscroll-behavior: none;
  background:
    radial-gradient(circle at 20% 10%, #d8d8c6 0%, transparent 45%),
    radial-gradient(circle at 90% 80%, #b8b8a4 0%, transparent 40%),
    linear-gradient(160deg, #d0d0bc 0%, #a8a894 100%);
  color: var(--gb-ink);
  font-family: "Trebuchet MS", "Segoe UI", sans-serif;
}

body {
  display: flex;
  align-items: stretch;
  justify-content: center;
  padding: 0;
  min-height: 100dvh;
}

.room-missing-banner {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  z-index: 60;
}

/* The `hidden` attribute's built-in browser rule is just `display: none` in
   the browser's own stylesheet - any rule here that also sets `display`
   (like the one above) silently overrides it, so the banner/shell would
   show even while `hidden` was set. These make `hidden` win regardless. */
.room-missing-banner[hidden],
.shell[hidden] {
  display: none !important;
}

.room-missing-card {
  width: min(100%, 360px);
  padding: 24px;
  border-radius: 16px;
  border: 3px solid var(--gb-body-edge);
  background: linear-gradient(180deg, #d2d2be 0%, var(--gb-body) 55%, var(--gb-body-dark) 100%);
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.35);
  text-align: center;
}

.room-missing-card h2 {
  margin: 0 0 8px;
  font-size: 1.1rem;
  letter-spacing: 0.06em;
  color: var(--gb-purple);
}

.room-missing-card p {
  margin: 0 0 16px;
  font-size: 0.85rem;
  color: var(--gb-muted);
}

.shell {
  width: min(100%, 540px);
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  background: linear-gradient(180deg, #d2d2be 0%, var(--gb-body) 40%, var(--gb-body-dark) 100%);
  border: none;
  border-radius: 0;
  padding: 10px 14px calc(12px + env(safe-area-inset-bottom, 0px));
  box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.35);
}

.brand {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin: 0 0 8px;
  letter-spacing: 0.08em;
  flex: 0 0 auto;
}

.brand-text {
  display: flex;
  align-items: baseline;
  gap: 8px;
  min-width: 0;
}

.brand-mark {
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--gb-purple);
}

.brand-name {
  font-size: 1.2rem;
  font-weight: 800;
  font-style: italic;
  color: var(--gb-purple);
}

.settings-btn {
  width: 40px;
  height: 40px;
  border: none;
  border-radius: 10px;
  background: rgba(0, 0, 0, 0.12);
  color: var(--gb-ink);
  font-size: 1.25rem;
  line-height: 1;
  cursor: pointer;
}

.settings-btn:active {
  filter: brightness(0.92);
}

.settings-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(20, 20, 16, 0.45);
  z-index: 40;
}

.settings-panel {
  position: fixed;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: min(92vw, 380px);
  max-height: min(80vh, 520px);
  overflow: auto;
  z-index: 50;
  padding: 16px;
  border-radius: 16px;
  border: 3px solid var(--gb-body-edge);
  background: linear-gradient(180deg, #d2d2be 0%, var(--gb-body) 55%, var(--gb-body-dark) 100%);
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.35);
}

.settings-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
}

.settings-header h2 {
  margin: 0;
  font-size: 1.1rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.settings-close {
  width: 36px;
  height: 36px;
  border: none;
  border-radius: 8px;
  background: rgba(0, 0, 0, 0.12);
  color: var(--gb-ink);
  font-size: 1rem;
  cursor: pointer;
}

.settings-section {
  margin-bottom: 16px;
}

.settings-section h3 {
  margin: 0 0 8px;
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  color: var(--gb-muted);
  text-transform: uppercase;
}

.setting-row {
  padding: 12px;
  border-radius: 10px;
  background: rgba(0, 0, 0, 0.06);
  border: 2px dashed var(--gb-body-edge);
}

.setting-row-top {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 8px;
  font-size: 0.85rem;
  font-weight: 700;
}

#bufferRange {
  width: 100%;
  accent-color: var(--gb-purple);
}

.setting-help {
  margin: 8px 0 0;
  font-size: 0.72rem;
  color: var(--gb-muted);
}

.toggle-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px;
  border-radius: 10px;
  background: rgba(0, 0, 0, 0.06);
  border: 2px dashed var(--gb-body-edge);
  font-size: 0.85rem;
  font-weight: 700;
  cursor: pointer;
}

.toggle-row input {
  width: 20px;
  height: 20px;
  accent-color: var(--gb-purple);
}

.btn-row {
  display: grid;
  gap: 8px;
}

.screen-bezel {
  background: linear-gradient(180deg, #7a825f 0%, var(--gb-screen-frame) 100%);
  border-radius: 14px 14px 28px 14px;
  padding: 8px 10px 12px;
  margin-bottom: 10px;
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.screen-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  align-self: stretch;
  margin-bottom: 6px;
  color: #d6dec0;
  font-size: 0.65rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #3a1010;
  box-shadow: 0 0 0 1px #220808;
}

.dot.live {
  background: #ff3b3b;
  box-shadow: 0 0 8px #ff5050;
}

.control-badge {
  margin-left: auto;
  padding: 2px 8px;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.3);
  color: #d6dec0;
  font-size: 0.6rem;
  letter-spacing: 0.1em;
}

.control-badge.mine {
  background: var(--gb-purple);
  color: #f7d7e7;
}

/* Viewer mode: on-screen game buttons are grayed out and can't be tapped -
   the server already rejects their input, this just avoids the misleading
   press animation/haptic on a button that wouldn't do anything. */
body.viewer-mode .dpad-btn,
body.viewer-mode .face-btn,
body.viewer-mode .sys-btn {
  opacity: 0.35;
  pointer-events: none;
}

/* Same idea for the Settings actions that mutate the shared game - these
   are the ones actually enforced server-side (controller_check in app.py);
   graying them out here just matches the UI to that. ROM library upload is
   deliberately NOT included - adding a ROM to the shared library doesn't
   affect the currently-running game, so it stays open to everyone. */
body.viewer-mode #romPlayBtn,
body.viewer-mode #romResumeBtn,
body.viewer-mode #romDeleteBtn,
body.viewer-mode #stopBtn,
body.viewer-mode #saveNow,
body.viewer-mode #saveDelete,
body.viewer-mode label[for="saveFile"],
body.viewer-mode #engineSelect,
body.viewer-mode #bufferRange {
  opacity: 0.4;
  pointer-events: none;
}

.viewer-notice {
  margin: -4px 0 14px;
  padding: 8px 10px;
  border-radius: 8px;
  background: rgba(0, 0, 0, 0.08);
  text-align: center;
}

.chat-body {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.chat-messages {
  max-height: 320px;
  min-height: 120px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 6px 4px;
  border-radius: 10px;
  background: rgba(0, 0, 0, 0.06);
}

.chat-message {
  font-size: 0.78rem;
  line-height: 1.4;
  word-break: break-word;
}

.chat-message .chat-role {
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  font-size: 0.62rem;
  margin-right: 6px;
}

.chat-message.role-controller .chat-role {
  color: var(--gb-purple);
}

.chat-message.role-viewer .chat-role {
  color: var(--gb-muted);
}

.chat-form {
  display: flex;
  gap: 8px;
}

.chat-input {
  flex: 1;
  min-width: 0;
  padding: 9px 10px;
  border-radius: 8px;
  border: 2px dashed var(--gb-body-edge);
  background: rgba(0, 0, 0, 0.06);
  color: var(--gb-ink);
  caret-color: var(--gb-ink);
  font-family: inherit;
  font-size: 0.8rem;
  -webkit-user-select: text;
  user-select: text;
}

.chat-input:focus {
  outline: none;
  border-color: var(--gb-purple);
}

.chat-form .cart-btn {
  /* .cart-btn's base rule sets width:100% (correct for buttons that fill
     their own row elsewhere, like Play/Delete) - inside this flex row that
     fights with .chat-input's flex:1, starving the input down to almost
     nothing. Reset it to a normal content-sized, non-growing, non-
     shrinking button so the input gets all the remaining space instead. */
  width: auto;
  flex: 0 0 auto;
  padding: 9px 14px;
  font-size: 0.72rem;
  white-space: nowrap;
}

#screen {
  display: block;
  /* Prefer filling width; grow tall - up to ~66% of the viewport */
  width: min(100%, calc(66dvh * 160 / 144));
  height: auto;
  aspect-ratio: 160 / 144;
  background: var(--gb-screen-bg);
  image-rendering: pixelated;
  image-rendering: crisp-edges;
  border-radius: 4px;
}

.controls {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 20px;
  margin: 8px 0 0;
  padding: 4px 2px 0;
  flex: 1 0 auto;
  min-height: 180px;
}

.dpad {
  width: 172px;
  height: 172px;
  display: grid;
  grid-template-columns: 54px 54px 54px;
  grid-template-rows: 54px 54px 54px;
  gap: 5px;
  justify-content: center;
  align-content: center;
  margin: 0;
  flex: 0 0 auto;
}

.dpad-btn[data-pos="2"] { grid-column: 2; grid-row: 1; }
.dpad-btn[data-pos="1"] { grid-column: 1; grid-row: 2; }
.dpad-btn[data-pos="0"] { grid-column: 3; grid-row: 2; }
.dpad-btn[data-pos="3"] { grid-column: 2; grid-row: 3; }

.btn {
  touch-action: none;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}

.dpad-btn {
  background: linear-gradient(180deg, #3a3a3a, #1c1c1c);
  color: #ccc;
  border: none;
  border-radius: 10px;
  font-size: 1.05rem;
}

.face-buttons {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 28px;
  padding: 0 6px 10px 0;
  transform: rotate(-18deg);
  flex: 0 0 auto;
  margin-left: auto;
}

.face-btn {
  width: 78px;
  height: 78px;
  border: none;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #c94a84, var(--gb-purple) 55%, var(--gb-purple-dark));
  color: #f7d7e7;
  font-weight: 800;
  font-size: 1.2rem;
  box-shadow: 0 6px 0 #4a0e30;
}

.face-btn:active,
.face-btn.pressed,
.dpad-btn:active,
.dpad-btn.pressed,
.sys-btn:active,
.sys-btn.pressed {
  transform: translateY(2px);
  filter: brightness(0.9);
}

.face-btn:active,
.face-btn.pressed {
  box-shadow: 0 3px 0 #4a0e30;
}

.system-buttons {
  display: flex;
  justify-content: center;
  gap: 56px;
  margin: 10px 0 4px;
  flex: 0 0 auto;
}

.sys-btn {
  min-width: 96px;
  padding: 10px 16px;
  border: none;
  border-radius: 999px;
  background: linear-gradient(180deg, #5a5a4a, #333328);
  color: #ddd;
  font-size: 0.7rem;
  letter-spacing: 0.14em;
  transform: rotate(-18deg);
}

.storage-meter {
  padding: 12px;
  border-radius: 10px;
  background: rgba(0, 0, 0, 0.06);
  border: 2px dashed var(--gb-body-edge);
  margin-bottom: 10px;
}

.rom-search {
  display: block;
  width: 100%;
  padding: 10px 12px;
  margin-bottom: 8px;
  border-radius: 10px;
  background: rgba(0, 0, 0, 0.06);
  border: 2px dashed var(--gb-body-edge);
  color: var(--gb-ink);
  font-family: inherit;
  font-size: 0.82rem;
  font-weight: 700;
  -webkit-user-select: text;
  user-select: text;
}

.rom-search::placeholder {
  color: var(--gb-muted);
  font-weight: 400;
}

.rom-search:focus {
  outline: none;
  border-color: var(--gb-purple);
}

.rom-select {
  display: block;
  width: 100%;
  margin: 0 0 12px;
  padding: 10px 12px;
  border-radius: 10px;
  background: rgba(0, 0, 0, 0.06);
  border: 2px dashed var(--gb-body-edge);
  color: var(--gb-ink);
  font-family: inherit;
  font-size: 0.82rem;
  font-weight: 700;
}

.rom-select:focus {
  outline: none;
  border-color: var(--gb-purple);
}

.rom-select option:disabled {
  color: var(--gb-muted);
}

.engine-row {
  margin: 12px 0;
  padding: 10px 12px;
  border-radius: 10px;
  background: rgba(0, 0, 0, 0.06);
}

.engine-row-label {
  display: block;
  font-size: 0.68rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--gb-muted);
  margin-bottom: 6px;
}

.engine-select {
  display: block;
  width: 100%;
  padding: 8px 10px;
  border-radius: 8px;
  border: 2px dashed var(--gb-body-edge);
  background: rgba(0, 0, 0, 0.06);
  color: var(--gb-ink);
  font-family: inherit;
  font-size: 0.78rem;
  font-weight: 700;
}

.engine-select:focus {
  outline: none;
  border-color: var(--gb-purple);
}

.engine-row .setting-help {
  margin: 6px 0 0;
}

.cart-info {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-bottom: 10px;
  min-width: 0;
}

.cart-label {
  font-size: 0.65rem;
  letter-spacing: 0.16em;
  color: var(--gb-muted);
}

#romName {
  font-size: 0.85rem;
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.cart-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  padding: 10px 12px;
  border-radius: 8px;
  background: linear-gradient(180deg, #5a5a4a, #333328);
  color: #f0f0e4;
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  cursor: pointer;
}

.cart-btn:active {
  filter: brightness(0.92);
}

.cart-btn.busy {
  opacity: 0.6;
  pointer-events: none;
}

.cart-btn.secondary {
  background: linear-gradient(180deg, #6a6a58, #404034);
}

.cart-btn.danger {
  background: linear-gradient(180deg, #8a3a4a, #5a1828);
}

.progress-track {
  margin-top: 10px;
  height: 6px;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.18);
  overflow: hidden;
}

.progress-bar {
  height: 100%;
  width: 0%;
  background: linear-gradient(90deg, var(--gb-purple), #c94a84);
  transition: width 0.12s linear;
}

.upload-msg {
  margin: 8px 0 0;
  min-height: 1em;
  font-size: 0.72rem;
  color: var(--gb-muted);
  text-align: center;
}

.upload-msg.error {
  color: #7a1028;
}

.upload-msg.ok {
  color: #2f5d2f;
}

.hint {
  margin: 6px 0 0;
  text-align: center;
  font-size: 0.68rem;
  color: var(--gb-muted);
  flex: 0 0 auto;
}

/* Short phones: keep screen dominant, tighten chrome */
@media (max-height: 700px) {
  .brand-name {
    font-size: 1.05rem;
  }

  #screen {
    width: min(100%, calc(60dvh * 160 / 144));
  }

  .controls {
    min-height: 148px;
  }

  .hint {
    display: none;
  }
}

@media (max-width: 380px) {
  .shell {
    padding-inline: 10px;
  }

  .dpad {
    width: 156px;
    height: 156px;
    grid-template-columns: 48px 48px 48px;
    grid-template-rows: 48px 48px 48px;
  }

  .face-btn {
    width: 70px;
    height: 70px;
  }

  .face-buttons {
    gap: 22px;
  }

  .system-buttons {
    gap: 40px;
  }
}

/* Wider phones / desktop: roomier shell, bigger playfield */
@media (min-width: 480px) {
  body {
    padding: 12px;
    align-items: center;
  }

  .shell {
    min-height: min(100dvh, 860px);
    height: min(100dvh, 860px);
    border: 3px solid var(--gb-body-edge);
    border-radius: 22px 22px 56px 56px;
    box-shadow:
      inset 0 2px 0 rgba(255, 255, 255, 0.35),
      0 18px 40px rgba(0, 0, 0, 0.28);
  }

  #screen {
    width: min(100%, calc(68dvh * 160 / 144), 540px);
  }

  .dpad {
    width: 188px;
    height: 188px;
    grid-template-columns: 58px 58px 58px;
    grid-template-rows: 58px 58px 58px;
    gap: 6px;
  }

  .face-btn {
    width: 84px;
    height: 84px;
  }

  .face-buttons {
    gap: 34px;
  }

  .system-buttons {
    gap: 64px;
  }
}

/* Desktop: chat becomes a permanent sidebar to the right of the shell,
   always visible, instead of the toggleable overlay used on narrower
   screens (there isn't room for both side by side below this width).
   #chatPanel is already a sibling of .shell in the DOM, so once it's
   taken out of position:fixed here, body's flexbox lays it out as a
   second column automatically - no HTML restructuring needed. */
@media (min-width: 900px) {
  #chatBtn {
    display: none;
  }

  #chatBackdrop {
    display: none;
  }

  #chatClose {
    display: none;
  }

  #chatPanel {
    /* Overrides .settings-panel's fixed/centered-modal positioning.
       Docked to the right edge of the VIEWPORT (not just placed next to
       .shell in flex flow) so it reads as its own separate window, like a
       real chat sidebar - independent of the shell's own centering.
       display:flex here also overrides the [hidden] attribute's default
       display:none - deliberately, so the panel stays visible regardless
       of whatever open/closed state the (now-hidden) mobile toggle left
       it in. Height is set in JS (syncChatPanelHeight) to exactly match
       .shell's actual rendered height - flexbox align-items:stretch
       turned out not to reliably produce equal heights here, so this is
       measured and applied directly instead. */
    position: fixed;
    display: flex !important;
    flex-direction: column;
    left: auto;
    right: 32px;
    top: 50%;
    transform: translateY(-50%);
    width: 320px;
    max-height: none;
    margin: 0;
  }

  .chat-body {
    flex: 1;
    min-height: 0;
  }

  .chat-messages {
    flex: 1;
    max-height: none;
  }
}
