/* ============================================================
   BSB MARKET TRACKER — Bloomberg Terminal Theme
   ============================================================ */

:root {
  --bg:          #050505;
  --bg-panel:    #0c0c0c;
  --bg-input:    #111111;
  --bg-hover:    #181818;
  --green:       #00e676;
  --green-dim:   #00b248;
  --orange:      #ff8f00;
  --orange-dim:  #e65100;
  /* Um degrau acima do --orange na mesma escala (Amber 800 -> 600). Existe
     para texto longo: o laranja cheio foi feito para rotulo curto, e uma
     coluna inteira de titulos nele cansa a leitura. */
  --orange-soft: #ffb300;
  --red:         #f44336;
  --yellow:      #ffd600;
  --cyan:        #00e5ff;
  --white:       #e0e0e0;
  --grey:        #616161;
  --grey-light:  #9e9e9e;
  --border:      #1c1c1c;
  --border-hi:   #2e7d32;
  --font:        'Courier New', Consolas, 'Lucida Console', monospace;
  --font-size:   13px;
  --topbar-h:    32px;
  --cmdbar-h:    30px;
}

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

html, body {
  height: 100%;
  overflow: hidden;        /* page itself never scrolls */
  background: var(--bg);
  color: var(--green);
  font-family: var(--font);
  font-size: var(--font-size);
  line-height: 1.4;
  -webkit-font-smoothing: none;
}

/* ── Scrollbar ────────────────────────────────────────────── */
::-webkit-scrollbar { width: 6px; }
::-webkit-scrollbar-track { background: var(--bg); }
::-webkit-scrollbar-thumb { background: var(--border-hi); }

/* ── Layout shell ─────────────────────────────────────────── */
.bsb-shell {
  display: flex;
  flex-direction: column;
  height: 100vh;           /* fixed viewport height — never grows */
  overflow: hidden;
}

.bsb-main {
  flex: 1;
  min-height: 0;           /* allows flex child to shrink below content size */
  padding: 12px 16px;
  overflow-y: auto;
  overflow-x: hidden;
  /* A folga de rodape era para a cmdbar, que subiu para o topo. O que sobra
     embaixo e a saida de comandos, que e `position: fixed` e so existe quando
     ha o que mostrar — reservar altura para ela deixaria um vao permanente no
     fim de toda pagina. */
  padding-bottom: 8px;
}

/* ── Top bar ──────────────────────────────────────────────── */
.bsb-topbar {
  height: var(--topbar-h);
  background: #000;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  padding: 0 12px;
  gap: 0;
  flex-shrink: 0;
  white-space: nowrap;
  overflow: hidden;
}

.bsb-topbar__brand {
  color: var(--orange);
  font-weight: bold;
  font-size: 12px;
  letter-spacing: 1px;
  padding-right: 16px;
  border-right: 1px solid var(--border);
}

.bsb-topbar__nav {
  display: flex;
  align-items: center;
  flex: 1;
  padding: 0 12px;
  gap: 2px;
}

.bsb-topbar__nav a {
  color: var(--grey-light);
  text-decoration: none;
  padding: 2px 10px;
  font-size: 11px;
  letter-spacing: 0.5px;
  border: 1px solid transparent;
  text-transform: uppercase;
  transition: color 0.1s, border-color 0.1s;
}
.bsb-topbar__nav a:hover,
.bsb-topbar__nav a.active {
  color: var(--orange);
  border-color: var(--orange-dim);
}

/* Item visivel e inerte enquanto o e-mail nao foi confirmado.

   Esconde-lo seria pior: quem acabou de se cadastrar nao descobriria que o
   produto tem feed e relatorios, e a tela pareceria vazia por defeito. Apagado
   e com o titulo explicando, a razao fica evidente.

   pointer-events: none bloqueia o clique ANTES do onclick, entao o handler nem
   chega a rodar e nao e preciso um segundo caminho de decisao no JavaScript.
   Isto e aparencia: quem barra de verdade e o servidor. */
.bsb-topbar__nav a.bsb-topbar__nav--bloqueado,
.bsb-topbar__nav a.bsb-topbar__nav--bloqueado:hover {
  color: var(--grey);
  border-color: transparent;
  pointer-events: none;
  opacity: .45;
  cursor: not-allowed;
}

.bsb-topbar__right {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 11px;
  color: var(--grey-light);
  padding-left: 12px;
  border-left: 1px solid var(--border);
}

.bsb-topbar__user { color: var(--white); }
.bsb-topbar__clock { color: var(--yellow); letter-spacing: 1px; }
.bsb-topbar__status-dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--green); display: inline-block;
  animation: pulse 2s infinite;
}
@keyframes pulse {
  0%, 100% { opacity: 1; }
  50%  { opacity: 0.3; }
}

/* ── Command bar ──────────────────────────────────────────── */
/* Logo abaixo da topbar, e nao mais no rodape. A borda inferior separa a
   barra do conteudo; a superior separava do conteudo quando ela estava
   embaixo, e mante-la desenharia um traco duplo contra a topbar. */
.bsb-cmdbar {
  height: var(--cmdbar-h);
  background: #000;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  padding: 0 12px;
  gap: 8px;
  flex-shrink: 0;
}

.bsb-cmdbar__label {
  color: var(--orange);
  font-size: 11px;
  letter-spacing: 1px;
}

.bsb-cmdbar__input {
  flex: 1;
  background: transparent;
  border: none;
  outline: none;
  color: var(--green);
  font-family: var(--font);
  font-size: 11px;
  caret-color: var(--green);
}

/* Copiar o comando digitado. min-width fixo porque o botao troca o icone pelo
   retorno curto (OK, VAZIO, ERRO) por um instante, e sem largura reservada o
   'WS: ONLINE' ao lado saltaria a cada clique. */
.bsb-cmdbar__copy {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 40px;
  height: 18px;
  padding: 0 5px;
  background: transparent;
  border: 1px solid var(--border);
  color: var(--grey);
  font-family: var(--font);
  font-size: 10px;
  line-height: 1;
  letter-spacing: 0.5px;
  cursor: pointer;
  flex-shrink: 0;
}
.bsb-cmdbar__copy:hover,
.bsb-cmdbar__copy:focus-visible {
  color: var(--orange);
  border-color: var(--orange);
  outline: none;
}

/* Aviso passageiro na barra: estado do socket e atividade dos agendadores
   dividem o mesmo lugar. Sao a mesma pergunta — "o canal esta vivo?" — e o
   rotulo permanente que existia antes ("WS: ONLINE") gastava espaco fixo para
   dizer que estava tudo bem, que e justamente a mensagem que ninguem le.

   max-width para o aviso longo nao empurrar o campo de comando: a barra agora
   divide UMA linha entre digitar e informar, e digitar tem precedencia. */
.bsb-cmdbar__aviso {
  font-size: 10px; letter-spacing: .5px; white-space: nowrap;
  color: var(--cyan);
  flex-shrink: 0;
  max-width: 45%;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* RUNNING so aparece quando a rodada passa de um segundo, entao quando aparece
   e porque de fato demorou: pulsar ali informa, nao enfeita. */
.bsb-cmdbar__aviso--running { color: var(--orange); animation: bsb-sched-pisca 1s ease-in-out infinite; }
.bsb-cmdbar__aviso--done    { color: var(--green); }
.bsb-cmdbar__aviso--failed  { color: var(--red); }

@keyframes bsb-sched-pisca {
  0%, 100% { opacity: 1; }
  50%      { opacity: .45; }
}
@media (prefers-reduced-motion: reduce) {
  .bsb-cmdbar__aviso--running { animation: none; }
}

/* ── Panel ────────────────────────────────────────────────── */
.bsb-panel {
  background: var(--bg-panel);
  border: 1px solid var(--border);
  margin-bottom: 12px;
}

.bsb-panel__header {
  background: #0f0f0f;
  border-bottom: 1px solid var(--border);
  padding: 4px 10px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.bsb-panel__title {
  color: var(--orange);
  font-size: 11px;
  font-weight: bold;
  letter-spacing: 1px;
  text-transform: uppercase;
}

.bsb-panel__badge {
  font-size: 10px;
  color: var(--grey);
  letter-spacing: 0.5px;
}

.bsb-panel__body {
  padding: 10px 12px;
  /* Contexto de posicionamento para o modo tomada da grade de séries manuais
     (issue #112): ela usa `position: absolute; inset: 0` para cobrir o painel,
     e sem isto cobriria a janela inteira. */
  position: relative;
}

/* ── Grid ─────────────────────────────────────────────────── */
.bsb-grid { display: grid; gap: 12px; }
.bsb-grid-2 { grid-template-columns: 1fr 1fr; }
.bsb-grid-3 { grid-template-columns: 1fr 1fr 1fr; }

@media (max-width: 900px) {
  .bsb-grid-2, .bsb-grid-3 { grid-template-columns: 1fr; }
}

/* ── Auth page (login / signup) ───────────────────────────── */
.bsb-auth {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: calc(100vh - var(--topbar-h) - var(--cmdbar-h));
  padding: 20px;
}

.bsb-auth__box {
  width: 100%;
  max-width: 420px;
  border: 1px solid var(--border-hi);
  background: var(--bg-panel);
}

.bsb-auth__header {
  background: #000;
  border-bottom: 1px solid var(--border-hi);
  padding: 10px 16px;
  text-align: center;
}

/* Cabecalho com a marca: a imagem ocupa o header inteiro, sem padding. */
.bsb-auth__header--brand {
  padding: 0;
  background: transparent;
  line-height: 0;
}

.bsb-auth__brand {
  display: block;
  width: 100%;
  height: auto;
}

/* Faixa de contexto sob a marca: diz em qual das telas de auth o usuario esta. */
.bsb-auth__context {
  border-bottom: 1px solid var(--border-hi);
  color: var(--grey-light);
  font-size: 10px;
  letter-spacing: 1px;
  padding: 6px 16px;
  text-align: center;
}

.bsb-auth__body { padding: 20px 16px; }

/* ── Landing publica (issue #78) ──────────────────────────── */
.bsb-landing__hero {
  background: var(--bg-panel);
  margin-bottom: 16px;
  padding-bottom: 4px;
  text-align: center;
}

.bsb-landing__brand {
  display: block;
  width: 100%;
  max-width: 520px;
  height: auto;
  margin: 0 auto;
}

.bsb-landing__title {
  color: var(--orange);
  font-size: 20px;
  font-weight: bold;
  letter-spacing: 3px;
  margin: 14px 0 8px;
}

.bsb-landing__lead {
  color: var(--white);
  margin: 0 auto;
  max-width: 780px;
  padding: 0 16px;
}

.bsb-landing__lead strong { color: var(--yellow); }

.bsb-landing__cta { justify-content: center; padding: 16px 0 12px; }

.bsb-landing__section {
  border-bottom: 1px solid var(--border);
  color: var(--grey-light);
  font-size: 11px;
  font-weight: normal;
  letter-spacing: 2px;
  margin: 20px 0 10px;
  padding-bottom: 4px;
}

.bsb-landing .bsb-panel__body { color: var(--grey-light); }

.bsb-landing__nota {
  color: var(--grey);
  font-size: 11px;
  margin-bottom: 12px;
}

/* A tabela de cobertura rola dentro de si mesma. Sao duas colunas de texto e
   64 linhas: sem este container, em tela estreita a pagina inteira ganharia
   rolagem horizontal, que e o defeito que mais estraga leitura no celular. */
.bsb-landing__cobertura {
  overflow-x: auto;
  width: 100%;
}

.bsb-landing__cobertura table { min-width: 520px; }

/* O nome da cobertura e a coluna que o olho percorre: fica amarela como os
   rotulos do resto do terminal, e sem quebrar no meio quando ha espaco. */
.bsb-landing__cobertura td:first-child {
  color: var(--yellow);
  white-space: nowrap;
  vertical-align: top;
}

.bsb-landing__cobertura td:first-child strong { color: inherit; }

.bsb-landing__cobertura td:last-child { color: var(--grey-light); }

@media (max-width: 720px) {
  /* Em tela estreita, forcar nowrap na primeira coluna empurraria a segunda
     para fora; melhor deixar quebrar e manter as duas visiveis. */
  .bsb-landing__cobertura td:first-child { white-space: normal; }
  .bsb-landing__cobertura table { min-width: 0; }
}

.bsb-landing__footer {
  border-top: 1px solid var(--border);
  color: var(--grey);
  display: flex;
  flex-wrap: wrap;
  font-size: 10px;
  gap: 8px;
  justify-content: space-between;
  letter-spacing: 1px;
  margin-top: 20px;
  padding: 10px 0;
}

.bsb-landing__footer a { color: var(--grey-light); text-decoration: none; }
.bsb-landing__footer a:hover { color: var(--orange); }

.bsb-auth__footer {
  border-top: 1px solid var(--border);
  padding: 10px 16px;
  text-align: center;
  font-size: 11px;
  color: var(--grey);
}

.bsb-auth__footer a {
  color: var(--orange);
  text-decoration: none;
}
.bsb-auth__footer a:hover { text-decoration: underline; }

/* ── Form elements ────────────────────────────────────────── */
.bsb-form-group {
  display: flex;
  align-items: center;
  border-bottom: 1px solid var(--border);
  padding: 8px 0;
}

.bsb-form-group:last-of-type { border-bottom: none; }

.bsb-form-group label {
  color: var(--orange);
  font-size: 11px;
  letter-spacing: 1px;
  width: 100px;
  flex-shrink: 0;
  text-transform: uppercase;
}

.bsb-form-group .bsb-arrow {
  color: var(--grey);
  margin-right: 6px;
  font-size: 12px;
}

.bsb-input {
  flex: 1;
  background: transparent;
  border: none;
  outline: none;
  color: var(--white);
  font-family: var(--font);
  font-size: 13px;
  caret-color: var(--green);
  padding: 2px 0;
}

.bsb-input::placeholder { color: var(--grey); }
.bsb-input:focus { color: var(--green); }

.bsb-select {
  flex: 1;
  background: transparent;
  border: none;
  outline: none;
  color: var(--white);
  font-family: var(--font);
  font-size: 13px;
  cursor: pointer;
  -webkit-appearance: none;
}
.bsb-select option { background: #111; color: var(--white); }

/* ── Buttons ──────────────────────────────────────────────── */
.bsb-btn-row {
  display: flex;
  gap: 8px;
  justify-content: center;
  margin-top: 16px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}

.bsb-btn {
  font-family: var(--font);
  font-size: 11px;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  padding: 6px 20px;
  border: 1px solid;
  cursor: pointer;
  transition: background 0.1s, color 0.1s;
  text-decoration: none;
  display: inline-block;
}

.bsb-btn-primary {
  background: var(--orange);
  border-color: var(--orange);
  color: #000;
  font-weight: bold;
}
.bsb-btn-primary:hover { background: var(--orange-dim); border-color: var(--orange-dim); }
.bsb-btn-primary:disabled { background: var(--grey); border-color: var(--grey); color: #333; cursor: not-allowed; }

.bsb-btn-secondary {
  background: transparent;
  border-color: var(--border-hi);
  color: var(--green);
}
.bsb-btn-secondary:hover { background: var(--bg-hover); }

.bsb-btn-danger {
  background: transparent;
  border-color: var(--red);
  color: var(--red);
}
.bsb-btn-danger:hover { background: var(--red); color: #000; }

/* ── Alert / feedback ─────────────────────────────────────── */
.bsb-alert {
  padding: 8px 12px;
  font-size: 11px;
  letter-spacing: 0.5px;
  margin-top: 12px;
  border-left: 3px solid;
  display: none;
}
.bsb-alert.visible { display: block; }
.bsb-alert-error  { border-color: var(--red);    color: var(--red);    background: rgba(244,67,54,.08); }
.bsb-alert-success{ border-color: var(--green);  color: var(--green);  background: rgba(0,230,118,.06); }
.bsb-alert-warn   { border-color: var(--yellow); color: var(--yellow); background: rgba(255,214,0,.06); }
.bsb-alert-info   { border-color: var(--cyan);   color: var(--cyan);   background: rgba(0,229,255,.06); }

/* ── Loading spinner ──────────────────────────────────────── */
.bsb-loading {
  display: none;
  align-items: center;
  gap: 8px;
  color: var(--grey-light);
  font-size: 11px;
  letter-spacing: 1px;
  margin-top: 12px;
  justify-content: center;
}
.bsb-loading.visible { display: flex; }
.bsb-spinner {
  width: 10px; height: 10px;
  border: 2px solid var(--border);
  border-top-color: var(--orange);
  border-radius: 50%;
  animation: spin .6s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ── KV rows (key-value) ──────────────────────────────────── */
.bsb-kv { display: flex; gap: 6px; padding: 3px 0; font-size: 12px; }
.bsb-kv__key   { color: var(--grey-light); min-width: 130px; }
.bsb-kv__val   { color: var(--white); }
.bsb-kv__val.green  { color: var(--green); }
.bsb-kv__val.orange { color: var(--orange); }
.bsb-kv__val.red    { color: var(--red); }
.bsb-kv__val.yellow { color: var(--yellow); }

/* ── Status badge ─────────────────────────────────────────── */
.bsb-badge {
  display: inline-block;
  padding: 1px 8px;
  font-size: 10px;
  letter-spacing: 1px;
  border: 1px solid;
  text-transform: uppercase;
}
.bsb-badge-active   { color: var(--green);  border-color: var(--green-dim); }
.bsb-badge-pending  { color: var(--yellow); border-color: var(--yellow); }
.bsb-badge-freemium { color: var(--grey-light); border-color: var(--grey); }
.bsb-badge-paid     { color: var(--orange); border-color: var(--orange); }
.bsb-badge-warn     { color: var(--yellow); border-color: var(--yellow); }

/* ── Banner (page-level alerts) ───────────────────────────── */
.bsb-banner {
  padding: 6px 16px;
  font-size: 11px;
  letter-spacing: 0.5px;
  border-bottom: 1px solid;
  display: none;
}
.bsb-banner.visible { display: block; }
.bsb-banner-success { background: rgba(0,230,118,.08); border-color: var(--green-dim); color: var(--green); }
.bsb-banner-error   { background: rgba(244,67,54,.08); border-color: var(--red);       color: var(--red);   }
.bsb-banner-warn    { background: rgba(255,214,0,.06); border-color: var(--yellow);    color: var(--yellow); }

/* ── Dashboard specific ───────────────────────────────────── */
.bsb-section-label {
  color: var(--grey);
  font-size: 10px;
  letter-spacing: 2px;
  text-transform: uppercase;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 10px;
}

.bsb-tag {
  display: inline-block;
  font-size: 9px;
  letter-spacing: 1px;
  padding: 1px 6px;
  border: 1px solid var(--border);
  color: var(--grey-light);
  text-transform: uppercase;
  margin-right: 4px;
}

.bsb-divider {
  border: none;
  border-top: 1px solid var(--border);
  margin: 12px 0;
}

/* ── Action row on dashboard ──────────────────────────────── */
.bsb-action-row {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 10px;
}

/* ── Empty state ──────────────────────────────────────────── */
.bsb-empty {
  padding: 24px;
  text-align: center;
  color: var(--grey);
  font-size: 11px;
  letter-spacing: 0.5px;
}
.bsb-empty__icon { font-size: 24px; margin-bottom: 8px; display: block; }

/* ── Cmdbar output ────────────────────────────────────────── */
/* Column layout so the close button stays put while the text scrolls. */
.bsb-cmdbar__output {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  max-height: 320px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: #080808;
  border-top: 1px solid var(--border-hi);
  border-bottom: 1px solid var(--border);
  z-index: 90;
}
/* O botao flutua sobre o canto em vez de ocupar uma faixa propria acima do
   texto. A faixa fazia sentido quando a barra de comandos vinha logo abaixo e
   as duas somavam duas linhas de moldura antes de qualquer conteudo. */
.bsb-cmdbar__close {
  position: absolute;
  top: 4px;
  right: 6px;
  z-index: 1;
  /* Opaco, e nao transparente: ele flutua sobre a saida, e a primeira linha
     passando por tras dele desenharia texto cortado no meio de um botao. */
  background: #080808;
  border: 1px solid var(--border);
  color: var(--grey);
  font-family: var(--font);
  font-size: 11px;
  line-height: 1;
  padding: 2px 7px;
  cursor: pointer;
}
.bsb-cmdbar__close:hover,
.bsb-cmdbar__close:focus-visible {
  color: var(--orange);
  border-color: var(--orange);
  outline: none;
}
#cmd-output__inner {
  flex: 1 1 auto;
  overflow-y: auto;
  /* O topo ganhou 6px porque o botao de fechar deixou de ter faixa propria e
     passou a flutuar sobre este canto. */
  padding: 6px 12px 8px;
  font-size: 11px;
  line-height: 1.55;
  color: var(--white);
  white-space: pre;
  font-family: var(--font);
}

/* ── Admin ────────────────────────────────────────────────── */
.bsb-admin-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 6px 0;
  gap: 8px;
}
.bsb-admin-toolbar__title {
  font-size: 11px;
  letter-spacing: 1.5px;
  color: var(--orange);
  white-space: nowrap;
}
.bsb-admin-toolbar__actions {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}
.bsb-admin-result {
  margin-top: 6px;
  overflow-x: auto;
  min-height: 20px;
}
.bsb-admin-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 11px;
  letter-spacing: 0.3px;
}
.bsb-admin-table th {
  text-align: left;
  color: var(--grey-light);
  border-bottom: 1px solid var(--border);
  padding: 4px 8px;
  white-space: nowrap;
  letter-spacing: 1px;
  font-size: 10px;
}
.bsb-admin-table td {
  padding: 4px 8px;
  border-bottom: 1px solid var(--border);
  color: var(--white);
  white-space: nowrap;
  max-width: 260px;
  overflow: hidden;
  text-overflow: ellipsis;
}
.bsb-admin-table tr:hover td { background: var(--bg-hover); }
/* Conexao do WhatsApp (issue #61). Pares chave-valor densos, no lugar de uma
   tabela: sao seis linhas de estado, e cabecalho para elas seria cerimonia. */
.bsb-admin-kv { font-size: 11px; margin: 6px 0; }
.bsb-admin-kv__row { display: flex; gap: 10px; padding: 1px 0; }
.bsb-admin-kv__k { color: var(--grey); min-width: 180px; }
/* Os tons fora da tabela: o estado da conexao precisa deles no par acima. */
.bsb-admin-kv .cell-green, .bsb-admin-empty.cell-green { color: var(--green); }
.bsb-admin-kv .cell-red,   .bsb-admin-empty.cell-red   { color: var(--red); }

/* O QR em fundo claro de proposito: o leitor do celular erra em tema escuro,
   e aqui a legibilidade da camera vence a consistencia visual. */
.bsb-wa__qr { margin: 10px 0; }
.bsb-wa__qr img {
  width: 260px; height: 260px; image-rendering: pixelated;
  background: #fff; padding: 8px; border: 1px solid var(--border);
}
.bsb-wa__qr-hint { color: var(--grey-light); font-size: 11px; margin-bottom: 6px; max-width: 520px; }

.bsb-admin-table .cell-green  { color: var(--green); }
.bsb-admin-table .cell-yellow { color: var(--yellow); }
.bsb-admin-table .cell-red    { color: var(--red); }
.bsb-admin-table .cell-grey   { color: var(--grey); }
.bsb-admin-empty {
  padding: 10px 0;
  font-size: 11px;
  color: var(--grey);
  letter-spacing: 0.5px;
}

/* ── Feed cards ───────────────────────────────────────────────── */
.bsb-feed-card {
  border: 1px solid var(--border);
  padding: 10px 12px;
  margin-bottom: 8px;
}
.bsb-feed-card:last-child { margin-bottom: 0; }
.bsb-feed-card__header {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 6px;
  font-size: 10px;
  letter-spacing: 0.8px;
}
.bsb-feed-card__type {
  color: var(--orange);
  letter-spacing: 1px;
}
.bsb-feed-card__urgency {
  font-size: 10px;
  letter-spacing: 1px;
}
.bsb-feed-card__urgency.cell-red    { color: var(--red); }
.bsb-feed-card__urgency.cell-yellow { color: var(--yellow); }
.bsb-feed-card__urgency.cell-grey   { color: var(--grey); }
.bsb-feed-card__date {
  color: var(--grey);
  margin-left: auto;
  white-space: nowrap;
}
.bsb-feed-card__title {
  font-size: 13px;
  color: var(--white);
  letter-spacing: 0.5px;
  line-height: 1.4;
  margin-bottom: 2px;
}
.bsb-feed-card__subtitle {
  font-size: 11px;
  color: var(--grey-light);
  margin-bottom: 6px;
  line-height: 1.4;
}
.bsb-feed-card__items {
  margin-top: 8px;
  border-top: 1px solid var(--border);
  padding-top: 6px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.bsb-feed-item {
  font-size: 11px;
  color: var(--grey-light);
  line-height: 1.5;
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  align-items: baseline;
}
.bsb-feed-item__section {
  color: var(--orange);
  font-size: 10px;
  letter-spacing: 0.8px;
  white-space: nowrap;
}
.bsb-feed-item__section::after { content: " —"; }
.bsb-feed-item__bullet {
  flex: 1;
  min-width: 0;
}
.bsb-feed-item__source {
  color: var(--grey);
  font-size: 10px;
  white-space: nowrap;
  text-decoration: none;
}
.bsb-feed-item__source:hover { color: var(--orange); text-decoration: underline; }

/* ==========================================================================
   PAINEL DE NOTÍCIAS
   Duas telas: a lista densa e o leitor. Sem token de cor novo: a manchete usa
   o âmbar da paleta, a entidade clicável usa o ciano, e o item já lido cai
   para o cinza. Não confundir com .bsb-feed, que é o feed de publicações
   da Buysidebrazil.
   ========================================================================== */

.bsb-news__bar {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 6px 10px;
  background: var(--bg-input);
  border-bottom: 1px solid var(--border);
}
.bsb-news__bar-label { color: var(--green); font-size: 11px; letter-spacing: 1px; }
.bsb-news__search {
  flex: 1 1 240px; min-width: 180px;
  background: transparent; border: none; outline: none;
  color: var(--orange); font-family: var(--font); font-size: 13px;
}
.bsb-news__search::placeholder { color: var(--grey); }

.bsb-news__chips { display: flex; gap: 5px; flex-wrap: wrap; }
.bsb-news__chip {
  display: inline-flex; align-items: center; gap: 5px;
  background: var(--orange-dim); color: #000;
  font-size: 10px; letter-spacing: .5px;
  padding: 1px 6px; border-radius: 2px; cursor: pointer;
}
.bsb-news__chip:hover { background: var(--orange); }

.bsb-news__sort { display: flex; gap: 2px; }
.bsb-news__tab {
  background: var(--bg-panel); color: var(--grey-light);
  border: 1px solid var(--border); cursor: pointer;
  font-family: var(--font); font-size: 10px; letter-spacing: 1px;
  padding: 2px 9px;
}
.bsb-news__tab--on { background: var(--border-hi); color: #fff; border-color: var(--border-hi); }

.bsb-news__layout { display: flex; align-items: stretch; min-height: 320px; }

/* ---- trilho esquerdo ---- */
.bsb-news__rail {
  position: relative; flex: 0 0 170px; padding: 8px 0 12px;
  border-right: 1px solid var(--border); background: var(--bg-panel);
  max-height: 620px; overflow-y: auto;
}
.bsb-news__rail--collapsed { flex-basis: 22px; overflow: hidden; }
.bsb-news__rail--collapsed > *:not(.bsb-news__rail-toggle) { display: none; }
.bsb-news__rail-toggle {
  position: absolute; top: 4px; right: 4px;
  background: transparent; border: none; cursor: pointer;
  color: var(--grey); font-family: var(--font); font-size: 12px;
}
.bsb-news__rail-toggle:hover { color: var(--white); }
.bsb-news__rail-group {
  color: var(--orange); font-size: 10px; letter-spacing: 1.2px;
  padding: 10px 10px 3px;
}
.bsb-news__rail-item {
  display: flex; justify-content: space-between; gap: 6px;
  padding: 2px 10px; cursor: pointer;
  color: var(--cyan); font-size: 12px;
  text-decoration: none;
}
.bsb-news__rail-item:hover { background: var(--bg-hover); }
.bsb-news__rail-item--on   { background: var(--border-hi); color: #fff; }
.bsb-news__rail-count      { color: var(--grey); font-size: 10px; }
.bsb-news__rail-item--on .bsb-news__rail-count { color: #cfe8cf; }

/* Feed da Buysidebrazil (issue #62). Reusa o desenho da tela de noticias; o que
   e proprio daqui e o tema na linha e o anexo, que noticia de RSS nao tem. */
/*
  O tema, onde quer que apareça: na lista do FEED e na tabela de RELATÓRIOS.

  O negrito mora aqui, e não na regra da lista, porque nos dois lugares ele faz
  a mesma coisa — separar rótulo de assunto entre textos que dividem a mesma
  cor. Deixá-lo só num dos dois daria a dois painéis irmãos duas leituras
  diferentes do mesmo dado.

  `min-width` e `text-overflow` só valem na lista: na tabela o span é inline
  dentro de um <td>, e nenhum dos dois se aplica a inline não substituído.
*/
.bsb-bsbfeed__tema {
  color: var(--orange); font-size: 10px; letter-spacing: .5px; font-weight: bold;
  min-width: 13ch; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/*
  A coluna do tema na LISTA do feed.

  Ela tinha só `min-width: 13ch` e nenhuma base flex, então encolhia até 13ch
  assim que o título disputava espaço — e 13ch corta o que a casa mais publica.
  Medido em produção: o percentil 90 do comprimento é 14 caracteres, e os três
  temas de maior volume passam disso.

      MONITOR DIÁRIO DE INFLAÇÃO   26 car., 146 posts  ->  MONITOR DIÁR…
      POLÍTICA MONETÁRIA           18 car.,  98 posts  ->  POLÍTICA MON…
      ESTADOS UNIDOS               14 car., 268 posts  ->  ESTADOS UNID…

  Base fixa e não elástica, porque a lista inteira é desenhada em colunas fixas:
  o título começando num x diferente a cada linha é o que torna uma lista densa
  ilegível de relance. 26ch cobre o maior tema de hoje, e o ellipsis fica como
  rede para o tema novo que passar disso.

  Só a largura aqui: o negrito é do tema em qualquer painel e mora na classe
  base, acima.
*/
.bsb-news__row .bsb-bsbfeed__tema {
  flex: 0 0 26ch;
}

/*
  O título no feed, um degrau mais claro que o laranja cheio.

  Escopado a `#bsb-list` e não aplicado a `.bsb-news__headline` inteira: a mesma
  classe desenha a lista de NOTÍCIAS (`#news-list`), que é outra tela e outro
  conteúdo — RSS de terceiros, e não publicação da casa.

  Vem depois da regra do tema de propósito: agora que o tema é negrito, os dois
  já se distinguem pelo peso, e o título podia abrir mão de parte da intensidade
  sem sumir. Antes do negrito, clarear o título o teria deixado abaixo do tema
  na hierarquia da linha.

  O `:not()` não é adorno. Um seletor com id vale mais que `.bsb-news__row--read
  .bsb-news__headline`, então sem ele esta regra venceria o cinza de "já lido" e
  o amarelo de "flash" — estados que hoje só a lista de NOTÍCIAS aplica, e que
  passariam a não funcionar no dia em que o feed os usasse, sem nada apontando
  para cá. Declarar que a cor vale só no estado normal custa uma linha e remove
  a armadilha.
*/
#bsb-list .bsb-news__row:not(.bsb-news__row--read):not(.bsb-news__row--flash)
  .bsb-news__headline {
  color: var(--orange-soft);
}
/* O clipe diz que ha PDF ou imagem antes de abrir: quem procura a Rotina
   Matinal reconhece a linha sem entrar em cada uma. */
.bsb-bsbfeed__clipe { color: var(--cyan); font-size: 10px; white-space: nowrap; }

/* O corpo do post preserva as quebras. Os topicos sao a estrutura do texto e
   nao enfeite: colapsa-los transformaria uma analise de oito pontos num
   paragrafo unico. Justificar tambem estraga lista. */
#bsb-reader-body { white-space: pre-wrap; text-align: left; }

.bsb-bsbfeed__anexos { margin-top: 12px; border-top: 1px solid var(--border); padding-top: 8px; }
.bsb-bsbfeed__anexo { display: flex; gap: 8px; align-items: center; padding: 3px 0; font-size: 11px; }
.bsb-bsbfeed__anexo a { color: var(--cyan); text-decoration: none; }
.bsb-bsbfeed__anexo a:hover { text-decoration: underline; }
.bsb-bsbfeed__tam { color: var(--grey); font-size: 10px; }
/* Imagem embutida: a tabela da agenda economica chega como imagem, e vira link
   faria o leitor perder justamente o conteudo. */
.bsb-bsbfeed__anexo img {
  max-width: 100%; border: 1px solid var(--border); background: #fff;
}

/* Item em destaque (issue #140).

   O modelo e o Alert Catcher do terminal antigo: uma faixa fixa acima da lista
   com o ultimo item dos seis temas de analise, e a lista rolando embaixo. Ela
   nao substitui a lista — por isso a borda esquerda em vez de caixa fechada,
   que anuncia destaque sem cortar a coluna em duas.

   A manchete e maior que a da lista de proposito: se tivesse o mesmo corpo de
   10px, o bloco viraria so um item com fundo diferente, e o ponto e que ele se
   leia de longe, sem procurar. */
/* Dentro do header a faixa ocupa tudo: o padding e a borda de baixo ja sao
   do header, e repeti-los desenharia duas molduras. */
.bsb-panel__header--destaque {
  display: block;
  padding: 0;
}

/* A ESCALA DO BLOCO SAI DAQUI.

   Os quatro tamanhos de dentro sao `em`, entao mudar esta linha move os quatro
   juntos e na mesma proporcao. Antes eram 10/13/11/10 em pixel solto, e subir
   o bloco significava acertar quatro numeros sem errar a razao entre eles.

   13px e o corpo base do terminal (--font-size): a faixa e conteudo de leitura,
   e nao rotulo, entao ela parte do mesmo tamanho do resto do texto em vez dos
   10px da lista densa logo abaixo. */
.bsb-bsbfeed__destaque {
  border-left: 3px solid var(--orange-soft);
  background: var(--bg-hover);
  font-size: 13px;
  padding: .8em 1em .85em;
  margin: 0;
  cursor: pointer;
}
.bsb-bsbfeed__destaque:hover { background: var(--bg-input); }

/* Cabecalho: tema, quando, quem. Mesma ordem da referencia. */
.bsb-bsbfeed__destaque-cab {
  display: flex; gap: .6em; align-items: baseline;
  font-size: 1em; margin-bottom: .25em;
}
.bsb-bsbfeed__destaque-tema {
  color: var(--orange); font-weight: bold; letter-spacing: .04em;
}
.bsb-bsbfeed__destaque-quando { color: var(--grey); }
/* Idade em vez de hora quando o destaque passa de um dia: o principio
   analitico da casa manda todo numero carregar o periodo, e "14:37" num item
   de 23 dias atras sugere novidade que nao existe. */
.bsb-bsbfeed__destaque-idade { color: var(--yellow); }
.bsb-bsbfeed__destaque-autor {
  color: var(--grey); margin-left: auto;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 30ch;
}

.bsb-bsbfeed__destaque-titulo {
  color: var(--orange-soft); font-size: 1.3em; font-weight: bold;
  line-height: 1.25; margin-bottom: .3em;
}

/* Quatro linhas, cortadas pelo navegador. O servidor ja manda o trecho pronto
   em uma linha so; o clamp resolve a largura, que ele nao tem como saber. */
.bsb-bsbfeed__destaque-corpo {
  color: var(--white); font-size: 1.1em; line-height: 1.45;
  display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical;
  overflow: hidden;
}
.bsb-bsbfeed__destaque-ler {
  display: block; text-align: right; color: var(--cyan);
  font-size: 1em; margin-top: .3em;
}

/* A troca pisca uma vez. Reusa a duracao e a cor do --flash da lista, e some
   para quem pediu menos movimento. */
.bsb-bsbfeed__destaque--flash { animation: bsb-news-pulso .9s ease-out 1; }
@media (prefers-reduced-motion: reduce) {
  .bsb-bsbfeed__destaque--flash { animation: none; }
}

@media (max-width: 900px) {
  .bsb-bsbfeed__destaque-autor { display: none; }
  .bsb-bsbfeed__destaque-corpo { -webkit-line-clamp: 3; }
}

/* Painel RELATÓRIOS: os documentos anexados aos posts.

   Tabela, e nao a lista densa do feed. O que identifica um relatorio e o nome
   do arquivo, o tamanho e a data, e essas tres colunas so se comparam de
   relance quando estao alinhadas — numa lista corrida o olho perde a coluna. */
.bsb-reports__table { width: 100%; font-size: 11px; }
.bsb-reports__table td { padding: 4px 8px; vertical-align: top; }
/* O nome do arquivo e a chave da linha: e por ele que se reconhece a Rotina
   Matinal daquela terca. */
.bsb-reports__file { color: var(--fg); white-space: nowrap; }
/* O titulo do post e contexto, nao identidade: cede espaco e nao empurra as
   colunas da direita para fora da tela. */
.bsb-reports__post {
  color: var(--grey); max-width: 34ch;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.bsb-reports__baixar { color: var(--cyan); text-decoration: none; white-space: nowrap; }
.bsb-reports__baixar:hover { text-decoration: underline; }

/* Nenhuma coluna pode empurrar a pagina para os lados; a tabela rola sozinha. */
#rep-list { overflow-x: auto; }

/* Chegou noticia neste veiculo ou tema, mas fora do recorte que esta na tela.
   Sem este sinal a tela fica muda quando o filtro do usuario e restritivo, e
   mudez se confunde com sistema parado — ele nao teria como saber se o filtro
   e estreito ou se a coleta morreu.

   Pulsa e para: animacao infinita num trilho de 20 itens vira ruido de fundo e
   o olho deixa de registrar justamente o que ela deveria destacar. */
@keyframes bsb-news-pulso {
  0%   { background: var(--green-dim); color: #000; }
  100% { background: transparent; }
}
.bsb-news__rail-item--nova {
  animation: bsb-news-pulso 2s ease-out 3;
  border-left: 2px solid var(--green);
}
/* Urgente insiste mais e em vermelho: e a mesma distincao da pilula. */
@keyframes bsb-news-pulso-urgente {
  0%   { background: var(--red); color: #fff; }
  100% { background: transparent; }
}
.bsb-news__rail-item--urgente {
  animation: bsb-news-pulso-urgente 1.2s ease-out 6;
  border-left: 2px solid var(--red);
}

@media (prefers-reduced-motion: reduce) {
  /* Quem pediu menos movimento continua precisando do aviso: a borda fica, a
     pulsacao sai. */
  .bsb-news__rail-item--nova,
  .bsb-news__rail-item--urgente { animation: none; }
}

/* ---- área principal ---- */
.bsb-news__main { flex: 1 1 auto; min-width: 0; padding: 6px 0 10px; position: relative; }

.bsb-news__pill {
  position: sticky; top: 4px; z-index: 5;
  margin: 0 auto 6px; width: fit-content;
  background: var(--green-dim); color: #000;
  font-size: 11px; letter-spacing: .5px;
  padding: 2px 12px; border-radius: 10px; cursor: pointer;
}
.bsb-news__pill:hover { background: var(--green); }

/* Urgente furou a regra de nao mexer na lista de quem le, e a cor precisa
   dizer isso: verde e "chegou coisa", vermelho e "interrompi voce". */
.bsb-news__pill--flash { background: var(--red); color: #fff; }
.bsb-news__pill--flash:hover { background: var(--red); filter: brightness(1.15); }

.bsb-news__volume {
  color: var(--grey-light); font-size: 11px;
  padding: 0 10px 6px;
}

/* A lista é o coração: uma linha por matéria, sem quebra, colunas fixas. */
.bsb-news__list { list-style: none; margin: 0; padding: 0; }
.bsb-news__row {
  display: flex; align-items: baseline; gap: 8px;
  padding: 1px 10px; cursor: pointer;
  white-space: nowrap;
}
.bsb-news__row:hover { background: var(--bg-hover); }
.bsb-news__num {
  flex: 0 0 34px; text-align: right;
  color: var(--grey); font-size: 12px;
}
.bsb-news__headline {
  flex: 1 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis;
  color: var(--orange); font-size: 13px;
}
.bsb-news__row--read  .bsb-news__headline { color: var(--grey); }
.bsb-news__row--flash .bsb-news__headline { color: var(--yellow); text-transform: uppercase; }
.bsb-news__src  { flex: 0 0 46px; color: var(--grey-light); font-size: 11px; }
.bsb-news__time { flex: 0 0 44px; color: var(--grey-light); font-size: 11px; text-align: right; }

.bsb-news__more { text-align: center; padding: 10px; }

/* ---- leitor ---- */
.bsb-news__reader { padding: 4px 16px 14px; max-width: 900px; }
.bsb-news__reader-nav { display: flex; gap: 6px; align-items: center; margin-bottom: 10px; }
.bsb-news__reader-pos { color: var(--grey); font-size: 11px; margin-left: 6px; }
.bsb-news__reader-title {
  color: var(--white); font-size: 17px; font-weight: bold;
  line-height: 1.35; margin: 0 0 4px;
}
.bsb-news__reader-meta { color: var(--grey-light); font-size: 11px; margin-bottom: 12px; }
.bsb-news__reader-body {
  color: var(--orange); font-size: 13px; line-height: 1.6;
  text-align: justify;
}
.bsb-news__reader-body em {              /* trecho casado pela busca */
  font-style: normal; color: var(--yellow); background: rgba(255,214,0,.12);
}
.bsb-news__nobody { color: var(--grey); font-style: italic; }

/* Entidade clicável: o termo no meio do texto que leva a outra tela. */
.bsb-news__ent {
  color: var(--cyan); cursor: pointer;
  border-bottom: 1px dotted var(--cyan);
}
.bsb-news__ent:hover { background: rgba(0,229,255,.12); }

.bsb-news__related { margin-top: 14px; color: var(--grey); font-size: 11px; }
.bsb-news__related a {
  color: var(--cyan); text-decoration: none; margin-right: 12px; cursor: pointer;
}
.bsb-news__related a:hover { text-decoration: underline; }

.bsb-news__source-link {
  display: inline-block; margin-top: 14px;
  color: var(--green); font-size: 12px; letter-spacing: .5px; text-decoration: none;
}
.bsb-news__source-link:hover { color: #fff; }

@media (max-width: 780px) {
  .bsb-news__rail { display: none; }
  .bsb-news__src  { display: none; }
  /* Numa tela estreita a coluna fixa de 26ch comeria o título. Volta ao
     percentil 90 medido (14 car.), que ainda cobre nove em cada dez temas. */
  .bsb-news__row .bsb-bsbfeed__tema { flex: 0 0 14ch; }
}

/* ==========================================================================
   PAINEL DE FONTE (viewsource)
   Um painel para todas as fontes. Sem token de cor novo: reaproveita a paleta
   Bloomberg-like já definida no topo deste arquivo.
   ========================================================================== */

.bsb-sv__context {
  display: flex; flex-wrap: wrap; gap: 14px; align-items: baseline;
  padding: 5px 12px;
  background: var(--bg-input);
  border-bottom: 1px solid var(--border);
  font-size: 11px; color: var(--grey-light);
}
.bsb-sv__context b { color: var(--white); font-weight: normal; }
.bsb-sv__context .sv-provider { color: var(--orange); }

/* KPI tiles. O valor é o número; a comparação abaixo é o que o torna legível. */
.bsb-sv__stats {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(178px, 1fr));
  gap: 8px; margin-bottom: 12px;
}
.bsb-sv__stat {
  border: 1px solid var(--border); border-left-width: 3px;
  background: var(--bg-panel); padding: 6px 10px;
}
.bsb-sv__stat--pos     { border-left-color: var(--green); }
.bsb-sv__stat--neg     { border-left-color: var(--red); }
.bsb-sv__stat--neutral { border-left-color: var(--yellow); }
.bsb-sv__stat-label { color: var(--grey);       font-size: 10px; letter-spacing: 1px; }
.bsb-sv__stat-value { color: var(--white);      font-size: 17px; margin: 2px 0; }
.bsb-sv__stat-cmp   { color: var(--grey-light); font-size: 10px; line-height: 1.3; }

.bsb-sv__charts {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(420px, 1fr));
  gap: 10px; margin-bottom: 12px;
}
/* position:relative contém o botão de PNG, que é absoluto. */
.bsb-sv__chart { border: 1px solid var(--border); background: var(--bg-panel);
                 padding: 6px; position: relative; }
.bsb-sv__chart-title    { color: var(--orange);     font-size: 11px; letter-spacing: 1px; padding-right: 86px; }
.bsb-sv__chart-subtitle { color: var(--grey-light); font-size: 10px; margin-bottom: 4px; padding-right: 86px; }
/* Altura fixa: gráfico que cresce com o dado desloca a tabela abaixo dele. */
.bsb-sv__chart-canvas   { width: 100%; height: 280px; }

.bsb-sv__tablebar {
  display: flex; align-items: center; gap: 8px;
  padding: 4px 8px; background: var(--bg-input); border: 1px solid var(--border);
  border-bottom: none;
}
.bsb-sv__tablebar-label { color: var(--green); font-size: 10px; letter-spacing: 1px; }
.bsb-sv__filter {
  flex: 1 1 auto; background: transparent; border: none; outline: none;
  color: var(--orange); font-family: var(--font); font-size: 12px;
}
.bsb-sv__filter::placeholder { color: var(--grey); }
.bsb-sv__rowcount { color: var(--grey-light); font-size: 10px; white-space: nowrap; }

/* Altura fixa com rolagem própria: tabela longa não empurra o rodapé. */
.bsb-sv__tablewrap { max-height: 420px; overflow: auto; border: 1px solid var(--border); }
.bsb-sv__tablewrap thead th {
  position: sticky; top: 0; z-index: 2;
  background: var(--bg-input);
  cursor: pointer; white-space: nowrap;
}
.bsb-sv__tablewrap thead th:hover { color: var(--white); }
.bsb-sv__sort { color: var(--cyan); }
.bsb-sv__num  { text-align: right; }
.bsb-sv__unit { color: var(--grey); font-size: 9px; }

.bsb-sv__downloads { display: flex; gap: 8px; align-items: center; margin-top: 10px; }
.bsb-sv__downloads-label { color: var(--grey); font-size: 10px; letter-spacing: 1px; }

.bsb-sv__tech { margin-top: 12px; color: var(--grey-light); font-size: 11px; }
.bsb-sv__tech summary { color: var(--orange); cursor: pointer; letter-spacing: 1px; font-size: 10px; }
.bsb-sv__tech-row { display: flex; gap: 10px; padding: 1px 0; }
.bsb-sv__tech-key { color: var(--grey); min-width: 150px; }

@media (max-width: 780px) {
  .bsb-sv__charts { grid-template-columns: 1fr; }
}

/* Célula de drill-down: leva a outra tela do próprio terminal. */
.bsb-sv__link { color: var(--cyan); cursor: pointer; border-bottom: 1px dotted var(--cyan); }
.bsb-sv__link:hover { background: rgba(0,229,255,.12); }

/* Link para fora do produto (issue #56): o post original na plataforma.
   Deliberadamente distinto do drill-down interno — um sai do terminal e o
   outro não, e confundir os dois faz o usuário perder o contexto sem esperar. */
.bsb-sv__ext { color: var(--yellow); text-decoration: none; white-space: nowrap; }
.bsb-sv__ext:hover { text-decoration: underline; }

/* Texto longo na célula (issue #56): fechado ocupa uma linha, aberto mostra o
   post inteiro com as quebras que o autor escreveu. O ponto é ler sem sair do
   terminal para a plataforma, e por isso `pre-wrap` — colapsar as quebras
   destruiria a formatação justamente dos posts que precisam ser lidos por
   inteiro. */
.bsb-sv__long {
  cursor: pointer;
  max-width: 46ch;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  border-bottom: 1px dotted var(--grey);
}
.bsb-sv__long:hover { color: var(--white); }
.bsb-sv__long:focus-visible { outline: 1px solid var(--cyan); }
.bsb-sv__long.is-open {
  max-width: 72ch;
  white-space: pre-wrap; overflow: visible; word-break: break-word;
  border-bottom: none; color: var(--white);
}
/* Aberta, a célula deixa de empurrar a linha para uma altura só. */
.bsb-sv__tablewrap td:has(> .bsb-sv__long.is-open) { vertical-align: top; }

/* Badge de status e plataforma. O tom vem de um mapa fechado no JS: valor
   inesperado do banco cai em neutro e nunca vira nome de classe. */
.bsb-sv__badge {
  display: inline-block; padding: 0 4px; border-radius: 2px;
  font-size: 9px; letter-spacing: .5px; white-space: nowrap;
  border: 1px solid currentColor;
}
.bsb-sv__badge--ok      { color: var(--green); }
.bsb-sv__badge--warn    { color: var(--yellow); }
.bsb-sv__badge--bad     { color: var(--red); }
.bsb-sv__badge--neutral { color: var(--grey-light); }

/* Painel de chat (issue #59).

   Deliberadamente sem bolha, sem avatar e sem canto arredondado: chat de
   produto de mercado se parece com log de terminal, e o resto da interface e
   denso e monoespacado. Quem fala se distingue pelo prefixo e pela cor, que e
   como um terminal sempre distinguiu. */
.bsb-chat__log {
  max-height: 420px; overflow-y: auto;
  border: 1px solid var(--border); padding: 8px;
  font-size: 12px; line-height: 1.5;
}
.bsb-chat__msg { padding: 3px 0; white-space: pre-wrap; word-break: break-word; }
.bsb-chat__msg--user { color: var(--green); }
.bsb-chat__msg--assistant { color: var(--grey-light); }
.bsb-chat__msg--erro { color: var(--red); }
.bsb-chat__quem {
  color: var(--orange); font-size: 10px; letter-spacing: 1px;
  display: inline-block; min-width: 5ch;
}
/* O rodape de cada resposta: modelo, ferramentas e tokens. Numero sem
   referencia e dado, nao analise — aqui a referencia e o custo da resposta. */
.bsb-chat__meta { color: var(--grey); font-size: 10px; padding: 1px 0 6px 5ch; }

/* O relato do que esta acontecendo enquanto a resposta nao existe. Uma barra
   girando nao diz se o sistema trabalha ou travou; isto diz qual ferramenta
   foi chamada e o que voltou. */
.bsb-chat__progresso {
  border-left: 2px solid var(--orange); padding: 4px 8px; margin-top: 6px;
  color: var(--grey-light); font-size: 11px; max-height: 140px; overflow-y: auto;
}
.bsb-chat__evento { padding: 1px 0; }
.bsb-chat__evento b { color: var(--cyan); font-weight: normal; }
.bsb-chat__evento--erro { color: var(--red); }

.bsb-chat__corte {
  color: var(--yellow); font-size: 11px; padding: 4px 0;
}

.bsb-chat__entrada { display: flex; gap: 8px; align-items: center; margin-top: 10px; }
.bsb-chat__prompt { color: var(--orange); }
.bsb-chat__input {
  flex: 1 1 auto; background: var(--bg-input); border: 1px solid var(--border);
  outline: none; padding: 4px 8px;
  color: var(--green); font-family: var(--font); font-size: 12px;
}
.bsb-chat__input:focus { border-color: var(--cyan); }
.bsb-chat__input::placeholder { color: var(--grey); }
.bsb-chat__input:disabled { color: var(--grey); }

/* Painel de politico (issue #51). Uma secao por bloco do perfil, densas e
   empilhadas: o padrao operacional do produto e ler tudo numa rolagem, nao
   caçar informacao atras de aba. */
.bsb-pol__secao { margin-top: 14px; }
.bsb-pol__secao-titulo {
  color: var(--orange); font-size: 10px; letter-spacing: 1px;
  border-bottom: 1px solid var(--border); padding-bottom: 3px; margin-bottom: 4px;
}
.bsb-pol__secao-titulo span { color: var(--grey); letter-spacing: 0; }

/* Limite de fonte nao e ausencia de fato, e a diferenca precisa saltar. */
.bsb-pol__notas { margin-top: 14px; color: var(--yellow); font-size: 11px; }
.bsb-pol__notas div { padding: 2px 0; }

/* Comando sugerido no estado vazio: clicavel, como o badge CMD >. */
.bsb-pol__cmd {
  color: var(--bg); background: var(--orange); padding: 1px 5px; border-radius: 2px;
  cursor: pointer; font-size: 11px; display: inline-block; margin-top: 2px;
}
.bsb-pol__cmd:hover { background: var(--white); }

/* Comando em execucao. Sem sinal nenhum, um comando de dez segundos e
   indistinguivel de um que falhou — e foi assim que ingestpolitica pareceu nao
   produzir saida. O tempo decorrido aparece a partir de 2s, que e quando a
   espera comeca a incomodar. */
.bsb-cmd-busy {
  color: var(--yellow);
  font-size: 11px;
  padding: 1px 0;
  white-space: pre;
}

/* Comando recomendado, em qualquer texto da interface. O badge preenche o
   cmdbar e nao executa: quem dispara ingestao ou cura e o usuario. O desenho
   fica aqui, e nao em cada tela, para sair igual em toda a interface. */
.bsb-cmd { display: inline-flex; align-items: center; gap: 4px; vertical-align: baseline; }
.bsb-cmd__txt {
  color: var(--white); background: rgba(255,255,255,.06);
  padding: 0 4px; border-radius: 2px; font-size: 11px; white-space: nowrap;
}
.bsb-cmd__badge {
  color: var(--bg); background: var(--orange);
  padding: 0 5px; border-radius: 2px; cursor: pointer;
  font-size: 10px; font-weight: bold; letter-spacing: .5px; white-space: nowrap;
  user-select: none;
}
.bsb-cmd__badge:hover { background: var(--white); }
.bsb-cmd__badge:focus { outline: 1px solid var(--cyan); outline-offset: 1px; }

/* Linha de drill-down: abre a série que a linha identifica. Existe além do
   link de célula porque numa tela de série de séries o destino é a combinação
   das colunas, não uma delas. O ▸ é a afordância; sem ele a linha só reage
   depois que o ponteiro já está em cima. */
.bsb-sv__row--go { cursor: pointer; }
.bsb-sv__row--go:hover  td { background: rgba(0,229,255,.07); }
.bsb-sv__row--go:focus  { outline: 1px solid var(--cyan); outline-offset: -1px; }
.bsb-sv__row--go:focus  td { background: rgba(0,229,255,.10); }
.bsb-sv__go { color: var(--cyan); text-align: right; width: 14px; padding-left: 4px; }

/* Entidade que abre uma fonte de dados, contra a que abre um gráfico. */
.bsb-news__ent--sourceview  { border-bottom-style: solid; }
.bsb-news__ent--news_filter { color: var(--green); border-bottom-color: var(--green); }

/* Barra de ações do gráfico: baixar e copiar. Fica no canto superior direito
   da caixa do gráfico, e o title/subtítulo reservam espaço para ela. */
.bsb-chart-actions {
  position: absolute; top: 6px; right: 6px; z-index: 2;
  display: flex; gap: 4px;
}
.bsb-chart-actions__btn {
  font-size: 9px; padding: 2px 8px; opacity: .8;
  display: inline-flex; align-items: center; gap: 4px;
}
.bsb-chart-actions__btn:hover:not(:disabled) { opacity: 1; }
.bsb-chart-actions__btn:disabled { opacity: .4; cursor: default; }

/* ============================================================
   CREDENCIAIS DE REDES SOCIAIS (issue #53)

   Um card por plataforma. A densidade continua a do terminal, mas a ajuda de
   cada campo é texto corrido e não caber tudo numa linha aqui é o ponto: a
   issue exige que o operador preencha sem abrir documentação, e ajuda cortada
   em "..." é ajuda que ninguém lê.
   ============================================================ */

.bsb-social-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(360px, 1fr));
  gap: 12px;
}

.bsb-social-card {
  border: 1px solid var(--border);
  background: var(--bg-panel);
  padding: 10px 12px;
}

.bsb-social-card__head {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 8px; margin-bottom: 4px;
}
.bsb-social-card__name {
  color: var(--orange); font-size: 12px; letter-spacing: 1px;
}
.bsb-social-card__status { font-size: 11px; white-space: nowrap; }

.bsb-social-card__lib { font-size: 10px; color: var(--grey); margin-bottom: 6px; }
.bsb-social-card__lib code,
.bsb-social-warn code,
.bsb-social-help code { color: var(--cyan); font-family: var(--font); }

/* Ressalva permanente da plataforma: expiração, 2FA, biblioteca parada. Fica no
   corpo do card e não num tooltip — é a informação que muda a decisão de qual
   conta usar, e tooltip é onde se guarda o que não se quer que seja lido. */
.bsb-social-warn,
.bsb-social-note {
  font-size: 10px; line-height: 1.45;
  border-left: 2px solid var(--border-hi);
  padding: 4px 8px; margin-bottom: 6px;
  background: rgba(255,255,255,.02);
}
.bsb-social-note { color: var(--grey-light); }
.bsb-social-warn.cell-red    { border-left-color: var(--red); }
.bsb-social-warn.cell-yellow { border-left-color: var(--yellow); }

.bsb-social-meta {
  border: 1px solid var(--border); padding: 6px 8px; margin-bottom: 8px;
  font-size: 10px;
}
.bsb-social-meta__row {
  display: flex; justify-content: space-between; gap: 12px; padding: 1px 0;
}
.bsb-social-meta__key { color: var(--grey); }

.bsb-social-field { margin-bottom: 10px; }
.bsb-social-field label { display: block; }

/* Obrigatório e opcional distinguidos por rótulo, e não só por cor: a issue
   pede que o campo informe seu nível, e cor sozinha não informa quem não a
   distingue. */
.bsb-social-req,
.bsb-social-opt {
  font-size: 9px; letter-spacing: 0; text-transform: lowercase;
  border: 1px solid var(--border); padding: 0 4px; margin-left: 6px;
}
.bsb-social-req { color: var(--orange); border-color: var(--orange-dim); }
.bsb-social-opt { color: var(--grey); }

.bsb-social-help {
  font-size: 10px; color: var(--grey-light); line-height: 1.45; margin-top: 3px;
}

.bsb-social-fielderr { font-size: 10px; color: var(--red); margin-top: 2px; }

.bsb-social-card__actions {
  display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px;
}
.bsb-social-card__actions .bsb-btn { font-size: 10px; padding: 3px 10px; }

/* O que o teste faz e o que ele não coleta, sempre visível junto do botão:
   ler isso depois de clicar não ajudaria. */
.bsb-social-card__testhelp {
  font-size: 10px; color: var(--grey); line-height: 1.45; margin-top: 6px;
}


/* Acoes por linha na tabela de usuarios do admin.

   Botoes pequenos e lado a lado: a coluna e a ultima e nao pode empurrar as
   outras. O de remover fica vermelho no hover, e nao sempre — uma coluna com
   cinquenta botoes vermelhos vira ruido e o olho deixa de registrar o aviso
   justamente na linha em que ele importa. */
.bsb-admin-acoes { white-space: nowrap; }

/* A CELULA DE ACOES NAO E TEXTO, E O RECORTE DELA ESCONDIA O ULTIMO BOTAO.

   `.bsb-admin-table td` traz `max-width: 260px; overflow: hidden`, que existe
   para impedir que titulo ou e-mail longo estoure a largura da tabela. Numa
   coluna de botoes isso recorta — e recorta pelo fim, que e onde ficam as
   acoes destrutivas.

   Medido na tabela do DATABASE, com os cinco botoes do vinculo por upload:
   DESCRICAO ~81px, ARQUIVO ~71, TEMA ~54, DESATIVAR ~81, APAGAR ~65, somando
   ~352px numa celula de 260px. Sobravam os tres primeiros inteiros, DESATIVAR
   pela metade e APAGAR invisivel. O botao estava no DOM o tempo todo.

   `width: 1%` com `nowrap` e o jeito de a coluna pedir exatamente o que os
   botoes ocupam: as colunas de texto ficam com o resto e continuam
   truncando com reticencias, que e o que aquelas regras queriam. */
.bsb-admin-table td.bsb-admin-acoes {
  max-width: none;
  overflow: visible;
  text-overflow: clip;
  width: 1%;
}

/* Rede de seguranca: com muitas colunas largas a tabela pode passar do painel,
   e ai a ultima acao volta a ficar fora de alcance por outro caminho. Rolar
   dentro da propria caixa mantem todo botao acessivel sem a pagina rolar de
   lado. */
.bsb-admin-rolagem { overflow-x: auto; }

.bsb-admin-acao {
  font-size: 9px; padding: 2px 8px; margin-right: 4px; letter-spacing: .5px;
}
.bsb-admin-acao--perigo:hover {
  color: var(--red); border-color: var(--red);
}

/* Campo recusado pela validacao de dominio no cadastro. A borda vermelha diz
   ONDE esta o problema; a mensagem, qual e. Uma sem a outra deixa o usuario
   procurando. */
.bsb-input--invalido {
  border-color: var(--red);
  color: var(--red);
}
/* ISSUES 79-81: viewers de anexos, PDFs e graficos. */
.bsb-bsbfeed__anexo--image { align-items: flex-start; }
.bsb-bsbfeed__image-wrap { position: relative; display: inline-block; max-width: 100%; }
.bsb-bsbfeed__fullscreen {
  position: absolute; top: 6px; right: 6px; width: 26px; height: 24px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--border); background: rgba(0,0,0,.74); color: var(--cyan);
  cursor: pointer; opacity: .88;
}
.bsb-bsbfeed__fullscreen:hover { opacity: 1; }
.bsb-bsbfeed__arquivo { color: var(--fg); overflow-wrap: anywhere; }
.bsb-bsbfeed__acao {
  border: 1px solid var(--border); background: var(--panel-2); color: var(--cyan);
  font: inherit; font-size: 10px; line-height: 1; padding: 4px 7px;
  text-decoration: none; cursor: pointer; white-space: nowrap;
}
.bsb-bsbfeed__acao:hover { border-color: var(--cyan); text-decoration: none; }

.bsb-reports__acoes { display: flex; justify-content: flex-end; gap: 6px; white-space: nowrap; }
.bsb-reports__acao,
.bsb-reports__baixar {
  border: 1px solid var(--border); background: var(--panel-2); color: var(--cyan);
  font: inherit; font-size: 10px; line-height: 1; padding: 4px 7px;
  text-decoration: none; cursor: pointer; white-space: nowrap;
}
.bsb-reports__acao:hover,
.bsb-reports__baixar:hover { border-color: var(--cyan); text-decoration: none; }

/* Edicao inline no painel RELATORIOS (issue #83) */
.bsb-reports__input {
  background: var(--bg); color: var(--white); border: 1px solid var(--border-hi);
  font: inherit; font-size: 11px; padding: 3px 5px; width: 100%; max-width: 420px;
}
.bsb-reports__input:focus { border-color: var(--cyan); outline: none; }

.bsb-reports__edit-acoes {
  display: flex; gap: 6px; align-items: center; margin-top: 5px; flex-wrap: wrap;
}

/* O erro aparece na propria linha: um alerta tiraria o admin do painel e
   faria perder filtro, paginacao e posicao de rolagem. */
.bsb-reports__erro { color: var(--red); font-size: 10px; }

/* Marca do que foi corrigido a mao. Sem ela o admin nao distingue o que ja
   revisou do que continua como o parser deixou. */
.bsb-reports__curado { color: var(--yellow); font-size: 10px; margin-left: 4px; cursor: help; }

.mt-embedded-viewer-host { width: 100%; padding-top: 8px; }
.mt-media-viewer,
.mt-chart-viewer {
  position: relative; display: none; width: 100%; margin: 10px 0 14px; padding: 0;
  background: transparent;
}
.mt-media-viewer--open,
.mt-chart-viewer--open { display: block; }
.mt-media-viewer__dialog,
.mt-chart-viewer__dialog {
  width: 100%; display: flex; flex-direction: column; min-height: 0;
  background: var(--panel); border: 1px solid var(--border);
}
.mt-media-viewer__dialog { height: min(76vh, 780px); min-height: 420px; }
.mt-chart-viewer__dialog { height: min(82vh, 860px); min-height: 460px; }
.mt-media-viewer__bar,
.mt-chart-viewer__bar {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 8px 10px; border-bottom: 1px solid var(--border); background: var(--panel-2);
}
.mt-media-viewer__title,
.mt-chart-viewer__title { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--fg); }
.mt-media-viewer__actions,
.mt-chart-viewer__actions { display: flex; gap: 6px; align-items: center; flex-shrink: 0; }
.mt-media-viewer__btn,
.mt-media-viewer__download { font-size: 10px; padding: 4px 8px; text-decoration: none; }
.mt-media-viewer__zoom {
  min-width: 42px; text-align: center; color: var(--grey-light); font-size: 10px;
  border: 1px solid var(--border); padding: 4px 6px; background: var(--bg);
}
.mt-media-viewer__body { flex: 1; min-height: 0; display: flex; align-items: flex-start; justify-content: center; overflow: auto; background: #111; }
.mt-media-viewer__frame { width: 100%; height: 100%; border: 0; background: #fff; }
.mt-media-viewer__img { max-width: none; height: auto; object-fit: contain; background: #fff; transform-origin: top center; }
.mt-chart-viewer__canvas { flex: 1; min-height: 360px; width: 100%; background: #fff; }
.mt-chart-viewer__fallback { width: 100%; height: 100%; object-fit: contain; background: #fff; }

@media (max-width: 700px) {
  .mt-media-viewer__dialog { min-height: 360px; height: min(72vh, 680px); }
  .mt-chart-viewer__dialog { min-height: 380px; height: min(78vh, 720px); }
  .mt-media-viewer__bar,
  .mt-chart-viewer__bar { align-items: flex-start; flex-direction: column; }
  .mt-media-viewer__actions,
  .mt-chart-viewer__actions { flex-wrap: wrap; }
  .bsb-reports__acoes { justify-content: flex-start; }
}

/* ── painel da agenda operacional (comando SCHEDULE) ───────────────────────
   O comando devolvia 40 linhas no output. Aqui o mesmo estado vira quadro:
   resumo clicavel em cima, tabela embaixo, acao por linha. */

.bsb-sched__resumo {
  display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 10px;
}

/* Cada bloco e um filtro: clicar liga, clicar de novo desliga. */
.bsb-sched__bloco {
  background: var(--bg); border: 1px solid var(--border);
  color: var(--white); cursor: pointer; font: inherit;
  padding: 6px 12px; min-width: 84px; text-align: left;
}
.bsb-sched__bloco:hover        { border-color: var(--cyan); }
.bsb-sched__bloco--ativo       { border-color: var(--cyan); background: var(--bg-panel); }
.bsb-sched__bloco-n            { display: block; font-size: 18px; line-height: 1.1; }
.bsb-sched__bloco-r            { display: block; font-size: 9px; letter-spacing: 1px; color: var(--grey); }

/* A cor carrega o significado: problema em vermelho, normal em verde.
   O rotulo continua escrito, porque cor sozinha nao e acessivel. */
.bsb-sched__bloco--neg .bsb-sched__bloco-n  { color: var(--red); }
.bsb-sched__bloco--warn .bsb-sched__bloco-n { color: var(--yellow); }
.bsb-sched__bloco--run .bsb-sched__bloco-n  { color: var(--cyan); }
.bsb-sched__bloco--pos .bsb-sched__bloco-n  { color: var(--green); }

.bsb-sched__estado {
  font-size: 9px; letter-spacing: 1px; padding: 2px 6px;
  border: 1px solid var(--border); white-space: nowrap;
}
.bsb-sched__estado--neg     { color: var(--red);    border-color: var(--red); }
.bsb-sched__estado--warn    { color: var(--yellow); border-color: var(--yellow); }
.bsb-sched__estado--run     { color: var(--cyan);   border-color: var(--cyan); }
.bsb-sched__estado--pos     { color: var(--green);  border-color: var(--green); }
.bsb-sched__estado--neutral { color: var(--grey); }

/* O erro fica recuado sob o nome, e nao em coluna propria: uma coluna para ele
   deixaria a tabela ilegivel para os 90% que estao bem. */
.bsb-sched__erro { color: var(--red); font-size: 10px; }

/* ── Séries mantidas à mão: a grade (issue #112) ──────────────────────────
   
   A tela anterior era um formulário com três campos soltos numa página fora
   do admin, e a medida do resultado foi zero conferências desde que subiu.
   Aqui é planilha: uma linha por data, uma coluna por campo, edição no lugar.
   Quem preenche está copiando um post com cinco números — o formato tem de
   parecer com o que a pessoa está lendo.
   
   O MODO TOMADA
   Enquanto se edita, a grade ocupa o painel inteiro do admin. Não é estética:
   a ABICOM tem cinco colunas mais data e ações, e disputá-las com as outras
   seções do admin deixaria a linha estreita demais para digitar sem errar de
   célula — que é justamente o erro que esta tela existe para consertar. */

.bsb-ms { font-size: 11px; }

/* Modo tomada: a div cobre o painel do admin inteiro. Fica DENTRO do painel,
   e não como modal sobre a página, para o operador não perder o contexto de
   onde está — a barra de comando e a topbar continuam acessíveis. */
.bsb-ms--tomada {
  position: absolute;
  inset: 0;
  z-index: 20;
  background: var(--bg-panel);
  display: flex;
  flex-direction: column;
  padding: 8px 10px;
  overflow: hidden;
}
.bsb-ms--tomada .bsb-ms__corpo { flex: 1; overflow: auto; }

.bsb-ms__topo {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  border-bottom: 1px solid var(--border);
  padding-bottom: 6px;
  margin-bottom: 6px;
  flex-wrap: wrap;
}
.bsb-ms__nome { color: var(--orange); letter-spacing: 1px; font-size: 12px; }
.bsb-ms__meta { color: var(--grey-light); font-size: 10px; }
.bsb-ms__meta a { color: var(--cyan); }
.bsb-ms__acoes { display: flex; gap: 6px; flex-wrap: wrap; }

/* A grade. `position: sticky` no cabeçalho porque a ABICOM acumula centenas
   de dias e rolar sem cabeçalho é digitar às cegas na coluna errada. */
.bsb-ms__grade { width: 100%; border-collapse: collapse; font-size: 11px; }
.bsb-ms__grade th {
  position: sticky; top: 0; z-index: 2;
  background: var(--bg-panel);
  text-align: right;
  color: var(--grey-light);
  border-bottom: 1px solid var(--border);
  padding: 4px 6px;
  font-size: 10px;
  letter-spacing: 1px;
  white-space: nowrap;
}
.bsb-ms__grade th:first-child,
.bsb-ms__grade td:first-child { text-align: left; }
.bsb-ms__grade th .u { color: var(--grey); letter-spacing: 0; }
.bsb-ms__grade td {
  padding: 0;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
.bsb-ms__grade tr:hover td { background: var(--bg-hover); }

/* Célula editável: input sem cara de input até receber foco, para a grade ler
   como planilha e não como formulário de cadastro. */
.bsb-ms__cel {
  width: 100%;
  background: transparent;
  border: 1px solid transparent;
  color: var(--white);
  font-family: var(--font);
  font-size: 11px;
  padding: 3px 6px;
  text-align: right;
}
.bsb-ms__cel:focus {
  outline: none;
  border-color: var(--border-hi);
  background: var(--bg-input);
}
.bsb-ms__cel--data { text-align: left; }
.bsb-ms__cel--nota { text-align: left; color: var(--grey-light); }
/* Alterada e ainda não gravada. O amarelo é o mesmo dos avisos do terminal. */
.bsb-ms__cel--suja { border-color: var(--yellow); }
.bsb-ms__cel:disabled { color: var(--grey); }

.bsb-ms__linha--nova td { background: rgba(0, 230, 118, 0.04); }
.bsb-ms__linha--suja td { background: rgba(255, 214, 0, 0.05); }

.bsb-ms__acao {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--grey-light);
  font-family: var(--font);
  font-size: 10px;
  padding: 2px 7px;
  cursor: pointer;
}
.bsb-ms__acao:hover { border-color: var(--grey-light); color: var(--white); }
.bsb-ms__acao--apagar:hover { border-color: var(--red); color: var(--red); }
.bsb-ms__acao--gravar:hover { border-color: var(--green); color: var(--green); }

.bsb-ms__aviso {
  font-size: 10px;
  padding: 4px 0;
  letter-spacing: 0.5px;
}
.bsb-ms__aviso--ok  { color: var(--green); }
.bsb-ms__aviso--err { color: var(--red); }

/* A lista de séries, quando nenhuma está aberta. */
.bsb-ms__cartao {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; padding: 5px 8px; border: 1px solid var(--border);
  margin-bottom: 4px; cursor: pointer;
}
.bsb-ms__cartao:hover { border-color: var(--border-hi); background: var(--bg-hover); }
.bsb-ms__cartao__nome { color: var(--white); }
.bsb-ms__cartao__cod  { color: var(--grey); font-size: 10px; }

/* Relatorio pendente de aprovacao (issue #114). Amarelo, que e o tom de aviso
   do terminal — o selo precisa saltar na lista, porque quem abre o painel de
   manha tem de ver num olhar que ha deck esperando conferencia. */
.bsb-reports__pendente {
  color: var(--yellow);
  border: 1px solid var(--yellow);
  font-size: 9px;
  letter-spacing: 1px;
  padding: 0 4px;
  margin-left: 4px;
  white-space: nowrap;
}

/* ── Diálogo do terminal ──────────────────────────────────────────────────
   Substitui alert(), confirm() e prompt() do navegador.

   Os diálogos nativos quebram de três formas que importam aqui: aparecem no
   chrome do navegador, num visual claro que nada tem a ver com o terminal;
   travam a thread, então nenhuma animação ou WebSocket avança enquanto estão
   abertos; e não deixam formatar nada — o confirm de remover usuário virava um
   bloco de texto sem hierarquia, com o aviso destrutivo do mesmo tamanho que o
   resto.

   z-index 200 fica acima da cmdbar (90), que é o teto do resto da interface. */
.bsb-dlg-fundo {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.82);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 200;
  padding: 16px;
}

.bsb-dlg {
  background: var(--bg-panel);
  border: 1px solid var(--border-hi);
  font-family: var(--font);
  font-size: var(--font-size);
  color: var(--white);
  width: 100%;
  max-width: 520px;
  max-height: 90vh;
  display: flex;
  flex-direction: column;
}

.bsb-dlg--perigo { border-color: var(--red); }

.bsb-dlg__titulo {
  background: var(--bg-input);
  border-bottom: 1px solid var(--border);
  color: var(--orange);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  padding: 6px 10px;
  font-size: 11px;
}

.bsb-dlg--perigo .bsb-dlg__titulo { color: var(--red); }

.bsb-dlg__corpo {
  padding: 12px 10px;
  overflow-y: auto;
  white-space: pre-wrap;
  line-height: 1.5;
}

/* O aviso do que não tem desfazer, separado do texto corrido: num parágrafo
   único ele tinha o mesmo peso visual que a pergunta. */
.bsb-dlg__aviso {
  display: block;
  margin-top: 8px;
  padding: 6px 8px;
  border-left: 2px solid var(--red);
  background: rgba(244, 67, 54, 0.08);
  color: var(--red);
}

.bsb-dlg__campo {
  width: 100%;
  margin-top: 10px;
  background: var(--bg-input);
  border: 1px solid var(--border);
  color: var(--white);
  font-family: var(--font);
  font-size: var(--font-size);
  padding: 5px 6px;
}

.bsb-dlg__campo:focus { outline: none; border-color: var(--border-hi); }

/* Opções de escolha: uma por linha, porque o menu "digite 1, 2 ou 3" do prompt
   obrigava a pessoa a traduzir número em significado. */
.bsb-dlg__opcoes { display: flex; flex-direction: column; gap: 4px; margin-top: 10px; }

.bsb-dlg__opcao {
  text-align: left;
  background: var(--bg-input);
  border: 1px solid var(--border);
  color: var(--white);
  font-family: var(--font);
  font-size: var(--font-size);
  padding: 6px 8px;
  cursor: pointer;
}

.bsb-dlg__opcao:hover { background: var(--bg-hover); border-color: var(--border-hi); }
.bsb-dlg__opcao b { color: var(--cyan); }
.bsb-dlg__opcao small { display: block; color: var(--grey-light); font-size: 11px; }

.bsb-dlg__acoes {
  display: flex;
  justify-content: flex-end;
  gap: 6px;
  padding: 8px 10px;
  border-top: 1px solid var(--border);
}

/* Explicação curta acima de uma tabela do /admin: o que a ação faz, antes de a
   pessoa clicar. Fica no painel e não num diálogo porque é contexto para
   decidir, e não confirmação do que já se decidiu. */
.bsb-admin-nota {
  border-left: 2px solid var(--orange);
  background: var(--bg-input);
  color: var(--grey-light);
  padding: 6px 8px;
  margin-bottom: 8px;
  font-size: 11px;
  line-height: 1.5;
}

.bsb-admin-nota b { color: var(--white); }

/* ── Ordenação de temas (FEED e RELATÓRIOS) ───────────────────────────────
   Lista arrastável do /admin. Mesmo componente para os dois painéis. */
.bsb-ordem__modo {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 8px;
}

.bsb-ordem__modo .bsb-btn { font-size: 10px; padding: 3px 14px; }

.bsb-ordem__explica { color: var(--grey-light); font-size: 11px; }

.bsb-ordem {
  list-style: none;
  margin: 0;
  padding: 0;
  border: 1px solid var(--border);
}

.bsb-ordem__item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 8px;
  border-bottom: 1px solid var(--border);
  background: var(--bg-panel);
}

.bsb-ordem__item:last-child { border-bottom: none; }

/* A alça só vira cursor de arrasto no modo MANUAL: em AUTO a lista informa a
   ordem em vigor, e um cursor de mover prometeria o que não funciona. */
.bsb-ordem--manual .bsb-ordem__item { cursor: grab; }
.bsb-ordem--manual .bsb-ordem__item:hover { background: var(--bg-hover); }

.bsb-ordem__item--arrastando { opacity: 0.4; }

/* A linha de destino marcada no topo, e não a inteira realçada: durante o
   arrasto o que se precisa saber é ONDE o item vai cair. */
.bsb-ordem__item--alvo { box-shadow: inset 0 2px 0 0 var(--green); }

.bsb-ordem__alca { color: var(--grey); width: 12px; }
.bsb-ordem--manual .bsb-ordem__alca { color: var(--orange); }

.bsb-ordem__pos {
  color: var(--grey);
  width: 26px;
  text-align: right;
  font-size: 11px;
}

.bsb-ordem__nome { color: var(--white); flex: 1; }
.bsb-ordem__meta { color: var(--grey-light); font-size: 11px; }

/* Tema criado depois da lista manual: entra no fim e é marcado, senão é
   indistinguível de um que alguém pôs ali de propósito. */
.bsb-ordem__item--novo { background: rgba(255, 214, 0, 0.06); }

.bsb-ordem__selo {
  color: var(--yellow);
  border: 1px solid var(--yellow);
  font-size: 9px;
  padding: 0 4px;
  white-space: nowrap;
}

.bsb-ordem__setas { display: flex; gap: 2px; }

.bsb-ordem__seta {
  background: var(--bg-input);
  border: 1px solid var(--border);
  color: var(--grey-light);
  font-family: var(--font);
  font-size: 10px;
  line-height: 1;
  padding: 2px 5px;
  cursor: pointer;
}

.bsb-ordem__seta:hover { background: var(--bg-hover); color: var(--white); }

.bsb-ordem__acoes {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 8px;
}

/* ── Explorador de fontes (viewsource sem opções, issue #129) ──────────────
   Construtor de consulta por mouse. Reusa a paleta e o desenho de trilha da
   tela de notícias; o que é próprio daqui é o par fonte/estado e os chips. */
.bsb-vs__busca { padding: 6px 8px; border-bottom: 1px solid var(--border); }

.bsb-vs__fonte { align-items: flex-start; gap: 8px; }

.bsb-vs__fonte-nome { display: flex; flex-direction: column; min-width: 0; }
.bsb-vs__fonte-nome small {
  color: var(--grey); font-size: 9px; letter-spacing: .3px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* O estado fica na linha da fonte, e não depois de abri-la: escolher uma fonte
   parada sem saber que está parada é o erro que o painel torna impossível. */
.bsb-vs__fonte-estado {
  display: flex; flex-direction: column; align-items: flex-end;
  font-size: 9px; letter-spacing: .5px; white-space: nowrap; flex-shrink: 0;
}
.bsb-vs__fonte-estado small { color: var(--grey); font-size: 9px; }

.bsb-vs__cab { padding: 10px 12px 6px; border-bottom: 1px solid var(--border); }
.bsb-vs__cab-nome { color: var(--orange); font-size: 13px; display: block; }
.bsb-vs__cab-meta { color: var(--grey-light); font-size: 10px; }

/* A contagem é o coração do painel: é ela que torna visível o filtro que não
   filtra nada. Fica no topo, grande, e responde a cada mudança. */
.bsb-vs__contagem {
  padding: 8px 12px; border-bottom: 1px solid var(--border);
  background: var(--bg-input); font-size: 12px;
}
.bsb-vs__contagem b { font-size: 16px; }
.bsb-vs__zerou { display: block; margin-top: 4px; color: var(--yellow); font-size: 10px; }

.bsb-vs__grupo { padding: 8px 12px; border-bottom: 1px solid var(--border); }
.bsb-vs__grupo-titulo {
  color: var(--orange); font-size: 9px; letter-spacing: 1.2px; margin-bottom: 6px;
}

.bsb-vs__linha { display: flex; gap: 8px; flex-wrap: wrap; }
.bsb-vs__campo { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 150px; }
.bsb-vs__campo > span { color: var(--grey-light); font-size: 10px; }
.bsb-vs__campo .bsb-input { font-size: 11px; padding: 3px 6px; }

.bsb-vs__nota { color: var(--grey); font-size: 10px; line-height: 1.5; }

/* Chips: a representação que torna óbvio que há mais de um filtro combinado e
   qual remover. Uma pilha de selects não comunica "estes três valem juntos". */
.bsb-vs__chips { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 6px; }
.bsb-vs__chip {
  display: inline-flex; align-items: center; gap: 5px;
  background: var(--bg-input); border: 1px solid var(--border-hi);
  color: var(--white); font-size: 10px; padding: 2px 4px 2px 7px;
}
.bsb-vs__chip button {
  background: transparent; border: none; color: var(--grey);
  font-family: var(--font); font-size: 11px; line-height: 1; cursor: pointer; padding: 0 2px;
}
.bsb-vs__chip button:hover { color: var(--red); }

/* A linha de comando montada. É o que faz o painel ensinar em vez de
   substituir: quem usa três vezes aprende o comando. */
.bsb-vs__cmd {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 12px; border-bottom: 1px solid var(--border); background: #000;
}
.bsb-vs__cmd-label { color: var(--orange); font-size: 10px; letter-spacing: 1px; flex-shrink: 0; }
.bsb-vs__cmd code {
  color: var(--green); font-family: var(--font); font-size: 11px;
  flex: 1; overflow-x: auto; white-space: nowrap;
}
.bsb-vs__cmd .bsb-btn { font-size: 9px; padding: 2px 8px; flex-shrink: 0; }

.bsb-vs__acoes {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 10px 12px;
}
.bsb-vs__acoes .bsb-btn { font-size: 10px; padding: 4px 12px; }

/* Fatia curada: a fonte não é a fonte inteira, é o que a casa escolheu
   acompanhar de um catálogo maior (issue #135).

   Cinza e discreto de propósito. Informa, não alarma: 0,2% do SIDRA pode ser
   exatamente o que a casa usa, e pintar de vermelho transformaria uma decisão
   editorial em pendência — a tela discordando de quem a opera. */
.bsb-vs__fatia {
  color: var(--grey-light);
  background: var(--bg-input);
  border: 1px solid var(--border);
  font-size: 9px;
  padding: 0 4px;
  white-space: nowrap;
  flex-shrink: 0;
}
