/*
 * Estilo da aplicacao. NENHUM valor de cor aqui -- todos vem de tokens.css.
 *
 * Referencia visual: densidade alta sem aperto, hierarquia por peso e espaco em vez de cor,
 * superficies separadas por borda de 1px.
 */

/*
 * A fonte no BODY nao basta: campos de formulario, botoes e tabelas herdam do agente do
 * usuario, nao do body. Sem a segunda regra, metade da interface continua em Arial -- e a
 * diferenca so aparece nos formularios, que e onde ninguem repara de imediato.
 */
body {
  background: var(--cp-fundo);
  color: var(--cp-texto);
  font-family: var(--cp-fonte);
  font-size: 0.9375rem;
}

input,
select,
textarea,
button,
.form-control,
.form-select,
.btn,
table {
  font-family: var(--cp-fonte);
}

/* -- Esqueleto: sidebar fixa + conteudo ---------------------------------------------------- */

/*
 * A SIDEBAR OCUPA A LATERAL INTEIRA, e a navbar comeca onde ela termina.
 *
 * Era o contrario: a navbar atravessava a largura toda e a sidebar comecava abaixo dela. A
 * objecao contra este desenho estava escrita aqui -- a marca ficaria numa faixa horizontal e o
 * menu do usuario em outra, e o olho passaria a procurar a identidade em dois lugares. Ela e
 * legitima, e a mudanca so vale porque a RESOLVE em vez de aceita-la: a marca desce para o
 * cabecalho da sidebar, no alto da coluna que ela agora encabeca, e some da navbar acima de lg.
 * Uma marca so, num lugar so.
 *
 * As duas faixas de cabecalho tem a MESMA ALTURA de proposito (`--cp-navbar-altura` nas duas), e
 * e o que faz o fio inferior da sidebar-header encontrar o da navbar numa linha continua
 * atravessando a tela. Alturas diferentes deixam um degrau de poucos pixels bem no ponto para
 * onde o olho vai primeiro.
 *
 * A colocacao e EXPLICITA nos tres filhos, e nao por posicionamento automatico. A ordem no DOM e
 * navbar, sidebar, conteudo -- que nao e a ordem visual --, e o automatico preencheria as
 * celulas nessa sequencia, jogando a sidebar para a direita.
 */
.cp-app {
  display: grid;
  grid-template-columns: var(--cp-sidebar-largura) 1fr;
  grid-template-rows: auto 1fr;
  min-height: 100dvh;
}

.cp-conteudo {
  grid-column: 2;
  grid-row: 2;
  padding: 1.5rem;
  min-width: 0;               /* sem isto, uma tabela larga estica o grid e quebra o layout */

  /* Coluna, para o rodape poder ser empurrado ao fim mesmo com pouco conteudo. */
  display: flex;
  flex-direction: column;
}

/*
 * O rodape vai para o fim da area de conteudo, e nao logo abaixo do que houver.
 *
 * Sem o margin-top:auto, numa tela curta ele apareceria colado no ultimo elemento, no meio da
 * pagina -- lido como parte do conteudo, e nao como rodape.
 */
.cp-rodape {
  margin-top: auto;
  padding-top: 1.5rem;
  display: flex;
  align-items: center;
  gap: 0.375rem;
  color: var(--cp-texto-suave);
  font-size: 0.75rem;
}

/* O link do rodape acompanha o tom apagado dele: e referencia, e nao chamada para clicar. */
.cp-rodape a {
  color: inherit;
  text-decoration: underline;
}

.cp-rodape a:hover {
  color: var(--cp-primaria);
}

/*
 * Abaixo de lg a sidebar vira gaveta (offcanvas-lg do Bootstrap), sai do fluxo, e o conteudo
 * ocupa a largura inteira.
 *
 * A COLUNA 2 PRECISA VOLTAR A SER A 1 AQUI. Sobrou uma coluna so na grade, e `grid-column: 2`
 * num filho pede uma coluna que nao foi declarada: o navegador CRIA uma implicita e a navbar sai
 * empurrada para fora da tela, com a largura da faixa vazia a esquerda. Nao e erro de sintaxe --
 * a grade simplesmente cresce, calada.
 */
@media (max-width: 991.98px) {
  .cp-app {
    grid-template-columns: 1fr;
  }

  /*
   * O SELETOR LEVA `.cp-app >` POR CAUSA DA ORDEM, e nao por escopo.
   *
   * Esta media query mora na secao do esqueleto, ANTES das regras de `.cp-navbar` e
   * `.cp-sidebar` la embaixo. Com `.cp-navbar` puro, as duas empatam em especificidade e a de
   * baixo vence por vir depois -- inclusive dentro da media query, que nao acrescenta peso
   * nenhum. O sintoma foi exatamente este: em tela estreita o conteudo obedecia (a regra dele
   * vem antes) e a navbar nao, entao ela ficava deslocada para a direita, do tamanho de uma
   * sidebar que nem estava na tela.
   *
   * Filho direto vale mais que classe solta e resolve sem `!important` -- e mantem as regras de
   * responsividade juntas, que e onde quem procura vai olhar.
   */
  .cp-app > .cp-navbar,
  .cp-app > .cp-conteudo {
    grid-column: 1;
  }

  .cp-conteudo {
    padding: 1rem;
  }
}

/* -- Navbar: ao lado da sidebar, sempre visivel --------------------------------------------- */

.cp-navbar {
  /* Coluna 2: ela COMECA onde a sidebar termina, em vez de passar por cima dela. */
  grid-column: 2;
  grid-row: 1;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  height: var(--cp-navbar-altura);
  padding: 0 1rem;
  background: var(--cp-superficie);
  border-bottom: 1px solid var(--cp-borda);

  /* Gruda no topo ao rolar. O z-index continua alto nao por causa da sidebar -- as duas ja nao
     se sobrepoem --, mas porque os menus que descem daqui precisam passar por cima do conteudo. */
  position: sticky;
  top: 0;
  z-index: 1030;
}

/* O seletor de organizacao na navbar.

   O botao foi desenhado para ocupar a largura da sidebar (`width: 100%`); aqui ele e um controle
   entre outros, entao a largura vem do CONTEUDO -- com teto, para um nome longo nao empurrar o
   tema e o menu do usuario para fora da faixa. */
.cp-navbar .cp-org-botao {
  width: auto;
  max-width: 18rem;
  padding: 0.375rem 0.625rem;
  font-size: 0.875rem;
}

/* O menu tinha `w-100` no HTML -- largura da sidebar. Preso a largura do botao na navbar, ele
   ficaria estreito demais para os nomes que lista. */
.cp-navbar .cp-org .dropdown-menu {
  min-width: 16rem;
}

/*
 * OS BOTOES DE ICONE DA NAVBAR -- sem moldura, sem fundo, sem hover de caixa.
 *
 * Eram `btn btn-outline-secondary`: tres retangulos com borda numa faixa que ja tem borda
 * embaixo, seletor de organizacao com borda e avatar ao lado. O peso todo vinha da CAIXA, e nao
 * do simbolo -- que e o que a pessoa procura. Sem ela, o alvo de clique continua o mesmo tamanho
 * (o padding permanece), e quem muda no hover e o icone.
 *
 * O ICONE CONTINUA SOLIDO, e isso e uma limitacao medida, nao uma escolha: a familia vazada do
 * FontAwesome Free nao tem `fa-gear`, `fa-bars` nem `fa-circle-half-stroke` -- os tres saem como
 * quadrado vazio, conferido no navegador. O efeito de "vazado" aqui vem do ESPACO em volta, e
 * da cor suave que so fecha no hover.
 *
 * `position: relative` E OBRIGATORIO: o selo de contagem das atividades e `position: absolute`
 * ancorado neste botao. Ele vinha do `position-relative` no HTML, que sai junto com as classes
 * do Bootstrap -- sem esta linha, o selo iria se pendurar na navbar inteira e apareceria no
 * canto da tela.
 */
.cp-btn-icone {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  position: relative;
  padding: 0.25rem 0.5rem;
  border: 0;
  background: transparent;
  color: var(--cp-texto-suave);
  font-size: 0.875rem;
  line-height: 1;
  transition: color var(--cp-transicao);
}

.cp-btn-icone:hover {
  color: var(--cp-texto);
}

/*
 * O ANEL DE FOCO PRECISA SER REPOSTO A MAO.
 *
 * Quem o desenhava era o `.btn` do Bootstrap, que saiu junto com a moldura. Sem esta regra, quem
 * navega por teclado perde o botao de vista -- e some justamente o unico sinal de onde se esta,
 * porque aqui nao ha mais borda que mude de cor.
 *
 * `:focus-visible`, e nao `:focus`: quem acabou de clicar ja sabe onde esta.
 */
.cp-btn-icone:focus-visible {
  outline: 0;
  color: var(--cp-texto);
  box-shadow: 0 0 0 3px var(--cp-primaria-suave);
  border-radius: var(--cp-raio);
}

@media (max-width: 575.98px) {
  /* Em tela estreita a faixa disputa espaco com a marca, o tema e o usuario: o nome sai e fica
     so o predinho, que continua sendo o alvo do clique. */
  .cp-navbar .cp-org-nome {
    display: none;
  }
}

/* -- Sidebar ------------------------------------------------------------------------------- */

/*
 * A FOLGA SAIU DAQUI e foi para os filhos.
 *
 * Com `padding` na coluna, o fio inferior do cabecalho morreria a 0.875rem de cada borda, em vez
 * de atravessar a sidebar e encontrar o da navbar. Uma faixa de cabecalho que nao fecha nas duas
 * pontas deixa de se ler como faixa.
 */
.cp-sidebar {
  grid-column: 1;
  grid-row: 1 / -1;

  /*
   * O `!important` AQUI RESPONDE A OUTRO `!important`, e nao a uma disputa de especificidade.
   *
   * Acima de lg o Bootstrap declara `background-color: transparent !important` em `.offcanvas-lg`
   * -- ele assume que a gaveta, virada coluna estatica, nao tem fundo proprio. Sem isto a regra
   * daqui simplesmente nao valia, e a sidebar mostrava o fundo da PAGINA atraves de si.
   *
   * Ficou anos invisivel porque `--cp-superficie` e branco e o fundo da pagina e quase branco: os
   * dois se pareciam. So apareceu quando a sidebar passou a ser sempre escura, e o que se via era
   * uma coluna clara com texto claro em cima -- ilegivel. Especificidade nao resolve: `!important`
   * so cede a `!important`.
   */
  background: var(--cp-superficie) !important;
  border-right: 1px solid var(--cp-borda);
  display: flex;
  flex-direction: column;
  padding: 0;
  width: var(--cp-sidebar-largura);
}

@media (min-width: 992px) {
  .cp-sidebar {
    position: sticky;

    /* Do topo ao rodape da janela: ela nao desconta mais a navbar, porque nao passa mais por
       baixo dela. */
    top: 0;
    height: 100dvh;
  }
}

/*
 * O CABECALHO DA SIDEBAR -- onde mora a marca.
 *
 * A altura e a MESMA da navbar (`--cp-navbar-altura`), e e disso que depende o alinhamento: os
 * dois fios inferiores viram uma linha so, atravessando a tela. Mudar uma das duas alturas
 * sozinha quebra a linha, e o degrau aparece no ponto mais visivel da interface.
 *
 * `flex: none` porque ele e faixa de altura fixa: sem isso, a navegacao rolavel abaixo o
 * espremeria ao encher a coluna, e a marca encolheria conforme o menu crescesse.
 */
.cp-sidebar-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  height: var(--cp-navbar-altura);
  padding: 0 0.875rem;
  border-bottom: 1px solid var(--cp-borda);
  flex: none;
}

/*
 * A MARCA E UM SVG ESCRITO DENTRO DA PAGINA, e nao um `<img src="logo.svg">`.
 *
 * A razao aparece no tema: um `.svg` carregado por `<img>` e um documento a parte -- ele nao
 * enxerga o CSS daqui, entao nem `currentColor` nem as variaveis chegam nele. As letras ficariam
 * presas a uma cor so, e no fundo escuro da coluna isso e o classico texto preto sobre preto.
 * Inline, elas herdam a cor de quem as envolve e trocam junto com o tema, sem valor duplicado.
 *
 * `height: 100%` porque quem manda no tamanho e a FAIXA que a contem -- ver
 * `.cp-sidebar-header .cp-marca` mais abaixo. A largura acompanha sozinha.
 */
.cp-marca {
  display: block;
  height: 100%;
  width: auto;
  color: var(--cp-texto);
  text-decoration: none;
}

/* O ACENTO DA MARCA -- a haste que sobe e o "Ads". O resto do desenho usa currentColor. */
.cp-marca__acento { fill: var(--cp-marca-acento); }

/*
 * O TAMANHO DA MARCA NA COLUNA sai da FAIXA, e nao de um numero proprio.
 *
 * A altura da faixa e `--cp-navbar-altura`, a MESMA da navbar ao lado, e e disso que depende a
 * linha continua que os dois fios inferiores formam atravessando a tela. Fixar uma altura aqui
 * criaria um segundo numero para manter em acordo com aquele; com a altura vindo do pai menos o
 * respiro, mexer na faixa leva a marca junto.
 *
 * O RESPIRO E VERTICAL E GENEROSO de proposito: o desenho tem hastes finas -- a ponta do lapis, o
 * traco do "S" --, e encostado no fio de baixo ele parece cortado.
 */
.cp-sidebar-header .cp-marca {
  height: calc(var(--cp-navbar-altura) - 1.5rem);
  max-width: 100%;
}

/*
 * O LINK QUE ENVOLVE A MARCA. Ele existe para o desenho ser clicavel -- e e dele que sai a COR:
 * as letras e a ponta do lapis usam `currentColor`, entao quem decide o tom delas e este
 * elemento. Na coluna, que carrega `data-bs-theme="dark"`, `--cp-texto` e o quase-branco.
 */
/*
 * O BLOCO DA MARCA: desenho, fio e nome, lado a lado.
 *
 * A classe e comum as duas telas onde ele aparece -- o cabecalho da coluna e o cartao de entrada
 * --, e cada uma so ajusta o TAMANHO. O arranjo e o mesmo nos dois lugares porque e ele que faz os
 * tres pedacos se lerem como uma coisa so.
 */
.cp-marca-bloco {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  min-width: 0;
}

/* No cartao de entrada o bloco e o centro da tela, e nao o canto de uma faixa. */
.cp-marca-bloco--centro {
  justify-content: center;
}

.cp-sidebar-header .cp-marca-alvo {
  color: var(--cp-texto);
  text-decoration: none;
}

/*
 * O FIO ENTRE A MARCA E O NOME.
 *
 * `currentColor` com transparencia, e nao `--cp-borda`: ele acompanha a cor do texto do cabecalho,
 * seja qual for o tema do elemento -- e a coluna carrega o tema escuro por conta propria. Com o
 * token de borda, ele sumiria no escuro ou apareceria demais no claro.
 *
 * `align-self: stretch` com margem vertical: a altura vem do bloco, e nao de um numero fixo que
 * teria de ser refeito toda vez que o nome ou a marca mudassem de tamanho.
 */
.cp-marca-fio {
  width: 1px;
  align-self: stretch;
  margin: 0.75rem 0;
  background: color-mix(in srgb, currentColor 22%, transparent);
  flex: none;
}

/*
 * O NOME POR EXTENSO, uma palavra por linha.
 *
 * Empilhado porque em linha unica ele nao cabe na coluna -- e empilhado ganha um sentido que a
 * linha nao teria: cada inicial responde por uma letra da sigla ao lado. Fica em
 * `--cp-texto-suave` de proposito: quem nomeia o produto e a marca, e este texto explica.
 */
.cp-marca-extenso {
  display: flex;
  flex-direction: column;
  font-size: 0.6875rem;
  font-weight: 500;
  line-height: 1.15;
  letter-spacing: 0.02em;
  color: var(--cp-texto-suave);
  min-width: 0;

  /*
   * AS TRES PALAVRAS ALINHAM PELA ESQUERDA, uma sob a outra -- e o alinhamento e declarado aqui,
   * e nao herdado.
   *
   * No cartao de entrada o bloco fica dentro de um `.text-center`, e a heranca centralizava cada
   * linha pelo proprio comprimento: "Sistema", "Escolar" e "Integrado" tem larguras diferentes, e
   * centradas viravam tres inicios diferentes ao lado de uma marca que tem um so. Com a borda
   * esquerda em comum, as tres se leem como um bloco -- e cada inicial fica na vertical, que e o
   * que faz elas responderem pelas letras da sigla.
   */
  text-align: start;
}

/* O bloco inteiro clareia junto no hover -- ele e um alvo so, e nao marca de um lado e texto do
   outro. */
.cp-sidebar-header .cp-marca-alvo:hover .cp-marca-extenso {
  color: var(--cp-texto);
}

/*
 * A MARCA NA TELA DE ENTRADA -- o simbolo sozinho, acima do formulario.
 *
 * So o lapis, e nao a palavra: o cartao e estreito, e a palavra inteira encolheria a ponto de as
 * letras virarem risco. E logo abaixo dele ja vem o titulo escrito, entao o nome nao se perde.
 */
/*
 * O TAMANHO DA MARCA NA ENTRADA VIVE EM `.cp-auth-cartao`, junto das outras regras do cartao --
 * e nao aqui.
 *
 * Havia uma regra neste ponto, feita quando a tela mostrava so o simbolo: ela centralizava o
 * desenho com `margin-inline: auto`. Isso funciona num elemento solto e QUEBRA dentro de um flex,
 * que foi o que a marca virou ao ganhar o fio e o nome: margem automatica num item flex nao
 * centraliza nada -- ela engole o espaco livre e empurra os irmaos para as bordas. Na tela, a
 * logo ficava de um lado, o nome do outro, e o conjunto fora do centro.
 *
 * Quem centraliza agora e `justify-content` no proprio bloco. Ver `.cp-marca-bloco--centro`.
 */

/* -- Seletor de organizacao ---------------------------------------------------------------- */

.cp-org-botao {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  padding: 0.5rem 0.625rem;
  background: var(--cp-fundo);
  border: 1px solid var(--cp-borda);
  border-radius: var(--cp-raio);
  color: var(--cp-texto);
  font-weight: 500;
  text-align: left;
}

.cp-org-botao:hover {
  border-color: var(--cp-borda-forte);
}

.cp-org-nome {
  flex: 1;
  min-width: 0;
}

/* -- Identidade na sidebar ------------------------------------------------------------------ */

/* Corte com reticencias que funciona em qualquer elemento.

   O `text-truncate` do Bootstrap so define `overflow`/`text-overflow`/`white-space`, e nenhum dos
   tres tem efeito sobre caixa INLINE -- num `span`, o texto vaza em vez de cortar. Aqui o
   `display: block` vem junto, que e o que faltava. */
.cp-truncado {
  display: block;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Bloco de LEITURA: organizacao e email, sem acao nenhuma. Por isso nao tem estado de hover nem
   cursor de clique -- parecer clicavel e prometer um menu que nao existe. */
.cp-side-user {
  display: flex;
  align-items: center;
  gap: 0.625rem;

  /* A folga externa mora aqui porque a sidebar deixou de te-la -- ver o comentario dela. */
  margin: 0.875rem 0.875rem 0;

  /*
   * A folga INTERNA e maior que a dos itens de menu de proposito, e mais ainda depois que a
   * coluna passou a ter 280px. Este bloco e o unico cartao da sidebar -- ele tem borda e fundo
   * proprios --, e com pouca folga a borda encosta no texto e ele se le como um campo de
   * formulario. Espaco em volta e o que faz uma caixa parecer conteudo, e nao controle.
   */
  padding: 1.3rem;
  background: var(--cp-fundo);
  border: 1px solid var(--cp-borda);
  border-radius: 0.75rem;

  /* O bloco NAO participa do encolhimento da coluna: sem isto ele cede largura para a navegacao
     abaixo e o texto perde espaco antes de precisar. */
  flex: none;
  min-width: 0;
}

.cp-side-user-avatar {
  width: 2.5rem;
  height: 2.5rem;

  /* Quadrado arredondado, e nao circulo: distingue o bloco de identidade da sidebar do avatar
     redondo da navbar, que e MENU -- um e leitura, o outro e acao. */
  border-radius: 0.625rem;
  object-fit: cover;
  background: var(--cp-superficie);

  /* Sem isto o avatar encolhe quando o email e longo: o flex tira de quem pode ceder, e uma foto
     de 8px de largura parece defeito. */
  flex: none;
}

/* `min-width: 0` e o que permite o filho truncar: sem ele o item flex adota a largura do
   conteudo, e o email empurra o bloco para fora da sidebar. */
.cp-side-user-texto {
  min-width: 0;
  flex: 1;
  line-height: 1.3;
}

.cp-side-user-org {
  font-weight: 600;
  font-size: 0.8125rem;
  color: var(--cp-texto);
}

.cp-side-user-email {
  font-size: 0.75rem;
  color: var(--cp-texto-suave);
}

.cp-side-user-status {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--cp-sucesso);
  flex: none;
}

/* -- Navegacao ----------------------------------------------------------------------------- */

.cp-nav {
  display: flex;
  flex-direction: column;
  gap: 0.125rem;
  margin-top: 0.875rem;

  /* Idem: a folga da coluna virou folga daqui. Ela e PADDING, e nao margin, para a barra de
     rolagem nascer dentro dela -- com margin, a barra encostaria no fio da borda direita. */
  padding: 0 0.875rem 0.875rem;
  overflow-y: auto;
  flex: 1;
}

/*
 * Os tres niveis do menu viram GRUPOS VISIVEIS aqui -- numa navbar horizontal eles ficavam
 * lado a lado, indistinguiveis. O rotulo do grupo so aparece para quem tem os itens dele.
 */
/*
 * A FOLGA LATERAL ACOMPANHA A DOS ITENS, e nao e um valor escolhido a parte.
 *
 * O rotulo do grupo e o item de menu comecam na mesma linha vertical -- e o olho le a coluna
 * inteira por essa linha. Com folgas diferentes, "ACADEMICO" ficaria dois pixels a esquerda de
 * "Alunos": pouco para alguem apontar, o bastante para a coluna parecer torta.
 *
 * A folga de CIMA continua maior, e a de baixo menor: e ela que separa um grupo do anterior e
 * cola o rotulo no que ele nomeia.
 */
.cp-nav-titulo {
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--cp-texto-suave);
  padding: 0.875rem 0.75rem 0.375rem;
}

/*
 * O TITULO DE GRUPO VIROU BOTAO -- e continua parecendo um rotulo.
 *
 * A aparencia nao muda de proposito: ele nomeia o grupo antes de qualquer outra coisa, e um botao
 * com cara de botao no meio da coluna competiria com os itens, que sao o que se clica para
 * navegar. O que ele ganha e a SETA, que e o unico sinal de que ali se clica -- e ela so precisa
 * ser notada por quem procura, e nao anunciada.
 *
 * Estas linhas so desfazem o que o navegador pinta por conta em `button`.
 */
.cp-nav-grupo {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  width: 100%;
  border: 0;
  background: transparent;
  font: inherit;
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--cp-texto-suave);
  text-align: left;
  cursor: pointer;
}

/* O rotulo clareia no hover, e o fundo NAO muda: fundo aqui o faria parecer um item de menu --
   que leva a algum lugar --, e este so abre e fecha o que ja esta na coluna. */
.cp-nav-grupo:hover {
  color: var(--cp-texto);
}

/*
 * A SETA APONTA PARA ONDE O GRUPO VAI: para baixo quando ele esta aberto -- o conteudo desce dali
 * --, e para o lado quando fechado. O estado vem do `aria-expanded`, que o Bootstrap ja mantem em
 * dia: sem uma classe propria para sincronizar, nao ha como os dois discordarem.
 */
.cp-nav-seta {
  font-size: 0.625rem;
  opacity: 0.7;
  transition: transform var(--cp-transicao);
}

.cp-nav-grupo[aria-expanded="false"] .cp-nav-seta {
  transform: rotate(-90deg);
}

.cp-nav-item {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  padding: 0.75rem;
  border-radius: var(--cp-raio);

  /*
   * O BRANCO VEM DO TOKEN, e nao escrito como `white`.
   *
   * Na sidebar -- que carrega `data-bs-theme="dark"` -- `--cp-texto` E o branco deste desenho:
   * `#e7eaee`, o tom que o tema escuro usa para texto de leitura. Escrever `white` aqui seria um
   * literal fora do `tokens.css`, e ele nao acompanharia se um dia o tema escuro mudar de tom.
   *
   * O que muda de fato e a HIERARQUIA: os itens estavam em `--cp-texto-suave`, o cinza de apoio,
   * e passam ao texto pleno. A coluna deixa de ter todo o menu em segundo plano.
   */
  color: var(--cp-texto);
  text-decoration: none;
  font-size: 0.9rem;
  transition: background var(--cp-transicao), color var(--cp-transicao);
}

.cp-nav-item i {
  font-size: 1rem;
  width: 1.125rem;
  text-align: center;
}

/* So o FUNDO muda no hover: a cor do texto ja e `--cp-texto` em repouso, e repeti-la aqui seria
   uma declaracao que nao faz nada -- o tipo de linha que sobrevive a refatoracao e engana quem
   for procurar por que o hover "nao clareia". */
.cp-nav-item:hover {
  background: var(--cp-fundo);
}

/*
 * O item atual: DEGRADE que nasce na cor da marca e se esvai para a direita.
 *
 * O realce era um azul chapado, e chapado ele compete com o proprio texto: a caixa inteira tem o
 * mesmo peso visual do comeco ao fim, e o olho nao sabe onde comeca o item. Com o degrade, a
 * intensidade fica na ESQUERDA -- junto do icone, que e por onde a leitura da coluna comeca -- e
 * some antes de chegar na borda direita.
 *
 * A COR SAI DO TOKEN, com `color-mix`: e o que permite um azul TRANSLUCIDO sem escrever rgba com
 * numeros. Escrito a mao, ele seria um literal fora do `tokens.css` e nao acompanharia o tema; e
 * `--cp-primaria-suave`, que ja e um azul rebaixado, e opaco -- nao da para esvair.
 *
 * O 55% foi escolhido contra o fundo da sidebar: acima disso o realce briga com o texto branco,
 * abaixo ele some no tema claro, onde o fundo da coluna e o mesmo escuro mas o entorno nao.
 */
.cp-nav-item.active {
  background: linear-gradient(
    90deg,
    color-mix(in srgb, var(--cp-primaria) 55%, transparent),
    transparent);
  color: var(--cp-texto);
}

/*
 * O ITEM PARA ONDE SE ESTA INDO -- entre o clique e a pagina nova.
 *
 * E o mesmo degrade do item atual, mais fraco: ele diz "e para ca que voce clicou" sem afirmar
 * "voce esta aqui", que ainda nao e verdade. Quando a pagina chega, o item de destino nasce com
 * `.active` e o realce apenas se firma -- a passagem de um para o outro nao tem salto.
 *
 * O SINAL PRECISA SER DO ITEM, e nao so da barra no topo: a barra diz que ALGO vem vindo, e numa
 * coluna de dez linhas isso nao responde "meu clique pegou?". Sem resposta, a pessoa clica de
 * novo -- e o segundo clique cancela a navegacao em andamento e recomeca do zero.
 */
.cp-nav-item-indo {
  background: linear-gradient(
    90deg,
    color-mix(in srgb, var(--cp-primaria) 28%, transparent),
    transparent);
}

/*
 * O ICONE FICA NA COR DA MARCA, e o texto continua branco.
 *
 * E o que distingue o item atual, junto do degrade: a faixa marca a linha e o icone marca o ponto.
 * Os dois carregam esse trabalho sozinhos -- o menu inteiro esta num peso so, e nenhum item fica
 * mais grosso que o outro por estar aberto.
 */
.cp-nav-item.active i {
  color: var(--cp-primaria);
}

/* -- Rodape da sidebar: a saida ------------------------------------------------------------ */

/*
 * O RODAPE E FIXO NO PE DA COLUNA, e nao o ultimo item da lista.
 *
 * Quem o empurra para baixo e o `flex: 1` da navegacao: com a lista curta, sair fica no pe da
 * tela; com a lista longa, ela rola por baixo e o rodape nao sai do lugar. Fosse mais um item do
 * `<nav>`, "Sair" entraria na rolagem e ficaria abaixo de "Permissoes" -- lido como se fosse
 * mais uma tela para onde ir, e nao a saida.
 *
 * O fio em cima e o mesmo do cabecalho, pelo mesmo motivo: fecha a coluna nas duas pontas.
 */
.cp-sidebar-footer {
  flex: none;
  padding: 0.75rem 0.875rem;
  border-top: 1px solid var(--cp-borda);
}

/*
 * O botao usa a forma de item de menu para nao inventar um controle novo -- mas ele e `button`
 * dentro de um `form`, e nao um link: sair MUDA ESTADO no servidor e viaja com o token de CSRF.
 * Estas linhas so desfazem o que o navegador pinta por conta em `button`.
 */
.cp-sidebar-footer .cp-nav-item {
  width: 100%;
  border: 0;
  background: transparent;
  font: inherit;
  text-align: left;
}

/*
 * VERMELHO, e nao cinza como os outros. Sair e a unica acao da coluna que nao leva a outra tela
 * -- ela termina a sessao --, e o custo de erra-la e refazer o login no meio do que se estava
 * fazendo. No hover ele preenche: cor de aviso em texto se le como "cuidado", preenchida se le
 * como "e esta mesmo".
 */
.cp-sidebar-footer .cp-nav-sair {
  color: var(--cp-perigo);
}

.cp-sidebar-footer .cp-nav-sair:hover {
  background: var(--cp-perigo);
  color: var(--cp-sobre-perigo);
}

/* -- Menu do usuario, na navbar ------------------------------------------------------------- */

.cp-usuario {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  max-width: 16rem;
  padding: 0.25rem 0.5rem;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--cp-raio);
  color: var(--cp-texto);
  text-align: left;
}

.cp-usuario:hover {
  background: var(--cp-fundo);
  border-color: var(--cp-borda);
}

.cp-usuario-email {
  min-width: 0;
  font-size: 0.8125rem;
}

/*
 * A foto ao lado do email.
 *
 * Dimensao FIXA e object-fit: cover porque a origem e uma imagem de usuario -- sem isso, uma
 * foto muito larga estica a navbar inteira, e o layout passa a depender do que alguem enviou.
 */
/*
 * QUADRADA TAMBEM, e nao redonda: e a MESMA foto que o menu logo abaixo mostra em 56px. Um
 * circulo no botao e um quadrado arredondado no menu, com a mesma imagem, se le como descuido.
 * O raio e menor porque a peca e menor -- o raio do sistema, em 28px, vira quase um circulo.
 */
.cp-avatar-navbar {
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 0.375rem;
  object-fit: cover;
  background: var(--cp-fundo);
  border: 1px solid var(--cp-borda);
  flex-shrink: 0;
}

/*
 * O MENU DO USUARIO tem largura propria, e nao a do conteudo.
 *
 * O padrao do Bootstrap e o menu encolher ate caber o maior item -- aqui, "Minha organizacao".
 * Isso deixava o cabecalho apertado: a foto de 56px mais o email disputavam uma faixa medida
 * por outro texto. Com o piso, o cabecalho manda na largura e os itens sobram folgados.
 *
 * O TETO EXISTE PELO MOTIVO OPOSTO: um endereco longo -- e endereco de escola costuma ser --
 * esticaria o menu para fora da tela em vez de quebrar em duas linhas.
 */
.cp-menu-usuario {
  min-width: 20rem;
  max-width: 24rem;
}

/*
 * O MENU FECHADO VOLTA A FICAR FECHADO.
 *
 * `.dropdown-menu` se esconde com `display: none` e aparece com `.show { display: block }`.
 * `.list-group` traz `display: flex` -- mesma especificidade, e vem DEPOIS na folha do
 * Bootstrap, entao ganha o desempate. Com as duas classes no mesmo elemento, o menu computa
 * `flex` o tempo todo: ele abria e NAO FECHAVA MAIS, e nao ha erro nenhum no console dizendo
 * isso. Medido: `dropdown-menu` sozinho da `none`; com `list-group`, da `flex`.
 *
 * O `:not(.show)` reescreve so o estado FECHADO. Aberto, quem decide continua sendo
 * `.dropdown-menu.show` -- que ja ganhava de `.list-group` por ter duas classes -- e a aparencia
 * segue exatamente a mesma.
 */
.cp-menu-usuario.list-group:not(.show) {
  display: none;
}

.cp-usuario-resumo {
  max-width: 100%;
}

/*
 * A COLUNA DO NOME E DO EMAIL precisa poder encolher.
 *
 * Item de flex nao encolhe abaixo do proprio conteudo por padrao -- `min-width: auto` --, e um
 * email sem espacos e conteudo indivisivel: sem isto ele empurra a foto para fora do menu em
 * vez de quebrar. `min-width: 0` e o que devolve o poder de quebrar ao `text-break`.
 */
.cp-usuario-identidade {
  min-width: 0;
}

/*
 * A FOTO DO PERFIL no menu: 56px, quadrada de cantos arredondados.
 *
 * QUADRADA, e nao redonda: o circulo corta as bordas da imagem, e foto de documento -- que e o
 * que a maioria envia -- perde justamente as laterais do rosto. O raio arredonda o canto sem
 * comer conteudo.
 *
 * `object-fit: cover` continua pelo mesmo motivo do avatar pequeno: a origem e uma imagem que
 * alguem enviou, e sem ele uma foto muito larga estica o menu inteiro.
 */
.cp-avatar-perfil {
  width: 56px;
  height: 56px;
  border-radius: var(--cp-raio);
  object-fit: cover;
  background: var(--cp-fundo);
  border: 1px solid var(--cp-borda);
  flex-shrink: 0;
}

.cp-superficie {
  background: var(--cp-superficie);
  border: 1px solid var(--cp-borda);
  border-radius: var(--cp-raio);
}

.card.cp-superficie {
  box-shadow: none;

  /*
   * O RAIO PRECISA CHEGAR AO BOOTSTRAP, e nao parar no `border-radius` acima.
   *
   * `.cp-superficie` arredonda o cartao em `--cp-raio`, mas quem calcula o raio INTERNO -- o do
   * cabecalho, que e um bloco preenchido encostado no topo -- e o Bootstrap, a partir da
   * variavel dele, que seguia em 6px. Os 4px de diferenca nao passam despercebidos: o fundo do
   * cabecalho, mais quadrado que o cartao, escapa pelos dois cantos de cima.
   *
   * O `calc` do raio interno ja desconta a borda sozinho -- por isso o que se ajusta aqui e o
   * raio EXTERNO, e nao o interno diretamente.
   */
  --bs-card-border-radius: var(--cp-raio);
}

/*
 * A FAIXA DE TITULO DO CARTAO.
 *
 * O titulo morava DENTRO do corpo, separado do conteudo por uma margem. Funciona e some: sem fio
 * nem fundo, o titulo e o que vem abaixo dele se leem como um bloco so, e os controles ao lado
 * ficam boiando num lugar que nao se anuncia como barra de ferramentas.
 *
 * A faixa usa O MESMO par de tokens da cabeca da tabela -- `--cp-fundo` sobre `--cp-superficie`,
 * fechada por um fio de 1px --, e isso e deliberado: cabecalho de cartao e cabecalho de coluna
 * respondem a mesma pergunta ("o que vem abaixo disto?"), entao passam a ter a mesma cara.
 *
 * A folga vertical sobe de 0.5rem para 0.75rem porque o cabecalho do grafico tem DUAS linhas
 * (titulo e legenda) e um grupo de botoes ao lado: no valor de fabrica, o botao encosta no fio.
 */
.card.cp-superficie > .card-header {
  background: var(--cp-fundo);
  border-bottom: 1px solid var(--cp-borda);
  color: var(--cp-texto);
  padding: 0.75rem 1rem;
}

/* Toda coluna numerica alinha pelo digito, nao pela largura do glifo. */
.cp-num,
td.cp-num,
th.cp-num {
  font-variant-numeric: tabular-nums;
  text-align: right;
}

input.cp-num {
  text-align: left;
}

/* -- Telas anonimas ---------------------------------------------------------------------- */

.cp-auth {
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: 1.5rem;
}

.cp-auth-cartao {
  width: 100%;
  max-width: 26rem;
  background: var(--cp-superficie);
  border: 1px solid var(--cp-borda);
  border-radius: var(--cp-raio);
  padding: 2rem;
}

/*
 * A MARCA NO CARTAO DE ENTRADA -- a mesma do painel, e maior.
 *
 * Ela e o unico elemento grande desta tela, e o que da a ela um centro visual antes do
 * formulario. As regras de tamanho e cor sao ESCOPADAS ao cartao: `.cp-marca` tambem vive no
 * cabecalho da coluna, e uma regra solta com a mesma especificidade venceria por ordem e mexeria
 * na de la -- o que ja aconteceu uma vez, quando esta regra ainda era de um icone de biblioteca e
 * pintava a marca do sistema de azul dentro de uma faixa de 3,25rem.
 *
 * A COR VEM DE `--cp-texto`, e nao da primaria: as letras usam `currentColor`, e no cartao claro o
 * azul da marca competiria com o botao de entrar, que e o unico azul que se clica ali.
 */
.cp-auth-cartao .cp-marca {
  height: 2.75rem;
}

.cp-auth-cartao .cp-marca-bloco {
  color: var(--cp-texto);
}

/* O nome cresce junto com o desenho: no cartao ha largura de sobra, e o mesmo corpo da coluna --
   pensado para 17,5rem -- ficaria miudo ao lado de um lapis de 2,75rem. */
.cp-auth-cartao .cp-marca-extenso {
  font-size: 0.8125rem;
}

/* O cartao LARGO: o cadastro do autenticador tem duas colunas -- o codigo de um lado, o QR e os
   passos do outro. No celular elas empilham, e ele volta a largura de sempre. */
.cp-auth-cartao-largo {
  max-width: 56rem;
}

/* A coluna da informacao, separada da do formulario pelo fundo da pagina, e nao por uma linha:
   ela e leitura, e o que se preenche fica sobre a superficie do cartao. */
.cp-auth-painel {
  background: var(--cp-fundo);
  border: 1px solid var(--cp-borda);
  border-radius: var(--cp-raio);
  padding: 1.25rem;
}

/* Dentro do cartao largo, a etapa dos codigos de recuperacao continua estreita: uma lista de dez
   linhas curtas esticada em 56rem fica perdida no meio. */
.cp-auth-estreito {
  max-width: 26rem;
  margin-inline: auto;
}

/* O CODIGO EM SEIS BLOCOS: um digito por caixa, grandes o bastante para conferir de relance.
   Em tela estreita os blocos encolhem juntos, em vez de quebrar a linha. */
.cp-blocos {
  display: flex;
  gap: 0.5rem;
}

.cp-bloco {
  flex: 1 1 0;
  min-width: 0;
  max-width: 3.25rem;
  height: 3.5rem;
  padding: 0;
  text-align: center;
  font-size: 1.5rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* O campo de codigo curto espacado, para conferir digito a digito sem contar com o dedo. Usado
   hoje pela grade de cadastros; o segundo fator passou aos blocos acima. */
.cp-codigo {
  letter-spacing: 0.5em;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

/* NO ERRO, SO A BORDA. O Bootstrap reserva a direita do campo invalido para o icone de alerta --
   48 dos 52 pixels de um bloco --, e o digito some: o codigo colado depois do erro entrava nos
   blocos sem aparecer, e parecia que colar tinha deixado de funcionar. */
.cp-bloco.is-invalid {
  padding: 0;
  background-image: none;
}

/* O codigo de recuperacao, que nao cabe em blocos: espacado e monoespacado, para conferir. */
.cp-codigo-recuperacao {
  letter-spacing: 0.15em;
  text-align: center;
  font-family: var(--bs-font-monospace);
}

/* -- Cadastro do aplicativo autenticador -------------------------------------------------- */

/* O QR sobre fundo sempre claro, com margem: o leitor do celular precisa da zona quieta em volta,
   e no tema escuro a borda do cartao encostaria no desenho. */
.cp-qr {
  width: 13rem;
  margin-inline: auto;
  padding: 0.5rem;
  background: var(--cp-qr-fundo);
  border: 1px solid var(--cp-borda);
  border-radius: var(--cp-raio);
}

.cp-qr-fantasma {
  height: 12rem;
}

.cp-qr img {
  display: block;
  width: 100%;
  height: auto;
}

/* A chave para digitar: monoespacada e em grupos, para nao trocar um 8 por um B de olho. */
.cp-chave {
  font-size: 0.9375rem;
  letter-spacing: 0.08em;
  word-break: break-word;
}

/* Os dez codigos em duas colunas, monoespacados: sao copiados a mao, um a um, para um papel. */
.cp-codigos-recuperacao {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.375rem 1rem;
  font-family: var(--bs-font-monospace);
  font-size: 0.9375rem;
  font-variant-numeric: tabular-nums;
}

/* -- Estado de carregamento: SKELETON, nao spinner ---------------------------------------- */

.cp-linha-fantasma {
  height: 1rem;
  border-radius: 4px;
  margin-bottom: 0.75rem;
  background: linear-gradient(90deg, var(--cp-borda) 25%, var(--cp-borda-forte) 37%, var(--cp-borda) 63%);
  background-size: 400% 100%;
  animation: cp-brilho 1.2s ease-in-out infinite;
}

@keyframes cp-brilho {
  0% { background-position: 100% 50%; }
  100% { background-position: 0 50%; }
}

/* -- A espera da PROXIMA PAGINA: barra fina no topo ---------------------------------------- */

/*
 * TRES PIXELS NO TOPO, e nao um veu sobre a tela.
 *
 * Esta e a unica espera do sistema em que a proxima tela ainda nao existe -- o intervalo entre
 * clicar num item do menu e o servidor devolver a pagina. Um preloader de tela cheia aqui
 * esconderia a tela em que a pessoa AINDA ESTA, para mostrar uma animacao de 0,3 s: ela perde o
 * contexto e ganha um pisca. A barra responde a pergunta do momento -- "clicou?" -- sem tapar
 * nada.
 *
 * O SKELETON LOGO ACIMA RESOLVE OUTRA COISA, e os dois nao se sobrepoem: ele ocupa o lugar de um
 * conteudo que a pagina JA sabe que vem, com a forma que ele tera. Aqui nao ha forma a mostrar,
 * porque nao ha pagina ainda.
 *
 * ELA NASCE INVISIVEL e so ganha corpo com `.cp-indo`, que o JavaScript poe depois de 150 ms de
 * espera -- ver `ESPERA_ANTES_DA_BARRA` em app.js.
 */
.cp-barra-navegacao {
  position: fixed;
  top: 0;
  left: 0;
  height: 3px;
  width: 100%;
  opacity: 0;

  /*
   * O TRILHO OCUPA A TELA INTEIRA e nao pinta nada: quem pinta e a faixa de dentro. `overflow`
   * existe para ela nao vazar pelas bordas enquanto atravessa.
   */
  overflow: hidden;
  pointer-events: none;

  /*
   * ACIMA DE TUDO, inclusive dos modais: o Bootstrap empilha overlay em 1050-1060, e o sistema
   * empilha modal sobre modal (ver `zIndexEmpilhado`). Uma navegacao disparada de dentro de um
   * modal aberto precisa aparecer por cima dele.
   */
  z-index: 2000;
  transition: opacity 0.2s ease;
}

/*
 * A FAIXA ATRAVESSA A TELA INTEIRA, EM LACO -- e este desenho substitui um que nao funcionava.
 *
 * A versao anterior era uma barra de PROGRESSO: ela crescia da esquerda ate perto de 90% enquanto
 * esperava, e os 10% finais eram corridos pela pagina que chegava. Bonito no papel, e errado na
 * pratica: "chegar ao fim" dependia de um recado atravessando a troca de pagina --
 * `sessionStorage`, `pagehide`, o primeiro paint do documento novo. Cada uma dessas pecas e um
 * lugar onde o movimento morre no meio, e foi o que aconteceu tres vezes seguidas: na tela, a
 * barra parava sempre no mesmo ponto -- os tais 90%, que numa tela larga caem bem em cima do menu
 * do usuario.
 *
 * ESTA NAO TEM FIM PARA ALCANCAR, e por isso nao tem como parar antes dele. A faixa entra pela
 * esquerda, cruza a largura toda -- passando por cima do menu do usuario ate a borda -- e recomeca
 * enquanto a resposta nao chega. Quando ela chega, a pagina inteira e trocada e a faixa vai junto:
 * nao ha nada a combinar entre os dois documentos.
 *
 * O QUE SE PERDE E A NOCAO DE QUANTO FALTA -- que a barra anterior tambem nao tinha de verdade,
 * porque ninguem sabe quanto falta: ela mede uma resposta que ainda nao veio. O que se ganha e a
 * unica coisa que essa faixa precisa dizer, e agora diz sem depender de nada: "estou trabalhando".
 */
.cp-barra-navegacao.cp-indo {
  opacity: 1;
}

.cp-barra-navegacao::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 40%;
  background: var(--cp-primaria);

  /* Fora da tela, a esquerda: sem a classe de movimento, nada aparece. */
  transform: translateX(-100%);
}

.cp-barra-navegacao.cp-indo::before {
  animation: cp-atravessando 1.05s cubic-bezier(0.65, 0, 0.35, 1) infinite;
}

/*
 * DE FORA A FORA: comeca inteiramente fora pela esquerda e termina inteiramente fora pela direita.
 * Com 40% de largura, `250%` de deslocamento poe a ponta esquerda da faixa na borda direita da
 * tela -- ela sai por completo antes de recomecar, em vez de piscar no meio do caminho.
 */
@keyframes cp-atravessando {
  from { transform: translateX(-100%); }
  to { transform: translateX(250%); }
}

/*
 * QUEM PEDIU MENOS MOVIMENTO recebe o mesmo aviso, parado: um fio inteiro, de ponta a ponta, sem
 * nada atravessando. Continua dizendo que a pagina esta vindo -- que e a informacao -- sem a
 * travessia, que e o enfeite.
 */
@media (prefers-reduced-motion: reduce) {
  .cp-barra-navegacao {
    transition: none;
  }

  .cp-barra-navegacao.cp-indo::before {
    animation: none;
    width: 100%;
    transform: none;
  }
}

/* -- Avatar ------------------------------------------------------------------------------- */

.cp-avatar {
  width: 8rem;
  height: 8rem;
  border-radius: 50%;
  object-fit: cover;
  border: 1px solid var(--cp-borda);
  background: var(--cp-fundo);
}

/*
 * Na grade a foto e um apoio para reconhecer a pessoa, nao o assunto da linha: ela fica do
 * tamanho do texto ao lado, para nao empurrar a altura da linha nem competir com o nome.
 */
.cp-avatar-linha {
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  object-fit: cover;
  border: 1px solid var(--cp-borda);
  background: var(--cp-fundo);

  /* A imagem e inline: sem isto ela assenta na linha de base e fica baixa em relacao ao nome. */
  vertical-align: middle;
}

/* Dentro do modal a foto divide espaco com o formulario, entao ela e menor que em Meus dados. */
.cp-avatar-modal {
  width: 4.5rem;
  height: 4.5rem;
  border-radius: 50%;
  object-fit: cover;
  border: 1px solid var(--cp-borda);
  background: var(--cp-fundo);
  flex-shrink: 0;
}

/* -- Permissao inativa: cinza, mas PRESENTE ----------------------------------------------- */

/*
 * Ela precisa aparecer no perfil ja montado. Se sumir da tela, o proximo PUT a remove sem
 * ninguem perceber -- e ninguem percebe justamente porque ela sumiu.
 */
.cp-inativa {
  opacity: 0.55;
  font-style: italic;
}

.dropdown-menu {
  border-color: var(--cp-borda);
}


/* -- O aviso do canto: um CARTAO, e nao um retangulo colorido ------------------------------ */

/*
 * O TOAST PASSA A SER DESTA INTERFACE.
 *
 * O que a biblioteca desenha e um bloco de cor chapada, texto branco e canto de 2 px -- nada
 * disso existe no resto do sistema. Aqui ele vira a mesma superficie dos cartoes, com a mesma
 * borda, o mesmo raio e a mesma fonte, e o ESTADO deixa de tomar o fundo inteiro: ele aparece
 * numa faixa lateral, no icone e na barra de tempo.
 *
 * O GANHO NAO E SO DE GOSTO. Texto escuro sobre superficie clara se le melhor que branco sobre
 * verde -- e o verde era o contraste mais fraco dos tres. E, com o fundo neutro, mensagens longas
 * (as recusas da API, que vem com frase inteira) param de virar um painel colorido no canto da
 * tela.
 *
 * A COR DO ESTADO ENTRA POR VARIAVEL, uma por classe: as tres regras abaixo trocam
 * `--cp-toast-cor`, e a faixa, o icone e a barra a leem. Sem isso seriam tres copias do cartao
 * inteiro, e a proxima mudanca de desenho seria aplicada em duas delas.
 */
.toastify.cp-toast {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  max-width: min(26rem, calc(100vw - 2rem));
  padding: 0;
  background: var(--cp-superficie);
  color: var(--cp-texto);
  border: 1px solid var(--cp-borda);

  /* A FAIXA DO ESTADO. Ela e a borda esquerda, e nao um elemento a mais: assim acompanha a altura
     do cartao sozinha, seja ele de uma linha ou de quatro. */
  border-left: 3px solid var(--cp-toast-cor);
  border-radius: var(--cp-raio);
  font-family: var(--cp-fonte);
  font-size: 0.875rem;
  line-height: 1.45;

  /*
   * A SOMBRA E MAIS FORTE QUE A DOS CARTOES de propósito: este flutua sobre a tela inteira, e sem
   * profundidade ele se confunde com o conteudo por baixo -- especialmente sobre uma tabela, que
   * ja e um retangulo claro cheio de linhas.
   */
  box-shadow: 0 10px 30px -12px rgb(0 0 0 / 45%), 0 2px 8px -4px rgb(0 0 0 / 25%);
  overflow: hidden;
}

.cp-toast-sucesso { --cp-toast-cor: var(--cp-sucesso); }
.cp-toast-atencao { --cp-toast-cor: var(--cp-atencao); }
.cp-toast-erro { --cp-toast-cor: var(--cp-perigo); }

/* O corpo carrega a folga: o cartao nao tem padding proprio para a barra de tempo poder encostar
   nas bordas de baixo. */
.cp-toast-corpo {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  padding: 0.875rem 1rem;

  /* Ocupa o que sobra para o "x" encostar na direita; `min-width: 0` e o que permite a mensagem
     longa QUEBRAR em vez de esticar o cartao para fora da tela. */
  flex: 1;
  min-width: 0;
}

/*
 * O ICONE DIZ O ESTADO SEM DEPENDER DA COR -- circulo com "v", triangulo, circulo com "!". Cor
 * sozinha nao serve: um homem em doze nao distingue verde de vermelho, e "deu certo" e "falhou"
 * viram o mesmo retangulo com um texto curto dentro.
 */
.cp-toast-icone {
  flex: none;
  font-size: 1.125rem;
  color: var(--cp-toast-cor);
}

.cp-toast-texto {
  min-width: 0;

  /* Mensagem longa QUEBRA em vez de esticar o cartao: as recusas da API vem com frase inteira. */
  overflow-wrap: anywhere;
}

/*
 * A BARRA DE PROGRESSO -- quanto falta para o aviso sumir.
 *
 * SAO DUAS PECAS, e a de baixo e o que a torna LEGIVEL como progresso: o trilho fraco mostra o
 * percurso inteiro, e o preenchimento forte mostra o que resta dele. Com uma camada so, o que se
 * ve e um risco encurtando sem referencia de tamanho -- quem olha nao sabe se aquilo esta acabando
 * ou apenas existe.
 *
 * O MOVIMENTO NAO ESTA AQUI, e a ausencia e deliberada: quem encolhe o preenchimento e o
 * `animate()` do JavaScript -- ver `correrOProgresso` em app.js. A versao anterior animava por CSS
 * um pseudo-elemento, com a duracao vindo por variavel e o gatilho preso a classe que a biblioteca
 * poe no cartao; na tela a barra ficava cheia e parada, e eram tres pecas suspeitas para uma
 * caçada as cegas. Aqui o CSS so desenha, e desenhar ou nao desenhar se ve num olhar.
 *
 * `transform-origin` FICA NO CSS porque ele descreve a FORMA de encolher -- pela esquerda, como
 * uma regua que se esvazia --, e nao o tempo dela.
 */
.cp-toast-tempo {
  position: absolute;
  left: 0;
  bottom: 0;
  height: 3px;
  width: 100%;
  background: color-mix(in srgb, var(--cp-toast-cor) 20%, transparent);
}

.cp-toast-tempo-cheio {
  display: block;
  height: 100%;
  width: 100%;
  background: var(--cp-toast-cor);
  transform-origin: left center;
}

/*
 * O "X" DA BIBLIOTECA, vestido. Ele nasce branco e opaco -- invisivel sobre superficie clara --,
 * e fica grudado no texto. Aqui ele vira um botao discreto que so ganha contraste no hover.
 */
.toastify.cp-toast .toast-close {
  align-self: stretch;
  padding: 0 0.875rem 0 0;
  color: var(--cp-texto-suave);
  font-size: 1.25rem;
  line-height: 1;
  opacity: 0.7;
  transition: opacity var(--cp-transicao), color var(--cp-transicao);
}

.toastify.cp-toast .toast-close:hover {
  color: var(--cp-texto);
  opacity: 1;
}

/*
 * A ENTRADA DESLIZA DE FORA, e nao so aparece. A lib anima `opacity` sozinha; o deslocamento e o
 * que faz o olho perceber que algo CHEGOU no canto -- um retangulo que surge parado passa
 * despercebido quando a atencao esta no meio da tela.
 */
.toastify.cp-toast {
  transform: translateX(0.75rem);
  transition: opacity 0.25s ease, transform 0.25s cubic-bezier(0.22, 1, 0.36, 1);
}

.toastify.cp-toast.on {
  transform: translateX(0);
}

@media (prefers-reduced-motion: reduce) {
  .toastify.cp-toast,
  .toastify.cp-toast.on {
    transform: none;
    transition: opacity 0.25s ease;
  }

  /* A barra de tempo continua ENCOLHENDO: ela nao e enfeite -- e a unica indicacao de quanto falta
     para o aviso sumir. Sem movimento nenhum, ela mentiria mostrando sempre cheio. */
}

/* -- Selos de estado ----------------------------------------------------------------------- */

/*
 * Sinalizacoes que o operador precisa VER na linha, sem abrir o registro.
 *
 * Cada uma responde uma pergunta que antes exigia deducao:
 *   pendente -- "por que essa pessoa nao consegue entrar?"
 *   master   -- "quem tem acesso total aqui?"
 *   sistema  -- "por que esse perfil nao tem botao de editar?"
 *
 * Todas carregam `title`, porque o selo diz O QUE e, e o title diz o que ISSO SIGNIFICA.
 */
.cp-selo-pendente,
.cp-selo-papel,
.cp-selo-sistema {
  font-weight: 500;
  font-size: 0.6875rem;
  vertical-align: middle;
}

.cp-selo-pendente {
  background: var(--cp-atencao-suave);
  color: var(--cp-atencao);
}

/*
 * O PAPEL, em selo neutro. Neutro de proposito: o papel e o estado normal de todo mundo,
 * e colori-lo competiria com o escudo de master, que e o unico sinal que pede atencao.
 */
.cp-selo-papel {
  background: var(--cp-fundo);
  color: var(--cp-texto-suave);
  border: 1px solid var(--cp-borda);
}

/*
 * A CONTAGEM -- quantos registros existem do outro lado de um botao.
 *
 * Azul rebaixado, e nao a primaria cheia: ela e informacao de apoio, e nao acao nem estado. Cheia,
 * uma coluna inteira de selos azuis puxaria o olho para o canto da tabela toda vez que a tela
 * abrisse -- e o que se procura numa lista de matriculas e o NOME.
 *
 * Zero nao usa este selo: ele cai no de atencao, porque zero disciplinas e um caso que pede acao.
 * Ver `celula` em cadastros.js.
 */
.cp-selo-contagem {
  background: var(--cp-primaria-suave);
  color: var(--cp-primaria);
  font-variant-numeric: tabular-nums;
}

/*
 * O escudo e o UNICO sinal de master -- nao ha mais selo escrito "Master" ao lado dele.
 * Por isso ele carrega title e aria-label: sem texto visivel, quem usa leitor de tela ou
 * passa o mouse depende deles para saber o que o desenho quer dizer.
 */
.cp-icone-master {
  color: var(--cp-primaria);
  font-size: 0.875rem;
  vertical-align: middle;
}


.cp-selo-sistema {
  background: var(--cp-fundo);
  color: var(--cp-texto-suave);
  border: 1px solid var(--cp-borda);
}

/*
 * `text-primary` PASSA A SER O AZUL DAQUI, e nao o do Bootstrap.
 *
 * A utilidade dele pinta `rgb(13, 110, 253)` -- um azul que nao existe neste projeto, cujo
 * primario e `#2b59d4` no claro e `#6f95ff` no escuro. Duas coisas quebravam ao usa-la: um
 * hexadecimal fora do `tokens.css`, e um azul que NAO ACOMPANHA O TEMA -- o mesmo tom ficaria
 * sobre fundo claro e sobre fundo escuro, e no escuro ele e escuro demais para se ler.
 *
 * O `!important` responde ao `!important` da utilidade, e nao a uma disputa de especificidade:
 * as classes de utilidade do Bootstrap nascem todas assim, para vencerem o componente que
 * decoram. So `!important` cede a `!important`.
 *
 * Amarrar em vez de evitar a classe: ela ja era usada no giro da central de atividades, com o
 * azul errado, e quem escrever `text-primary` na proxima tela vai esperar o azul do sistema.
 */
.text-primary {
  color: var(--cp-primaria) !important;
}

/*
 * `btn-transparent` -- a variante de botao SEM CAIXA.
 *
 * O nome segue a familia do Bootstrap (`btn-primary`, `btn-outline-secondary`) de proposito: ela
 * e passada pelo mesmo parametro `classe` do `Cp.botao`, e um nome fora do padrao ali pareceria
 * outra coisa. Mas ela NAO existe no Bootstrap -- e daqui, e so daqui.
 *
 * As variaveis sao as `--bs-btn-*` que o proprio `.btn` le. Escrever `background: transparent`
 * direto funcionaria ate o primeiro estado: o Bootstrap resolve hover, foco e desabilitado por
 * essas variaveis, e um `background` cru seria substituido por elas no hover, trazendo a caixa
 * de volta so naquele momento.
 *
 * O HOVER MUDA A COR DO SIMBOLO, e nao o fundo -- mesma decisao dos botoes da navbar: o que
 * responde ao mouse e o icone, que e o que a pessoa esta mirando.
 */
.btn-transparent {
  --bs-btn-color: var(--cp-texto-suave);
  --bs-btn-bg: transparent;
  --bs-btn-border-color: transparent;
  --bs-btn-hover-color: var(--cp-texto);
  --bs-btn-hover-bg: transparent;
  --bs-btn-hover-border-color: transparent;
  --bs-btn-active-color: var(--cp-texto);
  --bs-btn-active-bg: transparent;
  --bs-btn-active-border-color: transparent;
  --bs-btn-disabled-color: var(--cp-texto-suave);
  --bs-btn-disabled-bg: transparent;
  --bs-btn-disabled-border-color: transparent;

  /* O anel de foco do `.btn` continua valendo -- so troca de cor, para nao ficar azul do
     Bootstrap no meio de uma tela que nao usa aquele azul. */
  --bs-btn-focus-shadow-rgb: none;

  box-shadow: none;
}

.btn-transparent:focus-visible {
  outline: 0;
  color: var(--cp-texto);
  box-shadow: 0 0 0 3px var(--cp-primaria-suave);
}

/* -- Botoes de acao: SO ICONE --------------------------------------------------------------- */

/*
 * Sem rotulo, o alvo de clique precisa ser previsivel: largura fixa impede que o botao encolha
 * conforme o glifo, e mantem as colunas de acao alinhadas entre as linhas.
 */
.cp-acao {
  width: 2rem;
  height: 2rem;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}

.cp-acao + .cp-acao {
  margin-left: 0.25rem;
}

/*
 * O GATILHO DO DETALHE e maior que os outros botoes de acao, e a diferenca e proposital.
 *
 * Ele nao esta na mesma familia deles. Lapis e lixeira agem sobre o registro e ficam na ponta
 * direita da linha, em grupo; este abre e fecha o painel, mora sozinho na PRIMEIRA coluna e e o
 * unico alvo da linha inteira em muitas telas. Perdida a moldura, o que sobrou para marcar a
 * coluna foi o simbolo -- e no tamanho dos outros ele ficava miudo demais para isso.
 *
 * A CAIXA NAO ACOMPANHA MAIS O GLIFO, e o valor dela e o teto e nao um gosto: a linha do
 * `table-sm` mede cerca de 2.28rem -- 0.4375rem de folga de cada lado mais a altura do texto --,
 * entao 2.25rem e o ultimo tamanho que ainda CABE no espaco que ja existia. Passando disso, quem
 * define a altura da linha vira o botao, e a listagem de 25 avaliacoes fica sensivelmente mais
 * longa. E a diferenca entre crescer dentro da tabela e empurra-la.
 *
 * Por isso o ajuste fino e no `font-size`, que mexe so no desenho: ele foi de 20px para 18px sem
 * a caixa se mover, e continua com folga em volta -- o alvo de clique e o `.cp-acao` inteiro, e
 * nao o glifo.
 */
.cp-acao[data-detalhe] {
  width: 2.25rem;
  height: 2.25rem;
  font-size: 1.125rem;
}

/* -- DataTables: a forma do Tailwind, a cor dos tokens -------------------------------------- */

/*
 * O QUE FOI PEDIDO AQUI FOI "ESTILO TAILWIND", E O QUE ISSO QUER DIZER E FORMA -- NAO PALETA.
 *
 * A tabela do Tailwind se reconhece por seis coisas, e todas as seis sao alcancaveis com os
 * tokens deste projeto: cabecalho numa superficie rebaixada com rotulo miudo em caixa alta,
 * corpo dividido por fio de 1px em vez de moldura, realce de linha discreto, anel de foco de
 * 2-3px, paginacao em pilula, e vazio centrado com folga generosa.
 *
 * O TAILWIND DE VERDADE NAO ENTRA, e a razao nao e preferencia -- sao quatro regras deste
 * repositorio que ele quebraria de uma vez:
 *
 *   1. Ele exige um passo de build. Nao ha `package.json` nem node aqui, e o Nixpacks provisiona
 *      PHP e mais nada: o CSS gerado precisaria ser commitado a mao a cada classe nova.
 *   2. A alternativa (o CDN do Tailwind) e proibida -- nenhuma tag de terceiro em tela onde a
 *      sessao vive, nem para a fonte.
 *   3. O Preflight reescreve `table`, `button`, titulo e margem na aplicacao INTEIRA. O estrago
 *      apareceria fora das tabelas, que e onde ninguem procuraria.
 *   4. As utilidades trazem hexadecimal proprio e um variante `dark:` que nao olha para
 *      `data-bs-theme`. O tema escuro passaria a ter duas fontes de verdade.
 *
 * Por isso NENHUMA cor abaixo e literal. E `--cp-fundo` sobre `--cp-superficie` faz o trabalho
 * do `gray-50` nos DOIS temas sem regra duplicada: ele e o tom imediatamente mais escuro que a
 * superficie tanto no claro quanto no escuro.
 *
 * A classe `.dataTables_wrapper` saiu junto: e do DataTables 1.x, e a versao vendorizada e a
 * 2.1.8, que emite `.dt-container`. Ela nao casava com nada.
 */

/*
 * Sem folga externa -- a tabela ENCOSTA na borda do cartao.
 *
 * Era o `padding: 0.75rem` daqui que impedia o fio do cabecalho de atravessar a largura inteira:
 * ele morria a 0.75rem de cada lado e a faixa do cabecalho ficava flutuando dentro do cartao,
 * que e exatamente o oposto do desenho pretendido. Quem recebe respiro agora sao as faixas de
 * ferramentas, cada uma por conta propria.
 */
div.dt-container {
  padding: 0;
}

/*
 * As duas faixas de ferramentas: buscar/quantidade em cima, contagem/paginas embaixo.
 *
 * O `--bs-gutter-x: 0` nao e enfeite. Elas sao `.row` do Bootstrap, que nasce com margem
 * NEGATIVA de meia calha -- somada ao padding daqui, a faixa sairia mais larga que a tabela e
 * vazaria por fora do cartao. Zerar a calha torna a conta previsivel: a folga e a que esta
 * escrita, e nao ela menos o que o grid subtrai.
 *
 * `.dt-layout-table` fica de fora: essa linha e a tabela, e ela vai de borda a borda.
 */
div.dt-container > div.dt-layout-row:not(.dt-layout-table) {
  --bs-gutter-x: 0;
  margin: 0;
  padding: 0.75rem 1rem;
  align-items: center;
}

div.dt-container > div.dt-layout-row:first-child {
  border-bottom: 1px solid var(--cp-borda);
}

div.dt-container > div.dt-layout-row:last-child {
  border-top: 1px solid var(--cp-borda);
}

/*
 * As variaveis do Bootstrap, amarradas aos tokens.
 *
 * `--bs-table-bg` vira transparente de proposito: as celulas passam a deixar ver a superficie do
 * cartao, e o realce de linha deixa de disputar com um fundo opaco pintado por baixo dele.
 */
div.dt-container table.dataTable {
  --bs-table-bg: transparent;
  --bs-table-color: var(--cp-texto);
  --bs-border-color: var(--cp-borda);

  border-color: var(--cp-borda);
  width: 100%;
}

/*
 * O Bootstrap desenha `border-top: 2px solid currentColor` entre `<thead>` e `<tbody>`. E o fio
 * duplo grosso que denuncia uma tabela como "Bootstrap padrao" a metros de distancia; no lugar
 * dele fica o fio de 1px do proprio cabecalho.
 */
div.dt-container table.dataTable > :not(:first-child) {
  border-top: 0;
}

/* -- Cabecalho: rotulo, e nao titulo ------------------------------------------------------- */

/*
 * Miudo, em caixa alta, espacado e em cinza: o cabecalho de coluna e ROTULO, e nao conteudo.
 * Rebaixa-lo assim faz o dado da linha ganhar o peso da leitura sem precisar engrossar o dado.
 */
div.dt-container table.dataTable > thead > tr > th,
div.dt-container table.dataTable > thead > tr > td {
  background: var(--cp-fundo);
  color: var(--cp-texto-suave);
  border-bottom: 1px solid var(--cp-borda);
  padding: 0.625rem 1rem;
  font-size: 0.6875rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  white-space: nowrap;
}

/*
 * A FOLGA DA SETA -- e por que ela precisa ser reposta aqui.
 *
 * O DataTables reserva `padding-right: 30px` na coluna ordenavel, porque o indicador e um `span`
 * POSICIONADO POR CIMA da celula: sem a folga, ele nao empurra nada, ele cobre. A regra de folga
 * logo acima usa `padding` abreviado e, ganhando em especificidade, apagava essa reserva.
 *
 * O sintoma nao aparece na coluna comum -- so na alinhada a direita, onde o texto termina
 * embaixo da seta. Na conferencia, "Acoes" saiu lido como "ACOE$" e "Nivel" com a seta sobre o
 * L. Colunas de numero e de acao sao justamente as que alinham a direita, entao o defeito
 * atinge sempre a ponta da tabela, que e onde menos se olha ao revisar.
 */
div.dt-container table.dataTable > thead > tr > th.dt-orderable-asc,
div.dt-container table.dataTable > thead > tr > th.dt-orderable-desc,
div.dt-container table.dataTable > thead > tr > th.dt-ordering-asc,
div.dt-container table.dataTable > thead > tr > th.dt-ordering-desc,
div.dt-container table.dataTable > thead > tr > td.dt-orderable-asc,
div.dt-container table.dataTable > thead > tr > td.dt-orderable-desc,
div.dt-container table.dataTable > thead > tr > td.dt-ordering-asc,
div.dt-container table.dataTable > thead > tr > td.dt-ordering-desc {
  padding-right: 2rem;
}

div.dt-container table.dataTable.table-sm > thead > tr > th.dt-orderable-asc,
div.dt-container table.dataTable.table-sm > thead > tr > th.dt-orderable-desc,
div.dt-container table.dataTable.table-sm > thead > tr > th.dt-ordering-asc,
div.dt-container table.dataTable.table-sm > thead > tr > th.dt-ordering-desc,
div.dt-container table.dataTable.table-sm > thead > tr > td.dt-orderable-asc,
div.dt-container table.dataTable.table-sm > thead > tr > td.dt-orderable-desc,
div.dt-container table.dataTable.table-sm > thead > tr > td.dt-ordering-asc,
div.dt-container table.dataTable.table-sm > thead > tr > td.dt-ordering-desc {
  padding-right: 1.5rem;
}

/*
 * O DataTables marca a coluna ordenavel com `outline: 2px solid rgba(0,0,0,.05)` no hover -- um
 * retangulo em hexadecimal proprio, que no tema escuro ele troca por branco em outra regra.
 * Zerado aqui e substituido por um realce que ja vem do token, os dois temas passam a ser
 * servidos por UMA declaracao.
 */
div.dt-container table.dataTable > thead > tr > th.dt-orderable-asc:hover,
div.dt-container table.dataTable > thead > tr > th.dt-orderable-desc:hover,
div.dt-container table.dataTable > thead > tr > td.dt-orderable-asc:hover,
div.dt-container table.dataTable > thead > tr > td.dt-orderable-desc:hover {
  outline: 0;
  background: var(--cp-primaria-suave);
  color: var(--cp-texto);
}

/* A coluna que ESTA ordenando se distingue do resto do cabecalho pelo peso do texto. */
div.dt-container table.dataTable > thead > tr > th.dt-ordering-asc,
div.dt-container table.dataTable > thead > tr > th.dt-ordering-desc {
  color: var(--cp-texto);
}

/*
 * As setinhas nascem com opacidade .125 -- praticamente invisiveis, e quem nao sabe que a coluna
 * ordena nao descobre. A inativa sobe para .35 (o cinza discreto que se enxerga), e a ativa vai
 * a cor da marca e opacidade cheia.
 */
div.dt-container table.dataTable > thead > tr > th span.dt-column-order:before,
div.dt-container table.dataTable > thead > tr > th span.dt-column-order:after,
div.dt-container table.dataTable > thead > tr > td span.dt-column-order:before,
div.dt-container table.dataTable > thead > tr > td span.dt-column-order:after {
  opacity: 0.35;
}

div.dt-container table.dataTable > thead > tr > th.dt-ordering-asc span.dt-column-order:before,
div.dt-container table.dataTable > thead > tr > th.dt-ordering-desc span.dt-column-order:after,
div.dt-container table.dataTable > thead > tr > td.dt-ordering-asc span.dt-column-order:before,
div.dt-container table.dataTable > thead > tr > td.dt-ordering-desc span.dt-column-order:after {
  color: var(--cp-primaria);
  opacity: 1;
}

/* -- Corpo: fio entre linhas, nao moldura -------------------------------------------------- */

/*
 * A separacao vem de um fio no TOPO de cada linha, e nao de uma borda embaixo de cada celula.
 * Sao desenhos diferentes no fim da tabela: com borda embaixo, a ultima linha ganha um fio solto
 * a um pixel da borda do cartao -- dois tracos paralelos onde deveria haver um.
 */
div.dt-container table.dataTable > tbody > tr > td,
div.dt-container table.dataTable > tbody > tr > th {
  border-top: 1px solid var(--cp-borda);
  border-bottom: 0;
  padding: 0.625rem 1rem;
  color: var(--cp-texto);
  vertical-align: middle;
}

/* O cabecalho ja fechou com o fio dele; sem isto, a primeira linha desenha o segundo por cima. */
div.dt-container table.dataTable > tbody > tr:first-child > td,
div.dt-container table.dataTable > tbody > tr:first-child > th {
  border-top: 0;
}

/*
 * O REALCE DE LINHA, e por que ele e sombra e nao fundo.
 *
 * O DataTables pinta o hover com `box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-hover),.075)`
 * -- preto a 7,5% no tema claro, branco no escuro, por variavel propria. Trocar so a variavel
 * nao serve: ela e um TRIO RGB para entrar num `rgba()`, e os tokens sao hexadecimais.
 *
 * Entao a sombra inteira e substituida, com cor opaca do token. Precisa continuar sendo sombra
 * porque e sombra que vence: um `background` na celula fica ATRAS da sombra que o DataTables
 * pinta, e o realce simplesmente nao apareceria.
 */
div.dt-container table.table.dataTable.table-hover > tbody > tr:hover > * {
  box-shadow: inset 0 0 0 9999px var(--cp-fundo);
}

/* Linhas alternadas usam o mesmo tom -- e por isso a tabela escolhe UM dos dois, nunca os dois:
   com zebra e hover na mesma cor, passar o mouse na linha impar nao mostra nada. */
div.dt-container table.table.dataTable.table-striped > tbody > tr:nth-of-type(2n + 1) > * {
  box-shadow: inset 0 0 0 9999px var(--cp-fundo);
}

/*
 * A tabela densa (`table-sm`) so muda de folga -- todo o resto vem das regras acima. Ela e a
 * maioria das telas de cadastro, entao a folga menor precisa ser deliberada, e nao herdada.
 */
div.dt-container table.dataTable.table-sm > thead > tr > th,
div.dt-container table.dataTable.table-sm > thead > tr > td,
div.dt-container table.dataTable.table-sm > tbody > tr > td,
div.dt-container table.dataTable.table-sm > tbody > tr > th {
  padding: 0.4375rem 0.75rem;
}

/* -- A linha de DETALHE: um painel, e nao mais uma linha ------------------------------------ */

/*
 * O QUE FALTAVA quando as tabelas ganharam o desenho novo. A linha filha (`row().child`) abre as
 * acoes da avaliacao, e sem estilo proprio ela herdava a aparencia de LINHA DE DADOS: mesmo
 * fundo, mesmo fio em cima, mesmo realce ao passar o mouse. Quem abria via a tabela ganhar uma
 * linha a mais, e nao um painel se abrindo dentro dela.
 *
 * Tres coisas a distinguem, e cada uma responde a uma pergunta de quem olha:
 *
 *   o FUNDO REBAIXADO diz "isto nao e um registro" -- e o mesmo `--cp-fundo` da cabeca da
 *   tabela, que ja carrega esse significado aqui dentro;
 *
 *   a FAIXA DE ACENTO a esquerda diz DE QUEM e o painel: sem ela, aberto no meio de uma pagina
 *   de vinte linhas, ele nao se liga visualmente a linha que o abriu;
 *
 *   a AUSENCIA DE FIO EM CIMA gruda o painel na linha-mae. Com o fio, os dois se leem como
 *   irmaos; sem ele, como um bloco so.
 */
div.dt-container table.dataTable > tbody > tr.cp-detalhe > td {
  background: var(--cp-fundo);
  border-top: 0;

  /* A folga vem do `p-3` do conteudo, e nao daqui: com as duas, a faixa de acento ficaria
     afastada da borda e deixaria de encostar na linha de cima. */
  padding: 0;

  /* A faixa E SOMBRA INTERNA, e nao `border-left`: borda muda a largura da celula e desalinha o
     painel das colunas acima dele. */
  box-shadow: inset 3px 0 0 var(--cp-primaria);
}

/*
 * O REALCE DE LINHA NAO VALE AQUI. `table-hover` pinta qualquer `tr` sob o cursor, e o painel
 * ficaria acendendo enquanto a pessoa move o mouse ATE OS BOTOES dele -- prometendo um clique
 * que a linha nao tem. Repete a sombra do fundo para vencer a do hover, que e sombra tambem.
 */
div.dt-container table.table.dataTable.table-hover > tbody > tr.cp-detalhe:hover > * {
  box-shadow: inset 3px 0 0 var(--cp-primaria);
}

/*
 * A LINHA-MAE FICA MARCADA enquanto o painel esta aberto. `dt-hasChild` e posta pelo DataTables.
 *
 * Sem isso, rolando a pagina com o painel aberto, nao ha como saber a qual avaliacao ele
 * pertence -- a faixa de acento marca o painel, e esta marca fecha o par por cima.
 */
div.dt-container table.table.dataTable > tbody > tr.dt-hasChild > * {
  background: var(--cp-fundo);
}

/*
 * "Nenhum registro" ocupa espaco de proposito.
 *
 * Espremido na altura de uma linha, o vazio se le como uma linha de dado em branco -- parece
 * defeito de carregamento. Com folga em volta e centrado, se le como resposta.
 */
div.dt-container table.dataTable > tbody > tr > td.dt-empty {
  padding: 2.5rem 1rem;
  color: var(--cp-texto-suave);
  font-size: 0.875rem;
  text-align: center;
}

/* -- Ferramentas: busca, quantidade, contagem ---------------------------------------------- */

div.dt-container .dt-search input,
div.dt-container .dt-length select {
  background: var(--cp-superficie);
  border: 1px solid var(--cp-borda);
  color: var(--cp-texto);
  border-radius: 0.5rem;
  padding: 0.375rem 0.75rem;
  font-size: 0.8125rem;
  line-height: 1.25rem;
  transition: border-color var(--cp-transicao), box-shadow var(--cp-transicao);
}

div.dt-container .dt-search input::placeholder {
  color: var(--cp-texto-suave);
}

/*
 * O anel de foco -- a marca registrada do Tailwind, e aqui ele tambem e acessibilidade.
 *
 * O `outline: 0` sozinho seria remover o indicador de foco de quem navega por teclado. Ele so
 * pode sair porque a sombra abaixo o SUBSTITUI, e com area maior: o anel de 3px se enxerga de
 * longe, enquanto a borda de 1px trocando de cor exige olhar para o campo certo.
 */
div.dt-container .dt-search input:focus,
div.dt-container .dt-length select:focus {
  outline: 0;
  border-color: var(--cp-primaria);
  box-shadow: 0 0 0 3px var(--cp-primaria-suave);
}

div.dt-container .dt-info,
div.dt-container .dt-length label {
  color: var(--cp-texto-suave);
  font-size: 0.8125rem;
  margin: 0;
}

/* -- Paginacao: pilhas soltas, nao um bloco emendado --------------------------------------- */

/*
 * O Bootstrap emenda os botoes num bloco unico -- `margin-left: -1px` para as bordas colapsarem.
 * O desenho daqui e o oposto: cada pagina e uma pilula independente, separada por folga, sem
 * borda enquanto esta em repouso. Zerar a margem e o que desfaz a emenda.
 */
div.dt-container .dt-paging ul.pagination {
  margin: 0;
  gap: 0.25rem;
}

div.dt-container .dt-paging .page-item .page-link {
  margin: 0;
  border: 1px solid transparent;
  border-radius: 0.5rem;
  background: transparent;
  color: var(--cp-texto-suave);
  font-size: 0.8125rem;
  padding: 0.25rem 0.625rem;
  min-width: 2rem;
  text-align: center;
  transition: background var(--cp-transicao), color var(--cp-transicao),
    border-color var(--cp-transicao);
}

/* O `:not(.active):not(.disabled)` existe para o hover nao apagar a pagina atual ao passar por
   cima dela, nem prometer clique numa seta que nao leva a lugar nenhum. */
div.dt-container .dt-paging .page-item:not(.active):not(.disabled) .page-link:hover {
  background: var(--cp-fundo);
  border-color: var(--cp-borda);
  color: var(--cp-texto);
}

div.dt-container .dt-paging .page-item.active .page-link {
  background: var(--cp-primaria);
  border-color: var(--cp-primaria);
  color: var(--cp-sobre-primaria);
}

div.dt-container .dt-paging .page-item.disabled .page-link {
  background: transparent;
  border-color: transparent;
  color: var(--cp-texto-suave);
  opacity: 0.45;
}

/* `:focus-visible`, e nao `:focus`: o anel aparece para quem chegou de teclado e nao para quem
   acabou de clicar -- que ja sabe onde esta, e para quem o anel so fica no caminho. */
div.dt-container .dt-paging .page-link:focus-visible {
  outline: 0;
  box-shadow: 0 0 0 3px var(--cp-primaria-suave);
}

/*
 * GRAFICOS
 *
 * O SVG nasce com largura em pixels -- ele CRESCE com a quantidade de barras, em vez de
 * espremer 45 questoes na largura da tela ate cada uma virar um fio. Quem rola e este
 * container, e nao a pagina: barra horizontal na janela inteira para ler um grafico e o tipo de
 * coisa que faz a pessoa desistir de ler.
 */
.cp-grafico-rolagem {
  overflow-x: auto;
  overflow-y: hidden;
}

/*
 * O container de UM grafico. `position: relative` e exigencia do Chart.js: e sobre ele que o
 * canvas responsivo se dimensiona. Sem isso o grafico cresce a cada redesenho, porque mede um
 * pai que ja contem a altura dele.
 */
.cp-grafico {
  position: relative;
  width: 100%;
}

/*
 * O GIRO DE PROGRESSO.
 *
 * Classe propria, e nao a `fa-spin` do FontAwesome, por causa da regra de
 * `prefers-reduced-motion` la de cima: ela zera a duracao de TODA animacao da pagina, e o
 * spinner do botao parava de girar em quem tem efeitos desligados no sistema -- que foi
 * exatamente o defeito relatado.
 *
 * A excecao e deliberada e estreita. Movimento decorativo pode e deve ser desligado a pedido;
 * este aqui e a UNICA coisa dizendo que o sistema continua trabalhando, e sem ele "processando"
 * fica indistinguivel de "travado". O giro e lento de proposito, para informar sem incomodar.
 */
@keyframes cp-girar {
  to { transform: rotate(360deg); }
}

.cp-girando {
  animation: cp-girar 1.6s linear infinite;
}

@media (prefers-reduced-motion: reduce) {
  .cp-girando {
    animation: cp-girar 2.4s linear infinite !important;
  }
}

/*
 * O selo de quantas atividades estao em curso, no canto do botao da navbar.
 *
 * VERMELHO, e nao a cor da marca: ele so aparece quando ha trabalho pendente, e o vermelho e a
 * cor que o olho encontra sem procurar. Em azul, ele se confundia com o proprio botao.
 *
 * O ALINHAMENTO e ancorado no CANTO com `translate`, e nao com deslocamentos em rem. Com o
 * icone em fa-2x o botao mudou de tamanho, e qualquer medida fixa deixaria o selo boiando --
 * longe demais num tamanho, por cima do desenho no outro. Assim ele fica no canto seja qual
 * for o tamanho do botao.
 *
 * `line-height: 1` e o que centra o numero: sem isso o digito herda a entrelinha do corpo e
 * desce alguns pixels dentro da pilula.
 */
.cp-selo-atividades {
  position: absolute;
  top: 0;
  right: 0;
  transform: translate(35%, -35%);
  min-width: 1.15rem;
  padding: 0.2rem 0.35rem;
  line-height: 1;
  font-size: 0.7rem;
  background: var(--cp-perigo);
  color: var(--cp-sobre-perigo);
}

.cp-menu-atividades {
  min-width: 20rem;
  max-width: min(24rem, 90vw);
}

/*
 * A LISTA ROLA; o cabecalho nao.
 *
 * Sem teto, vinte atividades fazem o menu passar da altura da janela -- e o que sai da tela sai
 * tambem do alcance, porque menu suspenso nao rola junto com a pagina. Com o teto na LISTA, e
 * nao no menu, o titulo "Atividades" fica parado enquanto o conteudo corre por baixo.
 *
 * A altura acompanha a janela, com um teto absoluto: 60vh cabe em notebook e em celular
 * deitado, e as 26rem impedem que um monitor alto vire uma lista de trinta centimetros.
 */
.cp-atividades-lista {
  max-height: min(60vh, 26rem);
  overflow-y: auto;
}

.cp-atividade + .cp-atividade {
  border-top: 1px solid var(--cp-borda);
}

/*
 * O OLHO ao lado do campo de senha.
 *
 * A borda do botao acompanha a do campo, e nao a do tema do Bootstrap: sem isso, o par fica com
 * duas bordas de tons diferentes encostadas uma na outra, e a emenda aparece.
 */
.cp-olho {
  border-color: var(--cp-borda);
  color: var(--cp-texto-suave);
}

.cp-olho:hover,
.cp-olho:focus {
  background: var(--cp-fundo);
  border-color: var(--cp-borda-forte);
  color: var(--cp-texto);
}

/*
 * A PREVIA DA LOGOMARCA no modal da organizacao.
 *
 * Quadrada e com `object-fit: contain`: logomarca chega em qualquer proporcao, e `cover`
 * cortaria justamente as bordas onde costuma estar o nome da escola.
 */
.cp-logo-previa,
.cp-logo-vazia {
  width: 5rem;
  height: 5rem;
  border-radius: var(--cp-raio);
  border: 1px solid var(--cp-borda);
  flex: 0 0 auto;
}

.cp-logo-previa {
  object-fit: contain;
  background: var(--cp-superficie);
}

.cp-logo-vazia {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--cp-texto-suave);
  background: var(--cp-fundo);
  font-size: 1.5rem;
}

/*
 * SELECT2 nas cores do projeto.
 *
 * O tema bootstrap-5 do select2 desenha com as variaveis do Bootstrap, e nao olha para
 * `data-bs-theme` -- no modo escuro o campo saia branco no meio de um modal escuro. As regras
 * abaixo amarram tudo aos TOKENS, que ja viram com o tema: uma declaracao serve aos dois.
 */
.select2-container--bootstrap-5 .select2-selection,
.select2-container--bootstrap-5 .select2-dropdown,
/* O campo de busca leva o seletor INTEIRO do tema: com um mais curto, a regra dele -- que fixa
   fundo branco em hexadecimal -- ganha por especificidade, e a caixa fica branca no escuro. */
.select2-container--bootstrap-5 .select2-dropdown .select2-search .select2-search__field {
  background: var(--cp-superficie);
  border-color: var(--cp-borda);
  color: var(--cp-texto);
}

.select2-container--bootstrap-5 .select2-selection--single .select2-selection__rendered {
  color: var(--cp-texto);
}

.select2-container--bootstrap-5 .select2-selection--single .select2-selection__placeholder {
  color: var(--cp-texto-suave);
}

.select2-container--bootstrap-5 .select2-results__option {
  color: var(--cp-texto);
}

/* A opcao sob o cursor usa a cor da marca -- a mesma do resto da aplicacao. */
.select2-container--bootstrap-5 .select2-results__option--highlighted,
.select2-container--bootstrap-5 .select2-results__option--selected {
  background: var(--cp-primaria);
  color: var(--cp-sobre-primaria);
}

.select2-container--bootstrap-5.select2-container--focus .select2-selection,
.select2-container--bootstrap-5.select2-container--open .select2-selection {
  border-color: var(--cp-primaria);
}


/*
 * A LINHA DO TEMPO -- estrutura do AdminLTE, cores daqui.
 *
 * A forma e a dele: eixo vertical, marcador redondo com icone, cartao a direita. E uma
 * convencao que a pessoa ja viu em outros sistemas, e reconhecer a forma poupa a leitura de
 * descobrir o que a tela esta dizendo.
 *
 * O QUE NAO VEIO JUNTO foi a cor. O adminlte.css inteiro traz 183 regras de `.card` e 72 de
 * sidebar, e carrega-lo reestilizaria toda a aplicacao -- inclusive o layout proprio e o modo
 * escuro, que aqui saem dos tokens. Copiar a estrutura de meia duzia de regras custa menos do
 * que reconferir cada tela do sistema.
 */
/*
 * O SELECT2 DENTRO DE UM `input-group`.
 *
 * O Bootstrap monta o grupo como flex e espera que os filhos sejam `.form-control`,
 * `.form-select` ou `.btn`. O select2 nao e nenhum dos tres: ele ESCONDE o `<select>` original e
 * poe no lugar um `<span class="select2-container">` que o grupo nao sabe dimensionar -- o
 * resultado e o campo encolhendo para o proprio conteudo e o botao caindo para fora do conjunto,
 * como se nao fizesse parte dele.
 *
 * As tres regras abaixo devolvem ao container o que o `.form-select` teria: crescer para ocupar o
 * espaco, altura igual a do vizinho, e o canto direito reto para encostar no botao.
 *
 * `width: auto` com `!important` porque o select2 escreve a largura em ESTILO INLINE, calculada
 * do tamanho do `<select>` escondido -- e estilo inline nao se vence de outro jeito. A largura
 * quem decide passa a ser o flex.
 */
.input-group > .select2-container {
  flex: 1 1 auto;
  width: auto !important;
}

.input-group > .select2-container .select2-selection {
  height: 100%;
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
}

/*
 * O SELETOR DE ANO -- input com botao, e o painel de anos que ele abre.
 *
 * NAO E UM DATEPICKER. Escolher um periodo letivo e escolher um numero de quatro digitos, e um
 * calendario pediria dia e mes que nao existem nessa pergunta -- alem de trazer uma biblioteca
 * inteira para resolver doze botoes.
 *
 * `position: relative` na caixa e o que ancora o painel: ele flutua sobre o conteudo em vez de
 * empurrar a lista de disciplinas para baixo a cada abertura.
 */
.cp-ano-caixa {
  position: relative;
}

.cp-yearpicker {
  position: absolute;
  z-index: 5;
  top: 100%;
  left: 0;
  margin-top: 0.25rem;
  padding: 0.5rem;
  min-width: 15rem;
  background: var(--cp-superficie);
  border: 1px solid var(--cp-borda);
  border-radius: var(--cp-raio);
  box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
}

/*
 * ANCORADO A DIREITA quando o seletor mora no canto direito do cabecalho.
 *
 * Preso a esquerda ali, o painel -- que e mais largo que o campo -- atravessaria a borda da
 * pagina e a barra de rolagem horizontal apareceria por causa de doze botoes.
 */
.cp-yearpicker-direita {
  left: auto;
  right: 0;
}

.cp-yearpicker-grade {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0.25rem;
}

.cp-yearpicker-ano {
  padding: 0.375rem 0.25rem;
  border: 1px solid transparent;
  border-radius: var(--cp-raio);
  background: transparent;
  color: var(--cp-texto);
  font-size: 0.8125rem;
  line-height: 1.2;
}

.cp-yearpicker-ano:hover {
  background: var(--cp-fundo);
  border-color: var(--cp-borda);
}

.cp-yearpicker-ano[aria-pressed='true'] {
  background: var(--cp-primaria);
  border-color: var(--cp-primaria);
  color: var(--cp-sobre-primaria);
}

/*
 * O PONTO diz que AQUELE ano ja tem grade montada.
 *
 * E a unica coisa que a grade de anos sabe e o campo vazio nao tem como dizer: sem ele, quem
 * abre o painel ve doze numeros iguais e nao faz ideia de onde ha alguma coisa. Com ele, "copiar
 * a grade do ano passado" deixa de ser uma caca.
 *
 * Ponto E negrito, e nao so cor: a diferenca precisa sobreviver a quem nao distingue as duas.
 */
.cp-yearpicker-tem {
  font-weight: 600;
}

.cp-yearpicker-tem::after {
  content: '';
  display: block;
  width: 0.25rem;
  height: 0.25rem;
  margin: 0.125rem auto 0;
  border-radius: 50%;
  background: currentColor;
}

/*
 * A CAIXA DE ROLAGEM DA LINHA DO TEMPO.
 *
 * A lista nao tem fim natural: ela guarda o triplo do que mostra e recebe evento novo sozinha.
 * Sem um teto, o cartao cresce ate a pagina inteira rolar -- e ai o grafico da coluna ao lado sai
 * da tela por causa de uma lista que a pessoa nem estava olhando.
 *
 * SAO DUAS REGRAS PARA DUAS SITUACOES, e nao uma so por descuido.
 *
 * Empilhado (abaixo de xl), a coluna nao tem altura para dar: o teto e em `rem`, medido para
 * caber uma tela de celular sem tomar a rolagem da pagina.
 *
 * Lado a lado, o teto vira a altura da COLUNA VIZINHA -- `flex: 1 1 0` faz a caixa nao pedir
 * altura nenhuma para si, entao quem decide a altura da linha e a coluna dos numeros e do
 * grafico, e a caixa preenche o que sobrar. E o que mantem os dois cartoes terminando juntos por
 * mais que a lista cresca.
 *
 * `min-height` existe para o dia em que a coluna vizinha for curta -- uma escola com poucas
 * fichas --, e sem ele a caixa colapsaria para a altura de nada.
 */
.cp-timeline-rolagem {
  overflow-y: auto;
  max-height: 26rem;

  /* O espaco da barra de rolagem, para ela nao passar por cima dos cartoes dos eventos. */
  padding-right: 0.5rem;
}

@media (min-width: 1200px) {
  .cp-timeline-rolagem {
    flex: 1 1 0;
    min-height: 18rem;
    max-height: none;
  }
}

.cp-timeline {
  position: relative;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* O EIXO. Fica atras dos marcadores, e por isso nasce antes deles na pilha. */
.cp-timeline::before {
  content: '';
  position: absolute;
  top: 0.25rem;
  bottom: 0.25rem;
  left: 0.9375rem;
  width: 2px;
  background: var(--cp-borda);
}

.cp-timeline-dia {
  position: relative;
  margin: 0.75rem 0 0.5rem;
  padding-left: 2.75rem;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--cp-texto-suave);
}

/*
 * O SEPARADOR DE DIA cobre o eixo atras dele.
 *
 * Sem o fundo, a linha atravessa o texto da data e o dia vira parte do fio -- e o olho perde
 * exatamente a marca que existe para orientar.
 */
.cp-timeline-dia::before {
  content: '';
  position: absolute;
  top: -0.25rem;
  bottom: -0.25rem;
  left: 0.6875rem;
  width: 0.5rem;
  background: var(--cp-superficie);
}

.cp-timeline-item {
  position: relative;
  padding: 0 0 0.875rem 2.75rem;
}

/* O MARCADOR. `--cp-superficie` na borda e o que o destaca do eixo que passa por tras. */
.cp-timeline-marca {
  position: absolute;
  left: 0;
  top: 0.125rem;
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.75rem;
  color: var(--cp-sobre-primaria);
  border: 2px solid var(--cp-superficie);
}

.cp-timeline-corpo {
  border: 1px solid var(--cp-borda);
  border-radius: var(--cp-raio);
  padding: 0.5rem 0.75rem;
  background: var(--cp-fundo);
}

/*
 * A ENTRADA DE UM EVENTO NOVO.
 *
 * A lista se atualiza sozinha, e sem isto um evento simplesmente APARECE -- quem estava olhando
 * a tela nao percebe que ela mudou, e quem nao estava nao tem como saber que mudou. O realce
 * dura o suficiente para ser notado de canto de olho e sai sozinho, sem exigir clique.
 *
 * Respeita `prefers-reduced-motion` pela regra global la de cima, que zera toda animacao.
 */
@keyframes cp-timeline-entrada {
  from { background: var(--cp-primaria-suave); border-color: var(--cp-primaria); }
  to   { background: var(--cp-fundo); border-color: var(--cp-borda); }
}

.cp-timeline-novo .cp-timeline-corpo {
  animation: cp-timeline-entrada 2.5s ease-out;
}

/* As etiquetas de numero: folhas, duracao, quem pediu. */
.cp-etiqueta {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.0625rem 0.375rem;
  border-radius: 0.375rem;
  background: var(--cp-superficie);
  border: 1px solid var(--cp-borda);
  font-size: 0.6875rem;
  color: var(--cp-texto-suave);
  white-space: nowrap;
}

/*
 * A FICHA DE TOTAL -- o `small-box` do AdminLTE.
 *
 * O icone grande e semitransparente no canto e o que torna a ficha reconhecivel de relance: o
 * numero responde "quanto", e o icone responde "de que" sem obrigar a ler o rotulo.
 */
/*
 * FLEX, e nao icone posicionado por cima.
 *
 * A primeira versao punha o icone em `position: absolute` a direita, e o texto ocupava a largura
 * inteira por baixo dele -- entao o numero passava POR CIMA do icone. Com flex, o icone e uma
 * coluna de verdade: o texto termina onde ele comeca, e nao ha como um invadir o outro, por mais
 * longo que o numero fique.
 */
.cp-ficha {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  border: 1px solid var(--cp-borda);
  border-radius: var(--cp-raio);
  background: var(--cp-superficie);
  padding: 0.75rem 0.875rem;
  height: 100%;
}

/* `min-width: 0` deixa o texto encolher em vez de empurrar o icone para fora do cartao. */
.cp-ficha-texto {
  flex: 1 1 auto;
  min-width: 0;
}

/*
 * O icone: coluna propria, inteiro e legivel.
 *
 * Ele responde "de que e este numero" sem obrigar a ler o rotulo -- e para isso precisa ser
 * VISTO. A opacidade de marca d'agua que o small-box do AdminLTE usa funciona sobre fundo
 * colorido; sobre superficie clara ela some, e um icone que mal se ve nao ajuda ninguem.
 */
.cp-ficha-icone {
  flex: 0 0 auto;
  font-size: 1.5rem;
  opacity: 0.55;
  pointer-events: none;
}

/* A FAIXA DE ESTADO. 3px na lateral, e nao o cartao inteiro colorido: fundo colorido obriga a
   recalcular o contraste do texto em cima, e o numero e o que precisa ser lido. */
.cp-ficha-faixa {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 3px;
  border-radius: var(--cp-raio) 0 0 var(--cp-raio);
}

/*
  A CAIXA DE MULTIPLA ESCOLHA do mapa de arrumacao.

  Altura fixa com rolagem propria, e nao a lista inteira: uma escola com quarenta salas faria o
  modal crescer ate o rodape sumir da tela -- e o botao de gerar com ele.

  A ALTURA E A MESMA nas quatro caixas (cursos, turmas, avaliacoes, salas) de proposito: com
  alturas diferentes, as duas colunas do modal ficam desalinhadas a cada abertura, conforme o que
  a escola tem cadastrado.
*/
/*
  TRES ITENS A VISTA, e o quarto pede rolagem.

  A altura e MEDIDA, e nao estimada: com a fonte base de 16px, cada `.form-check` ocupa 28px --
  1.5rem de altura minima mais 0.25rem de margem --, o que da 80px ate o fim do terceiro; somando
  o padding e a borda da caixa, 98px. Dai os 6.125rem.

  Por que tres: a caixa fica dentro do cartao "Onde eles sentam", ao lado do formulario de quem faz
  a prova. Alta demais, ela empurra o botao de arrumar para fora da tela em monitor de notebook --
  e o botao e o proximo gesto de quem acabou de marcar as salas.
*/
.cp-caixa-rolagem {
  max-height: 6.125rem;
  overflow-y: auto;
  border: 1px solid var(--bs-border-color);
  border-radius: var(--cp-raio);
  padding: .5rem .75rem;
  background: var(--cp-superficie);
}

.cp-caixa-rolagem .form-check {
  margin-bottom: .25rem;
}

.cp-caixa-rolagem .form-check:last-child {
  margin-bottom: 0;
}

/* =========================================================================================
   Aviso de cookies
   ========================================================================================= */

/*
  UMA TARJA NO RODAPE, e nao um modal.

  Modal exige uma decisao antes de qualquer outra coisa, e aqui nao ha decisao a tomar: os
  cookies deste sistema sao os necessarios para entrar, e o aviso apenas informa. Barrar a tela
  de login com uma caixa que so tem "Entendi" e cobrar um clique para devolver o que a pessoa ja
  tinha.

  FICA ACIMA DE TUDO -- inclusive dos modais do Bootstrap, que ficam em 1055. Ela e a ultima
  coisa que alguem quer descobrir por baixo de outra.
*/
.cp-cookies {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 1080;

  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  flex-wrap: wrap;

  padding: .75rem 1rem;
  background: var(--cp-superficie);
  border-top: 1px solid var(--cp-borda-forte);
  box-shadow: 0 -2px 12px rgba(0, 0, 0, .08);
  font-size: .875rem;
}

/*
  O TEXTO ENCOLHE, e o botao nao.

  Sem `flex-shrink`, o texto ocupa toda a largura disponivel e empurra o "Entendi" para a linha
  de baixo em qualquer tela menor que o texto inteiro -- o que inclui a maioria dos monitores. O
  `flex-basis` de 20rem e o ponto em que ele desiste e aceita quebrar: abaixo disso, no celular,
  a tarja em duas linhas e mesmo o formato certo.
*/
.cp-cookies-texto {
  flex: 1 1 20rem;
  max-width: 60rem;
  color: var(--cp-texto);
}

.cp-cookies-texto a {
  color: var(--cp-primaria);
}

/* =========================================================================================
   Convite para ligar a notificacao
   ========================================================================================= */

/*
  UM CARTAO NO CANTO, e nao uma tarja de ponta a ponta como a de cookies.

  A DIFERENCA E DE PESO: o aviso de cookies e obrigacao legal e fala com quem acabou de chegar; o
  convite e um OFERECIMENTO, e ocupar a largura da tela para oferecer algo transforma oferta em
  cobranca. No canto, ele e ignoravel -- que e exatamente o que se quer de quem nao esta
  interessado.

  ELE ENTRA DESLIZANDO, e nao aparece de uma vez. Um bloco que surge no canto do olho durante a
  leitura assusta; o mesmo bloco subindo em 200 ms e percebido sem sobressalto. Quem pediu menos
  movimento nao recebe nenhum -- ver o bloco de `prefers-reduced-motion` no fim.

  A COR DA ACAO E `--cp-primaria`, e nao um verde. Verde aqui e STATUS -- e o que marca "deu
  certo" no resto do sistema --, e usa-lo num botao faria a acao principal desta caixa parecer um
  resultado. O sistema tem uma cor de acao, e e esta.
*/
.cp-convite-push {
  position: fixed;
  right: 1.25rem;
  bottom: 1.25rem;
  z-index: 1070;

  display: flex;
  align-items: flex-start;
  gap: .875rem;

  /*
    SEM ISTO O TEXTO VIRA UMA COLUNA DE UMA PALAVRA.

    A linha dos botoes tem `flex-basis: 100%` para descer para baixo do texto -- e sem `wrap` ela
    nao desce: fica na mesma linha reivindicando a largura inteira, e o que sobra para o texto sao
    uns poucos pixels. O defeito nao aparece na leitura do CSS, e apareceu na primeira imagem.
  */
  flex-wrap: wrap;

  width: calc(100% - 2.5rem);
  max-width: 26rem;
  padding: 1rem;

  background: var(--cp-superficie);
  border: 1px solid var(--cp-borda-forte);
  border-radius: .75rem;
  box-shadow: 0 8px 24px rgba(0, 0, 0, .18);

  opacity: 0;
  transform: translateY(1rem);
  transition: opacity .2s ease, transform .2s ease;
}

.cp-convite-push-visivel {
  opacity: 1;
  transform: translateY(0);
}

/*
  O ICONE NUM QUADRADO ARREDONDADO, e nao solto: solto ele se perde ao lado do texto em negrito, e
  o cartao passa a parecer um paragrafo com um enfeite. O fundo suave e o mesmo da cor de acao, o
  que amarra o icone ao botao sem repetir a cor cheia duas vezes.
*/
.cp-convite-push-icone {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;

  width: 2.5rem;
  height: 2.5rem;

  background: var(--cp-primaria-suave);
  color: var(--cp-primaria);
  border-radius: .625rem;
  font-size: 1.125rem;
}

.cp-convite-push-texto {
  /*
    BASE ZERO, e nao `auto` -- e a diferenca entre o icone ficar AO LADO do texto e ficar em cima
    dele. Com base automatica, este bloco reivindica a largura da frase inteira sem quebra (bem
    mais que o cartao), nao cabe ao lado do icone, e o `wrap` o joga para a linha seguinte. Com
    base zero ele aceita o espaco que sobrar e quebra dentro dele.
  */
  flex: 1 1 0;
  min-width: 0;
  font-size: .875rem;
  color: var(--cp-texto);
}

.cp-convite-push-texto strong {
  display: block;
  margin-bottom: .125rem;
}

.cp-convite-push-texto span {
  color: var(--cp-texto-suave);
}

/*
  OS BOTOES DESCEM PARA BAIXO DO TEXTO, e nao ficam ao lado dele: numa caixa de 26 rem, tres
  colunas espremem o texto a ponto de ele quebrar em quatro linhas de duas palavras.
*/
.cp-convite-push-acoes {
  flex: 1 0 100%;
  display: flex;
  justify-content: flex-end;
  gap: .5rem;
  margin-top: .25rem;
}

/* SOBE QUANDO A TARJA DE COOKIES ESTA NA TELA -- as duas moram no mesmo canto. */
body.cp-com-cookies .cp-convite-push {
  bottom: 6rem;
}

@media (prefers-reduced-motion: reduce) {
  .cp-convite-push {
    transition: none;
    transform: none;
  }
}

/* =========================================================================================
   Botao flutuante do WhatsApp
   ========================================================================================= */

/*
  UM ALVO REDONDO NO CANTO, do tamanho que um dedo acerta sem mirar: 3.5rem e o minimo
  confortavel em toque, e o icone ocupa metade dele.

  A COR NAO VEM DO TEMA -- ver `--cp-whatsapp` em tokens.css. O botao so funciona se for
  reconhecido de relance, e o verde e o que faz esse trabalho.

  SOBE QUANDO A TARJA DE COOKIES ESTA NA TELA. As duas moram no mesmo canto, e sem isto o botao
  fica por baixo da tarja justamente na primeira visita -- que e quando ele mais importa.
*/
.cp-zap {
  position: fixed;
  right: 1.25rem;
  bottom: 1.25rem;
  z-index: 1030;

  display: flex;
  align-items: center;
  justify-content: center;
  width: 3.5rem;
  height: 3.5rem;

  border-radius: 50%;
  background: var(--cp-whatsapp);
  color: var(--cp-sobre-whatsapp);
  font-size: 1.75rem;
  line-height: 1;
  text-decoration: none;
  box-shadow: 0 4px 14px rgba(0, 0, 0, .25);

  transition: transform .15s ease, box-shadow .15s ease;
}

.cp-zap:hover,
.cp-zap:focus {
  color: var(--cp-sobre-whatsapp);
  transform: translateY(-2px);
  box-shadow: 0 6px 18px rgba(0, 0, 0, .3);
}

.cp-zap:focus-visible {
  outline: 2px solid var(--cp-primaria);
  outline-offset: 3px;
}

body.cp-com-cookies .cp-zap {
  bottom: 6rem;
}

/* Quem pediu menos movimento nao ganha o empurrao do hover. */
@media (prefers-reduced-motion: reduce) {
  .cp-zap {
    transition: none;
  }

  .cp-zap:hover,
  .cp-zap:focus {
    transform: none;
  }
}

/* -- Acoes da linha da avaliacao ------------------------------------------------------------ */

/*
 * NO CELULAR OS BOTOES VIRAM UMA LISTA, e nao uma barra que quebra em duas.
 *
 * Sao oito acoes com rotulos longos -- "Conferencia de respostas", "Controle de correcao". Numa
 * tela estreita o `flex-wrap` quebrava a barra em linhas irregulares, com um botao sozinho aqui e
 * dois ali: a ordem deixa de ser legivel, e o alvo do dedo fica do tamanho do texto, que varia de
 * um para outro.
 *
 * Empilhados e ocupando a largura inteira, eles viram o que ja sao -- uma lista de coisas que se
 * pode fazer com esta avaliacao --, e cada alvo tem a largura da tela.
 *
 * BORDAS COLAPSADAS, cantos retos e sem folga externa: e o desenho de `list-group`, alcancado por
 * CSS em vez de trocar as classes de oito botoes. Assim a barra do desktop fica exatamente como
 * estava, e o custo de acrescentar um botao nono continua sendo uma linha no JavaScript.
 */
@media (max-width: 575.98px) {
  .cp-acoes-da-linha {
    flex-direction: column;
    align-items: stretch;

    /*
     * PRESO NA BORDA VISIVEL, e nao na largura da tabela.
     *
     * A tabela tem oito colunas e passa de 1200px; no celular ela rola dentro de um contentor de
     * ~360. A linha de detalhe e filha DELA, entao um botao a 100% media 1212px -- empilhado e
     * fora da tela, que e pior que a barra quebrada de antes.
     *
     * `sticky` com `left: 0` gruda o painel na borda esquerda do que se ve, e a largura passa a
     * sair da JANELA em vez da tabela. Os botoes ficam inteiros na tela sem ninguem rolar de lado.
     *
     * O DESCONTO SAO AS FOLGAS que a linha ja tem a esquerda e a direita -- o respiro do cartao
     * mais o da pagina. Sem ele, 100vw comeca depois da folga esquerda e termina DEPOIS da borda
     * direita da tela, e volta a haver rolagem lateral -- agora por 40px, que e pior de perceber
     * do que por 800.
     */
    position: sticky;
    left: 0;
    width: calc(100vw - 2.5rem);

    /* As utilitarias do Bootstrap vem com `!important`; sem ele aqui, elas venceriam. */
    gap: 0 !important;
    padding: 0 !important;
  }

  /* O seletor de turma e o botao do cartao viajam num `span` proprio -- ele tambem estica. */
  .cp-acoes-da-linha > span {
    display: flex !important;
    flex-direction: column;
    gap: 0 !important;
    width: 100%;
  }

  .cp-acoes-da-linha .btn,
  .cp-acoes-da-linha .form-select {
    width: 100% !important;

    /* A ESQUERDA, como item de lista: centralizado, oito rotulos de larguras diferentes nao
       formam coluna nenhuma, e o olho perde a primeira letra de cada linha. */
    text-align: left;
    border-radius: 0;

    /* A borda de baixo de um encosta na de cima do proximo -- sem isto, sai um fio duplo. */
    margin-top: -1px;
  }

  /* O icone ganha um respiro fixo: alinhados na mesma coluna, os rotulos comecam juntos. */
  .cp-acoes-da-linha .btn .fa-fw {
    margin-right: 0.5rem;
  }
}

/* =========================================================================================
 * O BOTAO PRIMARIO NA COR DA MARCA.
 *
 * O Bootstrap pinta `.btn-primary` com o azul DELE (#0d6efd). As variaveis do botao apontam para
 * o token, e nao para outro literal: trocar a primaria no tokens.css leva os botoes junto.
 * ========================================================================================= */
.btn-primary {
  --bs-btn-bg: var(--cp-primaria);
  --bs-btn-border-color: var(--cp-primaria);
  --bs-btn-color: var(--cp-sobre-primaria);
  --bs-btn-hover-bg: color-mix(in srgb, var(--cp-primaria) 88%, black);
  --bs-btn-hover-border-color: color-mix(in srgb, var(--cp-primaria) 88%, black);
  --bs-btn-active-bg: color-mix(in srgb, var(--cp-primaria) 80%, black);
  --bs-btn-active-border-color: color-mix(in srgb, var(--cp-primaria) 80%, black);
  --bs-btn-disabled-bg: var(--cp-primaria);
  --bs-btn-disabled-border-color: var(--cp-primaria);
}

/* O selo de um enum na tabela (classificacao, tipo de regra): neutro, so para separar do texto. */
.cp-selo-rotulo {
  background: var(--cp-primaria-suave);
  color: var(--cp-texto);
  font-weight: 500;
}

/* =========================================================================================
 * A BUSCA DO MENU, logo acima da navegacao.
 * ========================================================================================= */
.cp-busca-menu {
  position: relative;
  padding: 0.5rem 0.75rem 0.25rem;
}

.cp-busca-menu i {
  position: absolute;
  left: 1.4rem;
  top: 50%;
  transform: translateY(-35%);
  font-size: 0.75rem;
  color: var(--cp-texto-suave);
  pointer-events: none;
}

.cp-busca-menu input {
  padding-left: 1.9rem;
  background: var(--cp-fundo);
  border: 1px solid var(--cp-borda);
  color: var(--cp-texto);
}

/* Buscando, todo grupo aparece -- sem tocar no estado do Bootstrap. Limpar devolve o que estava. */
.cp-nav.cp-nav-buscando .collapse {
  display: block;
}

.cp-nav.cp-nav-buscando .cp-nav-seta {
  visibility: hidden;
}

.cp-nav-sem-resultado {
  color: var(--cp-texto-suave);
  padding: 0.5rem 0.75rem;
}

/* Na lateral aberta, so a marca completa; o simbolo sozinho e da lateral recolhida. */
.cp-sidebar-header .cp-marca--simbolo {
  display: none;
}

/* A versao publicada, abaixo do Sair. */
.cp-sidebar-versao {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.25rem 0.75rem 0.5rem;
  font-size: 0.6875rem;
  color: var(--cp-texto-suave);
}

/* A MIGALHA: a mesma estrutura do menu, em uma linha discreta acima do titulo da tela. */
.cp-migalha .breadcrumb {
  --bs-breadcrumb-divider-color: var(--cp-texto-suave);
  --bs-breadcrumb-item-active-color: var(--cp-texto);
  color: var(--cp-texto-suave);
}

.cp-migalha a {
  color: var(--cp-texto-suave);
  text-decoration: none;
}

.cp-migalha a:hover {
  color: var(--cp-primaria);
}

/* =========================================================================================
 * A LATERAL RECOLHIDA (so icones), acima de lg.
 *
 * O estado e resolvido no <head>, antes da pintura (`data-lateral` no <html>). A MEDIA QUERY
 * ENVOLVE O BLOCO INTEIRO: fora dela, a gaveta do telefone viraria uma coluna de icones.
 *
 * O ROTULO SAI DA VISTA, mas NAO da arvore de acessibilidade: nada de `display: none` -- ele e
 * recortado a zero, e o `title` do item fica para o ponteiro.
 * ========================================================================================= */
@media (min-width: 992px) {
  [data-lateral='recolhida'] .cp-app {
    grid-template-columns: var(--cp-sidebar-recolhida) 1fr;
  }

  [data-lateral='recolhida'] .cp-sidebar {
    width: var(--cp-sidebar-recolhida);
  }

  [data-lateral='recolhida'] .cp-nav-item span,
  [data-lateral='recolhida'] .cp-nav-grupo span,
  [data-lateral='recolhida'] .cp-side-user-texto,
  [data-lateral='recolhida'] .cp-sidebar-versao span,
  [data-lateral='recolhida'] .cp-marca-extenso {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }

  [data-lateral='recolhida'] .cp-busca-menu,
  [data-lateral='recolhida'] .cp-nav-seta,
  [data-lateral='recolhida'] .cp-marca-fio {
    visibility: hidden;
    height: 0;
    padding: 0;
    margin: 0;
  }

  [data-lateral='recolhida'] .cp-nav-item {
    justify-content: center;
  }

  /* RECOLHIDA, TODOS OS GRUPOS ABERTOS A FORCA: com so icones, o titulo do grupo nao se le, e um
     grupo fechado esconderia icones sem dizer onde. */
  [data-lateral='recolhida'] .cp-nav .collapse {
    display: block;
  }

  [data-lateral='recolhida'] .cp-nav-grupo {
    border-top: 1px solid var(--cp-borda);
    height: 0.5rem;
    padding: 0;
    pointer-events: none;
  }

  [data-lateral='recolhida'] .cp-sidebar-header .cp-marca--completa {
    display: none;
  }

  [data-lateral='recolhida'] .cp-sidebar-header .cp-marca--simbolo {
    display: block;
  }

  [data-lateral='recolhida'] #cp-recolher-lateral i {
    transform: rotate(180deg);
  }
}

/* =========================================================================================
 * OS PAINEIS DO VELOXADS
 * ========================================================================================= */

/* O SINAL DO RESULTADO -- sempre junto do numero com sinal, nunca so a cor. */
.cp-negativo { color: var(--cp-perigo); }
.cp-positivo { color: var(--cp-sucesso); }
.cp-atencao { color: var(--cp-atencao); }

.cp-selo-atencao {
  background: var(--cp-atencao-suave);
  color: var(--cp-atencao);
  font-weight: 500;
}

/* A altura do grafico mora na caixa, e nao no canvas: o Chart.js redimensiona pelo pai. */
.cp-grafico-caixa {
  position: relative;
  height: 18rem;
}

.cp-cabecalho-tela p {
  max-width: 60rem;
}

/* O RODAPE COMO BARRA DE ACOES: sticky, e nao fixed -- o fixed atravessaria a lateral. */
.cp-barra-de-acoes {
  position: sticky;
  bottom: 0;
  display: flex;
  justify-content: flex-end;
  gap: 0.5rem;
  margin-top: 1rem;
  padding: 0.75rem 0;
  background: var(--cp-fundo);
  border-top: 1px solid var(--cp-borda);
  z-index: 5;
}

@media print {
  .cp-barra-de-acoes { display: none; }
}

/* O giro de "trabalhando" DESACELERA com movimento reduzido, mas nao para: parado, se le travado. */
@media (prefers-reduced-motion: reduce) {
  .cp-giro { animation-duration: 2.4s !important; }
}
