:root {
  --ink: #042C60;
  --blue: #1CB0F6;
  --green: #58CC02;
  --yellow: #FFC800;
  --red: #E5484D;
  --bg: #F4F7FB;
  --card: #fff;
  --border: #DDE5EF;
  --muted: #5B6B80;
  --shadow: 0 8px 25px rgba(4, 44, 96, .08);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: "Segoe UI", "Noto Sans Thai", system-ui, sans-serif;
  background: var(--bg);
  color: var(--ink);
  -webkit-text-size-adjust: 100%; /* iOS Safari */
  text-size-adjust: 100%;
}

.skip {
  position: absolute; left: -999px;
  background: var(--ink); color: #fff; padding: 10px 16px; border-radius: 0 0 12px 0; z-index: 20;
}
.skip:focus { left: 0; }

.topbar {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 16px;
  background: var(--ink); color: #fff;
}
.home-link { color: #fff; text-decoration: none; font-weight: 700; font-size: .92rem; }
.home-link:hover { text-decoration: underline; }
.wordmark { flex: 1; font-weight: 900; letter-spacing: .3px; }
.ghost-btn {
  background: rgba(255, 255, 255, .15); color: #fff; border: 0;
  border-radius: 999px; padding: 7px 14px; font: inherit; font-weight: 700; cursor: pointer;
  min-height: 36px;
}
.ghost-btn:hover { background: rgba(255, 255, 255, .28); }

main { width: min(100% - 28px, 900px); margin: 0 auto; padding: 22px 0 60px; }

.screen[hidden] { display: none !important; }

/* ---- one-screen play surface ----
   The board must never scroll. While a round is on, the page becomes a flex
   column pinned to the dynamic viewport height and the twelve tiles divide
   whatever vertical space is left over. dvh rather than vh: Safari's
   collapsing toolbar changes the usable height mid-round, and vh would leave
   the bottom row underneath it. */
body.playing {
  display: flex; flex-direction: column; overflow: hidden;
  height: 100vh;  /* Chrome < 108 and Safari < 15.4 */
  height: 100dvh; /* everything current, in both engines */
}
body.playing .topbar { flex: none; }
body.playing main {
  flex: 1; min-height: 0; display: flex; flex-direction: column;
  padding: 10px 0;
  /* Keeps the bottom row clear of the iPhone home indicator. Resolves to 0 on
     Chrome and on any browser without notch insets, so it is safe everywhere. */
  padding-bottom: max(10px, env(safe-area-inset-bottom));
}
body.playing #gameScreen { flex: 1; min-height: 0; display: flex; flex-direction: column; }
body.playing .game-head,
body.playing .level-hint,
body.playing .notice,
body.playing .live { flex: none; }
body.playing .level-hint { margin: 2px 0 10px; }
body.playing .live { margin-top: 8px; }
/* ระหว่างเล่น คำเตือนแย่งความสูงกับกระดานตรง ๆ ทุก px ที่มันกินคือไทล์ที่เตี้ยลง */
body.playing .notice { padding: 4px 8px; margin-bottom: 6px; font-size: .68rem; line-height: 1.4; }
body.playing .board { flex: 1; min-height: 0; }
body.playing .column { min-height: 0; }
/* Tiles share the leftover height equally instead of carrying a fixed one. */
body.playing .tile { flex: 1 1 0; min-height: 44px; padding: 6px; }

/* ---- one-screen round summary ----
   จบรอบแล้วต้องเห็นทั้งกระดานและผลสรุปในหน้าเดียว ไม่ต้องเลื่อน: body ยังคง
   คลาส playing ไว้ (ดู app.js finishRound) เพื่อใช้การตรึงความสูง 100dvh เดิม
   แล้วบีบส่วนที่ไม่จำเป็นออกเพื่อแบ่งที่ให้การ์ดสรุป
   ต้องอยู่หลังบล็อก body.playing เพราะ specificity เท่ากัน ลำดับจึงเป็นตัวตัดสิน */
body.round-complete .level-hint { display: none; }
/* live region ต้องไม่ใช้ display:none เพราะ say() ประกาศผลตอนจบรอบพอดี
   ซ่อนแบบ visually-hidden จึงยังอ่านออกเสียงให้ screen reader ได้ */
body.round-complete .live {
  position: absolute; width: 1px; height: 1px; margin: 0;
  overflow: hidden; clip-path: inset(50%);
}
/* ไทล์ตอนจบรอบไม่ใช่เป้าแตะแล้ว ย่อได้ต่ำกว่า 44px เพื่อคืนที่ให้การ์ดสรุป */
body.round-complete .tile { min-height: 26px; padding: 3px 6px; }
/* flex: none บังคับให้การ์ดสรุปได้ความสูงเต็มที่ต้องการ แล้วผลักการบีบไป
   ที่กระดานแทน (ค่าเริ่มต้น 0 1 auto จะทำให้การ์ดหดตัวเองจนตกขอบ) */
body.round-complete .inline-summary { flex: none; margin-top: 10px; }
body.round-complete .summary { margin-bottom: 12px; }

/* จอเตี้ยกว่านี้บีบยังไงก็ไม่พอ ปล่อยให้เลื่อนดีกว่าโดน overflow:hidden ตัด
   ปุ่ม "เล่นรอบต่อไป" ทิ้งจนเล่นต่อไม่ได้ */
@media (orientation: portrait) and (max-height: 580px) {
  body.round-complete { height: auto; overflow: auto; }
}

h1 { font-size: 1.4rem; margin: 6px 0 8px; }
.lede { margin: 0 0 20px; color: var(--muted); font-size: .95rem; line-height: 1.6; }
.fineprint { margin-top: 26px; color: var(--muted); font-size: .78rem; line-height: 1.6; }

.back-btn {
  background: none; border: 0; padding: 6px 0; margin-bottom: 6px;
  font: inherit; font-weight: 700; color: var(--blue); cursor: pointer; min-height: 40px;
}
.back-btn:hover { text-decoration: underline; }

/* ---- deck picker ---- */
.deck-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; }
.deck-card {
  display: flex; flex-direction: column; align-items: flex-start; gap: 6px;
  padding: 16px; background: var(--card); border: 1px solid var(--border);
  border-radius: 16px; box-shadow: var(--shadow); cursor: pointer;
  font: inherit; color: inherit; text-align: left; min-height: 128px;
}
.deck-card:hover { border-color: var(--blue); }
.deck-card:focus-visible { outline: 3px solid var(--blue); outline-offset: 2px; }
.deck-emoji { font-size: 1.7rem; line-height: 1; }
.deck-name { font-weight: 800; font-size: 1rem; }
.deck-meta { color: var(--muted); font-size: .8rem; }
.deck-badge {
  align-self: flex-start; background: var(--yellow); color: var(--ink);
  border-radius: 999px; padding: 2px 9px; font-size: .7rem; font-weight: 800;
}
.deck-warn { color: #8A6100; font-size: .76rem; line-height: 1.5; }
.collection-groups { display: grid; gap: 20px; }
.collection-group { background: var(--card); border: 1px solid var(--border); border-radius: 16px; padding: 16px; box-shadow: var(--shadow); }
.collection-group h2 { margin: 0 0 4px; font-size: 1.1rem; }
.collection-description { margin: 0 0 12px; color: var(--muted); font-size: .85rem; line-height: 1.5; }
.collection-decks { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.collection-deck { display: grid; gap: 5px; min-height: 78px; padding: 12px; text-align: left; font: inherit; color: inherit; background: var(--bg); border: 1px solid var(--border); border-radius: 12px; cursor: pointer; }
.collection-deck:hover { border-color: var(--blue); }
.collection-deck:focus-visible { outline: 3px solid var(--blue); outline-offset: 2px; }
.collection-deck-label { font-weight: 800; line-height: 1.4; }
.collection-deck-count { color: var(--muted); font-size: .8rem; }
.bar { width: 100%; height: 8px; background: #E7EDF5; border-radius: 999px; overflow: hidden; margin-top: auto; }
.bar > span { display: block; height: 100%; background: var(--green); }

/* ---- level picker ----
   จับคู่ is the plain form of the game, so it gets one oversized card in the
   middle and the four variations sit underneath. Each level owns an accent
   colour, but the number, icon and name are always present too: colour alone
   never carries the meaning. */
.level-list { display: flex; flex-direction: column; align-items: center; gap: 16px; }

[data-level="1"] { --accent: #58CC02; --accent-deep: #43A000; --on-accent: #fff; --accent-soft: #EDFBE0; }
[data-level="2"] { --accent: #1CB0F6; --accent-deep: #0B84C4; --on-accent: #fff; --accent-soft: #E4F6FE; }
[data-level="3"] { --accent: #7C5CFF; --accent-deep: #5B3FD6; --on-accent: #fff; --accent-soft: #F0EBFF; }
[data-level="4"] { --accent: #FFC800; --accent-deep: #E0A800; --on-accent: #3D2E00; --accent-soft: #FFF6D9; }
[data-level="5"] { --accent: #FF6B4A; --accent-deep: #DC4526; --on-accent: #fff; --accent-soft: #FFEDE8; }

.level-hero {
  position: relative; overflow: hidden;
  width: min(100%, 430px);
  display: grid; justify-items: center; gap: 3px;
  padding: 26px 22px 24px;
  border: 0; border-radius: 26px; cursor: pointer; font: inherit; text-align: center;
  background: linear-gradient(158deg, var(--accent), var(--accent-deep));
  color: var(--on-accent);
  box-shadow: 0 14px 30px rgba(4, 44, 96, .28); /* Safari < 16.2, Chrome < 111 */
  box-shadow: 0 14px 30px color-mix(in srgb, var(--accent) 40%, transparent);
}
.level-hero::after {
  content: ""; position: absolute; right: -46px; top: -52px;
  width: 150px; height: 150px; border-radius: 50%;
  border: 20px solid rgba(255, 255, 255, .16);
}
.level-hero > * { position: relative; z-index: 1; }
.level-hero-icon { font-size: 2.6rem; line-height: 1.1; }
.level-hero-num { font-size: .78rem; font-weight: 800; letter-spacing: .06em; opacity: .85; }
/* Thai stacks vowels above and below the baseline, so a Latin-tight
   line-height clips glyphs like the ู in จับคู่. */
.level-hero-title { font-size: 1.9rem; font-weight: 900; line-height: 1.5; }
.level-hero-desc { font-size: .88rem; line-height: 1.55; opacity: .92; max-width: 30ch; }
.level-hero:hover { filter: brightness(1.05); }

.level-row {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px;
  width: min(100%, 560px);
}
.level-mini {
  display: grid; justify-items: center; align-content: start; gap: 3px;
  padding: 14px 8px 15px; min-height: 104px;
  background: var(--card); border: 1px solid var(--border); border-top: 4px solid var(--accent);
  border-radius: 16px; cursor: pointer; font: inherit; color: inherit; text-align: center;
}
.level-mini:hover { border-color: var(--accent); box-shadow: 0 6px 16px rgba(4, 44, 96, .09); }
.level-mini-icon {
  display: grid; place-items: center; width: 38px; height: 38px; margin-bottom: 2px;
  border-radius: 12px; background: var(--accent-soft); font-size: 1.25rem;
}
.level-mini-num { font-size: .62rem; font-weight: 800; color: var(--muted); letter-spacing: .04em; }
.level-mini-title { font-size: .88rem; font-weight: 800; line-height: 1.5; }
.level-mini-desc { display: none; }

.level-hero:focus-visible, .level-mini:focus-visible { outline: 3px solid var(--ink); outline-offset: 3px; }
.level-hero[disabled], .level-mini[disabled] { opacity: .72; cursor: not-allowed; filter: grayscale(.5); }
.level-mini[disabled] .level-mini-desc { display: block; margin-top: 3px; font-size: .6rem; line-height: 1.35; color: var(--red); font-weight: 800; }
.level-hero[disabled]::after { display: none; }

/* ---- board ---- */
.game-head { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin-bottom: 4px; }
.game-head .back-btn { margin-bottom: 0; }
.chip {
  background: var(--card); border: 1px solid var(--border); border-radius: 999px;
  padding: 5px 12px; font-size: .8rem; font-weight: 700;
}
.level-hint { margin: 4px 0 16px; color: var(--muted); font-size: .85rem; }

.board { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.column { display: flex; flex-direction: column; gap: 10px; }

.tile {
  position: relative; /* anchors .pos-badge */
  display: flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 58px; padding: 12px 10px;
  background: var(--card); border: 2px solid var(--border); border-radius: 14px;
  font: inherit; font-size: 1rem; font-weight: 700; color: var(--ink);
  cursor: pointer; text-align: center; word-break: break-word;
  transition: border-color .12s ease, background-color .12s ease, transform .12s ease;
}
.tile:hover:not([disabled]) { border-color: var(--blue); }
.tile:focus-visible { outline: 3px solid var(--blue); outline-offset: 2px; }
/* ---- word-class colour ----
   The frame colour tells the learner what kind of word it is. It is attached
   only to tiles whose English word is on screen, so it can never be used to
   pair the columns by colour instead of by meaning. Every colour is backed by
   the written abbreviation in .pos-badge, so the colour alone never carries
   the information. Green and red are reserved for correct/wrong. */
.tile[data-pos] { border-color: var(--pos); }
.tile[data-pos="noun"]      { --pos: #1CB0F6; --pos-soft: #E4F6FE; }
.tile[data-pos="verb"]      { --pos: #7C5CFF; --pos-soft: #F0EBFF; }
.tile[data-pos="adjective"] { --pos: #FF8A3D; --pos-soft: #FFF0E4; }
.tile[data-pos="adverb"]    { --pos: #00A6A6; --pos-soft: #E0F7F7; }
.tile[data-pos="other"]     { --pos: #7A8AA0; --pos-soft: #EEF2F7; }
.pos-badge {
  position: absolute; right: 7px; bottom: 5px;
  padding: 1px 6px; border-radius: 999px;
  background: var(--pos-soft, #EEF2F7); color: var(--pos, #7A8AA0);
  font-size: .6rem; font-weight: 800; letter-spacing: .02em; line-height: 1.6;
}

.tile.is-selected { border-color: var(--blue); background: #E8F7FE; }
.tile.is-wrong { border-color: var(--red); background: #FDECEC; animation: shake .14s linear 2; }
.tile.is-matched { border-color: var(--green); background: #EEF9E4; color: var(--muted); cursor: default; }
.tile.is-matched::after { content: "✓"; color: var(--green); font-weight: 900; }
.tile.is-matched .pos-badge { background: #DCF2C6; color: #3F8F00; }
.tile.just-matched { animation: pop .34s cubic-bezier(.2, .9, .3, 1.4); }
.tile[disabled] { cursor: default; }
.tile .speaker { font-size: 1.05rem; }
.tile.audio-only { font-size: 1.5rem; }
.tile.audio-only .revealed { font-size: .82rem; font-weight: 700; color: var(--muted); }

@keyframes shake {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-5px); }
  75% { transform: translateX(5px); }
}

/* A short overshoot on the pair that just landed. Scale only — no layout
   property is animated, so the six-row board cannot reflow mid-round. */
@keyframes pop {
  0% { transform: scale(1); }
  45% { transform: scale(1.07); }
  100% { transform: scale(1); }
}

.live { margin-top: 14px; min-height: 1.4em; font-size: .85rem; color: var(--muted); }

/* ---- summary + review ---- */
.inline-summary {
  margin-top: 24px; padding: 20px;
  background: var(--card); border: 1px solid var(--border); border-radius: 16px;
  box-shadow: var(--shadow);
}
.summary { display: grid; grid-template-columns: auto 1fr; gap: 8px 18px; margin: 0 0 24px; }
.summary dt { color: var(--muted); font-size: .88rem; }
.summary dd { margin: 0; font-weight: 800; }
.summary .highlight { color: var(--green); }
.summary-actions { display: flex; flex-wrap: wrap; gap: 10px; }
.btn {
  border: 0; border-radius: 12px; padding: 12px 20px; min-height: 46px;
  font: inherit; font-weight: 800; cursor: pointer;
}
.btn-primary { background: var(--green); color: #fff; }
.btn-secondary { background: var(--card); color: var(--ink); border: 1px solid var(--border); }

.review-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.review-list li {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 14px; background: var(--card); border: 1px solid var(--border); border-radius: 12px;
}
.review-en { font-weight: 800; min-width: 7.5rem; }
.review-th { flex: 1; color: var(--muted); }
.review-count { font-size: .78rem; color: var(--red); font-weight: 700; }
.review-empty { color: var(--muted); }

/* คำเตือนสีเหลืองต้อง "เห็นและเข้าใจ" แต่ห้ามกินที่จนกระดานหรือปุ่มตกจอบนมือถือ
   จึงบีบทุกมิติ: padding บาง มุมเล็ก ตัวอักษรเล็กที่สุดที่ยังอ่านออก
   line-height ไม่ต่ำกว่า 1.4 เพราะสระบน/ล่างของไทยจะโดนตัดถ้าชิดกว่านี้ */
.notice {
  padding: 6px 9px; border-radius: 8px; margin: 0 0 8px;
  background: #FFF7DB; border: 1px solid var(--yellow); font-size: .78rem; line-height: 1.45;
}
.notice[hidden] { display: none; }

/* A speaker that failed must look broken rather than dead: the player needs to
   know the silence is a fault, not a wrong answer. */
.tile.audio-error { border-style: dashed; border-color: var(--red); }
.tile.audio-error .speaker::after { content: "!"; color: var(--red); font-weight: 900; }

/* Phone portrait. Sized against iPhone Pro Max (430 x 932 CSS px, roughly
   780px of it usable once Safari's chrome is showing) and comfortable down to
   a 375px phone. */
@media (max-width: 620px) {
  main { width: min(100% - 20px, 900px); padding-top: 14px; }
  h1 { font-size: 1.15rem; }
  .lede { margin-bottom: 14px; font-size: .84rem; }

  /* Three compact columns put all twelve decks on one screen instead of two. */
  .deck-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 9px; }
  .deck-card { min-height: 0; padding: 10px 8px; gap: 3px; border-radius: 13px; }
  .deck-emoji { font-size: 1.3rem; }
  .deck-name { font-size: .73rem; line-height: 1.45; }
  .deck-meta { font-size: .62rem; line-height: 1.4; }
  .deck-badge { padding: 1px 6px; font-size: .58rem; }
  .deck-warn { font-size: .6rem; }
  .collection-groups { gap: 12px; }
  .collection-group { padding: 11px; border-radius: 13px; }
  .collection-group h2 { font-size: .92rem; }
  .collection-description { font-size: .72rem; margin-bottom: 8px; }
  .collection-decks { gap: 7px; }
  .collection-deck { min-height: 68px; padding: 9px 7px; border-radius: 10px; }
  .collection-deck-label { font-size: .72rem; }
  .collection-deck-count { font-size: .62rem; }
  .bar { height: 6px; margin-top: 6px; }

  .level-list { gap: 13px; }
  .level-hero { padding: 20px 16px 19px; border-radius: 22px; }
  .level-hero-icon { font-size: 2.1rem; }
  .level-hero-title { font-size: 1.55rem; }
  .level-hero-desc { font-size: .8rem; }
  .level-row { gap: 8px; }
  .level-mini { min-height: 92px; padding: 11px 4px 12px; border-radius: 14px; }
  .level-mini-icon { width: 34px; height: 34px; font-size: 1.1rem; }
  .level-mini-title { font-size: .78rem; }
  .level-mini-num { font-size: .58rem; }

  .game-head { gap: 6px; margin-bottom: 2px; }
  .chip { padding: 4px 9px; font-size: .72rem; }
  .level-hint { font-size: .76rem; }
  .board { gap: 8px; }
  .column { gap: 7px; }
  .tile { font-size: clamp(.78rem, 3.5vw, 1rem); line-height: 1.45; border-radius: 12px; }
  .tile.audio-only { font-size: clamp(1.25rem, 6vw, 1.6rem); }
  .tile.audio-only .revealed { font-size: .72rem; }
  .live { font-size: .78rem; }
  .notice { padding: 5px 8px; border-radius: 7px; margin-bottom: 6px; font-size: .68rem; }
  .inline-summary { margin-top: 16px; padding: 14px; border-radius: 13px; }
  .inline-summary h1 { font-size: 1.08rem; margin: 2px 0 8px; }
  .summary { margin-bottom: 16px; gap: 6px 12px; }
  body.round-complete .inline-summary { padding: 11px 13px; }
  body.round-complete .summary { gap: 4px 12px; margin-bottom: 10px; }
  .summary-actions { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; }
  .summary-actions .btn { min-width: 0; padding: 8px 5px; min-height: 42px; font-size: .72rem; line-height: 1.3; }
}

/* Landscape on a phone cannot fit six rows at a tappable size, so there the
   board keeps a real minimum height and the page is allowed to scroll. */
@media (orientation: landscape) and (max-height: 520px) {
  body.playing { height: auto; overflow: auto; }
  body.playing .tile { flex: none; min-height: 48px; }
}

/* Motion is decoration here: the colour, the ✓ and the tone all still land,
   so removing the movement costs the player nothing. */
@media (prefers-reduced-motion: reduce) {
  .tile { transition: none; }
  .tile.is-wrong,
  .tile.just-matched { animation: none; }
  .level-hero:hover { filter: none; }
}
