/**
 * Jogo da Velha — folha de estilo.
 *
 * O TABULEIRO É O ELEMENTO PRINCIPAL, e esta folha existe principalmente para garantir isso
 * em telas que vão de 320 px a um monitor largo, em pé e deitado. Todo o resto — o turno, o
 * placar, os botões — foi reduzido ao menor tamanho em que ainda se lê, porque a
 * simplicidade é uma característica do produto e não uma economia de trabalho.
 *
 * COMO O TABULEIRO SE DIMENSIONA. `--board-max` é um `min()` de três limites — uma medida
 * absoluta, uma fração da largura e uma fração da ALTURA —, e é o terceiro que costuma
 * faltar nas folhas que erram isso: sem `vh`, um tabuleiro quadrado com 90% da largura numa
 * tela deitada fica mais alto que a janela e sai por baixo sem nenhum aviso. Os três juntos
 * fazem o tabuleiro ser o maior quadrado que cabe, sempre.
 *
 * A PERGUNTA NÃO É UM MODAL. Ela vive no fluxo, ao lado do tabuleiro quando há largura e
 * abaixo dele quando não há, e o tabuleiro apenas ENCOLHE para abrir espaço (§18). Um modal
 * por cima esconderia o tabuleiro no momento exato em que o jogador precisa lembrar por que
 * escolheu aquela casa — que é a informação que dá sentido à pergunta.
 *
 * COMO O TAMANHO DO TEXTO FUNCIONA. `data-text` no <html> muda a raiz em `font-size`, e o
 * resto da folha é escrito em `rem`. Uma preferência, uma linha, e toda a interface
 * acompanha — inclusive espaçamentos e alturas de botão. E isso sozinho não basta: numa tela
 * estreita o cabeçalho estoura a largura antes de o texto ficar grande de verdade, então
 * todo agrupamento tem `flex-wrap`, todo modal rola no eixo vertical, e as caixas que
 * precisam caber usam `min-width: 0` — sem ele um item de flex se recusa a encolher abaixo
 * do próprio conteúdo e vaza para fora em silêncio, que é o defeito mais difícil de ver numa
 * captura de tela.
 *
 * A ORDEM DAS REGRAS IMPORTA E NÃO É ACIDENTE. `@media` não acrescenta especificidade: uma
 * regra dentro de media query escrita ANTES da regra que ela deveria sobrescrever
 * simplesmente perde, em silêncio, e a folha continua válida. Todo bloco responsivo desta
 * folha fica DEPOIS do bloco que ele ajusta.
 *
 * `[hidden]` PRECISA GANHAR DE `display:flex`. Sem `[hidden]{display:none!important}`,
 * metade da interface fica visível quando o jogo a esconde, porque a regra de layout do
 * componente é mais específica que o atributo.
 *
 * X E O NÃO SE DISTINGUEM POR COR (§29). Eles têm formas diferentes, que é a diferença que
 * funciona para todo mundo; a cor vem por cima como reforço, e em alto contraste ela some
 * por completo sem que o jogo perca nada.
 */

/* ------------------------------------------------------------------ base */
*, *::before, *::after { box-sizing: border-box; }

:root {
  --scale: 1;
  font-size: calc(16px * var(--scale));

  --mark-x: #f5a524;
  --mark-o: #3ecfc0;
  --accent: #6b8afd;
  --accent-soft: #93a9ff;
  --good: #35c46b;
  --bad: #e8604f;

  --bg: #0b1220;
  --bg-deep: #070c16;
  --panel: #141d31;
  --panel-2: #1b2740;
  --line: #2a3855;
  --ink: #eaeffb;
  --ink-dim: #a8b6d4;
  --ink-mute: #7d8dae;
  --shadow: 0 1.25rem 3rem rgba(2, 6, 16, .55);
  --radius: 1rem;
  --radius-lg: 1.5rem;
  /* Alvo de toque. `max()` e não `2.75rem` puro: com "texto pequeno" a raiz encolhe para
     14 px e 2,75 rem viram 38,7 px — abaixo do mínimo de 44 px que qualquer diretriz de
     toque exige. Reduzir o texto é uma preferência de leitura; encolher o botão junto
     transforma uma preferência numa barreira. */
  --tap: max(2.75rem, 44px);
  --speed: .2s;
  --safe-t: env(safe-area-inset-top, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-l: env(safe-area-inset-left, 0px);
  --safe-r: env(safe-area-inset-right, 0px);
}

html[data-text="small"]  { --scale: .88; }
html[data-text="normal"] { --scale: 1; }
html[data-text="large"]  { --scale: 1.18; }
html[data-text="huge"]   { --scale: 1.38; }

html[data-theme="light"] {
  --bg: #f2f5f9;
  --bg-deep: #e4eaf3;
  --panel: #ffffff;
  --panel-2: #f6f8fc;
  --line: #ccd6e6;
  --ink: #101a2e;
  --ink-dim: #46587a;
  --ink-mute: #6b7c9b;
  --mark-x: #c9700a;
  --mark-o: #0f8d84;
  --accent: #3355e0;
  --accent-soft: #4f74f5;
  --shadow: 0 1.25rem 3rem rgba(16, 32, 64, .14);
}

/* Alto contraste: preto e branco puros, bordas sempre visíveis, nada translúcido. */
html[data-contrast="high"] {
  --bg: #000; --bg-deep: #000; --panel: #000; --panel-2: #0a0a0a;
  --line: #fff; --ink: #fff; --ink-dim: #fff; --ink-mute: #e6e6e6;
  --mark-x: #ffd24a; --mark-o: #6cf3e6; --accent: #7fa6ff; --accent-soft: #a8c2ff;
  --good: #58f08c; --bad: #ff8a7a;
  --shadow: none;
}
html[data-contrast="high"][data-theme="light"] {
  --bg: #fff; --bg-deep: #fff; --panel: #fff; --panel-2: #fff;
  --line: #000; --ink: #000; --ink-dim: #000; --ink-mute: #1a1a1a;
  --mark-x: #7a4400; --mark-o: #005f58; --accent: #0032a0; --accent-soft: #0032a0;
  --good: #0a6b2e; --bad: #a01010;
}

html[data-motion="reduced"] *,
html[data-motion="reduced"] *::before,
html[data-motion="reduced"] *::after {
  animation-duration: .001ms !important;
  animation-iteration-count: 1 !important;
  transition-duration: .001ms !important;
}

[hidden] { display: none !important; }

body {
  margin: 0;
  min-height: 100svh;
  background: radial-gradient(120% 100% at 50% 0%, var(--bg) 0%, var(--bg-deep) 100%);
  color: var(--ink);
  font-family: Inter, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  font-size: 1rem;
  line-height: 1.45;
  -webkit-text-size-adjust: 100%;
  /* O tabuleiro é feito de toques repetidos; sem isto o navegador móvel dá zoom no toque
     duplo e o segundo toque numa casa vira uma lente de aumento em vez de uma jogada. */
  touch-action: manipulation;
}

#art-sprite { display: none; }

.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 60;
  background: var(--accent); color: #fff; padding: .6rem 1rem; border-radius: 0 0 var(--radius) 0;
}
.skip-link:focus { left: 0; }

:focus-visible {
  outline: 3px solid var(--accent-soft);
  outline-offset: 2px;
}

h1, h2, h3 { margin: 0; line-height: 1.2; font-weight: 700; }

/* --------------------------------------------------------------- botões */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  min-height: var(--tap); padding: .55rem 1.1rem;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--panel-2); color: var(--ink);
  font: inherit; font-weight: 600; cursor: pointer;
  transition: transform var(--speed), background var(--speed), border-color var(--speed);
}
.btn:hover { background: var(--panel); border-color: var(--accent); }
.btn:active { transform: translateY(1px); }
.btn-primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn-primary:hover { background: var(--accent-soft); border-color: var(--accent-soft); }
.btn-lg { min-height: calc(var(--tap) + .8rem); font-size: 1.05rem; width: 100%; }
.btn-wide { width: 100%; }
.btn-ghost { background: transparent; }

.icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: var(--tap); height: var(--tap); flex: none;
  border: 1px solid transparent; border-radius: .75rem;
  background: transparent; color: var(--ink-dim);
  font-size: 1.15rem; cursor: pointer;
  transition: color var(--speed), background var(--speed);
}
.icon-btn:hover { color: var(--ink); background: var(--panel-2); }

.ico { display: block; }

/* =============================== abertura =============================== */
.screen { min-height: 100svh; }

.setup {
  display: flex; align-items: flex-start; justify-content: center;
  padding: calc(1rem + var(--safe-t)) calc(1rem + var(--safe-r)) calc(1.5rem + var(--safe-b)) calc(1rem + var(--safe-l));
}
.setup-card {
  width: 100%; max-width: 46rem;
  display: flex; flex-direction: column; gap: 1.1rem;
}

.brand { display: flex; align-items: center; gap: .85rem; flex-wrap: wrap; }
.brand-mark { font-size: 2.6rem; line-height: 0; flex: none; }
.brand-text { flex: 1 1 12rem; min-width: 0; }
.brand-text h1 { font-size: clamp(1.35rem, 5vw, 1.9rem); letter-spacing: -.02em; }
.tagline { margin: .15rem 0 0; color: var(--ink-dim); font-size: .92rem; }
.brand-actions { display: flex; gap: .25rem; flex: none; }

.setup-group { display: flex; flex-direction: column; gap: .5rem; min-width: 0; }
/* Os títulos de grupo do menu: pequenos, em caixa alta, com o ícone do assunto à esquerda.
   O ícone não é enfeite — com sete grupos na tela, é ele que deixa "Idiomas", "Como treinar"
   e "Dificuldade" distinguíveis num relance, antes de qualquer leitura. */
.setup-group > h2, .setup-head {
  display: flex; align-items: center; gap: .4rem;
  margin: 0;
  font-size: .82rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--ink-mute);
}
.setup-head { margin-bottom: -.35rem; }
.setup-group > h2 svg, .setup-head svg { font-size: 1.05em; opacity: .9; }

/**
 * O PAR DE IDIOMAS É UMA GRADE DE DUAS LINHAS, e a seta mora na segunda.
 *
 * Ela aponta de um conjunto de botões para o outro, então precisa se alinhar ao meio DOS
 * BOTÕES — não ao meio do bloco, que inclui o título acima deles. Isso já foi resolvido
 * uma vez com `margin-top: 1.6rem`, um número escolhido a olho para descontar a altura do
 * título: ele acertava no tamanho de texto normal e errava em "muito grande", porque o
 * título cresce e a margem não.
 *
 * Com a grade não há número nenhum. Títulos na linha 1, botões na linha 2, seta na linha 2:
 * ela fica alinhada por construção, em qualquer tamanho de texto e em qualquer idioma —
 * inclusive quando "Quero aprender" quebra em duas linhas e "Já conheço" não.
 *
 * `display: contents` dissolve o agrupamento para que os filhos entrem direto na grade. Os
 * `.setup-group` daqui são divs sem semântica, então não há nada na árvore de
 * acessibilidade para se perder no caminho.
 */
.lang-pair {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  grid-template-rows: auto auto;
  gap: .5rem .75rem;
  align-items: center;
}
.lang-pair > .setup-group { display: contents; }
.lang-pair > .setup-group:first-of-type > h2       { grid-area: 1 / 1; }
.lang-pair > .setup-group:first-of-type > .pill-row { grid-area: 2 / 1; }
.lang-arrow                                         { grid-area: 2 / 2; color: var(--ink-mute); font-size: 1.1rem; }
.lang-pair > .setup-group:last-of-type > h2        { grid-area: 1 / 3; }
.lang-pair > .setup-group:last-of-type > .pill-row  { grid-area: 2 / 3; }

/**
 * COM TEXTO GRANDE NUMA TELA ESTREITA, OS DOIS IDIOMAS EMPILHAM.
 *
 * Lado a lado, cada coluna recebe metade de 320 px. "Português" a 22 px pede uns 155 px com
 * o preenchimento do botão, e duas colunas dessas mais a seta passam dos 370: a página
 * ganhava 55 px de rolagem horizontal, que é o defeito que esta folha inteira existe para
 * não ter. Encolher a pílula não é opção — ela é um alvo de toque.
 *
 * Empilhados, cada idioma tem a largura inteira. A seta gira 90 graus e continua apontando
 * de um para o outro: ela é o que diz que a relação entre os dois blocos é uma direção, e
 * escondê-la deixaria dois grupos soltos.
 *
 * A medida é em PIXELS de propósito. Em `rem` ela acompanharia a escala do texto e
 * empilharia também no tamanho normal, onde os dois cabem muito bem lado a lado.
 */
@media (max-width: 430px) {
  html:is([data-text="large"], [data-text="huge"]) .lang-pair {
    grid-template-columns: 1fr;
    grid-template-rows: repeat(5, auto);
    gap: .35rem;
  }
  html:is([data-text="large"], [data-text="huge"]) .lang-pair > .setup-group:first-of-type > h2 { grid-area: 1 / 1; }
  html:is([data-text="large"], [data-text="huge"]) .lang-pair > .setup-group:first-of-type > .pill-row { grid-area: 2 / 1; }
  html:is([data-text="large"], [data-text="huge"]) .lang-arrow {
    grid-area: 3 / 1; justify-self: center;
    transform: rotate(90deg);
  }
  html:is([data-text="large"], [data-text="huge"]) .lang-pair > .setup-group:last-of-type > h2 { grid-area: 4 / 1; margin-top: .25rem; }
  html:is([data-text="large"], [data-text="huge"]) .lang-pair > .setup-group:last-of-type > .pill-row { grid-area: 5 / 1; }
}

.pill-row { display: flex; gap: .4rem; flex-wrap: wrap; }
.pill {
  flex: 1 1 auto; min-width: 4.5rem; min-height: var(--tap);
  display: inline-flex; align-items: center; justify-content: center;
  padding: .4rem .8rem; border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--panel); color: var(--ink-dim);
  font: inherit; font-weight: 600; cursor: pointer;
  transition: color var(--speed), border-color var(--speed), background var(--speed);
}
.pill:hover { color: var(--ink); }
.pill[aria-checked="true"] {
  color: var(--ink); border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 18%, var(--panel));
}

.choice-grid { display: grid; gap: .45rem; grid-template-columns: 1fr; }
.choice {
  display: flex; flex-direction: column; gap: .1rem; text-align: left;
  min-height: var(--tap); padding: .6rem .85rem;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--panel); color: var(--ink);
  font: inherit; cursor: pointer;
  transition: border-color var(--speed), background var(--speed);
}
.choice:hover { border-color: var(--accent-soft); }
.choice[aria-checked="true"] {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 15%, var(--panel));
}
.choice strong { font-weight: 700; font-size: .98rem; }
.choice span { color: var(--ink-mute); font-size: .82rem; line-height: 1.3; }
.choice-grid.tight .choice { padding: .5rem .75rem; }

.two-cols { display: grid; gap: 1.1rem; grid-template-columns: 1fr; }

/* Um campo do menu: rótulo em cima, controle embaixo, ocupando a largura toda. O seletor
   herda a altura de toque de `--tap` como qualquer outro controle do jogo. */
.menu-field { display: flex; flex-direction: column; gap: .3rem; min-width: 0; }
.menu-field > label { font-size: .9rem; font-weight: 600; color: var(--ink-dim); }
.menu-field > select { font-weight: 600; }

/* Os dois atalhos do rodapé do menu. Lado a lado quando cabem, empilhados quando não. */
.setup-links { display: flex; gap: .5rem; flex-wrap: wrap; }
.setup-links .btn { flex: 1 1 10rem; }

.warn {
  display: flex; align-items: center; gap: .5rem; margin: 0;
  color: var(--bad); font-size: .9rem; font-weight: 600;
}

.setup-progress { margin: 0; color: var(--ink-mute); font-size: .85rem; text-align: center; }

@media (min-width: 34rem) {
  .choice-grid { grid-template-columns: repeat(3, 1fr); }
  .two-cols { grid-template-columns: 1fr 1fr; }

  /**
   * AS DUAS DIFICULDADES FICAM EM LINHAS, e não em três colunas como os modos de jogo.
   *
   * Elas dividem a largura da tela entre si, então cada cartão receberia um sexto da
   * página: "Joga perfeito. O melhor resultado possível é o empate" vira cinco linhas de
   * texto quebrado, e a explicação que existe justamente para o jogador ESCOLHER passa a
   * custar mais atenção do que a escolha. Em linha, o rótulo fica à esquerda e a explicação
   * corre ao lado, numa linha só.
   */
  .choice-grid.tight { grid-template-columns: 1fr; }
  .choice-grid.tight .choice { flex-direction: row; align-items: baseline; gap: .55rem; }
  .choice-grid.tight .choice strong { flex: none; min-width: 4.5rem; }
  .choice-grid.tight .choice span { flex: 1 1 auto; min-width: 0; }
}

/* ================================= jogo ================================= */
.play {
  display: flex; flex-direction: column;
  height: 100svh;
  padding: calc(.4rem + var(--safe-t)) calc(.6rem + var(--safe-r)) calc(.5rem + var(--safe-b)) calc(.6rem + var(--safe-l));
  gap: .35rem;
  overflow: hidden;
}

.topbar { display: flex; align-items: center; gap: .3rem; flex: none; }
.topbar-right { display: flex; gap: .1rem; margin-left: auto; }
.round-line {
  margin: 0; min-width: 0; flex: 1 1 auto; text-align: center;
  color: var(--ink-mute); font-size: .82rem; font-weight: 600;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/**
 * Com texto grande numa tela estreita, os quatro botões do cabeçalho não deixam espaço para
 * esta linha, e ela vira "V…" — um rótulo truncado a um caractere não informa nada e ainda
 * parece defeito. Some por inteiro: o que ela diz ("Você é X", "Partida 2 de 3") também
 * está na linha do turno logo abaixo e no placar logo acima do rodapé.
 *
 * A medida é em px de propósito. Em `rem` ela acompanharia a escala do texto e esconderia
 * a linha até com texto normal, que é o contrário do que se quer.
 */
@media (max-width: 400px) {
  html[data-text="large"] .round-line,
  html[data-text="huge"] .round-line { display: none; }
}

.turn-line {
  margin: 0; flex: none; text-align: center;
  font-size: clamp(1rem, 4.2vw, 1.25rem); font-weight: 700;
  display: flex; align-items: center; justify-content: center; gap: .5rem;
  min-height: 1.9rem;
}
.turn-line .turn-mark { display: inline-flex; width: 1.15em; height: 1.15em; flex: none; }
.turn-line .turn-mark svg { width: 100%; height: 100%; }
.turn-line .turn-mark[data-mark="X"] { color: var(--mark-x); }
.turn-line .turn-mark[data-mark="O"] { color: var(--mark-o); }
.turn-line[data-who="cpu"] .turn-text { color: var(--ink-dim); }

/* ------------------------------------------------------------ o tabuleiro */
/**
 * A ÁREA QUE ROLA É ESTA, E É A ÚNICA.
 *
 * O cabeçalho, a linha do turno e o placar ficam presos; o tabuleiro e a pergunta rolam
 * juntos quando não couberem. Isso acontece de verdade e não é hipótese: num celular em pé,
 * três alternativas que são FRASES inteiras, mais o quadro que mostra a resposta certa
 * depois de um erro, passam da altura da tela — e passam ainda mais com "texto muito
 * grande". A alternativa seria encolher o tabuleiro até ele deixar de ser o elemento
 * principal, ou cortar a explicação, que é justamente a parte que ensina.
 *
 * `overscroll-behavior: contain` impede que o rolar aqui dentro puxe a página inteira e
 * dispare o "atualizar puxando" do navegador móvel no meio de uma pergunta.
 */
.stage {
  flex: 1 1 auto; min-height: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: .75rem;
  overflow-y: auto; overscroll-behavior: contain;
  scrollbar-width: thin;
}
/* O tabuleiro não é espremido pelo irmão: ele tem o tamanho que `--board-max` diz, e o que
   não couber vira rolagem. Sem isto, uma pergunta comprida achataria o tabuleiro num
   retângulo — e `aspect-ratio` não protege contra um pai de flex encolhendo o item. */
.board-wrap { flex: none; }

.board-wrap {
  --board-max: min(30rem, 92vw, 58svh);
  display: flex; align-items: center; justify-content: center;
  width: 100%; min-height: 0;
  transition: transform var(--speed);
}
/* Perguntando: o tabuleiro cede espaço em vez de sumir (§18). */
.stage[data-phase="ask"] .board-wrap { --board-max: min(19rem, 62vw, 32svh); }
/* Fim de rodada: cede MENOS que na pergunta. Aqui ele é o assunto — a linha vencedora
   acesa é o que a barra está comentando —, então só encolhe o necessário para a barra
   caber junto na tela. */
.stage[data-phase="round"] .board-wrap { --board-max: min(24rem, 80vw, 42svh); }

.board {
  width: var(--board-max); height: var(--board-max);
  display: grid; grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(3, 1fr);
  gap: clamp(.25rem, 1.4vw, .5rem);
  padding: clamp(.25rem, 1.4vw, .5rem);
  background: var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
}

.cell {
  position: relative;
  display: flex; align-items: center; justify-content: center;
  padding: 0; border: none; cursor: pointer;
  background: var(--panel);
  border-radius: calc(var(--radius) * .85);
  color: var(--ink);
  transition: background var(--speed), box-shadow var(--speed), transform var(--speed);
}
.cell:first-child { border-top-left-radius: calc(var(--radius-lg) - .3rem); }
.cell:nth-child(3) { border-top-right-radius: calc(var(--radius-lg) - .3rem); }
.cell:nth-child(7) { border-bottom-left-radius: calc(var(--radius-lg) - .3rem); }
.cell:last-child { border-bottom-right-radius: calc(var(--radius-lg) - .3rem); }

.cell[data-free="yes"]:hover { background: var(--panel-2); }
.cell[data-free="yes"]:active { transform: scale(.97); }
/* Casa ocupada usa `aria-disabled`, e não `disabled`: um botão desativado sai da ordem de
   foco, e sair da ordem de foco quebra a navegação por setas — o jogador que atravessa o
   tabuleiro com o teclado ficaria preso na primeira casa marcada. Ela continua alcançável
   e legível; só não faz nada. */
.cell[aria-disabled="true"] { cursor: default; }

/* A casa reservada: escolhida, ainda de ninguém. O anel pulsante é a única animação
   contínua do jogo, e existe porque essa casa É a aposta do jogador. */
.cell[data-pending="yes"] {
  background: color-mix(in srgb, var(--accent) 22%, var(--panel));
  box-shadow: inset 0 0 0 3px var(--accent);
  animation: pending 1.6s ease-in-out infinite;
}
@keyframes pending {
  0%, 100% { box-shadow: inset 0 0 0 3px var(--accent); }
  50% { box-shadow: inset 0 0 0 5px var(--accent-soft); }
}
/**
 * No alto contraste o preenchimento translúcido não existe — `color-mix` com um painel
 * preto devolve um azul quase preto, e a casa reservada, que é a APOSTA do jogador, some
 * dentro do tabuleiro. Aqui ela se anuncia pela borda, que é a única coisa que o modo de
 * alto contraste garante que se vê.
 */
html[data-contrast="high"] .cell[data-pending="yes"] {
  background: var(--panel);
  box-shadow: inset 0 0 0 6px var(--accent);
}
html[data-contrast="high"] .cell[data-pending="yes"]::after {
  content: ''; position: absolute; inset: 22%;
  border: 3px dashed var(--accent); border-radius: .5rem;
}
html[data-contrast="high"] .cell[data-win="yes"] {
  background: var(--panel);
  box-shadow: inset 0 0 0 6px var(--good);
}

/* O X e o O são desenhados uma vez e reaproveitados em três tamanhos — na casa, no
   indicador de turno e na tela de resultado. As regras de traço são GENÉRICAS de propósito:
   presas a `.cell`, o mesmo SVG apareceria como uma mancha preta preenchida assim que fosse
   usado fora do tabuleiro, que é o defeito clássico de estilizar um símbolo pelo lugar em
   que ele nasceu em vez de pelo que ele é. A cor vem de `currentColor`, então quem insere a
   marca escolhe a cor no contêiner. */
svg.mark { overflow: visible; }
svg.mark path, svg.mark circle {
  fill: none; stroke: currentColor;
  stroke-linecap: round; stroke-linejoin: round; stroke-width: 11;
}
.cell svg.mark { width: 62%; height: 62%; }
.cell[data-mark="X"] { color: var(--mark-x); }
.cell[data-mark="O"] { color: var(--mark-o); }

/* A marca é desenhada, não aparece pronta: o traço nasce do começo ao fim em 260 ms. É a
   animação que faz uma jogada parecer um gesto em vez de uma troca de atributo. */
.cell[data-mark] svg.mark path, .cell[data-mark] svg.mark circle {
  stroke-dasharray: var(--len, 200);
  stroke-dashoffset: var(--len, 200);
  animation: draw .26s ease-out forwards;
}
.cell[data-mark] svg.mark :nth-child(2) { animation-delay: .11s; }
@keyframes draw { to { stroke-dashoffset: 0; } }

/* A linha vencedora. Cor E brilho E escala: quem não distingue as cores vê o tamanho. */
.cell[data-win="yes"] {
  background: color-mix(in srgb, var(--good) 26%, var(--panel));
  box-shadow: inset 0 0 0 3px var(--good);
  animation: pop .34s ease-out;
}
@keyframes pop { 0% { transform: scale(1); } 45% { transform: scale(1.07); } 100% { transform: scale(1); } }

/* ------------------------------------------------------------- a pergunta */
.ask {
  width: 100%; max-width: 32rem; min-width: 0;
  display: flex; flex-direction: column; gap: .55rem;
  padding: .8rem;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  animation: rise .22s ease-out;
}
@keyframes rise { from { opacity: 0; transform: translateY(.6rem); } to { opacity: 1; transform: none; } }

.ask-head { display: flex; align-items: center; gap: .5rem; }
.ask-for {
  margin: 0; flex: 1 1 auto; min-width: 0;
  color: var(--ink-mute); font-size: .8rem; font-weight: 700;
  letter-spacing: .05em; text-transform: uppercase;
}
/* O X de desistir da casa É DISCRETO E GRANDE ao mesmo tempo: o desenho tem 1rem, a área
   de toque tem `--tap` inteiro. Um botão de 32 px numa tela sensível é um botão que a
   pessoa erra — e errá-lo aqui significa tocar no tabuleiro por trás. */
/**
 * O X DE DESISTIR DA CASA: desenho pequeno, ALVO GRANDE — e sem uma margem negativa sequer.
 *
 * O botão precisa de duas coisas que brigam entre si. Visualmente ele tem de ser discreto,
 * porque é uma saída e não uma ação; para o dedo ele tem de ter 44 px, porque errá-lo numa
 * tela sensível significa tocar no tabuleiro por trás.
 *
 * A primeira tentativa foi puxá-lo com margem negativa, e margem negativa é sempre a mesma
 * história: ela resolveu a altura e criou um vazamento lateral em tela deitada, porque o
 * elemento passou a ocupar menos espaço do que desenha. Aqui o desenho tem 2 rem e ocupa
 * 2 rem — o layout vê exatamente o que a tela mostra — e um `::after` invisível estende o
 * ALVO até `--tap` a partir do centro. Ele não participa do layout, não pode transbordar
 * nada, e o dedo acerta.
 */
.ask-cancel { width: 2rem; height: 2rem; font-size: 1rem; position: relative; }
.ask-cancel::after {
  content: '';
  position: absolute; left: 50%; top: 50%;
  width: var(--tap); height: var(--tap);
  transform: translate(-50%, -50%);
}

.timer { height: .3rem; border-radius: 999px; background: var(--panel-2); overflow: hidden; flex: none; }
.timer i { display: block; height: 100%; width: 100%; background: var(--accent); transform-origin: left; }
.timer[data-low="yes"] i { background: var(--bad); }

.ask-title { font-size: 1.05rem; line-height: 1.25; }

.ask-prompt { display: flex; align-items: center; justify-content: center; min-height: 0; }
.prompt-word {
  font-size: clamp(1.4rem, 6.5vw, 2rem); font-weight: 800; letter-spacing: -.02em;
  text-align: center; overflow-wrap: anywhere;
}
.prompt-sentence {
  font-size: clamp(1rem, 4vw, 1.2rem); font-weight: 600; text-align: center;
  color: var(--ink); overflow-wrap: anywhere;
}
/**
 * A LACUNA É UM TRAÇO, e não uma sequência de sublinhados.
 *
 * `___` é texto: ele quebra linha no meio, some numa tela estreita e leva o ponto final
 * junto para a linha seguinte. Um `inline-block` com borda inferior tem largura própria,
 * não se parte, e continua parecendo o espaço onde falta uma palavra.
 */
.prompt-sentence .gap {
  display: inline-block; width: 3.5em; margin: 0 .15em;
  vertical-align: baseline; white-space: nowrap;
  border-bottom: 2px solid var(--accent-soft);
  color: transparent;
}
.prompt-art { width: clamp(4.5rem, 22vw, 7rem); height: clamp(4.5rem, 22vw, 7rem); }
.prompt-audio {
  display: inline-flex; align-items: center; gap: .5rem;
  min-height: var(--tap); padding: .5rem 1.1rem;
  border: 1px solid var(--line); border-radius: 999px;
  background: var(--panel-2); color: var(--ink); font: inherit; font-weight: 600; cursor: pointer;
}
.prompt-audio[data-playing="yes"] { border-color: var(--accent); color: var(--accent-soft); }

.ask-hint {
  margin: 0; text-align: center; color: var(--ink-mute);
  font-size: .95rem; font-weight: 600; letter-spacing: .18em;
}

.options { display: grid; gap: .4rem; grid-template-columns: 1fr; }
.opt {
  display: flex; align-items: center; justify-content: center; gap: .5rem;
  min-height: calc(var(--tap) + .3rem); padding: .5rem .8rem;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--panel-2); color: var(--ink);
  font: inherit; font-size: 1.02rem; font-weight: 600; cursor: pointer;
  text-align: center; overflow-wrap: anywhere;
  transition: border-color var(--speed), background var(--speed), transform var(--speed);
}
.opt:hover:not(:disabled) { border-color: var(--accent); }
.opt:active:not(:disabled) { transform: translateY(1px); }
.opt svg.art { width: 2.6rem; height: 2.6rem; flex: none; }
.opt.is-art { min-height: 4.4rem; }
/* Certo e errado nunca são SÓ cor: entra um ícone e o peso muda (§29). */
.opt[data-state="right"] { border-color: var(--good); background: color-mix(in srgb, var(--good) 22%, var(--panel-2)); }
.opt[data-state="wrong"] { border-color: var(--bad); background: color-mix(in srgb, var(--bad) 20%, var(--panel-2)); }
.opt[data-state] .opt-badge { display: inline-flex; }
.opt-badge { display: none; font-size: 1.1rem; flex: none; }
.opt[data-state="right"] .opt-badge { color: var(--good); }
.opt[data-state="wrong"] .opt-badge { color: var(--bad); }
.opt:disabled { cursor: default; opacity: .75; }
.opt[data-state] { opacity: 1; }
/* Qual número está soando agora, na modalidade "palavra → pronúncia". */
.opt[data-playing="yes"] { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 20%, var(--panel-2)); }

.feedback {
  display: flex; flex-direction: column; align-items: center; gap: .2rem;
  padding: .5rem; border-radius: var(--radius);
  background: var(--panel-2); text-align: center;
  animation: rise .18s ease-out;
}
.feedback[data-kind="right"] { color: var(--good); }
.feedback[data-kind="wrong"] { color: var(--bad); }
.feedback .fb-line { display: flex; align-items: center; gap: .4rem; font-weight: 700; }
.feedback .fb-answer { color: var(--ink); font-weight: 700; font-size: 1.05rem; }
.feedback .fb-note { color: var(--ink-mute); font-size: .82rem; font-weight: 600; }

/* --------------------------------------------------------------- placar */
.scoreline {
  flex: none; display: flex; align-items: center; justify-content: center; gap: .6rem;
  flex-wrap: wrap; min-height: 1.6rem;
  color: var(--ink-mute); font-size: .85rem; font-weight: 600;
}
.score-side { display: inline-flex; align-items: center; gap: .35rem; }
.score-side svg { width: .95em; height: .95em; }
.score-side[data-mark="X"] { color: var(--mark-x); }
.score-side[data-mark="O"] { color: var(--mark-o); }
.score-side b { color: var(--ink); font-size: 1.05rem; }
.score-dots { display: inline-flex; gap: .2rem; }
.score-dot { width: .45rem; height: .45rem; border-radius: 50%; background: var(--line); }
.score-dot[data-won="X"] { background: var(--mark-x); }
.score-dot[data-won="O"] { background: var(--mark-o); }
.score-dot[data-won="draw"] { background: var(--ink-mute); }

/* --------------------------------------------- deitado e telas com largura */
@media (min-width: 52rem) and (min-height: 26rem) {
  .stage { flex-direction: row; align-items: center; justify-content: center; gap: 1.5rem; }
  .board-wrap { --board-max: min(38rem, 52vw, 78svh); width: auto; }
  /* Deitado, o tabuleiro quase não encolhe: a pergunta ganhou uma COLUNA, e não um pedaço
     da altura. O pouco que ele cede é só para a linha do turno e o placar respirarem. */
  .stage[data-phase="ask"] .board-wrap { --board-max: min(34rem, 44vw, 72svh); }
  .stage[data-phase="round"] .board-wrap { --board-max: min(30rem, 44vw, 62svh); }
  .ask { max-width: 26rem; flex: 0 1 26rem; }
  .options { grid-template-columns: 1fr; }
}

/* Deitado e baixo — o celular na horizontal. Aqui a altura é o recurso escasso: o
   tabuleiro vai para o lado da pergunta e as sobras de cima e de baixo encolhem. */
@media (orientation: landscape) and (max-height: 30rem) {
  .stage { flex-direction: row; gap: .75rem; }
  .board-wrap { --board-max: min(88svh, 46vw); width: auto; }
  .stage[data-phase="ask"] .board-wrap { --board-max: min(84svh, 34vw); }
  /* Deitado e baixo é onde a barra mais aperta: a altura é o recurso escasso e ela é uma
     faixa horizontal. O tabuleiro encolhe de verdade aqui, e continua inteiro na tela. */
  .stage[data-phase="round"] .board-wrap { --board-max: min(52svh, 34vw); }
  .ask { max-width: 24rem; flex: 1 1 20rem; padding: .55rem; gap: .35rem; }
  .ask-title { font-size: .95rem; }
  .prompt-word { font-size: clamp(1.1rem, 3.4vw, 1.5rem); }
  .prompt-art { width: 3.6rem; height: 3.6rem; }
  .opt { min-height: var(--tap); font-size: .95rem; }
  .turn-line { font-size: .95rem; min-height: 1.4rem; }
  .scoreline { font-size: .78rem; min-height: 1.2rem; }
}

/* Quatro alternativas curtas cabem em duas colunas assim que houver largura. */
@media (min-width: 26rem) {
  .options[data-cols="2"] { grid-template-columns: 1fr 1fr; }
}

/* ================================ modais ================================ */
.modal-backdrop {
  position: fixed; inset: 0; z-index: 50;
  display: flex; align-items: center; justify-content: center;
  padding: calc(1rem + var(--safe-t)) calc(1rem + var(--safe-r)) calc(1rem + var(--safe-b)) calc(1rem + var(--safe-l));
  background: rgba(4, 8, 18, .72);
  backdrop-filter: blur(2px);
  animation: fade .18s ease-out;
}
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }

.modal {
  width: 100%; max-width: 32rem; max-height: 100%;
  display: flex; flex-direction: column; gap: .8rem;
  padding: 1.1rem;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius-lg); box-shadow: var(--shadow);
  overflow-y: auto;
  animation: rise .2s ease-out;
}
/**
 * A BARRA DE ROLAGEM, feita para esta interface.
 *
 * A do navegador é uma coluna clara de 15 px que atravessa o painel inteiro: num modal
 * escuro ela é a coisa mais luminosa da tela, e chama mais atenção do que qualquer ajuste
 * que esteja ao lado dela.
 *
 * O truque das três linhas abaixo é a borda transparente com `background-clip: padding-box`:
 * o thumb OCUPA 11 px, que é o que o ponteiro precisa acertar, e APARECE com 5, que é o que
 * a tela precisa. Fina para o olho, grossa para o mouse, sem escolher entre as duas.
 *
 * `scrollbar-color` cobre o Firefox, que não tem os pseudoelementos. Onde nenhum dos dois
 * existir, sobra a barra do sistema — que funciona, só não combina. No toque não muda nada:
 * o gesto continua sendo o gesto.
 */
.modal, .stage, .modal-body {
  scrollbar-width: thin;
  scrollbar-color: var(--line) transparent;
}
.modal::-webkit-scrollbar,
.stage::-webkit-scrollbar,
.modal-body::-webkit-scrollbar { width: 11px; height: 11px; }
.modal::-webkit-scrollbar-track,
.stage::-webkit-scrollbar-track,
.modal-body::-webkit-scrollbar-track { background: transparent; }
.modal::-webkit-scrollbar-thumb,
.stage::-webkit-scrollbar-thumb,
.modal-body::-webkit-scrollbar-thumb {
  background: var(--line);
  border: 3px solid transparent;
  background-clip: padding-box;
  border-radius: 999px;
}
.modal::-webkit-scrollbar-thumb:hover,
.stage::-webkit-scrollbar-thumb:hover,
.modal-body::-webkit-scrollbar-thumb:hover {
  background: var(--ink-mute);
  background-clip: padding-box;
}
/* Em alto contraste a borda transparente comeria a única cor que resta: o thumb fica
   sólido e branco, que é o que esse modo promete. */
html[data-contrast="high"] .modal::-webkit-scrollbar-thumb,
html[data-contrast="high"] .stage::-webkit-scrollbar-thumb,
html[data-contrast="high"] .modal-body::-webkit-scrollbar-thumb {
  background: var(--line); border-width: 2px;
}

/**
 * O CABEÇALHO DO MODAL FICA PARADO enquanto o corpo rola.
 *
 * Ajustes e "Como se joga" são painéis longos, e o botão de fechar estava no topo do
 * conteúdo: rolar até o fim significava rolar de volta até em cima para sair. Grudado, ele
 * está sempre a um toque, que é a promessa de acessibilidade que o painel precisa cumprir.
 */
.modal-head {
  display: flex; align-items: center; gap: .5rem;
  position: sticky; top: calc(-1.1rem - 1px); z-index: 2;
  margin: -1.1rem -1.1rem 0;
  padding: 1.1rem 1.1rem .7rem;
  background: var(--panel);
  border-bottom: 1px solid var(--line);
}
.modal-head h2 { flex: 1 1 auto; min-width: 0; font-size: 1.2rem; }
.modal-body { display: flex; flex-direction: column; gap: 1rem; min-width: 0; }
.modal-actions { display: flex; gap: .5rem; flex-wrap: wrap; }
/* `nowrap` com base de 10rem, e não uma base menor com o texto quebrando: "Próxima partida"
   em duas linhas dentro de um botão parece um botão apertado, e o remédio certo é a LINHA
   quebrar (o `flex-wrap` acima empilha os dois) e não a palavra. */
.modal-actions .btn { flex: 1 1 10rem; white-space: nowrap; }

.modal-result { text-align: center; align-items: center; }
.result-mark { display: inline-flex; width: 3.5rem; height: 3.5rem; }
.result-mark svg { width: 100%; height: 100%; }
.result-mark[data-mark="X"] { color: var(--mark-x); }
.result-mark[data-mark="O"] { color: var(--mark-o); }
.result-mark[data-mark="draw"] { color: var(--ink-mute); }
.modal-result h2 { font-size: clamp(1.3rem, 6vw, 1.7rem); }
.result-sub { margin: 0; color: var(--ink-dim); font-size: .92rem; }
.result-score { display: flex; align-items: center; justify-content: center; gap: 1rem; flex-wrap: wrap; }
.result-score .rs {
  display: flex; flex-direction: column; align-items: center; min-width: 4rem;
  padding: .5rem .8rem; border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--panel-2);
}
.result-score .rs b { font-size: 1.5rem; }
.result-score .rs span { color: var(--ink-mute); font-size: .78rem; font-weight: 600; }
.result-words { width: 100%; display: flex; flex-direction: column; gap: .35rem; }
.result-words h3 { font-size: .78rem; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-mute); }
.word-chips { display: flex; flex-wrap: wrap; gap: .3rem; justify-content: center; }
.word-chip {
  display: inline-flex; align-items: center; gap: .35rem;
  padding: .25rem .6rem; border-radius: 999px;
  border: 1px solid var(--line); background: var(--panel-2);
  font-size: .85rem; font-weight: 600;
}
.word-chip[data-ok="no"] { border-color: color-mix(in srgb, var(--bad) 55%, var(--line)); }
.word-chip em { font-style: normal; color: var(--ink-mute); font-weight: 500; }

.modal-confirm { max-width: 24rem; text-align: center; }
.modal-confirm p { margin: 0; font-weight: 600; }

/* ---------------------------------------------------------- ajustes/stats */
.set-section { display: flex; flex-direction: column; gap: .55rem; min-width: 0; }
/* Uma linha fina entre seções. Sem ela, quatro grupos de controles parecidos viram uma
   lista só, e a pessoa perde a noção de onde um assunto termina e o outro começa. */
.set-section + .set-section { border-top: 1px solid var(--line); padding-top: 1rem; }
.set-section > h3 {
  font-size: .78rem; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-mute);
  display: flex; align-items: center; gap: .4rem;
}
.set-row { display: flex; flex-direction: column; gap: .3rem; min-width: 0; }
.set-row > label, .set-label { font-size: .9rem; font-weight: 600; color: var(--ink-dim); }
.set-note { margin: 0; color: var(--ink-mute); font-size: .8rem; }
.set-toggle {
  display: flex; align-items: center; justify-content: space-between; gap: .75rem;
  min-height: var(--tap); padding: .35rem .1rem; cursor: pointer;
}
.set-toggle input { width: 1.25rem; height: 1.25rem; flex: none; accent-color: var(--accent); }
select, input[type="range"] {
  width: 100%; min-height: var(--tap); font: inherit;
  color: var(--ink); background: var(--panel-2);
  border: 1px solid var(--line); border-radius: var(--radius); padding: .35rem .6rem;
}
input[type="range"] { padding: 0; accent-color: var(--accent); background: transparent; border: none; }

.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(6.5rem, 1fr)); gap: .5rem; }
.stat {
  display: flex; flex-direction: column; gap: .1rem; padding: .6rem .7rem;
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--panel-2);
}
.stat b { font-size: 1.35rem; }
.stat span { color: var(--ink-mute); font-size: .78rem; font-weight: 600; }

.howto-list { margin: 0; padding-left: 1.2rem; display: flex; flex-direction: column; gap: .45rem; }
.howto-list li { font-size: .95rem; }
.howto-keys {
  margin: 0; display: flex; align-items: center; gap: .5rem;
  color: var(--ink-mute); font-size: .85rem; font-weight: 600;
}

/* ==================================================== o quadro da resposta */
/**
 * O PAR — "house = casa" — é a linha que ensina, e por isso é a maior do quadro.
 * O idioma estudado em negrito, o conhecido em cinza: a hierarquia diz sozinha qual dos
 * dois é a palavra nova.
 */
.fb-answer {
  margin: 0; display: flex; align-items: baseline; justify-content: center;
  flex-wrap: wrap; gap: .1rem .45rem; text-align: center;
}
.fb-label { color: var(--ink-mute); font-size: .8rem; font-weight: 600; width: 100%; }
.fb-answer b { color: var(--ink); font-size: 1.15rem; font-weight: 800; overflow-wrap: anywhere; }
.fb-eq { color: var(--ink-mute); font-weight: 600; }
.fb-base { color: var(--ink-dim); font-size: 1.02rem; font-weight: 600; overflow-wrap: anywhere; }

.fb-listen { align-self: center; }
.fb-continue { align-self: stretch; margin-top: .1rem; }

/**
 * A BARRA DE ESPERA. Ela encolhe da direita para a esquerda enquanto o quadro está aberto,
 * e some no modo "eu decido".
 *
 * Tem 3 px e a cor do texto apagado de propósito: o briefing pede um indicador
 * "extremamente discreto", e um segundo cronômetro grande na tela competiria com a palavra
 * que a pessoa está tentando ler — que é exatamente o que este quadro existe para evitar.
 * Quem olha vê; quem não olha não perde nada, porque o tempo dela é o mesmo que o jogo já
 * anunciou nos ajustes.
 */
.fb-wait {
  /* `align-self: stretch` porque o painel centraliza os filhos: uma barra sem conteúdo
     encolhe para largura zero e some sem deixar rastro — existe no DOM, mede 3×0 e nunca
     aparece. É o tipo de defeito que só uma régua encontra. */
  align-self: stretch; width: 100%;
  height: 3px; border-radius: 999px; background: var(--line); overflow: hidden;
  margin-top: .15rem;
}
.fb-wait i { display: block; height: 100%; width: 100%; background: var(--ink-mute); transform-origin: left; }

/* A marca-fantasma: a casa já é sua, mas ainda não foi aplicada. */
.cell[data-preview] { box-shadow: inset 0 0 0 3px var(--accent); }
.cell[data-preview] svg.mark { width: 62%; height: 62%; opacity: .5; }
.cell[data-preview="X"] { color: var(--mark-x); }
.cell[data-preview="O"] { color: var(--mark-o); }
html[data-contrast="high"] .cell[data-preview] svg.mark { opacity: .75; }

/* ========================================================= tutorial guiado */
/**
 * A DICA DO TUTORIAL não é um véu por cima do jogo — é uma barra no fluxo, entre o
 * tabuleiro e o placar. O jogo inteiro continua visível e clicável; quem já entendeu joga
 * por cima dela e ela vai sumindo sozinha (§18).
 */
.coach {
  flex: none; display: flex; align-items: center; gap: .6rem;
  padding: .5rem .75rem;
  border: 1px solid var(--accent); border-radius: var(--radius);
  background: color-mix(in srgb, var(--accent) 14%, var(--panel));
  animation: rise .22s ease-out;
}
.coach-text { margin: 0; flex: 1 1 auto; min-width: 0; font-size: .92rem; font-weight: 600; }
.coach-skip {
  flex: none; min-height: var(--tap); padding: 0 .8rem;
  border: 1px solid var(--line); border-radius: .7rem;
  background: var(--panel); color: var(--ink-dim);
  font: inherit; font-size: .85rem; font-weight: 600; cursor: pointer;
}
.coach-skip:hover { color: var(--ink); border-color: var(--accent); }

/* O anel que diz "é deste que eu estou falando". Não escurece nada em volta. */
[data-coach="on"] {
  outline: 3px solid var(--accent);
  outline-offset: 3px;
  border-radius: var(--radius);
  animation: coach 1.7s ease-in-out infinite;
}
@keyframes coach {
  0%, 100% { outline-color: var(--accent); }
  50% { outline-color: var(--accent-soft); }
}

/* ============================================================ como se joga */
.howto-body { gap: 1.25rem; }
.howto-intro { margin: 0; color: var(--ink-dim); font-size: .95rem; }

.howto-steps {
  margin: 0; padding-left: 1.35rem;
  display: flex; flex-direction: column; gap: .6rem;
}
.howto-steps li { padding-left: .15rem; }
.howto-steps strong { display: block; font-size: 1rem; }
.howto-steps span { display: block; color: var(--ink-dim); font-size: .9rem; line-height: 1.4; }

.howto-sec { display: flex; flex-direction: column; gap: .6rem; min-width: 0; }
.howto-sec > h3 {
  font-size: .78rem; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-mute);
}
.howto-step-note { margin: 0; color: var(--ink-dim); font-size: .9rem; line-height: 1.4; }

/**
 * Os tabuleirinhos: as MESMAS classes do jogo, só que pequenos e sem interação.
 *
 * OS TRÊS FICAM NUMA LINHA SÓ, sempre. Eles são uma comparação — horizontal, vertical,
 * diagonal —, e comparação que quebra de linha deixa de ser comparação: o terceiro sozinho
 * embaixo parece um caso à parte, e não o terceiro de três. Por isso a largura é
 * `min(6,5rem, 27vw)`: a fração da tela é o que garante que os três caibam lado a lado até
 * em 320 px, e a medida absoluta é o que impede que fiquem enormes num monitor largo.
 */
.howto-boards { display: flex; gap: .6rem; justify-content: center; align-items: flex-start; }
.howto-fig {
  margin: 0; min-width: 0; flex: 0 1 auto;
  display: flex; flex-direction: column; align-items: center; gap: .35rem;
}
.howto-fig figcaption {
  color: var(--ink-dim); font-size: .8rem; font-weight: 600;
  text-align: center; max-width: 11rem; overflow-wrap: anywhere;
}

.board.mini {
  width: min(6.5rem, 27vw); height: min(6.5rem, 27vw);
  flex: none;
  gap: 2px; padding: 2px;
  border-radius: .6rem; box-shadow: none;
}
.board.mini .cell { border-radius: .3rem; cursor: default; }
.board.mini .cell svg.mark { width: 66%; height: 66%; }
/* Sem animação nenhuma: aqui o tabuleiro é uma ilustração parada. Um X se desenhando e três
   linhas vencedoras pulando toda vez que a ajuda abre chamariam atenção para o movimento
   em vez de para a diferença entre os três desenhos, que é a única coisa que eles dizem. */
.board.mini .cell[data-mark] svg.mark path,
.board.mini .cell[data-mark] svg.mark circle { animation: none; stroke-dashoffset: 0; }
.board.mini .cell[data-pending="yes"],
.board.mini .cell[data-win="yes"] { animation: none; }

/* O tabuleiro do empate está sozinho na sua linha: pode ser maior e ficar ao lado do texto. */
.howto-boards:has(> .howto-fig:only-child) { justify-content: flex-start; gap: .9rem; }
.howto-boards:has(> .howto-fig:only-child) .howto-fig { flex-direction: row; align-items: center; gap: .8rem; }
.howto-boards:has(> .howto-fig:only-child) .board.mini { width: min(6rem, 30vw); height: min(6rem, 30vw); }
.howto-boards:has(> .howto-fig:only-child) figcaption { text-align: left; max-width: none; }

/* O cartão de pergunta de exemplo. Mesmas classes, sem sombra e sem largura própria. */
.demo-ask { box-shadow: none; background: var(--panel-2); max-width: none; }
.demo-ask .ask-title { font-size: .95rem; }
.demo-ask .opt { cursor: default; min-height: 2.4rem; font-size: .95rem; }
.demo-ask .feedback { background: var(--panel); }

.howto-body .modal-actions { margin-top: .25rem; }

/* ================================ placar da série e fim de rodada ======= */
/**
 * O PLACAR GRANDE. Dois lados com o símbolo, o nome e o número, e um `×` no meio — que é
 * como um placar se lê em qualquer lugar do mundo, sem precisar de rótulo.
 */
.series-score { display: flex; align-items: center; justify-content: center; gap: .75rem; }
.ss-side { display: flex; flex-direction: column; align-items: center; gap: .05rem; min-width: 3.5rem; }
.ss-head { display: flex; align-items: center; gap: .3rem; color: var(--ink-mute); font-size: .78rem; font-weight: 700; }
.ss-head svg { width: .95em; height: .95em; }
.ss-side[data-mark="X"] .ss-head { color: var(--mark-x); }
.ss-side[data-mark="O"] .ss-head { color: var(--mark-o); }
.ss-side b { font-size: 1.6rem; font-weight: 800; line-height: 1; color: var(--ink); }
.ss-x { color: var(--ink-mute); font-size: 1rem; font-weight: 700; }

.scoreline[data-series="yes"] { flex-direction: column; gap: .3rem; min-height: 0; }
.score-draws { font-size: .78rem; }

/* Com a barra de fim de rodada aberta, o placar do rodapé some: a barra já mostra o mesmo
   número, maior e junto do resultado. Dois placares idênticos na mesma tela fazem a pessoa
   comparar um com o outro procurando a diferença que não existe. */
.round-bar:not([hidden]) ~ .scoreline { display: none; }

/**
 * A BARRA DE FIM DE RODADA. Um painel no fluxo, entre o tabuleiro e o placar, com borda de
 * destaque e nada de véu: o tabuleiro atrás continua visível com a linha vencedora acesa,
 * que é o que a pessoa quer olhar no instante em que a partida termina.
 */
.round-bar {
  flex: none;
  display: flex; flex-direction: column; align-items: center; gap: .4rem;
  padding: .7rem .8rem;
  border: 1px solid var(--accent); border-radius: var(--radius);
  background: color-mix(in srgb, var(--accent) 12%, var(--panel));
  animation: rise .22s ease-out;
}
.round-line-result {
  margin: 0; display: flex; align-items: center; gap: .4rem;
  font-size: 1rem; font-weight: 700; text-align: center;
}
.round-line-result svg { color: var(--accent-soft); }
.round-note { margin: 0; color: var(--ink-dim); font-size: .85rem; font-weight: 600; }
.round-score .ss-side b { font-size: 2rem; }
.round-next { align-self: stretch; max-width: 22rem; }

html[data-contrast="high"] .round-bar { background: var(--panel); border-width: 2px; }

/* Deitado e baixo: a barra encolhe para não roubar altura do tabuleiro. */
@media (orientation: landscape) and (max-height: 30rem) {
  .round-bar { flex-direction: row; flex-wrap: wrap; justify-content: center; gap: .5rem; padding: .45rem .6rem; }
  .round-line-result { font-size: .9rem; }
  .round-score .ss-side b { font-size: 1.4rem; }
  .round-next { align-self: center; flex: 0 1 12rem; }
  .scoreline[data-series="yes"] { flex-direction: row; }
}

/* -------------------------------------------------------------- avisos */
.toasts {
  position: fixed; left: 50%; transform: translateX(-50%);
  bottom: calc(1rem + var(--safe-b)); z-index: 70;
  display: flex; flex-direction: column; gap: .4rem; align-items: center;
  width: min(26rem, calc(100vw - 2rem)); pointer-events: none;
}
.toast {
  padding: .5rem .9rem; border-radius: 999px;
  background: var(--panel); border: 1px solid var(--line); box-shadow: var(--shadow);
  font-size: .88rem; font-weight: 600; text-align: center;
  animation: rise .2s ease-out;
}
