/* ============================================================
   Tema: escuro e claro
   ============================================================
   ⚠️ O `data-tema` esta SEMPRE no <html>, nunca ausente — quem escreve e o
   script no <head> do index.html, antes da primeira pintura. Por isso aqui
   nao ha `@media (prefers-color-scheme)`: a paleta clara existe uma vez so,
   em vez de duplicada entre a media query (tema automatico) e o seletor de
   atributo (tema escolhido). Duas copias da mesma paleta e como nascem telas
   em que so metade das cores muda.

   O modo automatico (seguir o sistema) continua existindo: e o script que
   resolve "auto" para "claro" ou "escuro" e reage quando o sistema muda. */
:root,
:root[data-tema="escuro"]{
  --bg:#0f1216; --surface:#171c22; --surface-2:#1f262e; --line:#2b333d;
  --text:#e8edf2; --muted:#96a3b2; --accent:#3f8cff; --ok:#2fbf71;
  --warn:#f0a136; --err:#e5484d; --radius:10px;
  /* Papel quadriculado da tela de login. No escuro o "papel" e um azul
     grafite: papel branco de verdade cegaria quem abre o painel a noite. */
  --papel:#121821; --quadro-fino:rgba(125,160,205,.16);
  --quadro-forte:rgba(130,175,235,.34);
}
:root[data-tema="claro"]{
  --bg:#f4f6f9; --surface:#fff; --surface-2:#eef1f5; --line:#d9e0e8;
  --text:#131a21; --muted:#5c6a79; --accent:#3f8cff; --ok:#2fbf71;
  --warn:#f0a136; --err:#e5484d; --radius:10px;
  --papel:#fbfcfd; --quadro-fino:rgba(60,110,170,.13);
  --quadro-forte:rgba(45,95,160,.26);
}
*{box-sizing:border-box}
/* ⚠️ O iOS AUMENTA A LETRA SOZINHO quando a pagina gira para deitado
   ("text size adjust"), e so em alguns blocos: a tabela do relatorio saia com
   fonte maior que o cabecalho dela e as colunas desalinhavam sem ninguem ter
   mexido em nada. */
html{-webkit-text-size-adjust:100%;text-size-adjust:100%}
body{margin:0;background:var(--bg);color:var(--text);
  font:15px/1.5 system-ui,-apple-system,Segoe UI,Roboto,sans-serif}
/* ⚠️ O PADDING LATERAL RESPEITA O RECORTE DA TELA. O `viewport-fit=cover` do
   index.html manda a pagina ate embaixo do entalhe e das bordas curvas — e sem
   `env(safe-area-inset-*)` o logo e o botao "Sair" ficam DEBAIXO do entalhe com
   o celular deitado. `max()` mantem os 20px de sempre onde nao ha recorte. */
header{display:flex;align-items:center;gap:12px;
  padding:14px max(20px,env(safe-area-inset-right)) 14px max(20px,env(safe-area-inset-left));
  background:var(--surface);border-bottom:1px solid var(--line);
  position:sticky;top:0;z-index:10}
header h1{font-size:16px;margin:0;letter-spacing:.2px}
header .logo{width:28px;height:28px;border-radius:8px;object-fit:cover;transform:scale(1.8);transform-origin:left center;margin-right:16px}
header .sp{flex:1}
main{max-width:960px;margin:0 auto;
  padding:20px max(20px,env(safe-area-inset-right))
          max(20px,calc(env(safe-area-inset-bottom) + 20px))
          max(20px,env(safe-area-inset-left))}
.card{background:var(--surface);border:1px solid var(--line);
  border-radius:var(--radius);padding:18px;margin-bottom:16px}
h2{font-size:15px;margin:0 0 14px;text-transform:uppercase;
  letter-spacing:.6px;color:var(--muted)}
label{display:block;font-size:13px;color:var(--muted);margin:10px 0 4px}
/* ⚠️ 16px NAO E ESCOLHA DE ESTILO, E O PONTO EM QUE O IPHONE PARA DE DAR
   ZOOM. Campo com letra menor que 16px faz o Safari aproximar a pagina inteira
   ao tocar nele — e ele NAO desfaz o zoom ao sair: o professor digita o nome do
   aluno e o resto da correcao continua numa tela ampliada, com o botao de
   salvar fora do quadro. Era o caso de todos os campos daqui (15px) e do
   assunto da questao (13px).
   ⚠️ E os 44px de altura sao o alvo de toque minimo (o mesmo que Apple e
   Google publicam): com 10px de padding o campo tinha 40px, e errar o toque num
   formulario significa abrir o teclado no campo errado. */
input,select,textarea{width:100%;padding:11px 12px;background:var(--surface-2);
  border:1px solid var(--line);border-radius:8px;color:var(--text);font-size:16px}
input:not([type=checkbox]):not([type=radio]),select{min-height:44px}
textarea{min-height:56px}
/* ⚠️ TODO BOTAO TEM 44px DE ALTURA, inclusive os que so tem uma palavra.
   `padding:10px` com letra de 14px dava 38px — abaixo do alvo minimo de toque,
   e a lista de correcoes e uma coluna de botoes "Renomear"/"Excluir" a 8px um
   do outro: errar o toque ali apaga a nota de um aluno.
   ⚠️ `touch-action:manipulation` mata a espera de 300ms que o navegador guarda
   para ver se vem um segundo toque (zoom de duplo-toque). Sem isso todo botao
   do app responde com atraso perceptivel no celular — e atraso vira toque
   repetido, que na camera vira duas fotos. */
button{padding:10px 16px;border-radius:8px;border:1px solid var(--line);
  background:var(--surface-2);color:var(--text);font-size:15px;cursor:pointer;
  min-height:44px;touch-action:manipulation;-webkit-tap-highlight-color:transparent}
button.primary{background:var(--accent);border-color:var(--accent);color:#fff;font-weight:600}
button.danger{color:var(--err)}
/* Botao esperando o segundo toque (ver `confirmarNoBotao` em base.js): tem de
   parecer OUTRO botao, senao o professor acha que o primeiro toque nao pegou
   e sai clicando em volta. */
button.confirmando{background:var(--err);border-color:var(--err);color:#fff}
button:disabled{opacity:.5;cursor:not-allowed}
.row{display:flex;gap:10px;flex-wrap:wrap;align-items:center}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:12px}
@media(max-width:600px){.grid2{grid-template-columns:1fr}}
.muted{color:var(--muted);font-size:13px}
/* Contador de caracteres — some enquanto sobra espaco, e fica vermelho quando
   o campo trava. Ver `limitarTitulo` em avaliacoes.js. */
.conta-chars{float:right;font-weight:400;font-size:12px;color:var(--muted);
  font-variant-numeric:tabular-nums}
.conta-chars.no-limite{color:var(--warn)}
.hidden{display:none!important}

/* Editor de gabarito */
.key-grid{display:grid;gap:6px}
.key-row{display:grid;grid-template-columns:38px repeat(5,1fr);gap:6px;align-items:center}
.qn{color:var(--muted);font-variant-numeric:tabular-nums;font-size:13px}
/* ⚠️ A BOLHA E O ELEMENTO MAIS TOCADO DO APP — sao 15 questoes vezes 5
   alternativas, marcadas com o celular na mao. Tinha 36px de altura e 6px de
   respiro: no polegar, mirar em B e acertar A e um gabarito errado que
   contamina a prova inteira da turma. Agora tem 46px, o alvo de toque cheio. */
.opt{padding:0 2px;min-height:46px;display:flex;align-items:center;
  justify-content:center;text-align:center;border:1px solid var(--line);
  border-radius:8px;background:var(--surface-2);cursor:pointer;font-weight:600;
  font-size:15px;user-select:none;-webkit-user-select:none;
  touch-action:manipulation;-webkit-tap-highlight-color:transparent}
.opt.sel{background:var(--accent);border-color:var(--accent);color:#fff}
.opt.right{background:var(--ok);border-color:var(--ok);color:#06231a}
.opt.wrong{background:var(--err);border-color:var(--err);color:#fff}

/* Listas */
.item{display:flex;gap:12px;align-items:center;padding:12px;
  border:1px solid var(--line);border-radius:8px;margin-bottom:8px;background:var(--surface-2)}
.item .grow{flex:1;min-width:0}
/* O editor do nome ocupa a linha inteira, embaixo dos dados da correcao —
   `.item` e flex, entao sem o `flex-wrap` ele seria espremido ao lado da
   nota. */
.item{flex-wrap:wrap}
.editor-nome{flex-basis:100%;margin-top:10px;padding-top:10px;
  border-top:1px solid var(--line);display:flex;flex-direction:column;gap:8px}
.editor-nome input{flex:1;min-width:160px;margin:0}
/* Folha gravada sem nome e PENDENCIA, nao registro pronto: a nota nao entra
   no boletim de ninguem e some do relatorio da turma. */
.item.sem-nome{border-color:var(--warn);
  background:color-mix(in srgb, var(--warn) 7%, var(--surface-2))}
.item b{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.score{font-size:22px;font-weight:700;font-variant-numeric:tabular-nums}

/* Camera */
.frame-hint{border:2px dashed var(--accent);border-radius:8px;padding:8px;
  text-align:center;color:var(--muted);font-size:13px;margin-top:8px}
img.evidence{width:100%;border-radius:8px;border:1px solid var(--line)}
.badge{display:inline-block;padding:2px 8px;border-radius:99px;font-size:12px;
  border:1px solid var(--line)}
.badge.b-ok{color:var(--ok);border-color:var(--ok)}
.badge.b-warn{color:var(--warn);border-color:var(--warn)}
.badge.b-err{color:var(--err);border-color:var(--err)}
/* ⚠️ O AVISO SOBE ACIMA DA BARRA DE GESTOS. Preso em `bottom:24px`, no iPhone
   ele nasce debaixo da barrinha de "voltar ao inicio": some metade da frase, e
   e justamente por ela que o professor descobre que a foto foi recusada. */
#toast{position:fixed;left:50%;bottom:calc(24px + env(safe-area-inset-bottom));
  transform:translateX(-50%);
  background:var(--surface-2);border:1px solid var(--line);padding:12px 18px;
  border-radius:8px;max-width:90vw;z-index:50;box-shadow:0 8px 30px rgba(0,0,0,.35)}

/* Abas */
.tabs{display:flex;gap:8px;margin-bottom:16px}
.tab{flex:1;padding:11px;font-weight:600;min-height:46px}
.tab.active{background:var(--accent);border-color:var(--accent);color:#fff}

/* Camera com guia de enquadramento */
/* ⚠️ ESTILO DA CAMERA E POR CLASSE, NUNCA POR ID (#preview, #cam-overlay).
   Sao DUAS cameras na mesma pagina — corrigir e editor de gabarito. Enquanto
   estas regras moravam nos ids da tela de corrigir, a do gabarito nascia
   CRUA, e o estrago era em cascata: <video> sem largura assume o tamanho do
   stream (1920x1080 px de CSS), estoura a tela do celular, e o professor ve
   so um pedaco do que a camera enxerga. Sem ver o quadro inteiro ele nao
   consegue enquadrar o cartao; sem os 4 cantos no quadro a mira nunca acende,
   e o disparo automatico "nao funciona" no gabarito enquanto funciona em
   corrigir — mesmo codigo, mesmo laco, so faltava CSS. O canvas sem
   position:absolute ainda descia para BAIXO do video e desenhava o traco
   verde fora do lugar.

   ⚠️ E O VISOR E PEQUENO DE PROPOSITO. Preview ocupando a tela toda no
   celular empurra para fora do campo de visao justamente o que o professor
   precisa ler enquanto mira: a frase da mira ("vejo 3 de 4 quadrados") e os
   botoes de capturar/fechar. Uma camera que le sozinha PRECISA que a frase
   dela caiba na tela junto com o video — senao ela conta os quadrados para
   ninguem.

   ⚠️ QUEM MANDA NO TAMANHO E A ALTURA, e por isso o visor e dimensionado
   pela ALTURA (`height`) e nao pela largura. No celular o que falta e altura:
   teto so em px continua estourando a tela deitada, e teto so na largura
   deixa um video 9/16 crescer para fora. Com a altura presa em 44vh, a
   largura sai da proporcao do video e o quadro cabe sempre. */
/* ⚠️ `dvh`, NAO `vh`. No celular `vh` e a altura da tela COM a barra de
   endereco escondida — o maior valor possivel. Com a barra a vista (que e como
   a pagina abre), 44vh e mais de 44% do que se enxerga, e o visor empurrava
   para fora da tela exatamente o que o professor precisa ler enquanto mira: a
   frase da mira e o botao de capturar. `dvh` e a altura que existe AGORA. */
.cam-stage{position:relative;margin:0 auto;height:min(44dvh,320px);
  width:auto;max-width:100%;aspect-ratio:var(--video-prop,9/16);
  background:#000;border-radius:8px;overflow:hidden;
  user-select:none;-webkit-user-select:none;touch-action:manipulation}
/* ⚠️ A PROPORCAO E A DO VIDEO DE VERDADE (`--video-prop`, que camera.js
   grava quando o stream chega), com 9/16 so como palpite ate ele chegar.
   Fixar 4/3 na mao era o erro anterior: no celular a camera costuma entregar
   quadro em pe, e um visor deitado cercava esse quadro de tarja preta —
   quadro pequeno DENTRO de caixa grande, o pior dos dois mundos, porque a
   caixa ocupa a tela e o video que se enxerga fica menor ainda.

   ⚠️ E `contain`, nunca `cover`: o que aparece na tela tem de ser o que a
   foto vai pegar. Com `cover` o video era RECORTADO na exibicao — o
   professor enquadrava pelo que via e a foto saia com mais coisa em volta.
   Casando a caixa com a proporcao do video, `contain` nao deixa tarja
   nenhuma: nao ha o que recortar nem o que sobrar. */
.cam-stage video{display:block;width:100%;height:100%;object-fit:contain}
/* ⚠️ O GUIA TEM A PROPORCAO DO CARTAO, NAO A DO VIDEO.
   Com `inset:8%` ele herdava o 3:4 do preview e desenhava um retangulo
   vertical — mas o cartao e quase QUADRADO (1.06). O professor encaixava o
   cartao num guia alto demais: ou afastava o celular (ancora pequena, foto
   recusada) ou cortava as laterais. A proporcao vem de `--cartao-prop`, que
   correcao.js le de /api/layout — layout.py continua sendo a unica fonte de
   verdade da geometria. */
.cam-guide{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
  width:88%;max-height:84%;aspect-ratio:var(--cartao-prop,1.06);
  border:2px dashed rgba(63,140,255,.85);border-radius:6px;pointer-events:none}
.cam-guide::before,.cam-guide::after{content:"";position:absolute;width:26px;height:26px;
  border:3px solid var(--accent)}
.cam-guide::before{top:-3px;left:-3px;border-right:0;border-bottom:0}
.cam-guide::after{bottom:-3px;right:-3px;border-left:0;border-top:0}
/* Traco verde por cima do video, onde a mira achou as 4 ancoras. */
.cam-stage canvas{position:absolute;inset:0;width:100%;height:100%;pointer-events:none}
/* ⚠️ O NUMERAO DA CONTAGEM PRECISA SER LIDO DE RELANCE, com o celular na mao
   e a atencao no cartao — nao na tela. Por isso ocupa o visor inteiro, em
   tamanho que acompanha a largura dele (`vw` no meio do clamp: visor pequeno
   no celular, numero proporcional), e com sombra: numero branco sobre foto
   clara some, e uma contagem que some vira disparo sem aviso outra vez. */
.cam-count{position:absolute;inset:0;display:flex;align-items:center;
  justify-content:center;font-size:clamp(44px,18vw,96px);font-weight:700;
  color:#fff;text-shadow:0 2px 14px rgba(0,0,0,.85);pointer-events:none;
  font-variant-numeric:tabular-nums}
.frame-hint.mira-ok{border-color:var(--ok);color:var(--ok)}
/* ⚠️ O ROTULO INTEIRO E O ALVO, nao so o quadradinho. Uma caixa de marcar tem
   ~16px: mirar nela com o polegar, no meio da correcao, e o tipo de toque que
   erra e desliga o disparo automatico sem o professor perceber — e dali em
   diante "a camera parou de tirar foto sozinha". Com o `label` de 44px de
   altura, o alvo e a frase toda. */
.auto-toggle{display:flex;align-items:center;gap:8px;margin:0;min-height:44px;
  padding:4px 2px;font-size:14px;color:var(--muted);cursor:pointer;
  touch-action:manipulation;-webkit-tap-highlight-color:transparent}
.auto-toggle input{width:22px;height:22px;min-height:0;margin:0;flex:0 0 auto;
  accent-color:var(--accent)}

textarea{resize:vertical;font-family:inherit}
.pill{display:inline-block;padding:2px 8px;border-radius:99px;font-size:12px;
  background:var(--surface);border:1px solid var(--line);color:var(--muted);margin-left:6px}
.spinner{display:inline-block;width:14px;height:14px;border:2px solid var(--line);
  border-top-color:var(--accent);border-radius:50%;animation:spin .7s linear infinite;
  vertical-align:-2px;margin-right:8px}
@keyframes spin{to{transform:rotate(360deg)}}

/* Login social */
.btn-social{display:flex;align-items:center;justify-content:center;gap:10px;
  width:100%;padding:12px;border:1px solid var(--line);border-radius:8px;
  background:var(--surface-2);color:var(--text);font-size:15px;font-weight:600;
  text-decoration:none;cursor:pointer}
.separador{display:flex;align-items:center;gap:12px;margin:16px 0;color:var(--muted);
  font-size:13px}
.separador::before,.separador::after{content:"";flex:1;height:1px;background:var(--line)}
.aviso{padding:10px 12px;border-radius:8px;border:1px solid var(--err);
  color:var(--err);font-size:14px;margin-bottom:14px}
code.chave{background:var(--surface-2);border:1px solid var(--line);border-radius:4px;
  padding:1px 6px;font-size:12px;word-break:break-all}


/* ============================================================
   Papel quadriculado — fundo da tela de login
   ============================================================
   Quatro gradientes: as linhas finas do quadriculado (a cada 24px) e as
   reforcadas a cada 5 quadrados, como num caderno de matematica.

   ⚠️ As linhas sao desenhadas em um ::before de posicao fixa, e nao no
   `background` do body. No celular, a barra de endereco que some ao rolar muda
   a altura do body — com o padrao preso a ele, o quadriculado "pula" no meio
   da rolagem. Fixo na viewport, ele fica parado como papel de verdade.

   O `background-position` central alinha o cruzamento das linhas grossas com o
   meio da tela, entao o cartao de login cai dentro de um quadro, e nao em cima
   de uma linha. */
body.tela-login{background:var(--papel)}

body.tela-login::before{
  content:"";
  position:fixed;
  inset:0;
  z-index:-1;
  pointer-events:none;
  background-image:
    linear-gradient(var(--quadro-forte) 1.5px, transparent 1.5px),
    linear-gradient(90deg, var(--quadro-forte) 1.5px, transparent 1.5px),
    linear-gradient(var(--quadro-fino) 1px, transparent 1px),
    linear-gradient(90deg, var(--quadro-fino) 1px, transparent 1px);
  background-size:120px 120px, 120px 120px, 24px 24px, 24px 24px;
  background-position:center center;
  /* Vinheta suave: o quadriculado forte ate a borda competiria com o cartao.
     Assim ele desaparece nos cantos e o olho vai para o formulario. */
  -webkit-mask-image:radial-gradient(ellipse 75% 65% at 50% 45%, #000 30%, transparent 100%);
  mask-image:radial-gradient(ellipse 75% 65% at 50% 45%, #000 30%, transparent 100%);
}

/* O cartao centrado no papel. Com a largura de 960px do resto do painel ele
   ficava deitado no canto superior, e o quadriculado virava so uma faixa
   sobrando a direita. */
body.tela-login main{
  max-width:none;
  min-height:calc(100dvh - 120px);
  display:grid;
  place-items:center;
  padding:24px 20px 40px;
}
body.tela-login #view-auth{
  width:100%;
  max-width:430px;
  margin:0;
  /* Sobre papel a borda sozinha sumia no meio das linhas: a sombra e o leve
     desfoque do fundo e que fazem o cartao parecer pousado nele. */
  box-shadow:0 18px 50px rgba(0,0,0,.22);
  backdrop-filter:blur(3px);
}
body.tela-login header{background:transparent;border-bottom-color:transparent}

/* Quem pediu para o sistema nao animar nada tambem nao quer um fundo vibrando
   em telas de alta densidade. */
@media (prefers-reduced-motion:reduce){
  body.tela-login::before{-webkit-mask-image:none;mask-image:none;opacity:.5}
}

/* Administracao de usuarios */
.resumo{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:12px}
.resumo .bloco{background:var(--surface-2);border:1px solid var(--line);
  border-radius:8px;padding:12px}
.resumo .bloco b{display:block;font-size:22px;font-variant-numeric:tabular-nums}
.resumo .bloco span{color:var(--muted);font-size:12px;text-transform:uppercase;
  letter-spacing:.5px}

.usuario{border:1px solid var(--line);border-radius:8px;background:var(--surface-2);
  padding:12px;margin-bottom:10px}
.usuario .topo{display:flex;gap:10px;align-items:center;flex-wrap:wrap}
/* `b` e inline por padrao — sem isto o e-mail cola no nome. */
.usuario .topo .grow b{display:block;font-size:15px;margin-bottom:2px}
.usuario .topo .grow > span{display:block}
.usuario .topo .pill{font-weight:400}
.usuario .linha-plano{display:flex;gap:8px;align-items:flex-end;flex-wrap:wrap;
  margin-top:10px;padding-top:10px;border-top:1px solid var(--line)}
.usuario .linha-plano label{margin:0 0 2px}
.usuario input,.usuario select{width:auto}
.inativo{opacity:.55}

/* Estados da assinatura — a cor diz o que fazer sem ler */
.est{display:inline-block;padding:2px 9px;border-radius:99px;font-size:12px;
  font-weight:600;border:1px solid currentColor}
.est-gratis{color:var(--muted)}
.est-em-dia{color:var(--ok)}
.est-vence-hoje{color:var(--warn)}
.est-atrasado{color:var(--err)}
.est-suspenso{color:var(--err)}
.est-desativado{color:var(--muted)}

/* Logo na tela de login */
.login-logo{display:block;width:96px;height:96px;margin:0 auto 18px;border-radius:16px;object-fit:cover}

/* Tela de confirmacao antes de salvar a correcao (nome + turma) */
.confirm-card{border:2px solid var(--accent);border-radius:10px;padding:14px;
  background:var(--surface-2);margin:10px 0}
.confirm-card h3{margin:0 0 12px;font-size:14px;text-transform:uppercase;
  letter-spacing:.4px;color:var(--accent)}
.confirm-card label{display:block;font-size:13px;color:var(--muted);margin-bottom:4px}
.confirm-card input{width:100%}
.confirm-card .muted{display:block;margin-top:4px;font-size:12px}
.turma-fixa{padding:9px 12px;border-radius:8px;background:var(--surface);
  border:1px solid var(--line);font-weight:600}
.salvo-ok{color:var(--ok);font-weight:600;margin:0 0 10px}

/* Navegacao no cabecalho (antes ficava em barra separada no corpo) */
.nav-topo{display:flex;gap:6px;margin-left:22px}
.nav-topo .tab{padding:8px 14px;font-weight:600;border-radius:8px;
  background:transparent;border:1px solid transparent;color:var(--muted)}
.nav-topo .tab.active{background:var(--accent);border-color:var(--accent);color:#fff}
/* ⚠️ 1100px, nao 820px. Sao SEIS abas: no limite antigo elas ainda cabiam na
   mesma linha do logo e do botao de tema em telas medias — e a ultima ficava
   escondida atras do "Sair", sem barra de rolagem nenhuma para revelar. */
@media(max-width:1100px){
  header{flex-wrap:wrap}
  .nav-topo{order:3;width:100%;margin:8px 0 0;overflow-x:auto;
    -webkit-overflow-scrolling:touch;scroll-snap-type:x proximity;
    scrollbar-width:none}
  .nav-topo::-webkit-scrollbar{display:none}
  .nav-topo .tab{flex:1;white-space:nowrap;padding:8px 12px}
}
/* ⚠️ ABAIXO DE 700px AS ABAS PARAM DE DIVIDIR E PASSAM A ROLAR (`flex:0 0
   auto`). Com `flex:1` dentro de um contentor que rola, as seis abas se
   espremem para caber na largura em vez de transbordar: em tela de 360px
   sobravam ~55px por aba e "Configuracoes" nao cabia de jeito nenhum. Rolando,
   cada aba tem o tamanho do nome dela e o dedo arrasta a barra. */
@media(max-width:700px){
  .nav-topo{margin:8px -20px 0;padding:0 20px;width:calc(100% + 40px)}
  .nav-topo .tab{flex:0 0 auto;padding:10px 14px;scroll-snap-align:start}
}

/* Erro de formulario colado no campo — o toast do rodape passava batido */
.erro-campo{display:block;margin-top:4px;color:var(--err);font-size:13px;font-weight:600}
.campo-invalido{border-color:var(--err)!important;outline:none}

/* ---------- Relatorios ---------- */
h3.sub{font-size:14px;margin:22px 0 8px;color:var(--text)}

/* Alerta de gabarito suspeito: e a informacao que muda o que o professor
   faz a seguir, entao vem antes de tudo e com peso visual. */
.alerta-gabarito{border:2px solid var(--warn);border-radius:10px;padding:14px;
  margin:16px 0;background:var(--surface-2)}
.alerta-gabarito b{display:block;color:var(--warn);margin-bottom:6px}
.alerta-gabarito p{margin:0 0 10px;color:var(--muted);font-size:13px}
.alerta-gabarito div{padding:4px 0;font-size:14px}

/* Progresso da turma na tela de corrigir. Barra, e nao so numero: "12 de 32"
   exige ler e comparar; a barra responde "quanto falta" de relance, que e a
   pergunta de quem esta com a pilha na mao. */
.progresso{display:flex;flex-direction:column;gap:6px;margin:0 0 14px}
.progresso b{font-size:15px}
.progresso-trilha{height:8px;border-radius:99px;background:var(--surface-2);
  border:1px solid var(--line);overflow:hidden}
.progresso-barra{height:100%;background:var(--accent);border-radius:99px;
  transition:width .3s ease}
.progresso-barra.completa{background:var(--ok)}

/* "Todos os alunos ja tem folha": e o fim da tarefa, e merece a cor de
   acerto — a mesma frase em cinza passaria batida na hora em que ela e a
   unica coisa que o professor queria saber. */
.tudo-feito{color:var(--ok);font-size:13px;font-weight:600}

/* Prova sem turma, no cadastro do gabarito. E um bloco de acao, nao um aviso
   cinza: sem turma nao ha lista de chamada, o nome lido nao casa com aluno
   nenhum e as correcoes ficam fora do relatorio da turma. */
#key-turma{display:flex;flex-direction:column;gap:8px;margin:0 0 14px;
  padding:12px 14px;border-radius:10px;border:1px solid var(--warn);
  background:color-mix(in srgb, var(--warn) 10%, transparent)}
#key-turma b{color:var(--warn)}

/* ============================================================
   Avisos da tela de conferencia e da lista de correcoes
   ============================================================ */
/* Aluno que ja tem correcao nesta prova. Cor de ALERTA, nao de erro: nao ha
   nada errado em corrigir de novo — o que nao pode e acontecer sem que o
   professor perceba, porque as duas notas entram na media da turma. */
.aviso-duplo{margin-top:10px;padding:10px 12px;border-radius:8px;
  border:1px solid var(--warn);background:color-mix(in srgb, var(--warn) 10%, transparent);
  font-size:13px;display:flex;gap:10px;align-items:center;flex-wrap:wrap}
.aviso-duplo .auto-toggle{color:var(--text);font-weight:600}
/* Quem ainda falta: informacao de PENDENCIA, entao usa a cor de alerta; a
   frase de "todos corrigidos" e o fim da tarefa, e usa a de acerto. */
.faltam-lista,.faltam-ok{margin:0 0 10px;padding:9px 12px;border-radius:8px;
  font-size:13px;border:1px solid}
.faltam-lista{color:var(--warn);border-color:var(--warn);
  background:color-mix(in srgb, var(--warn) 8%, transparent)}
.faltam-ok{color:var(--ok);border-color:var(--ok);
  background:color-mix(in srgb, var(--ok) 8%, transparent)}

/* Distribuicao de notas */
.barra-linha{display:grid;grid-template-columns:70px 1fr 110px;gap:10px;
  align-items:center;margin-bottom:6px}
.barra-rotulo{font-size:13px;color:var(--muted)}
.barra-trilha{background:var(--surface-2);border-radius:6px;height:20px;overflow:hidden}
.barra{background:var(--accent);height:100%;border-radius:6px;min-width:2px}
.barra-valor{font-size:13px;color:var(--muted);text-align:right}

/* Tabelas de questao e de aluno */
.tabela-questoes{border:1px solid var(--line);border-radius:8px;overflow:hidden}
.q-linha{display:grid;grid-template-columns:70px 80px 150px 1fr 110px;gap:10px;
  padding:9px 12px;align-items:center;font-size:14px;
  border-bottom:1px solid var(--line)}
.q-linha:last-child{border-bottom:0}
.q-linha.q-alunos{grid-template-columns:1fr 70px 90px 2fr}
.q-linha.q-evolucao{grid-template-columns:2fr 110px 80px 80px 130px}
.q-cab{background:var(--surface-2);font-weight:600;font-size:12px;
  text-transform:uppercase;letter-spacing:.4px;color:var(--muted)}
.q-linha .gab{font-weight:700}
.q-suspeita{background:color-mix(in srgb, var(--warn) 12%, transparent)}
.q-atencao{background:color-mix(in srgb, var(--err) 10%, transparent)}

/* Cor do indice de dificuldade: diz o que fazer sem precisar ler o numero */
.dif{display:inline-block;padding:1px 8px;border-radius:99px;font-size:12px;
  font-weight:700;border:1px solid currentColor;margin-right:6px}
.dif-facil{color:var(--ok)}
.dif-media{color:var(--warn)}
.dif-dificil{color:var(--err)}

@media(max-width:760px){
  .q-linha,.q-linha.q-alunos,.q-linha.q-evolucao{
    grid-template-columns:1fr 1fr;row-gap:4px}
  .q-cab{display:none}
}

/* Assunto por questao no editor de gabarito */
.key-row.com-assunto{grid-template-columns:38px repeat(5,1fr) 1.6fr}
.assunto-q{padding:9px 10px}
@media(max-width:700px){
  .key-row.com-assunto{grid-template-columns:38px repeat(5,1fr);row-gap:6px}
  .assunto-q{grid-column:1 / -1}
}

/* Analise da IA */
.card-ia{border:1px solid var(--line);border-radius:10px;padding:16px;
  background:var(--surface-2)}
.card-ia h3.sub{margin-top:0}
.ia-saida{margin-top:12px}
.ia-saida p{margin:0 0 10px;line-height:1.6}

/* Tabelas por assunto e por aluno */
.q-linha.q-assunto{grid-template-columns:2fr 150px 1fr 110px}
.q-linha.q-desempenho{grid-template-columns:2fr 80px 80px 80px 130px 110px}
.q-sem-nota{opacity:.6}
.tend-sobe{color:var(--ok);font-weight:600}
.tend-desce{color:var(--err);font-weight:600}
@media(max-width:760px){
  .q-linha.q-assunto,.q-linha.q-desempenho{grid-template-columns:1fr 1fr}
}

/* Marcar turmas para aplicar a mesma prova */
.lista-turmas{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));
  gap:8px}
.turma-check{display:flex;align-items:center;gap:10px;padding:11px 12px;
  min-height:48px;border:1px solid var(--line);border-radius:8px;
  background:var(--surface-2);cursor:pointer;font-size:15px;
  touch-action:manipulation;-webkit-tap-highlight-color:transparent}
.turma-check input{width:22px;height:22px;min-height:0;margin:0;flex:0 0 auto;
  accent-color:var(--accent)}


/* Botao de tema no cabecalho */
.btn-tema{display:flex;align-items:center;gap:6px;padding:8px 12px;
  font-size:13px;white-space:nowrap}
.btn-tema .icone-tema{display:flex;align-items:center;line-height:0}

/* Sugestoes de aluno quando o OCR leu o nome mas nao casou com a lista. */
.ocr-sugestoes { display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
                 margin-top: 6px; }
/* O mesmo chip serve ao editor de nome da lista de correcoes: e o mesmo
   gesto (tocar no que o cartao dizia em vez de digitar), e desenhar dois
   jeitos para a mesma coisa e como o professor deixa de reconhece-la. */
/* O chip e um atalho de toque ("era este nome aqui"), entao segue a mesma
   regra de alvo minimo dos botoes — com 4px de padding ele tinha 22px. */
.chip { display:inline-flex; align-items:center; min-height:40px;
        padding: 6px 14px; border-radius: 99px; cursor: pointer;
        border: 1px solid var(--line); background: var(--surface-2);
        color: var(--text); font-size: 14px;
        touch-action:manipulation; -webkit-tap-highlight-color:transparent; }


/* ============================================================
   Navegacao em abas: barra do topo, sub-abas e cabecalho de tela
   ============================================================
   ⚠️ SUB-ABA E SUBLINHADO, ABA DO TOPO E PILULA CHEIA. As duas barras ficam
   uma embaixo da outra na avaliacao aberta; desenhadas igual, o professor
   nao enxergava qual das duas o levava para fora da prova. A diferenca de
   FORMA (nao so de cor) e o que separa os dois niveis. */
/* ⚠️ A BARRA ROLA DE LADO, E A ROLAGEM PRECISA SER MACIA NO CELULAR. Sao
   quatro sub-abas na avaliacao e seis no cadastro: em tela de 360px as ultimas
   ficam fora da largura. O `scroll-snap` para em aba inteira, nunca no meio de
   uma palavra, e a barra de rolagem some — no touch ela so ocupa altura. */
.sub-abas{display:flex;gap:2px;margin:0 0 18px;overflow-x:auto;
  -webkit-overflow-scrolling:touch;scroll-snap-type:x proximity;
  scrollbar-width:none;border-bottom:1px solid var(--line)}
.sub-abas::-webkit-scrollbar{display:none}
.sub-tab{background:transparent;border:0;border-bottom:2px solid transparent;
  border-radius:0;padding:10px 16px;min-height:46px;color:var(--muted);
  font-weight:600;white-space:nowrap;scroll-snap-align:start}
.sub-tab.active{color:var(--accent);border-bottom-color:var(--accent)}

/* Cabecalho de uma tela: titulo a esquerda, filtros e acao a direita. Substitui
   o card "Nova avaliacao" que abria a aba ocupando a primeira dobra. */
.barra-tela{display:flex;gap:10px;align-items:flex-end;flex-wrap:wrap;
  margin-bottom:16px}
.barra-tela .sp{flex:1}
.barra-tela p{margin:3px 0 0}
.titulo-tela{margin:0;font-size:18px;text-transform:none;letter-spacing:0;
  color:var(--text)}
@media(max-width:700px){
  .barra-tela{align-items:stretch}
  .barra-tela select,.barra-tela input{max-width:none!important;flex:1}
}

/* A lista de avaliacoes nao mora mais dentro de um card: item sobre o fundo
   da pagina precisa da cor de superficie, senao vira uma faixa apagada. */
#exam-list .item{background:var(--surface);padding:14px}

/* ---------- cabecalho da avaliacao aberta ---------- */
.exam-topo{display:flex;gap:12px;align-items:center;flex-wrap:wrap;
  background:var(--surface);border:1px solid var(--line);
  border-radius:var(--radius);padding:12px 16px;margin-bottom:10px}
.exam-nome{font-weight:600;font-size:17px}
/* A pilula fica sobre `--surface`, a mesma cor do fundo dela: sem trocar para
   `--surface-2` sobrava so a borda. */
.exam-topo .pill{background:var(--surface-2)}
.exam-topo .grow{flex:1;min-width:180px}
.btn-voltar{background:transparent;border-color:transparent;color:var(--muted);
  padding-left:0}
.exam-descricao{margin:0 0 14px;padding:0 2px}
/* Gabarito incompleto e o unico estado da pilula que pede acao. */
.pill-alerta{color:var(--warn);border-color:var(--warn)}

/* ============================================================
   Historico — a linha do tempo das provas aplicadas
   ============================================================ */
.hist-mes{margin:24px 0 10px;padding-bottom:6px;font-size:12px;font-weight:600;
  text-transform:uppercase;letter-spacing:.7px;color:var(--muted);
  border-bottom:1px solid var(--line)}
.hist-mes:first-child{margin-top:4px}
.hist-item{display:flex;gap:14px;align-items:center;flex-wrap:wrap;
  padding:12px 16px;margin-bottom:8px;background:var(--surface);
  border:1px solid var(--line);border-radius:var(--radius)}
.hist-item .grow{flex:1;min-width:200px}
.hist-item .grow b{display:block;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
.hist-item .grow span{display:block}
/* O dia grande e o que faz a lista virar linha do tempo: da para varrer a
   coluna da esquerda procurando "a prova do dia 12" sem ler nome nenhum. */
.hist-dia{flex:0 0 48px;width:48px;text-align:center;padding-right:12px;
  border-right:1px solid var(--line)}
.hist-dia b{display:block;font-size:20px;line-height:1.15;
  font-variant-numeric:tabular-nums}
.hist-dia span{font-size:11px;text-transform:uppercase;letter-spacing:.4px;
  color:var(--muted)}
/* Prova criada e ainda nao aplicada: presente na lista, mas sem o peso de
   quem ja tem nota. */
.hist-pendente{border-style:dashed;opacity:.75}

/* A nota media diz sozinha como a turma foi. Mesmos cortes do indice de
   dificuldade dos relatorios, para as duas telas nao se contradizerem. */
.score.nota-boa{color:var(--ok)}
.score.nota-media{color:var(--warn)}
.score.nota-baixa{color:var(--err)}

@media(max-width:600px){
  .hist-dia{flex-basis:40px;width:40px;padding-right:10px}
  .hist-item{gap:10px;padding:12px}
}


/* ============================================================
   Planos e precos — os tres niveis da venda
   ============================================================ */
.plano-linha{display:flex;gap:12px;align-items:flex-end;flex-wrap:wrap;
  padding:12px 14px;margin-bottom:8px;background:var(--surface-2);
  border:1px solid var(--line);border-radius:8px}
.plano-linha .grow{flex:1;min-width:200px}
.plano-linha .grow b{display:block;margin-bottom:2px}
.plano-linha .grow span.muted{display:block}
.plano-valor label{margin:0 0 4px}
.plano-valor input{width:130px}
/* Plano sem campo de preco (combo-incluido e personalizado): a frase ocupa o
   lugar do campo, para a linha nao parecer quebrada. */
.plano-fixo{max-width:260px;text-align:right}
@media(max-width:600px){.plano-fixo{max-width:none;text-align:left}}

/* Pilula do plano no cartao do usuario. Difere das outras por ter fundo: e a
   informacao que responde "quem esta no combo?" numa varredura da lista. */
.pill-plano{background:var(--surface-2);color:var(--text);border-color:var(--line);
  margin-left:0}
.plano-nota{flex:1;min-width:160px;padding-bottom:9px}

/* ⚠️ A confirmacao de SAIDA DO COMBO nasce dentro do cartao, nao num
   `confirm()` do navegador. Sao TRES caminhos (cobrar nos dois, desativar nos
   dois, cancelar) e o dialogo nativo so tem dois botoes — a terceira opcao
   viraria um segundo popup, ou pior, um padrao escolhido por nos. */
.saida-combo{border:2px solid var(--warn);border-radius:10px;padding:14px;
  margin:10px 0 0;background:var(--surface)}
.saida-combo b{display:block;color:var(--warn);margin-bottom:4px}
.saida-combo p{margin:0 0 12px}


/* ============================================================
   Questao sem resposta — editor de gabarito E resultado da correcao
   ============================================================
   Um risco por cima das cinco alternativas, como quem corta a linha no papel.

   ⚠️ AS DUAS TELAS USAM ESTE MESMO RISCO, de proposito. E o mesmo estado da
   mesma prova ("esta questao nao tem resposta"), e enquanto o resultado da
   correcao marcava isso com uma pilula laranja escrita "em branco", quem
   riscava no editor procurava o risco no resultado e achava outra coisa.
   Duas aparencias para um estado so e o professor tendo de aprender a mesma
   informacao duas vezes.

   ⚠️ A COR E `--text`, NAO BRANCO FIXO. No tema escuro `--text` ja e quase
   branco, que e o risco pedido; branco cravado sumiria no tema claro, onde as
   bolhas ficam sobre fundo claro — o aviso viraria invisivel justamente para
   quem usa o painel de dia.

   ⚠️ E O RISCO E DESENHADO NAS CELULAS, nao na linha. Um `::after` na
   `.key-row` teria de saber onde a coluna do assunto comeca, e ela e `1.6fr` —
   largura que so existe depois do layout. Nas celulas, cada uma risca a si
   mesma e o vao de 6px entre elas e coberto por 4px de sobra de cada lado. */
.key-row.em-branco .opt{position:relative}
.key-row.em-branco .opt::after{
  content:"";position:absolute;pointer-events:none;
  top:50%;margin-top:-1px;height:2px;border-radius:2px;
  left:-4px;right:-4px;background:var(--text);opacity:.75}
/* As pontas param na borda da primeira e da ultima bolha: sobra para fora da
   grade pareceria rabisco, e nao marcacao.

   ⚠️ `:last-of-type`, e nao `:nth-child(6)`. Sao cinco alternativas hoje, mas
   quem manda e `state.layout.options`, que vem do servidor: fixar o numero na
   folha de estilo faria a ponta direita escapar 4px no dia em que o layout
   mudasse. Funciona porque o que vem depois das alternativas nunca e uma
   `div`: no editor e um `input` (o assunto) e no resultado da correcao e um
   `span` (o selo de dupla marcacao) — entre as `div`s da linha, a ultima e
   sempre a ultima alternativa.

   No celular nada muda: a media query de 700px so manda o assunto para a
   segunda linha da grade; as cinco alternativas continuam lado a lado, e o
   risco vive DENTRO de cada uma delas. */
.key-row.em-branco .opt:nth-child(2)::after{left:0}
.key-row.em-branco .opt:last-of-type::after{right:0}


/* ============================================================
   Toque: o app e usado com o celular numa mao e a pilha de provas na outra
   ============================================================ */

/* ⚠️ HOVER SO ONDE EXISTE PONTEIRO DE VERDADE. No touch nao ha "passar por
   cima": o navegador aplica o `:hover` no TOQUE e ele fica GRUDADO ate o
   professor tocar em outro lugar. O resultado era uma lista com dois itens
   destacados ao mesmo tempo (o que ele abriu e o ultimo em que encostou) e um
   botao aceso que ninguem selecionou — e o realce de "aba ativa" perdia o
   sentido, porque tudo o que foi tocado continuava aceso. */
@media (hover:hover) and (pointer:fine){
  button:hover{border-color:var(--accent)}
  .btn-social:hover{border-color:var(--accent)}
  .nav-topo .tab:hover{color:var(--text);border-color:var(--line)}
  .sub-tab:hover{color:var(--text);border-color:transparent;
  border-bottom-color:var(--line)}
  .btn-voltar:hover{color:var(--text)}
  .hist-item:hover{border-color:var(--accent)}
  .hist-pendente:hover{opacity:1}
  .turma-check:hover{border-color:var(--accent)}
  .chip:hover { border-color: var(--accent); }
}

/* ⚠️ O QUE SUBSTITUI O HOVER NO CELULAR E O `:active`: sem nenhuma resposta ao
   toque, um botao que demora meio segundo para responder parece nao ter sido
   tocado — e o professor toca de novo. Dois toques em "Salvar gabarito" e um
   POST duplicado; dois em "Capturar agora" CANCELAM a contagem (o segundo
   toque desiste, ver camera.js) e a foto nunca sai. Encolher 3% enquanto o
   dedo esta em cima e a confirmacao imediata de que o toque pegou. */
button:active:not(:disabled),.opt:active,.chip:active,.turma-check:active,
.tab:active,.sub-tab:active{transform:scale(.97)}
button,.opt,.chip,.turma-check{transition:transform .06s ease}
@media (prefers-reduced-motion:reduce){
  button:active:not(:disabled),.opt:active,.chip:active,.turma-check:active,
  .tab:active,.sub-tab:active{transform:none}
  button,.opt,.chip,.turma-check{transition:none}
}
/* Sem o realce azul do Android, que so aparece DEPOIS do toque e num tom que
   nao e o do app — o `:active` acima ja responde, e responde antes. */
a,label,summary{-webkit-tap-highlight-color:transparent}

/* Link solto no meio de uma linha de botoes ("Folha padrao (PDF)", na tela de
   entrada) tambem e alvo de toque: como texto corrido ele tem 18px de altura,
   metade do dedo, e fica a 8px do botao "Criar conta". */
.row > a{display:inline-flex;align-items:center;min-height:44px}

/* Quem navega por teclado continua vendo onde esta: o `outline` padrao some
   junto com o realce de toque em varios navegadores. */
:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

/* ⚠️ O CABECALHO E `sticky`: sem `scroll-margin-top`, todo `scrollIntoView`
   entrega o elemento DEBAIXO dele. Vale para o cartao de confirmacao do nome
   (correcao.js) e para o visor da camera: o professor toca em "Abrir camera",
   a pagina rola, e o topo do video fica escondido atras da barra de abas. */
.card,.confirm-card,.cam-stage,#camera-wrap,#key-camera-wrap,#scan-result,
.exam-topo,.barra-tela{scroll-margin-top:120px}

/* ============================================================
   Celular: uma coluna, alvos maiores, menos moldura
   ============================================================ */
@media(max-width:640px){
  /* Menos moldura sobra mais tela para o conteudo: 20px de padding no `main`
     mais 18px no card comiam 76px dos 360px de largura de um celular comum. */
  main{padding:14px max(14px,env(safe-area-inset-right))
             max(14px,calc(env(safe-area-inset-bottom) + 16px))
             max(14px,env(safe-area-inset-left))}
  .card{padding:14px;margin-bottom:12px}
  body{font-size:16px}
  header{padding-top:10px;padding-bottom:10px;gap:8px}
  /* ⚠️ O TITULO SAI DA VISTA, MAS NAO DO DOCUMENTO. "Corretor de Prova" ocupava
     metade da largura do cabecalho e empurrava o "Sair" para uma segunda linha
     — dois nomes ("Corretor de Prova" e o do professor) e tres botoes nao cabem
     em 360px. E ele nao informa nada: quem abriu o app sabe em que app esta, e
     o logo continua ali dizendo isso.
     ⚠️ E NAO E `display:none`. O logo e decorativo (`alt=""`), entao este h1 e
     o unico nome acessivel da tela: escondido de vez, quem usa leitor de tela
     abriria uma pagina sem titulo nenhum. Escondido assim, ele sai dos pixels
     e continua sendo lido. */
  header h1{position:absolute;width:1px;height:1px;margin:-1px;padding:0;
    overflow:hidden;white-space:nowrap;clip-path:inset(50%)}
  /* A logo esta em `scale(1.8)` ancorada a esquerda: no celular e ela que
     empurra o titulo para fora antes de qualquer outra coisa. */
  header .logo{transform:scale(1.5)}
  /* O rotulo "Escuro"/"Claro" e redundante ao lado do proprio icone, e e o que
     faz o cabecalho quebrar em mais uma linha em tela estreita. */
  #rotulo-tema{display:none}
  .btn-tema{padding:8px 10px}

  /* ⚠️ BOTAO DE ACAO OCUPA A LARGURA DA LINHA. Meia duzia de botoes de 100px
     numa linha que quebra e um campo minado para o polegar; esticados, cada um
     e uma faixa inteira e o toque nao tem como cair no vizinho.
     ⚠️ MENOS OS DESTRUTIVOS (`.danger`): "Excluir todas as avaliacoes" com a
     largura da tela viraria o maior alvo da pagina — exatamente o contrario do
     que ele deve ser. Fica no tamanho do texto, como estava. */
  .row > button:not(.danger){flex:1 1 auto}

  /* ⚠️ O CABECALHO DA TELA VIRA TRES FAIXAS: titulo, filtros, acao. Numa linha
     so, o titulo ("Minhas avaliacoes") e o espacador empurram os filtros para
     um canto de ~70px — dois seletores tao estreitos que nao mostram o nome da
     turma que esta selecionada. E o filtro que nao se le e um filtro que o
     professor nao usa: ele volta a rolar a lista inteira procurando a prova. */
  .barra-tela > div:first-child{flex:1 1 100%}
  .barra-tela .sp{display:none}
  .barra-tela select,.barra-tela input{flex:1 1 140px}
  .barra-tela > button{flex:1 1 100%}
  /* ⚠️ O ITEM DA LISTA VIRA DUAS LINHAS, NAO QUATRO COLUNAS. Informacao, nota
     e dois botoes lado a lado em 360px espremiam o titulo ate "P...": o
     `.grow` tem `min-width:0` (e o que faz o reticencias funcionar) e por isso
     cede espaco ate sumir, enquanto os botoes nao cedem nada. Uma lista de
     provas em que nenhum titulo se le e uma lista inutil. Com a informacao na
     faixa inteira o nome cabe, e a nota e os botoes dividem a linha de baixo —
     que de quebra e a linha em que o polegar chega primeiro. */
  .item{padding:14px}
  .item > .grow{flex:1 1 100%}
  .item > button{flex:1 1 auto}

  /* O numerao da nota e o que se le de relance ao passar a lista. */
  .score{font-size:24px}
  .barra-linha{grid-template-columns:56px 1fr 92px;gap:8px}
  /* Alvo de toque tambem na grade do gabarito: a coluna do numero da questao
     encolhe para sobrar largura para as cinco alternativas, que sao o que se
     toca. */
  .key-row{grid-template-columns:30px repeat(5,1fr);gap:7px}
  .key-row.com-assunto{grid-template-columns:30px repeat(5,1fr)}
  .opt{min-height:50px;font-size:16px}
  /* O aviso ocupa a largura toda: centrado e estreito, cabiam duas palavras
     por linha. */
  #toast{left:12px;right:12px;transform:none;max-width:none;text-align:center}
}

/* ============================================================
   Tabelas de relatorio no celular
   ============================================================
   ⚠️ ABAIXO DE 760px O CABECALHO DA TABELA SOME (nao ha largura para cinco
   colunas) — e sem ele sobrava uma grade de numeros soltos: "8,4 / 6,1 / 3,2"
   sem dizer qual e a media, qual a melhor e qual a pior nota. O nome da coluna
   passa a viajar em cada celula (`data-rotulo`, carimbado por
   `rotularTabela()` em base.js a partir do proprio cabecalho). */
@media(max-width:760px){
  .q-linha{padding:12px;row-gap:8px}
  .q-linha > [data-rotulo]::before{
    content:attr(data-rotulo);display:block;font-size:11px;font-weight:600;
    text-transform:uppercase;letter-spacing:.4px;color:var(--muted);
    margin-bottom:1px}
  /* A primeira coluna e a identidade da linha (o aluno, a questao, o assunto):
     ocupa a faixa inteira, como o titulo do bloco. */
  .q-linha > :first-child{grid-column:1 / -1;font-weight:600}
  .q-linha > :first-child[data-rotulo]::before{display:none}
}

/* ============================================================
   Celular deitado
   ============================================================
   O manifesto pede retrato, mas isso so vale para o app instalado — no
   navegador o professor gira o aparelho a hora que quiser. Deitado sobram
   ~380px de altura: com o visor em 44dvh (~165px) o quadro fica pequeno demais
   para enquadrar o cartao, e e ele quem tem de ganhar o espaco que resta. O
   cabecalho para de grudar no topo pelo mesmo motivo — deitado ele custa um
   terco da altura util. */
@media(orientation:landscape) and (max-height:560px){
  .cam-stage{height:min(66dvh,300px)}
  header{position:static}
}
