:root {
  --bg: #f7f8fa;
  --surface: #ffffff;
  --text: #1a1a2e;
  --muted: #6b7280;
  --border: #d3d6da;
  --key: #e9ebee;
  --key-text: #1a1a2e;
  --correct: #6aaa64;
  --present: #c9b458;
  --absent: #787c7e;
  --primary: #6aaa64;
  --primary-d: #5a9456;
  --shadow: 0 4px 18px rgba(0,0,0,.08);
  --radius: 14px;
}
[data-theme="dark"] {
  --bg: #121213;
  --surface: #1e1e22;
  --text: #f2f2f5;
  --muted: #9aa0a6;
  --border: #3a3a3c;
  --key: #2b2b30;
  --key-text: #f2f2f5;
  --absent: #3a3a3c;
}

* { box-sizing: border-box; margin: 0; padding: 0; -webkit-tap-highlight-color: transparent; }
html, body { height: 100%; }
/* กัน double-tap zoom ทั้งเว็บ (ทุก OS) แต่ยังเปิด pinch-zoom เพื่ออ่าน (accessibility);
   canvas เกม real-time ที่ตั้ง touch-action:none เองจะ override เฉพาะจุด */
html { touch-action: manipulation; }
body {
  font-family: 'Noto Sans Thai', 'Sarabun', system-ui, sans-serif;
  background: var(--bg);
  color: var(--text);
  display: flex;
  flex-direction: column;
  min-height: 100dvh;
  overflow-x: hidden;
  transition: background .25s, color .25s;
}

/* ---------- Top bar ---------- */
.topbar {
  display: flex; align-items: center; justify-content: space-between;
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
}
.brand { font-size: 26px; font-weight: 800; letter-spacing: .5px; text-decoration: none; color: var(--text); }
.brand span { color: var(--correct); }

/* game switcher nav (on game pages) */
.game-switch { display: flex; gap: 6px; }
.game-switch a {
  text-decoration: none; color: var(--muted); font-weight: 700; font-size: 14px;
  padding: 7px 14px; border-radius: 999px; border: 1px solid var(--border); white-space: nowrap;
}
.game-switch a.active { background: var(--primary); color: #fff; border-color: var(--primary); }
@media (max-width: 560px) {
  .topbar { flex-wrap: wrap; row-gap: 8px; }
  .game-switch { order: 3; flex-basis: 100%; justify-content: center; }
  .brand { font-size: 22px; }
  .game-switch a { padding: 6px 12px; font-size: 13px; }
  /* declutter: the "all games" 🎮 button is redundant with the brand link → hide on phones */
  .top-right a.icon-btn[href="index.html"] { display: none; }
  .top-right { gap: 3px; }
  .coin-chip { padding: 5px 9px; }
}
.top-right { display: flex; gap: 6px; }
.icon-btn {
  width: 40px; height: 40px; border-radius: 10px;
  border: none; background: transparent; color: var(--text);
  font-size: 19px; font-weight: 700; cursor: pointer;
  display: grid; place-items: center; transition: background .15s;
}
.icon-btn:hover { background: var(--key); }

/* ---------- Tabs ---------- */
.tabs {
  display: flex; gap: 8px; justify-content: center;
  padding: 12px; background: var(--surface);
  border-bottom: 1px solid var(--border);
}
.tab {
  border: 1px solid var(--border); background: transparent; color: var(--muted);
  padding: 9px 18px; border-radius: 999px; font-size: 15px; font-weight: 700;
  cursor: pointer; font-family: inherit; transition: all .15s;
}
.tab.active { background: var(--primary); color: #fff; border-color: var(--primary); }

main { flex: 1; display: flex; flex-direction: column; align-items: center; width: 100%; }
/* Thai text has no word spaces, so flex items must be allowed to shrink below their
   min-content width, otherwise a long phrase widens the whole page past the viewport. */
main > * { min-width: 0; max-width: 100%; }
.game {
  display: none; flex-direction: column; align-items: center; width: 100%; max-width: 560px; padding: 14px;
  /* No accidental text-select / iOS long-press "copy" callout anywhere in the
     play area — a per-class allowlist (see .key/.icon-btn/... below) keeps
     missing new elements every time a game adds its own canvas/tile class
     (this is what let the callout cover snooker's canvas). user-select and
     -webkit-touch-callout inherit, so setting them here covers every current
     and future game's title/score/canvas/custom controls in one place. Inputs
     keep their own native text editing regardless of an ancestor's user-select. */
  -webkit-user-select: none; user-select: none; -webkit-touch-callout: none;
}
.game.active { display: flex; }
.game > * { min-width: 0; max-width: 100%; }
.game-sub { color: var(--muted); font-size: 15px; text-align: center; margin: 4px 0 14px; overflow-wrap: anywhere; }
.howto, .type-result, .passage, .hub-info, .hero p, .card p, .game-sub { overflow-wrap: anywhere; }

/* ---------- Wordle board ---------- */
.board { display: grid; grid-template-rows: repeat(6, 1fr); gap: 6px; margin-bottom: 6px; }
.row { display: grid; grid-template-columns: repeat(5, 1fr); gap: 6px; }
.tile {
  width: 58px; height: 58px;
  border: 2px solid var(--border);
  display: grid; place-items: center;
  font-size: 26px; font-weight: 700; line-height: 1;
  border-radius: 8px; background: var(--surface);
  user-select: none; text-transform: none;
}
.tile.filled { border-color: var(--muted); animation: pop .1s ease; }
.tile.correct { background: var(--correct); border-color: var(--correct); color: #fff; }
.tile.present { background: var(--present); border-color: var(--present); color: #fff; }
.tile.absent  { background: var(--absent);  border-color: var(--absent);  color: #fff; }
.tile.reveal { animation: flip .5s ease forwards; }
.row.shake { animation: shake .5s; }
.row.win .tile { animation: bounce .6s; }

@keyframes pop { 0%{transform:scale(.9)} 100%{transform:scale(1)} }
@keyframes flip { 0%{transform:rotateX(0)} 50%{transform:rotateX(90deg)} 100%{transform:rotateX(0)} }
@keyframes shake { 0%,100%{transform:translateX(0)} 20%,60%{transform:translateX(-6px)} 40%,80%{transform:translateX(6px)} }
@keyframes bounce { 0%,100%{transform:translateY(0)} 30%{transform:translateY(-14px)} 50%{transform:translateY(4px)} }

/* ---------- Toast ---------- */
.toast {
  min-height: 0; position: relative; width: 100%; display: flex; justify-content: center;
}
.toast .bubble {
  position: absolute; top: 6px;
  background: var(--text); color: var(--bg);
  padding: 9px 16px; border-radius: 8px; font-weight: 600; font-size: 14px;
  box-shadow: var(--shadow); animation: fadein .15s; z-index: 50; white-space: nowrap;
}
@keyframes fadein { from{opacity:0; transform:translateY(-6px)} to{opacity:1} }

/* ---------- Keyboard ---------- */
.keyboard { width: 100%; margin-top: 16px; display: flex; flex-direction: column; gap: 6px; }
.kb-row { display: flex; gap: 4px; justify-content: center; }
.key {
  flex: 1; min-width: 0; height: 46px;
  border: none; border-radius: 6px;
  background: var(--key); color: var(--key-text);
  font-family: inherit; font-size: 17px; font-weight: 600;
  cursor: pointer; display: grid; place-items: center; padding: 0;
  transition: transform .05s, background .2s;
}
.key:active { transform: scale(.92); }
.key.wide { flex: 1.7; font-size: 13px; font-weight: 700; }
.key.correct { background: var(--correct); color: #fff; }
.key.present { background: var(--present); color: #fff; }
.key.absent  { background: var(--absent);  color: #fff; }

/* ---------- Typing ---------- */
.typing-controls { display: flex; gap: 10px; align-items: center; justify-content: space-between; width: 100%; margin-bottom: 14px; flex-wrap: wrap; }
.seg { display: inline-flex; background: var(--key); border-radius: 999px; padding: 3px; }
.seg-btn { border: none; background: transparent; color: var(--muted); padding: 6px 16px; border-radius: 999px; font-family: inherit; font-weight: 700; font-size: 14px; cursor: pointer; }
.seg-btn.active { background: var(--surface); color: var(--text); box-shadow: var(--shadow); }
.ghost-btn { border: 1px solid var(--border); background: transparent; color: var(--text); padding: 8px 14px; border-radius: 10px; font-family: inherit; font-weight: 600; cursor: pointer; }

.type-stats, .stats-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; width: 100%; margin-bottom: 14px; }
.stat { background: var(--surface); border: 1px solid var(--border); border-radius: 12px; padding: 10px 4px; text-align: center; }
.stat .num { display: block; font-size: 22px; font-weight: 800; color: var(--primary); }
.stat .lbl { font-size: 12px; color: var(--muted); }

.passage {
  width: 100%; background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 18px; font-size: 20px; line-height: 1.9;
  margin-bottom: 12px; min-height: 90px; word-break: break-word;
}
.passage .ch { transition: background .08s; border-radius: 3px; }
.passage .ch.correct { color: var(--correct); }
.passage .ch.wrong { color: #fff; background: #e06c5e; }
.passage .ch.current { background: rgba(106,170,100,.25); box-shadow: 0 2px 0 var(--primary); }
.passage .ch.space.wrong { background: #e06c5e; }

.type-input {
  width: 100%; background: var(--surface); color: var(--text);
  border: 2px solid var(--border); border-radius: var(--radius);
  padding: 14px; font-family: inherit; font-size: 18px; line-height: 1.7; resize: none;
}
.type-input:focus { outline: none; border-color: var(--primary); }
.type-input:disabled { opacity: .6; }

.typing-actions { display: flex; flex-direction: column; align-items: center; gap: 10px; margin-top: 14px; width: 100%; }
.type-result { font-weight: 700; text-align: center; color: var(--text); white-space: pre-line; }

.primary-btn { background: var(--primary); color: #fff; border: none; padding: 12px 28px; border-radius: 12px; font-family: inherit; font-size: 16px; font-weight: 700; cursor: pointer; transition: background .15s; }
.primary-btn:hover { background: var(--primary-d); }
.primary-btn.full { width: 100%; }

/* ---------- Modals ---------- */
.modal-backdrop {
  position: fixed; inset: 0; background: rgba(10,10,20,.62); display: none; z-index: 9995;
  -webkit-backdrop-filter: blur(6px) saturate(.9); backdrop-filter: blur(6px) saturate(.9);
}
.modal-backdrop.show { display: block; animation: bdfade .2s ease both; }
@keyframes bdfade { from { opacity: 0; } to { opacity: 1; } }
body.modal-open { overflow: hidden; }
.modal {
  position: fixed; top: 50%; left: 50%; transform: translate(-50%,-50%) scale(.96);
  background: var(--surface); color: var(--text);
  border-radius: 18px; padding: 26px 22px; width: min(440px, 92vw);
  max-height: 86vh; overflow-y: auto; box-shadow: var(--shadow);
  display: none; z-index: 9996; opacity: 0; transition: opacity .15s, transform .15s;
}
.modal.show { display: block; opacity: 1; transform: translate(-50%,-50%) scale(1); animation: modalpop .26s cubic-bezier(.18,.9,.32,1.2) both; }
@keyframes modalpop { from { opacity: 0; transform: translate(-50%,-46%) scale(.9); } to { opacity: 1; transform: translate(-50%,-50%) scale(1); } }
.modal h2 { margin-bottom: 12px; font-size: 22px; }
.modal h3 { margin: 18px 0 8px; font-size: 17px; color: var(--primary); }
.modal p { color: var(--muted); line-height: 1.7; margin-bottom: 8px; }
.modal-close {
  position: absolute; top: 8px; right: 8px; width: 40px; height: 40px;
  background: none; border: none; font-size: 28px; color: var(--muted);
  cursor: pointer; line-height: 1; border-radius: 10px; display: grid; place-items: center;
  z-index: 2; transition: background .15s;
}
.modal-close:hover { background: var(--key); }
/* Full-width bottom close — primary way to dismiss tall modals on mobile,
   where the corner × scrolls out of view. */
.modal-close-btn {
  display: block; width: 100%; margin-top: 18px; padding: 13px;
  background: var(--key); color: var(--text); border: 1px solid var(--border);
  border-radius: 12px; font-family: inherit; font-size: 15px; font-weight: 700;
  cursor: pointer; transition: background .15s;
}
.modal-close-btn:hover { background: var(--border); }
.modal-close-btn:active { transform: translateY(1px); }
.legend { list-style: none; display: flex; flex-direction: column; gap: 8px; margin: 8px 0; }
.legend li { display: flex; align-items: center; gap: 10px; color: var(--muted); }
.ex { width: 34px; height: 34px; display: grid; place-items: center; border-radius: 6px; color: #fff; font-weight: 700; flex-shrink: 0; }
.ex.correct { background: var(--correct); } .ex.present { background: var(--present); } .ex.absent { background: var(--absent); }

.dist { display: flex; flex-direction: column; gap: 5px; }
.dist-row { display: flex; align-items: center; gap: 8px; font-size: 14px; }
.dist-row .n { width: 14px; font-weight: 700; }
.dist-row .bar { background: var(--absent); color: #fff; padding: 3px 8px; border-radius: 4px; text-align: right; min-width: 26px; font-weight: 700; font-size: 13px; transition: width .4s; }
.dist-row .bar.hl { background: var(--correct); }

/* ---------- Hub / landing page ---------- */
.hub { width: 100%; max-width: 720px; padding: 14px 16px 30px; }
.hero { text-align: center; padding: 26px 10px 22px; }
.hero h1 { font-size: 34px; font-weight: 800; margin-bottom: 10px; }
.hero h1 span { color: var(--correct); }
.hero p { color: var(--muted); font-size: 16px; line-height: 1.7; max-width: 480px; margin: 0 auto; }
/* auto-fill (not auto-fit) so a single search result stays one column instead of stretching full-width */
/* Denser game-portal grid (thumbnail tiles, no description) like Poki/CrazyGames */
.game-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 14px; margin-top: 8px; }
@media (min-width: 700px) { .game-grid { grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); gap: 16px; } }
/* Wider hub on larger screens so the 50-game grid uses more columns */
@media (min-width: 900px) { .hub { max-width: 1100px; } .hero p { max-width: 850px; } }
.card {
  position: relative;
  display: flex; flex-direction: column; align-items: stretch; gap: 0;
  text-align: left; overflow: hidden;
  background: var(--surface); border: 1px solid var(--border); border-radius: 16px;
  text-decoration: none; color: var(--text);
  box-shadow: var(--shadow); transition: transform .15s, border-color .15s, box-shadow .15s;
}
.card .new-badge {
  position: absolute; top: 10px; right: 10px; z-index: 2;
  background: var(--correct, #6aaa64); color: #fff;
  font-size: 11px; font-weight: 800; letter-spacing: .5px;
  padding: 3px 9px; border-radius: 999px; box-shadow: 0 2px 8px rgba(0,0,0,.25);
}
.card:hover { transform: translateY(-4px); border-color: var(--primary); }
.card-thumb { display: block; width: 100%; aspect-ratio: 1 / 1; overflow: hidden; background: var(--key); }
.card-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .28s ease; }
.card:hover .card-thumb img { transform: scale(1.07); }
.card h2 { font-size: 16px; font-weight: 700; margin: 10px 12px 2px; line-height: 1.25; }
.card .tag { font-size: 12px; color: var(--muted); font-weight: 700; margin: 0 12px 12px; }
.hub-info { margin-top: 26px; color: var(--muted); line-height: 1.8; font-size: 14px; }
.hub-info h3 { color: var(--text); font-size: 17px; margin-bottom: 8px; }

/* compact inline help on game pages */
.howto {
  width: 100%; background: var(--surface); border: 1px solid var(--border);
  border-radius: 12px; padding: 10px 14px; margin-bottom: 12px;
  color: var(--muted); font-size: 14.5px; line-height: 1.75;
}
.howto b { color: var(--text); }
.chip { display: inline-grid; place-items: center; width: 22px; height: 22px; border-radius: 5px; color: #fff; font-weight: 700; font-size: 13px; vertical-align: middle; }
.chip.correct { background: var(--correct); } .chip.present { background: var(--present); } .chip.absent { background: var(--absent); }

.foot { text-align: center; color: var(--muted); font-size: 12px; padding: 16px 16px 50px; }
.foot a { color: var(--muted); text-decoration: none; }
.foot a:hover { text-decoration: underline; }
/* Buy-me-a-coffee / donate chip */
.donate-link {
  display: inline-block;
  margin-top: 14px;
  padding: 9px 16px;
  border-radius: 999px;
  background: linear-gradient(135deg, #ffd27a, #f5a623);
  color: #5a3a00 !important;
  font-size: 13.5px;
  font-weight: 700;
  text-decoration: none !important;
  box-shadow: 0 3px 12px rgba(245, 166, 35, .28);
  transition: transform .12s ease, box-shadow .12s ease;
}
.donate-link:hover {
  transform: translateY(-2px);
  box-shadow: 0 6px 18px rgba(245, 166, 35, .42);
  text-decoration: none !important;
}
@media (prefers-reduced-motion: reduce) { .donate-link { transition: none; } }

@media (max-width: 420px) {
  .tile { width: 50px; height: 50px; font-size: 22px; }
  .key { height: 44px; font-size: 16px; }
  .stat .num { font-size: 18px; }
}

/* ============================================================
   Shared bits for the extra games
   ============================================================ */
.score-bar { display: flex; gap: 10px; width: 100%; margin-bottom: 14px; }
/* container-type lets .num size itself off this box's own rendered width, so
   scores stay legible whether there are 2, 3 or 4 boxes, and in/out of
   fullscreen — instead of a fixed px size that overflows on big numbers. */
.score-box { flex: 1; min-width: 0; overflow: hidden; container-type: inline-size; background: var(--surface); border: 1px solid var(--border); border-radius: 12px; padding: 8px 6px; text-align: center; }
.score-box .lbl { font-size: 12.5px; color: var(--muted); letter-spacing: .3px; }
.score-box .num { display: block; font-size: clamp(14px, 22cqw, 26px); font-weight: 800; color: var(--text); line-height: 1.2; white-space: nowrap; }
.big-btn { background: var(--primary); color: #fff; border: none; padding: 12px 26px; border-radius: 12px; font-family: inherit; font-size: 16px; font-weight: 700; cursor: pointer; }
.big-btn:hover { background: var(--primary-d); }
.overlay {
  /* Full-viewport modal (fixed, not absolute) so the start / game-over screen
     covers the whole page — including the recommended-games & donate sections
     below — and blocks interaction, for every game (canvas or DOM). No overlay
     ancestor uses transform/filter/contain, so fixed resolves against the
     viewport. z-index sits below the sticky topbar (60) so nav stays reachable. */
  position: fixed; inset: 0; display: none; align-items: center; justify-content: center; flex-direction: column; gap: 12px;
  background: rgba(0,0,0,.55); border-radius: var(--radius); color: #fff; text-align: center; z-index: 20; padding: 20px;
}
.overlay.show { display: flex; }
.overlay h2 { font-size: 26px; }
.overlay p { color: #eee; }

/* ---------- 2048 ---------- */
.b2048-wrap { position: relative; }
.b2048 { background: var(--border); border-radius: 12px; padding: 10px; display: grid; grid-template-columns: repeat(4,1fr); grid-template-rows: repeat(4,1fr); gap: 10px; touch-action: none; width: min(92vw, 420px); aspect-ratio: 1; }
.cell2048 { background: rgba(128,128,128,.18); border-radius: 8px; display: grid; place-items: center; font-weight: 800; font-size: clamp(20px, 7vw, 34px); transition: transform .08s; }
.cell2048.pop { animation: pop2048 .12s ease; }
@keyframes pop2048 { 0%{transform:scale(.7)} 100%{transform:scale(1)} }
.v2{background:#eee4da;color:#776e65}.v4{background:#ede0c8;color:#776e65}
.v8{background:#f2b179;color:#fff}.v16{background:#f59563;color:#fff}
.v32{background:#f67c5f;color:#fff}.v64{background:#f65e3b;color:#fff}
.v128{background:#edcf72;color:#fff;font-size:clamp(16px,6vw,28px)}.v256{background:#edcc61;color:#fff;font-size:clamp(16px,6vw,28px)}
.v512{background:#edc850;color:#fff;font-size:clamp(16px,6vw,28px)}.v1024{background:#edc53f;color:#fff;font-size:clamp(13px,5vw,22px)}
.v2048{background:#edc22e;color:#fff;font-size:clamp(13px,5vw,22px)}.vbig{background:#3c3a32;color:#fff;font-size:clamp(13px,5vw,22px)}

/* ---------- Memory ---------- */
.mem-grid { display: grid; grid-template-columns: repeat(4,1fr); gap: 10px; width: min(92vw, 400px); }
.mem-card { aspect-ratio: 1; border-radius: 12px; cursor: pointer; perspective: 600px; }
.mem-inner { position: relative; width: 100%; height: 100%; transition: transform .35s; transform-style: preserve-3d; }
.mem-card.flip .mem-inner, .mem-card.matched .mem-inner { transform: rotateY(180deg); }
.mem-face { position: absolute; inset: 0; display: grid; place-items: center; border-radius: 12px; backface-visibility: hidden; font-size: clamp(26px,9vw,40px); }
.mem-front { background: var(--primary); color: #fff; font-size: 24px; }
.mem-back { background: var(--surface); border: 2px solid var(--border); transform: rotateY(180deg); }
.mem-card.matched .mem-back { border-color: var(--correct); background: rgba(106,170,100,.15); }

/* ---------- Snake ---------- */
.snake-wrap { position: relative; width: min(92vw, 400px); }
#snakeCanvas { width: 100%; aspect-ratio: 1; background: var(--surface); border: 2px solid var(--border); border-radius: 12px; display: block; touch-action: none; }
.dpad { display: grid; grid-template-columns: repeat(3,56px); grid-template-rows: repeat(3,56px); gap: 6px; justify-content: center; margin-top: 16px; }
.dpad button { border: 1px solid var(--border); background: var(--key); color: var(--text); border-radius: 10px; font-size: 22px; cursor: pointer; }
.dpad .up{grid-area:1/2}.dpad .left{grid-area:2/1}.dpad .right{grid-area:2/3}.dpad .down{grid-area:3/2}

/* Snake — on touch screens pin the d-pad + pause/fullscreen into a stable bottom
   control bar (d-pad bottom-LEFT, pause/fullscreen bottom-RIGHT) so they are
   ALWAYS reachable without scrolling and stay put in fullscreen — same pattern as
   mktsurvival. Active only while a round is running (body.snake-playing); the
   start / game-over overlay covers them otherwise. */
@media (pointer: coarse), (max-width: 600px) {
  body.snake-playing .dpad {
    position: fixed;
    left: calc(10px + env(safe-area-inset-left));
    bottom: calc(16px + env(safe-area-inset-bottom));
    z-index: 15; margin: 0;             /* below .overlay (20) & topbar (60) */
    /* .dpad is a direct child of .game, so the fullscreen `> *` rule would stretch
       it full-width and center the arrows — pin it to content width at the left. */
    width: auto; max-width: none; justify-content: start;
    pointer-events: none;              /* only the buttons capture taps; empty
                                          cells stay click-through */
  }
  body.snake-playing .dpad button { pointer-events: auto; box-shadow: 0 2px 8px rgba(0,0,0,.35); }
  body.snake-playing .game-controls {
    position: fixed;
    right: calc(10px + env(safe-area-inset-right));
    bottom: calc(16px + env(safe-area-inset-bottom));
    left: auto; margin: 0; z-index: 15;
    flex-direction: column; gap: 8px; width: auto; max-width: none;
  }
}

/* ---------- Reaction ---------- */
.react-box { width: 100%; min-height: 300px; border-radius: var(--radius); display: grid; place-items: center; text-align: center; cursor: pointer; user-select: none; color: #fff; font-size: 22px; font-weight: 700; padding: 20px; transition: background .1s; }
.react-wait { background: #d2453b; } .react-go { background: var(--correct); } .react-early { background: #4453c9; } .react-idle { background: #5b6470; }
.react-box .ms { font-size: 44px; }
.react-tries { display: flex; gap: 6px; justify-content: center; margin-top: 12px; flex-wrap: wrap; color: var(--muted); font-size: 13px; }
.react-tries span { background: var(--surface); border: 1px solid var(--border); padding: 4px 10px; border-radius: 999px; }

/* ---------- Quick Math ---------- */
.math-problem { font-size: clamp(36px,12vw,56px); font-weight: 800; text-align: center; margin: 10px 0 6px; min-height: 70px; }
.math-answer { font-size: 32px; font-weight: 800; text-align: center; min-height: 46px; color: var(--primary); letter-spacing: 2px; }
.math-answer.shake { animation: shake .35s; }
.numpad { display: grid; grid-template-columns: repeat(3,1fr); gap: 8px; width: min(92vw, 340px); margin-top: 14px; }
.numpad button { padding: 16px 0; font-size: 24px; font-weight: 700; border: none; border-radius: 12px; background: var(--key); color: var(--text); cursor: pointer; font-family: inherit; }
.numpad button:active { transform: scale(.94); }
.numpad .wide { grid-column: span 1; background: var(--present); color: #fff; }
.timer-big { font-size: 20px; font-weight: 800; color: var(--primary); }

/* page title block on game pages */
.page-title { text-align: center; margin: 6px 0 2px; font-size: 22px; font-weight: 800; }
.page-title .ic { margin-inline-end: 6px; }

/* ---------- Leaderboard ---------- */
.lb-msg { color: var(--text); margin-bottom: 10px; }
.lb-list { list-style: none; display: flex; flex-direction: column; gap: 5px; margin: 4px 0; }
.lb-list li { display: flex; align-items: center; gap: 10px; padding: 9px 12px; border-radius: 10px; background: var(--bg); border: 1px solid var(--border); }
.lb-list li.hl { background: rgba(106,170,100,.18); border-color: var(--correct); }
.lb-rank { width: 28px; text-align: center; font-weight: 800; font-size: 15px; }
.lb-name { flex: 1; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lb-score { font-weight: 800; color: var(--primary); }
.lb-empty { justify-content: center; color: var(--muted); }
.lb-entry { display: flex; gap: 8px; margin-top: 12px; }
.lb-entry input { flex: 1; min-width: 0; padding: 11px 14px; border-radius: 10px; border: 2px solid var(--border); background: var(--bg); color: var(--text); font-family: inherit; font-size: 16px; }
.lb-entry input:focus { outline: none; border-color: var(--primary); }

/* ---------- Whack-a-mole ---------- */
.whack-grid { display: grid; grid-template-columns: repeat(3,1fr); gap: 12px; width: min(92vw, 380px); }
.hole { aspect-ratio: 1; background: var(--surface); border: 2px solid var(--border); border-radius: 50%; display: grid; place-items: center; font-size: clamp(34px,11vw,52px); cursor: pointer; overflow: hidden; user-select: none; }
.hole .pop { transform: translateY(110%); transition: transform .1s; }
.hole.up .pop { transform: translateY(0); }
.hole.bonk { animation: bonk .2s; }
@keyframes bonk { 50% { transform: scale(.86); } }

/* ---------- Simon ---------- */
.simon { position: relative; width: min(86vw, 320px); aspect-ratio: 1; border-radius: 50%; display: grid; grid-template-columns: 1fr 1fr; gap: 8px; padding: 8px; background: var(--border); margin: 0 auto; }
.simon-pad { cursor: pointer; opacity: .55; transition: opacity .12s, filter .12s; }
.simon-pad.lit { opacity: 1; filter: brightness(1.5); }
.simon-pad.g { background: #2ecc71; border-radius: 100% 0 0 0; }
.simon-pad.r { background: #e74c3c; border-radius: 0 100% 0 0; }
.simon-pad.y { background: #f1c40f; border-radius: 0 0 0 100%; }
.simon-pad.b { background: #3498db; border-radius: 0 0 100% 0; }
.simon-center { position: absolute; inset: 32%; background: var(--surface); border-radius: 50%; display: grid; place-items: center; text-align: center; font-weight: 800; font-size: 15px; border: 4px solid var(--border); }

/* ---------- Minesweeper ---------- */
.mines-top { display: flex; gap: 10px; align-items: center; justify-content: center; margin-bottom: 12px; flex-wrap: wrap; }
.mines-grid { display: grid; gap: 2px; background: var(--border); border: 3px solid var(--border); border-radius: 8px; width: min(94vw, 430px); }
.mcell { aspect-ratio: 1; display: grid; place-items: center; background: var(--key); font-weight: 800; cursor: pointer; user-select: none; font-size: clamp(12px,3.6vw,18px); border-radius: 3px; }
.mcell.revealed { background: var(--surface); cursor: default; }
.mcell.mine { background: #e06c5e; }
.mcell.flag { background: var(--present); }
.mcell.c1{color:#2980b9}.mcell.c2{color:#27ae60}.mcell.c3{color:#e74c3c}.mcell.c4{color:#8e44ad}
.mcell.c5{color:#d35400}.mcell.c6{color:#16a085}.mcell.c7{color:#2c3e50}.mcell.c8{color:#7f8c8d}
.flag-toggle { display: inline-flex; align-items: center; gap: 6px; }

/* ---------- Sudoku ---------- */
.sudoku { display: grid; grid-template-columns: repeat(9,1fr); width: min(94vw, 450px); aspect-ratio: 1; background: var(--text); gap: 1px; border: 3px solid var(--text); border-radius: 6px; }
.scell { background: var(--surface); display: grid; place-items: center; font-size: clamp(16px,5vw,24px); font-weight: 700; cursor: pointer; user-select: none; }
.scell.given { color: var(--text); font-weight: 800; }
.scell.user { color: var(--primary); }
.scell.sel { background: rgba(106,170,100,.28); }
.scell.peer { background: rgba(128,128,128,.12); }
.scell.bad { color: #e06c5e; }
.scell.br { border-right: 2px solid var(--text); }
.scell.bb { border-bottom: 2px solid var(--text); }
.sudoku-pad { display: grid; grid-template-columns: repeat(5,1fr); gap: 8px; width: min(94vw, 450px); margin-top: 12px; }
.sudoku-pad button { padding: 14px 0; font-size: 22px; font-weight: 700; border: none; border-radius: 10px; background: var(--key); color: var(--text); cursor: pointer; font-family: inherit; }

/* ---------- Quiz ---------- */
.quiz-flag { font-size: clamp(80px,28vw,130px); text-align: center; line-height: 1.1; margin: 10px 0; display: flex; justify-content: center; min-height: 120px; align-items: center; }
.quiz-flag img { width: min(72%, 260px); height: auto; border-radius: 8px; border: 1px solid var(--border); box-shadow: 0 6px 18px rgba(0,0,0,.25); }
.quiz-q { text-align: center; font-size: 18px; font-weight: 700; margin-bottom: 14px; }
.quiz-choices { display: grid; gap: 10px; width: 100%; }
.quiz-choices button { padding: 15px; font-size: 17px; font-weight: 600; border: 2px solid var(--border); border-radius: 12px; background: var(--surface); color: var(--text); cursor: pointer; font-family: inherit; transition: all .12s; }
.quiz-choices button:hover { border-color: var(--primary); }
.quiz-choices button.correct { background: var(--correct); color: #fff; border-color: var(--correct); }
.quiz-choices button.wrong { background: #e06c5e; color: #fff; border-color: #e06c5e; }
.quiz-choices button:disabled { cursor: default; }
.quiz-progress { color: var(--muted); font-weight: 700; margin-bottom: 8px; }

/* ============================================================
   World-class polish: a11y, safe-areas, sticky header, motion
   ============================================================ */
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
body { text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
::selection { background: rgba(106,170,100,.3); }

/* sticky, glassy header with iOS safe-area insets */
.topbar {
  position: sticky; top: 0; z-index: 60;
  padding-top: calc(10px + env(safe-area-inset-top));
  padding-left: calc(14px + env(safe-area-inset-left));
  padding-right: calc(14px + env(safe-area-inset-right));
  -webkit-backdrop-filter: saturate(1.2) blur(10px);
  backdrop-filter: saturate(1.2) blur(10px);
  background: color-mix(in srgb, var(--surface) 84%, transparent);
}
@supports not ((backdrop-filter: blur(2px)) or (-webkit-backdrop-filter: blur(2px))) {
  .topbar { background: var(--surface); }
}
main { padding-bottom: calc(env(safe-area-inset-bottom)); }
.foot { padding-bottom: calc(16px + env(safe-area-inset-bottom)); }

/* keyboard-accessible focus ring (mouse clicks stay clean) */
a:focus-visible, button:focus-visible, input:focus-visible, .card:focus-visible, [tabindex]:focus-visible {
  outline: 3px solid var(--primary); outline-offset: 2px; border-radius: 8px;
}
:focus:not(:focus-visible) { outline: none; }

/* comfortable tap targets, no accidental text selection / double-tap zoom on controls.
   -webkit-touch-callout:none stops the iOS long-press "select + copy" callout menu on
   buttons whose label is a text glyph (arrows ▲◀▶ etc.); tap-highlight kills the flash. */
.key, .icon-btn, .dpad button, .numpad button, .sudoku-pad button, .seg-btn, .ghost-btn,
.big-btn, .primary-btn, .hole, .simon-pad, .mcell, .scell, .tab, .quiz-choices button {
  -webkit-user-select: none; user-select: none; touch-action: manipulation;
  -webkit-touch-callout: none; -webkit-tap-highlight-color: transparent;
}
.icon-btn { min-width: 44px; min-height: 44px; }

/* tactile press feedback */
.big-btn:active, .primary-btn:active, .ghost-btn:active { transform: translateY(1px) scale(.99); }
.card { -webkit-tap-highlight-color: transparent; }
.card:active { transform: translateY(-1px) scale(.995); }

/* respect users who prefer less motion */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important; animation-iteration-count: 1 !important;
    transition-duration: .001ms !important; scroll-behavior: auto !important;
  }
}

/* ---------- Hub: search + recently played ---------- */
.hub-search { width: 100%; position: relative; margin: 2px 0 16px; }
.hub-search input {
  width: 100%; padding: 13px 16px 13px 44px; border-radius: 14px;
  border: 1px solid var(--border); background: var(--surface); color: var(--text);
  font-family: inherit; font-size: 16px;
}
.hub-search input:focus { outline: none; border-color: var(--primary); }
.hub-search .si { position: absolute; left: 15px; top: 50%; transform: translateY(-50%); opacity: .55; pointer-events: none; }
.recent { width: 100%; margin-bottom: 16px; }
.recent-title { font-size: 14px; color: var(--muted); font-weight: 700; margin-bottom: 8px; }
.recent-row { display: flex; gap: 8px; overflow-x: auto; padding-bottom: 4px; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
.recent-row::-webkit-scrollbar { display: none; }
.recent-chip {
  display: flex; align-items: center; gap: 8px; white-space: nowrap; text-decoration: none;
  color: var(--text); background: var(--surface); border: 1px solid var(--border);
  padding: 9px 15px; border-radius: 999px; font-weight: 700; font-size: 14px; flex: 0 0 auto;
  transition: border-color .15s, transform .1s;
}
.recent-chip:hover { border-color: var(--primary); }
.recent-chip:active { transform: scale(.96); }
.recent-chip .ri { font-size: 18px; }
.hub-empty { text-align: center; color: var(--muted); padding: 30px 10px; display: none; }

/* ============================================================
   8 new games
   ============================================================ */
.cv-wrap { position: relative; width: min(94vw, 420px); margin: 0 auto; }
.cv-wrap canvas {
  width: 100%; display: block; background: var(--surface); border: 2px solid var(--border); border-radius: 12px;
  touch-action: none; -webkit-user-select: none; user-select: none; -webkit-touch-callout: none;
}

/* Rock-paper-scissors */
.rps-arena { display: flex; align-items: center; justify-content: center; gap: 18px; font-size: clamp(44px,15vw,80px); min-height: 110px; }
.rps-arena .vs { font-size: 18px; color: var(--muted); font-weight: 800; }
.rps-arena .slot { width: 1.4em; text-align: center; }
.rps-result { text-align: center; font-size: 20px; font-weight: 800; min-height: 30px; margin-bottom: 6px; }
.rps-choices { display: flex; gap: 14px; justify-content: center; margin-top: 8px; }
.rps-choices button { font-size: clamp(34px,10vw,52px); width: 90px; height: 90px; border-radius: 20px; border: 2px solid var(--border); background: var(--surface); cursor: pointer; transition: transform .08s, border-color .15s; }
.rps-choices button:hover { border-color: var(--primary); }
.rps-choices button:active { transform: scale(.92); }

/* XO / tic-tac-toe */
.xo-grid { display: grid; grid-template-columns: repeat(3,1fr); gap: 8px; width: min(86vw,320px); margin: 0 auto; }
.xo-cell { aspect-ratio: 1; background: var(--surface); border: 2px solid var(--border); border-radius: 14px; display: grid; place-items: center; font-size: clamp(40px,14vw,64px); font-weight: 800; cursor: pointer; user-select: none; }
.xo-cell.x { color: var(--primary); } .xo-cell.o { color: #e06c5e; }
.xo-cell.win { background: rgba(106,170,100,.22); }
.xo-status { text-align: center; font-weight: 700; font-size: 17px; margin: 12px 0; min-height: 24px; }

/* CPS click speed */
.cps-pad { width: 100%; min-height: 300px; border-radius: var(--radius); background: var(--primary); color: #fff; display: grid; place-items: center; text-align: center; cursor: pointer; user-select: none; font-size: 22px; font-weight: 800; padding: 20px; }
.cps-pad .big { font-size: clamp(48px,18vw,76px); line-height: 1; }
.cps-pad.idle { background: #5b6470; } .cps-pad.done { background: var(--primary-d); }

/* Slide 15-puzzle */
.slide-grid { display: grid; grid-template-columns: repeat(4,1fr); gap: 8px; width: min(92vw,400px); margin: 0 auto; background: var(--border); padding: 8px; border-radius: 12px; }
.slide-tile { aspect-ratio: 1; border-radius: 10px; display: grid; place-items: center; font-size: clamp(20px,7vw,30px); font-weight: 800; background: var(--primary); color: #fff; cursor: pointer; user-select: none; transition: transform .05s; }
.slide-tile:active { transform: scale(.96); }
.slide-tile.blank { background: transparent; cursor: default; }

/* Stroop colour match */
.stroop-word { text-align: center; font-size: clamp(52px,18vw,92px); font-weight: 900; margin: 16px 0; min-height: 110px; line-height: 1.1; }
.stroop-choices { display: grid; grid-template-columns: repeat(2,1fr); gap: 12px; width: min(92vw,420px); margin: 0 auto; }
.stroop-choices button { padding: 18px; border-radius: 14px; border: 2px solid var(--border); background: var(--surface); color: var(--text); font-family: inherit; font-size: 18px; font-weight: 800; cursor: pointer; }
.stroop-choices button:active { transform: scale(.97); }

/* shooting games */
.cv-wrap canvas.crosshair { cursor: crosshair; }

/* ---------- Hub: category filter tabs ---------- */
.cat-tabs { display: flex; gap: 8px; overflow-x: auto; padding: 6px 0; margin-bottom: 16px; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
.cat-tabs::-webkit-scrollbar { display: none; }
.cat-tab {
  flex: 0 0 auto; border: 1px solid var(--border); background: var(--surface); color: var(--muted);
  padding: 9px 16px; border-radius: 999px; font-family: inherit; font-weight: 700; font-size: 14px;
  cursor: pointer; white-space: nowrap; transition: background .15s, color .15s, border-color .15s;
}
.cat-tab:hover { border-color: var(--primary); }
.cat-tab.active { background: var(--primary); color: #fff; border-color: var(--primary); }
.cat-tab .ct-n { opacity: .7; font-weight: 600; }

/* ============================================================
   Accent themes (cosmetic — unlocked with coins) + Coins/Daily UI
   ============================================================ */
:root[data-accent="blue"]   { --primary:#3b82f6; --primary-d:#2563eb; --correct:#3b82f6; }
:root[data-accent="purple"] { --primary:#8b5cf6; --primary-d:#7c3aed; --correct:#8b5cf6; }
:root[data-accent="pink"]   { --primary:#ec4899; --primary-d:#db2777; --correct:#ec4899; }
:root[data-accent="orange"] { --primary:#f59e0b; --primary-d:#d97706; --correct:#f59e0b; }
:root[data-accent="teal"]   { --primary:#14b8a6; --primary-d:#0d9488; --correct:#14b8a6; }
:root[data-accent="red"]     { --primary:#ef4444; --primary-d:#dc2626; --correct:#ef4444; }
:root[data-accent="lime"]    { --primary:#84cc16; --primary-d:#65a30d; --correct:#84cc16; }
:root[data-accent="cyan"]    { --primary:#06b6d4; --primary-d:#0891b2; --correct:#06b6d4; }
:root[data-accent="indigo"]  { --primary:#6366f1; --primary-d:#4f46e5; --correct:#6366f1; }
:root[data-accent="fuchsia"] { --primary:#d946ef; --primary-d:#c026d3; --correct:#d946ef; }
:root[data-accent="slate"]   { --primary:#64748b; --primary-d:#475569; --correct:#64748b; }

.coin-chip {
  display: inline-flex; align-items: center; gap: 5px;
  background: var(--key); color: var(--text); border: 1px solid var(--border);
  border-radius: 999px; padding: 5px 11px; font-weight: 800; font-size: 14px;
  cursor: pointer; font-family: inherit; line-height: 1; white-space: nowrap;
}
.coin-chip:active { transform: scale(.96); }
.coin-chip.claimable::after { content: ''; width: 8px; height: 8px; border-radius: 50%; background: #e23b3b; display: inline-block; }
.coin-float {
  position: fixed; z-index: 120; font-weight: 800; font-size: 18px;
  color: var(--correct); pointer-events: none; animation: coinup 1s ease-out forwards;
}
@keyframes coinup { 0%{opacity:0;transform:translateY(6px) scale(.8)} 20%{opacity:1;transform:translateY(0) scale(1.1)} 100%{opacity:0;transform:translateY(-32px)} }

/* Daily reward modal — full-bleed gradient "reward" banner so it reads as a
   game popup, clearly distinct from the page behind it. */
.modal-daily { padding: 0; overflow: hidden auto; }
.modal-daily .modal-close { color: #fff; text-shadow: 0 1px 3px rgba(0,0,0,.4); }
.modal-daily .modal-close:hover { background: rgba(255,255,255,.18); }
.daily-hero {
  position: relative; text-align: center; color: #fff;
  padding: 26px 22px 20px;
  background: linear-gradient(135deg, var(--primary) 0%, var(--primary-d) 70%, color-mix(in srgb, var(--primary-d) 70%, #000) 100%);
  overflow: hidden;
}
.daily-hero::after { /* soft sheen */
  content: ''; position: absolute; top: -60%; left: -20%; width: 80%; height: 200%;
  background: radial-gradient(ellipse at center, rgba(255,255,255,.25), transparent 60%);
  transform: rotate(18deg); pointer-events: none;
}
.daily-hero h2 { margin: 0 0 4px; font-size: 22px; color: #fff; }
.daily-hero-emoji { font-size: 52px; line-height: 1; animation: giftbob 2.4s ease-in-out infinite; }
@keyframes giftbob { 0%,100% { transform: translateY(0) rotate(-3deg); } 50% { transform: translateY(-6px) rotate(3deg); } }
.daily-body { padding: 18px 22px 22px; }
.daily-streak { text-align: center; font-size: 26px; font-weight: 800; margin: 6px 0 2px; }
.daily-sub { text-align: center; color: rgba(255,255,255,.9); font-size: 14px; }
.claim-btn { box-shadow: 0 6px 16px color-mix(in srgb, var(--primary) 45%, transparent); }
.claim-btn:not(:disabled) { animation: claimpulse 1.6s ease-in-out infinite; }
@keyframes claimpulse { 0%,100% { transform: scale(1); } 50% { transform: scale(1.025); } }
.chal { display: flex; align-items: center; gap: 10px; padding: 11px 0; border-top: 1px solid var(--border); }
.chal-i { font-size: 22px; }
.chal-main { flex: 1; min-width: 0; font-size: 14px; }
.chal-bar { height: 7px; background: var(--key); border-radius: 999px; overflow: hidden; margin-top: 6px; }
.chal-bar > i { display: block; height: 100%; background: var(--primary); border-radius: 999px; transition: width .3s; }
.chal-done { color: var(--correct); font-weight: 800; }
.chal-rew { font-weight: 800; white-space: nowrap; font-size: 14px; }
.shop-grid { display: flex; gap: 12px; flex-wrap: wrap; justify-content: center; margin-top: 8px; }
.shop-acc { width: 52px; height: 52px; border-radius: 50%; border: 3px solid var(--border); cursor: pointer; position: relative; padding: 0; }
.shop-acc.sel { border-color: var(--text); }
.shop-acc .lock { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-size: 16px; color: #fff; font-weight: 800; text-shadow: 0 1px 2px rgba(0,0,0,.5); }
.shop-acc.afford { animation: accpulse 1.3s ease-in-out infinite; }
@keyframes accpulse { 0%,100%{transform:scale(1)} 50%{transform:scale(1.12)} }

/* ============================================================
   Game-arcade look — hub / landing page
   Scoped with :has(.hub) so individual game pages stay clean.
   ============================================================ */
body:has(.hub) {
  background:
    radial-gradient(900px 520px at 50% -8%, color-mix(in srgb, var(--primary) 22%, transparent), transparent 70%),
    radial-gradient(700px 500px at 100% 0%, color-mix(in srgb, var(--correct) 16%, transparent), transparent 65%),
    var(--bg);
  background-attachment: fixed;
}
[data-theme="dark"] body:has(.hub) {
  background:
    radial-gradient(900px 520px at 50% -8%, color-mix(in srgb, var(--primary) 30%, transparent), transparent 70%),
    radial-gradient(700px 500px at 100% 0%, color-mix(in srgb, var(--primary-d) 22%, transparent), transparent 65%),
    var(--bg);
  background-attachment: fixed;
}

/* Hero — punchier, arcade headline */
.hub .hero { padding: 34px 10px 24px; }
.hub .hero h1 {
  font-size: clamp(30px, 8vw, 46px); line-height: 1.15; letter-spacing: .3px;
  text-shadow: 0 2px 18px color-mix(in srgb, var(--primary) 30%, transparent);
}
.hub .hero h1 span {
  background: linear-gradient(100deg, var(--primary), var(--correct), var(--primary));
  background-size: 200% auto; -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
  animation: heroshine 5s linear infinite;
}
@keyframes heroshine { to { background-position: 200% center; } }
@media (prefers-reduced-motion: reduce) { .hub .hero h1 span { animation: none; } }

/* Hero stat badges */
.hero-badges { display: flex; gap: 8px; justify-content: center; flex-wrap: wrap; margin-top: 16px; }
.hero-badge {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--surface); border: 1px solid var(--border); box-shadow: var(--shadow);
  border-radius: 999px; padding: 7px 14px; font-size: 13px; font-weight: 700; color: var(--text);
}
.hero-badge b { color: var(--primary); }

/* Cards — game-tile feel: glow lift on hover (thumbnail zoom handled above) */
.hub .card:hover { transform: translateY(-6px); border-color: var(--primary); box-shadow: 0 14px 30px color-mix(in srgb, var(--primary) 28%, transparent); }

/* ---------- Curated shelves (themed horizontal rows, Poki/CrazyGames-style) ---------- */
.shelf { margin: 4px 0 22px; }
.shelf-head { display: flex; align-items: center; gap: 8px; margin: 0 2px 11px; }
.shelf-head h3 { font-size: 19px; font-weight: 800; }
.shelf-head .shelf-count { font-size: 13px; color: var(--muted); font-weight: 700; }
.shelf-row {
  display: flex; gap: 13px; overflow-x: auto; padding: 2px 2px 8px;
  scroll-snap-type: x proximity; -webkit-overflow-scrolling: touch; scrollbar-width: none;
}
.shelf-row::-webkit-scrollbar { display: none; }
.gtile { flex: 0 0 auto; width: 150px; scroll-snap-align: start; text-decoration: none; color: var(--text); }
.tile-thumb {
  display: block; width: 150px; height: 150px; border-radius: 14px; overflow: hidden;
  border: 1px solid var(--border); box-shadow: var(--shadow); background: var(--key);
  transition: transform .15s, box-shadow .15s;
}
.tile-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .25s ease; }
.gtile:hover .tile-thumb { box-shadow: 0 12px 26px color-mix(in srgb, var(--primary) 30%, transparent); transform: translateY(-3px); }
.gtile:hover .tile-thumb img { transform: scale(1.08); }
.tile-name {
  display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  font-size: 14px; font-weight: 700; line-height: 1.3; margin-top: 8px;
}
.all-head { font-size: 19px; font-weight: 800; margin: 8px 2px 12px; }

/* Category tabs — chunky arcade pills */
.cat-tab { transition: background .15s, color .15s, border-color .15s, transform .12s, box-shadow .15s; }
.cat-tab:hover { transform: translateY(-2px); }
.cat-tab.active { box-shadow: 0 6px 16px color-mix(in srgb, var(--primary) 40%, transparent); }

/* ============================================================
   Modern game-page look (scoped to pages with the ? help button,
   so the hub is unaffected). Uses shared classes only — no per-game edits.
   ============================================================ */
body:has(#helpModal) {
  background:
    radial-gradient(760px 380px at 50% -12%, color-mix(in srgb, var(--primary) 15%, transparent), transparent 70%),
    var(--bg);
  background-attachment: fixed;
}
[data-theme="dark"] body:has(#helpModal) {
  background:
    radial-gradient(760px 380px at 50% -12%, color-mix(in srgb, var(--primary) 26%, transparent), transparent 70%),
    var(--bg);
  background-attachment: fixed;
}

/* Title — bigger, icon with depth */
body:has(#helpModal) .page-title { font-size: clamp(24px, 6vw, 30px); margin-top: 12px; }
body:has(#helpModal) .page-title .ic { filter: drop-shadow(0 3px 8px rgba(0,0,0,.2)); margin-inline-end: 8px; }

/* Score bar → game HUD: accent top bar, glowing numbers */
body:has(#helpModal) .score-box {
  position: relative; overflow: hidden; border-radius: 14px;
  box-shadow: var(--shadow); padding: 10px 6px 9px;
}
body:has(#helpModal) .score-box::before {
  content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px;
  background: linear-gradient(90deg, var(--primary), var(--correct));
}
body:has(#helpModal) .score-box .lbl { text-transform: uppercase; font-weight: 700; }
body:has(#helpModal) .score-box .num { color: var(--primary); }

/* Big action button — lift + glow, start screen pulses to invite play */
body:has(#helpModal) .big-btn { box-shadow: 0 6px 18px color-mix(in srgb, var(--primary) 42%, transparent); }
body:has(#helpModal) .big-btn:active { transform: translateY(1px) scale(.99); }

/* Start / game-over overlay — richer, more "game" */
.overlay {
  background: linear-gradient(165deg, rgba(8,10,20,.84), rgba(8,10,20,.6));
  -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px);
}
.overlay.show { animation: ovin .26s cubic-bezier(.18,.9,.32,1.2) both; }
@keyframes ovin { from { opacity: 0; transform: scale(.96); } to { opacity: 1; transform: scale(1); } }
.overlay h2 { font-size: 30px; text-shadow: 0 3px 14px rgba(0,0,0,.45); }
.overlay .big-btn { font-size: 18px; padding: 14px 34px; animation: claimpulse 1.7s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) { .overlay .big-btn { animation: none; } }

/* D-pad / direction buttons — tactile */
body:has(#helpModal) .dpad button {
  background: var(--surface); box-shadow: var(--shadow); font-weight: 800;
  transition: transform .08s, background .12s, color .12s;
}
body:has(#helpModal) .dpad button:active { background: var(--primary); color: #fff; transform: scale(.94); }

/* ---------- Always-visible "how to play" section (bottom of game pages) ---------- */
.howto-section { width: 100%; max-width: 560px; margin: 26px auto 0; padding: 0 14px; }
.howto-card {
  position: relative; overflow: hidden;
  background: var(--surface); border: 1px solid var(--border); border-radius: 18px;
  padding: 22px 22px 20px; box-shadow: var(--shadow);
}
.howto-card::before {
  content: ''; position: absolute; top: 0; left: 0; right: 0; height: 4px;
  background: linear-gradient(90deg, var(--primary), var(--correct));
}
.howto-card h2 { font-size: 20px; font-weight: 800; margin: 2px 0 12px; }
.howto-card p { color: var(--muted); font-size: 16px; line-height: 1.9; margin-bottom: 11px; }
.howto-card p:last-of-type { margin-bottom: 0; }
.howto-card b { color: var(--text); font-weight: 700; }
.howto-card ul, .howto-card .legend { margin: 10px 0; }
/* Ghost/outline — intentionally lower-emphasis than in-game action buttons */
.howto-play {
  margin-top: 16px; width: 100%; padding: 12px;
  background: transparent; color: var(--primary); border: 2px solid var(--primary); border-radius: 12px;
  font-family: inherit; font-size: 15px; font-weight: 700; cursor: pointer;
  transition: background .15s, color .15s, transform .1s;
}
.howto-play:hover { background: color-mix(in srgb, var(--primary) 12%, transparent); }
.howto-play:active { transform: translateY(1px); }

/* ============================================================
   Mobile readability — Thai script needs a bit more size than Latin.
   Bump the most-read text on phones so it's comfortable to read.
   ============================================================ */
@media (max-width: 560px) {
  .game-sub { font-size: 16px; }
  .page-title { font-size: 25px; }
  /* how-to (bottom section + inline) — this is what new players read */
  .howto-card p { font-size: 17px; line-height: 1.95; }
  .howto-card h2 { font-size: 21px; }
  .howto-card .howto-play { font-size: 16px; padding: 14px; }
  .howto { font-size: 15.5px; line-height: 1.8; }
  /* modal help text */
  .modal p, .modal li, .modal .legend li { font-size: 16px; }
  .modal h2 { font-size: 21px; }
  /* score HUD */
  .score-box .lbl { font-size: 13px; }
  body:has(#helpModal) .score-box .num { font-size: clamp(14px, 24cqw, 30px); }
  /* hub */
  .card h2 { font-size: 16.5px; }
  .card .tag { font-size: 13px; }
  .tile-name { font-size: 14px; }
  .shelf-head h3, .all-head { font-size: 18px; }
  .cat-tab, .tab { font-size: 15px; }
}

/* ============================================================
   Slot machine — bet row + full-width spin button + centered result
   ============================================================ */
.slot-controls { width: 100%; max-width: min(94vw, 420px); margin: 14px auto 0; display: flex; flex-direction: column; gap: 12px; }
.bet-row { display: flex; align-items: center; justify-content: center; gap: 14px; }
.bet-row #betLabel { font-weight: 800; font-size: 16px; min-width: 110px; text-align: center; }
.bet-row .ghost-btn { font-size: 20px; width: 54px; padding: 9px 0; }
.spin-full { width: 100%; padding: 16px; font-size: 19px; border-radius: 14px; }
.slot-result {
  position: absolute; left: 50%; top: 50%; z-index: 25; pointer-events: none;
  opacity: 0; transform: translate(-50%, -50%) scale(.8);
  transition: opacity .22s ease, transform .28s cubic-bezier(.18,.9,.32,1.3);
  background: rgba(15,17,28,.92); color: #fff; font-weight: 800; font-size: 20px;
  padding: 15px 26px; border-radius: 16px; text-align: center; max-width: 88%;
  box-shadow: 0 12px 32px rgba(0,0,0,.45); border: 1px solid rgba(255,255,255,.12);
}
.slot-result.show { opacity: 1; transform: translate(-50%, -50%) scale(1); }
.slot-result.win {
  background: linear-gradient(135deg, var(--primary), var(--primary-d));
  border-color: rgba(255,255,255,.3); font-size: 22px;
}

/* ============================================================
   ตำส้มตำ (rhythm) — timing ring + mortar
   ============================================================ */
.somtam-stage {
  position: relative; width: min(90vw, 360px); height: min(90vw, 360px); margin: 8px auto 4px;
  display: grid; place-items: center; user-select: none; -webkit-user-select: none;
  touch-action: manipulation; cursor: pointer;
}
.somtam-mortar { font-size: clamp(90px, 30vw, 130px); line-height: 1; z-index: 2; transition: transform .08s; }
.somtam-mortar.hit { transform: scale(.86); }
.somtam-ring {
  position: absolute; width: 150px; height: 150px; border-radius: 50%;
  border: 7px solid var(--primary); box-sizing: border-box; pointer-events: none;
  will-change: transform, opacity;
}
.somtam-target {
  position: absolute; width: 150px; height: 150px; border-radius: 50%;
  border: 3px dashed var(--border); box-sizing: border-box; pointer-events: none;
}
.somtam-judge {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -120px);
  font-weight: 800; font-size: 26px; pointer-events: none; opacity: 0; z-index: 3;
}
.somtam-judge.show { animation: judgepop .5s ease both; }
@keyframes judgepop { 0% { opacity: 0; transform: translate(-50%, -100px) scale(.8); } 30% { opacity: 1; } 100% { opacity: 0; transform: translate(-50%, -150px) scale(1.1); } }
.somtam-judge.perfect { color: var(--correct); }
.somtam-judge.good { color: var(--primary); }
.somtam-judge.miss { color: #e23b3b; }
.tap-btn {
  display: block; width: 100%; max-width: min(90vw, 360px); margin: 10px auto 0; padding: 18px;
  background: var(--primary); color: #fff; border: none; border-radius: 16px;
  font-family: inherit; font-size: 20px; font-weight: 800; cursor: pointer;
  box-shadow: 0 6px 18px color-mix(in srgb, var(--primary) 42%, transparent); touch-action: manipulation;
}
.tap-btn:active { transform: translateY(2px) scale(.99); }

/* ============================================================
   ต่อคำไทย (word chain) — timer bar
   ============================================================ */
.wc-timer { width: 100%; max-width: 520px; height: 8px; background: var(--key); border-radius: 999px; overflow: hidden; margin: 2px 0 12px; }
.wc-timer > i { display: block; height: 100%; width: 100%; background: linear-gradient(90deg, var(--primary), var(--correct)); border-radius: 999px; transition: width .1s linear; }
.wc-timer.low > i { background: #e23b3b; }
.wc-need { font-weight: 800; color: var(--primary); }

/* ============================================================
   Result quiz (ทายนิสัย / สายไหน) + รวยเกิน (spending sim)
   ============================================================ */
.rq-question { font-size: clamp(19px,5.2vw,25px); font-weight: 800; text-align: center; line-height: 1.55; min-height: 78px; display: flex; align-items: center; justify-content: center; padding: 10px 8px; }
#rqResultIcon { font-size: 76px; line-height: 1; margin-bottom: 6px; }
.spend-bal {
  position: sticky; top: 0; z-index: 5; text-align: center; padding: 12px 10px; margin-bottom: 12px;
  background: linear-gradient(135deg, var(--primary), var(--primary-d)); color: #fff; border-radius: 16px; box-shadow: var(--shadow);
}
.spend-bal .lbl { font-size: 13px; opacity: .9; }
.spend-bal .amt { font-size: clamp(26px,8vw,36px); font-weight: 800; line-height: 1.1; }
.spend-list { display: flex; flex-direction: column; gap: 10px; width: 100%; max-width: 520px; }
.spend-item {
  display: flex; align-items: center; gap: 12px; padding: 10px 12px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 14px;
}
.spend-item .si-emoji { font-size: 36px; line-height: 1; flex: 0 0 auto; }
.spend-item .si-main { flex: 1; min-width: 0; }
.spend-item .si-name { font-weight: 700; font-size: 15px; }
.spend-item .si-price { color: var(--muted); font-size: 13px; }
.spend-item .si-ctrl { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }
.spend-item .si-qty { min-width: 26px; text-align: center; font-weight: 800; }
.spend-btn { width: 38px; height: 38px; border-radius: 10px; border: none; font-size: 20px; font-weight: 800; cursor: pointer; font-family: inherit; color: #fff; }
.spend-btn.buy { background: var(--primary); } .spend-btn.buy:disabled { opacity: .35; cursor: not-allowed; }
.spend-btn.sell { background: var(--border); color: var(--text); }
.spend-done { width: 100%; max-width: 520px; margin: 14px auto 0; padding: 15px; font-size: 17px; }

/* ============================================================
   Game-over overlay buttons — fixed comfortable size (180×56)
   ============================================================ */
.overlay .big-btn, .overlay .ghost-btn {
  width: 180px; height: 56px; padding: 0; max-width: 80vw;
  display: inline-flex; align-items: center; justify-content: center;
}
.overlay .ghost-btn { font-size: 17px; }

/* ============================================================
   ชงชาไทย (time management) — customer, recipe steps, ingredients
   ============================================================ */
.ts-customer { text-align: center; margin: 6px 0 2px; }
.ts-face { font-size: 64px; line-height: 1; transition: transform .12s; }
.ts-face.angry { animation: tsangry .4s; }
@keyframes tsangry { 0%,100% { transform: translateX(0); } 25% { transform: translateX(-8px) rotate(-4deg); } 75% { transform: translateX(8px) rotate(4deg); } }
.ts-order { font-weight: 800; font-size: 20px; margin-top: 4px; }
.ts-recipe { display: flex; gap: 8px; justify-content: center; margin: 10px 0; flex-wrap: wrap; }
.ts-step {
  width: 52px; height: 52px; border-radius: 12px; display: grid; place-items: center;
  font-size: 28px; border: 2px solid var(--border); background: var(--surface); position: relative;
}
.ts-step.done { opacity: .4; border-color: var(--correct); }
.ts-step.cur { border-color: var(--primary); box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary) 35%, transparent); transform: scale(1.06); }
.ts-timer { width: 100%; max-width: 460px; height: 10px; background: var(--key); border-radius: 999px; overflow: hidden; margin: 6px auto 14px; }
.ts-timer > i { display: block; height: 100%; width: 100%; background: linear-gradient(90deg, var(--primary), var(--correct)); transition: width .1s linear; }
.ts-timer.low > i { background: #e23b3b; }
.ts-ings { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; width: 100%; max-width: 420px; margin: 0 auto; }
.ts-ing {
  display: flex; flex-direction: column; align-items: center; gap: 2px; padding: 12px 4px;
  border: 2px solid var(--border); border-radius: 14px; background: var(--surface); color: var(--text);
  font-family: inherit; font-weight: 700; font-size: 13px; cursor: pointer; touch-action: manipulation;
  transition: transform .08s, border-color .12s, background .12s;
}
.ts-ing .ig { font-size: 32px; line-height: 1; }
.ts-ing:active { transform: scale(.94); }
.ts-ing.good { border-color: var(--correct); background: color-mix(in srgb, var(--correct) 18%, transparent); }
.ts-ing.bad { border-color: #e23b3b; background: color-mix(in srgb, #e23b3b 18%, transparent); }

/* ============================================================
   Pause overlay + Fullscreen (injected by common.js)
   ============================================================ */
#pauseOverlay {
  position: absolute; inset: 0; z-index: 21;
  display: none; flex-direction: column;
  align-items: center; justify-content: center; gap: 14px;
  background: rgba(0,0,0,.72);
  border-radius: 12px; /* matches .cv-wrap canvas border-radius */
  backdrop-filter: blur(3px);
}
#pauseOverlay.show { display: flex; }
#pauseOverlay .p-icon { font-size: 56px; line-height: 1; }
#pauseOverlay .p-lbl  { color: #fff; font-size: 1.1rem; font-weight: 700; margin: 0; }

/* On-screen game controls (pause + fullscreen) placed below the canvas so
   players can see them — labelled with Thai text, not just an icon. */
.game-controls {
  display: flex; gap: 10px; justify-content: center; align-items: center;
  flex-wrap: wrap; margin: 12px auto 4px;
}
.gc-btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 9px 18px; border-radius: 12px;
  background: var(--surface); border: 1px solid var(--border);
  color: var(--text); font-weight: 600; font-size: 14.5px; line-height: 1;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: background .12s ease, transform .08s ease, border-color .12s ease;
}
.gc-btn:hover { background: var(--border); border-color: var(--primary); }
.gc-btn:active { transform: scale(.96); }

/* Hide topbar in fullscreen so the game fills cleanly */
body.in-fullscreen .topbar { display: none; }
/* Lock the page behind CSS pseudo-fullscreen (iPhone Safari) so nothing scrolls
   underneath the pinned game. Native fullscreen doesn't need this but it's inert
   there. */
body.in-fullscreen { overflow: hidden; }

/* ---- CSS pseudo-fullscreen (iPhone Safari fallback — no Fullscreen API) ----
   Pin the game section over the whole visible viewport. 100dvh tracks the
   dynamic viewport so it stays correct as Safari's URL bar shows/hides. */
.game.pseudo-fs, main.pseudo-fs {
  position: fixed !important; inset: 0 !important;
  z-index: 9990 !important;
  width: 100vw !important; height: 100dvh !important;
}

/* Fullscreen targets the .game SECTION (see common.js — this keeps the pause /
   fullscreen buttons and score bar visible). For canvas games the canvas wrapper
   takes the leftover vertical space and common.js scales the canvas to fit that
   box with its aspect ratio preserved. It sizes the DISPLAY box only (inline
   width/height in px) — never the drawing buffer — so pointer mapping via
   getBoundingClientRect stays correct. */
.game:fullscreen .cv-wrap, .game:fullscreen .snake-wrap,
.game:-webkit-full-screen .cv-wrap, .game:-webkit-full-screen .snake-wrap,
.game.pseudo-fs .cv-wrap, .game.pseudo-fs .snake-wrap {
  flex: 1 1 auto; min-height: 0;
  width: 100%; max-width: none;
  display: flex; align-items: center; justify-content: center;
}
.game:fullscreen .cv-wrap canvas, .game:fullscreen .snake-wrap canvas,
.game:-webkit-full-screen .cv-wrap canvas, .game:-webkit-full-screen .snake-wrap canvas,
.game.pseudo-fs .cv-wrap canvas, .game.pseudo-fs .snake-wrap canvas {
  border: none; border-radius: 0;
  max-width: 100%; max-height: 100%;
}
.game:fullscreen .overlay, .game:fullscreen #pauseOverlay,
.game:-webkit-full-screen .overlay, .game:-webkit-full-screen #pauseOverlay,
.game.pseudo-fs .overlay, .game.pseudo-fs #pauseOverlay {
  border-radius: 0;
}
/* Reclaim vertical space for the board/canvas: drop the title + subtitle. */
.game:fullscreen .page-title, .game:fullscreen .game-sub,
.game:-webkit-full-screen .page-title, .game:-webkit-full-screen .game-sub,
.game.pseudo-fs .page-title, .game.pseudo-fs .game-sub {
  display: none;
}
/* Score bar stays a normal centered row above the canvas in fullscreen.
   Must keep width:100% (capped like the other direct children below) —
   width:auto here used to let align-items:center shrink-wrap it to content,
   which squeezed each .score-box down to near-nothing and let big scores
   spill past the edge. */
.game:fullscreen .score-bar,
.game:-webkit-full-screen .score-bar,
.game.pseudo-fs .score-bar {
  width: 100%; max-width: 560px; margin: 0; gap: 8px; flex: 0 0 auto;
}

/* Fullscreen for non-canvas (DOM) games — center the game section on a full-screen
   themed background with vertical scroll if the board is tall. */
.game:fullscreen, .game:-webkit-full-screen,
main:fullscreen, main:-webkit-full-screen,
.game.pseudo-fs, main.pseudo-fs {
  background: var(--bg) !important;
  max-width: none !important; margin: 0 !important;
  overflow-y: auto !important; -webkit-overflow-scrolling: touch;
  display: flex !important; flex-direction: column; align-items: center;
  justify-content: flex-start; gap: 10px;
  padding: calc(12px + env(safe-area-inset-top)) 14px calc(18px + env(safe-area-inset-bottom)) !important;
}
.game:fullscreen, .game:-webkit-full-screen,
main:fullscreen, main:-webkit-full-screen {
  width: 100vw !important; height: 100vh !important;
}
.game:fullscreen > *, .game:-webkit-full-screen > *,
main:fullscreen > *, main:-webkit-full-screen > *,
.game.pseudo-fs > *, main.pseudo-fs > * {
  width: 100%; max-width: 560px;
}
/* The start / game-over overlay in these DOM games is a direct child of the
   (unpositioned) .game section. As position:absolute it only covered the first
   viewport, so the recommended-games / donate sections below stayed clickable —
   and the fullscreen max-width above pinned it to the left. Make it a real
   full-viewport modal so it always covers the page and centers, in and out of
   fullscreen. (Canvas games nest their overlay in a positioned wrapper, so this
   direct-child selector leaves them covering just the board, as intended.) */
.game > .overlay {
  position: fixed; inset: 0; width: 100%; max-width: none;
}

/* Tighten topbar on small phones now that we have 2 extra buttons */
@media (max-width: 400px) {
  #pauseBtn, #fsBtn { font-size: 16px; }
}
