/* ======================================================================
   COMPONENTES — botão, formulário, tabela, card, badge, alerta.
   Tabela vira card abaixo de 880px (spec D12): nunca scroll horizontal.
====================================================================== */

/* ---- Botões ---------------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: var(--toque-min);
  padding: 0 18px;
  border-radius: var(--r-md);
  font-size: 15px; font-weight: 500;
  transition: background var(--transicao);
}
.btn--primario { background: var(--primaria-800); color: var(--branco); }
.btn--primario:hover { background: var(--primaria-900); }
.btn--secundario {
  background: var(--branco); color: var(--neutro-700);
  border: 1px solid var(--neutro-300);
}
.btn--secundario:hover { background: var(--neutro-100); }
.btn--perigo { background: var(--perigo-700); color: var(--branco); }
.btn[disabled] { opacity: 0.5; cursor: not-allowed; }

/* ---- Formulário ------------------------------------------------------ */
.campo { margin-bottom: 16px; }
.campo__rotulo {
  display: block; margin-bottom: 6px;
  font-size: 13px; font-weight: 500; color: var(--neutro-700);
}
.campo__controle {
  width: 100%;
  min-height: var(--toque-min);
  padding: 10px 12px;
  border: 1px solid var(--neutro-300);
  border-radius: var(--r-md);
  background: var(--branco);
  color: var(--neutro-900);
  transition: border-color var(--transicao);
}
.campo__controle:focus { border-color: var(--primaria-500); }
.campo__controle[aria-invalid='true'] { border-color: var(--perigo-700); }

/* Marca de EXCEÇÃO no lançamento de conceito: uma faixa na borda esquerda
   do próprio campo, para o conceito que a professora digitou no lugar do
   calculado.

   Faixa, e não um texto abaixo do campo: o texto ("manual"/"(derivado)")
   deixava a célula mais alta que as vizinhas e desalinhava a linha inteira
   da grade. Esta ocupa ZERO altura.

   O `padding-left` desconta os 3px da faixa para o conteúdo do campo NÃO
   se deslocar: o campo normal tem `border: 1px` + `padding-left: 12px` = 13px
   de recuo até o texto; o marcado troca a borda por `border-left: 3px`, e
   por isso o `padding-left` cai para 10px (3 + 10 = 13) — não 9, que deixaria
   1px de diferença. Campo marcado e campo normal ficam com o texto na
   mesma coluna, lado a lado.

   Cor sozinha não basta (daltonismo). A faixa é mudança de FORMA — borda
   grossa de um lado só — e a view sempre acompanha com
   `title="Digitado pela professora"`. */
.campo__controle--manual {
  border-left: 3px solid var(--primaria-500);
  padding-left: 10px;
}

/* O mesmo traço, em miniatura, para a legenda sob a tabela. É o próprio
   elemento, não o caractere "▍": um caractere depende de a fonte tê-lo, e
   a Inter Tight é auto-hospedada com um subconjunto. */
.legenda-marca {
  display: inline-block;
  width: 3px;
  height: 12px;
  margin-right: 6px;
  vertical-align: -1px;
  background: var(--primaria-500);
}

/* Fechamento anual (D-2.10): os estados de uma célula da grade que pedem
   atenção antes de confirmar, na mesma FORMA de campo__controle--manual
   acima -- borda grossa de um lado só, nunca só cor (daltonismo). Duas
   variantes porque são dois momentos diferentes: `--conferir` é ANTES da
   decisão (empate ou bimestre faltando -- a coordenação ainda precisa
   olhar); `--ajustado` é DEPOIS (a coordenação já escolheu um conceito
   diferente do calculado, e a escolha ficou registrada). */
.campo__controle--conferir {
  border-left: 3px solid var(--aviso-500);
  padding-left: 10px;
}
.campo__controle--ajustado {
  border-left: 3px solid var(--primaria-500);
  padding-left: 10px;
}

/* A sugestão calculada, ao lado do campo -- nunca dentro dele (R40: o
   <select> nunca vem com a sugestão pré-selecionada, só o valor já
   confirmado ou vazio). Texto pequeno e discreto de propósito: é uma
   dica, não um resultado. */
.fechamento-dica {
  display: block;
  margin-top: 4px;
  font-size: 11px;
  color: var(--neutro-500);
}

/* Componente nunca lançado (D-2.10, exigência 3): "—" sem campo. O
   `cursor: help` avisa que há um title por trás, para quem usa mouse; o
   texto do title já carrega o significado para quem usa leitor de tela. */
.fechamento-vazio {
  color: var(--neutro-400);
  cursor: help;
}

/* Campo mostrado só para conferência (nome e login em "Meu perfil").
   Precisa PARECER travado: um campo que aceita o cursor mas descarta o
   que foi digitado é pior que um campo cinza. */
.campo__controle[readonly],
.campo__controle[disabled] {
  background: var(--neutro-100);
  color: var(--neutro-600);
  cursor: not-allowed;
}
.campo__controle[readonly]:focus { border-color: var(--neutro-200); }
/* Campo de senha com botão de revelar. A caixa é criada por
   assets/js/senha-revelar.js; sem JavaScript o campo continua sendo um
   campo de senha comum, e nada aqui atrapalha. */
.campo__senha { position: relative; display: flex; }
.campo__senha .campo__controle { padding-right: var(--toque-min); }
.campo__senha-olho {
  position: absolute; right: 0; top: 0; bottom: 0;
  width: var(--toque-min);
  display: flex; align-items: center; justify-content: center;
  color: var(--neutro-500);
  border-radius: 0 var(--r-md) var(--r-md) 0;
  transition: color var(--transicao);
}
.campo__senha-olho:hover { color: var(--neutro-800); }
.campo__senha-olho svg { width: 18px; height: 18px; }
/* Campo de senha com "Gerar senha" ao lado (assets/js/senha-gerar.js). */
.campo__senha-linha { display: flex; gap: 8px; align-items: stretch; }
.campo__senha-linha .campo__senha { flex: 1; min-width: 0; }
.campo__senha-linha .btn { white-space: nowrap; }

.campo__erro { margin-top: 4px; font-size: 13px; color: var(--perigo-700); }
.campo__ajuda { margin-top: 4px; font-size: 12px; color: var(--neutro-500); }

.form-grade { display: grid; gap: 0 16px; grid-template-columns: 1fr; }
@media (min-width: 768px) {
  .form-grade--2 { grid-template-columns: 1fr 1fr; }
  .form-grade--3 { grid-template-columns: 1fr 1fr 1fr; }
}

/* Barra de ação fixa no rodapé em formulário longo (spec D12). */
.acoes-fixas {
  position: sticky; bottom: var(--bottomnav-altura);
  display: flex; gap: 10px; justify-content: flex-end;
  padding: 12px 0;
  /* Acompanha o fundo do body: barra de outra cor sobre a lista dá a
     impressão de que a página terminou ali. */
  background: var(--neutro-50);
  border-top: 1px solid var(--neutro-200);
}
@media (min-width: 1024px) { .acoes-fixas { bottom: 0; } }

/* ---- Card ------------------------------------------------------------ */
.card {
  background: var(--branco);
  border: 1px solid var(--neutro-200);
  border-radius: var(--r-lg);
  box-shadow: var(--sombra-sm);
  padding: 20px;
  margin-bottom: 16px;
}
.card__titulo {
  font-size: 16px; font-weight: 600; color: var(--neutro-900);
  margin-bottom: 16px;
}

/* ---- Tabela que vira card no celular --------------------------------- */
.tabela th, .tabela td {
  padding: 12px;
  text-align: left;
  border-bottom: 1px solid var(--neutro-200);
}
.tabela th {
  font-size: 12px; text-transform: uppercase; letter-spacing: 0.03em;
  color: var(--neutro-500); font-weight: 600;
}

/* Tabelas irmãs (a folha: uma por categoria) com as MESMAS larguras de coluna
   no desktop — o <colgroup> da view manda. No celular a tabela vira cartão e
   a regra não se aplica. */
@media (min-width: 880px) {
  .tabela--colunas-fixas { table-layout: fixed; }
}

@media (max-width: 879px) {
  .tabela thead { display: none; }
  .tabela tr {
    display: block;
    background: var(--branco);
    border: 1px solid var(--neutro-200);
    border-radius: var(--r-lg);
    margin-bottom: 12px;
    padding: 8px 12px;
  }
  .tabela td {
    display: flex; justify-content: space-between; gap: 12px;
    border-bottom: 1px solid var(--neutro-100);
    padding: 8px 0;
  }
  /* Quebra de linha em célula de TEXTO ou BOTÕES, nunca em célula com CAMPO.
     Medido a 390 px em 13/09/2026, nos perfis da escola:
       - sem quebra, a célula de ações de Mensalidades (até cinco botões) e a
         Descrição longa do Caixa alargavam a tabela, e a página rolava de lado;
       - com quebra em TODA célula, o seletor de conceito ia para baixo do nome
         do item, e o lançamento da turma da Infantil ficou 36% mais comprido
         (3.706 → 5.034 px por aluna).
     `:has()` separa os dois casos. Navegador sem `:has()` fica sem quebra —
     o comportamento de antes —, e a regra do rótulo vazio garante ao menos a
     célula de botões. */
  .tabela td[data-rotulo=""],
  .tabela td:not(:has(input, select, textarea)) { flex-wrap: wrap; }
  .tabela tr td:last-child { border-bottom: none; }
  /* O rótulo da coluna vem do atributo data-rotulo de cada <td>. */
  .tabela td::before {
    content: attr(data-rotulo);
    font-size: 12px; font-weight: 600; color: var(--neutro-500);
  }
}

/* ---- Badge ----------------------------------------------------------- */
.badge {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 10px;
  border-radius: var(--r-full);
  font-size: 12px; font-weight: 500;
}
.badge--sucesso { background: var(--sucesso-100); color: var(--sucesso-700); }
.badge--aviso   { background: var(--aviso-100); color: var(--aviso-700); }
.badge--erro    { background: var(--perigo-100);  color: var(--perigo-700); }
.badge--neutro  { background: var(--neutro-200); color: var(--neutro-700); }

/* ---- Alerta ---------------------------------------------------------- */
.alerta {
  padding: 12px 16px;
  border-radius: var(--r-md);
  margin-bottom: 16px;
  font-size: 14px;
}

/* Rematrícula (Task 12, achado 1) grava o resultado do lote como uma
   única mensagem de Flash multilinha ("N criadas" + um erro nomeado por
   linha), e `pre-line` é o que faz aqueles \n virarem linhas de verdade.
   Ele mora AQUI, e não em `.alerta`, por causa de um defeito visto na
   homologação de 04/09/2026: `pre-line` honra as quebras do CÓDIGO-FONTE
   também, então todo alerta cujo markup foi escrito em mais de uma linha
   no template saía quebrado no meio da frase — o aviso de matéria sem
   professor, no painel, quebrava em quatro. O comentário original dizia
   "não muda nada nos alertas de uma linha só", e era verdade para os
   alertas montados de uma STRING; era falso para os montados de MARKUP,
   que são a maioria dos 48 do projeto.

   Se um dia outro lugar precisar de mensagem multilinha, ele usa esta
   mesma classe — nunca devolva `pre-line` para `.alerta`. */
.alerta--texto { white-space: pre-line; }
.alerta--sucesso { background: var(--sucesso-100); color: var(--sucesso-700); }
.alerta--erro    { background: var(--perigo-100);  color: var(--perigo-700); }
.alerta--aviso   { background: var(--aviso-100); color: var(--aviso-700); }
.alerta--info    { background: var(--primaria-100);   color: var(--primaria-800); }
