﻿/* ==========================================================================
   Dois temas, um só conjunto de nomes.
   ==========================================================================

   O escuro continua sendo o padrão — é o cockpit que fica aberto a noite toda
   numa sala de operação, e é o tema que o wordmark branco do
   radiomonitor.com.br pede. O claro existe porque o painel também é usado de
   dia, em sala com janela, onde tela preta cansa e projetor não mostra nada.

   A troca é UM atributo no <html> (`data-tema="claro"`), gravado no
   localStorage e aplicado antes da primeira pintura pelo script no <head> do
   _Layout — senão a página pisca preta antes de clarear.

   Regra para quem for escrever tela nova: NENHUMA cor literal fora deste
   bloco. Três tokens fazem quase todo o trabalho:

     --fundo / --painel / --campo   as três superfícies (página, cartão, campo)
     --tinta                        os canais RGB do realce (hover, zebra,
                                    fim de semana). Branco no escuro, PRETO no
                                    claro — é o que impede que um hover de
                                    `rgba(255,255,255,.04)` desapareça sobre
                                    fundo branco. Use `rgba(var(--tinta), .04)`.
     --texto / --texto-fraco / --texto-tenue

   `color-scheme` não é enfeite: é o que faz o navegador desenhar no tema certo
   o que o CSS não alcança — o calendário do <input type=date>, a lista do
   <select>, a barra de rolagem e o autofill. Sem ele, o seletor de data abre
   branco no meio do painel preto. */

:root {
  color-scheme: dark;

  --fundo:        #0d1117;
  --painel:       #161b22;
  --painel-alto:  #1c2330;
  --campo:        #0d1117;
  --borda:        #2a3038;
  --texto:        #e6edf3;
  --texto-fraco:  #8b949e;
  --texto-tenue:  #6e7681;

  --no-ar:        #3fb950;
  --parada:       #6e7681;
  --reconectando: #d29922;
  --erro:         #f85149;
  --match:        #58a6ff;
  --nao-ident:    #d29922;
  --silencio:     #6e7681;
  /* Fala detectada pela transcrição. Violeta de propósito: azul e âmbar já dizem
     'identificado' e 'não identificado', e a fala é uma leitura de outra natureza —
     ela se sobrepõe às duas em vez de competir. */
  --fala:         #bc8cff;
  --destaque:     #58a6ff;
  --anunciante:   #f0883e;
  --ruim:         #f85149;

  /* Botão de ação principal: o azul é o mesmo nos dois temas — sobre ele o texto
     é branco de qualquer jeito. */
  --primario:       #1f6feb;
  --primario-alto:  #388bfd;
  --primario-texto: #fff;

  /* O log ao vivo é terminal, e terminal é escuro nos dois temas: as cores dos
     eventos (violeta, verde, vermelho claros) foram escolhidas contra preto. */
  --terminal:      #010409;

  /* Barra de sinal cheia (a marca "mais de uma inserção no dia"). */
  --barra-forte: #79c0ff;

  --tinta:  255, 255, 255;
  --fundo-suave: rgba(var(--tinta), .10);

  --raio: 8px;
  --mono: ui-monospace, "Cascadia Code", "Consolas", monospace;
}

:root[data-tema="claro"] {
  color-scheme: light;

  /* Página cinza, cartão branco: no claro a hierarquia inverte — o que estava
     afundado passa a saltar. Sem isso o cartão sumiria no fundo, porque no
     escuro ele é MAIS claro que a página. */
  --fundo:        #f3f5f9;
  --painel:       #ffffff;
  --painel-alto:  #e9edf2;
  --campo:        #ffffff;
  --borda:        #d3dae3;
  --texto:        #1b2430;
  --texto-fraco:  #566274;
  --texto-tenue:  #68727f;

  /* Os mesmos significados, escurecidos: o verde e o âmbar do tema escuro têm
     contraste de 2:1 sobre branco — viram texto que não se lê. */
  --no-ar:        #17803d;
  --parada:       #68727f;
  --reconectando: #8a5a00;
  --erro:         #c9252d;
  --match:        #0a5fc2;
  --nao-ident:    #8a5a00;
  --silencio:     #68727f;
  --fala:         #7c3aed;
  --destaque:     #0a5fc2;
  --anunciante:   #a4530b;
  --ruim:         #c9252d;

  --barra-forte:  #08306b;

  --tinta:  0, 0, 0;
}

/* --------------------------------------------------------------------------
   As ilhas escuras do tema claro.
   --------------------------------------------------------------------------

   Duas partes do painel continuam escuras no tema claro, e cada uma por um
   motivo que não é estético:

   · a ARTE DO LOGIN é uma fotografia noturna, e o texto sobre ela é branco;
   · o LOG AO VIVO é terminal — fundo preto nos dois temas, e as cores dos
     eventos (violeta, verde e vermelho claros) foram escolhidas contra preto.
     Sem a ilha, `.log div` viraria cinza-escuro sobre preto.

   A BARRA DO TOPO **saiu** desta lista. Ela ficou escura enquanto o logotipo
   era o único problema — wordmark branco sobre transparente não existe sobre
   fundo claro. Mas o cabeçalho passou a desenhar a marca do LICENCIADO, e arte
   de cliente é quase sempre feita para fundo claro: manter a barra preta
   resolveria o nosso logotipo e estragaria o dele. A saída certa é escurecer o
   NOSSO wordmark por filtro (ver `.marca-propria` adiante) e deixar a barra
   seguir o tema.

   O truque das ilhas é redeclarar os tokens NO ELEMENTO: tudo que está dentro
   herda a paleta escura sem uma única regra reescrita. */

:root[data-tema="claro"] .entrar-arte,
:root[data-tema="claro"] .log {
  --painel:       #161b22;
  --painel-alto:  #262d3a;
  --borda:        #2a3038;
  --texto:        #e6edf3;
  --texto-fraco:  #aeb8c4;
  --texto-tenue:  #8b949e;
  --destaque:     #58a6ff;
  --match:        #58a6ff;
  --tinta:  255, 255, 255;
  color-scheme: dark;

  /* `color` explícito, e não só os tokens: cor HERDA por VALOR já resolvido.
     Redeclarar `--texto` aqui só muda o que este bloco e os filhos DECLARAM —
     um texto que não declara cor nenhuma continua chegando com o cinza-escuro
     que o <body> claro resolveu. Foi exatamente o que apagou a frase da arte do
     login (`.entrar-arte .frase` não declara cor) sobre a foto escura. */
  color: var(--texto);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--fundo);
  color: var(--texto);
  font: 15px/1.5 system-ui, -apple-system, "Segoe UI", sans-serif;
}

a { color: var(--destaque); text-decoration: none; }
a:hover { text-decoration: underline; }

/* O título de uma lista que ABRE ALGO NESTA PÁGINA — o formulário do topo em
   /Marcas, por exemplo. Nas outras listas o título é <a> e navega; aqui não há
   para onde ir, e um <a href="#"> mentiria sobre isso além de sujar a URL. Este
   é o mesmo desenho do <a>, num <button> que é o elemento honesto. */
button.titulo-acao {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: var(--destaque);
  cursor: pointer;
}
button.titulo-acao:hover { text-decoration: underline; }

/* ---------- estrutura ---------- */

.topo {
  display: flex;
  align-items: center;
  gap: 24px;
  padding: 12px 24px;
  background: var(--painel);
  border-bottom: 1px solid var(--borda);
  position: sticky;
  top: 0;
  z-index: 10;
}

/* ---------- a marca no cabeçalho ---------- */

.topo .marca { display: flex; align-items: center; }

.topo img { height: 26px; width: auto; }

/* O NOSSO wordmark é branco sobre transparente. `brightness(0)` zera os canais de
   cor e NÃO toca no alfa: o desenho vira preto com o mesmo antialiasing, sem
   arquivo novo e sem a inversão de matiz que estragaria um logotipo colorido.
   Medi o PNG antes: ele é monocromático (branco com as bordas em cinza), que é a
   condição para isto funcionar. */
:root[data-tema="claro"] .topo img.marca-propria { filter: brightness(0) opacity(.86); }

/* Arte de terceiro NÃO passa por filtro nenhum — inverter a marca de um cliente é
   destruí-la. O que se controla aqui é só o espaço que ela ocupa: o cabeçalho não
   pode depender de o cliente ter mandado a arte na proporção certa. */
.topo img.marca-licenciado { max-width: 190px; object-fit: contain; }

.topo nav { display: flex; gap: 4px; flex-wrap: wrap; }

.topo nav a {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 10px;
  border-radius: var(--raio);
  color: var(--texto-fraco);
  font-size: 14px;
}

/* ---------- os ícones do menu ---------- */

/* Traço, espessura e junção ficam AQUI e não em cada <symbol>: é o que mantém as
   trinta e sete peças parecendo uma família só, e o que faz um ícone novo nascer
   certo sem copiar atributos. Ver Pages/Shared/_Icones.cshtml. */
svg.ic {
  width: 14px;
  height: 14px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.9;
  stroke-linecap: round;
  stroke-linejoin: round;
  /* Um pouco atrás do rótulo: o ícone é para achar o item de relance, não para
     competir com a palavra que diz o que ele é. */
  opacity: .72;
}

.topo nav a:hover svg.ic,
.topo nav a.ativo svg.ic,
.menu-grupo[open] > summary svg.ic,
.menu-grupo.ativo > summary svg.ic,
.menu-lista a:hover svg.ic,
.menu-lista a.ativo svg.ic { opacity: 1; }

.topo nav a:hover { background: var(--painel-alto); color: var(--texto); text-decoration: none; }
.topo nav a.ativo { background: var(--painel-alto); color: var(--texto); }

.topo .resumo {
  margin-left: auto;
  font-size: 13px;
  color: var(--texto-fraco);
  display: flex;
  gap: 16px;
  align-items: center;
  /* Sem isto o "12 no ar" quebra em duas linhas quando a barra aperta, e a barra
     inteira cresce de altura por causa de três palavras. */
  white-space: nowrap;
}

/* ---------- barra do copiloto ---------- */

/* UMA pílula, e não um campo mais um botão soltos.
 *
 * A primeira versão punha um input com borda própria ao lado de um botão com borda
 * própria, e o resultado eram três retângulos disputando a mesma linha do menu — o
 * cabeçalho ficava com cara de formulário. Aqui a MOLDURA é do <form>, o campo e o
 * botão entram sem borda nenhuma, e o conjunto lê como um controle só, na mesma
 * família do botão de tema e do menu de conta.
 *
 * Leva o `margin-left:auto` para ocupar a folga da barra; o resumo continua
 * encostado à direita. */
.copiloto-barra {
  margin-left: auto;
  display: flex;
  align-items: center;
  min-width: 0;
  padding: 0 2px 0 8px;
  border: 1px solid var(--borda);
  border-radius: 999px;
  background: transparent;
  transition: border-color .12s, background-color .12s;
}

.copiloto-barra:hover { background: var(--painel-alto); }

/* O foco acende o conjunto, e não só o campo: é o <form> que desenha a moldura. */
.copiloto-barra:focus-within {
  background: var(--painel-alto);
  border-color: var(--texto-fraco);
}

.copiloto-barra input {
  /* Curta em repouso para não disputar espaço com o menu, e larga em uso. */
  width: 15ch;
  min-width: 0;
  padding: 5px 0;
  font-size: 13px;
  color: var(--texto);
  background: transparent;
  border: 0;
  outline: none;
  transition: width .14s;
}

.copiloto-barra:focus-within input { width: 32ch; }

.copiloto-barra input::placeholder { color: var(--texto-fraco); }

/* Dentro da pílula, no lugar em que o olho já procura o botão de enviar. */
.copiloto-barra button {
  display: flex;
  align-items: center;
  padding: 5px 7px;
  color: var(--texto-fraco);
  background: transparent;
  border: 0;
  border-radius: 999px;
  cursor: pointer;
}

.copiloto-barra button:hover { color: var(--texto); }

/* Numa tela estreita a barra sai INTEIRA — perdê-la é melhor que empurrar o menu
   para uma segunda linha, e o copiloto continua na home. Esconder só o campo
   deixaria um botão que posta pergunta vazia, que é pior que botão nenhum. */
@media (max-width: 1400px) {
  .copiloto-barra { display: none; }
}

/* ---------- troca de tema ---------- */

/* Um botão só, com dois estados, na barra de todas as telas. Não é menu de três
   opções ("claro / escuro / do sistema") de propósito: quem opera um painel quer
   apertar uma vez e continuar trabalhando. O ícone mostra PARA ONDE o clique
   leva — sol quando está escuro —, que é o que a pessoa procura. */
button.tema-troca {
  padding: 5px 9px;
  font-size: 15px;
  line-height: 1;
  background: none;
  border-color: transparent;
  color: var(--texto-fraco);
}

button.tema-troca:hover {
  background: var(--painel-alto);
  border-color: var(--borda);
  color: var(--texto);
}

/* O par de ícones vive no HTML; o tema decide qual dos dois aparece. Assim o
   botão não depende de JavaScript para desenhar o estado certo na primeira
   pintura. */
button.tema-troca svg { display: block; width: 16px; height: 16px; }
button.tema-troca .icone-lua { display: none; }
:root[data-tema="claro"] button.tema-troca .icone-lua { display: block; }
:root[data-tema="claro"] button.tema-troca .icone-sol { display: none; }

main { padding: 24px; max-width: 1500px; margin: 0 auto; }

h1 { font-size: 22px; margin: 0 0 4px; font-weight: 600; }
h2 { font-size: 17px; margin: 28px 0 12px; font-weight: 600; }
.legenda { color: var(--texto-fraco); font-size: 14px; margin: 0 0 20px; }

/* ---------- cartões ---------- */

.grade {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
  gap: 16px;
}

.cartao {
  background: var(--painel);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  padding: 16px;
}

.cartao h3 { margin: 0; font-size: 16px; font-weight: 600; }

.cartao-topo {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 12px;
}

.metricas {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(90px, 1fr));
  gap: 12px;
  margin: 12px 0;
}

.metrica .rotulo { font-size: 11px; color: var(--texto-tenue); text-transform: uppercase; letter-spacing: .04em; }
.metrica .valor { font-size: 19px; font-weight: 600; font-variant-numeric: tabular-nums; }
.metrica .valor.pequeno { font-size: 15px; }

/* ---------- estado ---------- */

.estado {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  font-weight: 600;
  padding: 3px 10px;
  border-radius: 999px;
  white-space: nowrap;
}

.estado::before {
  content: "";
  width: 7px; height: 7px;
  border-radius: 50%;
  background: currentColor;
}

.estado.NoAr        { color: var(--no-ar);        background: rgba(63,185,80,.12); }
.estado.NoAr::before { animation: pulsa 2s ease-in-out infinite; }
.estado.Parada      { color: var(--parada);       background: rgba(110,118,129,.12); }
.estado.Iniciando,
.estado.Parando,
.estado.Reconectando { color: var(--reconectando); background: rgba(210,153,34,.12); }
.estado.Erro        { color: var(--erro);         background: rgba(248,81,73,.12); }

@keyframes pulsa { 0%,100% { opacity: 1 } 50% { opacity: .25 } }

/* ---------- botões e formulários ---------- */

.botoes { display: flex; gap: 8px; flex-wrap: wrap; }

button, .botao {
  font: inherit;
  font-size: 13px;
  padding: 6px 14px;
  border-radius: 6px;
  border: 1px solid var(--borda);
  background: var(--painel-alto);
  color: var(--texto);
  cursor: pointer;
}

button:hover, .botao:hover { border-color: var(--texto-tenue); text-decoration: none; }
button:disabled { opacity: .4; cursor: not-allowed; }

button.primario { background: var(--primario); border-color: var(--primario); color: var(--primario-texto); }
button.primario:hover { background: var(--primario-alto); }
button.perigo { color: var(--erro); }
button.perigo:hover { background: rgba(248,81,73,.1); border-color: var(--erro); }

label { display: block; font-size: 13px; color: var(--texto-fraco); margin-bottom: 4px; }

/* A lista de tipos precisa ser EXAUSTIVA, e `input:not([type])` precisa estar nela.
   Foi o que faltava e produziu o defeito mais visível do painel: um `<input
   name="cidade" />` sem atributo `type` — há dezenas deles nos cadastros — não é
   alcançado por `input[type=text]`, então caía no desenho de fábrica do
   navegador: caixa BRANCA, no meio de uma tela preta. O mesmo valia para os 15
   `type="search"` dos filtros e os 8 `type="time"` das grades.

   Por que `:not([type])` e não `input:not([type=checkbox]):not(...)`: cada
   `:not()` de atributo SOMA especificidade, e um encadeado empataria com — na
   verdade venceria — as dezenas de regras adiante que ajustam campo por campo
   (`input.estreito`, `.grade-pi td input`, `.dia-campo input`). Do jeito que
   está, todo seletor desta lista tem a mesma especificidade 0,1,1 de antes e
   nada mais na folha muda de lugar. Tipo novo em tela nova: acrescente aqui. */
input:not([type]), input[type=text], input[type=search], input[type=url], input[type=tel],
input[type=number], input[type=date], input[type=time], input[type=month], input[type=week],
input[type=datetime-local], input[type=email], input[type=password], select, textarea {
  width: 100%;
  font: inherit;
  font-size: 14px;
  padding: 7px 10px;
  background: var(--campo);
  border: 1px solid var(--borda);
  border-radius: 6px;
  color: var(--texto);
}

input:focus, select:focus, textarea:focus { outline: 2px solid var(--destaque); outline-offset: -1px; }

::placeholder { color: var(--texto-tenue); opacity: 1; }

/* Caixa e radinho no azul do sistema, e não no azul do sistema operacional. */
input[type=checkbox], input[type=radio], input[type=range] { accent-color: var(--primario); }

/* O autopreenchimento do Chrome pinta o campo de amarelo-claro com texto escuro —
   sobre o tema escuro isso vira uma faixa que grita, e no login é justamente o
   campo que o navegador preenche. `color-scheme` resolve na maioria das versões;
   a sombra interna resolve no resto (não há como sobrescrever `background` do
   autofill, só cobri-lo). */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--texto);
  box-shadow: 0 0 0 100px var(--campo) inset;
  caret-color: var(--texto);
}

.campo { margin-bottom: 14px; }
.campo .ajuda { font-size: 12px; color: var(--texto-tenue); margin-top: 4px; }

.linha-campos {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 16px;
}

.check { display: flex; align-items: center; gap: 8px; }
.check input { width: auto; }
.check label { margin: 0; color: var(--texto); }

fieldset {
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  padding: 16px;
  margin: 0 0 18px;
}

legend { padding: 0 8px; font-size: 13px; color: var(--texto-fraco); text-transform: uppercase; letter-spacing: .05em; }

/* ---------- tabelas ---------- */

.tabela-rolavel { overflow-x: auto; }

table { width: 100%; border-collapse: collapse; font-size: 14px; }

th {
  text-align: left;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--texto-tenue);
  font-weight: 600;
  padding: 8px 10px;
  border-bottom: 1px solid var(--borda);
  white-space: nowrap;
}

td { padding: 8px 10px; border-bottom: 1px solid var(--borda); }
/* Realce, e não `var(--painel)`: no tema claro o cartão JÁ é branco, e uma linha
   branca sobre cartão branco não realça nada. */
tbody tr:hover { background: rgba(var(--tinta), .04); }

.num { text-align: right; font-variant-numeric: tabular-nums; }
.mono { font-family: var(--mono); font-size: 13px; }

/* ---------- log ao vivo ---------- */

.log {
  background: var(--terminal);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  padding: 12px 14px;
  font-family: var(--mono);
  font-size: 12.5px;
  line-height: 1.55;
  height: 460px;
  overflow-y: auto;
  white-space: pre-wrap;
  word-break: break-word;
}

.log div { color: var(--texto-fraco); }
.log div.Event { color: var(--texto); }
.log div.Status { color: var(--destaque); }
.log div.Icy { color: #a371f7; }
.log div.Outage, .log div.Reconnect { color: var(--erro); }
.log div.Back, .log div.Retention { color: var(--no-ar); }
.log div.EventNote { color: var(--texto-tenue); }

/* ---------- barras e cobertura ---------- */

.barra { display: flex; height: 10px; border-radius: 5px; overflow: hidden; background: var(--painel-alto); }
.barra span { display: block; }
.barra .m { background: var(--match); }
.barra .u { background: var(--nao-ident); }
.barra .s { background: var(--silencio); }

.legenda-barra { display: flex; gap: 16px; font-size: 12px; color: var(--texto-fraco); margin-top: 8px; flex-wrap: wrap; }
.legenda-barra i { display: inline-block; width: 9px; height: 9px; border-radius: 2px; margin-right: 5px; }

/* ---------- avisos ---------- */

.aviso {
  padding: 10px 14px;
  border-radius: var(--raio);
  border: 1px solid var(--borda);
  background: var(--painel);
  margin-bottom: 16px;
  font-size: 14px;
}

.aviso.erro { border-color: var(--erro); background: rgba(248,81,73,.08); }
.aviso.ok { border-color: var(--no-ar); background: rgba(63,185,80,.08); }
.aviso.atencao { border-color: var(--reconectando); background: rgba(210,153,34,.08); }

.vazio { color: var(--texto-tenue); padding: 32px; text-align: center; }

/* Data que já passou, dentro de uma célula: vencimento vencido em contas a receber
   e PI a faturar com o vencimento no passado. As duas telas já pediam a classe. */
.alerta { color: var(--erro); font-weight: 600; }

/* ---------- grade de gravações (dias × horas) ---------- */

.calendario { display: grid; gap: 2px; font-size: 11px; }
.calendario .cabeca { color: var(--texto-tenue); text-align: center; padding: 2px 0; }
.calendario .dia { color: var(--texto-fraco); padding-right: 8px; white-space: nowrap; text-align: right; }

.hora {
  height: 20px;
  border-radius: 3px;
  background: var(--painel-alto);
  display: block;
}

.hora.tem { background: var(--primario); }
.hora.tem.hd { background: var(--no-ar); }
.hora.falta { background: rgba(248,81,73,.25); }

/* A hora com gravacao e um <button>: ela ABRE o detalhe em modal, e botao e o que o teclado
   alcanca e o que o leitor de tela anuncia como acionavel. Precisa desfazer o estilo de botao do
   painel — padding e borda — senao cada quadrado da grade vira um botao de 30 px e a grade de 24
   colunas nao cabe mais na tela. */
button.hora {
  padding: 0;
  border: 0;
  width: 100%;
  cursor: pointer;
  transition: outline-color .1s;
  outline: 2px solid transparent;
  outline-offset: 1px;
}

button.hora:hover, button.hora:focus-visible { outline-color: var(--texto); }

/* ---------- abas ---------- */
/* Duas leituras da mesma tabela precisam parecer duas leituras, e não dois filtros: um seletor
   sugere que a diferença é de recorte, quando é de pergunta. */

.abas {
  display: flex;
  gap: 4px;
  margin: 0 0 14px;
  border-bottom: 1px solid var(--borda);
}

.abas .aba {
  padding: 7px 14px;
  font-size: 14px;
  color: var(--texto-fraco);
  border: 1px solid transparent;
  border-bottom: none;
  border-radius: var(--raio) var(--raio) 0 0;
  margin-bottom: -1px;
}

.abas .aba:hover { color: var(--texto); text-decoration: none; }

.abas .aba.ativa {
  color: var(--texto);
  background: var(--painel);
  border-color: var(--borda);
  font-weight: 600;
}

/* ---------- filtros ---------- */

.filtros {
  display: flex;
  gap: 12px;
  align-items: flex-end;
  flex-wrap: wrap;
  background: var(--painel);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  padding: 14px;
  margin-bottom: 18px;
}

.filtros .campo { margin: 0; min-width: 140px; }

.selo {
  font-size: 11px;
  padding: 2px 7px;
  border-radius: 4px;
  background: var(--painel-alto);
  color: var(--texto-fraco);
  white-space: nowrap;
}

.selo.Match { color: var(--match); background: rgba(88,166,255,.12); }
.selo.Unidentified { color: var(--nao-ident); background: rgba(210,153,34,.12); }
.selo.Silence { color: var(--silencio); background: rgba(110,118,129,.12); }
.selo.sim { color: var(--no-ar); background: rgba(63,185,80,.12); }
.selo.nao { color: var(--erro); background: rgba(248,81,73,.12); }
/* Anunciante e estilo são atribuições humanas, e as duas cores dizem isso sem competir com os
   estados de ar (verde/âmbar/vermelho, que significam saúde e não classificação). */
.selo.anunciante { color: var(--anunciante); background: rgba(240,136,62,.12); }
.selo.estilo { color: var(--fala); background: rgba(188,140,255,.12); }

.discreto { color: var(--texto-tenue); font-size: 13px; }

audio { width: 100%; max-width: 420px; height: 32px; }

/* ---------- edição de faixa no catálogo ---------- */
/* A linha se abre debaixo da faixa e o formulário herda a largura da tabela: sem grade, cada campo
   virava um input de mil pixels, um embaixo do outro, e a edição de cinco campos ficava mais alta
   que a tela. */

tr.edicao > td { background: var(--painel); padding: 0; }

.editar-faixa { padding: 16px 14px; border-left: 3px solid var(--destaque); }

.editar-faixa .cabeca {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 14px;
}

.editar-faixa .campos {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 14px 16px;
  align-items: start;
}

/* Artista e título são os que recebem texto longo; os outros três cabem em uma coluna. */
.editar-faixa .campo.largo { grid-column: span 2; }
@media (max-width: 760px) { .editar-faixa .campo.largo { grid-column: span 1; } }

.editar-faixa .campo { margin: 0; display: block; }
.editar-faixa .campo .ajuda { display: block; font-size: 12px; color: var(--texto-tenue); margin-top: 4px; }
.editar-faixa .campo > input, .editar-faixa .campo > select { margin-top: 4px; }

.editar-faixa .rodape {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  margin-top: 16px;
}

/* ---------- tocador fixo ---------- */

.tocador {
  position: sticky;
  bottom: 12px;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 12px;
  padding: 10px 14px;
  background: var(--painel-alto);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  box-shadow: 0 -4px 16px rgba(0,0,0,.45);
}

.tocador .rotulo { font-size: 11px; color: var(--texto-tenue); text-transform: uppercase; letter-spacing: .04em; }
.tocador .nome { font-size: 14px; font-weight: 600; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tocador audio { width: 340px; flex: none; }

@media (max-width: 720px) {
  .tocador { flex-wrap: wrap; }
  .tocador audio { width: 100%; }
}

button.tocando { color: var(--match); border-color: var(--match); }

/* ---------- editor de onda ---------- */
/* O canvas ocupa a largura toda e tem altura fixa em CSS; o buffer é redimensionado por
   devicePixelRatio no JS. Sem a altura aqui, o clientHeight sai zero no primeiro desenho e a onda
   aparece só depois do primeiro resize. */

.editor { padding: 14px; }

.editor-mapa, .editor-onda {
  border: 1px solid var(--borda);
  border-radius: 6px;
  overflow: hidden;
  background: var(--fundo);
}

.editor-mapa { margin-bottom: 8px; }
.editor-mapa canvas { display: block; width: 100%; height: 34px; cursor: pointer; }

.editor-onda canvas { display: block; width: 100%; height: 240px; touch-action: none; }

.transporte {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin: 12px 0 10px;
}

.transporte button { min-width: 42px; }
.transporte .tempo { font-size: 14px; font-variant-numeric: tabular-nums; padding: 0 4px; }
.transporte .separador { width: 1px; height: 22px; background: var(--borda); margin: 0 4px; }

label.inline { display: inline-flex; align-items: center; gap: 6px; margin: 0; font-size: 13px; }
label.inline input[type=checkbox] { width: auto; }

input.estreito, select.estreito { width: auto; min-width: 78px; }
input.deslizante { width: 90px; padding: 0; background: none; border: none; }

.marcacao {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px;
  background: var(--painel-alto);
  border: 1px solid var(--borda);
  border-radius: 6px;
}

.campos-marca, .opcoes-marca {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  font-size: 13px;
}

.opcoes-marca #btn-cortar { margin-left: auto; }

.atalhos { margin: 12px 0 0; font-size: 12.5px; }

kbd {
  font-family: var(--mono);
  font-size: 11px;
  padding: 1px 5px;
  border: 1px solid var(--borda);
  border-bottom-width: 2px;
  border-radius: 4px;
  background: var(--painel-alto);
  color: var(--texto);
}

.painel-indexar {
  margin-top: 18px;
  padding-top: 4px;
  border-top: 1px solid var(--borda);
}

.painel-indexar h2 { margin-top: 16px; }
.painel-indexar audio { max-width: 100%; }

/* ---------- entrar ---------- */
/* As telas de conta não usam o _Layout: elas existem justamente para quem ainda não passou por ele,
   e o cabeçalho com a navegação do cockpit não faz sentido ali. Por isso trazem o próprio <head> —
   e por isso apontavam para um css/site.css que nunca existiu. */

body.login {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  padding: 24px;
}

.login-card {
  width: 100%;
  max-width: 340px;
  padding: 28px;
  background: var(--painel);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
}

.login-card h1 { margin: 0 0 20px; font-size: 20px; }
.login-card label { margin-top: 14px; }

/* ---------- entrar: a tela partida ----------
   O login é a primeira coisa que um cliente vê numa demonstração, e um cartão de
   340 px no meio do escuro não diz que produto é este. Metade da tela é a marca,
   metade é o formulário. Abaixo de 860 px a arte sai: numa tela estreita ela
   empurraria o formulário para baixo da dobra, que é o oposto do que se quer. */

body.entrar {
  margin: 0;
  min-height: 100vh;
}

.entrar-palco {
  display: grid;
  grid-template-columns: minmax(0, 1.06fr) minmax(0, 1fr);
  min-height: 100vh;
}

.entrar-arte {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: 46px 48px;
  background: #0a1526 url("../img/login.jpg") center center / cover no-repeat;
  overflow: hidden;
}
/* Véu só onde há texto: topo e base. O miolo fica limpo, senão o cone de sinal —
   que é a única coisa luminosa da arte — some atrás da cortina. */
.entrar-arte::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg,
    rgba(6,12,22,.82) 0%,
    rgba(6,12,22,.22) 26%,
    rgba(6,12,22,.20) 54%,
    rgba(6,12,22,.92) 100%);
}
.entrar-arte > * { position: relative; }

/* `align-self` é obrigatório aqui: num flex em coluna o padrão `stretch` puxa a
   imagem para a largura inteira do painel, e com a altura travada em 30px o
   wordmark sai achatado a um terço da proporção. */
.entrar-arte img.marca { height: 32px; width: auto; align-self: flex-start; }

.entrar-arte .frase {
  font-size: 27px;
  line-height: 1.25;
  letter-spacing: -0.02em;
  font-weight: 600;
  max-width: 15ch;
  margin: 0 0 12px;
}
.entrar-arte .frase em { font-style: normal; color: var(--match); }
.entrar-arte .rodape {
  font-family: var(--mono);
  font-size: 12.5px;
  color: var(--texto-tenue);
  letter-spacing: .04em;
  margin: 0;
}

.entrar-forma {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 46px 32px;
  background: var(--fundo);
}

.entrar-caixa { width: 100%; max-width: 344px; }

/* Só aparece quando a arte some: sem isto, a tela estreita fica sem marca alguma. */
.entrar-caixa img.marca { height: 27px; width: auto; margin-bottom: 30px; display: none; }

.entrar-caixa h1 {
  margin: 0 0 8px;
  font-size: 25px;
  letter-spacing: -0.02em;
}
.entrar-caixa .sub {
  margin: 0 0 26px;
  font-size: 14px;
  color: var(--texto-fraco);
}

.entrar-caixa .campo { margin-bottom: 16px; }
.entrar-caixa label { margin-bottom: 6px; }

/* OS QUATRO TIPOS, e não só dois.
 *
 * A regra listava `email` e `password` porque era só o que o login tinha. O cadastro trouxe `text`
 * e `tel` — e sem eles o navegador aplica a largura PADRÃO dele, que é ~20 caracteres: os campos de
 * e-mail e WhatsApp apareceram com um terço da largura dos vizinhos, no primeiro contato de um
 * cliente. Um seletor que enumera tipos vai deixar um de fora toda vez que uma tela nova aparecer;
 * a largura vem do `width: 100%` logo abaixo, que é o que garante que todos fiquem iguais. */
.entrar-caixa input[type=text],
.entrar-caixa input[type=email],
.entrar-caixa input[type=tel],
.entrar-caixa input[type=password] {
  width: 100%;
  padding: 10px 12px;
  background: var(--painel);
  box-sizing: border-box;
}

/* ---- o cadastro: a irmã da tela de login ---- */

/* A promessa, na arte. Três linhas, e cada uma responde uma dúvida de quem está decidindo se
   preenche: o que eu faço, o que eu recebo, quanto custa. */
.cadastrar .entrar-arte .promessa {
  list-style: none;
  margin: 0 0 22px;
  padding: 0;
  max-width: 34ch;
}
.cadastrar .entrar-arte .promessa li {
  position: relative;
  padding-left: 20px;
  margin-bottom: 7px;
  font-size: 14px;
  line-height: 1.5;
  color: var(--texto);
}
.cadastrar .entrar-arte .promessa li::before {
  content: "";
  position: absolute;
  left: 0;
  top: .55em;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--match);
}

/* "No e-mail você define sua senha" — o que acontece depois, na tela do Enviado. */
.entrar-caixa .passos-do-email {
  margin: 0 0 4px;
  padding: 13px 15px;
  border-radius: 6px;
  background: var(--painel);
  border: 1px solid var(--borda);
  font-size: 13px;
  line-height: 1.6;
  color: var(--texto-fraco);
}

/* Um LINK com cara de botão primário. `.entrar-caixa button` já é de largura cheia, mas um `<a>`
   não herda nada dela — e navegar não é submeter, então trocar o link por um botão seria mentir
   sobre o que o clique faz. Usado no desfecho raro do convite, quando o que resta é ir ao login. */
.entrar-caixa a.como-botao {
  display: block;
  width: 100%;
  padding: 11px;
  border: 1px solid var(--primario);
  border-radius: 6px;
  background: var(--primario);
  color: var(--primario-texto);
  font-size: 14.5px;
  font-weight: 600;
  text-align: center;
  text-decoration: none;
  box-sizing: border-box;
}
.entrar-caixa a.como-botao:hover { background: var(--primario-alto); }

/* A regra do campo, colada nele: "pelo menos 10 caracteres". Sobe 4 px para encostar no campo de
   cima — solta no meio, ela parece legenda do botão de baixo, que é o que ela não é. */
.entrar-caixa .dica-do-campo {
  margin: -4px 0 18px;
  font-size: 12.5px;
  color: var(--texto-tenue);
  line-height: 1.5;
}

.entrar-caixa .opcional {
  font-weight: 400;
  font-size: 12px;
  color: var(--texto-tenue);
}

/* O campo-armadilha do cadastro. Fora da tela, e não `display:none`: um campo escondido pelo
   display é ignorado por parte dos preenchedores automáticos, que é justamente quem se quer pegar. */
.fora-de-vista {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.entrar-caixa label.inline {
  display: flex;
  align-items: center;
  gap: 9px;
  margin: 4px 0 22px;
  color: var(--texto);
  font-size: 13.5px;
}
.entrar-caixa label.inline input { width: auto; }

.entrar-caixa button { width: 100%; padding: 11px; font-size: 14.5px; font-weight: 600; }

.entrar-caixa .erro {
  padding: 11px 13px;
  border-radius: 6px;
  border: 1px solid var(--erro);
  background: rgba(248,81,73,.08);
  font-size: 13px;
  margin: 0 0 18px;
}

/* "Sessão encerrada" — a mesma caixa do erro, na cor de quem deu certo. Ver
   Pages/Conta/Entrar: aparece quando a pessoa chegou por ter clicado em Sair. */
.entrar-caixa .saiu {
  padding: 11px 13px;
  border-radius: 6px;
  border: 1px solid var(--no-ar);
  background: rgba(63,185,80,.08);
  font-size: 13px;
  margin: 0 0 18px;
}

.entrar-caixa .ajuda-pe {
  margin: 26px 0 0;
  padding-top: 20px;
  border-top: 1px solid var(--borda);
  font-size: 12.5px;
  color: var(--texto-tenue);
  line-height: 1.6;
}

/* "Ainda não tem conta?" — o convite para testar, no pé da tela de login.

   DISCRETO de propósito, e a razão é quem usa esta tela: a esmagadora maioria de
   quem chega aqui já tem conta e está indo trabalhar. Um botão do tamanho do
   "Entrar" competiria com ele todo dia, para atender o visitante ocasional.
   Quem não tem conta procura justamente esta frase, e a acha; quem tem, não
   tropeça nela. */
.entrar-caixa .testar {
  margin: 18px 0 0;
  padding: 14px;
  border-radius: 6px;
  border: 1px dashed var(--borda);
  font-size: 12.5px;
  color: var(--texto-tenue);
  line-height: 1.6;
}
.entrar-caixa .testar strong { color: var(--texto); font-weight: 600; }
.entrar-caixa .testar a { font-weight: 600; }

@media (max-width: 860px) {
  .entrar-palco { grid-template-columns: minmax(0, 1fr); }
  .entrar-arte { display: none; }
  .entrar-caixa img.marca { display: block; }
  .entrar-forma { padding: 40px 24px; }
}
.login-card label.inline {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 16px 0;
  color: var(--texto);
}
.login-card label.inline input { width: auto; }
.login-card button { width: 100%; padding: 9px; font-size: 14px; }

.login-card .erro,
.login-card .aviso {
  padding: 10px 12px;
  border-radius: 6px;
  border: 1px solid var(--erro);
  background: rgba(248,81,73,.08);
  font-size: 13px;
  margin: 0 0 16px;
}

/* ---------- agentes ---------- */

.linha-nova {
  display: flex;
  gap: 12px;
  align-items: flex-end;
  flex-wrap: wrap;
  margin-bottom: 18px;
}

/* O código de enrolamento aparece uma vez só, então ele tem que ser impossível de não ver — e
   grande o bastante para alguém digitá-lo do outro lado de uma chamada de vídeo. */
.codigo-enrolamento .codigo {
  font-size: 26px;
  letter-spacing: .12em;
  font-weight: 600;
  margin: 6px 0 10px;
  user-select: all;
}

.metrica .discreto { margin-top: 2px; }

td.erro { color: var(--erro); }

/* ---- cabeçalho que ordena, padrão de toda tela de lista (ver Services/Ordenacao.cs) ---- */
th a.ordena {
    color: inherit;
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    white-space: nowrap;
}
th a.ordena:hover { text-decoration: underline; }

/* A seta ocupa lugar mesmo vazia: sem isso o cabeçalho pula de largura ao trocar a coluna
   ordenadora, e a tabela inteira treme a cada clique. */
th a.ordena .seta {
    display: inline-block;
    min-width: 0.9em;
    font-size: 0.8em;
    opacity: 0.75;
}
th.ordenando a.ordena { font-weight: 700; }

/* ---- a barra de paginação, padrão de toda lista longa (ver Services/Paginacao.cs) ---- */

.paginacao {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin: 14px 0 4px;
}

/* A posição fica NO MEIO, entre os dois destinos: é o texto que responde "onde eu estou", e no canto
   ela vira legenda que ninguém lê. */
.paginacao .posicao {
    font-size: 13px;
    color: var(--texto-fraco);
    font-variant-numeric: tabular-nums;
}

/* Extremo sem para onde ir. Continua ocupando o lugar — a barra pular de largura ao virar página é
   pior que um botão apagado. */
.paginacao .inerte {
    opacity: .4;
    cursor: default;
    user-select: none;
}

/* O filtro aplica sozinho; sem botão, a única pista de que ele está ativo é o campo preenchido. */
.filtros input[type="search"] { width: 100%; }

/* ---------- menu em grupos (Bloco E) ----------
   O menu deixou de ser uma fileira de links quando o painel virou multi-licenciado: com
   licenciados, usuários, perfis e auditoria — e anunciante, agência, campanha e checking a
   caminho — seriam dezoito itens numa linha só. Ver Services/Menu.cs.

   A mecânica é <details>/<summary>, não JavaScript: abre, fecha, navega por teclado e é lido por
   leitor de tela sem script nenhum. O js/menu.js só acrescenta o que um menu de barra espera
   (fechar os outros, fechar ao clicar fora, fechar com Esc). */

.topo nav { align-items: center; }

.menu-grupo { position: relative; }

.menu-grupo > summary {
  display: flex;
  align-items: center;
  gap: 6px;
  /* 10px e não 12: com ícone, seis grupos a 12px de cada lado jogavam o último
     item para a segunda linha num monitor de 1366 — medido. */
  padding: 6px 10px;
  border-radius: var(--raio);
  color: var(--texto-fraco);
  font-size: 14px;
  cursor: pointer;
  user-select: none;
  list-style: none;          /* Firefox */
  white-space: nowrap;
}

.menu-grupo > summary::-webkit-details-marker { display: none; }

.menu-grupo > summary::after {
  content: "▾";
  font-size: 10px;
  margin-left: 2px;
  opacity: .6;
}

.menu-grupo > summary:hover { background: var(--painel-alto); color: var(--texto); }
.menu-grupo[open] > summary { background: var(--painel-alto); color: var(--texto); }

/* O grupo herda o destaque do item aberto: sem isso, quem está em /Perfis não tem como saber que
   está dentro de Administração — o menu fecha e não sobra pista nenhuma na tela. */
.menu-grupo.ativo > summary { color: var(--texto); box-shadow: inset 0 -2px 0 var(--destaque); }

.menu-lista {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 30;
  min-width: 190px;
  padding: 6px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  background: var(--painel);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  box-shadow: 0 12px 28px rgba(0, 0, 0, .45);
}

.menu-lista a,
.menu-lista .futuro,
.menu-lista button {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  text-align: left;
  padding: 7px 10px;
  border: 0;
  border-radius: 6px;
  background: none;
  color: var(--texto-fraco);
  font: inherit;
  font-size: 14px;
  cursor: pointer;
  white-space: nowrap;
}

.menu-lista a:hover,
.menu-lista button:hover { background: var(--painel-alto); color: var(--texto); text-decoration: none; }
.menu-lista a.ativo { background: var(--painel-alto); color: var(--texto); }

/* Tela que ainda não existe. Cinza e sem cursor de link: o lugar dela no menu já está decidido, e
   fingir que ela abre seria pior que não mostrá-la. */
.menu-lista .futuro { color: var(--texto-tenue); cursor: default; }
.menu-lista .futuro em { font-style: normal; font-size: 11px; opacity: .8; margin-left: 6px; }

.menu-lista form { margin: 0; }

/* O menu da conta abre da direita para a esquerda — é o último elemento da barra, e alinhado à
   esquerda ele sairia da tela. */
.menu-grupo.conta .menu-lista { left: auto; right: 0; }
.menu-grupo.conta > summary { max-width: 220px; overflow: hidden; text-overflow: ellipsis; }

/* ---------- matriz de perfis ---------- */

.matriz-perfis th.num, .matriz-perfis td.num { text-align: center; }
.matriz-perfis td.num input { cursor: pointer; }
.matriz-perfis td.num input:disabled { cursor: not-allowed; opacity: .45; }

.matriz-perfis tr.grupo th {
  background: var(--painel-alto);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--texto-fraco);
}

/* Botão de ação destrutiva. Vermelho na borda e no texto, não no fundo: um botão vermelho sólido
   numa tela escura puxa o olho para a coisa que menos deveria ser clicada por engano. */
button.perigo, .botao.perigo {
  border-color: var(--erro);
  color: var(--erro);
}
button.perigo:hover, .botao.perigo:hover { background: rgba(248, 81, 73, .1); }

/* ===================================================================== */
/*  A grade da PI                                                        */
/*                                                                       */
/*  Trinta e uma colunas de dia mais cinco fixas numa tela. O que a faz  */
/*  legível não é o tamanho da fonte: é a coluna de dia ter largura FIXA  */
/*  e mínima, para o navegador não distribuir o espaço sobrando entre 31  */
/*  células e deixar a coluna "Posição" com 40 px. E o fim de semana      */
/*  sombreado, porque contar dia no calendário é o erro mais caro de      */
/*  quem monta grade à mão.                                              */
/* ===================================================================== */

.grade-pi { border-collapse: collapse; font-size: 12px; }

.grade-pi th,
.grade-pi td {
    padding: 2px 3px;
    border: 1px solid var(--borda);
    white-space: nowrap;
}

.grade-pi thead th {
    position: sticky;
    top: 0;
    z-index: 2;
    background: var(--painel);
    font-size: 11px;
    text-align: center;
    vertical-align: bottom;
}

/* A coluna de dia: estreita, centrada, e larga o suficiente para dois dígitos. */
.grade-pi th.dia,
.grade-pi td.dia {
    width: 26px;
    min-width: 26px;
    max-width: 26px;
    text-align: center;
    padding: 1px;
}

.grade-pi th.dia { font-size: 10px; line-height: 1.15; }

/* A inicial do dia da semana, acima do numero. É o que permite ler a grade sem
   abrir o calendário — e é o que o relatório do sistema antigo desenha. */
.grade-pi th.dia .dow { color: var(--texto-fraco); font-weight: 400; }

/* Sábado e domingo sombreados nas duas faixas, cabeçalho e corpo. */
.grade-pi th.dia.fds,
.grade-pi td.dia.fds { background: rgba(var(--tinta), .04); }

.grade-pi td.dia input {
    width: 100%;
    min-width: 0;
    padding: 1px 0;
    border: 0;
    background: transparent;
    color: inherit;
    text-align: center;
    font-family: inherit;
    font-size: 12px;
}

/* A célula focada precisa ser óbvia: com 31 colunas iguais, perder de vista em
   qual dia se está digitando é o erro que produz PI com inserção no dia errado. */
.grade-pi td.dia input:focus {
    outline: 2px solid var(--destaque);
    outline-offset: -2px;
    background: var(--campo);
}

.grade-pi td input,
.grade-pi td select {
    padding: 2px 4px;
    font-size: 12px;
    width: 100%;
    min-width: 0;
}

.grade-pi td input.num { text-align: right; }

/* Coluna de custo e de total: número alinhado à direita e monoespaçado, para a
   coluna inteira poder ser conferida de cima a baixo. */
.grade-pi td.num,
.grade-pi th.num { text-align: right; }

/* ===================================================================== */
/*  A grade do PLANO — o editor em lote, em duas colunas                 */
/*                                                                       */
/*  A campanha à esquerda, as emissoras à direita e sempre à vista.      */
/*                                                                       */
/*  As 31 colunas de dia SAÍRAM do cabeçalho: cada linha traz uma TIRA   */
/*  de 31 marcas para ler, e os campos por dia abrem numa faixa embaixo  */
/*  da linha selecionada, uma de cada vez. A largura da tabela deixou de */
/*  ser função do mês, e a emissora deixou de estar atrás de um clique.  */
/* ===================================================================== */

.editor-grade {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 380px;
    gap: 16px;
    align-items: start;
}

/* Abaixo de ~1180 px as duas colunas viram uma. O painel empilhado embaixo é
   pior do que lado a lado, e é muito melhor do que 380 px roubados da grade. */
@media (max-width: 1180px) {
    .editor-grade { grid-template-columns: minmax(0, 1fr); }
    .painel-emissoras { position: static; max-height: none; }
}

.painel-linhas { min-width: 0; }

/* ---------- a linha da campanha ---------- */

.linhas-da-campanha { width: 100%; }

/* A linha inteira é o alvo do clique que a seleciona; os campos dentro dela, não —
   clicar num campo para digitar não pode parecer clicar na linha. */
.linhas-da-campanha tbody tr.linha-grade > td { cursor: pointer; }
.linhas-da-campanha tbody tr.linha-grade input,
.linhas-da-campanha tbody tr.linha-grade select { cursor: auto; }

/* A linha selecionada é a que a faixa de dias e o painel de emissoras estão
   servindo. Sem esta marca, as duas metades da tela parecem soltas. */
.linhas-da-campanha tr.linha-grade.sel > td { background: rgba(88, 166, 255, .08); }
.linhas-da-campanha tr.linha-grade.sel > td:first-child { box-shadow: inset 2px 0 0 var(--destaque); }

/* Dia sem emissora é a única combinação que o POST recusa. Avisar aqui poupa a ida
   ao servidor para receber a recusa. */
.linhas-da-campanha tr.linha-grade.incompleta .conta-emissoras {
    color: var(--erro);
    border-color: var(--erro);
}

/* ---------- a tira dos dias ---------- */

.celula-tira { padding: 2px 4px !important; }

button.tira-mini {
    display: block;
    width: 100%;
    padding: 3px 2px;
    border: 1px solid transparent;
    border-radius: 4px;
    background: transparent;
    cursor: pointer;
}

button.tira-mini:hover { border-color: var(--borda); background: rgba(var(--tinta), .04); }

.tira { display: flex; align-items: flex-end; gap: 1px; height: 14px; }

/* Cada marca é um dia. Três pixels desenham o mês inteiro em ~130 px, contra os
   ~810 px que as 31 colunas de campo ocupavam. */
.tira i {
    display: block;
    flex: 1 1 0;
    min-width: 2px;
    height: 8px;
    border-radius: 1px;
    background: rgba(var(--tinta), .10);
}

/* O fim de semana continua sombreado, como no cabeçalho da grade da PI: contar dia
   no calendário é o erro mais caro de quem monta grade à mão. */
.tira i.fds { background: rgba(var(--tinta), .05); }

/* Aceso é "vai ao ar", alto é "mais de uma inserção no dia". Duas alturas em vez de
   um número: a tira é leitura de PADRÃO, e o total exato está na coluna Ins. */
.tira i.on { height: 11px; background: var(--destaque); }
.tira i.on.mais { height: 14px; background: var(--barra-forte); }

/* ---------- a faixa de dias da linha selecionada ---------- */

/* Existe para TODAS as linhas — é o que carrega os campos l{i}_d{dia} no POST — e
   só é exibida na selecionada. display:none não tira um campo do envio; só
   disabled tiraria. É o que permite editar a linha 3 sem perder o que está
   digitado na 1. */
tr.dias-linha { display: none; }
tr.dias-linha.sel { display: table-row; }

tr.dias-linha > td {
    padding: 10px 12px !important;
    background: rgba(88, 166, 255, .05);
    white-space: normal !important;
}

.atalhos-dias {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    margin-bottom: 8px;
}

.atalhos-dias .rotulo-faixa { font-size: 12px; color: var(--texto-fraco); margin-right: 4px; }

.atalhos-dias .separador {
    width: 1px;
    align-self: stretch;
    background: var(--borda);
    margin: 0 4px;
}

/* O dia da semana é um INTERRUPTOR: aceso quando todas as ocorrências dele no mês
   estão preenchidas. Um botão que só preenche obriga a pessoa a adivinhar o estado,
   e é por isso que o desenho anterior precisava de sete caixas de seleção mais um
   botão "Aplicar" para dizer a mesma coisa. */
.atalhos-dias .botao.dow.ativo {
    color: var(--fundo);
    background: var(--destaque);
    border-color: var(--destaque);
}

.atalhos-dias .qtd-por-dia {
    display: flex;
    align-items: center;
    gap: 5px;
    font-size: 12px;
    color: var(--texto-fraco);
}

.atalhos-dias .qtd-por-dia input { width: 44px; padding: 2px 4px; font-size: 12px; }

/* ------------------------------------------------------- bi-semanas (OOH) --

   O lugar das 31 colunas de dia numa linha vendida por PERÍODO. São duas ou três
   caixas por mês, e elas podem ser grandes: o problema da grade de rádio — não
   caber de lado — não existe aqui, e a caixa grande é o que permite mostrar as
   datas junto do número, que é como a exibidora confere a ordem de colagem. */
/*
    O ATRIBUTO `hidden` NÃO FUNCIONA SOZINHO NESTES TRÊS.

    A regra do navegador é `[hidden] { display: none }`, de especificidade zero — qualquer classe que
    declare `display` a vence. Como `.faixa-bissemanas`, `.atalhos-dias` e `.tira-editor` são `flex`,
    o `hidden` que o Razor e o JS ligam não escondia NADA, e o estrago era nos dois sentidos:

      * num plano de RÁDIO a faixa "Bi-semanas da linha 1" aparecia em toda linha, falando de lona,
        de exibidora e de troca de LED numa campanha de spot;
      * numa linha de BI-SEMANA o editor de dias aparecia junto, oferecendo os 31 dias do mês para
        uma face que se vende por período.

    O JS não salvava: `aplicarUnidade` sai cedo quando a linha não tem seletor de unidade — e num
    plano de rádio ela não tem —, então nem o `hidden` dele chegava a ser aplicado.

    O mesmo tropeço já tinha sido corrigido em `.editor-grade`, `.por-emissora` e nos blocos de
    `.painel-emissoras`. Estes três ficaram para trás.
*/
.faixa-bissemanas[hidden],
.atalhos-dias[hidden],
.tira-editor[hidden] { display: none; }

.faixa-bissemanas { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }

.faixa-bissemanas .rotulo-faixa {
    font-size: 12px;
    color: var(--texto-fraco);
    margin-right: 4px;
}

.faixa-bissemanas .ajuda { flex-basis: 100%; margin: 2px 0 0; }

.chip-bissemana {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 10px;
    border: 1px solid var(--borda);
    border-radius: 5px;
    cursor: pointer;
    font-size: 12px;
    line-height: 1.2;
}

.chip-bissemana:hover { border-color: var(--destaque); }

/* Marcada é a informação principal desta faixa: sem realce, uma lona contratada e
   uma não contratada ficam a uma caixinha de distância visual.

   O realce é `--fundo-suave` e não um azul literal: a regra do topo deste arquivo
   é nenhuma cor fora do bloco de tokens, e um `rgba(255,255,255,.10)` literal
   desapareceria sobre o fundo branco do tema claro. */
.chip-bissemana:has(input:checked) {
    border-color: var(--destaque);
    background: var(--fundo-suave);
}

.chip-bissemana strong { font-variant-numeric: tabular-nums; }
.chip-bissemana .discreto { font-size: 11px; }

.tira-editor { display: flex; flex-wrap: wrap; gap: 2px; }

.dia-campo { width: 28px; text-align: center; }
.dia-campo .dow,
.dia-campo .num-dia { display: block; font-size: 9px; line-height: 1.1; color: var(--texto-tenue); }
.dia-campo .num-dia { color: var(--texto-fraco); }

.dia-campo input {
    width: 100%;
    padding: 2px 0;
    text-align: center;
    font-size: 12px;
    border: 1px solid var(--borda);
    border-radius: 3px;
    background: var(--campo);
    color: inherit;
}

.dia-campo.fds input { background: rgba(var(--tinta), .06); }

/* Com 31 campos iguais, perder de vista em qual dia se está digitando é o erro que
   produz PI com inserção no dia errado. */
.dia-campo input:focus { outline: 2px solid var(--destaque); outline-offset: -1px; }

/* ---------- a contagem de emissoras na linha ---------- */

.celula-emissoras { padding: 2px 4px !important; }

button.conta-emissoras {
    width: 100%;
    padding: 3px 6px;
    border: 1px solid var(--borda);
    border-radius: 4px;
    background: transparent;
    color: inherit;
    font: inherit;
    font-size: 12px;
    cursor: pointer;
}

button.conta-emissoras:hover { background: rgba(var(--tinta), .06); }
button.conta-emissoras .discreto { font-size: 11px; }

/* As emissoras em colunas de 290 px, quantas couberem. É o seletor do plano
   (Planos/Detalhe), onde a largura é a da página inteira. No painel estreito da
   grade a mesma lista cai para uma coluna — ver .painel-emissoras. */
.grade-emissoras {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(290px, 1fr));
    gap: 4px 14px;
}

.emissora-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 2px 4px;
    border-radius: 4px;
}

.emissora-item:hover { background: rgba(var(--tinta), .04); }

.emissora-item .check { flex: 1; min-width: 0; gap: 6px; }

.emissora-item .check .discreto { font-size: 11px; }

/* O campo de exceção de preço: estreito e discreto até ser preenchido, porque o
   caso comum é herdar o padrão da linha. */
.emissora-item input[type="text"] {
    width: 88px;
    flex: none;
    padding: 2px 6px;
    font-size: 12px;
}

.emissora-item input[type="text"]:placeholder-shown { opacity: .55; }
.emissora-item input[type="text"]:focus { opacity: 1; }

/* ===================================================================== */
/*  O passo-a-passo do plano                                             */
/*                                                                       */
/*  É navegação e progresso ao mesmo tempo. Todo passo é clicável desde   */
/*  o começo: o assistente do sistema antigo só deixa voltar atrás        */
/*  recomeçando, e o resultado lá é metade dos planos parada em           */
/*  "informações incompletas".                                           */
/* ===================================================================== */

.passos {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    margin: 16px 0 14px;
}

.passos .passo {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 7px 14px;
    border: 1px solid var(--borda);
    border-radius: 999px;
    color: inherit;
    text-decoration: none;
    font-size: 13px;
    white-space: nowrap;
}

.passos a.passo:hover { border-color: var(--destaque); }

/* O passo que esta pessoa não pode abrir. Apagado e sem cursor de link — ele está ali para a
   contagem de etapas não mudar conforme quem olha, não para ser clicado. */
.passos .passo.travado { color: var(--texto-tenue); border-style: dotted; cursor: default; }
.passos .passo.travado .n { opacity: .55; }

.passos .passo .n {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 19px;
    height: 19px;
    border-radius: 50%;
    border: 1px solid var(--borda);
    font-size: 11px;
}

.passos .passo .conta {
    padding: 0 6px;
    border-radius: 999px;
    background: rgba(var(--tinta), .08);
    font-size: 11px;
}

/* Feito: o passo tem conteúdo. */
.passos .passo.feito .n { border-color: transparent; background: var(--destaque); color: var(--fundo); }

/* Onde a pessoa está agora. */
.passos .passo.ativo { border-color: var(--destaque); background: rgba(var(--tinta), .05); }

/* O próximo passo vazio: é a única sugestão que a barra faz, e ela não impede
   nenhuma das outras. */
.passos .passo.a-seguir { border-style: dashed; border-color: var(--destaque); }

/* O confronto com o ar fica DEPOIS de um corte, e não como um sexto passo: a
   trilha é o que falta montar, e isto é a medição do que já foi vendido. O
   traço é o que impede a leitura "ainda tenho um passo pela frente". */
.passos-corte {
    width: 1px;
    height: 18px;
    margin: 0 6px;
    background: var(--borda);
}

/* Sem apuração ainda: o passo existe (a PI saiu) mas não afirma número. Fica
   apagado em vez de mostrar 0%, que culparia a emissora por algo que ninguém
   mediu. */
.passos .passo.confronto:not(.feito) { color: var(--texto-fraco); }
.passos .passo.confronto:not(.feito) .n { color: var(--texto-tenue); }

/* O ◎ não é um número de ordem — não recebe o disco cheio de `.feito`. */
.passos .passo.confronto .n { border-color: transparent; background: none; font-size: 13px; }
.passos .passo.confronto.feito .n { background: none; color: var(--texto-fraco); }

/* ===================================================================== */
/*  Modal de escolha de emissora                                         */
/*                                                                       */
/*  <dialog> nativo: abre, fecha com Esc e prende o foco sem uma linha    */
/*  de JS para isso. O painel não tinha modal nenhum até aqui, e este é   */
/*  o primeiro caso em que ele ganha de uma tela: escolher entre milhares */
/*  de emissoras sem perder o plano de vista.                             */
/* ===================================================================== */

dialog.modal {
    width: min(760px, 94vw);
    max-height: 88vh;
    padding: 18px 20px;
    border: 1px solid var(--borda);
    border-radius: var(--raio);
    background: var(--painel);
    color: inherit;
    overflow: auto;
}

dialog.modal::backdrop { background: rgba(0, 0, 0, .6); }

dialog.modal .modal-topo {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 12px;
}

dialog.modal .modal-topo h2 { margin: 0; font-size: 17px; }

dialog.modal .modal-rodape {
    margin-top: 14px;
    padding-top: 12px;
    border-top: 1px solid var(--borda);
}

/* A lista de achados: altura fixa para o rodapé com o botão não fugir da tela
   quando a busca traz 40 resultados. */
.resultados {
    max-height: 42vh;
    overflow-y: auto;
    margin-top: 10px;
    border: 1px solid var(--borda);
    border-radius: var(--raio);
}

.resultados .resultado {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 7px 10px;
    cursor: pointer;
    border-bottom: 1px solid rgba(var(--tinta), .05);
}

.resultados .resultado:last-child { border-bottom: 0; }
.resultados .resultado:hover { background: rgba(var(--tinta), .05); }
.resultados .vazio { padding: 18px; text-align: center; }

/* As escolhidas viram fichas e SOBREVIVEM à troca de busca: dá para procurar
   "curitiba", marcar duas, procurar "salvador" e marcar mais três. */
.escolhidas {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    margin-top: 10px;
}

.escolhidas .ficha {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 6px 3px 10px;
    border-radius: 999px;
    background: rgba(var(--tinta), .09);
    font-size: 12px;
}

.escolhidas .ficha button {
    border: 0;
    background: transparent;
    color: inherit;
    cursor: pointer;
    font-size: 15px;
    line-height: 1;
    padding: 0 2px;
}

.escolhidas .ficha button:hover { color: var(--destaque); }

/* Edição na própria linha da tabela de emissoras do plano. */
.emissoras-plano td.acoes { white-space: nowrap; }
.emissoras-plano td.acoes .botao { margin-right: 4px; }

.emissoras-plano tr.linha-edicao > td {
    background: rgba(var(--tinta), .04);
    padding: 12px 14px;
}

/* Modal estreito: para diálogos de um assunto só (dias da linha, nova peça). */
dialog.modal.estreito { width: min(440px, 94vw); }

/* Botão miúdo, para caber dentro de célula de tabela sem engordar a linha. */
.botao.mini { padding: 2px 8px; font-size: 11px; }

/* A grade do PLANO herda a da PI e acrescenta as colunas de edição. Os campos de
   texto dentro da célula não podem ter largura mínima do navegador: com min-width
   do navegador, nove colunas de campo já estouram a metade esquerda do editor. */
.grade-plano td input[type="text"],
.grade-plano td input[type="time"],
.grade-plano td select {
    width: 100%;
    min-width: 0;
    padding: 2px 4px;
    font-size: 12px;
}

.grade-plano td { vertical-align: middle; }

.pecas-plano td.acoes { white-space: nowrap; }
.pecas-plano td.acoes .botao { margin-right: 4px; }

/* A linha que só carrega um <dialog> não pode ocupar altura na tabela. */
tr.linha-modal > td { padding: 0 !important; border: 0 !important; }

/* ===================================================================== */
/*  Upload de áudio da peça                                              */
/* ===================================================================== */

.upload .zona-arquivo {
    display: block;
    position: relative;
    padding: 20px 16px;
    border: 2px dashed var(--borda);
    border-radius: var(--raio);
    text-align: center;
    cursor: pointer;
}

.upload .zona-arquivo:hover,
.upload .zona-arquivo.sobre { border-color: var(--destaque); background: rgba(var(--tinta), .04); }

/* O <input> continua sendo o mecanismo; a zona só o cobre. Não usar display:none
   porque isso o tira da navegação por teclado. */
.upload .zona-arquivo input[type="file"] {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
}

.upload .zona-arquivo:focus-within { border-color: var(--destaque); }

.upload .zona-texto { display: block; }
.upload .zona-texto .discreto { display: block; margin-top: 4px; font-size: 12px; }

.upload .escolhido {
    margin-top: 10px;
    padding: 8px 10px;
    border-radius: var(--raio);
    background: rgba(var(--tinta), .06);
    font-size: 13px;
}

/* A ficha do arquivo que já está guardado. */
.ficha-arquivo {
    padding: 12px 14px;
    margin-bottom: 14px;
    border: 1px solid var(--borda);
    border-radius: var(--raio);
    background: rgba(var(--tinta), .03);
}

.ficha-arquivo .ficha-topo {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-bottom: 4px;
}

.ficha-dados {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 2px 12px;
    margin: 10px 0 0;
    font-size: 12px;
}

.ficha-dados dt { color: var(--texto-fraco); }
.ficha-dados dd { margin: 0; overflow-wrap: anywhere; }

/* ===================================================================== */
/*  O painel das emissoras — o lado direito da grade do plano            */
/*                                                                       */
/*  FIXO na tela e apontado para a linha selecionada. Marcar emissora e   */
/*  digitar a grade acontecem na mesma tela, sem abrir nem fechar nada —  */
/*  que é o que o desenho de um modal por linha não conseguia dar.       */
/*                                                                       */
/*  Duas abas porque são duas perguntas: "quem veicula ESTA linha"       */
/*  (edição) e "o que CADA emissora vai receber" (conferência). As duas   */
/*  são sobre emissora, e o lado direito da tela é o lado das emissoras. */
/* ===================================================================== */

.painel-emissoras {
    position: sticky;
    top: 68px;
    align-self: start;
    display: flex;
    flex-direction: column;
    max-height: calc(100vh - 96px);
    padding: 12px;
    background: var(--painel);
    border: 1px solid var(--borda);
    border-radius: var(--raio);
}

.painel-emissoras .abas { margin: 0 0 10px; }

.painel-emissoras button.aba { background: transparent; font: inherit; font-size: 13px; cursor: pointer; }

/* O corpo rola; o painel não. min-height: 0 é o que faz a rolagem acontecer dentro
   de um item de flex — sem ele o corpo estica o painel, o painel estica a página e a
   tela volta a ser alta, que é a queixa que este desenho resolve. */
.painel-emissoras .corpo { overflow-y: auto; min-height: 0; }
.painel-emissoras .corpo[hidden] { display: none; }
.painel-emissoras .grupo-emissoras[hidden] { display: none; }

.cabeca-grupo { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px; margin-bottom: 8px; }
.cabeca-grupo .discreto { font-size: 12px; }

.busca-emissora { width: 100%; margin-bottom: 8px; }

.acoes-grupo { display: flex; flex-wrap: wrap; gap: 5px; margin-bottom: 6px; }

.painel-emissoras .ajuda { margin: 0 0 8px; }

/* No painel estreito a emissora ocupa a linha inteira e o campo de exceção de preço
   encolhe: o nome é o que se procura, o preço é a exceção. */
.painel-emissoras .grade-emissoras { grid-template-columns: minmax(0, 1fr); gap: 1px; }
.painel-emissoras .emissora-item input[type="text"] { width: 68px; }
.painel-emissoras .emissora-item[hidden] { display: none; }

.nome-emissora { min-width: 0; overflow-wrap: anywhere; font-size: 13px; }
.nome-emissora .discreto { display: block; font-size: 11px; }


/* ==========================================================================
   Confirmação e recado em modal — padrão do sistema (ver modal.js)
   ========================================================================== */

dialog.modal .modal-corpo p { margin: 0; line-height: 1.5; }

/* O rodapé da pergunta alinha à direita: a ação fica onde a mão já está indo
   depois de ler o texto, e "Cancelar" nunca cai debaixo do cursor do botão que
   abriu o diálogo. */
dialog.modal .modal-rodape.botoes { display: flex; justify-content: flex-end; gap: 8px; }

/* Recado de erro se anuncia pela cor antes de ser lido. */
dialog#modal-mensagem.erro .modal-topo h2 { color: var(--ruim); }

/* ==========================================================================
   Barra de ações grudada no rodapé
   ==========================================================================
   Para telas de edição longa — a grade do plano é o caso: 31 colunas de dia,
   emissoras por linha e resumo por emissora. Sem isto, salvar exige rolar até
   o fim e voltar, a cada vez. */

.barra-acoes {
    position: sticky;
    bottom: 0;
    z-index: 5;
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 14px;
    padding: 10px 14px;
    border: 1px solid var(--borda);
    border-radius: var(--raio);
    background: var(--painel);
    /* A sombra é o que diz que existe conteúdo por baixo — sem ela a barra
       parece o fim da página e a pessoa não rola mais. */
    box-shadow: 0 -6px 16px rgba(0, 0, 0, .28);
}

.barra-acoes .resumo-barra { display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; }
.barra-acoes .botoes { display: flex; gap: 8px; margin: 0; }

/* ===================================================================== */
/*  MODO POR EMISSORA — a grade inteira, de uma emissora só              */
/*                                                                       */
/*  A emissora GRUDADA na grade dela: a lista à esquerda, o documento à   */
/*  direita. Aqui as 31 colunas de dia voltam, e é de propósito — com     */
/*  uma emissora só na tela a largura que elas custam está disponível.    */
/*                                                                       */
/*  É o que o modo campanha, por construção, nunca consegue mostrar: lá   */
/*  a linha vale para várias emissoras, e por isso ele não responde       */
/*  "o que a Caiobá vai receber".                                         */
/* ===================================================================== */

.modos-da-grade { margin-bottom: 14px; }
.modos-da-grade .aba { background: transparent; font: inherit; cursor: pointer; }

/* `hidden` sozinho não vence um `display` declarado — e os dois modos declaram. */
.editor-grade[hidden],
.por-emissora[hidden] { display: none; }

.por-emissora {
    display: grid;
    grid-template-columns: 250px minmax(0, 1fr);
    gap: 16px;
    align-items: start;
}

@media (max-width: 1180px) {
    .por-emissora { grid-template-columns: minmax(0, 1fr); }
    .rail-emissoras { position: static; max-height: none; }
}

/* ---------- a lista das emissoras ---------- */

.rail-emissoras {
    position: sticky;
    top: 68px;
    align-self: start;
    display: flex;
    flex-direction: column;
    gap: 2px;
    max-height: calc(100vh - 96px);
    overflow-y: auto;
    padding: 6px;
    background: var(--painel);
    border: 1px solid var(--borda);
    border-radius: var(--raio);
}

button.item-rail {
    display: block;
    width: 100%;
    padding: 7px 9px;
    border: 1px solid transparent;
    border-radius: 6px;
    background: transparent;
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
}

button.item-rail:hover { background: rgba(var(--tinta), .05); }

button.item-rail.sel {
    background: rgba(88, 166, 255, .12);
    border-color: var(--destaque);
}

button.item-rail .nome { display: block; font-size: 13px; font-weight: 600; }
button.item-rail .praca { display: block; font-size: 11px; }

button.item-rail .numeros {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 5px;
    margin-top: 3px;
    font-size: 11px;
}

/* Emissora sem linha NÃO sai da lista: ela é justamente a que precisa de atenção
   antes de emitir, porque não vai receber PI nenhuma. Só fica esmaecida. */
button.item-rail.vazia { opacity: .6; }
button.item-rail.vazia.sel { opacity: 1; }

/* ---------- a grade da emissora ---------- */

.grade-da-emissora[hidden] { display: none; }

.cabeca-emissora {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-bottom: 8px;
}

.cabeca-emissora .separador { flex: 1; }
.cabeca-emissora .discreto { font-size: 12px; }

/* A grade de LEITURA herda a da PI — mesma fonte, mesma coluna de dia estreita,
   mesmo fim de semana sombreado — e troca os campos por texto. Ser o mesmo desenho
   do editor da PI é o que faz conferir aqui valer para o documento de lá. */
.grade-lida { width: 100%; }
.grade-lida td { padding: 3px 5px; }

/* A coluna de dia aqui é 22 px e não 26: sem campo de digitação dentro, dois
   dígitos centrados cabem, e os 4 px × 31 economizados são o que traz a tabela
   inteira para dentro da tela ao lado da lista de emissoras. */
.grade-lida th.dia,
.grade-lida td.dia {
    width: 22px;
    min-width: 22px;
    max-width: 22px;
    text-align: center;
    padding: 3px 1px;
    color: var(--texto-tenue);
}

/* Dia com inserção acende. Sem isso, ler 31 colunas quase todas vazias é contar
   casa no calendário — o erro mais caro de quem monta grade à mão. */
.grade-lida td.dia.tem {
    color: var(--texto);
    font-weight: 600;
    background: rgba(88, 166, 255, .14);
}

.grade-lida td.peca { color: var(--destaque); }

.grade-lida tbody tr:hover > td { background: rgba(var(--tinta), .04); }
.grade-lida tbody tr:hover > td.dia.tem { background: rgba(88, 166, 255, .2); }

/* O total da emissora fecha a tabela: é o número que vai para a PI, e é o que se
   confere contra o que o cliente aprovou. */
.grade-lida tfoot th {
    position: sticky;
    bottom: 0;
    background: var(--painel-alto);
    padding: 5px;
    font-size: 12px;
}

.grade-lida tfoot .rotulo-total { text-align: left; }
.grade-lida tfoot th.num { text-align: right; }

/* ---------- o painel de emissoras perdeu as abas ---------- */

.cabeca-painel {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 8px;
    margin: 0 0 10px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--borda);
}

.cabeca-painel .discreto { font-size: 12px; }

/* ===================================================================== */
/*  Valor que o sistema decide                                           */
/*                                                                       */
/*  Onde havia um campo e passou a haver um fato: o número da PI, que é   */
/*  automático. Parece com um campo — mesma altura, mesmo alinhamento na  */
/*  faixa de campos — e NÃO parece editável, que é a única coisa que ele  */
/*  precisa comunicar. Um <input readonly> pareceria um campo quebrado.   */
/* ===================================================================== */

.valor-fixo {
    padding: 6px 10px;
    border: 1px dashed var(--borda);
    border-radius: var(--raio);
    background: rgba(var(--tinta), .03);
    color: var(--texto);
    font-size: 14px;
}

/* ==========================================================================
   Métrica clicável — o painel por perfil
   ==========================================================================
   Cada número do painel é uma pilha de trabalho com destino: clicar leva à
   lista já filtrada nela. Sem o afeto de clique a pessoa lê o número, entende
   que há trabalho, e não descobre que dali se chega ao trabalho. */

a.metrica {
    text-decoration: none;
    color: inherit;
    border-radius: var(--raio);
    padding: 6px 10px;
    margin: -6px -10px;
    transition: background-color .12s ease;
}

a.metrica:hover,
a.metrica:focus-visible { background: var(--fundo-suave); }

a.metrica strong.ruim { color: var(--ruim); }

/* ==========================================================================
   Checking — a matriz emissora × dia
   ==========================================================================
   Reusa `.grade-pi`, que é a mesma malha em que a campanha foi digitada: quem
   montou a grade lê o resultado no formato em que vendeu, sem aprender uma
   segunda tela.

   As cores dizem quatro coisas diferentes, e a distinção entre a terceira e a
   quarta é o que sustenta o laudo: `falha` é a emissora não ter veiculado,
   `cinza` é NÓS não termos ouvido. Pintar as duas de vermelho cobraria da
   emissora uma lacuna nossa. */

.matriz-checking td.checking-celula { padding: 0; }

.matriz-checking td.checking-celula a {
    display: block;
    padding: 2px 1px;
    text-decoration: none;
    color: inherit;
    font-size: 11px;
}

.matriz-checking td.checking-celula.ok      { background: rgba(63, 185, 80, .18); }
.matriz-checking td.checking-celula.parcial { background: rgba(210, 153, 34, .20); }
.matriz-checking td.checking-celula.falha   { background: rgba(248, 81, 73, .20); }

/* Lacuna nossa: sem cor de julgamento. Cinza é "não sabemos", e é o que ela é. */
.matriz-checking td.checking-celula.cinza   { background: rgba(110, 118, 129, .22); }

/* Testemunhal vendido e ainda não conferido. Roxo, e deliberadamente NÃO vermelho
   nem cinza: vermelho acusaria a emissora de uma leitura que ninguém mediu, e
   cinza a confundiria com lacuna de captação — que manda o operador procurar
   defeito no satélite, onde não há nenhum. Ver a migração 028. */
.matriz-checking td.checking-celula.locucao { background: rgba(163, 113, 247, .18); }

/* Veiculação a mais é bônus da emissora, não erro — azul, o mesmo do MATCH. */
.matriz-checking td.checking-celula.extra   { background: rgba(88, 166, 255, .16); }

.matriz-checking td.checking-celula a:hover { outline: 1px solid var(--borda); }

/* A legenda de cores, abaixo da matriz. */
.checking-legenda {
    display: inline-block;
    width: 11px;
    height: 11px;
    border: 1px solid var(--borda);
    border-radius: 2px;
    vertical-align: -1px;
    margin: 0 3px 0 12px;
}

.checking-legenda.ok      { background: rgba(63, 185, 80, .35); }
.checking-legenda.parcial { background: rgba(210, 153, 34, .40); }
.checking-legenda.falha   { background: rgba(248, 81, 73, .40); }
.checking-legenda.cinza   { background: rgba(110, 118, 129, .40); }
.checking-legenda.locucao { background: rgba(163, 113, 247, .40); }
.checking-legenda.extra   { background: rgba(88, 166, 255, .35); }

/* A lista de prontidão: o que impede a campanha de ser aferida, com o atalho. */
.lista-prontidao { list-style: none; margin: 10px 0 0; padding: 0; }
.lista-prontidao > li { margin-bottom: 8px; line-height: 1.5; }
.lista-prontidao a { margin-left: 6px; }

/* Resolver uma falha: seletor, motivo e gravar na mesma linha. */
.bloco-falha { margin-bottom: 8px; }

.linha-resolver {
    display: flex;
    gap: 6px;
    align-items: center;
    margin-top: 4px;
    flex-wrap: wrap;
}

.linha-resolver select { max-width: 140px; }
.linha-resolver input[type="text"] { flex: 1 1 140px; min-width: 120px; }

/* O bloco de "colocar em monitoramento" na ficha da peça. */
.monitoramento {
    margin-top: 12px;
    padding-top: 10px;
    border-top: 1px dashed var(--borda);
}

/* ------------------------------------------------ criar sem sair do modal --

   O botao "+ Nova agencia" abaixo dos seletores do modal de plano. Discreto de
   proposito: e uma saida para quando a agencia nao esta na lista, nao o caminho
   principal — o cadastro completo continua sendo /Agencias e /Anunciantes.

   O formulario em si vive num <dialog> irmao, e herda o estilo de .modal. */
.criar-rapido { margin-top: 5px; }

/* O recado dentro do modal de cadastro: ele aparece depois de um clique que a
   pessoa acha que funcionou, entao precisa ser visto. Cores por token, como manda
   a regra do topo deste arquivo. */
dialog[data-criar] .aviso { margin: 10px 0 0; }
dialog[data-criar] .aviso.erro { background: var(--fundo-suave); color: var(--ruim); }

/* As duas caixas de bi-semana do modal, lado a lado. */
#np-bissemanas .linha-campos { display: flex; gap: 8px; align-items: flex-end; }
#np-bissemanas .linha-campos .campo { flex: 1; min-width: 0; }

/* --------------------------------------------------------- filtro de meio ---
   O filtro do seletor de veículos: mídia exterior / rádio e TV / todos.

   Botões de rádio em vez de <select>: são três opções e as três precisam estar
   visíveis. Num <select> fechado a escolha vigente fica escondida atrás de um
   clique, e o efeito é o defeito que este filtro conserta ao contrário — a
   busca volta vazia e não há nada na tela dizendo por quê.

   O <input> continua no DOM (só fora de vista) em vez de `display:none`:
   escondido de verdade ele sai da navegação por teclado e do leitor de tela, e
   o grupo deixa de ser operável sem mouse. */
.filtro-meio {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.filtro-meio .opcao-meio {
    display: inline-flex;
    align-items: center;
    padding: 5px 12px;
    border: 1px solid rgba(var(--tinta), .18);
    border-radius: 999px;
    font-size: 13px;
    cursor: pointer;
    user-select: none;
}

.filtro-meio .opcao-meio:hover { background: rgba(var(--tinta), .05); }

.filtro-meio .opcao-meio input {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
    pointer-events: none;
}

.filtro-meio .opcao-meio:has(input:checked) {
    background: rgba(var(--tinta), .10);
    border-color: rgba(var(--tinta), .45);
    font-weight: 600;
}

/* O foco tem de aparecer no rótulo, porque o input que o recebe é invisível.
   Sem isto, andar de Tab pelo grupo não mostra onde se está. */
.filtro-meio .opcao-meio:has(input:focus-visible) {
    outline: 2px solid rgba(var(--tinta), .55);
    outline-offset: 2px;
}


/* ==========================================================================
   A HOME — blocos com peso por perfil
   ==========================================================================
   A ordem dos blocos NÃO está aqui: ela vem de `Services/Home.cs`. Isto é só a
   moldura. Nenhuma cor literal: as dos gráficos chegam em `style` como
   `var(--match)` etc., vindas de C#, para o tema claro funcionar sem JS. */

.cabeca-home {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
    margin-bottom: 14px;
}

.cabeca-home h1 { margin: 0 0 2px; }
.cabeca-home p { margin: 0; }

.titulo-secao { font-size: 14px; color: var(--texto-fraco); margin: 26px 0 10px; font-weight: 600; }

/* ---------- a faixa de pendências ---------- */

.faixa-pendencias {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    margin-bottom: 16px;
}

.chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 12px;
    border-radius: 999px;
    font-size: 13px;
    font-weight: 600;
    text-decoration: none;
    border: 1px solid var(--borda);
    background: var(--painel);
    color: var(--texto);
}

.chip:hover, .chip:focus-visible { background: var(--painel-alto); }
.chip.erro    { border-color: var(--erro);         color: var(--erro); }
.chip.atencao { border-color: var(--reconectando); color: var(--nao-ident); }
.chip.ok      { border-color: var(--no-ar);        color: var(--no-ar); }

/* O chip como FILTRO ESCOLHIDO. Existe porque combobox de entidade que cresce
   não é filtro: numa base com 6.956 campanhas, o seletor de plano da fila de
   conferência listava tudo o que existe para uma fila de dois itens. O chip sai
   do RESULTADO — é curto por construção — e o estado marcado é o que diz qual
   recorte está no ar. */
.chip.ativo {
    border-color: var(--destaque);
    background: var(--fundo-suave);
    color: var(--texto);
}

.chip strong { font-variant-numeric: tabular-nums; }

/* ---------- a grade dos blocos ----------

   `minmax(0, 1fr)` e não `1fr`: uma tabela larga dentro de um item de grid
   estoura a coluna, e a página inteira passa a rolar de lado. */

.grade-home {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(360px, 100%), 1fr));
    gap: 16px;
    align-items: start;
}

.bloco-home { min-width: 0; }
.bloco-home.largo { grid-column: 1 / -1; }

.bloco-home .cartao-topo { align-items: center; margin-bottom: 10px; }

.acoes-bloco { display: inline-flex; align-items: center; gap: 6px; }
.acoes-bloco form { display: inline-flex; gap: 4px; }

/* Os botões de arrumar só aparecem quando o bloco tem o ponteiro ou o foco: com
   quinze blocos, quatro botões visíveis em cada um viram sessenta setas na tela.
   Com foco-dentro, quem navega por teclado continua alcançando. */
.acoes-bloco .botao.mini,
.acoes-bloco form { opacity: 0; transition: opacity .12s ease; }
.bloco-home:hover .acoes-bloco .botao.mini,
.bloco-home:hover .acoes-bloco form,
.bloco-home:focus-within .acoes-bloco .botao.mini,
.bloco-home:focus-within .acoes-bloco form { opacity: 1; }

/* ---------- o número grande de um bloco de uma pergunta só ---------- */

a.numerao, .numerao {
    display: flex;
    align-items: baseline;
    gap: 10px;
    text-decoration: none;
    color: inherit;
    border-radius: var(--raio);
    padding: 4px 6px;
    margin: -4px -6px;
}

a.numerao:hover, a.numerao:focus-visible { background: var(--fundo-suave); }
.numerao strong { font-size: 34px; font-weight: 600; font-variant-numeric: tabular-nums; line-height: 1; }
.numerao span { color: var(--texto-fraco); font-size: 13px; }
.numerao.atencao strong { color: var(--nao-ident); }
.numerao.erro strong { color: var(--erro); }

.selos { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }

.metrica .legenda {
    display: block;
    font-size: 11px;
    color: var(--texto-tenue);
    text-transform: uppercase;
    letter-spacing: .04em;
    margin: 0 0 2px;
}

.metrica strong { font-size: 19px; font-weight: 600; font-variant-numeric: tabular-nums; }
.metrica strong.ruim { color: var(--ruim); }
.metrica strong.sim { color: var(--no-ar); }
.metrica strong.atencao { color: var(--nao-ident); }

/* Explicação de uma linha embaixo de um número. Existia só dentro de `.campo`. */
.ajuda { font-size: 12px; color: var(--texto-tenue); margin: 8px 0 0; }
.ajuda a { color: var(--texto-fraco); }

/* Tabela densa: a home mostra cinco linhas, não cinquenta, e cada linha tem de
   caber num cartão ao lado de outro. */
table.densa { font-size: 13px; }
table.densa th { padding: 4px 8px; font-size: 11px; }
table.densa td { padding: 5px 8px; }
table.densa td.ruim, table.densa .ruim { color: var(--ruim); }
table.densa .discreto { font-size: 12px; }

/* ==========================================================================
   Os gráficos — SVG desenhado no servidor, sem biblioteca
   ==========================================================================
   A cor de cada forma chega em `fill`/`background` como `var(--…)`, calculada
   em C#. É o que faz o gráfico acompanhar o tema claro sem uma linha de JS —
   e é o motivo de não haver Chart.js aqui: biblioteca recebe hexadecimal e
   criaria uma segunda paleta, para divergir desta no primeiro ajuste. */

.grafico-rosca { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }

.rosca { position: relative; flex: 0 0 auto; }
.rosca svg { display: block; }
.rosca .trilha { stroke: var(--painel-alto); }
.rosca a { cursor: pointer; }
.rosca circle { transition: opacity .12s ease; }
.rosca a:hover circle { opacity: .78; }

.rosca-centro {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    pointer-events: none;
}

.rosca-centro strong { font-size: 20px; font-weight: 600; font-variant-numeric: tabular-nums; }
.rosca-centro span { font-size: 10px; color: var(--texto-tenue); text-transform: uppercase; letter-spacing: .04em; }

.legenda-grafico { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; font-size: 13px; min-width: 0; }
.legenda-grafico li { display: flex; align-items: center; gap: 8px; }
.legenda-grafico i { width: 9px; height: 9px; border-radius: 2px; flex: 0 0 auto; }
.legenda-grafico a { color: inherit; text-decoration: none; }
.legenda-grafico a:hover { text-decoration: underline; }
.legenda-grafico b { margin-left: auto; font-variant-numeric: tabular-nums; }

/* ---------- barras horizontais ----------

   Em CSS e não em SVG: a barra horizontal é uma LINHA, e como linha ela ganha
   rótulo legível, número alinhado, área de clique do tamanho do dedo e reflow
   em tela estreita. O SVG fica para o que é forma. */

.grafico-barras { list-style: none; margin: 4px 0 0; padding: 0; display: grid; gap: 3px; }

.barra-linha {
    display: grid;
    grid-template-columns: minmax(90px, 40%) 1fr auto;
    align-items: center;
    gap: 10px;
    padding: 3px 6px;
    margin: 0 -6px;
    border-radius: 6px;
    text-decoration: none;
    color: inherit;
    font-size: 13px;
}

a.barra-linha:hover, a.barra-linha:focus-visible { background: var(--fundo-suave); }

.barra-nome { color: var(--texto-fraco); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.barra-trilha { height: 8px; border-radius: 4px; background: var(--painel-alto); overflow: hidden; }
.barra-preenchida { display: block; height: 100%; border-radius: 4px; min-width: 2px; }
.barra-valor { font-variant-numeric: tabular-nums; white-space: nowrap; }

/* ---------- colunas verticais ---------- */

.grafico-colunas { margin-top: 6px; }
.grafico-colunas svg { display: block; width: 100%; height: 84px; }
.grafico-colunas .eixo { stroke: var(--borda); stroke-width: 1; vector-effect: non-scaling-stroke; }
.grafico-colunas a rect { transition: opacity .12s ease; }
.grafico-colunas a:hover rect { opacity: .75; }

.colunas-rotulos {
    display: flex;
    justify-content: space-between;
    font-size: 11px;
    color: var(--texto-tenue);
    margin-top: 4px;
}

/* ---------- faixa de tendência ---------- */

.tendencia { display: flex; align-items: center; gap: 10px; margin-top: 10px; flex-wrap: wrap; }
.grafico-faixa { display: block; flex: 0 0 auto; }

/* ---------- mapa de calor ---------- */

.grafico-mapa { display: grid; gap: 2px; font-size: 10px; }

.mapa-horas {
    display: grid;
    grid-template-columns: repeat(24, 1fr);
    color: var(--texto-tenue);
    margin-left: 34px;
}

.mapa-linha { display: flex; align-items: center; gap: 6px; }
.mapa-dia { width: 28px; text-align: right; color: var(--texto-tenue); flex: 0 0 auto; }
.mapa-celulas { display: grid; grid-template-columns: repeat(24, 1fr); gap: 2px; flex: 1 1 auto; min-width: 0; }
.mapa-celula { display: block; height: 13px; border-radius: 2px; }

/* O bloco adiado: espaço reservado com a altura de um cartão pequeno, para a
   grade não pular quando o conteúdo chegar. */
.bloco-home.adiado { min-height: 120px; }
.bloco-home.adiado .vazio { padding: 18px; }

/* ---------- percurso do briefing ---------- */
/*
   A FAIXA DE ETAPAS e a LINHA DO TEMPO da tela /Briefings/Detalhe.

   As duas respondem perguntas diferentes e por isso não compartilham estilo: a faixa é ONDE o
   pedido está (varredura horizontal, uma olhada), a linha é COMO ele chegou (leitura vertical,
   em ordem). Fundi-las daria uma coisa que não serve bem a nenhuma das duas.
*/

.etapas {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  list-style: none;
  margin: 0 0 14px;
  padding: 0;
  counter-reset: etapa;
}

.etapa {
  flex: 1 1 150px;
  min-width: 140px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  background: var(--painel);
  /* A barra de estado fica na BORDA DE CIMA e não num ícone: ela precisa ser legível de relance
     numa fila de cinco, e ponto colorido nesse tamanho vira ruído. */
  border-top-width: 3px;
  border-top-color: var(--borda);
  padding: 9px 12px;
}

.etapa.feita { border-top-color: var(--no-ar); }
.etapa.pendente { background: transparent; }

.etapa a { display: block; text-decoration: none; color: inherit; }
.etapa a:hover .etapa-valor { text-decoration: underline; }

.etapa-rotulo {
  display: block;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--texto-tenue);
}

.etapa-valor {
  display: block;
  font-size: 13px;
  font-weight: 600;
  margin-top: 2px;
  overflow-wrap: anywhere;
}

.etapa.pendente .etapa-valor { font-weight: 400; color: var(--texto-tenue); }

.linha-tempo { list-style: none; margin: 0; padding: 0; }

.marco {
  display: flex;
  gap: 14px;
  align-items: baseline;
  padding: 8px 0 8px 16px;
  /* O fio contínuo à esquerda é o que faz a lista LER como cronologia. Ele é do item, não de um
     pseudo-elemento do <ol>, para que o último marco não fique com o fio sobrando embaixo. */
  border-left: 2px solid var(--borda);
  position: relative;
}

.marco::before {
  content: "";
  position: absolute;
  left: -5px;
  top: 15px;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--borda);
}

/* A cor do ponto diz de QUE ETAPA o marco é, e é a mesma leitura da faixa. */
.marco.cenario::before  { background: var(--match); }
.marco.proposta::before { background: var(--anunciante); }
.marco.plano::before    { background: var(--no-ar); }
.marco.pi::before       { background: var(--fala); }

.marco-quando {
  font-size: 12px;
  color: var(--texto-tenue);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  min-width: 122px;
}

.marco-corpo { font-size: 13px; }
.marco-corpo .discreto { display: block; margin-top: 1px; }

/* ==========================================================================
   O COCKPIT DE GESTÃO
   ==========================================================================

   Quatro telas com a mesma moldura: faixa de números grandes em cima, grade de
   cartões embaixo. Reaproveita `.cartao`, `.metrica`, `table.densa` e a família
   de gráficos; o que existe aqui é só o que não existia — o cartão de KPI com
   variação, a grade dos cartões e as duas formas novas (empilhada e funil).

   Nenhuma cor literal, como sempre: tudo sai das variáveis do topo. */

/* ---------- a faixa de números grandes ---------- */

/* `auto-fit` com piso de 200px: em tela larga cabem sete cartões numa linha, em
   telefone cada um ocupa a largura toda. Sem o piso, sete cartões de 90px
   ficariam ilegíveis — e KPI ilegível é decoração. */
.faixa-kpi {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr));
    gap: 12px;
    margin-bottom: 18px;
}

.cartao.kpi {
    padding: 12px 14px;
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.cartao.kpi .legenda {
    font-size: 11px;
    color: var(--texto-tenue);
    text-transform: uppercase;
    letter-spacing: .04em;
}

.kpi-valor {
    font-size: 26px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    line-height: 1.15;
    color: inherit;
    text-decoration: none;
    /* Quebra em vez de estourar: "R$ 1.234,5 mil" num cartão de 200px cabe. */
    overflow-wrap: anywhere;
}

a.kpi-valor:hover, a.kpi-valor:focus-visible { text-decoration: underline; }

.kpi-rodape {
    display: flex;
    align-items: baseline;
    gap: 8px;
    flex-wrap: wrap;
    font-size: 12px;
}

.kpi-variacao {
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* A cor diz para que LADO a variação foi, e o lado bom depende do número — ver
   `CartaoDeKpi.MaiorEMelhor`. Verde não é "subiu": é "foi para onde queríamos". */
.kpi-variacao.sim     { color: var(--no-ar); }
.kpi-variacao.ruim    { color: var(--ruim); }
.kpi-variacao.neutra  { color: var(--texto-tenue); }

.cartao.kpi .ajuda { margin-top: 6px; font-size: 11px; line-height: 1.35; }

/* ---------- a grade dos cartões ----------

   `minmax(0, 1fr)` e não `1fr`: uma tabela larga dentro de um item de grid
   estoura a coluna e a página inteira passa a rolar de lado. Mesma armadilha
   que `.grade-home` já documenta. */

.grade-gestao {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(380px, 100%), 1fr));
    gap: 16px;
    align-items: start;
}

.grade-gestao > .cartao { min-width: 0; }
.grade-gestao > .cartao.largo { grid-column: 1 / -1; }

/* ---------- o filtro de período ---------- */

.gestao-filtro { align-items: flex-end; }
.gestao-filtro .campo { max-width: 130px; }

.atalhos-periodo {
    display: inline-flex;
    gap: 6px;
    flex-wrap: wrap;
    margin-bottom: 2px;
}

.atalhos-periodo .chip { padding: 4px 10px; font-size: 12px; }

/* ---------- coluna empilhada ---------- */

.grafico-empilhadas { margin: 6px 0 2px; }

.grafico-empilhadas svg {
    display: block;
    width: 100%;
    height: 132px;
    overflow: visible;
}

.grafico-empilhadas rect { transition: opacity .12s ease; }
.grafico-empilhadas a:hover rect,
.grafico-empilhadas a:focus-visible rect { opacity: .78; }

/* ---------- funil ---------- */

.grafico-funil {
    list-style: none;
    margin: 4px 0 0;
    padding: 0;
    counter-reset: etapa;
}

.grafico-funil > li { margin-bottom: 2px; }

/* A taxa de passagem fica ENTRE as linhas e recuada, para se ler como um degrau
   e não como mais uma etapa. */
.funil-passagem {
    display: block;
    font-size: 11px;
    color: var(--texto-tenue);
    font-variant-numeric: tabular-nums;
    padding: 1px 0 1px 10px;
}

.funil-passagem.ruim { color: var(--ruim); }

.funil-etapa {
    display: grid;
    grid-template-columns: minmax(96px, 1fr) minmax(0, 2.4fr) auto;
    grid-template-areas: "nome trilha valor" "nome detalhe valor";
    align-items: center;
    gap: 2px 10px;
    padding: 5px 6px;
    border-radius: var(--raio);
    text-decoration: none;
    color: inherit;
}

a.funil-etapa:hover, a.funil-etapa:focus-visible { background: var(--fundo-suave); }

.funil-nome { grid-area: nome; font-size: 13px; }
.funil-trilha {
    grid-area: trilha;
    display: block;
    height: 14px;
    border-radius: 3px;
    background: rgba(var(--tinta), .07);
    overflow: hidden;
}
.funil-preenchida { display: block; height: 100%; border-radius: 3px; }

.funil-valor {
    grid-area: valor;
    font-size: 14px;
    font-variant-numeric: tabular-nums;
    text-align: right;
    min-width: 46px;
}

.funil-detalhe {
    grid-area: detalhe;
    font-size: 11px;
    color: var(--texto-tenue);
    font-variant-numeric: tabular-nums;
}

/* ---------- o rodapé dos números que falharam ---------- */

.gestao-problemas { margin-top: 20px; }
.gestao-problemas ul { margin: 6px 0 0; padding-left: 18px; }
.gestao-problemas li { font-size: 12px; margin-bottom: 2px; }

@media (max-width: 560px) {
    /* Em telefone o funil vira duas linhas por etapa: a barra perde a comparação
       lado a lado, mas o rótulo e o número continuam legíveis — que é a troca
       certa numa tela onde 96px de rótulo já comem metade da largura. */
    .funil-etapa {
        grid-template-columns: 1fr auto;
        grid-template-areas: "nome valor" "trilha trilha" "detalhe detalhe";
    }
}

/* ---------- a cascata da peça (Inteligência) ----------

   Uma fileira de passos que se lê como frase: programado, menos o que não ouvimos,
   menos o que não medimos, igual ao cobrável, menos o achado, igual ao que falta.
   É a decomposição de docs/inteligencia.md §3.5.

   Por que fileira e não gráfico de barras: os números têm ordens de grandeza muito
   diferentes (240 programado contra 3 faltando), e a barra proporcional some
   justamente na parcela que interessa. O que se compara aqui é a CONTA, não o
   tamanho. */

.cascata {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    align-items: stretch;
}

.cascata .passo {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 8px 12px;
    min-width: 104px;
    border: 1px solid var(--borda);
    border-radius: var(--raio);
    background: var(--painel-alto);
}

.cascata .passo .rotulo { font-size: 11px; color: var(--texto-tenue); }
.cascata .passo strong { font-size: 20px; font-variant-numeric: tabular-nums; }

/* O cobrável é o número do meio da conta e o único que o resto referencia — ele
   ganha o realce, e não o programado, que é só o ponto de partida. */
.cascata .passo.forte { border-color: var(--destaque); background: var(--fundo-suave); }
.cascata .passo.ok strong    { color: var(--no-ar); }
.cascata .passo.falta strong { color: var(--erro); }

/* As duas parcelas que acusam o NOSSO lado, e não o do veículo. Cor de "não
   identificado" de propósito: é a mesma família de "não sabemos", que é o que as
   duas dizem. */
.cascata .passo.nosso strong { color: var(--nao-ident); }

/* ---------- a fila de conferência (checking de locução) ----------

   Cada item é um cartão de EVIDÊNCIA, e não uma linha de tabela: o que a pessoa
   precisa ler para decidir é o trecho transcrito e o checklist de termos, e os
   dois são texto corrido de tamanho variável. Numa tabela, eles seriam a coluna
   que estoura a largura e que ninguém consegue ler. */

.fila-topo {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 8px;
}

/* O trecho ouvido. Fica com a cor da FALA (violeta), que é a mesma que a
   transcrição usa no resto do painel — quem já viu a onda de uma gravação
   reconhece de onde aquele texto veio. */
.trecho {
    margin: 8px 0;
    padding: 8px 12px;
    border-left: 3px solid var(--fala);
    background: rgba(var(--tinta), .04);
    border-radius: 0 var(--raio) var(--raio) 0;
    font-size: 14px;
    line-height: 1.5;
}

/* ---------------------------------------------------------------- área de envio de arquivos --

   Uma ÁREA DE SOLTAR, e não um `<input type=file>` nu. O áudio chega arrastado de uma pasta na
   maioria das vezes, e o controle nativo não diz que aceita isso — quem não sabe, clica, procura a
   pasta e arrasta assim mesmo na terceira tentativa.

   O `<label>` embrulha o input de propósito: clicar na área inteira abre o seletor sem uma linha de
   JS, e o teclado continua chegando ao controle nativo. O input fica no DOM e some por posição, e
   não por `display:none` — que o tiraria da ordem de foco.

   Veio de Pages/Fingerprints em 10/09/2026, quando /Monitoramentos/Novo passou a aceitar vários
   áudios e precisou da mesma peça. As regras são as de lá, sem mudança: mover sem mexer é o que
   permite conferir que a tela antiga continua igual. */
/* ---- área de envio ---- */
.area-envio {
  display: block;
  border: 2px dashed var(--borda);
  border-radius: var(--raio);
  padding: 22px 18px;
  text-align: center;
  cursor: pointer;
  margin-top: 10px;
  transition: border-color .15s, background .15s;
}

.area-envio:hover,
.area-envio:focus-within { border-color: var(--acento, #3b82f6); }

/* Estado de arraste. É o retorno que diz "pode soltar" — sem ele a área parece inerte. */
.area-envio.sobre {
  border-color: var(--acento, #3b82f6);
  background: color-mix(in srgb, var(--acento, #3b82f6) 8%, transparent);
}

/* O input continua no DOM (é ele que envia), só não é o que se vê. `display:none` o tiraria
   da ordem de foco; assim o teclado continua alcançando. */
.area-envio input[type=file] {
  position: absolute;
  width: 1px; height: 1px;
  opacity: 0;
}

.area-envio .icone { font-size: 26px; line-height: 1; opacity: .55; }
.area-envio .chamada { font-weight: 600; margin: 8px 0 4px; }

.area-envio .escolhidos {
  list-style: none;
  margin: 12px 0 0;
  padding: 0;
  text-align: left;
  max-height: 140px;
  overflow-y: auto;
  font-size: 13px;
}

.area-envio .escolhidos li {
  padding: 3px 0;
  border-top: 1px solid var(--borda);
  font-family: var(--mono, monospace);
}

/* ---- um nome por comercial, na lista de arquivos escolhidos ----

   Nasce com o nome do arquivo sem extensão e é editável ali mesmo. Com três áudios no mesmo envio,
   um campo "nome do comercial" só batizaria os três igual — e a lista da pessoa ficaria com três
   linhas indistinguíveis, que é justamente o que ela precisa separar depois. */
.pecas-escolhidas {
  list-style: none;
  margin: 12px 0 0;
  padding: 0;
}

.pecas-escolhidas li {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 0;
  border-top: 1px solid var(--borda);
}

/* O nome do arquivo é referência, não campo: fica estreito e em fonte de código, porque o que se
   faz com ele é conferir se é o certo. Encolhe primeiro quando falta espaço. */
.pecas-escolhidas .arquivo {
  flex: 0 1 240px;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: var(--mono, monospace);
  font-size: 12px;
  color: var(--texto-tenue);
}

.pecas-escolhidas input[type=text] { flex: 1 1 220px; min-width: 0; }

/* O selo "já ouvimos" empurrado para a direita da linha do resultado. */
.resultados .resultado .selo { margin-left: auto; }

/* ------------------------------------------------- home do licenciado de monitoramento --

   O relatório do bloco: três números, o aviso de captação pendente, e os comerciais que mais
   tocaram. Os números usam `.numerao`, que já existe — a coluna é a mesma dos cartões da operação,
   e reusá-la é o que faz as duas homes parecerem o mesmo sistema. */
.numerao-linha {
  display: flex;
  flex-wrap: wrap;
  gap: 28px;
}

.destaques-monitoramento {
  list-style: none;
  margin: 14px 0 0;
  padding: 0;
  font-size: 13.5px;
}

.destaques-monitoramento li {
  padding: 6px 0;
  border-top: 1px solid var(--borda);
  color: var(--texto-fraco);
}

.destaques-monitoramento li strong { color: var(--texto); }

/* ---- a vitrine do que a conta de teste AINDA não tem ----

   Nada aqui é link, de propósito: são telas que aquela conta não alcança, e um link que leva a
   "sem permissão" é pior que link nenhum — parece produto quebrado, e não produto a contratar.
   O item é clicável só para escolher o ASSUNTO da ligação. */
.vitrine {
  list-style: none;
  margin: 0 0 16px;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 10px;
}

.vitrine li {
  padding: 11px 13px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  background: var(--painel);
  cursor: pointer;
  transition: border-color .15s, background .15s;
}

.vitrine li:hover { border-color: var(--primario); }

/* O escolhido fica marcado: é o que diz à pessoa que o clique dela foi registrado antes mesmo de
   ela apertar o botão. Sem isso, clicar num cartão parece não fazer nada. */
.vitrine li.marcado {
  border-color: var(--primario);
  background: color-mix(in srgb, var(--primario) 10%, transparent);
}

.vitrine li strong { display: block; margin-bottom: 4px; font-size: 14px; }
.vitrine li span { color: var(--texto-fraco); font-size: 12.5px; line-height: 1.5; }

/* ------------------------------------------------- relatório de monitoramento --

   A tela do detalhe era um cartão por dia, na ordem do calendário: trinta blocos, a maioria
   dizendo "nada encontrado neste dia". Não respondia pergunta nenhuma — "quantas vezes tocou de
   manhã?" exigia rolar tudo e somar de cabeça. Agora é agregado em cima, histograma, uma linha por
   dia e uma tabela plana de veiculações. */
.topo-relatorio {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 14px;
}

.painel-numeros {
  display: flex;
  flex-wrap: wrap;
  gap: 34px;
  margin-bottom: 14px;
}

/* "12/30": o denominador não compete com o número. */
.numerao strong .de { font-size: 20px; font-weight: 400; color: var(--texto-tenue); }

/* ---- o histograma por hora ----

   Barras em CSS, sem biblioteca. São 24 valores inteiros e uma régua: qualquer biblioteca de
   gráfico aqui seria 90 kB para desenhar um `height` em porcentagem — e traria fonte, cor e
   tooltip próprios, que é como uma tela deixa de parecer o resto do sistema.

   As 24 barras aparecem SEMPRE, inclusive as zeradas: um gráfico que só desenha as horas com
   evento esconde exatamente o que se quer ver, que é a madrugada vazia. */
.histograma {
  display: flex;
  align-items: flex-end;
  gap: 3px;
  height: 150px;
  margin-top: 12px;
}

.histograma .barra {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  height: 100%;
  min-width: 0;
}

.histograma .valor {
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  color: var(--texto-fraco);
  margin-bottom: 3px;
}

/* `min-height` para a hora com UMA veiculação não sumir: 1 de 40 daria menos de um pixel, e a
   barra invisível é indistinguível de hora sem veiculação nenhuma. */
.histograma .haste {
  width: 100%;
  min-height: 3px;
  background: var(--primario);
  border-radius: 2px 2px 0 0;
}

.histograma .barra.vazia .haste { background: var(--borda); min-height: 2px; }

.histograma .hora {
  font-size: 10px;
  color: var(--texto-tenue);
  margin-top: 4px;
  font-variant-numeric: tabular-nums;
}

/* Dia que ainda não chegou: presente na tabela, e claramente sem dado. Escondê-lo faria o período
   parecer menor do que é. */
.tabela tr.futuro td { opacity: .45; }

.aviso-inline { color: var(--nao-ident); font-weight: 600; }

.tabela ul.lacunas { margin: 6px 0 0; padding-left: 18px; }

/* ---- o que se procura: comercial gravado ou marca falada ----

   Dois cartoes de radio, e nao um <select> de duas opcoes: a diferenca entre os dois tipos precisa
   de uma frase para ser entendida, e uma lista suspensa nao tem onde por a frase. Quem chega aqui
   pela primeira vez nao sabe que existe monitoramento de testemunhal. */
.tipos-de-monitoramento {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 10px;
  margin-top: 6px;
}

.opcao-tipo {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 14px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  background: var(--painel);
  cursor: pointer;
}

.opcao-tipo:has(input:checked) {
  border-color: var(--primario);
  background: color-mix(in srgb, var(--primario) 10%, transparent);
}

.opcao-tipo input { margin-top: 3px; width: auto; }
.opcao-tipo span { display: block; font-size: 12.5px; color: var(--texto-fraco); line-height: 1.5; }
.opcao-tipo strong { display: block; font-size: 14px; color: var(--texto); margin-bottom: 2px; }

/* A frase transcrita na tabela do relatorio. Larga, porque o contexto e o dado - e e ele que
   distingue o testemunhal do cliente de uma coincidencia de nome. */
.tabela td.trecho-falado {
  max-width: 520px;
  font-size: 12.5px;
  color: var(--texto-fraco);
  line-height: 1.5;
}
