/* OneOneTyping v6 — games hub and game player. */

/* ------------------------------------------------------------------ hub */

.game-grid {
  display: grid;
  /* as many columns as fit, each card 252px or a little more: a wider screen
     gets another card per row (3 on a 1440 laptop, 4 from 1536 to 1080p,
     5 on 2K), never bigger cards */
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 252px), 1fr));
  gap: 20px;
}

.game-card {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-card);
  background: var(--bg-elevated);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
  transition: transform 0.2s var(--ease), box-shadow 0.2s;
}

.game-card:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-md);
}

.game-cover {
  aspect-ratio: 16 / 9;
  overflow: hidden;
  background: var(--bg-sunken);
}

.game-cover svg {
  display: block;
  width: 100%;
  height: 100%;
  transition: transform 0.4s var(--ease);
}

.game-card:hover .game-cover svg {
  transform: scale(1.04);
}

.game-body {
  display: flex;
  flex-direction: column;
  gap: 10px;
  flex: 1 1 auto;
  padding: 16px 18px 18px;
}

.game-body h3 {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 18px;
}

.game-body p {
  color: var(--text-muted);
  font-size: 13.5px;
  line-height: 1.6;
}

.game-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: auto;
  padding-top: 6px;
}

.game-best {
  display: flex;
  flex-direction: column;
  color: var(--text-dim);
  font-size: 12px;
}

.game-best b {
  color: var(--text-strong);
  font-size: 18px;
  font-variant-numeric: tabular-nums;
}

.game-notes {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
  margin-top: 28px;
}

.game-note {
  display: flex;
  gap: 12px;
  padding: 16px;
  border: 1px solid var(--line-soft);
  border-radius: 14px;
  background: var(--bg-elevated);
}

.game-note svg {
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
  color: var(--accent);
}

.game-note b {
  display: block;
  margin-bottom: 3px;
  color: var(--text-strong);
  font-size: 14px;
}

.game-note span {
  color: var(--text-muted);
  font-size: 13px;
  line-height: 1.55;
}

@media (max-width: 960px) {
  .game-grid,
  .game-notes {
    grid-template-columns: 1fr;
  }
}

/* --------------------------------------------------------------- player */

.game-page {
  min-height: 100vh;
  background: var(--bg);
}

/* a computer: the game fills the window exactly and nothing scrolls (game.js adds .is-game) */
html.is-game,
html.is-game body {
  height: 100%;
  overflow: hidden;
  overscroll-behavior: none;
}

.game-bar {
  position: sticky;
  top: 0;
  z-index: 20;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center;
  gap: 16px;
  height: 64px;
  padding: 0 20px;
  border-bottom: 1px solid var(--line-soft);
  background: var(--bg-elevated);
}

.game-bar-left {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
}

.game-back {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border-radius: 10px;
  color: var(--text-muted);
}

.game-back:hover {
  background: var(--bg-sunken);
  color: var(--text-strong);
}

.game-back svg {
  width: 20px;
  height: 20px;
}

.game-title b {
  display: block;
  color: var(--text-strong);
  font-size: 15px;
}

.game-title {
  min-width: 0;
}

.game-title span {
  display: block;
  overflow: hidden;
  color: var(--text-dim);
  font-size: 12px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* tablets: the canvas already shows wave / sun, so the bar keeps only score and lives */
@media (max-width: 1100px) {
  .game-hud-label {
    display: none;
  }
}

.game-hud {
  display: flex;
  align-items: center;
  gap: 18px;
  color: var(--text-muted);
  font-size: 13px;
  white-space: nowrap;
}

.game-hud b {
  color: var(--text-strong);
  font-size: 18px;
  font-variant-numeric: tabular-nums;
}

.game-lives {
  display: inline-flex;
  gap: 3px;
  color: var(--red);
}

.game-lives svg {
  width: 17px;
  height: 17px;
}

.game-lives .is-lost {
  color: var(--line);
}

.game-tools {
  display: flex;
  justify-content: flex-end;
  gap: 6px;
}

.game-tools button {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border: 0;
  border-radius: 10px;
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
}

.game-tools button:hover,
.game-tools button[aria-pressed='true'] {
  background: var(--accent-tint);
  color: var(--accent-ink);
}

.game-tools svg {
  width: 19px;
  height: 19px;
}

.game-progress {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 3px;
}

.game-progress i {
  display: block;
  height: 100%;
  width: 0;
  background: var(--green);
  transition: width 0.25s;
}

.game-main {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: calc(100vh - 64px);
  min-height: calc(100dvh - 64px);
  padding: 16px 20px;
}

/* The play area takes the room the window gives it — as wide as fits, never
   taller than the screen below the bar — and sits in the middle of it. */
.game-stage {
  position: relative;
  width: 100%;
  max-width: 1880px;
  /* Room for the start/result card even when the play area is short (the
     race track is 250 units tall; its result card was clipped). */
  min-height: min(640px, calc(100vh - 110px));
}

.game-canvas-box {
  position: relative;
  width: 100%;
  margin: 0 auto;
  border-radius: 18px;
  overflow: hidden;
  background: var(--bg-sunken);
  box-shadow: var(--shadow-md);
}

.game-canvas-box canvas {
  display: block;
}

.game-canvas-box.is-shake {
  animation: game-shake 0.35s;
}

@keyframes game-shake {
  20% { transform: translateX(-7px); }
  40% { transform: translateX(6px); }
  60% { transform: translateX(-4px); }
  80% { transform: translateX(2px); }
}

.game-banner {
  position: absolute;
  left: 50%;
  bottom: 5%;
  transform: translateX(-50%);
  pointer-events: none;
  white-space: nowrap;
}

.game-banner.is-top {
  top: 12%;
  bottom: auto;
}

.game-banner .gb-pill {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 7px 18px 7px 8px;
  border-radius: 999px;
  background: rgba(16, 20, 34, 0.72);
  color: #fff;
  font-size: 17px;
  font-weight: var(--fw-bold);
  box-shadow: 0 8px 22px -10px rgba(0, 0, 0, 0.6);
  backdrop-filter: blur(4px);
  animation: gb-breathe 1.6s ease-in-out infinite;
}

.game-banner .gb-pill:not(:has(kbd)) { padding-left: 18px; }

.game-banner kbd {
  display: inline-block;
  min-width: 58px;
  padding: 5px 12px;
  border-radius: 9px;
  background: #fff7e0;
  color: #3a2a1a;
  font: inherit;
  font-size: 14px;
  text-align: center;
  box-shadow: 0 3px 0 rgba(0, 0, 0, 0.35);
}

@keyframes gb-breathe { 50% { transform: translateY(-2px); } }

@media (prefers-reduced-motion: reduce) { .game-banner .gb-pill { animation: none; } }

.game-banner:empty {
  display: none;
}

.game-extra:empty {
  display: none;
}

/* Start, pause and result cards float over the stage. */
.game-overlay {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  padding: 20px;
  border-radius: 18px;
  background: rgba(16, 17, 19, 0.38);
  backdrop-filter: blur(3px);
}

.game-overlay[hidden] {
  display: none;
}

.game-card-panel {
  width: min(520px, 100%);
  max-height: 100%;
  /* a last resort: the start card is laid out to fit (.gp-groups) */
  overflow: auto;
  padding: 26px 28px;
  border-radius: 20px;
  background: var(--bg-elevated);
  box-shadow: var(--shadow-lg);
  text-align: center;
}

.game-card-panel h2 {
  font-size: 24px;
}

.game-card-panel .gp-howto {
  margin: 10px auto 0;
  max-width: 400px;
  color: var(--text-muted);
  font-size: 14px;
  line-height: 1.65;
}

.gp-group {
  margin-top: 18px;
  text-align: left;
}

/* The start card: the choices in columns, as many as the card is wide (two or
   three), so a game with seven groups of choices is a short card, not a long
   scroll. The card widens to hold them. */
.game-card-panel:has(.gp-groups) { width: min(1080px, 100%); }
.game-card-panel:has(.gp-groups) .gp-howto { max-width: 720px; }
/* flowing columns: a tall group and a short one stack without leaving holes,
   each column 260px and up (three across from an 880px card) */
.gp-groups {
  columns: 3 260px;
  column-gap: 24px;
  margin-top: 18px;
}
.gp-groups > * { break-inside: avoid; }
/* space below each group, none above: the three columns start level */
.gp-groups > .gp-group { margin: 0 0 16px; }
/* short windows: less air between the parts */
@media (max-height: 780px) {
  /* the start card may use the whole window under the bar, not just the stage */
  .game-overlay:has(.gp-groups) { position: fixed; inset: 64px 0 0; z-index: 15; padding: 10px; border-radius: 0; }
  .game-card-panel:has(.gp-groups) { padding: 16px 24px 14px; }
  .game-card-panel:has(.gp-groups) h2 { font-size: 21px; }
  /* the how-to folds to two lines; a click opens it (game.js) */
  .game-card-panel:has(.gp-groups) .gp-howto { display: -webkit-box; margin-top: 6px; overflow: hidden; font-size: 13px; line-height: 1.55; -webkit-box-orient: vertical; -webkit-line-clamp: 2; cursor: pointer; }
  .game-card-panel:has(.gp-groups) .gp-howto.is-open { display: block; cursor: default; }
  .gp-groups { margin-top: 12px; }
  .gp-groups > .gp-group { margin-bottom: 10px; }
  .gp-groups .gp-group > span { margin-bottom: 5px; }
  .game-card-panel:has(.gp-groups) .gp-actions { margin-top: 6px; }
  .game-card-panel:has(.gp-groups) .gp-hint { margin-top: 8px; }
}
@media (max-height: 640px) {
  .game-card-panel:has(.gp-groups) .gp-hint { display: none; }
  .gp-groups .gp-options button { padding: 6px 10px; }
  .gp-groups > .gp-group { margin-bottom: 8px; }
}

.gp-group > span {
  display: block;
  margin-bottom: 8px;
  color: var(--text-dim);
  font-size: 12px;
  font-weight: var(--fw-semibold);
}

.gp-options {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.gp-options button {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1px;
  padding: 8px 12px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--bg-elevated);
  color: var(--text-strong);
  font: inherit;
  font-size: 13.5px;
  font-weight: var(--fw-semibold);
  cursor: pointer;
  text-align: left;
}

.gp-options button small {
  color: var(--text-dim);
  font-size: 11px;
  font-weight: var(--fw-medium);
}

.gp-options button[aria-pressed='true'] {
  border-color: var(--accent);
  background: var(--accent-tint);
  color: var(--accent-ink);
}

.gp-options.is-compact {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 6px;
}

.gp-options.is-compact button {
  padding: 6px 9px;
  border-radius: 10px;
  font-size: 13px;
}

.gp-options.is-compact button small {
  max-width: 100%;
  overflow: hidden;
  font-size: 10.5px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.gp-options button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.gp-actions {
  position: sticky;
  bottom: -26px;
  z-index: 1;
  padding: 12px 0 12px;
  /* pinned to the card's bottom while the choices scroll under it: solid, with a soft edge on top */
  background: var(--bg-elevated);
  box-shadow: 0 -10px 14px -8px var(--bg-elevated), 0 -1px 0 var(--line-soft);
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 12px;
}

.gp-hint {
  margin-top: 10px;
  color: var(--text-dim);
  font-size: 12px;
}

.gp-hint kbd,
.gp-howto kbd {
  display: inline-block;
  padding: 0 6px;
  border: 1px solid var(--line);
  border-bottom-width: 2px;
  border-radius: 5px;
  font-family: var(--font-mono);
  font-size: 11px;
}

.gp-score {
  margin-top: 12px;
  color: var(--text-strong);
  font-size: 56px;
  font-weight: var(--fw-bold);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

.gp-score small {
  display: block;
  margin-top: 6px;
  color: var(--text-dim);
  font-size: 13px;
  font-weight: var(--fw-medium);
}

.gp-newbest {
  display: inline-block;
  margin-top: 10px;
  padding: 3px 12px;
  border-radius: 999px;
  background: var(--gold-soft);
  color: var(--gold-ink);
  font-size: 12.5px;
  font-weight: var(--fw-bold);
}

.gp-stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  margin-top: 18px;
  border-top: 1px solid var(--line-soft);
  border-bottom: 1px solid var(--line-soft);
}

.gp-stats div {
  padding: 12px 6px;
}

.gp-stats div + div {
  border-left: 1px solid var(--line-soft);
}

.gp-stats b {
  display: block;
  color: var(--text-strong);
  font-size: 18px;
  font-variant-numeric: tabular-nums;
}

.gp-stats span {
  color: var(--text-dim);
  font-size: 11.5px;
}

.gp-lines {
  margin-top: 14px;
  text-align: left;
}

.gp-lines div {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 7px 2px;
  border-bottom: 1px dashed var(--line-soft);
  color: var(--text-muted);
  font-size: 13px;
}

.gp-lines b {
  color: var(--text-strong);
  font-weight: var(--fw-semibold);
  text-align: right;
}

.game-mobile-note {
  display: none;
  margin-top: 12px;
  color: var(--text-dim);
  font-size: 12.5px;
}

@media (hover: none) and (pointer: coarse) {
  .game-mobile-note {
    display: block;
  }
}

@media (max-width: 720px) {
  .game-bar {
    grid-template-columns: minmax(0, 1fr) auto;
    padding: 0 12px;
  }
  .game-title span,
  .game-hud-label {
    display: none;
  }
  .game-tools {
    display: none;
  }
  .game-main {
    padding: 14px 10px 30px;
  }
  .game-banner .gb-pill {
    font-size: 14px;
  }
}

/* A small ribbon on a game's card (manifest badge: 新 / 更新). */
.game-card { position: relative; }
.game-ribbon { position: absolute; top: 12px; right: 12px; z-index: 2; padding: 3px 10px; border-radius: 999px; background: #ff5a7a; color: #fff; font-size: 12px; font-weight: 800; letter-spacing: 0.04em; box-shadow: 0 4px 10px -4px rgba(255, 60, 110, 0.6); }

/* 全屏: the stage alone fills the screen, the canvas as large as fits, centred */
.game-stage:fullscreen {
  display: flex;
  align-items: center;
  justify-content: center;
  max-width: none;
  width: 100vw;
  height: 100vh;
  min-height: 0;
  padding: 0;
  background: #0d0c0a;
}
.game-stage:fullscreen .game-canvas-box {
  max-width: calc(100vh * var(--game-ratio, 1.7857)) !important;
  width: 100%;
  border-radius: 0;
}
.game-stage:fullscreen .game-extra { display: none; }

/* 本局单词: the words typed this round, with their meanings (单词防线1918) */
.gp-vocab { margin: 12px 0 4px; text-align: left; }
.gp-vocab summary { cursor: pointer; color: var(--text-strong); font-weight: var(--fw-bold); font-size: 14px; }
.gp-vocab summary small { color: var(--text-dim); font-weight: var(--fw-medium); margin-left: 4px; }
.gp-vocab ul { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 4px 14px; max-height: 190px; overflow: auto; margin: 8px 0 0; padding: 0; list-style: none; }
.gp-vocab li { display: flex; gap: 8px; align-items: baseline; min-width: 0; font-size: 13px; }
.gp-vocab li b { color: var(--text-strong); font-family: var(--font-mono); }
.gp-vocab li span { color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* 键盘打僵尸 · 用输入法打汉字: the learner's own IME types into this box over the top bar */
.game-canvas-box .zb-ime {
  position: absolute;
  left: 65.4%;
  top: 2%;
  width: 33.8%;
  height: 8%;
  box-sizing: border-box;
  padding: 0 12px;
  border: 2px solid rgba(255, 211, 90, 0.75);
  border-radius: 10px;
  background: rgba(20, 16, 30, 0.72);
  color: #fff;
  font: 600 clamp(12px, 1.6vw, 18px)/1 "Noto Sans SC", "PingFang SC", system-ui, sans-serif;
  outline: none;
  text-align: center;
}
.game-canvas-box .zb-ime::placeholder { color: rgba(255, 255, 255, 0.6); }
.game-canvas-box .zb-ime:focus { border-color: #ffd35a; box-shadow: 0 0 0 3px rgba(255, 211, 90, 0.25); }

/* trophies earned this round, on the result card */
.gp-trophies { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 8px; margin: 10px 0 2px; }
.gp-trophy { display: inline-flex; align-items: center; gap: 6px; padding: 4px 12px 4px 4px; border: 1px solid var(--line-soft); border-radius: 9999px; background: var(--bg-soft); font-size: 13px; }
.gp-trophy .tp-cup { width: 26px; height: 26px; }
.gp-trophy b { color: var(--text-strong); }
.gp-trophy small { color: var(--text-dim); font-size: 11px; }
.gp-trophies a { font-size: 12.5px; font-weight: var(--fw-semibold); }

/* 手机、平板 */
.is-touch .game-mobile-note { display: none; }
.is-kb-open .game-notes, .is-kb-open .footer { display: none !important; }
.is-kb-open .game-main { padding-top: 4px; }
.is-touch .gp-hint kbd { display: none; }
/* a portrait iPad has room below the play area: let the start card use it instead of scrolling inside the canvas */
@media (orientation: portrait) {
  .is-touch .game-stage { min-height: min(1020px, calc(var(--vvh, 100vh) - 110px)); }
  .is-touch .game-main { align-items: flex-start; }
}
.is-kb-open .game-stage { min-height: 0; }

/* the ribbon kinds (manifest.js / core.js ribbonFor) */
.game-ribbon.is-update { background: #2f8be0; box-shadow: 0 4px 10px -4px rgba(47, 139, 224, .6); }
.game-ribbon.is-beta { background: #8a64e0; box-shadow: 0 4px 10px -4px rgba(138, 100, 224, .6); }
.game-ribbon.is-soon { background: #7a8599; box-shadow: none; }
.game-card.is-soon { opacity: .72; cursor: default; }
.game-card.is-soon .btn { pointer-events: none; opacity: .6; }
.game-news { display: flex; align-items: flex-start; gap: 6px; margin: 0 0 6px; padding: 6px 10px; border-radius: 10px; background: #eaf4ff; color: #1f5f9e; font-size: 12.5px; font-weight: var(--fw-semibold); }
.game-news svg { width: 14px; height: 14px; flex: 0 0 auto; margin-top: 2px; }
[data-theme="dark"] .game-news { background: rgba(47, 139, 224, .14); color: #9ccbf5; }

/* start card: member chapters / maps / modes (docs/ACCESS-PLAN.md) */
.gp-options button.is-member { display: inline-flex; align-items: center; gap: 4px; }
.gp-options button.is-member svg { width: 13px; height: 13px; color: #d49a18; flex: none; }
.gp-options button.is-member small { color: #9a6a0c; }
.gp-member { display: flex; align-items: center; gap: 6px; margin: 4px 0 10px; font-size: 12.5px; color: var(--text-muted); }
.gp-member svg { width: 14px; height: 14px; color: #d49a18; flex: none; }
.gp-member a { color: var(--accent-ink); font-weight: var(--fw-bold); }

/* 背景音乐 off: the note crossed out */
#musicBtn.is-off { opacity: 0.45; position: relative; }
#musicBtn.is-off::after { content: ''; position: absolute; left: 25%; right: 25%; top: 50%; height: 2px; background: currentColor; transform: rotate(-35deg); }

/* 存档: 继续上次 on the start card, and the note on the pause card */
.gp-save { display: flex; align-items: center; gap: 12px; margin: 4px 0 14px; padding: 10px 12px; border: 1.5px solid color-mix(in srgb, var(--gold, #f2b62c) 60%, transparent);
  border-radius: 14px; background: color-mix(in srgb, var(--gold, #f2b62c) 10%, var(--bg-elevated, #fff)); text-align: left; }
.gp-save > svg { flex: none; width: 22px; height: 22px; color: #b07a10; }
.gp-save > span { flex: 1; display: flex; flex-direction: column; min-width: 0; }
.gp-save > span b { font-size: 15px; }
.gp-save > span small { color: var(--text-dim); font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gp-saved { display: flex; align-items: center; justify-content: center; gap: 6px; margin: 0 0 8px; color: #2f8a4f; font-size: 13px; font-weight: 600; }
.gp-saved svg { width: 16px; height: 16px; }

/* 经验 on the end card: one line, the gain first */
.gp-xp { margin: 12px 0 0; color: var(--text-dim); font-size: 12.5px; line-height: 1.55; }
.gp-xp b { color: var(--gold-ink); }
html[data-theme='dark'] .gp-xp b { color: var(--gold-400); }

/* 课程游戏关：开始卡和结算卡都只说这一关的事（game.js lessonCard / lessonEndCard） */
.gp-lesson { max-width: 440px; text-align: center; }
.gp-lesson-eyebrow { margin: 0 0 4px; color: var(--accent-ink, #1c64c8); font-size: 12px; font-weight: 800; letter-spacing: 0.08em; }
.gp-lesson-rule { margin: 8px 0 14px; color: var(--text-muted); font-size: 14.5px; line-height: 1.65; }
.gp-lesson-goal { display: inline-flex; align-items: baseline; gap: 6px; margin: 0 0 16px; padding: 8px 18px; border-radius: 99px; background: #fff3cf; color: #8a5a00; }
.gp-lesson-goal b { font-size: 26px; }
.gp-lesson .gp-actions { justify-content: center; }
.gp-lesson .btn kbd { margin-left: 6px; }

/* ------------------------------------------------------------ 主推和 HOT（2026-10-14）
   主推（manifest featured）：游戏中心最上面一排两张大卡片，封面更高、标题更大。
   HOT：最近玩的人最多的前三个（GET /api/games/heat），卡片左上角一枚火焰标签。 */
.game-featured { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px; margin-bottom: 22px; }
.game-featured[hidden] { display: none; }
.game-card.is-featured { box-shadow: 0 0 0 2px #f2c14e, 0 18px 36px -20px rgba(200, 140, 20, 0.55); }
/* 封面是按 16:9 画满的（不留白边），主推卡也用 16:9 */
.game-card.is-featured .game-body h3 { font-size: 21px; }
.game-card.is-featured .game-tagline { font-size: 14px; -webkit-line-clamp: 2; }
.game-ribbon.is-featured { background: linear-gradient(180deg, #ffd765, #f0a92a); color: #5a3a00; box-shadow: 0 4px 10px -4px rgba(220, 150, 20, .7); }
.game-hot {
  position: absolute;
  top: 12px;
  left: 12px;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 3px 9px 3px 6px;
  border-radius: 999px;
  background: linear-gradient(180deg, #ff8a3d, #ef4a24);
  color: #fff;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.06em;
  box-shadow: 0 4px 10px -4px rgba(239, 74, 36, 0.7);
}
.game-hot svg { width: 13px; height: 13px; }
@media (max-width: 760px) { .game-featured { grid-template-columns: minmax(0, 1fr); gap: 14px; } }

/* 会员游戏：试玩用完后的开局卡（2026-10-15） */
.gp-locked { text-align: center; }
.gp-lock-ico { display: inline-grid; place-items: center; width: 56px; height: 56px; border-radius: 16px; background: #fbf1d9; color: #b07d12; margin-bottom: 8px; }
.gp-lock-ico svg { width: 28px; height: 28px; }
.gp-locked .gp-actions { justify-content: center; gap: 10px; flex-wrap: wrap; }
.gp-trial { margin: -4px 0 10px; }
.chip-member { display: inline-flex; align-items: center; gap: 3px; margin-left: 6px; background: #fbf1d9; color: #8a6212; }
.chip-member svg { width: 12px; height: 12px; }

/* 打字小结（2026-10-16，游戏结束卡片）：一句话 + 最常按错的键 + 去练这几个键 */
.gp-report { display: grid; justify-items: center; gap: 8px; margin: 12px auto 0; padding: 12px 16px; max-width: 420px; border-radius: 14px; background: var(--bg-soft); text-align: center; }
.gp-report > b { color: var(--text-strong); font-size: 14px; }
.gp-report p { margin: 0; color: var(--text-muted); font-size: 13.5px; line-height: 1.7; }
.gp-report kbd { display: inline-grid; place-items: center; min-width: 26px; height: 26px; margin: 0 2px; padding: 0 6px; border: 1px solid var(--line); border-bottom-width: 3px; border-radius: 7px; background: var(--bg-elevated); color: var(--text-strong); font: 800 13px/1 ui-monospace, Menlo, monospace; }

/* 图鉴（2026-10-16，game.js showAlmanac + 游戏给的内容，键盘打僵尸 zombie.js almanac） */
.gp-alm-veil { position: fixed; inset: 0; z-index: 1200; display: grid; place-items: center; padding: 20px; background: rgba(10, 14, 24, .5); backdrop-filter: blur(3px); }
.gp-alm { position: relative; width: min(900px, 100%); max-height: calc(100vh - 40px); overflow-y: auto; padding: 22px 24px 18px; border-radius: 20px; background: var(--bg-elevated); box-shadow: 0 30px 80px -20px rgba(0, 0, 0, .5); }
.gp-alm-x { position: absolute; top: 12px; right: 12px; width: 34px; height: 34px; border: 0; border-radius: 50%; background: var(--bg-soft); color: var(--text-muted); font-size: 20px; cursor: pointer; }
.gp-alm-x:hover { color: var(--text-strong); }
.zba-h { margin: 0 0 12px; color: var(--text-strong); font-size: 20px; }
.zba-tabs { display: inline-flex; gap: 4px; margin-bottom: 14px; padding: 4px; border-radius: 12px; background: var(--bg-soft); }
.zba-tabs button { padding: 7px 16px; border: 0; border-radius: 9px; background: transparent; color: var(--text-muted); font: inherit; font-weight: 700; cursor: pointer; }
.zba-tabs button[aria-pressed="true"] { background: var(--bg-elevated); color: var(--text-strong); box-shadow: 0 1px 3px rgba(16, 24, 40, .12); }
.zba-tabs small { margin-left: 4px; color: var(--text-dim); font-weight: 600; }
.zba-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 10px; }
.zba-item { display: flex; gap: 12px; padding: 10px; border-radius: 14px; background: var(--bg-soft); }
.zba-pic { display: grid; place-items: end center; flex: none; width: 76px; height: 78px; overflow: hidden; border-radius: 10px; background: linear-gradient(#a8dcf5, #b9e3a0 70%); }
.zba-three { display: grid; grid-template-columns: repeat(2, auto); justify-content: center; align-items: end; }
.zba-three svg:first-child { grid-column: 1 / 3; justify-self: center; }
.zba-item.is-unknown .zba-pic svg { filter: brightness(0) opacity(.35); }
.zba-item.is-locked { opacity: .62; }
.zba-item.is-locked .zba-pic svg { filter: grayscale(1); }
.zba-txt { display: grid; align-content: start; gap: 3px; min-width: 0; }
.zba-txt b { color: var(--text-strong); font-size: 14.5px; }
.zba-txt b i { margin-left: 4px; color: #c98a10; font-size: 12px; font-style: normal; }
.zba-txt small { color: var(--text-dim); font-size: 12px; }
.zba-txt em { color: var(--text-muted); font-size: 12.5px; font-style: normal; line-height: 1.5; }
.zba-foot { margin: 14px 0 0; color: var(--text-dim); font-size: 12.5px; }
@media (max-width: 560px) { .gp-alm { padding: 18px 14px 14px; } .zba-grid { grid-template-columns: 1fr; } }
