/* ═══════════════════════════════════════════════════════════════
   careiti-fitplay.css — 玩緊嗰陣，個遊戲要 fit 得晒、夠大隻

   Measured in play, before this file:

     iPad 橫 1194x834   color-match 超出 1571px · reaction 超出 2721px
                        n-back 超出 1546px · number-memory 超出 1079px
     手機 390x844       同樣四隻，最細嘅可撳目標 28px（低過 44px 下限）

   Two problems, one cause. The play screen is only part of a long page —
   the hero, the science card, the how-to prose and the level picker are
   all still below it — so the player has to scroll to reach the game, and
   the game itself is drawn at whatever size the page's own CSS happened
   to pick, with no idea how much room there actually is.

   So: while a round is running, the play area is the page, and everything
   in it is sized from the space that exists rather than from fixed pixels.

   ── Why not just clip the page ──────────────────────────────────
   Because that is what I did first, and it made the result screen render
   below the fold of a body that could no longer scroll — blank. Nothing
   here sets `overflow: hidden` on the body, and the play area itself
   keeps `overflow-y: auto`: if a game genuinely needs more room than the
   screen has, it scrolls INSIDE its own box instead of being cut off.
   Fitting is the goal; unreachable content is never the price.
   ═══════════════════════════════════════════════════════════════ */

:root {
  /* Height actually available to a game: the screen, less the game bar.
     100dvh rather than 100vh because on iOS the address bar counts toward
     vh, which would make every play area taller than what can be seen. */
  /* --cgf-top 由 careiti-countdown.js 量返嚟（棋盤區真正嘅頂）。
     以前用 --cgt-h（頂欄高度）做代替，等於假設「棋盤區緊貼頂欄底」。
     10 吋平板量出嚟差 24px，而差嗰 24px 令記憶翻牌最底一行牌跌出屏幕。
     fallback 68px 只係量唔到嗰陣先用，同以前行為一樣。 */
  --cgf-avail: calc(100dvh - var(--cgf-top, var(--cgt-h, 68px)));
}

/* ── The play area is the page ───────────────────────────────────
   Siblings are hidden by JS (see markPlay() in careiti-countdown.js),
   which is reversible and does not depend on knowing every game's markup.
   This part sizes what is left. */
body.cgc-playing [data-cgf-play] {
  min-height: var(--cgf-avail);
  max-height: var(--cgf-avail);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: clamp(8px, 1.4vmin, 20px);
  overflow-y: auto;              /* never clip — see header */
  padding: clamp(8px, 1.6vmin, 20px);
  margin: 0 auto;
  width: 100%;
}
body.cgc-playing .cgf-hidden { display: none !important; }

/* ── Controls scale with the room, and never go under 44px ───────
   The divisors are the number of rows each control type realistically
   shares the screen with, so a four-answer quiz gets tall buttons and a
   sixteen-tile board gets small ones, without either being told a fixed
   pixel size that is wrong on the other device. */
body.cgc-playing .ans-btn,
body.cgc-playing .choice-btn,
body.cgc-playing .opt-btn,
body.cgc-playing .c-btn,
body.cgc-playing [id^="choice-"],
body.cgc-playing [id^="ans"],
body.cgc-playing [id^="ao"] {
  min-height: clamp(52px, calc(var(--cgf-avail) / 9), 118px);
  font-size: clamp(17px, calc(var(--cgf-avail) / 26), 32px);
  font-weight: 700;
}

/* Question text is the thing being read, so it gets the largest ramp. */
body.cgc-playing #qText,
body.cgc-playing .q-text,
body.cgc-playing #emojiDisplay,
body.cgc-playing #question,
body.cgc-playing .question {
  font-size: clamp(22px, calc(var(--cgf-avail) / 15), 56px);
  line-height: 1.3;
}

/* ── Boards and tiles ────────────────────────────────────────────
   The complaint was specifically that card and tile games came out tiny.
   These are square-ish and live entirely on screen, so they are sized
   against BOTH axes — vmin — and capped by the available height so a
   board can never be taller than the room it is in. */
body.cgc-playing .tile-grid,
body.cgc-playing .cats-grid,
body.cgc-playing .items-pool,
body.cgc-playing .card-grid,
body.cgc-playing .nb-stage {
  width: min(96%, calc(var(--cgf-avail) * 1.25));
  margin-inline: auto;
}
body.cgc-playing .tile-grid > *,
body.cgc-playing .cats-grid > *,
body.cgc-playing .items-pool > * {
  min-height: clamp(56px, calc(var(--cgf-avail) / 7), 150px);
  font-size: clamp(20px, calc(var(--cgf-avail) / 18), 44px);
}
/* n-back's stimulus is a single big glyph — it should fill the stage. */
body.cgc-playing .nb-stim {
  font-size: clamp(56px, calc(var(--cgf-avail) / 4), 220px);
  line-height: 1;
}
body.cgc-playing .nb-btn {
  min-height: clamp(56px, calc(var(--cgf-avail) / 8), 120px);
  font-size: clamp(18px, calc(var(--cgf-avail) / 24), 34px);
}
/* number-memory shows and then takes a digit string. */
body.cgc-playing #numberShow,
body.cgc-playing #recallDigits,
body.cgc-playing #digitInput {
  font-size: clamp(34px, calc(var(--cgf-avail) / 8), 110px);
  letter-spacing: .12em;
  line-height: 1.15;
}

/* ── Tablet gets the bigger end of every ramp ────────────────────
   This audience is on a tablet held at arm's length or resting in a lap,
   which is further away than a phone is ever held. */
@media (min-width: 700px) {
  body.cgc-playing .ans-btn,
  body.cgc-playing .choice-btn,
  body.cgc-playing .opt-btn,
  body.cgc-playing [id^="choice-"],
  body.cgc-playing [id^="ans"],
  body.cgc-playing [id^="ao"] {
    min-height: clamp(64px, calc(var(--cgf-avail) / 8), 132px);
  }
}

/* Children get to grow: a play area that is a flex column will otherwise
   leave its rows at content height and pile the slack at the bottom. */
body.cgc-playing [data-cgf-play] > * { flex: 0 0 auto; }
body.cgc-playing [data-cgf-play] > .grow,
body.cgc-playing [data-cgf-play] > #choices,
body.cgc-playing [data-cgf-play] > #answerGrid { flex: 0 1 auto; }

/* The bottom nav is hidden while playing, so the space reserved for it
   must go too. careiti-nav.css puts 84-92px of padding-bottom on the body
   so content never ends under the fixed bar; during a round that padding
   is 84-92px of nothing, and it was the entire overflow measured after
   this file's first version — the play area was exactly 100dvh minus the
   game bar, and then the page was that plus the nav gap. */
body.cgc-playing { padding-bottom: 0 !important; }

/* ── Residual overflow ───────────────────────────────────────────
   After the play area was sized to the available height, four games
   still ran 16-48px past the bottom. That is the page wrapper's own
   vertical padding and margin, which is correct for a scrolling document
   and is pure waste when the play area is the only thing on screen. */
/* .cgf-anc is every wrapper between the body and the play area, tagged
   by markPlay() as it walks up. Listing the class names instead missed
   .game-wrap on 記憶翻牌 — 30px of overflow from a wrapper nobody had
   thought to name. */
body.cgc-playing .cgf-anc,
body.cgc-playing [data-cgf-play] {
  margin-block: 0 !important;
  padding-block: 0 !important;
}

/* ── A floor under every control in the play area ────────────────
   The typed selectors above cover the controls each game names; they
   cannot cover the ones it does not. reaction's in-play button measured
   40px and 記憶翻牌's 39px on a phone — both under the 44px minimum, both
   missed because they carry no class this file knows about.

   Matching on "a button inside the play area" needs no list. */
body.cgc-playing [data-cgf-play] button,
body.cgc-playing [data-cgf-play] [role="button"] {
  min-height: 48px;
}

/* ── 卡牌／格仔棋盤：兩條軸都用盡 ──────────────────────────────
   `--cgf-cols` / `--cgf-rows` are measured off the rendered grid by
   sizeBoards() in careiti-countdown.js, because the column count changes
   with the level.

   `avail * cols / rows` is the width at which the board exactly fills the
   height available to it; the viewport width is the other bound. Taking
   the smaller means the short axis binds, which is what "fill the screen"
   actually means for something with a fixed aspect ratio.

   The 132px allowance is the in-play HUD (timer, 棄關) that shares the
   column with the board.

   !important because careiti-memory.css already uses it to beat the
   inline `max-width:(cols*68+20)px` that game.html writes per level —
   this has to win against that same inline style. */
body.cgc-playing .card-grid,
body.cgc-playing .tile-grid {
  /* 132px 本來係寫死嘅 HUD 高度估算。而家 --cgf-hud 係量返嚟嘅實數，
     所以呢條式唔會再喺 HUD 變高（大字模式、長機名）嗰陣算多咗高度。
     再減 8px 做安全邊 —— gap 同 padding 唔喺呢條式入面，唔留位就會啱啱好
     爆一兩 px，而「爆一兩 px」同「爆一百 px」對院友嚟講一樣係要碌屏。 */
  width: min(94vw, calc((var(--cgf-avail) - var(--cgf-hud, 132px) - 8px)
                        * var(--cgf-cols, 4) / var(--cgf-rows, 2))) !important;
  max-width: none !important;
  margin-inline: auto !important;
}
