/* Painel de Inteligência de Mercado — layout e componentes */

/*
 * Jost — a fonte da marca, usada nos gráficos. Servida pelo próprio hub, e não
 * pelo Google Fonts nem pela fonte instalada no Windows: na VPS não há nenhuma
 * das duas, e o gráfico cairia calado num fallback. Como ele vira imagem colada
 * no relatório, essa diferença viajaria para fora da casa sem ninguém notar.
 *
 * Só dois pesos, que são os que o desenho usa. TTF em vez de WOFF2 porque a
 * conversão exige brotli, e 120 KB num hub local não paga uma dependência nova.
 * Licença SIL OFL 1.1 — redistribuir junto do projeto é permitido.
 */
@font-face {
  font-family: "Jost";
  src: url("../fonts/Jost-Regular.ttf") format("truetype");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Jost";
  src: url("../fonts/Jost-SemiBold.ttf") format("truetype");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}


*, *::before, *::after { box-sizing: border-box; }

/*
 * `hidden` tem de esconder, sempre.
 *
 * O atributo `hidden` do HTML vale `display: none`, mas QUALQUER regra de
 * `display` no CSS ganha dele — e o hub tem várias (`.btn` é inline-flex,
 * `.filtros` é flex). Sem esta linha, `elemento.hidden = true` no JavaScript não
 * fazia nada nesses casos, e o botão "baixar planilha" das telas de gráfico
 * aparecia antes de existir arquivo para baixar, levando a um link morto.
 *
 * É a mesma regra que os normalize.css da vida trazem, e a razão de o `!important`
 * ser aceitável aqui: esconder é a intenção declarada no HTML, não um estilo a
 * ser sobreposto.
 */
[hidden] { display: none !important; }

html, body { height: 100%; }

/*
 * A barra de rolagem ocupa lugar SEMPRE, apareça ela ou não.
 *
 * Sem isso, o gráfico entra num vai e vem: ele fica mais alto quanto mais largo
 * for, então redesenhar pode fazer a página passar da altura da janela, o que
 * faz nascer a barra de rolagem, o que estreita a área em ~15px, o que manda
 * redesenhar de novo mais estreito, o que pode tirar a barra. Reservando o
 * espaço, a largura útil para de depender do tamanho do conteúdo.
 */
html { scrollbar-gutter: stable; }

body {
  margin: 0;
  font-family: var(--ff);
  font-size: var(--fs);
  color: var(--txt);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

a { color: var(--verde-700); text-decoration: none; }
a:hover { text-decoration: underline; }
html[data-tema="escuro"] a { color: var(--verde-500); }

h1, h2, h3, h4 { margin: 0; font-weight: 600; line-height: 1.25; }
p { margin: 0 0 10px; }

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-thumb { background: var(--borda-forte); border-radius: 6px; border: 2px solid var(--bg); }
::-webkit-scrollbar-track { background: transparent; }

/* ============================ ESTRUTURA — CHROME NO PADRÃO JDE E1 ============================ */

/*
 * O DOCUMENTO INTEIRO CONTINUA ROLANDO. Nenhuma faixa é `fixed` e nenhum painel
 * tem rolagem própria: banner, navegador, abas e trilha grudam com `sticky`.
 *
 * Isso é decisão, não acaso. Trocar por painéis de rolagem independente mudaria
 * o container de rolagem de tudo que já usa `position: sticky` por dentro do
 * conteúdo — o cabeçalho das tabelas (`.tbl th`) e o cartão lateral do Morning
 * Call, que gruda em `calc(var(--topo-h) + 20px)`. Por isso `--topo-h` passou a
 * ser a SOMA das três faixas do alto, e não a altura de uma barra só.
 */
.e1 { min-height: 100vh; display: flex; flex-direction: column; }

/* -------------------- 1. BANNER -------------------- */

.e1-banner {
  height: var(--banner-h); flex: none;
  position: sticky; top: 0; z-index: 60;
  background: linear-gradient(90deg, var(--banner-1) 0%, var(--banner-2) 58%, var(--banner-1) 100%);
  border-bottom: 1px solid var(--banner-borda);
  color: var(--banner-txt);
  display: flex; align-items: center; gap: 10px;
  padding: 0 10px 0 4px;
}

/* Hambúrguer: recolhe o navegador para a tela inteira virar área de trabalho. */
.e1-hamburguer {
  width: 34px; height: 30px; flex: none;
  display: grid; align-content: center; justify-items: center; gap: 3px;
  border: 1px solid transparent; border-radius: var(--r); background: none; cursor: pointer;
  transition: background .12s, border-color .12s;
}
.e1-hamburguer:hover { background: var(--banner-campo); border-color: var(--banner-borda); }
.e1-hamburguer span { display: block; width: 15px; height: 1.5px; background: var(--banner-txt); border-radius: 2px; }

.e1-marca {
  display: flex; align-items: center; gap: 8px; flex: none;
  padding: 3px 10px 3px 4px; border-right: 1px solid var(--banner-borda);
  color: var(--banner-txt-forte); text-decoration: none;
}
.e1-marca:hover { text-decoration: none; }
/*
 * O logo da casa, em arquivo. A ALTURA manda e a largura acompanha: a marca
 * não é quadrada (~1,39:1), e fixar as duas medidas a achataria.
 */
.e1-marca-logo { height: 26px; width: auto; flex: none; display: block; }

/*
 * Uma linha só. O subtítulo "Inteligência de Mercado" saiu junto com o nome
 * antigo: ele existia para dizer o que era o "BASIS HUB", e repeti-lo debaixo
 * de um nome que já termina nessas mesmas três palavras seria eco.
 */
.e1-marca-txt {
  font-size: var(--fs-sm); font-weight: 700; letter-spacing: .3px;
  color: var(--banner-txt-forte); white-space: nowrap;
}

/* -------- Fast Path -------- */

.e1-fastpath { position: relative; flex: 1; max-width: 460px; min-width: 0; }
.e1-fastpath-ico {
  position: absolute; left: 8px; top: 50%; transform: translateY(-50%);
  font-size: 14px; color: var(--banner-txt); opacity: .65; pointer-events: none;
}
.e1-fastpath input[type="text"] {
  width: 100%; height: 27px; padding: 0 8px 0 26px;
  background: var(--banner-campo); border: 1px solid var(--banner-borda); border-radius: var(--r);
  color: var(--banner-txt-forte); font-size: var(--fs-sm); font-family: inherit;
  transition: background .12s, border-color .12s;
}
.e1-fastpath input::placeholder { color: var(--banner-txt); opacity: .65; }
.e1-fastpath input:focus {
  outline: none; background: rgba(255, 255, 255, .16);
  border-color: var(--verde-500); box-shadow: 0 0 0 2px rgba(63, 148, 100, .30);
}

.e1-fastpath-lista {
  position: absolute; top: calc(100% + 5px); left: 0; right: 0; z-index: 70;
  background: var(--bg-elev); border: 1px solid var(--borda-forte); border-radius: var(--r);
  box-shadow: var(--sombra-3); max-height: 62vh; overflow-y: auto; padding: 3px;
  display: none;
}
.e1-fastpath-lista.on { display: block; }
.e1-fastpath-op {
  display: flex; align-items: center; gap: 9px; padding: 6px 8px;
  border-radius: var(--r-sm); cursor: pointer; color: var(--txt); font-size: var(--fs-sm);
}
.e1-fastpath-op:hover, .e1-fastpath-op.marcado { background: var(--verde-050); }
html[data-tema="escuro"] .e1-fastpath-op:hover,
html[data-tema="escuro"] .e1-fastpath-op.marcado { background: var(--bg-inset); }
.e1-fastpath-op .cod {
  font-family: var(--ff-mono); font-size: 10.5px; font-weight: 700; flex: none;
  color: var(--verde-700); background: var(--verde-050); border: 1px solid var(--verde-100);
  border-radius: var(--r-sm); padding: 1px 5px; min-width: 46px; text-align: center;
}
html[data-tema="escuro"] .e1-fastpath-op .cod { color: var(--verde-500); background: var(--bg-inset); border-color: var(--borda); }
.e1-fastpath-op .nome { font-weight: 600; }
.e1-fastpath-op .onde { margin-left: auto; font-size: var(--fs-xs); color: var(--txt-3); white-space: nowrap; }
.e1-fastpath-vazio { padding: 10px 12px; font-size: var(--fs-sm); color: var(--txt-3); }

/* -------- lado direito do banner -------- */

.e1-banner-dir { margin-left: auto; display: flex; align-items: center; gap: 8px; flex: none; }
.e1-relogio { text-align: right; line-height: 1.3; }
.e1-data { font-size: 10.5px; color: var(--banner-txt); opacity: .8; text-transform: capitalize; }
.e1-horas { font-size: var(--fs-xs); color: var(--banner-txt-forte); }
.e1-horas .mono { font-family: var(--ff-mono); font-size: 11px; }
.e1-horas .silencioso { color: var(--banner-txt); opacity: .7; }

.e1-banner-sep { width: 1px; height: 22px; background: var(--banner-borda); }

.e1-acao {
  position: relative; width: 30px; height: 27px; flex: none;
  display: grid; place-items: center; font-size: 14px; line-height: 1;
  border: 1px solid transparent; border-radius: var(--r); background: none; cursor: pointer;
  transition: background .12s, border-color .12s;
}
.e1-acao:hover { background: var(--banner-campo); border-color: var(--banner-borda); }
.e1-badge {
  position: absolute; top: -4px; right: -4px;
  background: var(--baixa); color: #fff; font-size: 9.5px; font-weight: 700;
  border-radius: 8px; padding: 0 4px; min-width: 15px; text-align: center; line-height: 1.5;
  border: 1px solid var(--banner-1);
}
.e1-usuario {
  font-size: var(--fs-xs); font-weight: 650; color: var(--banner-txt-forte);
  background: var(--banner-campo); border: 1px solid var(--banner-borda); border-radius: var(--r);
  padding: 4px 9px; max-width: 150px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* -------------------- 2. CORPO: NAVEGADOR + ÁREA DE TRABALHO -------------------- */

/*
 * `flex: 1 0 auto` — cresce para preencher a viewport numa tela curta, e NÃO
 * encolhe abaixo do próprio conteúdo numa tela longa. Com `flex: 1` (base 0) e
 * `min-height: 0`, o contêiner podia ficar menor que o conteúdo e a página
 * transbordava em vez de rolar.
 */
/*
 * SEM TRANSIÇÃO NA LARGURA DA COLUNA, e isso é correção de defeito, não gosto.
 *
 * Animar `grid-template-columns` deixava a área de conteúdo mudando de largura
 * quadro a quadro. As telas de gráfico redesenham o canvas depois de uma pausa
 * (o `debounce` de 150ms do `resize`), então durante toda a animação MAIS a
 * pausa o bitmap antigo ficava esticado pelo CSS, e o desenho aparecia
 * espichado na horizontal. Instantânea, a largura nova já é a definitiva e o
 * esticamento dura só a pausa, que quase não se vê.
 *
 * A gaveta da tela estreita continua deslizando: ela usa `transform` e fica
 * POR CIMA do conteúdo, sem mexer na largura de ninguém.
 */
.e1-corpo {
  flex: 1 0 auto;
  display: grid; grid-template-columns: var(--nav-w) minmax(0, 1fr);
}
.e1.nav-oculto .e1-corpo { grid-template-columns: 0 minmax(0, 1fr); }
.e1.nav-oculto .e1-nav { opacity: 0; pointer-events: none; }

.e1-nav {
  background: var(--nav-bg);
  border-right: 1px solid var(--nav-borda);
  color: var(--nav-txt);
  display: flex; flex-direction: column;
  position: sticky; top: var(--banner-h); height: calc(100vh - var(--banner-h));
  overflow: hidden; min-width: 0;
  transition: opacity .12s;
}

.e1-nav-topo {
  flex: none; padding: 8px 9px; border-bottom: 1px solid var(--nav-borda);
  background: var(--nav-bg-2);
  display: flex; align-items: center; gap: 8px;
}
.e1-nav-rot {
  font-size: 9.5px; font-weight: 800; letter-spacing: 1px; text-transform: uppercase;
  color: var(--nav-txt-2); flex: none;
}
.e1-visao {
  margin-left: auto; width: auto; flex: 1; min-width: 0;
  height: 25px; padding: 0 6px; font-size: var(--fs-xs); font-weight: 600;
  background: var(--bg-elev); color: var(--nav-txt);
  border: 1px solid var(--nav-borda); border-radius: var(--r);
}

.e1-nav-filtro { flex: none; position: relative; padding: 8px 9px; border-bottom: 1px solid var(--nav-borda); }
.e1-nav-filtro input[type="text"] {
  height: 27px; padding: 0 24px 0 8px; font-size: var(--fs-sm);
  background: var(--bg-elev); border-color: var(--nav-borda); border-radius: var(--r);
}
.e1-filtro-x {
  position: absolute; right: 13px; top: 50%; transform: translateY(-50%);
  border: none; background: none; cursor: pointer; color: var(--txt-3); font-size: 11px; padding: 2px 4px;
}
.e1-filtro-x:hover { color: var(--txt); }

/* -------- a árvore -------- */

.e1-arvore { flex: 1; overflow-y: auto; overflow-x: hidden; padding: 5px 0 12px; }

.e1-no { border-bottom: 1px solid var(--nav-borda); }
.e1-no:last-child { border-bottom: none; }

/*
 * Cabeçalho de pasta. Em ERP a pasta é uma linha de comando, não um rótulo
 * decorativo: ocupa a largura toda, tem alvo de clique cheio e mostra quantas
 * telas guarda — o número é o que dispensa abrir para saber se vale.
 */
.e1-no-cab {
  display: flex; align-items: center; gap: 7px; width: 100%;
  padding: 7px 10px; border: none; background: none; cursor: pointer;
  font-family: inherit; font-size: var(--fs-sm); font-weight: 700; color: var(--nav-modulo);
  text-align: left; letter-spacing: .2px;
  transition: background .1s;
}
.e1-no-cab:hover { background: var(--nav-hover); }
.e1-caret { flex: none; width: 9px; font-size: 9px; color: var(--nav-txt-2); transition: transform .14s; }
.e1-no.aberto > .e1-no-cab .e1-caret { transform: rotate(90deg); }
.e1-no-cab .pasta { flex: none; font-size: 12px; opacity: .75; }
.e1-no-cab .rot { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.e1-no-cab .conta {
  flex: none; font-size: 9.5px; font-weight: 700; color: var(--nav-txt-2);
  background: var(--bg-elev); border: 1px solid var(--nav-borda); border-radius: 9px; padding: 0 5px;
}
.e1-no-corpo { display: none; padding-bottom: 4px; }
.e1-no.aberto > .e1-no-corpo { display: block; }

/* Segundo nível — o emissor dentro de "Fontes Públicas". */
.e1-sub-no > .e1-no-cab {
  padding: 5px 10px 5px 24px; font-size: var(--fs-xs); font-weight: 700;
  color: var(--nav-txt-2); text-transform: uppercase; letter-spacing: .7px;
}
.e1-sub-no { border-bottom: none; }

/* -------- a folha: uma aplicação -------- */

/*
 * A linha é um contêiner, e o LINK é filho dela — não a linha inteira.
 *
 * A estrela de favorito é um botão, e botão dentro de âncora é marcação
 * inválida: o navegador reaninha os dois e o clique passa a cair no lugar
 * errado. Por isso o alvo de navegação é `.e1-app-link`, que estica para
 * ocupar toda a linha menos o canto da estrela.
 */
.e1-app {
  display: flex; align-items: center; gap: 5px;
  padding: 0 7px 0 25px;
  color: var(--nav-txt);
  border-left: 3px solid transparent;
  transition: background .1s, color .1s;
}
.e1-sub-no .e1-app { padding-left: 39px; }
.e1-app:hover { background: var(--nav-hover); color: var(--txt); }
.e1-app.ativo {
  background: var(--nav-ativo-bg); color: var(--nav-ativo-txt);
  border-left-color: var(--nav-trilho);
  box-shadow: inset 0 1px 0 var(--nav-borda), inset 0 -1px 0 var(--nav-borda);
}

.e1-app-link {
  flex: 1; min-width: 0;
  display: flex; align-items: center; gap: 8px;
  padding: 5px 0;
  color: inherit; font-size: var(--fs-sm); text-decoration: none;
}
.e1-app-link:hover { color: inherit; text-decoration: none; }
.e1-app.ativo .e1-app-link { font-weight: 700; }

.e1-app .ico { flex: none; width: 15px; text-align: center; font-size: 12px; opacity: .8; }
.e1-app.ativo .ico { opacity: 1; }
.e1-app .rot { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.e1-app .selo {
  flex: none; background: var(--baixa); color: #fff; font-size: 9.5px; font-weight: 700;
  border-radius: 8px; padding: 0 5px; min-width: 16px; text-align: center; line-height: 1.6;
}
.e1-app .ponto-att { flex: none; width: 7px; height: 7px; border-radius: 50%; background: var(--baixa); }
.e1-app .fav {
  flex: none; border: none; background: none; cursor: pointer; padding: 2px 3px;
  font-size: 12px; line-height: 1; color: var(--txt-3); opacity: 0; transition: opacity .1s, color .1s;
}
.e1-app:hover .fav, .e1-app .fav.on { opacity: 1; }
.e1-app .fav.on { color: var(--alerta); }
.e1-app .fav:hover { color: var(--alerta); }
/* Sem :hover no toque, a estrela nunca apareceria — ali ela fica sempre visível. */
@media (hover: none) { .e1-app .fav { opacity: .55; } }

/* Marcação do trecho que casou com o filtro da árvore. */
.e1-app mark, .e1-fastpath-op mark {
  background: color-mix(in srgb, var(--alerta) 30%, transparent);
  color: inherit; border-radius: 2px; padding: 0 1px;
}

.e1-arvore-vazio { padding: 18px 14px; font-size: var(--fs-sm); color: var(--nav-txt-2); text-align: center; }

.e1-nav-rodape {
  flex: none; padding: 8px 11px; border-top: 1px solid var(--nav-borda);
  background: var(--nav-bg-2);
  font-size: var(--fs-xs); color: var(--nav-txt-2);
  display: flex; align-items: center; gap: 7px;
}
.ponto { width: 7px; height: 7px; border-radius: 50%; background: var(--neutro); flex: none; }
.ponto.on { background: #24a35e; box-shadow: 0 0 0 3px rgba(36, 163, 94, .18); animation: pulsar 2.4s infinite; }
.ponto.off { background: #d2604f; }
@keyframes pulsar { 0%, 100% { opacity: 1 } 50% { opacity: .45 } }

/* -------------------- 3. ÁREA DE TRABALHO -------------------- */

.e1-principal { display: flex; flex-direction: column; min-width: 0; }

/* -------- abas de aplicações abertas -------- */

.e1-abas {
  height: var(--abas-h); flex: none;
  position: sticky; top: var(--banner-h); z-index: 45;
  background: var(--aba-bg); border-bottom: 1px solid var(--borda);
  display: flex; align-items: stretch; gap: 0;
  padding: 0 6px; overflow-x: auto; overflow-y: hidden;
  scrollbar-width: none;
}
.e1-abas::-webkit-scrollbar { height: 0; }

.e1-aba {
  display: flex; align-items: center; gap: 4px; flex: none;
  max-width: 230px; margin-top: 4px; padding-right: 5px;
  border: 1px solid var(--borda); border-bottom: none;
  border-radius: var(--r) var(--r) 0 0;
  background: transparent; color: var(--txt-2);
  font-size: var(--fs-sm);
  transition: background .1s, color .1s;
}
/* O link ocupa a aba inteira menos o canto do ✕, que é irmão dele, não filho. */
.e1-aba-link {
  display: block; min-width: 0; padding: 0 4px 0 11px; line-height: calc(var(--abas-h) - 5px);
  color: inherit; text-decoration: none;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.e1-aba-link:hover { color: inherit; text-decoration: none; }
.e1-aba + .e1-aba { margin-left: 3px; }
.e1-aba:hover { background: color-mix(in srgb, var(--bg-elev) 60%, transparent); color: var(--txt); text-decoration: none; }
.e1-aba.ativa {
  background: var(--aba-ativa); color: var(--txt); font-weight: 650;
  border-color: var(--borda); box-shadow: 0 1px 0 0 var(--aba-ativa);
  position: relative;
}
.e1-aba.ativa::before {
  content: ''; position: absolute; left: -1px; right: -1px; top: -1px; height: 2px;
  background: var(--verde-700); border-radius: 2px 2px 0 0;
}
.e1-aba .x {
  flex: none; border: none; background: none; cursor: pointer; color: var(--txt-3);
  font-size: 12px; line-height: 1; padding: 2px 3px; border-radius: var(--r-sm);
}
.e1-aba .x:hover { background: var(--bg-inset); color: var(--baixa); }

/* -------- trilha -------- */

.e1-caminho {
  height: var(--caminho-h); flex: none;
  position: sticky; top: calc(var(--banner-h) + var(--abas-h)); z-index: 44;
  background: var(--bg-elev); border-bottom: 1px solid var(--borda);
  display: flex; align-items: center; gap: 10px; padding: 0 18px;
}
.e1-trilha { display: flex; align-items: center; gap: 6px; min-width: 0; overflow: hidden; }
.e1-trilha a, .e1-trilha span { font-size: var(--fs-sm); white-space: nowrap; }
.e1-trilha .passo { color: var(--txt-3); cursor: default; }
.e1-trilha .passo.clicavel { cursor: pointer; color: var(--txt-2); }
.e1-trilha .passo.clicavel:hover { color: var(--verde-700); text-decoration: underline; }
.e1-trilha .sep { color: var(--txt-3); opacity: .6; font-size: 11px; }
.e1-trilha .folha {
  font-size: var(--fs-md); font-weight: 650; color: var(--txt);
  overflow: hidden; text-overflow: ellipsis;
}

.e1-caminho-dir { margin-left: auto; display: flex; align-items: center; gap: 8px; flex: none; }
.e1-cod {
  font-family: var(--ff-mono); font-size: 10.5px; font-weight: 700; letter-spacing: .5px;
  color: var(--txt-3); background: var(--bg-inset); border: 1px solid var(--borda);
  border-radius: var(--r-sm); padding: 2px 6px;
}
.e1-estrela {
  border: 1px solid transparent; background: none; cursor: pointer;
  font-size: 15px; line-height: 1; padding: 3px 5px; border-radius: var(--r); color: var(--txt-3);
  transition: color .12s, background .12s;
}
.e1-estrela:hover { background: var(--bg-inset); color: var(--alerta); }
.e1-estrela.on { color: var(--alerta); }

/* Subtítulo da tela: a linha que a view declara em `sub`. */
.e1-subtitulo {
  flex: none; padding: 9px 18px 0; font-size: var(--fs-sm); color: var(--txt-3); line-height: 1.4;
}
.e1-subtitulo:empty { display: none; }

.conteudo { padding: 16px 18px 26px; flex: 1; min-width: 0; }

/* -------------------- responsivo -------------------- */

/*
 * Abaixo de 1080px o navegador vira GAVETA sobreposta em vez de coluna: numa
 * tela estreita, 268px de menu comem a metade útil da área de trabalho, e a
 * árvore só é consultada de vez em quando.
 */
@media (max-width: 1080px) {
  .e1-corpo { grid-template-columns: 0 minmax(0, 1fr); }
  .e1-nav {
    position: fixed; top: var(--banner-h); left: 0; width: var(--nav-w); z-index: 55;
    box-shadow: var(--sombra-2);
    transform: translateX(-100%); transition: transform .16s ease; opacity: 1; pointer-events: auto;
  }
  .e1.nav-aberto .e1-nav { transform: none; }
  .e1.nav-oculto .e1-nav { opacity: 1; pointer-events: auto; }
}

@media (max-width: 900px) {
  .e1-marca-txt, .e1-relogio { display: none; }
  .e1-fastpath { max-width: none; }
}

@media (max-width: 640px) {
  .e1-usuario { display: none; }
  .conteudo { padding: 12px 12px 20px; }
  .e1-caminho { padding: 0 12px; }
  .e1-subtitulo { padding: 8px 12px 0; }
}

/* ============================ COMPONENTES ============================ */

.grade { display: grid; gap: var(--gap); }
.g2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.g3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.g4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.g-2-1 { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); }
.g-1-2 { grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); }
@media (max-width: 1180px) { .g4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } .g-2-1, .g-1-2, .g3 { grid-template-columns: 1fr; } }
@media (max-width: 820px) { .g2, .g4 { grid-template-columns: 1fr; } }

.cartao {
  background: var(--bg-elev); border: 1px solid var(--borda);
  border-radius: var(--r-lg); box-shadow: var(--sombra-1);
  display: flex; flex-direction: column; min-width: 0;
}
.cartao-topo {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 15px; border-bottom: 1px solid var(--borda);
}
.cartao-topo h2 { font-size: var(--fs); font-weight: 650; letter-spacing: .1px; }
.cartao-topo .acoes { margin-left: auto; display: flex; gap: 6px; align-items: center; }
.cartao-corpo { padding: 15px; min-width: 0; }
.cartao-corpo.plano { padding: 0; }
.cartao-rodape { padding: 10px 15px; border-top: 1px solid var(--borda); font-size: var(--fs-sm); color: var(--txt-3); }

/* métrica */
.metrica { padding: 14px 16px; }
.metrica .rot { font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: .6px; color: var(--txt-3); font-weight: 650; }
.metrica .val { font-size: var(--fs-2xl); font-weight: 700; line-height: 1.1; margin-top: 6px; font-variant-numeric: tabular-nums; }
.metrica .nota { font-size: var(--fs-sm); color: var(--txt-2); margin-top: 4px; }

/* botões */
.btn {
  display: inline-flex; align-items: center; gap: 6px; justify-content: center;
  padding: 6px 12px; border-radius: var(--r); border: 1px solid var(--borda-forte);
  background: var(--bg-elev); color: var(--txt); font-size: var(--fs-sm); font-weight: 550;
  font-family: inherit; cursor: pointer; transition: all .12s; white-space: nowrap;
}
.btn:hover { background: var(--bg-inset); border-color: var(--txt-3); }
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: .45; cursor: not-allowed; transform: none; }
.btn.primario { background: var(--verde-800); border-color: var(--verde-800); color: #fff; }
.btn.primario:hover { background: var(--verde-700); border-color: var(--verde-700); }
.btn.perigo { background: var(--baixa); border-color: var(--baixa); color: #fff; }
.btn.perigo:hover { filter: brightness(1.08); }
.btn.fantasma { border-color: transparent; background: transparent; color: var(--txt-2); }
.btn.fantasma:hover { background: var(--bg-inset); color: var(--txt); }
.btn.pequeno { padding: 3px 8px; font-size: var(--fs-xs); }
.btn.bloco { width: 100%; }

/* campos */
.campo { display: flex; flex-direction: column; gap: 5px; margin-bottom: 12px; }
.campo label { font-size: var(--fs-sm); font-weight: 600; color: var(--txt-2); }
.campo .ajuda { font-size: var(--fs-xs); color: var(--txt-3); }
input[type="text"], input[type="date"], input[type="password"], input[type="number"], select, textarea {
  font-family: inherit; font-size: var(--fs); color: var(--txt);
  background: var(--bg-elev); border: 1px solid var(--borda-forte);
  border-radius: var(--r); padding: 7px 10px; width: 100%; transition: border-color .12s, box-shadow .12s;
}
textarea { resize: vertical; line-height: 1.55; min-height: 74px; }
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--verde-600); box-shadow: 0 0 0 3px rgba(47, 122, 79, .14);
}
input::placeholder, textarea::placeholder { color: var(--txt-3); }
input:disabled, select:disabled, textarea:disabled { opacity: .55; cursor: not-allowed; }

/* etiquetas */
.tag {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: var(--fs-xs); font-weight: 650; padding: 2px 7px; border-radius: 20px;
  background: var(--bg-inset); color: var(--txt-2); border: 1px solid var(--borda); white-space: nowrap;
}
.tag.soja { background: color-mix(in srgb, var(--c-soja) 13%, transparent); color: var(--c-soja); border-color: color-mix(in srgb, var(--c-soja) 30%, transparent); }
.tag.milho { background: color-mix(in srgb, var(--c-milho) 15%, transparent); color: #8f6d09; border-color: color-mix(in srgb, var(--c-milho) 35%, transparent); }
.tag.algodao { background: color-mix(in srgb, var(--c-algodao) 13%, transparent); color: var(--c-algodao); border-color: color-mix(in srgb, var(--c-algodao) 30%, transparent); }
.tag.fertilizantes { background: color-mix(in srgb, var(--c-fertilizantes) 13%, transparent); color: var(--c-fertilizantes); border-color: color-mix(in srgb, var(--c-fertilizantes) 30%, transparent); }
.tag.macro { background: color-mix(in srgb, var(--c-macro) 13%, transparent); color: var(--c-macro); }
.tag.clima { background: color-mix(in srgb, var(--c-clima) 13%, transparent); color: var(--c-clima); border-color: color-mix(in srgb, var(--c-clima) 30%, transparent); }
.tag.alta { background: color-mix(in srgb, var(--alta) 14%, transparent); color: var(--alta); border-color: color-mix(in srgb, var(--alta) 32%, transparent); }
.tag.baixa { background: color-mix(in srgb, var(--baixa) 14%, transparent); color: var(--baixa); border-color: color-mix(in srgb, var(--baixa) 32%, transparent); }
.tag.alerta { background: color-mix(in srgb, var(--alerta) 14%, transparent); color: var(--alerta); border-color: color-mix(in srgb, var(--alerta) 32%, transparent); }
.tag.solido { background: var(--verde-800); color: #fff; border-color: var(--verde-800); }
html[data-tema="escuro"] .tag.milho { color: #e2b83a; }

/* filtros */
.filtros { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.chip {
  font-size: var(--fs-sm); padding: 4px 11px; border-radius: 20px; cursor: pointer;
  border: 1px solid var(--borda-forte); background: var(--bg-elev); color: var(--txt-2);
  font-family: inherit; font-weight: 550; transition: all .12s;
}
.chip:hover { border-color: var(--verde-600); color: var(--verde-700); }
.chip.ativo { background: var(--verde-800); border-color: var(--verde-800); color: #fff; }
/* Chip que não mudaria nada no dado de hoje: fica à vista (a opção existe e
 * vai valer), mas não convida o clique. O motivo vai no `title`. */
.chip:disabled,
.chip:disabled:hover { opacity: .45; cursor: not-allowed; border-color: var(--borda-forte); color: var(--txt-2); }

/* listas */
.lista { display: flex; flex-direction: column; }
.lista-item {
  display: flex; gap: 12px; padding: 11px 15px; border-bottom: 1px solid var(--borda);
  align-items: flex-start; transition: background .1s;
}
.lista-item:last-child { border-bottom: none; }
.lista-item:hover { background: var(--bg-sub); }
.lista-item .corpo { flex: 1; min-width: 0; }
.lista-item .titulo { font-weight: 600; font-size: var(--fs); line-height: 1.4; }
.lista-item .meta { font-size: var(--fs-xs); color: var(--txt-3); margin-top: 3px; display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.lista-item .resumo { font-size: var(--fs-sm); color: var(--txt-2); margin-top: 5px; line-height: 1.5; }
.lista-item .lateral { flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: 5px; }

/* Lista de lançamentos (telas de preço proprietário): uma linha por registro.
   O .lateral em coluna empilhava preço, relógio, editar e ✕ e cada item
   passava de 120px; aqui tudo fica na mesma linha, e a lista rola em vez de
   empurrar o gráfico para baixo quando o dia tem dezenas de lançamentos. */
.lista.compacta { max-height: 360px; overflow-y: auto; }
.lista.compacta .lista-item { padding: 6px 12px; align-items: center; }
.lista.compacta .corpo { display: flex; align-items: baseline; gap: 10px; }
.lista.compacta .titulo { min-width: 90px; }
.lista.compacta .meta { margin-top: 0; }
.lista.compacta .lateral { flex-direction: row; align-items: center; gap: 8px; }
.lista.compacta .lateral .mono { min-width: 72px; text-align: right; }

.faixa { width: 3px; border-radius: 3px; flex: none; align-self: stretch; background: var(--borda-forte); }
.faixa.alta { background: var(--baixa); }
.faixa.media { background: var(--alerta); }
.faixa.baixa { background: var(--borda-forte); }

/* tabela */
table.tbl { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
.tbl th {
  text-align: left; font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: .5px;
  color: var(--txt-3); font-weight: 700; padding: 9px 12px; border-bottom: 1px solid var(--borda);
  background: var(--bg-sub); position: sticky; top: 0; z-index: 1;
}
.tbl td { padding: 9px 12px; border-bottom: 1px solid var(--borda); vertical-align: top; }
.tbl tr:last-child td { border-bottom: none; }
.tbl tbody tr:hover { background: var(--bg-sub); }
.num { font-variant-numeric: tabular-nums; text-align: right; }

/* ============================================================
   Ações da linha do relatório — Agenda e Calendário

   DUAS ALTURAS COM HIERARQUIA, e não três itens soltos no fluxo.

   A primeira versão largava um botão com borda ao lado de dois
   links pelados. Como o botão é `inline-flex`, ele dividia a
   linha com o link da automação e o da fonte caía sozinho
   embaixo, desalinhado — três pesos visuais competindo sem
   ordem. Agora a ação principal é um botão de largura cheia, o
   que lhe dá a mesma forma em toda linha, e as secundárias
   viram uma linha discreta embaixo.

   Centralizadas de propósito: a coluna de ações é a última, e
   uma pilha centrada num bloco de largura fixa lê como um
   grupo, enquanto encostada à esquerda pareceria continuação
   da coluna anterior.
   ============================================================ */
.cel-acoes { vertical-align: middle; }

.acao-principal {
  display: flex; width: 100%; justify-content: center; gap: 5px;
  margin-bottom: 4px;
}
.acao-ico { font-size: 11px; opacity: .75; }

/*
 * O menu de várias telas. `<details>` é bloco, então já ocupa a
 * largura da célula sem ajuda; o painel é ABSOLUTO porque, no
 * fluxo, abrir empurraria a linha do relatório para baixo — e é
 * a data dela que a Agenda existe para mostrar.
 */
details.acao-menu { display: block; position: relative; margin-bottom: 4px; }
details.acao-menu > .acao-principal { margin-bottom: 0; }
.acao-menu > summary {
  list-style: none; cursor: pointer; user-select: none;
}
/* O triângulo padrão do <details> não combina com um botão. */
.acao-menu > summary::-webkit-details-marker { display: none; }
.acao-menu > summary::marker { content: ''; }
.acao-menu[open] > summary { background: var(--bg-inset); border-color: var(--txt-3); }

.acao-lista {
  position: absolute; top: calc(100% + 3px); right: 0; z-index: 20;
  min-width: 212px; padding: 3px;
  background: var(--bg-elev); border: 1px solid var(--borda-forte);
  border-radius: var(--r); box-shadow: var(--sombra-2);
}
.acao-lista a {
  display: flex; align-items: center; gap: 7px;
  padding: 6px 8px; border-radius: var(--r-sm);
  font-size: var(--fs-sm); color: var(--txt); white-space: nowrap;
}
.acao-lista a:hover { background: var(--verde-050); text-decoration: none; }
html[data-tema="escuro"] .acao-lista a:hover { background: var(--bg-inset); }

.acoes-secundarias {
  display: flex; align-items: center; justify-content: center; gap: 6px;
  font-size: var(--fs-xs); white-space: nowrap;
}
.acoes-secundarias a { color: var(--txt-3); }
.acoes-secundarias a:hover { color: var(--verde-700); }
html[data-tema="escuro"] .acoes-secundarias a:hover { color: var(--verde-500); }
.acoes-secundarias .sep { color: var(--borda-forte); }

/* vazio */
.vazio { padding: 34px 20px; text-align: center; color: var(--txt-3); font-size: var(--fs-sm); }
.vazio .ico { font-size: 26px; display: block; margin-bottom: 8px; opacity: .5; }

/* toasts */
.toasts { position: fixed; bottom: 18px; right: 18px; z-index: 200; display: flex; flex-direction: column; gap: 9px; max-width: 380px; }
.toast {
  background: var(--bg-elev); border: 1px solid var(--borda); border-left: 3px solid var(--verde-600);
  border-radius: var(--r); box-shadow: var(--sombra-3); padding: 11px 13px;
  animation: entrar .25s cubic-bezier(.2, .9, .3, 1);
}
.toast.relatorio { border-left-color: var(--verde-600); }
.toast.noticia { border-left-color: var(--info); }
.toast.job { border-left-color: var(--alerta); }
.toast.automacao { border-left-color: var(--verde-700); }
.toast.erro { border-left-color: var(--baixa); }
.toast .t { font-weight: 650; font-size: var(--fs-sm); display: flex; gap: 7px; align-items: center; }
.toast .d { font-size: var(--fs-xs); color: var(--txt-2); margin-top: 4px; line-height: 1.45; }
.toast .x { margin-left: auto; cursor: pointer; color: var(--txt-3); border: none; background: none; font-size: 14px; padding: 0 2px; }
@keyframes entrar { from { opacity: 0; transform: translateX(22px); } to { opacity: 1; transform: none; } }

/* gaveta de notificações */
.gaveta {
  position: fixed; top: 0; right: 0; width: 400px; max-width: 92vw; height: 100vh; z-index: 150;
  background: var(--bg-elev); border-left: 1px solid var(--borda); box-shadow: var(--sombra-3);
  display: flex; flex-direction: column; transform: translateX(100%); transition: transform .22s cubic-bezier(.3, .8, .3, 1);
}
.gaveta.aberta { transform: none; }
.gaveta-topo { padding: 14px 16px; border-bottom: 1px solid var(--borda); display: flex; align-items: center; gap: 10px; }
.gaveta-corpo { overflow-y: auto; flex: 1; }
.veu { position: fixed; inset: 0; background: rgba(10, 25, 17, .38); z-index: 149; opacity: 0; pointer-events: none; transition: opacity .2s; }
.veu.on { opacity: 1; pointer-events: auto; }

/* terminal */
.terminal {
  background: #0b1410; color: #c9e6d5; font-family: var(--ff-mono); font-size: 12px;
  line-height: 1.58; padding: 12px 14px; border-radius: var(--r); overflow: auto;
  height: 380px; white-space: pre-wrap; word-break: break-word; border: 1px solid #1c3327;
}
.terminal .l-out { color: #c9e6d5; }
.terminal .l-err { color: #ff9d8f; }
.terminal .l-sys { color: #7fb89a; font-style: italic; }
.terminal .l-ok { color: #6ee7a8; font-weight: 600; }

/* morning call */
.mc-secao { border: 1px solid var(--borda); border-radius: var(--r-lg); margin-bottom: 14px; overflow: hidden; background: var(--bg-elev); }
.mc-secao-topo { display: flex; align-items: center; gap: 9px; padding: 10px 14px; background: var(--bg-sub); border-bottom: 1px solid var(--borda); }
.mc-secao-topo h3 { font-size: var(--fs); font-weight: 700; }
.mc-secao-topo .acoes { margin-left: auto; display: flex; gap: 6px; }
.mc-par { padding: 12px 14px; border-bottom: 1px dashed var(--borda); }
.mc-par:last-child { border-bottom: none; }
.mc-par-topo { display: flex; gap: 8px; align-items: center; margin-bottom: 7px; }
.mc-par-topo .idx { font-size: var(--fs-xs); color: var(--txt-3); font-weight: 700; }
.mc-par-topo .acoes { margin-left: auto; display: flex; gap: 4px; }
.mc-alertas { margin-top: 7px; display: flex; flex-direction: column; gap: 4px; }
.mc-alerta { font-size: var(--fs-xs); display: flex; gap: 6px; align-items: flex-start; line-height: 1.45; }
.mc-alerta.erro { color: var(--baixa); }
.mc-alerta.aviso { color: var(--alerta); }
.mc-preview {
  font-size: var(--fs); line-height: 1.6; background: var(--bg-sub);
  border: 1px solid var(--borda); border-radius: var(--r); padding: 16px; max-height: 620px; overflow: auto;
}
.mc-preview h2 { font-size: var(--fs-md); color: var(--verde-800); margin: 16px 0 8px; }
.mc-preview h2:first-child { margin-top: 0; }
html[data-tema="escuro"] .mc-preview h2 { color: var(--verde-500); }

/* medidor de qualidade */
.medidor { height: 6px; background: var(--bg-inset); border-radius: 4px; overflow: hidden; }
.medidor > i { display: block; height: 100%; background: var(--alta); transition: width .3s; }
.medidor.ruim > i { background: var(--baixa); }
.medidor.media > i { background: var(--alerta); }

/* diversos */
.linha { display: flex; align-items: center; gap: 8px; }
.linha.entre { justify-content: space-between; }
.esticar { flex: 1; }
.mono { font-family: var(--ff-mono); font-size: 12px; }
.silencioso { color: var(--txt-3); }
.pequeno { font-size: var(--fs-sm); }
.minusculo { font-size: var(--fs-xs); }
.negrito { font-weight: 650; }
.mt8 { margin-top: 8px; } .mt12 { margin-top: 12px; } .mt16 { margin-top: 16px; } .mt24 { margin-top: 24px; }
.mb8 { margin-bottom: 8px; } .mb12 { margin-bottom: 12px; } .mb16 { margin-bottom: 16px; }
.nowrap { white-space: nowrap; }
.divisor { height: 1px; background: var(--borda); margin: 14px 0; }
.rolar { overflow: auto; }
.max420 { max-height: 420px; }
.max520 { max-height: 520px; }

/* ============================================================
   Calendário anual — Agenda, período "Ano"

   Doze meses na mesma tela exigem célula pequena, então a leitura
   é por COR, não por texto: a cor diz o peso do dia e o número diz
   quantos relatórios saem. O detalhe do dia abre embaixo, ao clique.
   ============================================================ */
.cal-grade {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(196px, 1fr));
  gap: 10px;
}
.cal-mes {
  border: 1px solid var(--borda);
  border-radius: var(--r);
  background: var(--bg-sub);
  padding: 8px 9px 9px;
}
.cal-mes > h3 {
  font-size: var(--fs-sm);
  margin: 0 0 7px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  text-transform: capitalize;
  font-weight: 650;
}
.cal-mes > h3 .cal-conta { font-size: var(--fs-xs); color: var(--txt-3); font-weight: 500; }
.cal-mes.cal-mes-atual { border-color: var(--verde-600); background: var(--verde-050); }

.cal-semana, .cal-dias { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.cal-semana > span {
  font-size: 9px; text-align: center; color: var(--txt-3);
  font-weight: 700; padding-bottom: 3px;
}

.cal-dia {
  position: relative;
  aspect-ratio: 1 / 1;
  display: flex; align-items: center; justify-content: center;
  font-size: 10px; line-height: 1;
  border-radius: var(--r-sm);
  color: var(--txt-2);
  border: 1px solid transparent;
}
.cal-dia.cal-vazio { border-color: transparent; }
.cal-dia.cal-fds { color: var(--txt-3); background: var(--bg-inset); }

/*
 * Três intensidades, por SIGNIFICÂNCIA e não por prioridade pura.
 *
 * Prioridade sozinha não serve num calendário anual: o Daily Sales do USDA é
 * diário E prioridade alta, então todo dia útil ficaria marcado como forte e o
 * WASDE — que sai uma vez por mês e é o que move a semana — não se destacaria de
 * nada. A escala combina prioridade com raridade:
 *
 *   p3  relatório MENSAL de prioridade alta   → WASDE, CONAB, NOPA, SECEX
 *   p2  relatório SEMANAL de prioridade alta  → Crop Progress, CFTC, Export Sales
 *   p1  o resto (inclui a rotina diária)
 */
/* Fundo separado do resto para a amostra da legenda reusar a mesma cor. */
.cal-p1 {
  background: color-mix(in srgb, var(--verde-600) 11%, transparent);
  border-color: color-mix(in srgb, var(--verde-600) 22%, transparent);
}
.cal-p2 {
  background: color-mix(in srgb, var(--alerta) 18%, transparent);
  border-color: color-mix(in srgb, var(--alerta) 38%, transparent);
}
.cal-p3 { background: var(--baixa); border-color: var(--baixa); }

.cal-dia.cal-p1 { cursor: pointer; font-weight: 600; color: var(--verde-800); }
.cal-dia.cal-p2 { cursor: pointer; font-weight: 700; color: #7a3c06; }
.cal-dia.cal-p3 { cursor: pointer; font-weight: 800; color: #fff; }
.cal-dia.cal-p1:hover, .cal-dia.cal-p2:hover, .cal-dia.cal-p3:hover { border-color: var(--txt); }
.cal-dia.cal-hoje { box-shadow: 0 0 0 2px var(--verde-600); }
.cal-dia.cal-sel { box-shadow: 0 0 0 2px var(--txt); }

/* Contador de relatórios do dia, no canto. */
.cal-dia > i {
  position: absolute; top: -3px; right: -2px;
  font-style: normal; font-size: 8px; font-weight: 700;
  background: var(--bg-elev); color: var(--txt-2);
  border: 1px solid var(--borda); border-radius: 6px;
  padding: 0 2px; line-height: 1.3;
}
.cal-dia.cal-p3 > i { color: var(--baixa); border-color: color-mix(in srgb, var(--baixa) 45%, transparent); }

.cal-legenda { display: flex; flex-wrap: wrap; gap: 14px; align-items: center; }
.cal-legenda .cal-amostra {
  display: inline-block; width: 12px; height: 12px; border-radius: var(--r-sm);
  vertical-align: -2px; margin-right: 5px; border: 1px solid transparent;
}

/* ============================================================
   Botão que gira enquanto a requisição está em voo.

   Usado no ⟳ do painel de Automações: em localhost a resposta
   volta rápido demais para o olho registrar que algo aconteceu,
   e sem o giro o clique parece não ter feito nada.
   ============================================================ */
@keyframes hub-girar { to { transform: rotate(360deg); } }
.girando { animation: hub-girar .7s linear infinite; }

/* ============================================================
   Modal — manual da automação

   `<dialog>` nativo: o navegador já entrega backdrop, fechar no
   Esc e travar o foco. Só falta a aparência.
   ============================================================ */
.modal {
  border: 1px solid var(--borda);
  border-radius: var(--r-lg);
  background: var(--bg-elev);
  color: var(--txt);
  padding: 0;
  width: min(640px, calc(100vw - 32px));
  box-shadow: var(--sombra-3);
}
.modal::backdrop { background: rgba(10, 25, 17, .42); }
.modal-topo {
  display: flex; align-items: center; gap: 10px;
  padding: 13px 16px; border-bottom: 1px solid var(--borda);
}
.modal-topo h2 { font-size: var(--fs); font-weight: 650; }
.modal-corpo { padding: 15px 16px; max-height: 68vh; overflow-y: auto; }
.modal-secao { margin-bottom: 14px; }
.modal-secao:last-child { margin-bottom: 0; }
.modal-secao > h3 {
  font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: .6px;
  color: var(--txt-3); font-weight: 700; margin-bottom: 5px;
}
.modal-secao p { font-size: var(--fs-sm); line-height: 1.55; margin: 0; }

/* ================= gráfico do CFTC =================
 * A dica que segue o cursor no gráfico. Fica fora do canvas de propósito: texto
 * em DOM é selecionável, respeita o zoom do navegador e não entra no PNG
 * exportado — cruz e dica são estado de interação, não fazem parte da figura.
 */
.dica-grafico {
  position: absolute; pointer-events: none; z-index: 5;
  background: var(--bg-elev); border: 1px solid var(--borda-forte);
  border-radius: var(--r); box-shadow: var(--sombra-2);
  padding: 8px 10px; min-width: 150px;
  font-size: var(--fs-sm); line-height: 1.45;
}
.dica-grafico .dica-data {
  font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: .5px;
  color: var(--txt-3); font-weight: 700; margin-bottom: 5px;
}
/* O valor lidera e o rótulo segue: quem passa o cursor já sabe a série e quer o número. */
.dica-grafico .dica-linha {
  display: flex; justify-content: space-between; gap: 14px;
  color: var(--txt-2);
}
.dica-grafico .dica-linha b { font-variant-numeric: tabular-nums; color: var(--txt-2); font-weight: 600; }
.dica-grafico .dica-linha.forte b { color: var(--txt); font-weight: 700; }
/* Pastilha de cor por série (dica de "todos os adubos" do CFR e afins) — a
   identidade é a pastilha, o texto ao lado continua em tinta, nunca na cor da série. */
.dica-grafico .dica-swatch {
  display: inline-block; width: 8px; height: 8px; border-radius: 50%;
  margin-right: 5px; flex: none;
}

/* ------------------------------------------------------------------ */
/* grade de digitação de preços (dados proprietários)                   */
/* ------------------------------------------------------------------ */

/*
 * São 21 praças digitadas todo dia. A grade se adapta à largura em vez de
 * ter número fixo de colunas: em tela estreita vira duas colunas e continua
 * utilizável, em tela larga cabe a linha inteira sem rolar.
 */
.grade-precos {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(155px, 1fr));
  gap: 8px;
}

.celula-preco {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}

/* O rótulo corta com reticência em vez de empurrar a célula: "Santa Rita
   do Trivelato" ao lado de "Sinop" deformaria a grade inteira. */
.celula-preco > span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Número alinhado à direita e em fonte tabular — é assim que se confere
   uma coluna de preço de relance, e é o que a planilha já fazia. */
.celula-preco input {
  width: 100%;
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-family: var(--ff-mono, monospace);
}

.celula-preco input:focus { border-color: var(--verde-700); }

.toast.proprietario { border-left-color: var(--verde-700); }

/* ------------------------------------------------------------------ */
/* preços: cálculo por frete, meses de entrega e base exposta          */
/* ------------------------------------------------------------------ */

/*
 * Praça calculada pelo frete tem fundo próprio e não fica só "mais clara":
 * quem digita precisa ver de relance o que veio da conta e o que veio do
 * teclado, e a diferença some se for só uma variação de opacidade.
 * O valor continua editável — digitar por cima é o jeito de corrigir.
 */
.celula-preco input.calculado {
  background: color-mix(in srgb, var(--verde-700) 8%, transparent);
  border-color: color-mix(in srgb, var(--verde-700) 30%, transparent);
  color: var(--txt-2);
}

/* Os 18 meses da entrega, quebrando em várias linhas conforme a largura. */
.meses { display: flex; flex-wrap: wrap; gap: 5px; }
.meses .btn { min-width: 62px; justify-content: center; }

/*
 * A base tem 8 colunas e 100 linhas por página. Em tela estreita ela rola
 * DENTRO deste contêiner — sem isso a página inteira rolaria de lado, que
 * é o defeito que se paga por tabela larga em layout responsivo.
 */
.tabela-rolagem { overflow-x: auto; max-height: 460px; overflow-y: auto; }

.tabela { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
.tabela th {
  position: sticky; top: 0; z-index: 1;
  background: var(--bg-sub);
  text-align: left; font-weight: 600; font-size: var(--fs-xs);
  text-transform: uppercase; letter-spacing: .5px; color: var(--txt-3);
  padding: 7px 9px; white-space: nowrap;
  border-bottom: 1px solid var(--borda);
}
.tabela td { padding: 5px 9px; border-bottom: 1px solid var(--borda-sutil, #eee); white-space: nowrap; }
.tabela tbody tr:hover { background: var(--bg-sub); }
/* Número alinhado à direita e tabular: é assim que se confere uma coluna. */
.tabela td.num { text-align: right; font-variant-numeric: tabular-nums; font-family: var(--ff-mono, monospace); }

/* ------------------------------------------------------------------ */
/* dropzone do upload de relatório (Line Up)                            */
/* ------------------------------------------------------------------ */

.dropzone {
  border: 1.5px dashed var(--borda);
  border-radius: 8px;
  padding: 26px;
  text-align: center;
  cursor: pointer;
  transition: border-color .15s, background-color .15s;
}
.dropzone:hover, .dropzone.ativo { border-color: var(--verde-700); background: color-mix(in srgb, var(--verde-700) 6%, transparent); }
.dropzone.carregando { cursor: wait; border-style: solid; border-color: var(--verde-700); }

/* Aro que gira — reusa a animação `hub-girar` já existente, só desenha o
   círculo. Ao lado do texto de status durante o upload do Line Up. */
.spinner {
  display: inline-block;
  width: 14px; height: 14px;
  border: 2px solid var(--borda-forte);
  border-top-color: var(--verde-700);
  border-radius: 50%;
  vertical-align: -2px;
  margin-right: 6px;
  animation: hub-girar .7s linear infinite;
}

.mb4 { margin-bottom: 4px; }

/* ==========================================================================
   Mapas & Clima
   ==========================================================================
   Escopadas em `.tabela-clima` de propósito: `.acima`/`.abaixo` são palavras
   genéricas demais para soltar no espaço global de nomes, e o hub já usa
   `.abaixo` com outro sentido em outro lugar.

   Estas cores repetem, no TEXTO, a mesma leitura que o mapa dá: verde
   escuro é MAIS chuva, escuro acromático é MENOS. No mapa o seco clareia
   até o branco e o chuvoso vai do verde claro ao verde escuro, mas tom claro
   sobre folha branca é ilegível num número de 11 px — por isso o texto usa o
   par próprio TEXTO_DESVIO_* de `assets/js/lib/mapa-geo.js`, escuro dos dois
   lados. Não são o verde/vermelho de alta e baixa da casa: chover mais que a
   média não é "alta" de nada.

   QUEM AINDA USA ESTAS CLASSES é só a tabela de VIÉS de
   `#/chuva-previsto-realizado` (previu mais ou menos do que caiu), que é um
   corte binário no zero. A tabela de desvio contra a normal NÃO usa mais:
   ela pede a cor a `M.corDesvioTexto`, que gradua nos mesmos ±10/30/60% do
   mapa. As duas pareciam a mesma coisa e eram cortadas em réguas diferentes
   na MESMA tela — o desvio em ±15% aqui e em ±10/30/60% no mapa logo acima,
   então uma célula a +12% saía colorida num lugar e sem cor no outro.
   ========================================================================== */

/* Os mesmos polos do mapa de desvio, para o viés não falar outra língua.
 * Fora de sincronia com `RAMPA_SECA`/`RAMPA_MOLHADA` de mapa-geo.js, a mesma
 * leitura sai de uma cor no mapa e de outra na tabela. */
/* Seguem TEXTO_DESVIO_MOLHADO[0] e TEXTO_DESVIO_SECO[0] de mapa-geo.js — o
 * par de TEXTO, não a rampa do mapa: no mapa o polo seco é claro (branco é
 * seca extrema), e claro sobre folha branca é invisível num número de 11 px. */
.tabela-clima td.acima  { color: #195b3b; font-weight: 600; }
.tabela-clima td.abaixo { color: #4a4a4a; font-weight: 600; }
.tabela-clima td.total  { border-left: 1px solid var(--borda-sutil, #eee); font-weight: 600; }
.tabela-clima td.vazio,
.tabela-clima .vazio    { color: var(--txt-3); font-weight: 400; }

/* A linha da normal fecha a tabela e não é um ano como os outros: fundo
   próprio e régua em cima, para o olho não a somar à série. */
.tabela-clima tr.normal { background: var(--bg-sub); }
.tabela-clima tr.normal th,
.tabela-clima tr.normal td { border-top: 2px solid var(--borda-forte, #ddd); font-style: italic; }

/* O mapa é arrastável: sem isto o navegador seleciona texto ao arrastar e o
   cursor pisca entre "mover" e "selecionar" no meio do gesto. */
#mapa { touch-action: none; user-select: none; -webkit-user-select: none; }

/* ==========================================================================
   Relatório Semanal (`#/relatorio-semanal`)

   O editor reaproveita a casca de seção do Morning Call (`.mc-secao`); o que
   é próprio daqui são o item com data, a grade de figuras e a zona de colar.
   A folha que vai para o PDF NÃO usa estas classes — o estilo dela mora em
   `shared/relatorio-semanal.js` (`.rsd`), para a pré-visualização e a
   impressão saírem do mesmo lugar.
   ========================================================================== */
.rs-ico { width: 20px; height: 20px; object-fit: contain; }
html[data-tema="escuro"] .rs-ico { filter: invert(1); }
.rs-item {
  display: grid; grid-template-columns: 138px minmax(0, 1fr) auto; gap: 8px;
  padding: 9px 14px; border-bottom: 1px dashed var(--borda); align-items: start;
}
.rs-item textarea { min-height: 52px; resize: vertical; }
.rs-item-acoes { display: flex; flex-direction: column; gap: 2px; }
.rs-figs { display: flex; flex-wrap: wrap; gap: 10px; padding: 12px 14px; align-items: stretch; }
.rs-fig {
  width: 230px; border: 1px solid var(--borda); border-radius: var(--r); background: var(--bg-sub);
  padding: 6px; display: flex; flex-direction: column; gap: 5px;
}
.rs-fig.metade { width: 170px; }
.rs-fig img, .rs-fig-vazia {
  width: 100%; height: 120px; object-fit: contain; background: #fff; border-radius: var(--r-sm);
}
.rs-fig-vazia { display: flex; align-items: center; justify-content: center; color: var(--txt-3); font-size: var(--fs-xs); }
.rs-fig input { padding: 3px 6px; font-size: var(--fs-xs); }
.rs-drop {
  flex: 1 1 200px; min-height: 120px; border: 1.5px dashed var(--borda-forte); border-radius: var(--r);
  display: flex; align-items: center; justify-content: center; text-align: center; padding: 10px;
  color: var(--txt-3); font-size: var(--fs-sm); cursor: pointer; line-height: 1.5;
}
.rs-drop:hover { background: var(--bg-sub); }
.rs-drop.alvo, .rs-drop:focus { border-color: var(--verde-600); color: var(--txt); background: var(--bg-sub); outline: none; }
.rs-drop.ativo { border-style: solid; border-color: var(--verde-600); background: color-mix(in srgb, var(--verde-500) 10%, transparent); }
.rs-cfr { padding: 10px 14px; border-top: 1px dashed var(--borda); }
.rs-cfr-grade { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; margin-top: 8px; }
.rs-cfr-grade img { width: 100%; border: 1px solid var(--borda); border-radius: var(--r-sm); background: #fff; }
.rs-grupo + .rs-grupo { border-top: 1px dashed var(--borda); }
.rs-ind td { vertical-align: top; }
.rs-ind input { width: 100%; padding: 3px 7px; }
.rs-ind .rs-valor { display: flex; flex-direction: column; gap: 2px; min-width: 120px; }
.rs-ind td.rs-var { font-weight: 650; white-space: nowrap; padding-top: 9px; }
.rs-ind tr.rs-ind-cfg td { background: var(--bg-sub); }
.rs-invalido { border-color: var(--baixa) !important; }
.rs-dia { font-weight: 700; font-size: var(--fs-sm); padding: 10px 14px 3px; }
.rs-ag { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; gap: 8px; padding: 3px 14px; align-items: center; }
.rs-ag input[type="text"] { padding: 3px 7px; }
.rs-ag-novo { padding: 10px 14px 12px; border-top: 1px dashed var(--borda); margin-top: 8px; }
.rs-nav { display: flex; justify-content: space-between; gap: 10px; padding: 5px 0; font-size: var(--fs-sm); cursor: pointer; border-bottom: 1px solid var(--borda); }
.rs-nav:last-child { border-bottom: none; }
.rs-nav:hover span:first-child { text-decoration: underline; }
.rs-previa { background: #e9ecea; }
.rs-previa .rsd { width: 210mm; max-width: 100%; margin: 0 auto; padding: 14mm; box-shadow: 0 1px 6px rgba(0, 0, 0, .15); }
.rs-fig.grande { width: 200px; }
.rs-fig-origem { display: flex; align-items: center; gap: 5px; min-width: 0; }
.rs-fig-origem .tag { flex: none; }
.rs-fig-origem .btn { margin-left: auto; flex: none; }
.rs-fig-nome { font-size: var(--fs-xs); color: var(--txt-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.rs-fig-estado { color: var(--txt-3); min-height: 1.2em; }
.rs-fig[data-vaga] { cursor: pointer; border-style: dashed; }
.rs-fig[data-vaga] .rs-fig-vazia { color: var(--txt-2); }
.rs-fig.alvo, .rs-fig[data-vaga]:focus { border-color: var(--verde-600); border-style: solid; outline: none; }
.rs-fig.ativo { border-color: var(--verde-600); background: color-mix(in srgb, var(--verde-500) 10%, transparent); }
