/* Self-hosted UI fonts (variable woff2) — no online dependency, works in the
   offline APK. One file per family covers the full weight range. */
@font-face {
  font-family: 'Manrope';
  src: url('fonts/manrope.woff2') format('woff2');
  font-weight: 400 800; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'JetBrains Mono';
  src: url('fonts/jetbrainsmono.woff2') format('woff2');
  font-weight: 400 700; font-style: normal; font-display: swap;
}

:root {
  --font-ui: 'Manrope', system-ui, "Segoe UI", Roboto, sans-serif;
  --font-mono: 'JetBrains Mono', ui-monospace, "SF Mono", Menlo, monospace;
  --bg: #0a1426;
  --bg2: #122544;
  --panel: #122036;
  --accent: #e8b84b;     /* gold */
  --accent2: #54c8e0;    /* teal */
  --crimson: #d6453f;
  --text: #e9eef7;
  --muted: #93a4c2;
  --border: #2a3f63;
  --good: #6ee0a0;
}

* { box-sizing: border-box; }

/* The `hidden` attribute must always win, even over rules like
   `.game-stage { display: flex }` below (otherwise the full-screen game
   overlay covers the launcher from page load). */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  min-height: 100%;
  background: radial-gradient(circle at 50% -10%, #0e1b30, #070d18 60%);
  color: var(--text);
  font-family: var(--font-ui);
}
select option { background: #0c1729; color: var(--text); }

/* ===================== launcher console ===================== */
.console-wrap {
  min-height: 100dvh;
  display: flex; flex-direction: column; align-items: center; gap: 14px;
  padding: 30px 18px 40px;
}
.console {
  width: min(1040px, 100%);
  background: linear-gradient(180deg, #0c1729, #0a1322);
  border: 1px solid #1c2b48;
  border-radius: 14px;
  box-shadow: 0 30px 80px rgba(0,0,0,.5);
  overflow: hidden;
  display: flex; flex-direction: column;
}

.console-top {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 16px 26px; border-bottom: 1px solid rgba(255,255,255,.06);
}
.brand { display: flex; align-items: center; gap: 11px; }
.wordmark { font: 800 21px var(--font-ui); letter-spacing: 3px; color: var(--accent); }
.browser-pill {
  font: 600 10px var(--font-ui); letter-spacing: 1.5px; color: #6f80a0;
  border: 1px solid var(--border); border-radius: 5px; padding: 2px 7px;
}
.tabs-top { display: flex; gap: 5px; }
.tab-top {
  padding: 8px 16px; border: none; border-radius: 9px;
  font: 600 13px var(--font-ui); color: var(--muted); background: transparent; cursor: pointer;
}
.tab-top.active { background: rgba(232,184,75,.14); color: var(--accent); font-weight: 700; }
.sync-pill {
  display: inline-flex; align-items: center; gap: 7px; white-space: nowrap;
  font: 700 12px var(--font-ui); color: var(--good);
  background: rgba(110,224,160,.1); border: 1px solid rgba(110,224,160,.25);
  padding: 7px 12px; border-radius: 20px;
}
.sync-pill .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--good); }
.sync-pill.warn { color: var(--accent); background: rgba(232,184,75,.1); border-color: rgba(232,184,75,.3); }
.sync-pill.warn .dot { background: var(--accent); }

.console-body { padding: 22px 26px 26px; }

/* cards */
.card {
  background: #13223c; border: 1px solid rgba(255,255,255,.07);
  border-radius: 18px; padding: 18px 20px; box-shadow: 0 10px 30px rgba(0,0,0,.3);
}
.card-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 10px; }
.card-title { font: 700 15px var(--font-ui); color: var(--text); }
.card-title.big { font-size: 16px; }
.card-sub { font: 600 12px var(--font-ui); color: #6f80a0; }

/* hero */
.hero-card { padding: 0; overflow: hidden; }
.hero-poster { display: block; width: 100%; border: 0; padding: 0; cursor: pointer; position: relative; height: 278px; background: #05080f; }
.poster-bg { position: absolute; inset: 0; background: radial-gradient(ellipse at 50% 40%, #21466f, #0a1426 74%); }
.poster-scan { position: absolute; inset: 0; background: repeating-linear-gradient(0deg, transparent 0 2px, rgba(0,0,0,.32) 3px, transparent 4px); }
.poster-fg { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 18px; }
.poster-title { font: 800 40px var(--font-ui); letter-spacing: 6px; color: var(--accent); text-shadow: 0 0 28px #e8b84b55; }
.poster-play { width: 64px; height: 64px; border-radius: 50%; background: rgba(232,184,75,.95); display: flex; align-items: center; justify-content: center; color: #14110a; font-size: 24px; padding-left: 4px; box-shadow: 0 8px 28px rgba(232,184,75,.4); }
.hero-foot { padding: 20px 22px; display: flex; align-items: center; justify-content: space-between; gap: 18px; }
.hero-blurb { margin: 0; color: #a7b6d0; font: 400 14px var(--font-ui); line-height: 1.55; max-width: 44ch; }
.hero-blurb a { color: var(--accent2); text-decoration: none; cursor: pointer; }

.play-btn {
  flex: 0 0 auto; padding: 14px 26px;
  background: linear-gradient(180deg, #f0c659, #e0a93c); color: #14110a;
  border: none; border-radius: 12px; font: 800 16px var(--font-ui); cursor: pointer;
  box-shadow: 0 10px 24px rgba(232,184,75,.25);
}
.play-btn:hover:not(:disabled) { filter: brightness(1.04); }
.play-btn:disabled { opacity: .45; cursor: not-allowed; }
.play-btn.inline { padding: 12px 26px; font-size: 14px; min-width: 170px; }

.play-sync-note { margin: 12px 4px 0; font: 500 12.5px var(--font-ui); color: var(--accent2); min-height: 1em; text-align: center; }
.howto-link-m { display: none; margin: 10px 0 0; }
.howto-link-m a { color: var(--accent2); }

/* saves */
.save-size { font: 800 26px var(--font-ui); color: var(--accent); margin-bottom: 14px; }
.save-actions { display: flex; gap: 8px; margin-bottom: 12px; }
.btn-2 { flex: 1; padding: 10px 6px; background: #18304f; color: var(--text); border: 1px solid var(--border); border-radius: 10px; font: 700 12.5px var(--font-ui); cursor: pointer; }
.btn-2:hover:not(:disabled) { filter: brightness(1.15); }
.btn-2:disabled { opacity: .4; cursor: not-allowed; }
.btn-danger { flex: 0 0 auto; padding: 10px 12px; background: #3a1a1f; color: #ff9a9a; border: 1px solid #5a2a30; border-radius: 10px; font: 700 12.5px var(--font-ui); cursor: pointer; }
.btn-danger:disabled { opacity: .4; cursor: not-allowed; }
.muted-note { margin: 8px 0 0; color: #6f80a0; font: 400 12px var(--font-ui); line-height: 1.5; }
.muted-note code { background: #0005; padding: .1em .35em; border-radius: 4px; color: var(--accent2); }
.muted-note strong { color: var(--muted); }

/* switch */
.switch { position: relative; width: 42px; height: 24px; flex: 0 0 auto; cursor: pointer; }
.switch input { position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.switch-knob { position: absolute; inset: 0; border-radius: 20px; background: #3d557d; transition: background .15s; }
.switch-knob::after { content: ""; position: absolute; top: 3px; left: 3px; width: 18px; height: 18px; border-radius: 50%; background: #fff; transition: transform .15s; }
.switch input:checked + .switch-knob { background: var(--good); }
.switch input:checked + .switch-knob::after { transform: translateX(18px); }

/* sync key + devices + link */
.key-row { display: flex; align-items: center; gap: 8px; background: rgba(0,0,0,.3); border: 1px solid #243a5e; border-radius: 10px; padding: 8px 11px; margin-bottom: 12px; }
.key-row code { flex: 1; font: 700 13px var(--font-mono); color: var(--accent2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; letter-spacing: .04em; }
.btn-key { flex: 0 0 auto; min-width: 62px; padding: 6px 11px; border-radius: 8px; font-size: 12px; }
.device-rows { display: flex; flex-direction: column; gap: 7px; margin-bottom: 12px; }
.device-row { display: flex; align-items: center; gap: 9px; font: 600 12.5px var(--font-ui); color: #cdd6e6; }
.device-row .dot { width: 7px; height: 7px; border-radius: 50%; background: #3d557d; }
.device-row .dot.good { background: var(--good); }
.device-row .dim { color: #6f80a0; font-weight: 400; }
.link-row { display: flex; gap: 8px; margin-bottom: 10px; }
.link-row input { flex: 1; min-width: 0; padding: 8px 11px; background: rgba(0,0,0,.3); color: var(--text); border: 1px solid var(--border); border-radius: 10px; font: 600 13px var(--font-mono); text-transform: uppercase; letter-spacing: .06em; }
.btn-dashed { width: 100%; padding: 9px; background: transparent; color: var(--accent2); border: 1px dashed var(--border); border-radius: 10px; font: 700 12.5px var(--font-ui); cursor: pointer; }
.linklike { background: none; border: none; padding: 0; cursor: pointer; color: var(--accent2); text-decoration: underline; font: inherit; }

/* how to play */
.controls-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 13px 40px; margin-top: 6px; }
.ctl { display: flex; align-items: center; gap: 9px; font: 500 13.5px var(--font-ui); color: #a7b6d0; }
.cap { display: inline-flex; align-items: center; justify-content: center; height: 24px; padding: 0 8px; background: rgba(0,0,0,.4); border: 1px solid var(--border); border-bottom-width: 2px; border-radius: 6px; font: 700 12px var(--font-mono); color: var(--accent2); }
.howto-note { margin: 18px 0 0; padding-top: 16px; border-top: 1px solid rgba(255,255,255,.06); color: #8595b3; font: 400 13px var(--font-ui); line-height: 1.6; }
.howto-note strong { color: #cdd6e6; }

/* settings */
.settings-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px 44px; margin-top: 4px; }
.set-row { display: flex; align-items: center; justify-content: space-between; gap: 14px; }
.set-label { font: 600 13.5px var(--font-ui); color: #cdd6e6; }
.seg { display: inline-flex; background: rgba(0,0,0,.3); border: 1px solid var(--border); border-radius: 11px; padding: 3px; }
.seg button { padding: 7px 14px; border: none; border-radius: 8px; font: 600 12.5px var(--font-ui); color: var(--muted); background: transparent; cursor: pointer; white-space: nowrap; }
.seg button.active { background: var(--accent); color: #14110a; font-weight: 700; }
.set-row select { min-width: 210px; padding: 9px 12px; background: rgba(0,0,0,.3); color: var(--text); border: 1px solid var(--border); border-radius: 11px; font: 600 12.5px var(--font-ui); cursor: pointer; }

/* ===================== modals ===================== */
.overlay { position: fixed; inset: 0; z-index: 2000; background: rgba(6,11,22,.72); display: flex; align-items: center; justify-content: center; padding: 20px; }
.modal-box { position: relative; width: 440px; max-width: 100%; background: #13223c; border: 1px solid rgba(255,255,255,.1); border-radius: 22px; box-shadow: 0 30px 90px rgba(0,0,0,.65); padding: 24px 26px; }
.modal-box.wide { width: 600px; }
.modal-box h3 { margin: 0 0 8px; font: 800 21px var(--font-ui); color: var(--text); }
.modal-x { position: absolute; top: 14px; right: 16px; background: none; border: none; color: #6f80a0; font-size: 18px; cursor: pointer; }
.modal-foot { display: flex; justify-content: flex-end; gap: 10px; margin-top: 18px; }
.modal-stack { display: flex; flex-direction: column; gap: 10px; margin-top: 16px; }
.modal-stack .play-btn { width: 100%; }
.btn-ghost { padding: 12px 20px; background: transparent; color: var(--muted); border: 1px solid var(--border); border-radius: 12px; font: 700 14px var(--font-ui); cursor: pointer; }

.conflict-tiles { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin: 18px 0 0; }
.tile { position: relative; text-align: left; padding: 20px 18px; border-radius: 16px; cursor: pointer; border: 2px solid var(--border); background: rgba(0,0,0,.22); display: flex; flex-direction: column; color: var(--text); }
.tile.sel { border-color: var(--accent); background: rgba(232,184,75,.08); }
.tile-badge { position: absolute; top: 14px; right: 14px; width: 20px; height: 20px; border-radius: 50%; border: 2px solid #5d6f8f; }
.tile.sel .tile-badge { border: none; background: var(--accent); }
.tile.sel .tile-badge::after { content: "✓"; color: #14110a; font: 800 12px var(--font-ui); display: flex; align-items: center; justify-content: center; height: 100%; }
.tile-ic { font-size: 24px; margin-bottom: 10px; }
.tile-title { font: 800 16px var(--font-ui); color: var(--text); }
.tile-size { margin-top: 5px; font: 600 13px var(--font-ui); color: var(--accent); }
#tile-local .tile-size { color: #cdd6e6; }
.tile-desc { margin-top: 8px; font: 400 12.5px var(--font-ui); color: var(--muted); line-height: 1.45; }

/* BYO modal bits */
.dropzone { margin-top: 14px; border: 2px dashed var(--border); border-radius: 12px; padding: 18px; text-align: center; cursor: pointer; transition: border-color .15s, background .15s; }
.dropzone:hover, .dropzone:focus, .dropzone.dragover { border-color: var(--accent); background: rgba(232,184,75,.06); outline: none; }
.dz-icon { font-size: 1.8rem; }
.dropzone p { margin: .3rem 0; color: #a7b6d0; font: 400 13px var(--font-ui); }
.dz-hint { font-size: 11.5px !important; color: #6f80a0; }
.dropzone code { background: #0005; padding: .1em .35em; border-radius: 4px; color: var(--accent2); }
.file-status { margin-top: 12px; font: 400 12.5px var(--font-ui); background: rgba(0,0,0,.25); border: 1px solid var(--border); border-radius: 8px; padding: 10px 12px; line-height: 1.5; }
.file-status .ok { color: var(--good); }
.file-status .miss { color: #ff9a9a; }
.runcmd-row { margin-top: 12px; }
.runcmd-row input { flex: 1; min-width: 0; padding: 8px 11px; background: rgba(0,0,0,.3); color: var(--text); border: 1px solid var(--border); border-radius: 10px; font: 600 13px var(--font-mono); }
#byo-modal .play-btn { width: 100%; margin-top: 14px; }

.legal-foot { color: #6f80a0; font: 400 11.5px var(--font-ui); text-align: center; max-width: 620px; line-height: 1.5; }
.legal-foot a { color: var(--accent2); }

/* ===================== responsive tab routing ===================== */
.tabs-bottom { display: none; }
.panel { display: none; }

@media (min-width: 821px) {
  .console[data-tab="play"] #panel-play,
  .console[data-tab="play"] #panel-saves,
  .console[data-tab="play"] #panel-sync { display: block; }
  .console[data-tab="howto"] #panel-howto { display: block; }
  .console[data-tab="settings"] #panel-settings { display: block; }
  .console[data-tab="play"] .console-body {
    display: grid; grid-template-columns: 1.6fr 1fr; grid-auto-rows: min-content; gap: 18px;
  }
  .console[data-tab="play"] #panel-play  { grid-column: 1; grid-row: 1 / span 2; }
  .console[data-tab="play"] #panel-saves { grid-column: 2; grid-row: 1; }
  .console[data-tab="play"] #panel-sync  { grid-column: 2; grid-row: 2; }
}

@media (max-width: 820px) {
  .console-wrap { padding: 0; gap: 0; }
  .console { width: 100%; min-height: 100dvh; border: 0; border-radius: 0; box-shadow: none; }
  .tabs-top, .browser-pill { display: none; }
  .console-top { padding: 14px 16px; }
  .wordmark { font-size: 18px; letter-spacing: 2px; }
  .console-body { flex: 1; overflow: auto; padding: 14px 14px 84px; -webkit-overflow-scrolling: touch; }
  .console[data-tab="play"] #panel-play { display: block; }
  .console[data-tab="saves"] #panel-saves { display: block; }
  .console[data-tab="sync"] #panel-sync { display: block; }
  .console[data-tab="howto"] #panel-howto { display: block; }
  .console[data-tab="settings"] #panel-settings { display: block; }
  .tabs-bottom {
    display: flex; position: sticky; bottom: 0; justify-content: space-around; align-items: center;
    padding: 9px 8px calc(12px + env(safe-area-inset-bottom));
    background: rgba(10,19,34,.97); border-top: 1px solid rgba(255,255,255,.07);
  }
  .tab-b { background: none; border: none; cursor: pointer; display: flex; flex-direction: column; align-items: center; gap: 3px; color: #6f80a0; }
  .tab-b .ic { font-size: 18px; opacity: .5; }
  .tab-b span:last-child { font: 700 10px var(--font-ui); }
  .tab-b.active { color: var(--accent); }
  .tab-b.active .ic { opacity: 1; }
  .hero-poster { height: 172px; }
  .poster-title { font-size: 28px; letter-spacing: 4px; }
  .hero-foot { flex-direction: column; align-items: stretch; padding: 15px 16px; }
  .hero-foot .play-btn { width: 100%; order: -1; }
  .hero-blurb { text-align: center; max-width: none; }
  .howto-link-m { display: block; text-align: center; }
  .settings-grid { grid-template-columns: 1fr; gap: 15px; }
  .pixels-row { display: none; }   /* mobile omits Pixels per the design */
  .set-row { gap: 10px; }
  .set-row select { min-width: 0; max-width: 170px; }
  .seg { width: 100%; }
  .seg button { flex: 1; text-align: center; padding: 8px; }
  .controls-grid { grid-template-columns: 1fr; gap: 11px; }
  .modal-box.wide { width: 100%; }
  .conflict-tiles { grid-template-columns: 1fr; }
}

/* ===================== game stage (preserved verbatim) ===================== */
.game-stage {
  position: fixed;
  inset: 0;
  background: #000;
  z-index: 1000;
  display: flex;
}
.dos-window { flex: 1; width: 100%; height: 100%; }

/* ---- touch controls (mobile split view) ---- */
.touch-controls { display: none; }

/* Suppress native long-press behaviours on every control element so a held
   button is never interrupted by a callout/selection gesture that would cancel the touch. */
.touch-controls, .touch-controls * {
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
  touch-action: none;
}

/* When touch mode is active, stack game over controls. The game pane is sized to the
   game's actual height (a function of width, so no wasted black letterbox on tall
   phones) and the controls take ALL the remaining vertical space. Zoom mode makes the
   game pane a bit taller (96vw) since the cropped game is slightly taller than 4:3. */
.game-stage.touch { flex-direction: column; }
.game-stage.touch .dos-window { flex: 0 0 auto; height: 75vw; min-height: 0; }
.game-stage.touch.zoom .dos-window { height: 96vw; }
.game-stage.touch .touch-controls {
  flex: 1 1 auto;
  min-height: 0;
  position: relative;            /* anchor the menu keys to the corners */
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2vw;
  padding: 2vw 3vw calc(2vw + env(safe-area-inset-bottom));
  background: #081020;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}

/* movement joystick -> arrow keys (walk / jump via up / kneel via down) */
.stick {
  position: relative;
  flex: 0 0 auto;
  margin-left: 4vw;
  width: min(34vw, 40vh);
  height: min(34vw, 40vh);
  border-radius: 50%;
  background: radial-gradient(circle at 50% 50%, #18304f, #0a1426 70%);
  border: 2px solid var(--border);
  touch-action: none;
}
.stick-knob {
  position: absolute;
  left: 50%; top: 50%;
  width: 42%; height: 42%;
  margin-left: -21%; margin-top: -21%;
  border-radius: 50%;
  background: var(--accent2);
  border: 3px solid #ffffff55;
  box-shadow: 0 2px 10px #000a;
  will-change: transform;
}

.menu-keys {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: 3vmin;
}
.mbtn {
  min-width: 14vmin;
  padding: 1.6vmin 0;
  border: 1px solid var(--border);
  background: #18304f;
  color: var(--text);
  border-radius: 10px;
  font-size: 1rem;
  touch-action: none;
}
.mbtn.active { background: var(--accent); color: #14110a; }
.mbtn.kbd-btn { font-size: 1rem; }
.mbtn.kbd-btn.active { background: var(--accent2); color: #06202a; }

/* Off-screen but focusable input — focusing it raises the device soft keyboard.
   Pinned at top:0 (in view) so the browser doesn't scroll the page up to reveal it;
   the keyboard then overlays the bottom controls and the game stays visible up top.
   font-size 16px avoids iOS auto-zoom; transparent so no caret/text shows. */
.kbd-proxy {
  position: fixed;
  top: 0;
  left: 50%;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
  border: 0;
  padding: 0;
  margin: 0;
  font-size: 16px;
  color: transparent;
  background: transparent;
  caret-color: transparent;
  z-index: -1;
}
.mbtn.ff { background: #1f3a5c; color: var(--accent); font-weight: 800; }
.mbtn.ff.active { background: var(--accent); color: #14110a; }

/* ---- top row: number keys (1-9) + Y/N ---- */
.top-keys { display: none; }
.game-stage.touch .top-keys {
  position: absolute;
  top: 0.6vh;                      /* hug the top edge of the controls area */
  left: 0; right: 0;
  display: flex;
  justify-content: center;
  gap: 1vw;
  padding: 0 1.5vw;
  pointer-events: none;            /* container passes through; only buttons capture taps */
}
.nbtn {
  pointer-events: auto;
  flex: 1 1 0;
  min-width: 0;
  max-width: 9vw;
  padding: 0.85vh 0;
  border: 1px solid var(--border);
  background: #18304f;
  color: var(--text);
  border-radius: 8px;
  font-size: 0.72rem;
  font-weight: 700;
  touch-action: none;
}
.nbtn.active { background: var(--accent); color: #14110a; }
.nbtn.yn { background: #2a1f4a; color: var(--accent2); }
.nbtn.zoom-btn { background: #143a2f; color: var(--good); }
.nbtn.zoom-btn.active { background: var(--good); color: #06200f; }

/* Zoom / crop the decorative border: scale the DOS canvas up; its parent (.bg-black
   .overflow-hidden, set by js-dos) clips the overflow. Origin biased toward the lower
   half so the crop eats the top band/sky and keeps the HUD panel at the bottom. */
.game-stage.zoom #dos canvas {
  transform: scale(var(--zoom-scale, 1.42)) !important;
  /* Crop the side columns; the taller game pane (below) gives the scaled canvas room to
     fit vertically. Origin biased slightly low (70%) so any residual overflow on short
     viewports is cropped off the TOP, never the HUD (GOLD/ALMAS) at the bottom. */
  transform-origin: 50% var(--zoom-origin-y, 64%) !important;
}
/* reserve room at the top of the control pad for the (lowered) number row */
.game-stage.touch .touch-controls { padding-top: 4.5vh; }
/* joystick + action buttons sit a bit below center, clear of the number row above */
.game-stage.touch .stick,
.game-stage.touch .actions { transform: translateY(-2vh); }
.mbtn.state { background: #1b4a32; color: var(--good); font-weight: 800; }
.mbtn.state.active { background: var(--good); color: #06200f; }

/* In touch mode, tuck the menu keys (Items / Save / Esc) along the BOTTOM edge,
   away from the joystick/action thumbs so they aren't pressed by accident.
   The container spans the bottom but only the buttons capture taps. */
.game-stage.touch .menu-keys {
  position: absolute;
  left: 0; right: 0;
  bottom: calc(1.5vw + env(safe-area-inset-bottom));
  flex-direction: row;
  justify-content: space-between;
  gap: 0;
  padding: 0 4vw;
  pointer-events: none;
}
.game-stage.touch .menu-keys .mbtn {
  pointer-events: auto;
  min-width: 11vw;
  padding: 1.3vw 2.5vw;
  font-size: 0.74rem;
  opacity: 0.78;
}

/* Bottom-row order. Default = DOSBox:  Esc · ⌨ · Speed · F7 · ⏎  */
.menu-keys .esc      { order: 1; }
.menu-keys .kbd-btn  { order: 2; }
.menu-keys .ff       { order: 3; }
.menu-keys .f7       { order: 4; }
.menu-keys .enter    { order: 5; }
.menu-keys .saveload { order: 2; }   /* (hidden on DOSBox) */
/* DOSBox-X:  Esc · 💾 · ⌨ · F7 · Speed · ⏎  */
.engine-dosboxX .menu-keys .saveload { order: 2; }
.engine-dosboxX .menu-keys .kbd-btn  { order: 3; }
.engine-dosboxX .menu-keys .f7       { order: 4; }
.engine-dosboxX .menu-keys .ff       { order: 5; }
.engine-dosboxX .menu-keys .enter    { order: 6; }

/* Save/Load popup — appears above the bottom row when 💾 is tapped (DOSBox-X). */
.saveload-popup { display: none; }
.game-stage.touch .saveload-popup.open {
  display: flex;
  gap: 4vw;
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  bottom: 12vh;
  z-index: 1100;
  padding: 2.5vw 3.5vw;
  background: #0b1830;
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: 0 6px 24px #000a;
}
.saveload-popup .mbtn {
  pointer-events: auto;
  min-width: 24vw;
  padding: 3vw 0;
  font-size: 1.05rem;
  opacity: 1;
  touch-action: none;
}

.actions {
  flex: 0 0 auto;
  display: grid;
  grid-template-columns: repeat(2, auto);
  gap: 3vw;
  align-items: center;
}
.abtn {
  width: min(18vw, 22vh);
  height: min(18vw, 22vh);
  border-radius: 50%;
  border: 2px solid var(--border);
  font-weight: 800;
  font-size: clamp(0.62rem, 2.4vmin, 1rem);
  color: #14110a;
  touch-action: none;
}
.abtn.sword { background: var(--crimson); color: #fff; grid-column: 1; grid-row: 1; }  /* top-left */
.abtn.magic { background: var(--accent2);                grid-column: 2; grid-row: 1; }  /* top-right */
.abtn.ctrl  { background: var(--accent);  grid-column: 1 / -1; grid-row: 2; justify-self: center; } /* bottom */
.abtn.active { filter: brightness(0.7); transform: scale(0.95); }
.abtn small { display: block; font-size: 0.6em; font-weight: 700; opacity: 0.8; margin-top: 0.1em; }

/* In touch mode, hide the js-dos sidebar (save/keyboard/fullscreen/settings) entirely
   so the game fills the space — saves auto-persist, and SAVE/LOAD/ESC live on our pad. */
.game-stage.touch #dos .sidebar,
.game-stage.touch #dos .sidebar-thin { display: none !important; }
.game-stage.touch #dos .left-12 { left: 0 !important; }
/* js-dos reserves a thin left gutter for the sidebar; since we moved the sidebar to a
   top strip, collapse it so the game canvas isn't pushed right. */
.game-stage.touch #dos .flex-row > .w-4 { display: none !important; }


/* ---- visual filters (CRT / scanlines) -------------------------------------
   WebGL canvas sized to the game canvas, blended over it; chosen in Settings.
   See js/app.js for the dual-mode (overlay / sampling) implementation. */
.crt-canvas {
  display: none;
  position: absolute;
  z-index: 1002;
  pointer-events: none;
  mix-blend-mode: multiply;
}
.crt-canvas.on { display: block; }

/* ---- live in-game sync indicator (ported from keen456) ----------------------
   Tiny always-on save-sync status while playing: a pill bottom-left on desktop,
   a dot at the top-left of the screen on touch. States via data-state: synced/
   checking/uptodate/backedup/conflict/local/offline. `backedup` = we detected
   local changes AND pushed them to the server just now (the payoff: green
   ring-pulse + "Backed up"). */
.sync-ind { display: none; border: 0; background: none; }
#sync-ind-d.show { display: inline-flex; }
.game-stage.touch #sync-ind-d.show { display: none; }        /* touch uses the dot */
.game-stage.touch #sync-ind-m.show { display: inline-flex; } /* dot only in touch */

/* desktop pill: bottom-left of the stage */
#sync-ind-d {
  position: absolute;
  left: 10px;
  bottom: 10px;
  z-index: 1002;
  align-items: center;
  gap: 6px;
  padding: 4px 10px 4px 8px;
  border: 1px solid #ffffff26;
  border-radius: 999px;
  background: rgba(8, 10, 20, 0.62);
  -webkit-backdrop-filter: blur(5px);
  backdrop-filter: blur(5px);
  color: #e7edf3;
  font-weight: 600;
  font-size: 11px;
  line-height: 1;
  letter-spacing: 0.02em;
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
  transition: background 0.2s;
}
#sync-ind-d:hover { background: rgba(8, 10, 20, 0.82); }
.si-label { white-space: nowrap; }

/* mobile dot: top-left corner of the game screen (the top-keys row owns the
   controls area's top edge in this layout, so the dot rides the screen edge) */
#sync-ind-m {
  position: fixed;
  top: calc(6px + env(safe-area-inset-top));
  left: 6px;
  z-index: 1002;
  width: 24px;
  height: 24px;
  padding: 0;
  align-items: center;
  justify-content: center;
  pointer-events: auto;
}

/* the status dot (shared) */
.sync-ind .si-dot {
  position: relative;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  flex: 0 0 auto;
  background: #4fd777;
  color: #4fd777;                 /* currentColor drives the glow + ring */
  box-shadow: 0 0 5px currentColor;
}
#sync-ind-m .si-dot {
  width: 13px;
  height: 13px;
  box-shadow: 0 0 6px currentColor, 0 0 0 3px #0006;
}

/* ---- per-state colours ---- */
.sync-ind[data-state="synced"]   .si-dot,
.sync-ind[data-state="uptodate"] .si-dot,
.sync-ind[data-state="backedup"] .si-dot { background: #4fd777; color: #4fd777; }
.sync-ind[data-state="checking"] .si-dot,
.sync-ind[data-state="local"]    .si-dot,
.sync-ind[data-state="offline"]  .si-dot { background: #f0b849; color: #f0b849; }
.sync-ind[data-state="conflict"] .si-dot { background: #e8626a; color: #e8626a; }

/* ---- animations ---- */
/* checking: gentle pulse while a check/upload is in flight */
.sync-ind[data-state="checking"] .si-dot { animation: si-pulse 0.85s ease-in-out infinite; }
@keyframes si-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } }

/* up-to-date (checked, nothing to send): one quick soft blink, NO ring —
   deliberately distinct from the payoff so "nothing changed" never looks
   like "changes were uploaded". */
.sync-ind[data-state="uptodate"] .si-dot { animation: si-blink 0.5s ease-out 1; }
@keyframes si-blink { 0% { transform: scale(1); } 45% { transform: scale(1.6); } 100% { transform: scale(1); } }

/* backed up (THE payoff): an expanding green ring-pulse (x2) around the dot */
.sync-ind[data-state="backedup"] .si-dot::after {
  content: "";
  position: absolute;
  inset: -3px;
  border-radius: 50%;
  border: 2px solid #4fd777;
  animation: si-ring 0.9s ease-out 2;
}
@keyframes si-ring { 0% { transform: scale(0.7); opacity: 0.85; } 100% { transform: scale(2.5); opacity: 0; } }
