/* A game screen is the only lit thing on the page and the page is looked at in
   the dark as often as not, so the paper around it is the same near-black the
   panels already use rather than the browser's white. */
:root {
  /* 지령전 다크 테마 */
  --bg-main: #0C090B;
  --bg-panel: #1B1216;
  --bg-elevated: #26181D;
  --border: #432B32;
  /* 지옥의 불꽃 */
  --primary: #C7283E;
  --primary-hover: #E14456;
  --accent: #FF7844;
  --accent-gold: #FFC071;
  /* 글자 */
  --text-main: #F6E8E9;
  --text-muted: #B49EA3;
  --danger: color-mix(in srgb, var(--primary) 72%, black);
  --canvas-black: #000;
  --shadow: rgb(from var(--canvas-black) r g b / .45);
  --shadow-heavy: rgb(from var(--canvas-black) r g b / .6);
  --fire-haze: rgba(165, 25, 38, 0.16);
  --fire-shadow: rgba(165, 25, 38, .25);
  --card-glow: rgba(199, 40, 62, .35);
  /* The sliders, checkboxes, dropdown lists and scrollbars are the browser's
     own, and it draws them light unless told which way round the page is. */
  color-scheme: dark;

  --stage-vertical: 0px;
  --viewport-height: 100vh;
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --safe-left: env(safe-area-inset-left, 0px);
  --safe-right: env(safe-area-inset-right, 0px);
  --stage-height: max(0px, calc(var(--viewport-height) - var(--stage-vertical)));
  --usable-height: max(0px, calc(var(--stage-height) - var(--safe-top) - var(--safe-bottom)));
  --keypad-width: min(480px, max(0px, calc(100vw - var(--safe-left) - var(--safe-right))));
  /* Reserve nine base-height rows when there is room, or 55% of a short
     window. Any height left after the fitted game belongs to the keypad. */
  --keypad-reserved: min(284px, calc(var(--usable-height) * 0.55));
  --canvas-width: min(var(--keypad-width),
      calc((var(--usable-height) - var(--keypad-reserved)) * 0.75));
  --canvas-height: calc(var(--canvas-width) / 0.75);
  --keypad-grid-height: max(0px, calc(var(--usable-height) - var(--canvas-height)));
  /* Gaps shrink too in extremely short/narrow windows; every cell stays inside
     the board. The renderer reads this same computed gap for shape hit areas. */
  --keypad-gap: min(4px, calc(var(--keypad-grid-height) / 18), calc(var(--keypad-width) / 28));
  --keypad-cell-height: calc((var(--keypad-grid-height) - 8 * var(--keypad-gap)) / 9);
}

@supports (height: 100dvh) {
  :root { --viewport-height: 100dvh; }
}

body, p {
  margin: 0px;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}

body {
  background: radial-gradient(ellipse at 50% 110%, var(--fire-haze), transparent 60%), var(--bg-main);
  color: var(--text-main);
}

/* The stage is one column by default. The rails carry no layout of their own
   here — their panels are modals, which take no space — so a phone lays out
   exactly as it did before the rails existed. */
.stage {
  display: block;
  padding-inline: var(--safe-left) var(--safe-right);
  box-sizing: border-box;
}

/* The game and keypad share one height budget and touch at their common edge.
   Only the OS safe areas remain outside it; no decorative bottom gap is kept. */
.stage-main {
  display: flex;
  flex-direction: column;
  height: var(--stage-height);
  box-sizing: border-box;
  padding-top: var(--safe-top);
  padding-bottom: var(--safe-bottom);
}

.rail {
  display: contents;
}

.log-card {
  display: none;
}

.prestart {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: safe center;
  /* Adding a game and starting one are two different intentions, and the gap
     is what says so: without it the second row reads as part of the first and
     a thumb aimed at 실행 lands on ＋ 게임 추가. */
  gap: 28px;
  padding: 24px;
  background: var(--bg-panel);
  box-sizing: border-box;
  /* Short screens keep the menu inside the game area. Safe alignment leaves
     its first controls reachable when the contents need to scroll. */
  overflow-y: auto;
  overscroll-behavior: contain;
  touch-action: pan-y;
  transition: opacity 0.3s ease;
}

.prestart > * {
  flex-shrink: 0;
}

.prestart.hidden {
  opacity: 0;
  pointer-events: none;
}

.prestart-row {
  display: flex;
  gap: 12px;
  align-items: center;
  flex-wrap: wrap;
  justify-content: center;
  max-width: 100%;
}

/* The hint under the picker belongs to the row above it, so it gives back most
   of the column's gap, and it is quieter than the controls it is about. It
   wraps between words: a Korean line broken inside one reads as two. */
.prestart-note {
  margin: -18px 0 0;
  max-width: 24em;
  color: var(--text-muted);
  font-size: 0.85em;
  line-height: 1.45;
  text-align: center;
  word-break: keep-all;
}

/* Editing occupies the game screen while the grid stays visible below it.
   The panel scrolls inside short viewports. */
.keypad-arrange {
  display: none;
  position: absolute;
  inset: 0;
  box-sizing: border-box;
  flex-direction: column;
  gap: 10px;
  /* The same padding the settings panel has, because the header bar the two
     share is pulled out to the edges with a negative margin cut to it. */
  padding: 12px 14px 14px;
  overflow-y: auto;
  overscroll-behavior: contain;
  background: var(--bg-panel);
  color: var(--text-main);
  font-size: 0.9em;
  /* The panel scrolls independently of keypad selection gestures. */
  touch-action: auto;
}

.keypad-arrange.visible {
  display: flex;
}

/* Each type keeps its own arrangement. */
.keypad-arrange-shape {
  display: flex;
  align-items: center;
  gap: 8px;
}

.keypad-arrange-shape select {
  flex: 1;
  min-width: 0;
}

.keypad-arrange-tools {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.keypad-arrange-tools button {
  font: inherit;
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 6px 8px;
  background: var(--bg-elevated);
  color: inherit;
  cursor: pointer;
}

.keypad-arrange-tools button[aria-pressed="true"],
.keypad-arrange-keys button[aria-pressed="true"] {
  background: var(--bg-elevated);
  outline: 1px solid var(--accent-gold);
}

.keypad-arrange-tools button:disabled { opacity: 0.4; cursor: default; }
.keypad-arrange-storage { color: var(--danger); margin: 0; }

.keypad-arrange-hint {
  margin: 0;
  line-height: 1.4;
  color: var(--text-muted);
}

/* A class rule beats the browser's own `[hidden] { display: none }` whatever
   its specificity — author styles win over the user agent's — so the display
   this sets has to be given back. The attribute is what the panel toggles from
   script, because `el.hidden` is the one way to hide something that needs no
   second name for the state. */
.keypad-arrange-keys[hidden] {
  display: none;
}

.keypad-arrange-keys {
  display: grid;
  /* Twenty keys, and the shortest is one character: a fixed column count would
     make a 3.5em button for 확인 and the same for 5. */
  grid-template-columns: repeat(auto-fill, minmax(3.2em, 1fr));
  gap: 6px;
}

.keypad-arrange-keys button {
  font: inherit;
  padding: 8px 4px;
  background: var(--bg-elevated);
  color: var(--text-main);
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.keypad-arrange-keys button:hover {
  background: var(--bg-elevated);
}

/* Emptying a cell is not one of the twenty, and it is not a key: it is the
   thing the other nineteen are not, so it does not sit in the grid with them. */
.keypad-arrange-keys button.keypad-arrange-clear {
  grid-column: 1 / -1;
  background: var(--bg-elevated);
}

/* The settings key in the list wears the colour it wears on the pad. */
.keypad-arrange-keys button.keypad-arrange-settings {
  background: var(--bg-elevated);
}

.keypad-arrange-keys button.keypad-arrange-settings:hover {
  background: var(--bg-elevated);
}

/* Nothing in the list acts on the cell holding the settings key; app.js
   disables the list while that cell is picked, and this says so. */
.keypad-arrange-keys button:disabled {
  opacity: 0.4;
  cursor: default;
}

.game-select,
.game-start,
.game-add {
  font: inherit;
  border-radius: 4px;
}

/* The input is never seen: it is opened by the button beside it, which says
   what it is for. A bare file input says "파일 선택" and nothing about games. */
.game-file {
  display: none;
}

/* The same shape as 실행, and a quieter fill. They are the same kind of thing
   — one press, one word — but only one of them is what the screen is for, and
   two buttons of equal weight would make a person read both every time. */
.game-add {
  background: var(--bg-elevated);
  color: var(--text-main);
  border: none;
  padding: 14px 28px;
  cursor: pointer;
}

.game-add:hover:not(:disabled) {
  background: var(--bg-elevated);
}

.game-add:disabled {
  cursor: wait;
  opacity: 0.65;
}

/* Smaller than 게임 추가 and quieter than it, because deleting is the rarer
   errand of the two and the one that cannot be undone from this screen. The
   red is kept for the hover: at rest it is one more button in a row, and under
   a finger it says what it is about to do. */
.game-remove {
  padding: 8px 16px;
  font-size: 0.9em;
}

.game-remove:hover:not(:disabled) {
  background: var(--bg-elevated);
}

/* Disabled means "not yours to delete" here rather than "busy", which is what
   the shared rule above assumes: this one is the state of the game the picker
   is showing, and it can sit there for the whole visit. */
.game-remove:disabled {
  cursor: not-allowed;
}

/* Two more buttons at the weight of 게임 추가 would make the first screen read
   as four equal choices. Backing a save up is the rarer errand of the four, so
   the pair is smaller rather than louder. */
.save-backup {
  padding: 8px 16px;
  font-size: 0.9em;
}

.game-select {
  width: min(100%, 300px);
  padding: 13px 12px;
  border: 1px solid var(--border);
  background: var(--bg-elevated);
  color: var(--text-main);
}

.game-start {
  background: var(--bg-elevated);
  color: var(--text-main);
  border: none;
  padding: 14px 28px;
  cursor: pointer;
}

.game-start:hover:not(:disabled) {
  background: var(--bg-elevated);
}

.game-start:disabled,
.game-select:disabled {
  cursor: wait;
  opacity: 0.65;
}

/* The settings key (설정) is a keypad cell like the rest, so nothing here
   positions it: the grid places it wherever the person put it. What sets it
   apart is its colour — see the rule by its key below. */

.canvas-wrapper {
  position: relative;
  margin: 0 auto;
  flex: 0 0 var(--canvas-height);
  min-height: 0;
  /* The last term is a height budget: what has to stay on screen is the keypad
     under the canvas, so the room left over for the hole is the viewport less
     the keypad, turned back into a width by the hole's 3:4. It is in the base
     rule rather than a media query because a keypad pushed off the bottom is
     not a phone-only shape — a half-height desktop window does it too. */
  width: var(--canvas-width);
  /* The wrapper is the hole the handset is looked at through, not the handset:
     it keeps the default screen's 3:4 whatever the game is running on, so a
     larger screen setting is shown smaller inside the same hole rather than
     growing the page and pushing the keypad past the bottom of it. */
  aspect-ratio: 0.75;
  /* What the frame does not cover once it is fitted rather than stretched. */
  background: var(--bg-main);
  z-index: 1;
}

#canvas {
  display: block;
  width: 100%;
  height: 100%;
  /* The element takes the whole hole, but the frame inside it is fitted rather
     than stretched: the screen setting offers handsets that are 3:5 and 2:3 as
     well as the hole's 3:4, and a frame of another shape keeps its own and
     leaves the axis that does not fill as bezel — the wrapper's black. */
  object-fit: contain;
  /* The frame is 240x320 shown several times that size, and the browser's
     default smoothing turns a pixel-art frame into a blurred one. Letting the
     compositor take the nearest pixel costs nothing and is what makes the
     unmagnified setting worth choosing: the alternative is hq2x and up, which
     cost more per frame on this hardware than emulating the frame did. */
  image-rendering: pixelated;
}

/* Settings and cheats are centred modals on anything narrower than the
   three-column layout. A phone cannot scroll the page (touch-action: none) and
   the keypad already fills its viewport, so a panel anchored to the flow would
   hang below the fold with no way to reach it. */
.settings-panel {
  display: none;
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: min(92vw, 360px);
  max-height: 82dvh;
  overflow-y: auto;
  overscroll-behavior: contain;
  z-index: 210;
  box-sizing: border-box;
  background: var(--bg-elevated);
  color: var(--text-main);
  border-radius: 8px;
  padding: 12px 14px 14px;
  font-size: 0.9em;
  box-shadow: 0 8px 28px var(--shadow);
  touch-action: auto;
}

.settings-panel.visible {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.settings-panel label {
  display: flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
}

/* A row the page removes. The rule above sets `display: flex`, which beats the
   browser's own `[hidden] { display: none }`, so a row hidden by script would
   otherwise stay on screen — which is how the vibration switch would show up on
   a browser that has no vibrator to switch. */
.settings-panel label[hidden] {
  display: none;
}

.settings-panel input[type="range"] {
  width: 120px;
  margin-left: auto;
  min-width: 0;
}

.panel-header,
.cheat-header {
  position: sticky;
  top: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.panel-header {
  margin: -12px -14px 4px;
  padding: 10px 14px;
  background: var(--bg-elevated);
  border-bottom: 1px solid var(--border);
}

.panel-close,
.cheat-close {
  font: inherit;
  background: var(--bg-elevated);
  color: var(--text-main);
  border: none;
  border-radius: 4px;
  padding: 5px 12px;
  cursor: pointer;
}

.panel-close:hover,
.cheat-close:hover {
  background: var(--bg-elevated);
}

.game-speed {
  width: 120px;
  margin-left: auto;
  padding: 2px 4px;
  font: inherit;
  color: inherit;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: 4px;
}

.modal-backdrop {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 150;
  background: var(--shadow);
}

.button-container {
  position: relative;
  width: var(--keypad-width);
  margin: 0 auto;
  padding: 0;
  flex: 1 1 0;
  min-height: 0;
  box-sizing: border-box;
}

.keypad-grid {
  position: relative;
  height: 100%;
  gap: var(--keypad-gap);
  touch-action: none;
}
.keypad-clips { position: absolute; pointer-events: none; }
.button-container .keypad-cell {
  position: absolute;
  margin: 0;
  padding: 0;
  min-width: 0;
  border: 0;
  border-radius: 0;
  font: inherit;
  font-size: min(16px, calc(var(--keypad-cell-height) * 0.58));
  background: var(--bg-elevated);
  color: var(--text-main);
  cursor: pointer;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
}
.keypad-label {
  position: absolute;
  transform: translateY(-50%);
  line-height: 1.1;
  white-space: nowrap;
  pointer-events: none;
}
.keypad-outline {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  fill: none;
  stroke: var(--border);
  stroke-width: 2;
}
.keypad-cell.empty { visibility: hidden; }
.button-container.arranging .keypad-cell.empty {
  visibility: visible;
  background: var(--bg-panel);
  color: var(--text-muted);
}
.button-container.arranging .keypad-cell.empty .keypad-outline { stroke-dasharray: 3 3; }
.button-container .keypad-cell:hover { background: var(--bg-elevated); }
.button-container .keypad-cell.pressed { background: var(--accent); color: var(--bg-main); }
.button-container .keypad-cell[data-key="SETTINGS"] { background: var(--bg-elevated); color: var(--text-main); }
.button-container .keypad-cell[data-key="SETTINGS"]:hover { background: var(--bg-elevated); }
.button-container.arranging .keypad-cell.picked { background: var(--bg-elevated); }
/* A pressed key must only repaint. Chromium lays an SVG outline out again when
   its stroke width or its opacity changes, and not when its stroke-opacity does. */
.keypad-highlight { stroke: var(--accent-gold); stroke-width: 4; stroke-opacity: 0; }
.keypad-cell.pressed .keypad-edge,
.keypad-cell.picked .keypad-edge,
.keypad-cell:focus-visible .keypad-edge { stroke-opacity: 0; }
.keypad-cell.pressed .keypad-highlight,
.keypad-cell.picked .keypad-highlight,
.keypad-cell:focus-visible .keypad-highlight { stroke-opacity: 1; }
.button-container .keypad-cell:focus-visible { background: var(--bg-elevated); }
.button-container button[data-key="QUICK_SAVE"],
.button-container button[data-key="QUICK_LOAD"],
.button-container button[data-key="RAPID_FIRE"] { font-size: min(12px, calc(var(--keypad-cell-height) * 0.5)); }
.button-container button:disabled { opacity: 0.45; cursor: default; }

.checkpoint-status {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  padding: 6px 8px;
  background: color-mix(in srgb, var(--bg-panel) 90%, transparent);
  color: var(--text-main);
  font-size: 12px;
  text-align: center;
  overflow-wrap: anywhere;
  pointer-events: none;
}

.checkpoint-status.error {
  color: var(--danger);
}

/* The status line used to sit in the column between the screen and the keypad,
   which meant a message arriving pushed the keypad down — under the fold on a
   phone, and out from under a thumb already resting on it. It is a popup now:
   fixed, over the screen, taking no layout at all, so nothing below it moves
   whether there is a message or not. */
.status-message {
  display: none;
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: min(88vw, 340px);
  max-height: 70dvh;
  overflow-y: auto;
  overscroll-behavior: contain;
  /* Above the panels: an error is worth reading even when one is open, and it
     is the thing that was just asked for. */
  z-index: 220;
  box-sizing: border-box;
  padding: 16px;
  background: var(--bg-panel);
  color: var(--danger);
  border-radius: 8px;
  box-shadow: 0 8px 28px var(--shadow);
  font-size: 0.9em;
  text-align: center;
  /* An error is often something to copy into a bug report. */
  user-select: text;
  -webkit-user-select: text;
  touch-action: auto;
}

.status-message.visible {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
}

.status-text {
  line-height: 1.5;
  word-break: break-word;
}

.status-close {
  font: inherit;
  background: var(--bg-elevated);
  color: var(--text-main);
  border: none;
  border-radius: 4px;
  padding: 7px 20px;
  cursor: pointer;
}

.status-close:hover {
  background: var(--bg-elevated);
}

/* The page's own confirmation window, in the shape of the message popup above
   because it is the same kind of thing: centred, over everything, and the only
   thing being read while it is up. It sits above the message, since a question
   asked after a message is the one waiting for an answer. */
.confirm-dialog {
  display: none;
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: min(88vw, 340px);
  max-height: 70dvh;
  overflow-y: auto;
  overscroll-behavior: contain;
  z-index: 240;
  box-sizing: border-box;
  padding: 20px 16px 16px;
  background: var(--bg-panel);
  color: var(--text-main);
  border-radius: 8px;
  box-shadow: 0 8px 28px var(--shadow);
  text-align: center;
}

.confirm-dialog.visible {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
}

.confirm-text {
  line-height: 1.6;
  word-break: break-word;
}

.confirm-actions {
  display: flex;
  gap: 10px;
}

.confirm-button {
  font: inherit;
  background: var(--bg-elevated);
  color: var(--text-main);
  border: none;
  border-radius: 4px;
  padding: 9px 22px;
  cursor: pointer;
}

.confirm-button:hover {
  background: var(--bg-elevated);
}

/* The one that goes through is the red one, and it is second: the safe button
   is where a thumb already is, and the colour is the last thing read. */
.confirm-accept {
  background: var(--bg-elevated);
}

.confirm-accept:hover {
  background: var(--bg-elevated);
}

/* A controller moves the focus between the answers with a script, and a
   browser shows no focus a script moved after a click; the dialog says the
   controller moved it, so the answer in focus is shown here. */
[data-pad] .confirm-actions .confirm-button:focus {
  outline: 2px solid var(--accent-gold);
  outline-offset: 2px;
}

/* A message dims the page at every width, unlike the panels below: it is a
   modal everywhere, because it is never something the page is read alongside.
   A question is the same, and more so. */
body:has(.status-message.visible) .modal-backdrop,
body:has(.confirm-dialog.visible) .modal-backdrop {
  display: block;
}

/* Only a modal gets a backdrop; the docked panels of the wide layout are part
   of the page rather than on top of it. */
@media (max-width: 899px) {
  body:has(.settings-panel.visible) .modal-backdrop,
  body:has(.cheat-panel.visible) .modal-backdrop {
    display: block;
  }
}

@media (max-width: 480px) {
  .cheat-list {
    max-height: 120px;
  }
}

/* These live inside a panel; the top bar has no free corner. */
.settings-panel .panel-button,
.keypad-arrange .panel-button {
  font: inherit;
  margin-top: 2px;
  padding: 8px 10px;
  background: var(--bg-elevated);
  color: var(--text-main);
  border: none;
  border-radius: 4px;
  cursor: pointer;
  text-align: center;
}

.settings-panel .panel-button:hover,
.keypad-arrange .panel-button:hover {
  background: var(--bg-elevated);
}

.panel-button.hidden {
  display: none;
}

/* The key list. Hidden until app.js has reason to think there is a keyboard,
   which on a phone is never. */
.key-bindings.hidden {
  display: none;
}

.key-bindings summary {
  cursor: pointer;
  padding: 2px 0;
}

/* The rows are three columns that have to line up down the list rather than
   nineteen independent rows, so the list is the grid and each row disappears
   into it. */
.key-bindings-list {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 4px 8px;
  max-height: 38dvh;
  overflow-y: auto;
  overscroll-behavior: contain;
  margin: 6px 0;
}

.key-binding {
  display: contents;
}

.key-binding-key {
  color: var(--text-muted);
  min-width: 2.5em;
}

.key-binding-code {
  font: inherit;
  padding: 5px 8px;
  background: var(--bg-elevated);
  color: var(--text-main);
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.key-binding-code:hover {
  background: var(--bg-elevated);
}

/* A row waiting for a press is the one thing on screen that is listening, so
   it says so in colour as well as in words. */
.key-binding-code.capturing {
  background: var(--bg-elevated);
  color: var(--text-main);
}

.key-binding-code.unbound {
  color: var(--text-muted);
}

.key-binding-clear {
  font: inherit;
  padding: 4px 6px;
  background: none;
  color: var(--text-muted);
  border: none;
  cursor: pointer;
}

.key-binding-clear:disabled {
  color: var(--border);
  cursor: default;
}

/* A controller's list is two columns: the control, and what it sends. */
.pad-bindings-list {
  grid-template-columns: auto 1fr;
}

.pad-binding-target {
  min-width: 0;
  padding: 3px 4px;
  font: inherit;
  color: inherit;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: 4px;
}

/* The row whose control is held right now, in the colour a row waiting for a
   key uses: it is the answer to "which row is this button". */
.pad-binding.active .key-binding-key {
  color: var(--text-main);
}

.pad-binding.active .pad-binding-target {
  background: var(--bg-elevated);
  border-color: var(--text-muted);
}

/* A settings note says what a setting will and will not do to the game that is
   running. It sits under its own control rather than in a status line, because
   what it is about is that control. */
/* Hidden when there is nothing to say, and this rule is why the page has one
   per element: `.hidden` is a convention rather than a rule of its own, so a
   class carrying it does nothing until somebody writes the pair. Without this
   the note was an empty <p> that still laid out — a flex item with margins,
   collecting the panel's gap at both ends, which is twenty-six pixels of gap
   between the setting above it and the one below. `markup.test.mjs` compares
   the two lists now. */
.settings-note.hidden {
  display: none;
}

.settings-note {
  margin: 2px 0 8px;
  color: var(--danger);
  font-size: 0.85em;
  line-height: 1.4;
}

.key-bindings-hint {
  margin: 6px 0;
  color: var(--text-muted);
  font-size: 0.85em;
  line-height: 1.45;
}

.key-bindings .panel-button {
  width: 100%;
}

.cheat-panel {
  display: none;
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: min(96vw, 460px);
  max-height: 82dvh;
  overflow-y: auto;
  overscroll-behavior: contain;
  z-index: 200;
  padding: 0 12px 12px;
  box-sizing: border-box;
  background: var(--bg-panel);
  color: var(--text-main);
  border-radius: 8px;
  box-shadow: 0 8px 28px var(--shadow);
  font-size: 0.85em;
  user-select: text;
  touch-action: auto;
}

.cheat-panel.visible {
  display: block;
}

.cheat-header {
  margin: 0 -12px 8px;
  padding: 10px 12px;
  background: var(--bg-panel);
  border-bottom: 1px solid var(--bg-elevated);
}

.cheat-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin-bottom: 8px;
}

.cheat-row button {
  font: inherit;
  background: var(--bg-elevated);
  color: var(--text-main);
  border: none;
  border-radius: 4px;
  padding: 6px 10px;
  cursor: pointer;
}

.cheat-row button:hover {
  background: var(--bg-elevated);
}

.cheat-panel input,
.cheat-panel select {
  font: inherit;
  background: var(--bg-panel);
  color: var(--text-main);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 5px 8px;
}

.cheat-panel #cheat-value {
  flex: 1;
  min-width: 120px;
}

.cheat-check {
  display: flex;
  align-items: center;
  gap: 4px;
}

.cheat-count {
  margin-left: auto;
  opacity: 0.8;
}

/* A control for something this platform cannot do is worse than no control:
   it invites a click that can only fail. The panel hides the write-watch rows
   rather than disabling them, so what is on screen is what works here. */
.cheat-section.hidden,
.cheat-row.hidden,
.cheat-list.hidden {
  display: none;
}

.cheat-section {
  margin: 12px 0 6px;
  padding-top: 8px;
  border-top: 1px solid var(--bg-elevated);
  opacity: 0.8;
}

.cheat-list {
  max-height: 180px;
  overflow-y: auto;
  overflow-x: hidden;
}

.cheat-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 3px 0;
}

.cheat-item button {
  font: inherit;
  font-size: 0.9em;
  background: var(--bg-elevated);
  color: var(--text-main);
  border: none;
  border-radius: 3px;
  padding: 3px 8px;
  cursor: pointer;
}

.cheat-item button:hover {
  background: var(--bg-elevated);
}

.cheat-address {
  font-family: monospace;
  color: var(--accent-gold);
}

.cheat-item .cheat-value {
  flex: 1;
  font-family: monospace;
}

.cheat-freeze-value {
  flex: 1;
  min-width: 80px;
}

.cheat-type-tag {
  opacity: 0.6;
}

.cheat-hit {
  font-family: monospace;
  padding: 2px 0;
  white-space: nowrap;
  overflow-x: auto;
}

.cheat-more {
  padding: 4px 0;
  opacity: 0.6;
}

/* The docked layout. A desktop window is mostly empty either side of a 3:4
   phone screen, so the margins are spent on the panels, which are then read
   alongside the game rather than on top of it. One margin is enough for
   settings and cheats; the log needs a second one and waits for it below. */
@media (min-width: 900px) {
  :root {
    /* This layout pads the stage, and that padding is height the canvas and
       the keypad cannot have. */
    --stage-vertical: 16px;
  }

  .stage {
    display: grid;
    grid-template-columns: 480px minmax(0, 380px);
    justify-content: center;
    align-items: start;
    gap: 16px;
    padding: 16px max(16px, var(--safe-right)) 0 max(16px, var(--safe-left));
    box-sizing: border-box;
  }

  .rail-left {
    display: none;
  }

  .rail-right {
    display: flex;
    flex-direction: column;
    gap: 12px;
    position: sticky;
    top: 16px;
    min-width: 0;
    max-height: calc(100dvh - 32px);
  }

  .rail-card {
    display: flex;
    flex-direction: column;
    min-height: 0;
    overflow: hidden;
    background: var(--bg-panel);
    color: var(--text-main);
    border-radius: 8px;
    font-size: 0.85em;
  }

  .rail-card-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 8px 12px;
    border-bottom: 1px solid var(--bg-elevated);
  }

  .rail-card-action {
    font: inherit;
    background: var(--bg-elevated);
    color: var(--text-main);
    border: none;
    border-radius: 4px;
    padding: 4px 10px;
    cursor: pointer;
  }

  .rail-card-action:hover {
    background: var(--bg-elevated);
  }

  .log-card {
    flex: 1;
    min-height: 0;
  }

  /* Fit the 3:4 canvas into the height left after the keypad and stage padding.
     A short desktop window must not push the bottom keypad rows offscreen. */
  .canvas-wrapper {
    width: var(--canvas-width);
  }

  .log-view {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 8px 12px;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 11px;
    line-height: 1.45;
    user-select: text;
    touch-action: auto;
  }

  .log-line {
    padding: 1px 0;
    white-space: pre-wrap;
    word-break: break-word;
    border-bottom: 1px solid color-mix(in srgb, var(--text-main) 5%, transparent);
  }

  /* Docked, not floating: the panels keep the same .visible switch the gear
     and the cheat button already flip, they just occupy the rail when on. */
  .settings-panel,
  .cheat-panel {
    position: static;
    transform: none;
    width: auto;
    max-height: none;
    box-shadow: none;
  }

  .cheat-panel {
    max-height: calc(100dvh - 32px);
  }

  .rail .settings-panel,
  .rail .cheat-panel {
    flex: 0 1 auto;
    min-height: 0;
  }
}

/* Wide enough for a second margin, which the run log takes — in a debug build.
   A release has no run log to show, so it keeps the two-column layout at every
   width and the page stays centred rather than leaving a gap where the log
   would have been. */
@media (min-width: 1180px) {
  body.debug-build .stage {
    grid-template-columns: minmax(240px, 340px) 480px minmax(280px, 380px);
  }

  /* The log takes the height it is given rather than the height it has: a
     scrollback that grew the column would push the page around all run. */
  body.debug-build .rail-left {
    display: flex;
    flex-direction: column;
    gap: 12px;
    position: sticky;
    top: 16px;
    min-width: 0;
    height: calc(100dvh - 32px);
  }
}

/* 전체화면: the keypad put away, the rails with it, and the game screen as
   large as the window allows. It is the same hole — still 3:4, still centred —
   given the whole window instead of what the keypad leaves.

   The width is the largest of three that leaves room by the picture's
   top-right corner: the exit button sits just above it or just beside it,
   outside the picture, so a picture that would reach both the top edge and the
   right edge gives up the button's room on one axis. On any window not close
   to 3:4 that costs nothing, because the margin on the other axis already
   holds the button. */
:root.fullscreen {
  --stage-vertical: 0px;
  --fullscreen-corner: 48px;
  --fullscreen-width: max(0px, calc(100vw - var(--safe-left) - var(--safe-right)));
  --canvas-width: min(
      var(--fullscreen-width),
      calc(var(--usable-height) * 0.75),
      max(calc(var(--fullscreen-width) - 2 * var(--fullscreen-corner)),
          calc((var(--usable-height) - 2 * var(--fullscreen-corner)) * 0.75)));
}

:root.fullscreen .button-container,
:root.fullscreen .rail-left {
  display: none;
}

:root.fullscreen .stage {
  display: block;
  padding: 0 var(--safe-right) 0 var(--safe-left);
}

:root.fullscreen .stage-main {
  justify-content: center;
}

/* No rail at any width, so the panels are the narrow layout's modals again. */
:root.fullscreen .rail-right {
  display: contents;
}

:root.fullscreen .settings-panel,
:root.fullscreen .cheat-panel {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  max-height: 82dvh;
  box-shadow: 0 8px 28px var(--shadow);
}

:root.fullscreen .settings-panel {
  width: min(92vw, 360px);
}

:root.fullscreen .cheat-panel {
  width: min(96vw, 460px);
}

:root.fullscreen body:has(.settings-panel.visible) .modal-backdrop,
:root.fullscreen body:has(.cheat-panel.visible) .modal-backdrop {
  display: block;
}

/* The way back, drawn only in that layout. Quiet, because it sits beside the
   game for as long as the game is played. The corner below is only where it
   starts: app.js moves it against the picture's top-right corner, above it or
   beside it, whichever the window has room for. */
.fullscreen-exit {
  display: none;
}

:root.fullscreen .fullscreen-exit {
  display: flex;
  align-items: center;
  justify-content: center;
  position: fixed;
  top: calc(var(--safe-top) + 6px);
  right: calc(var(--safe-right) + 6px);
  z-index: 120;
  width: 36px;
  height: 36px;
  padding: 0;
  border: none;
  border-radius: 6px;
  background: color-mix(in srgb, var(--text-main) 8%, transparent);
  color: var(--text-muted);
  cursor: pointer;
}

:root.fullscreen .fullscreen-exit:hover {
  background: color-mix(in srgb, var(--text-main) 16%, transparent);
  color: var(--text-main);
}

.fullscreen-exit svg {
  width: 22px;
  height: 22px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

#text-input-dialog {
  width: min(88vw, 400px);
  max-height: 80dvh;
  overflow: auto;
  box-sizing: border-box;
  border: 0;
  border-radius: 8px;
  padding: 20px;
  color: var(--text-main);
  background: var(--bg-panel);
}
#text-input-dialog::backdrop { background: var(--shadow-heavy); }
#text-input-dialog h2 { font-size: 1.1rem; }
#text-input-dialog input, #text-input-dialog textarea {
  box-sizing: border-box;
  width: 100%;
  margin: 12px 0;
  padding: 8px;
  font: inherit;
  font-size: 16px;
  user-select: text;
}
#text-input-dialog textarea { min-height: 6em; }

#text-input-status {
  padding: 8px 12px;
  border-radius: 6px;
  background: var(--bg-elevated);
  font-weight: 600;
}
#text-input-status[data-state="available"] { color: var(--text-main); }
#text-input-status[data-state="unavailable"],
#text-input-status[data-state="error"] { color: var(--danger); }
#text-input-dialog button:disabled { opacity: 0.45; cursor: default; }

/* Long control names start smaller. The label fitter shrinks further when the
   actual text does not fit the assigned cells. */
.button-container button[data-key="RAPID_FIRE"],
.button-container button[data-key="SOFT2"] {
  font-size: 11px;
}

.game-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); gap: 10px; width: 100%; }
.game-card { display: flex; flex-direction: column; text-align: left; gap: 6px; min-width: 0; padding: 10px; border: 1px solid var(--border); border-radius: 10px; background: var(--bg-elevated); color: var(--text-main); cursor: pointer; }
.game-card img { width: 100%; height: 110px; object-fit: contain; border-radius: 5px; }
.game-card span { color: var(--text-muted); font-size: 12px; }
.game-card-play { margin-top: 4px; padding: 6px 8px; border: 0; border-radius: 7px; background: var(--accent); color: var(--text-main); font-size: 13px; font-weight: 600; cursor: pointer; }
.game-card-play:hover { background: var(--accent); }
.game-info-play { margin-top: 16px; width: 100%; padding: 11px; border: 0; border-radius: 9px; background: var(--accent); color: var(--text-main); font-size: 15px; font-weight: 700; cursor: pointer; }
.game-info-play:hover { background: var(--accent); }
.metadata-dialog { box-sizing: border-box; width: min(480px, 94vw); max-height: 88dvh; overflow-y: auto; background: var(--bg-elevated); color: var(--text-main); border: 1px solid var(--border); border-radius: 16px; padding: 24px; }
.metadata-dialog::backdrop { background: var(--shadow-heavy); }
.metadata-dialog label { display: grid; gap: 6px; margin: 12px 0; }
.metadata-dialog input, .metadata-dialog textarea { box-sizing: border-box; width: 100%; font: inherit; color: var(--text-main); background: var(--bg-panel); border: 1px solid var(--border); border-radius: 6px; padding: 9px; }
.metadata-dialog button { font: inherit; padding: 8px 14px; cursor: pointer; }
.metadata-dialog img { max-width: 100%; max-height: 220px; object-fit: contain; }
.metadata-dialog p { line-height: 1.6; white-space: pre-wrap; }
.metadata-actions { display: flex; justify-content: flex-end; gap: 10px; }

/* Library shell is separate from the phone's canvas and control geometry. */

#library { display:none; }
body.library-ready:not(.session-active) { overflow:auto; touch-action:pan-y; font-family: -apple-system,BlinkMacSystemFont,"Apple SD Gothic Neo","Noto Sans KR",sans-serif; }
body.library-ready:not(.session-active) > .stage { display:none; }
body.library-ready:not(.session-active) #library { display:block; min-height:100dvh; }
#library, #library * { box-sizing:border-box; touch-action:pan-y; }
#library button, #game-info button { cursor:pointer; font:inherit; }
.library-header { display:flex; align-items:center; justify-content:space-between; padding:22px 32px; max-width:1440px; margin:auto; gap:16px; }
.library-header h1 { margin:0; color:var(--accent); font-size:25px; letter-spacing:-.8px; }
.header-add, .continue { border:1px solid var(--border); background:var(--bg-elevated); color:var(--accent-gold); border-radius:11px; padding:11px 16px; }
.library-main { max-width:1440px; margin:auto; padding:10px 40px 120px; }
.section-heading { display:flex; align-items:center; justify-content:space-between; margin:20px 0; gap:16px; }
.section-heading h2 { margin:0; font-size:21px; }
.text-action { border:0; background:none; color:var(--text-muted); font-size:12px!important; }
.genre-chips { display:flex; overflow-x:auto; gap:8px; padding-bottom:12px; scrollbar-color:var(--border) transparent; }
.genre-chips button, .status-chips button { white-space:nowrap; border:1px solid var(--border); border-radius:30px; background:var(--bg-elevated); color:var(--text-main); padding:9px 13px; font-size:12px!important; }
.genre-chips .active, .status-chips .active { background:var(--accent); color:var(--bg-panel); border-color:var(--accent); }
.section-note { font-size:12px; color:var(--text-muted); margin:8px 0 20px; }
.recommendations { display:grid; grid-template-columns:repeat(5,minmax(0,1fr)); gap:clamp(6px, 1.5vw, 18px); margin-bottom:34px; }
.library-card { display:flex; flex-direction:column; gap:6px; min-width:0; text-align:left; padding:0; border:0; background:none; color:var(--text-main); }
.recommendations .library-card { width:100%; min-width:0; }
.cover { width:100%; aspect-ratio: .8; overflow:hidden; border:1px solid var(--border); border-radius:10px; background:radial-gradient(ellipse at top right,var(--border),transparent 70%),linear-gradient(145deg,var(--border),var(--bg-elevated)); display:flex; flex-direction:column; align-items:center; justify-content:center; gap:16px; color:var(--text-main); }
.cover img { width:100%; height:100%; object-fit:cover; }
.cover-symbol {font-size:44px; color:var(--accent);}.cover-initial { padding:0 12px; font-size:18px; font-weight:700; text-align:center; }.cover small {font-size:10px;letter-spacing:3px;opacity:.6;}
.library-card strong { width:100%; overflow:hidden; white-space:nowrap; text-overflow:ellipsis; font-size:14px; margin-top:3px; }
.platform { color:var(--text-muted); font-size:11px; line-height:1.6; }
.rating { color:var(--text-muted); font-size:12px; }
.library-grid { display:grid; grid-template-columns:repeat(6,minmax(0,1fr)); gap:28px 16px; }
.search-row input { width:100%; padding:15px 18px; border:1px solid var(--border); background:var(--bg-elevated); border-radius:11px; font:inherit; color:var(--text-main); }
.section-heading select, #library input, .save-accordion select { background:var(--bg-panel); color:var(--text-main); border:1px solid var(--border); border-radius:8px; padding:10px; }
.recent-list { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:12px; }
.recent-row { display:flex; align-items:center; gap:14px; padding:14px; border:1px solid var(--border); border-radius:14px; background:var(--bg-elevated); }
.recent-cover { width:62px; flex-shrink:0; padding:0; background:none; border:0; }.recent-cover .cover {aspect-ratio:.85;border-radius:6px;}.recent-cover .cover-symbol{font-size:20px;}.recent-cover .cover-initial{font-size:10px;padding:2px}.recent-cover .cover small{display:none;}
.recent-text { display:flex; flex-direction:column; gap:3px; flex:1; min-width:0; }.recent-text strong{font-size:14px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}.continue{font-size:12px!important;white-space:nowrap;padding:10px;}
/* Keep the fixed Android navigation opaque: backdrop sampling can repaint
   unrelated scrolled content (including the header) into its compositor layer. */
.bottom-nav { position:fixed; bottom:0; left:0; right:0; background:var(--bg-panel); isolation:isolate; border-top:1px solid var(--bg-elevated); display:flex; z-index:20; padding:10px 0 calc(10px + env(safe-area-inset-bottom)); }
.bottom-nav button { flex:1; border:0; color:var(--text-muted); background:none; display:flex; flex-direction:column; align-items:center; gap:4px; font-size:11px!important; }.bottom-nav .active {color:var(--accent);}.nav-icon {font-size:27px;line-height:30px;}
.empty-state {padding:35px 20px; border:1px dashed var(--border); border-radius:12px; text-align:center; color:var(--text-muted); font-size:14px;}
#game-info { background:var(--bg-elevated); color:var(--text-main); border:1px solid var(--border); border-radius:18px; width:min(520px,94vw); max-height:90dvh; padding:22px; font-family:-apple-system,BlinkMacSystemFont,"Apple SD Gothic Neo",sans-serif; touch-action:pan-y; }
#game-info::backdrop {background:color-mix(in srgb, var(--bg-main) 73%, transparent);backdrop-filter:blur(5px);}
#game-info-content > img {display:none;}
#game-info .detail-play { border:0; border-radius:10px; padding:12px 20px; background:var(--accent); color:var(--bg-elevated); font-weight:700; margin:0; box-shadow:0 5px 20px color-mix(in srgb, var(--accent) 10%, transparent); }
.detail-hero {display:flex;gap:20px;align-items:center;}.detail-hero .cover{width:158px;flex-shrink:0;}.detail-hero h2{font-size:22px;overflow-wrap:anywhere;margin:8px 0;}.eyebrow{font-size:10px;letter-spacing:2px;color:var(--accent);}.detail-meta{display:grid;grid-template-columns:90px 1fr;font-size:13px;gap:12px;padding:20px 0;border-bottom:1px solid var(--border);}.detail-meta dt{color:var(--text-muted);}.detail-meta dd{margin:0;}.description{font-size:13px;line-height:1.8;white-space:pre-wrap;color:var(--text-main);user-select:text;}
.detail-footer{display:grid;grid-template-columns:1fr 1fr 1fr;gap:8px;margin-top:20px;}
.detail-footer button{padding:12px 8px;border-radius:9px;border:1px solid var(--border);background:var(--bg-elevated);color:var(--text-main);font-size:13px;}
.detail-footer button.url{border-color:var(--border);color:var(--accent-gold);}
.detail-footer button.danger{border-color:var(--border);color:var(--danger);}
#game-info h3{font-size:15px;margin-top:25px;}.status-chips{display:flex;flex-wrap:wrap;gap:7px;}.stars{display:flex;gap:10px;}.stars button{font-size:32px!important;border:0;background:none;color:var(--text-muted);padding:0;}.save-accordion{margin-top:22px;border:1px solid var(--border);border-radius:10px;padding:13px;background:var(--bg-elevated);}.save-accordion summary{cursor:pointer;font-size:14px;color:var(--text-main);}.save-accordion select{width:100%;margin-top:15px;}.save-actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px;}.save-actions button{flex:1;padding:10px;background:var(--bg-elevated);color:var(--text-main);border:1px solid var(--border);border-radius:8px;font-size:12px!important;white-space:nowrap;}.save-actions .danger{flex-basis:100%;border-color:var(--border);color:var(--danger);}.save-accordion p{font-size:12px;margin-top:10px;}

@media(max-width:800px){.library-grid{grid-template-columns:repeat(4,minmax(0,1fr));}.library-main{padding:6px 22px 110px;}.library-header{padding:20px 22px;}.recent-list{grid-template-columns:1fr;}}
@media(max-width:480px){.library-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:22px 14px;}.library-header h1{font-size:20px;}.header-add{padding:9px;font-size:11px!important;}.library-main{padding-inline:18px;}}
#game-info > form button { border:1px solid var(--border); background:var(--bg-elevated); color:var(--text-main); border-radius:8px; padding:9px 16px; margin-top:14px; }
#game-info-content { overflow:visible; }

/* The reference settings panel is a single scrolling sheet. */
.settings-panel { font-size: 14px; scrollbar-color: var(--text-muted) var(--bg-elevated); }
.settings-panel.visible { gap: 9px; }
.settings-panel label { min-height: 22px; }
.settings-panel .settings-note { color: var(--text-muted); font-size: 12px; line-height: 1.45; margin: 0 0 12px; white-space: normal; }
.settings-panel select { margin-left: auto; width: 120px; padding: 5px 7px; background: var(--bg-elevated); color: var(--text-main); border: 1px solid var(--border); border-radius: 2px; }
.settings-panel .panel-button { background: var(--bg-elevated); border-radius: 3px; min-height: 37px; margin: 0; }
.settings-actions { display: flex; gap: 8px; }
.settings-actions .panel-button { flex: 1; }
.settings-panel .panel-header { top: -12px; min-height: 42px; flex-shrink: 0; }
.settings-panel .panel-header span { margin-right: auto; }
.help-button { border-radius: 50%; border: 1px solid var(--text-muted); background: var(--bg-elevated); color: var(--text-main); width: 25px; height: 25px; }
.settings-panel details { border-top: 1px solid var(--bg-elevated); padding-top: 8px; }
.settings-panel summary { cursor: pointer; }
.settings-panel input { accent-color: var(--primary); }
#overlay-opacity-value { margin-left: -2px; }
#feedback-dialog { background: var(--bg-elevated); color: var(--text-main); width: min(85vw, 400px); border: 1px solid var(--border); border-radius: 8px; }
#feedback-message { display: block; width: 100%; box-sizing: border-box; margin: 12px 0; }
.canvas-wrapper { overflow: hidden; }
.canvas-wrapper > button, #keypad-grid button[data-key="SETTINGS"], #keypad-grid button[data-key="QUICK_SAVE"], #keypad-grid button[data-key="QUICK_LOAD"] { opacity: var(--overlay-opacity, 1); }
.keypad-restore { display: none; position: absolute; right: 10px; top: 10px; z-index: 5; }
:root.keypad-hidden .button-container { display: none; }
:root.keypad-hidden .keypad-restore { display: block; }
:root.keypad-hidden { --canvas-width: min(100vw, calc((100dvh - 30px) * .75)); --canvas-height: calc(var(--canvas-width) / .75); }
.settings-panel, .settings-panel button, .settings-panel select, #feedback-dialog { font-family: -apple-system, BlinkMacSystemFont, "Apple SD Gothic Neo", "Noto Sans KR", sans-serif; }
.settings-panel > * { flex-shrink: 0; }
.screen-toolbar { position: absolute; top: 8px; left: 10px; right: 10px; display: flex; gap: 6px; z-index: 4; opacity: var(--overlay-opacity, 1); }
.screen-toolbar button { border: 1px solid color-mix(in srgb, var(--text-main) 20%, transparent); border-radius: 18px; color: var(--text-main); background: color-mix(in srgb, var(--bg-panel) 50%, transparent); padding: 6px 10px; cursor: pointer; font: 12px sans-serif; }
.screen-toolbar button:nth-child(3) { margin-left: auto; }

/* Type5 handset. Only the canvas rotates; the shell and physical keys stay put.
   Edited layouts retain the normal grid so every custom hit area is preserved. */
:root.phone-skin { --keypad-width: 100%; }

.phone-skin .stage { display: block; padding: 0; }
.phone-skin .stage-main {
  position: relative;
  width: min(420px, calc(100vw - var(--safe-left) - var(--safe-right)));
  height: min(858px, calc(var(--viewport-height) - var(--safe-top) - var(--safe-bottom) - 16px));
  min-height: 560px;
  margin: calc(8px + var(--safe-top)) auto;
  padding: 26px 3px 17px;
  border: 2px solid var(--bg-main);
  border-radius: 6px;
  background: linear-gradient(105deg, var(--bg-elevated), var(--bg-panel) 12%, var(--bg-elevated) 48%, var(--bg-panel) 91%, var(--bg-elevated));
  box-shadow: inset 0 0 0 2px var(--border), inset 0 0 0 5px var(--bg-panel), 0 15px 45px var(--shadow);
}
.phone-skin .canvas-wrapper {
  flex: 1 1 auto; width: 100%; aspect-ratio: auto; min-height: 180px;
  border: 3px solid var(--bg-main); border-radius: 5px; box-sizing: border-box;
  box-shadow: 0 1px 1px var(--text-muted), inset 0 0 5px var(--canvas-black);
  background: var(--bg-main);
}
.phone-skin .button-container { flex: 0 0 302px; margin-top: 12px; width: 100%; }
.phone-skin #keypad-grid { display: grid; grid-template-columns: repeat(3, 1fr); grid-template-rows: 122px repeat(4, 1fr); gap: 7px; }
.phone-skin #keypad-grid::before {
  content: ""; position: absolute; top: 0; left: 33.5%; width: 33%; height: 122px;
  box-sizing: border-box; border: 2px solid var(--text-muted); border-radius: 46%;
  background: linear-gradient(130deg, var(--text-main), var(--border) 27%, var(--text-main) 49%, var(--border) 80%, var(--text-main));
  box-shadow: 0 2px 3px var(--canvas-black), inset 0 0 0 4px var(--bg-elevated);
}
.phone-skin #keypad-grid .keypad-cell { display: none; }
.phone-skin #keypad-grid .keypad-cell[data-phone-key] {
  display: flex; position: relative; inset: auto !important; width: auto !important; height: auto !important;
  clip-path: none !important; border: 1px solid var(--border); border-radius: 10px;
  align-items: center; justify-content: center; flex-direction: column;
  background: linear-gradient(var(--text-main), var(--text-muted)); color: var(--bg-main);
  box-shadow: inset 0 1px 1px var(--text-main), 0 2px 3px var(--shadow-heavy);
  font-family: Arial, 'Apple SD Gothic Neo', sans-serif; font-size: 23px;
}
.phone-skin #keypad-grid .keypad-label {
  position: static; transform: none; width: auto !important; font-size: inherit !important;
}
.phone-key-hint { display: none; }
.phone-skin #keypad-grid .phone-key-hint { display: block; order: 1; font-size: 10px; line-height: 1.2; margin-top: 2px; white-space: nowrap; pointer-events: none; }
.phone-skin #keypad-grid .keypad-outline { display: none; }
.phone-skin #keypad-grid .keypad-cell[data-phone-key="SOFT1"],
.phone-skin #keypad-grid .keypad-cell[data-phone-key="CLR"],
.phone-skin #keypad-grid .keypad-cell[data-phone-key="MENU"],
.phone-skin #keypad-grid .keypad-cell[data-phone-key="SOFT2"] {
  position: absolute !important; width: 31% !important; height: 43px !important; font-size: 14px;
}
.phone-skin #keypad-grid .keypad-cell[data-phone-key="SOFT1"] { left: 0 !important; top: 4px !important; }
.phone-skin #keypad-grid .keypad-cell[data-phone-key="CLR"] { right: 0 !important; top: 4px !important; }
.phone-skin #keypad-grid .keypad-cell[data-phone-key="MENU"] { left: 0 !important; top: 75px !important; }
.phone-skin #keypad-grid .keypad-cell[data-phone-key="SOFT2"] { right: 0 !important; top: 75px !important; }
.phone-skin #keypad-grid .keypad-cell[data-phone-key="UP"],
.phone-skin #keypad-grid .keypad-cell[data-phone-key="DOWN"],
.phone-skin #keypad-grid .keypad-cell[data-phone-key="LEFT"],
.phone-skin #keypad-grid .keypad-cell[data-phone-key="RIGHT"],
.phone-skin #keypad-grid .keypad-cell[data-phone-key="OK"] {
  position: absolute !important; width: 11% !important; height: 39px !important;
  border: 0; background: transparent; box-shadow: none; font-size: 17px;
}
.phone-skin #keypad-grid .keypad-cell[data-phone-key="UP"] { left: 44.5% !important; top: 0 !important; }
.phone-skin #keypad-grid .keypad-cell[data-phone-key="DOWN"] { left: 44.5% !important; top: 83px !important; }
.phone-skin #keypad-grid .keypad-cell[data-phone-key="LEFT"] { left: 33.5% !important; top: 42px !important; }
.phone-skin #keypad-grid .keypad-cell[data-phone-key="RIGHT"] { left: 55.5% !important; top: 42px !important; }
.phone-skin #keypad-grid .keypad-cell[data-phone-key="OK"] { left: 44.5% !important; top: 42px !important; border: 1px solid var(--border); border-radius: 12px; background: linear-gradient(var(--text-main), var(--text-muted)); font-size: 14px; }
.phone-skin #keypad-grid .keypad-cell[data-phone-key="1"] { grid-area: 2 / 1; }
.phone-skin #keypad-grid .keypad-cell[data-phone-key="2"] { grid-area: 2 / 2; }
.phone-skin #keypad-grid .keypad-cell[data-phone-key="3"] { grid-area: 2 / 3; }
.phone-skin #keypad-grid .keypad-cell[data-phone-key="4"] { grid-area: 3 / 1; }
.phone-skin #keypad-grid .keypad-cell[data-phone-key="5"] { grid-area: 3 / 2; }
.phone-skin #keypad-grid .keypad-cell[data-phone-key="6"] { grid-area: 3 / 3; }
.phone-skin #keypad-grid .keypad-cell[data-phone-key="7"] { grid-area: 4 / 1; }
.phone-skin #keypad-grid .keypad-cell[data-phone-key="8"] { grid-area: 4 / 2; }
.phone-skin #keypad-grid .keypad-cell[data-phone-key="9"] { grid-area: 4 / 3; }
.phone-skin #keypad-grid .keypad-cell[data-phone-key="*"] { grid-area: 5 / 1; }
.phone-skin #keypad-grid .keypad-cell[data-phone-key="0"] { grid-area: 5 / 2; }
.phone-skin #keypad-grid .keypad-cell[data-phone-key="#"] { grid-area: 5 / 3; }
.phone-skin #keypad-grid .keypad-cell.pressed,
.phone-skin #keypad-grid .keypad-cell:focus-visible { background: linear-gradient(var(--text-muted), var(--text-main)); outline: 2px solid var(--accent-gold); outline-offset: -2px; }
.phone-skin .rail-left { display: none; }
@media (max-width: 440px) {
  .phone-skin .stage-main { margin-block: var(--safe-top) 0; height: calc(var(--viewport-height) - var(--safe-top) - var(--safe-bottom)); border-radius: 6px; padding-inline: 12px; }
}
.phone-skin .rail-right { display: contents; }
.phone-skin .settings-panel, .phone-skin .cheat-panel {
  position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: min(92vw, 360px); max-height: 82dvh;
  box-shadow: 0 8px 28px var(--shadow);
}
.phone-skin body:has(.settings-panel.visible) .modal-backdrop,
.phone-skin body:has(.cheat-panel.visible) .modal-backdrop { display: block; }
/* The layout editor owns the screen while arranging physical keys. */
body:has(#keypad-arrange.visible) .screen-toolbar { display: none; }

#session-actions { flex-shrink: 0; }
.settings-actions.hidden { display: none; }
#session-actions .panel-button { flex: 1 1 0; min-width: 0; border: 1px solid var(--border); }
#session-actions .danger { border-color: var(--danger); color: var(--danger); }

/* Fullscreen owns the viewport, including when entered from the handset. */
:root.fullscreen, :root.transparent-keypad {
  --canvas-width: min(calc(100vw - var(--safe-left) - var(--safe-right)), calc(var(--usable-height) * .75));
  --canvas-height: calc(var(--canvas-width) / .75);
}
:root.fullscreen .stage-main, :root.transparent-keypad .stage-main {
  width: 100%; height: var(--viewport-height); min-height: 0; margin: 0;
  padding: var(--safe-top) var(--safe-right) var(--safe-bottom) var(--safe-left);
  border: 0; border-radius: 0; background: var(--bg-main); box-shadow: none;
  align-items: center; justify-content: center;
}
:root.fullscreen .stage, :root.transparent-keypad .stage { padding: 0; display: block; }
:root.fullscreen .stage-main::before, :root.transparent-keypad .stage-main::before { display: none; }
:root.fullscreen .canvas-wrapper, :root.transparent-keypad .canvas-wrapper {
  flex: 0 0 auto; width: var(--canvas-width); height: var(--canvas-height);
  min-height: 0; padding: 0; border: 0; border-radius: 0; box-shadow: none; background: var(--bg-main);
}
:root.transparent-keypad .rail-left { display: none; }
:root.transparent-keypad .button-container {
  display: block; position: fixed; z-index: 10;
  width: min(480px, calc(100vw - var(--safe-left) - var(--safe-right)));
  height: min(284px, calc(var(--usable-height) * .48));
  bottom: var(--safe-bottom); left: 50%; transform: translateX(-50%);
  margin: 0; pointer-events: none; opacity: var(--overlay-opacity, .35);
  --keypad-grid-height: min(284px, calc(var(--usable-height) * .48));
}
:root.transparent-keypad .keypad-cell:not(.empty) { pointer-events: auto; }
:root.transparent-keypad #keypad-grid button { opacity: 1; }
:root.phone-skin:not(.fullscreen) .stage-main {
  width: min(420px, calc(100vw - var(--safe-left) - var(--safe-right)), max(180px, calc((var(--usable-height) - 351px) * .75 + 6px)));
  height: auto; min-height: 0;
}
:root.phone-skin:not(.fullscreen) .canvas-wrapper {
  flex: none; height: auto; aspect-ratio: .75; min-height: 0;
}
:root.fullscreen, :root.transparent-keypad {
  --canvas-width: min(calc(100vw - var(--safe-left) - var(--safe-right)), calc(var(--usable-height) * var(--game-aspect, .75)));
  --canvas-height: calc(var(--canvas-width) / var(--game-aspect, .75));
}
:root.transparent-keypad .button-container {
  width: min(480px, var(--canvas-width));
  bottom: calc(var(--safe-bottom) + (var(--usable-height) - var(--canvas-height)) / 2);
}
.cheat-item { flex-wrap: wrap; }

/* No rail at any width, so the panels are the narrow layout's modals again. */
:root.transparent-keypad .rail-right {
  display: contents;
}

:root.transparent-keypad .settings-panel,
:root.transparent-keypad .cheat-panel {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  max-height: 82dvh;
  box-shadow: 0 8px 28px var(--shadow);
}

:root.transparent-keypad .settings-panel {
  width: min(92vw, 360px);
}

:root.transparent-keypad .cheat-panel {
  width: min(96vw, 460px);
}

:root.transparent-keypad body:has(.settings-panel.visible) .modal-backdrop,
:root.transparent-keypad body:has(.cheat-panel.visible) .modal-backdrop {
  display: block;
}

:root.fullscreen .button-container { display: none; }

.cover { position: relative; }
.cover-tags { position: absolute; top: 6px; right: 6px; display: flex; gap: 4px; z-index: 1; pointer-events: none; }
.cover-tags span { background: color-mix(in srgb, var(--bg-main) 85%, transparent); color: var(--text-main); border: 1px solid color-mix(in srgb, var(--text-main) 25%, transparent); border-radius: 4px; padding: 2px 5px; font-size: 10px; line-height: 1.3; text-shadow: 0 1px 2px var(--canvas-black); }

/* Handset controls occupy the speaker bezel, with reserved fullscreen space. */
.phone-skin .stage-main { padding-top: 0; }
.phone-skin .screen-toolbar {
  position: relative; inset: auto; display: grid; grid-template-columns: auto auto minmax(54px, 1fr) auto auto;
  flex: 0 0 auto; width: 100%; min-width: 0;
  align-items: flex-end; gap: clamp(2px, 1vw, 6px); opacity: 1;
}
.phone-skin .screen-toolbar::before {
  content: ""; position: absolute; left: 50%; bottom: 6px; transform: translateX(-50%);
  width: 54px; height: 8px;
  box-sizing: border-box; border: 2px solid var(--bg-main); border-radius: 4px;
  background: radial-gradient(circle, var(--bg-main) 1px, transparent 1.5px) 0 0 / 5px 4px, var(--border);
  box-shadow: inset 0 2px 4px var(--canvas-black), 0 1px 1px var(--border);
}
.screen-toolbar { opacity: 1; }
/* Keep 28px hit areas while the visible button faces are 20px tall. */
.phone-skin .screen-toolbar button {
  position: relative; isolation: isolate; grid-row: 1; flex-shrink: 0;
  box-sizing: border-box; min-height: 28px; padding: 2px 7px;
  border-color: transparent; background: transparent;
  font-size: 11px; line-height: 16px; white-space: nowrap;
}

.phone-skin .screen-toolbar button:nth-child(1) { grid-column: 1; }
.phone-skin .screen-toolbar button:nth-child(2) { grid-column: 2; }
.phone-skin .screen-toolbar button:nth-child(3) { grid-column: 4; margin-left: 0; }
.phone-skin .screen-toolbar button:nth-child(4) { grid-column: 5; }
:root.fullscreen, :root.transparent-keypad {
 --canvas-width: min(calc(100vw - var(--safe-left) - var(--safe-right)), calc((var(--usable-height) - 56px) * var(--game-aspect, .75)));
 --canvas-height: calc(var(--canvas-width) / var(--game-aspect, .75));
}
:root.fullscreen .stage-main, :root.transparent-keypad .stage-main { padding-top: calc(var(--safe-top) + 56px); box-sizing: border-box; }
:root.fullscreen .screen-toolbar, :root.transparent-keypad .screen-toolbar { position: fixed; top: calc(var(--safe-top) + 8px); left: auto; right: calc(var(--safe-right) + 8px); opacity: 1; }
:root.fullscreen .screen-toolbar button, :root.transparent-keypad .screen-toolbar button { background: var(--bg-elevated); }
.fullscreen-exit { display: none !important; }
:root .settings-panel, :root .cheat-panel {
 position: fixed; top: max(58px, var(--safe-top)); bottom: auto; transform: none;
 max-height: calc(100dvh - 80px); box-sizing: border-box; z-index: 30;
}
:root .settings-panel { left: calc(50% + 224px); right: auto; width: 300px; }
:root .cheat-panel { right: calc(50% + 224px); left: auto; width: 340px; }
:root body:has(.settings-panel.visible) .modal-backdrop,
:root body:has(.cheat-panel.visible) .modal-backdrop { display: none; }
@media (max-width: 1120px) {
 :root .settings-panel, :root .cheat-panel { top: auto; bottom: var(--safe-bottom); left: 6px; right: 6px; width: auto; max-height: min(34dvh, 290px); background: color-mix(in srgb, var(--bg-elevated) 92%, transparent); backdrop-filter: blur(10px); border: 1px solid var(--text-muted); }
 :root .settings-panel.visible, :root .cheat-panel.visible { animation: panel-slide .18s ease-out; }
}
@keyframes panel-slide { from { transform: translateY(100%); } to { transform: translateY(0); } }
:root.transparent-keypad .button-container { opacity: 1; }
:root.transparent-keypad #keypad-grid .keypad-cell[data-phone-key] { color: var(--text-main); background: rgb(from var(--bg-elevated) r g b / var(--overlay-opacity, .35)); text-shadow: 0 1px 3px var(--canvas-black), 0 0 3px var(--canvas-black); }
:root.transparent-keypad #keypad-grid::before { opacity: var(--overlay-opacity, .35); }
:root.transparent-keypad #keypad-grid .keypad-label { color: var(--text-main); opacity: 1; z-index: 1; }
:root.transparent-keypad .keypad-cell .keypad-outline { opacity: var(--overlay-opacity, .35); }
.phone-editor { border-top: 1px solid var(--border); padding-top: 10px; }
.phone-editor p, .cheat-guide { font-size: 12px; line-height: 1.6; }
.phone-editor button { padding: 7px; margin: 3px; }
.phone-editor input[type=number] { width: 65px; }
#phone-selection { display: flex; flex-wrap: wrap; gap: 5px; }
#phone-selection label { display: inline-flex; }
.phone-skin #keypad-grid.phone-unlocked { background-image: linear-gradient(color-mix(in srgb, var(--accent-gold) 33%, transparent) 1px, transparent 1px),linear-gradient(90deg,color-mix(in srgb, var(--accent-gold) 33%, transparent) 1px,transparent 1px); background-size: 2% 2%; touch-action: none; }
.phone-skin #keypad-grid.phone-unlocked button { cursor: grab; touch-action: none; }
.phone-skin #keypad-grid .phone-selected { outline: 2px solid var(--accent); }
.phone-skin #keypad-grid.phone-customized::before { display: none; }
.cheat-guide { padding: 8px; background: var(--bg-elevated); border-radius: 6px; }
.cheat-guide summary { cursor: pointer; }
.cheat-guide ol { padding-left: 20px; }
:root:is(.fullscreen, .transparent-keypad) .settings-panel,
:root:is(.fullscreen, .transparent-keypad) .cheat-panel { top: max(58px, var(--safe-top)); bottom: auto; transform: none; max-height: calc(100dvh - 80px); }
:root:is(.fullscreen, .transparent-keypad) .settings-panel { left: calc(50% + 224px); right: auto; width: 300px; }
:root:is(.fullscreen, .transparent-keypad) .cheat-panel { right: calc(50% + 224px); left: auto; width: 340px; }
@media (min-width: 1121px) {
 :root:is(.fullscreen, .transparent-keypad):has(.settings-panel.visible, .cheat-panel.visible) { --canvas-width: min(420px, calc((var(--usable-height) - 56px) * var(--game-aspect, .75))); }
}
@media (max-width: 1120px) {
 :root:is(.fullscreen, .transparent-keypad) .settings-panel,
 :root:is(.fullscreen, .transparent-keypad) .cheat-panel { top: auto; bottom: var(--safe-bottom); left: 6px; right: 6px; width: auto; max-height: min(34dvh, 290px); }
}
.phone-skin #keypad-grid {
  height: 100%; min-height: 0;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  grid-template-rows: 122px repeat(4, minmax(0, 1fr));
}
.phone-skin #keypad-grid .keypad-cell[data-phone-key] { min-width: 0; min-height: 0; padding: 0; line-height: 1; }
:root.phone-skin:is(.fullscreen, .transparent-keypad) .screen-toolbar { display: flex; width: auto; }
:root.phone-skin:is(.fullscreen, .transparent-keypad) .screen-toolbar::before { display: none; }
:root body:has(.settings-panel.visible, .cheat-panel.visible):not(:has(#confirm-dialog.visible, #keypad-arrange.visible)) .modal-backdrop { display: none !important; }
:root.fullscreen.transparent-keypad .button-container { display: block; }
.phone-skin #keypad-grid.phone-customized .keypad-cell[data-phone-key] { grid-area: auto !important; }
.phone-skin #keypad-grid.phone-customized .keypad-cell:is([data-phone-key="UP"], [data-phone-key="DOWN"], [data-phone-key="LEFT"], [data-phone-key="RIGHT"]) { background: linear-gradient(var(--text-main), var(--text-muted)); border-radius: 10px; }
:root.transparent-keypad #keypad-grid .keypad-cell:not(.empty) { background: rgb(from var(--bg-elevated) r g b / var(--overlay-opacity, .35)) !important; color: var(--text-main); }
:root.transparent-keypad #keypad-grid .keypad-label { left: 50% !important; top: 50% !important; width: auto !important; transform: translate(-50%, -50%); font: bold clamp(12px, 2.5vw, 18px)/1.1 sans-serif !important; color: var(--text-main); text-shadow: 0 1px 3px var(--canvas-black), 0 0 3px var(--canvas-black); opacity: 1; }

#game-info {padding:0;overflow:hidden;}
#game-info-content {display:flex;flex-direction:column;max-height:calc(90dvh - 2px);overflow:hidden;}
.detail-body {overflow-y:auto;min-height:0;padding:22px;scrollbar-gutter:stable;}
.detail-actions {display:grid;grid-template-columns:1fr 1fr;gap:12px;flex-shrink:0;position:relative;z-index:1;padding:14px 22px calc(14px + env(safe-area-inset-bottom));background:var(--bg-elevated);border-top:1px solid var(--border);}
.detail-actions > .save-menu {min-width:0;}
.detail-actions .save-menu summary, #game-info .detail-actions .detail-play {box-sizing:border-box;display:flex;align-items:center;justify-content:center;min-height:48px;height:100%;margin:0;font-size:14px;}
.save-menu {position:relative;}
.save-menu #game-info-status {margin:0;padding:8px;font-size:12px;overflow-wrap:anywhere;}
.save-menu #game-info-status:empty {display:none;}
.save-menu summary {cursor:pointer;list-style:none;border:1px solid var(--border);background:var(--bg-elevated);border-radius:9px;padding:12px 16px;}
.save-menu .save-actions {position:absolute;bottom:calc(100% + 8px);left:0;display:grid;min-width:180px;padding:8px;background:var(--bg-elevated);border:1px solid var(--border);border-radius:10px;box-shadow:0 8px 24px var(--shadow);}
.detail-hero > div:last-child {min-width:0;}
.detail-hero .cover-tags {display:none;}
.detail-hero .detail-tags {display:flex;position:static;gap:5px;}
.metadata-dialog select {padding:9px;background:var(--bg-panel);color:var(--text-main);border:1px solid var(--border);border-radius:6px;font:inherit;}

.cover-genre { position:absolute; top:7px; left:7px; max-width:52%; padding:3px 6px; border-radius:4px; background:color-mix(in srgb, var(--bg-elevated) 92%, transparent); color:var(--text-main); font-size:11px; line-height:1.3; z-index:1; }
#metadata-dialog { width:min(1000px, 94vw); max-width:1000px; }
.cover-comparison { display:grid; grid-template-columns:1fr; gap:16px; }
.cover-comparison figure { margin:0; min-width:0; }
.cover-comparison figcaption { font-weight:600; margin:8px 0; }
#metadata-dialog .cover-comparison img { width:100%; height:440px; max-width:none; max-height:none; object-fit:contain; background:var(--bg-panel); }
.screenshot-controls { margin:12px 0; min-width:0; }
#screenshot-status { overflow-wrap:anywhere; }
@media(max-width:600px) { #metadata-dialog .cover-comparison img { height:280px; } }

#bridge-progress { position:fixed; top:20px; left:50%; transform:translateX(-50%); background:var(--bg-elevated); color:var(--text-main); padding:12px 20px; border-radius:12px; z-index:10000; }
#bridge-progress:not([hidden])::before { content:""; display:inline-block; width:14px; height:14px; margin-right:10px; border:2px solid color-mix(in srgb, var(--text-main) 33%, transparent); border-top-color:var(--accent); border-radius:50%; animation:bridge-spin 1s linear infinite; }
@keyframes bridge-spin { to {transform:rotate(360deg);} }

.cover-genre { white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
#metadata-dialog .cover-compare-control { display:flex; justify-content:flex-start; }
#metadata-dialog .cover-compare-control input { width:auto; margin:0; }

/* Fit the entire classic handset as one proportional unit. Zoom participates
   in layout, so its unscaled box cannot create document overflow. */
:root.phone-skin:not(.transparent-keypad) .stage {
  display: grid; place-items: center;
  height: var(--viewport-height); box-sizing: border-box;
  padding: calc(var(--safe-top) + 8px) var(--safe-right) calc(var(--safe-bottom) + 8px) var(--safe-left);
}
:root.phone-skin:not(.transparent-keypad) .stage-main {
  width: 420px; height: auto; min-height: 0; margin: 0;
  padding: 0 3px 17px; border: 2px solid var(--bg-main); border-radius: 6px;
  background: linear-gradient(105deg, var(--bg-elevated), var(--bg-panel) 12%, var(--bg-elevated) 48%, var(--bg-panel) 91%, var(--bg-elevated));
  box-shadow: inset 0 0 0 2px var(--border), inset 0 0 0 5px var(--bg-panel), 0 15px 45px var(--shadow);
  zoom: var(--phone-fit, 1);
}
:root.phone-skin:not(.transparent-keypad) .canvas-wrapper {
  flex: none; width: 100%; height: auto; aspect-ratio: var(--game-aspect, .75); min-height: 0;
  border: 3px solid var(--bg-main); border-radius: 5px;
}
:root.phone-skin:not(.transparent-keypad) .button-container { display: block; }
:root.phone-skin:not(.transparent-keypad) .screen-toolbar {
  position: relative; inset: auto; display: grid; width: 100%;
}
:root.phone-skin:not(.transparent-keypad) .screen-toolbar::before { display: block; }
:root.phone-skin:not(.transparent-keypad) .screen-toolbar button {
  min-height: calc(28px / var(--phone-fit, 1));
}

/* Session surfaces must never occupy the home screen. */
body:not(.session-active) > .stage { display:none !important; }
.detail-footer { display:flex; justify-content:flex-end; gap:6px; margin:0; padding:12px 18px; flex-shrink:0; }
#game-info .detail-footer button { flex:none; font-size:12px; padding:6px 10px; min-height:30px; }
.connection-status { margin-left:auto; margin-right:12px; font-size:12px; color:var(--text-muted); }
.library-header .header-add { margin-left:0; }

.game-intro { margin: 1rem 0; }
.game-intro > summary { cursor: pointer; padding: .8rem; border: 1px solid var(--border, var(--border)); border-radius: .6rem; }
.game-screenshots { display: flex; gap: .6rem; overflow-x: auto; margin-top: .8rem; }
.game-screenshots button { flex: 0 0 auto; padding: .2rem; }
.game-screenshots img { width: 100px; height: 130px; object-fit: contain; }
.screenshot-viewer { max-width: 95vw; max-height: 95dvh; }
.screenshot-viewer img { display: block; max-width: 85vw; max-height: 80dvh; object-fit: contain; }
.prelaunch { position: fixed; inset: 0; z-index: 100; display: grid; place-content: center; justify-items: center; gap: 1rem; background: var(--bg-panel); color: var(--text-main); }
.prelaunch img { max-width: 75vw; width: 240px; height: 320px; object-fit: contain; }

/* Library navigation, filters and browser preferences. */
.nav-icon svg, .detail-favourite svg { width:22px; height:22px; vertical-align:middle; }
#game-info .detail-footer .detail-favourite { margin-right:auto; display:flex; align-items:center; gap:6px; }
.detail-favourite[aria-pressed="true"] { color:var(--accent)!important; }
.library-filters { display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:12px; margin:16px 0; }
.library-filters label { display:flex; flex-direction:column; gap:6px; font-size:13px; color:var(--text-muted); }
.library-filters select { min-width:0; width:100%; background:var(--bg-panel); color:var(--text-main); border:1px solid var(--border); border-radius:8px; padding:10px; }
.view-toggle { display:flex; gap:6px; }
.view-toggle button, .clear-site-data { border:1px solid var(--border); border-radius:8px; background:var(--bg-panel); color:var(--text-main); padding:9px 12px; }
.view-toggle button { display:flex; gap:6px; align-items:center; }
.view-toggle button.active { border-color:var(--accent); color:var(--accent); }
.library-grid.library-list { grid-template-columns:1fr; gap:10px; }
.library-list .library-card { display:grid; grid-template-columns:64px minmax(0,1fr) auto; align-items:center; padding:10px; border-bottom:1px solid var(--border); }
.library-list .cover { grid-row:1; width:64px; }
.library-list .cover-tags, .library-list .cover-genre { display:none; }
.clear-site-data { display:block; margin-top:28px; color:var(--danger); border-color:var(--border); }
.site-data-status { max-width:1360px; margin:12px auto; padding:12px 20px; color:var(--accent-gold); }
@media(max-width:600px) { .library-filters { grid-template-columns:repeat(2,minmax(0,1fr)); } .library-list .library-card { grid-template-columns:54px minmax(0,1fr); } .library-list .rating { grid-column:2; } #game-info .detail-footer { padding:10px; gap:4px; } #game-info .detail-footer button { padding:6px; } }

.metadata-source-tabs,.metadata-search-bar { display:flex; gap:8px; margin:10px 0; }
.metadata-search-bar input { flex:1; min-width:0; }
.metadata-source-tabs [aria-pressed="true"],.metadata-result[aria-pressed="true"] { outline:2px solid var(--accent,var(--accent)); }
/* Fixed column counts keep the search cards legible at every dialog width. */
.metadata-results { display:grid; grid-template-columns:repeat(5,minmax(0,1fr)); gap:12px; padding:4px; }
#metadata-dialog .metadata-result { display:flex; flex-direction:column; align-items:stretch; gap:4px; min-width:0; padding:8px; text-align:left; color:inherit; background:var(--bg-elevated); border:1px solid var(--border); border-radius:10px; transition:background .15s,border-color .15s; }
.metadata-result:hover { background:var(--bg-elevated)!important; border-color:var(--accent-gold)!important; }
.metadata-result:active { transform:translateY(1px); }
.metadata-result:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
.metadata-result[aria-pressed="true"] { background:var(--bg-elevated)!important; border-color:var(--accent)!important; }
.metadata-result-cover { display:block; aspect-ratio:1; overflow:hidden; border-radius:6px; background:var(--bg-panel); }
#metadata-dialog .metadata-result img { display:block; width:100%; height:100%; max-height:none; object-fit:cover; }
.metadata-result-title { display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden; overflow-wrap:anywhere; line-height:1.35; min-height:2.7em; font-size:14px; font-weight:600; margin:4px 0; }
.metadata-result-meta { display:block; min-height:1.4em; font-size:12px; line-height:1.4; color:var(--text-muted); overflow-wrap:anywhere; }
@media(max-width:1000px) { .metadata-results { grid-template-columns:repeat(3,minmax(0,1fr)); } }
@media(max-width:600px) { #metadata-dialog { padding:14px; } .metadata-results { grid-template-columns:repeat(2,minmax(0,1fr)); gap:8px; } }

.release-year { color:var(--text-muted); }
.library-list .cover { grid-row:1 / span 2; }
.library-list .release-year { grid-column:3; grid-row:1 / span 2; }
.library-list .rating { grid-column:2; grid-row:2; }
@media(max-width:600px) { .library-list .release-year { grid-column:2; grid-row:2; } .library-list .rating { grid-row:3; } .library-list .cover { grid-row:1 / span 3; } }

/* Shared controls and exact crimson theme states. */
button, input, select, textarea { accent-color: var(--primary); }
button { background-color: var(--bg-elevated); color: var(--text-main); border-color: var(--border); }
input:is([type=text], [type=number], [type=search]), textarea, .library-filters select { background-color: var(--bg-elevated); color: var(--text-main); border-color: var(--border); }
a { color: var(--accent); }
.game-start, .game-card-play, .game-info-play, .genre-chips .active, .status-chips .active, #game-info .detail-play,
.view-toggle button.active, button[aria-pressed="true"] { background: var(--primary); color: var(--text-main); border-color: var(--primary); }
.game-start:hover:not(:disabled), .game-card-play:hover, .game-info-play:hover, #game-info .detail-play:hover,
.genre-chips .active:hover, .status-chips .active:hover, button[aria-pressed="true"]:hover { background: var(--primary-hover); }
.game-start:active:not(:disabled), #game-info .detail-play:active { background: var(--danger); }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
canvas { background-color: var(--canvas-black); }
.library-header { background: var(--bg-main); }
.library-header h1 { color: var(--text-main); }
.brand-flame { color: var(--accent); }

.library-card { background: var(--bg-panel); border: 1px solid var(--border); border-radius: 10px; overflow: hidden; transition: border-color .18s, box-shadow .18s; }
.library-card:hover, .library-card:focus-visible { border-color: var(--primary); box-shadow: 0 0 18px var(--card-glow); }
.library-card strong, .library-card .rating, .library-card .release-year { padding-inline: 8px; box-sizing: border-box; }
.rating { color: var(--accent-gold); }
.bottom-nav { border-top-color: var(--border); }
.bottom-nav button { font-size: 12px!important; }
.settings-panel, .cheat-panel, dialog, #feedback-dialog { background: var(--bg-panel); }
.danger, #session-actions .danger, .detail-footer button.danger, .save-actions .danger, .clear-site-data {
  background: var(--danger); color: var(--text-main); border-color: var(--primary);
}
.danger:hover, .clear-site-data:hover { background: color-mix(in srgb, var(--primary) 85%, var(--canvas-black)); }
.phone-skin .stage-main {
  background: linear-gradient(105deg, var(--bg-main), color-mix(in srgb, var(--bg-main) 80%, var(--border)) 12%, var(--bg-main) 48%, var(--bg-panel) 91%, var(--bg-main));
  box-shadow: inset 0 0 0 2px var(--border), inset 0 0 0 5px var(--bg-main), 0 18px 45px var(--fire-shadow);
}
/* Two composited particle layers drift upward without layout or paint loops. */
#boot-buffer::before, #boot-buffer::after, .prelaunch::before, .prelaunch::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(circle at 18% 85%, var(--accent) 0 1px, transparent 2px), radial-gradient(circle at 72% 65%, var(--accent) 0 1px, transparent 2px), radial-gradient(circle at 43% 96%, var(--accent-gold) 0 1px, transparent 2px);
  opacity: .14; animation: ember-rise 9s linear infinite;
}
#boot-buffer::after, .prelaunch::after { animation-delay: -4.5s; background-size: 73% 87%; }
.boot-content, .prelaunch > * { position: relative; z-index: 1; }
@keyframes ember-rise { from { transform: translateY(10%); opacity: 0; } 25% { opacity: .14; } to { transform: translateY(-35%); opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  #boot-buffer::before, #boot-buffer::after, .prelaunch::before, .prelaunch::after { animation: none; }
  .library-card { transition: none; }
}

fieldset { border: 1px solid var(--border); }

.library-main .patch-notes-button { flex-shrink:0; padding:8px 12px; font-size:13px; }
.library-header .connection-status { margin-left:auto; }
.search-row { display:flex; align-items:center; gap:10px; }
.search-row input { flex:1; min-width:0; }
.filter-toggle { display:flex; align-items:center; gap:6px; flex-shrink:0; padding:13px 16px; }
.filter-count { border-radius:99px; min-width:20px; background:var(--accent); color:var(--bg-main); padding:1px 5px; }
.library-filters[hidden] { display:none; }
#patch-notes-dialog { width:min(560px,calc(100vw - 32px)); max-height:80vh; overflow:auto; padding:24px; border:1px solid var(--border); border-radius:16px; background:var(--bg-panel); color:var(--text-main); }
#patch-notes-dialog::backdrop { background:#0009; }
#patch-notes-dialog ol { padding-left:20px; }
#patch-notes-dialog li { margin:18px 0; }
#patch-notes-dialog time { color:var(--text-muted); font-size:12px; }
#patch-notes-dialog li p { margin:6px 0; }
@media(max-width:600px) { .library-header { flex-wrap:wrap; gap:8px; } .library-header h1 { font-size:18px; } }

/* Shared button system. Visual properties are authoritative over the legacy
   component rules; component display, placement and sizing stay local. */
button, .save-menu summary {
  box-sizing: border-box;
  border: 1px solid var(--border) !important;
  border-radius: 8px !important;
  background: var(--bg-elevated) !important;
  color: var(--text-main) !important;
  padding: 8px 14px;
  font-weight: 600 !important;
  text-decoration: none !important;
  box-shadow: none !important;
  transition: background 120ms ease, border-color 120ms ease, color 120ms ease, transform 120ms ease !important;
  cursor: pointer;
}
button:not(.keypad-cell):not(.library-card):not(.game-card):not(.metadata-result) { padding: 8px 14px !important; }
button::before, button::after { content: none !important; display: none !important; }
button:hover:not(:disabled), .save-menu summary:hover { background: var(--bg-panel) !important; border-color: var(--primary) !important; }
button:is(.secondary, .ghost, .patch-notes-button, .panel-close, .cheat-close, .status-close),
.bottom-nav button, .save-menu summary { background: transparent !important; }
button:is(.primary, .game-start, .game-card-play, .game-info-play, .detail-play, .confirm-accept, .active, [aria-pressed="true"]),
button[type="submit"]:not([value="skip"]), #text-input-apply {
  background: var(--primary) !important; border-color: transparent !important; color: #fff !important;
}
button:is(.primary, .game-start, .game-card-play, .game-info-play, .detail-play, .confirm-accept, .active, [aria-pressed="true"]):hover:not(:disabled),
button[type="submit"]:not([value="skip"]):hover:not(:disabled), #text-input-apply:hover:not(:disabled) { background: var(--primary-hover) !important; }
button:active:not(:disabled) { transform: translateY(1px); }
button:is(.danger, .game-remove, .clear-site-data) { background: var(--danger) !important; border-color: transparent !important; color: #fff !important; }
button:is(.danger, .game-remove, .clear-site-data):hover:not(:disabled) { background: color-mix(in srgb, var(--primary) 85%, black) !important; }
button:is(.icon-button, .help-button, .key-binding-clear), .stars button { display: inline-flex; align-items: center; justify-content: center; width: 34px; height: 34px; min-width: 34px; padding: 0 !important; flex-shrink: 0; }
button:focus-visible, .save-menu summary:focus-visible { outline: 2px solid var(--accent) !important; outline-offset: 2px !important; }
button:disabled { opacity: .45; cursor: default; }
/* Hit areas with geometric meaning keep their dimensions and content layout. */
button.keypad-cell { padding: 0; }
button.library-card, button.game-card, button.metadata-result { font-weight: inherit !important; }
button.keypad-cell.pressed { background: var(--primary) !important; color: #fff !important; }

/* Browser-specific game library density preferences. */
.library-game-grid { grid-template-columns:repeat(var(--album-columns,6),minmax(0,1fr)); }
.library-game-grid.library-list { grid-template-columns:repeat(var(--list-columns,1),minmax(0,1fr)); }
.view-count { display:inline-grid; place-items:center; min-width:1.6em; padding:2px 4px; border-radius:5px; background:color-mix(in srgb,currentColor 14%,transparent); font-size:11px; font-variant-numeric:tabular-nums; }
.view-toggle button, .sort-direction { cursor:pointer; box-shadow:0 2px 0 var(--border); transition:background .15s,transform .15s; }
.view-toggle button:hover, .sort-direction:hover { background:var(--bg-elevated); border-color:var(--accent); }
.view-toggle button:active, .sort-direction:active { transform:translateY(2px); box-shadow:none; }
.view-toggle button:focus-visible, .sort-direction:focus-visible { outline:2px solid var(--accent); outline-offset:3px; }
.sort-controls { display:flex; align-items:end; gap:8px; min-width:0; }
.sort-controls label { display:flex; align-items:center; gap:8px; font-size:12px; }
.sort-direction { border:1px solid var(--border); border-radius:8px; padding:10px 14px; background:var(--bg-panel); color:var(--text-main); }
@media(max-width:800px) {
  .library-main { padding-inline:12px; }
  .library-game-grid { grid-template-columns:repeat(var(--album-columns,6),minmax(0,1fr)); column-gap:2px; }
  .library-game-grid .library-card { min-width:0; overflow:hidden; }
  .library-game-grid .cover { min-width:0; }
}
@media(max-width:600px) {
  .sort-controls label { flex-direction:column; align-items:start; gap:4px; }
  .library-game-grid.library-list .library-card { grid-template-columns:40px minmax(0,1fr); gap:4px; padding:6px; }
  .library-game-grid.library-list .cover { width:40px; }
  .library-game-grid .cover-initial { font-size:12px; padding:4px; }
  .library-game-grid .cover-tags { font-size:8px; gap:2px; }
}

/* Custom key geometry may extend into the empty margins for every keypad. */
#keypad-grid.phone-customized, #keypad-grid.phone-unlocked { overflow: visible; }
#keypad-grid.phone-unlocked button { cursor: grab; touch-action: none; }
#keypad-grid.phone-customized button[data-geometry-key] { z-index: 6; }
.client-reload[hidden] { display: none !important; }

#keypad-grid.phone-customized button[data-geometry-key] { grid-area: auto !important; }

/* Touch drawers open expanded; the header toggles the saved sheet state. */
:root .panel-sheet.panel-collapsed { overflow: hidden; }
:root .panel-sheet.panel-collapsed > :not(.panel-header):not(.cheat-header) { display: none !important; }
:root .panel-sheet .panel-header, :root .panel-sheet .cheat-header { position: sticky; top: -12px; min-height: 42px; background: var(--bg-panel); z-index: 2; touch-action: none; user-select: none; }
:root .panel-sheet { overscroll-behavior: contain; overflow-y: auto; animation: none !important; }
.options-section > summary { font-weight: 700; padding: 10px 0; }
.options-section > label { margin: 9px 0; }
.options-section > button { margin: 5px 0; }
.settings-panel [hidden] { display: none !important; }
#keypad-grid button[hidden] { display: none !important; }
.screen-toolbar button:nth-child(3) { margin-left: 0; }
.screen-toolbar button:nth-child(4) { margin-left: auto; }
.phone-skin .screen-toolbar { grid-template-columns: auto auto auto 1fr auto auto auto; }
.phone-skin .screen-toolbar button:nth-child(3) { grid-column: 3; }
.phone-skin .screen-toolbar button:nth-child(4) { grid-column: 5; margin-left: 0; }
.phone-skin .screen-toolbar button:nth-child(5) { grid-column: 6; }
.phone-skin .screen-toolbar button:nth-child(6) { grid-column: 7; }
.settings-panel p, .cheat-panel p { touch-action: pan-y; }

.quick-resume { width:min(360px,90vw); border:1px solid var(--border); border-radius:16px; padding:24px; background:var(--bg-panel); color:var(--text-main); }
.quick-resume::backdrop { background:#0009; }
.quick-resume p { line-height:1.6; }
.quick-resume .quick-actions { display:flex; align-items:center; gap:12px; }
.quick-resume button.quick-yes { flex:2; padding:18px !important; font-size:20px !important; background:var(--primary) !important; color:white !important; border-radius:10px; }
.quick-resume button.quick-yes:hover:not(:disabled) { background:var(--primary-hover) !important; }
.quick-resume .quick-no { flex:1; position:relative; padding:12px; touch-action:none; user-select:none; }

/* One non-interactive notice, clear of navigation and the live keypad. */
.app-toast {
  position: fixed; left: 50%; bottom: var(--toast-bottom, 88px); z-index: 1100;
  transform: translate(-50%, 8px); opacity: 0; pointer-events: none;
  width: max-content; max-width: calc(100vw - 32px); box-sizing: border-box;
  padding: 12px 18px; border: 1px solid var(--accent); border-radius: 10px;
  background: var(--bg-panel, #242424); color: var(--text-main, #fff);
  box-shadow: 0 6px 24px #0006; font-size: 14px; line-height: 1.5;
  overflow-wrap: anywhere; text-align: center;
  transition: opacity 180ms ease, transform 180ms ease;
}
.app-toast.visible { opacity: 1; transform: translate(-50%, 0); }
@media (prefers-reduced-motion: reduce) { .app-toast { transition: none; } }

/* Flat navigation: separators belong to the bar; the selected destination is filled. */
.bottom-nav button {
  position:relative; min-height:44px; border:0!important; box-shadow:none!important;
  border-radius:0; margin:0 6px; padding:6px 4px; min-width:0;
}
.bottom-nav button + button::before {
  content:""; position:absolute; left:-6px; top:8px; bottom:8px; width:1px; background:var(--border); z-index:1; pointer-events:none;
}
.bottom-nav button.active {
  background:var(--primary)!important; color:white!important; border-radius:10px;
}
.confirm-actions .confirm-accept { min-height:44px; flex:2; }
.bottom-nav button + button::before { content:""!important; display:block!important; }
.quick-resume { box-sizing:border-box; max-width:calc(100vw - 24px); }

.quick-points { display: grid; gap: 6px; margin: 12px 0; max-height: 45dvh; overflow-y: auto; }
.quick-point { display: flex; align-items: center; gap: 12px; padding: 7px 10px; border: 1px solid var(--border, #8886); border-radius: 10px; cursor: pointer; min-height: 48px; }
.quick-point:has(input:checked) { border-color: var(--accent, #668fff); background: #668fff18; }
.quick-point img { width: 36px; height: 48px; object-fit: contain; image-rendering: pixelated; }
.quick-point small { display: block; opacity: .65; font-size: 11px; margin-top: 3px; }
.quick-resume button.quick-yes { word-break: keep-all; }

/* Shared compact badges keep the cover's upper corners balanced at every density. */
.cover .cover-tags {
  left:3px; right:3px; top:4px; display:grid;
  grid-template-columns:minmax(0,1fr) auto; grid-template-rows:15px 15px;
  align-items:start; gap:2px 3px;
}
.cover .cover-tags > span {
  box-sizing:border-box; position:static; max-width:100%; min-width:0; margin:0;
  height:15px; padding:0 2px; border:1px solid color-mix(in srgb, var(--text-main) 25%, transparent);
  border-radius:3px; font-size:10px; line-height:13px; white-space:nowrap;
  grid-column:2; justify-self:end;
}
.cover .cover-tags > span:first-child:not(.cover-genre),
.cover .cover-tags > .cover-genre + span { grid-row:1; }
.cover .cover-tags > span:last-child { grid-row:2; }
.cover .cover-tags > .cover-genre {
  grid-column:1; grid-row:1; justify-self:start;
  background:#c62828; color:#fff; text-shadow:none;
}
/* Keep dense album covers tall enough to show their artwork below the badges. */
.library-game-grid:not(.library-list) .cover { min-height:80px; }

/* Dense preferences fit the viewport while retaining the desktop setting. */
@media (max-width:700px) {
  .library-game-grid:not(.library-list) {
    grid-template-columns:repeat(min(var(--album-columns,6),5),minmax(0,1fr));
  }
}
@media (max-width:480px) {
  .library-game-grid:not(.library-list) {
    grid-template-columns:repeat(min(var(--album-columns,6),4),minmax(0,1fr));
  }
}
/* Recent rows must shrink inside the home grid on phones too. */
.recent-list { min-width:0; }
.recent-row { min-width:0; box-sizing:border-box; }
.recent-text .platform { overflow-wrap:anywhere; }

.quick-point { position:relative; overflow:hidden; user-select:none; touch-action:pan-y; }
.quick-point::after { content:""; position:absolute; bottom:0; left:0; height:4px; width:calc(var(--hold,0)*100%); background:var(--accent); }

.quick-resume .quick-heading { display:flex; justify-content:flex-end; }
.quick-resume .quick-close { min-width:44px; min-height:44px; padding:8px 12px; }

.quick-resume { max-height:85dvh; overflow-y:auto; width:min(480px,94vw); padding:16px; }
.quick-points { max-height:none; overflow:visible; }
.quick-point { min-height:108px; gap:10px; }
.quick-point img { width:75px; height:100px; flex-shrink:0; object-fit:contain; }
.quick-point > span { line-height:20px; font-size:14px; }
.quick-point small { line-height:17px; }

/* Detail ratings keep their own palette above the general form button rules. */
#game-info .stars button { color: #85858D !important; background: transparent !important; border: 0 !important; }
#game-info .stars button.selected { color: var(--accent-gold) !important; }
#game-info .stars button:hover:not(:disabled) { background: color-mix(in srgb, var(--accent-gold) 12%, transparent) !important; }
#game-info .stars button:active:not(:disabled) { background: color-mix(in srgb, var(--accent-gold) 22%, transparent) !important; transform: scale(.94); }
#game-info .stars button:focus-visible { outline: 2px solid var(--accent-gold); outline-offset: 2px; }

.game-intro .description p { margin: 0 0 1em; }
.game-intro .description h3 { font: inherit; font-size: 1.25em; font-weight: 700; color: inherit; margin: 1.2em 0 .5em; }

/* Keep game feedback together without the spacing of two detail sections. */
.game-feedback { margin-top: 16px; }
#game-info .game-feedback h3 { margin: 0 0 8px; }
.feedback-controls { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 18px; }
.game-feedback .stars { gap: 6px; }
.game-feedback > .platform { display: block; margin-top: 4px; }
@media (max-width: 600px) {
  .feedback-controls { flex-direction: column; align-items: flex-start; }
}

.account-dialog form { display: grid; gap: 12px; min-width: 240px; }
.account-dialog input { padding: 10px; }
.owner-badge { display: inline-block; color: var(--muted, #aaa); font-size: 11px; }
.more-data-toast { position: fixed; bottom: calc(90px + env(safe-area-inset-bottom)); left: 50%; transform: translateX(-50%); margin: 0; text-align: center; font-size: 12px; border-radius: 8px; background: var(--bg-panel); padding: 8px 14px; z-index: 21; }
.more-data-toast:empty { display: none; }
#client-refresh-dialog { text-align: center; }

.account-dialog { max-width: min(520px, calc(100vw - 32px)); }
.signup-rules { margin: 0; padding-left: 0; list-style: none; font-size: 12px; line-height: 1.65; }
.signup-rules .valid { color: #16803b; }
.signup-rules .invalid { color: #cf3434; }
.account-dialog button:disabled { opacity: .45; cursor: not-allowed; }

/* Fullscreen controls float over the largest safe-area-fitted game picture. */
:root:is(.fullscreen, .transparent-keypad),
:root:is(.fullscreen, .transparent-keypad):has(.settings-panel.visible, .cheat-panel.visible) {
  --canvas-width: min(calc(100vw - var(--safe-left) - var(--safe-right)), calc(var(--usable-height) * var(--game-aspect, .75)));
  --canvas-height: calc(var(--canvas-width) / var(--game-aspect, .75));
}
:root:is(.fullscreen, .transparent-keypad) .stage-main { padding-top: var(--safe-top); zoom: 1; }
:root.fullscreen.transparent-keypad .button-container { display: block; }
.options-section > h3 { font-size: inherit; font-weight: 700; margin: 10px 0; }

/* The transparent fullscreen editor spans the letterbox, not the picture. */
:root.fullscreen.transparent-keypad { --outside-bottom: 0px; --outside-top: 96px;
  --canvas-width: min(calc(100vw - var(--safe-left) - var(--safe-right) - 224px), calc((var(--usable-height) - var(--outside-top)) * var(--game-aspect, .75)));
  --canvas-height: calc(var(--canvas-width) / var(--game-aspect, .75)); }
:root.fullscreen.transparent-keypad .stage-main { padding-top: calc(var(--safe-top) + var(--outside-top)); padding-bottom: calc(var(--safe-bottom) + var(--outside-bottom)); }
:root.fullscreen.transparent-keypad .button-container { position: fixed; inset: var(--safe-top) var(--safe-right) var(--safe-bottom) var(--safe-left); width: auto; height: auto; transform: none; }
:root.fullscreen.transparent-keypad #keypad-grid { position: absolute; inset: 0; width: 100%; height: 100%; padding: 0; margin: 0; }
:root.fullscreen.transparent-keypad #keypad-grid::before { display: none; }
:root.fullscreen.transparent-keypad #keypad-grid .keypad-cell:not(.empty) { min-width: 0; min-height: 0; padding: 0; grid-area: auto !important; }
@media (orientation: portrait) {
 :root.fullscreen.transparent-keypad { --outside-bottom: 180px;
 --canvas-width: min(calc(100vw - var(--safe-left) - var(--safe-right)), calc((var(--usable-height) - var(--outside-top) - var(--outside-bottom)) * var(--game-aspect, .75))); }
}
:root.fullscreen.transparent-keypad #keypad-grid .keypad-cell:not(.empty) { clip-path: none !important; border: 1px solid color-mix(in srgb, var(--text-main) 20%, transparent); border-radius: 7px; }
:root.fullscreen.transparent-keypad #keypad-grid [data-key="RAPID_FIRE"] .keypad-label { font-size: 11px !important; }

.account-dialog .account-mode-link { background: transparent !important; color: inherit; text-decoration: underline !important; border: 0 !important; box-shadow: none; }
.account-spinner { display: inline-block; width: .8em; height: .8em; margin-right: .5em; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: account-spin .8s linear infinite; }
@keyframes account-spin { to { transform: rotate(360deg); } }

.hidden-games { margin-block: 24px; }
.hidden-game-row { display: flex; align-items: center; gap: 16px; padding: 12px 0; border-bottom: 1px solid var(--border, #ddd); }
.hidden-game-row > span { flex: 1; }
.duplicate-filter-row { display: grid; grid-template-columns: auto; align-items: center; justify-content: end; gap: 8px; margin: 0; grid-column: 1 / -1; min-width: 0; }
.duplicate-filter { justify-self: end; display: inline-flex; align-items: center; gap: 8px; padding: 10px 12px; border: 1px solid var(--border); border-radius: 8px; }
.duplicate-filter[aria-pressed="true"] { background: var(--primary); border-color: var(--primary); }
#game-info .detail-footer .detail-favourite { margin-right: 0; }
#game-info .detail-footer .detail-hide { margin-right: auto; }
#game-info .detail-footer { flex-wrap: wrap; }

.duplicate-filter { touch-action: manipulation; -webkit-touch-callout: none; user-select: none; }
.duplicate-rules { position: fixed; z-index: 1000; width: min(420px, calc(100vw - 16px)); box-sizing: border-box; padding: 10px 14px; border: 1px solid #b77936; border-radius: 8px; background: #241e1b; color: #f4e5d6; font-size: 13px; line-height: 1.65; overflow-wrap: anywhere; box-shadow: 0 4px 16px #0005; pointer-events: none; visibility: hidden; opacity: 0; transition: opacity 150ms ease, visibility 150ms; }
.duplicate-rules.is-visible { visibility: visible; opacity: 1; }
.duplicate-rules p { margin: 0; }
.duplicate-rules-priority { color: #ffc56b; }
@media (prefers-reduced-motion: reduce) { .duplicate-rules { transition: none; } }

.metadata-header { display:flex; align-items:center; justify-content:space-between; gap:12px; }
.metadata-header h2 { margin:0; }
.metadata-header button { flex-shrink:0; }

.keypad-label-mode { display: flex; align-items: center; gap: 4px; margin: 6px 0; }
.keypad-label-mode span { margin-right: auto; }
.keypad-label-mode button { padding: 4px 10px; font: inherit; }
.keypad-label-mode button[aria-pressed="true"] { background: var(--text-main); color: var(--bg-main, #171717); }

.hidden-games > summary { display:flex; align-items:center; gap:10px; cursor:pointer; list-style:none; font-weight:600; padding-block:12px; }
.hidden-games > summary::-webkit-details-marker { display:none; }
.hidden-games > summary::before { content:""; width:7px; height:7px; border-right:2px solid currentColor; border-bottom:2px solid currentColor; transform:rotate(-45deg); transition:transform .15s; }
.hidden-games[open] > summary::before { transform:rotate(45deg); }
.more-account-row { display:flex; align-items:center; gap:12px; flex-wrap:wrap; }
.account-name { overflow-wrap:anywhere; }
.more-account-actions { display:flex; align-items:center; gap:12px; margin-top:12px; flex-wrap:wrap; }
.more-account-actions .clear-site-data { margin:0; }

.master-account-badge {
  margin-left:0;
  flex-shrink:0;
  padding:4px 8px;
  border:1px solid #8c4935;
  border-radius:999px;
  background:#281c1b;
  color:#f5bd70;
  font-size:11px;
  font-weight:600;
  line-height:1.4;
  white-space:nowrap;
}

/* brand mark next to the app title */
.library-title { display:inline-flex; align-items:center; gap:9px; }
.brand-mark { width:52px; height:52px; image-rendering:pixelated; opacity:.92;
  filter: drop-shadow(0 0 7px rgba(255,120,68,.28)); border-radius:6px; }
@media(max-width:480px){ .brand-mark { width:44px; height:44px; } }
