## PP-5 — Bloqueio do palpite no horário oficial do jogo

**PRD:** `docs/prd/palpite-e-prazo.md`

**Como** participante competitivo, **quero** que nenhum palpite seja aceito
depois do horário oficial de início do jogo, **para** confiar que ninguém
palpitou já sabendo do resultado.

**Prioridade:** Must — é a regra que sustenta a integridade do bolão; sem
ela o app não é melhor que o WhatsApp.

**Critérios de aceite:**

- Dado que o horário oficial de início do jogo chegou, quando alguém tenta
  registrar ou editar palpite naquele jogo, então o servidor recusa.
- Dado que o prazo fechou, quando vejo aquele jogo, então ele aparece como
  fechado e os campos de placar não aceitam edição.
- Dado que o relógio do device está atrasado, quando tento palpitar depois do
  apito, então o servidor recusa mesmo que o app mostre prazo aberto.
- Dado que a rodada tem jogos em horários diferentes, quando o primeiro
  fecha, então os outros continuam abertos — o fechamento é por jogo, não por
  rodada.
- Dado que sou admin do bolão, quando tento palpitar depois do apito, então
  sou recusado igual a qualquer participante.

**Tasks:**

_Backend_
- [x] `BE-1` Rejeitar registro e edição de palpite quando o horário do servidor passou do início oficial do jogo (depende de PP-1 BE-2)
- [x] `BE-2` Garantir que o fechamento seja por jogo, independente dos outros jogos da rodada
- [x] `BE-3` Nenhum papel (admin incluído) tem exceção ao bloqueio

_Mobile_
- [x] `FE-1` Estado visual de jogo fechado, com campos não editáveis e motivo explícito
- [x] `FE-2` Não permitir montar envio para jogo fechado, e tratar a recusa do servidor como fluxo esperado

_QA_
- [x] `QA-1` Escrever o plano de casos de teste a partir desta story
- [x] `QA-2` Executar o plano incluindo bypass pela API direta com prazo vencido, e tentativa como admin

**Riscos/Dependências:**

- Depende de PP-1 e PP-3.
- **O teste de bypass pela API é obrigatório:** bloquear só na tela não
  cumpre esta story.
- Interage com PP-6: jogo adiado muda o horário oficial e, com ele, o prazo.

- **06/08:** o app não monta envio para jogo fechado (o servidor recusaria, e
  tentar seria fingir que ainda dá) e trata a recusa por item como fluxo
  esperado, com texto próprio. Verificado em device com jogo de rodada passada e
  com bolão encerrado.

- **06/08:** plano de casos em `docs/testes/PP-5-plano.md`. Escrito a partir da
  story, não do código — caso escrito depois de olhar a implementação valida o
  que foi feito, não o que foi pedido.

- **06/08 — execução: ✅ 11 de 11** (`docs/testes/PP-5-execucao.md`).
- Duas lacunas apareceram na execução. `PP-5-02` (a borda exata do apito) não
  tinha teste nenhum: a suíte cobria "rodada passada", com semanas de folga, não
  o instante em que o prazo virou. `PP-5-10` (o cartão fechar sozinho quando a
  contagem zera) **não era testável**, porque `pump(Duration)` move os timers
  falsos mas não o `DateTime.now()`; abri na `RodadaPage` a mesma costura de
  relógio injetável que o `RelogioDoServidor` já tinha.
- ⚠️ Aviso: `PP-5-05`/`PP-5-06` foram executados no nível do relógio injetado, não
  mexendo no relógio do emulador. A lógica é a mesma que a tela usa, mas uma
  passada em device com a hora realmente alterada ainda vale antes do release.
