/* Camada de design do portal — consome SOMENTE variáveis --portal-* (spec, seção 10.4).
   Funciona em tema claro e escuro: nada de cor literal fora dos tokens; realces
   derivam do próprio texto/superfície via color-mix. */

/* Navegação entre páginas com crossfade nativo (Chrome/Edge; os demais
   ignoram a regra): suaviza o "piscar" seco do reload server-rendered ao
   trocar de conversa ou de tela. Zero JavaScript. */
@view-transition {
  navigation: auto;
}

@font-face {
  font-family: 'Inter Variable';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('../vendor/fonts/inter-variable.woff2') format('woff2');
}

/* ---------- Base ---------- */

body {
  background-color: var(--portal-color-bg-body);
  color: var(--portal-color-text);
  font-family: var(--portal-font-family-base);
  font-size: var(--portal-font-size-base);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4, h5, h6 {
  font-family: var(--portal-font-family-headings);
  font-weight: 600;
  letter-spacing: -0.01em;
}

a { color: var(--portal-color-primary); }

.text-muted { color: var(--portal-color-text-muted) !important; }

code {
  color: var(--portal-color-text-muted);
  background: color-mix(in srgb, var(--portal-color-border) 45%, transparent);
  padding: 0.1rem 0.35rem;
  border-radius: 0.3rem;
  font-size: 0.8em;
}

/* ---------- Shell autenticado ---------- */

.portal-shell { display: flex; min-height: 100vh; }

/* !important: acima de 992px o Bootstrap zera o fundo de .offcanvas-lg */
/* A sidebar deriva TODAS as cores dos tokens nav-* — nunca dos tokens de
 * texto/borda gerais, que pertencem ao conteúdo. Isso permite sidebar escura
 * em tema claro (ex.: tema Irison) sem perder legibilidade. */
.portal-sidebar {
  /* Largura ditada pelo item mais longo do menu ("Base de conhecimento"),
     sem folga sobrando à direita */
  width: 15rem;
  transition: width 0.16s ease;
  flex-shrink: 0;
  background: var(--portal-color-nav-bg) !important;
  color: var(--portal-color-nav-text);
  display: flex;
  flex-direction: column;
  border: 0;
  border-right: 1px solid color-mix(in srgb, var(--portal-color-nav-text) 15%, transparent);
}

@media (min-width: 992px) {
  .portal-sidebar {
    position: sticky;
    top: 0;
    height: 100vh;
    transform: none !important;
    visibility: visible !important;
    /* O z-index do Bootstrap para .offcanvas-lg só existe ABAIXO de 992px;
       daqui para cima a sidebar ficaria em `auto` e o conteúdo — que vem
       depois no HTML — passaria por cima dela (e das dicas do modo
       recolhido). Fica abaixo de modal (1055) e de toast (1090). */
    z-index: 1030;
  }
}

.portal-sidebar-brand {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  padding: 1.1rem 1.1rem 0.9rem;
  font-weight: 700;
  font-size: 1.02rem;
  color: var(--portal-color-nav-text);
}

.portal-brand-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border-radius: 0.6rem;
  background: var(--portal-color-primary);
  color: var(--portal-color-primary-contrast);
  font-size: 1rem;
  flex-shrink: 0;
}

.portal-sidebar-nav { flex: 1; padding: 0.35rem 0.7rem; overflow-y: auto; }

.portal-nav-section {
  font-size: 0.67rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: color-mix(in srgb, var(--portal-color-nav-text) 65%, transparent);
  padding: 1.05rem 0.7rem 0.3rem;
}

.portal-nav-item {
  position: relative; /* âncora da dica exibida com a sidebar recolhida */
  display: flex;
  align-items: center;
  gap: 0.65rem;
  width: 100%;
  padding: 0.5rem 0.7rem;
  margin-bottom: 0.1rem;
  border: 0;
  border-radius: 0.55rem;
  background: transparent;
  color: var(--portal-color-nav-text);
  text-decoration: none;
  font-size: 0.92rem;
  transition: background 0.12s ease, color 0.12s ease;
}

.portal-nav-item i { font-size: 1.02rem; width: 1.25rem; text-align: center; }

.portal-nav-item:hover,
.portal-nav-item:focus {
  background: color-mix(in srgb, var(--portal-color-nav-text) 12%, transparent);
  color: var(--portal-color-nav-text);
}

.portal-nav-item.active {
  background: var(--portal-color-nav-active-bg);
  color: var(--portal-color-nav-active-text);
  font-weight: 600;
}

.portal-nav-item.disabled { opacity: 0.5; pointer-events: none; }

.portal-nav-soon {
  margin-left: auto;
  font-size: 0.6rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  border: 1px solid currentColor;
  border-radius: 1rem;
  padding: 0.05rem 0.4rem;
  opacity: 0.75;
}

/* Usuário no rodapé da sidebar (menu para cima) */

.portal-sidebar-footer {
  padding: 0.7rem;
  border-top: 1px solid color-mix(in srgb, var(--portal-color-nav-text) 18%, transparent);
}

.portal-user-chip {
  position: relative; /* idem: âncora da dica no modo recolhido */
  display: flex;
  align-items: center;
  gap: 0.65rem;
  width: 100%;
  padding: 0.5rem 0.6rem;
  border: 0;
  border-radius: 0.65rem;
  background: transparent;
  color: var(--portal-color-nav-text);
  text-align: left;
  transition: background 0.12s ease;
}

.portal-user-chip:hover,
.portal-user-chip[aria-expanded="true"] {
  background: color-mix(in srgb, var(--portal-color-nav-text) 10%, transparent);
}

.portal-user-chip-text { display: flex; flex-direction: column; min-width: 0; }

.portal-user-chip-name {
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--portal-color-nav-text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.portal-user-chip-email {
  font-size: 0.72rem;
  color: color-mix(in srgb, var(--portal-color-nav-text) 70%, transparent);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.portal-user-menu {
  width: 15.5rem;
  border: 1px solid var(--portal-color-border);
  border-radius: 0.75rem;
  padding: 0.4rem;
  background-color: var(--portal-color-bg-surface);
  box-shadow: var(--portal-shadow-raised);
}

.portal-user-menu .dropdown-item {
  border-radius: 0.5rem;
  padding: 0.45rem 0.65rem;
  font-size: 0.9rem;
  color: var(--portal-color-text);
}

.portal-user-menu .dropdown-item:hover { background: var(--portal-color-bg-body); }

.portal-user-menu .dropdown-header {
  font-size: 0.67rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--portal-color-text-muted);
  padding: 0.35rem 0.65rem 0.15rem;
}

.portal-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.1rem;
  height: 2.1rem;
  border-radius: 50%;
  background: color-mix(in srgb, var(--portal-color-primary) 18%, var(--portal-color-bg-surface));
  color: var(--portal-color-primary);
  font-weight: 700;
  flex-shrink: 0;
}

/* ---------- Sidebar recolhida (só desktop; no mobile ela é offcanvas) ----------
 *
 * Recolher NÃO esconde a navegação: a sidebar vira uma faixa de ícones,
 * e o rótulo de cada um aparece como dica ao passar o mouse. O estado é
 * lembrado em cookie e aplicado na renderização (ver base/base.html). */

.portal-sidebar-toggle {
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  margin-left: auto;
  padding: 0;
  border: 0;
  border-radius: 0.5rem;
  background: transparent;
  color: var(--portal-color-nav-text);
  opacity: 0.7;
  flex-shrink: 0;
}

.portal-sidebar-toggle:hover {
  background: color-mix(in srgb, var(--portal-color-nav-text) 12%, transparent);
  opacity: 1;
}

@media (min-width: 992px) {
  .portal-sidebar-collapsed .portal-sidebar { width: 4.25rem; }

  /* Recolhida, a marca dá lugar ao botão: com 4rem não cabem os dois */
  .portal-sidebar-collapsed .portal-brand-logo,
  .portal-sidebar-collapsed .portal-brand-mark,
  .portal-sidebar-collapsed .portal-brand-name,
  .portal-sidebar-collapsed .portal-nav-item > span,
  .portal-sidebar-collapsed .portal-user-chip-text,
  .portal-sidebar-collapsed .portal-user-chip > .bi-chevron-expand { display: none; }

  .portal-sidebar-collapsed .portal-sidebar-brand { justify-content: center; padding: 1.1rem 0 0.9rem; }

  .portal-sidebar-collapsed .portal-sidebar-toggle { margin-left: 0; }

  .portal-sidebar-collapsed .portal-nav-item,
  .portal-sidebar-collapsed .portal-user-chip {
    justify-content: center;
    padding-left: 0;
    padding-right: 0;
  }

  /* A dica é posicionada FORA da faixa; sem isto a rolagem vertical do
     menu recortaria o balão. A lista é curta por natureza. */
  .portal-sidebar-collapsed .portal-sidebar-nav { overflow: visible; padding: 0.35rem 0.5rem; }

  /* O título da seção some, mas a separação entre grupos permanece */
  .portal-sidebar-collapsed .portal-nav-section {
    font-size: 0;
    padding: 0;
    margin: 0.55rem 0.35rem 0.45rem;
    border-top: 1px solid color-mix(in srgb, var(--portal-color-nav-text) 18%, transparent);
  }

  .portal-sidebar-collapsed .portal-nav-item::after,
  .portal-sidebar-collapsed .portal-user-chip::after,
  .portal-sidebar-collapsed .portal-sidebar-toggle::after {
    content: attr(data-label);
    position: absolute;
    left: calc(100% + 0.55rem);
    top: 50%;
    transform: translateY(-50%);
    z-index: 30;
    white-space: nowrap;
    padding: 0.3rem 0.6rem;
    border: 1px solid var(--portal-color-border);
    border-radius: var(--portal-radius-base);
    background: var(--portal-color-bg-surface);
    color: var(--portal-color-text);
    box-shadow: var(--portal-shadow-raised);
    font-size: 0.82rem;
    font-weight: 500;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.12s ease;
  }

  .portal-sidebar-collapsed .portal-sidebar-toggle { position: relative; }

  .portal-sidebar-collapsed .portal-nav-item:hover::after,
  .portal-sidebar-collapsed .portal-nav-item:focus-visible::after,
  .portal-sidebar-collapsed .portal-user-chip:hover::after,
  .portal-sidebar-collapsed .portal-user-chip:focus-visible::after,
  .portal-sidebar-collapsed .portal-sidebar-toggle:hover::after,
  .portal-sidebar-collapsed .portal-sidebar-toggle:focus-visible::after { opacity: 1; }
}

/* Barra superior apenas no mobile */

.portal-mobilebar {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.55rem 1rem;
  background: var(--portal-color-bg-surface);
  border-bottom: 1px solid var(--portal-color-border);
}

.portal-mobilebar-toggle { font-size: 1.35rem; padding: 0.1rem 0.4rem; }

.portal-mobilebar-brand { font-weight: 700; }

/* Conteúdo */

.portal-main { flex: 1; display: flex; flex-direction: column; min-width: 0; }

/* O conteúdo acompanha a largura do monitor; o teto alto só evita linhas
   quilométricas em ultrawide. Formulários continuam estreitos por card. */
.portal-content {
  flex: 1;
  padding: 1.75rem clamp(1.1rem, 1.6vw, 2rem) 2.5rem;
  max-width: 120rem;
  width: 100%;
  margin: 0 auto;
}

.portal-footer {
  padding: 1rem 1.75rem;
  color: var(--portal-color-text-muted);
  font-size: 0.85rem;
  border-top: 1px solid var(--portal-color-border);
}

/* ---------- Cabeçalho de página ---------- */

.portal-page-header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1.5rem;
}

.portal-page-title { font-size: 1.55rem; margin: 0; }

.portal-page-subtitle {
  margin: 0.3rem 0 0;
  color: var(--portal-color-text-muted);
  font-size: 0.9rem;
  font-family: var(--portal-font-family-base);
}

/* ---------- Superfícies ---------- */

.card,
.portal-surface {
  background-color: var(--portal-color-bg-surface);
  border: 1px solid var(--portal-color-border);
  border-radius: var(--portal-radius-surface);
  box-shadow: var(--portal-shadow-surface);
}

.portal-tile {
  display: block;
  text-decoration: none;
  color: inherit;
  transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease;
}

.portal-tile:hover {
  transform: translateY(-2px);
  border-color: color-mix(in srgb, var(--portal-color-primary) 35%, var(--portal-color-border));
  box-shadow: var(--portal-shadow-raised);
  color: inherit;
}

.portal-tile-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.6rem;
  height: 2.6rem;
  border-radius: 0.8rem;
  background: color-mix(in srgb, var(--portal-color-primary) 16%, var(--portal-color-bg-surface));
  color: var(--portal-color-primary);
  font-size: 1.2rem;
  margin-bottom: 0.75rem;
}

/* ---------- Tabelas ---------- */

/* Escala única: conteúdo de tabela acompanha o corpo (0.88rem), como menus e
   subtítulos. Células NÃO quebram linha por padrão — texto longo usa a classe
   .portal-cell-wrap; o excesso rola horizontalmente no .table-responsive. */

.portal-table { font-size: 0.88rem; }

/* A tabela é retangular; sem o recorte, o fundo do cabeçalho e o hover das
   linhas vazam pelos cantos arredondados do card. O -1px compensa a borda. */
.portal-surface > .table-responsive {
  border-radius: calc(var(--portal-radius-surface) - 1px);
}

/* Tabela precedida de outro conteúdo no card (ex.: título): só os cantos
   de baixo encostam na borda arredondada. */
.portal-surface .card-body > .table-responsive {
  border-bottom-left-radius: calc(var(--portal-radius-surface) - 1px);
  border-bottom-right-radius: calc(var(--portal-radius-surface) - 1px);
}

.portal-table thead th {
  font-size: 0.72rem;
  font-weight: 700;
  font-family: var(--portal-font-family-base);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--portal-color-text-muted);
  border-bottom: 1px solid var(--portal-color-border);
  padding: 0.8rem 1rem;
  background: color-mix(in srgb, var(--portal-color-bg-body) 55%, var(--portal-color-bg-surface));
  white-space: nowrap;
}

.portal-table tbody td {
  padding: 0.8rem 1rem;
  border-color: var(--portal-color-border);
  white-space: nowrap;
}

.portal-table .portal-cell-wrap {
  white-space: normal;
  overflow-wrap: anywhere;
  min-width: 16rem;
}

.portal-table tbody tr:hover {
  background: color-mix(in srgb, var(--portal-color-text) 5%, transparent);
}

.portal-table tbody tr:last-child td { border-bottom: 0; }

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

.form-label { font-weight: 600; font-size: 0.87rem; }

.form-control, .form-select {
  border-radius: var(--portal-radius-base);
  border-color: var(--portal-color-border);
  background-color: var(--portal-color-bg-surface);
  color: var(--portal-color-text);
  padding: 0.5rem 0.8rem;
  font-size: 0.9rem;
}

.form-control::placeholder { color: var(--portal-color-text-muted); }

.form-control:focus, .form-select:focus, .form-check-input:focus {
  border-color: var(--portal-color-primary);
  background-color: var(--portal-color-bg-surface);
  color: var(--portal-color-text);
  box-shadow: 0 0 0 0.2rem color-mix(in srgb, var(--portal-color-primary) 18%, transparent);
}

.form-check-input {
  background-color: var(--portal-color-bg-surface);
  border-color: color-mix(in srgb, var(--portal-color-text) 30%, transparent);
}

.form-text { color: var(--portal-color-text-muted); }

.form-check-input:checked {
  background-color: var(--portal-color-primary);
  border-color: var(--portal-color-primary);
}

/* Botões na mesma escala do conteúdo (menu = 0.92rem, tabela = 0.88rem) */
.btn { border-radius: var(--portal-radius-base); font-weight: 550; font-size: 0.9rem; }

.btn-sm { font-size: 0.8rem; }

.btn i { font-size: 0.95em; }

.btn-primary {
  --bs-btn-bg: var(--portal-color-primary);
  --bs-btn-border-color: var(--portal-color-primary);
  --bs-btn-color: var(--portal-color-primary-contrast);
  --bs-btn-hover-bg: var(--portal-color-primary);
  --bs-btn-hover-border-color: var(--portal-color-primary);
  --bs-btn-hover-color: var(--portal-color-primary-contrast);
  --bs-btn-active-bg: var(--portal-color-primary);
  --bs-btn-active-border-color: var(--portal-color-primary);
  --bs-btn-active-color: var(--portal-color-primary-contrast);
}

.btn-primary:hover { filter: brightness(0.92); }

.btn-outline-secondary {
  --bs-btn-color: var(--portal-color-text);
  --bs-btn-border-color: var(--portal-color-border);
  --bs-btn-hover-bg: var(--portal-color-bg-body);
  --bs-btn-hover-color: var(--portal-color-text);
  --bs-btn-hover-border-color: var(--portal-color-border);
}

.badge { font-weight: 600; }

.portal-badge-muted {
  background: color-mix(in srgb, var(--portal-color-border) 60%, transparent);
  color: var(--portal-color-text-muted);
}

.portal-theme-dot {
  display: inline-block;
  width: 0.85rem;
  height: 0.85rem;
  border-radius: 50%;
  margin-right: 0.45rem;
  vertical-align: -0.05rem;
  border: 1px solid color-mix(in srgb, var(--portal-color-text) 20%, transparent);
}

.portal-brand-logo { max-height: 2rem; max-width: 11rem; }

.alert { border-radius: var(--portal-radius-base); font-size: 0.9rem; }

.dropdown-menu { font-size: 0.9rem; }

.pagination .page-link { color: var(--portal-color-primary); }

.pagination .page-item.active .page-link {
  background-color: var(--portal-color-primary);
  border-color: var(--portal-color-primary);
  color: var(--portal-color-primary-contrast);
}

/* ---------- Páginas anônimas (login, recuperação, MFA) ---------- */

.portal-anon {
  background:
    radial-gradient(55rem 28rem at 85% -10%, color-mix(in srgb, var(--portal-color-primary) 12%, transparent), transparent 60%),
    radial-gradient(45rem 26rem at -10% 110%, color-mix(in srgb, var(--portal-color-primary) 9%, transparent), transparent 55%),
    var(--portal-color-bg-body);
  min-height: 100vh;
}

.portal-anon-wrap {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
}

.portal-anon-inner { width: 100%; max-width: 26rem; }

.portal-auth-card { margin: 0; }

.portal-auth-brand {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-weight: 700;
  font-size: 1.1rem;
  font-family: var(--portal-font-family-headings);
  margin-bottom: 0.35rem;
}

.portal-auth-brand .portal-brand-mark { width: 2.3rem; height: 2.3rem; }

/* ---------- Conversa com agente (Fase 4) ---------- */

.portal-chat {
  /* Largura do miolo da conversa: cresce com a resolução, sem virar
     linha quilométrica — o excedente vai para as laterais. */
  --portal-chat-col: 56rem;
  display: flex;
  flex-direction: column;
  min-height: 24rem;
  /* Recorta a barra de rolagem interna no raio do card — sem isso o canto
     superior direito perde o arredondamento */
  overflow: hidden;
}

/* Na página de conversa quem rola é a LISTA DE MENSAGENS, nunca a página.
   O chat OCUPA O QUE SOBRA em vez de descontar uma constante da janela: o
   `calc(100vh - 8.1rem)` de antes era um número mágico que não conferia com o
   cabeçalho real — título, descrição e a fila de botões que só aparece com a
   conversa aberta. Quando essa fila nascia, ela empurrava tudo para baixo e o
   chat não encolhia, porque a altura dele não dependia do que havia acima.
   Medido em 09/08/2026: 983px de documento numa janela de 950.

   O crescimento tem de ser repassado pela cadeia INTEIRA (shell → main →
   content → row do Bootstrap → coluna); parar em qualquer degrau faz o chat
   medir contra altura automática e o excedente volta a virar rolagem de
   página. Escopado por `:has()` para não tocar nas telas que rolam de
   propósito, e só a partir de `lg` — abaixo disso as colunas empilham e a
   página rolar é o comportamento certo. */
@media (min-width: 992px) {
  body:has(.portal-chat) .portal-shell { height: 100vh; }

  body:has(.portal-chat) .portal-main { min-height: 0; }

  /* O respiro inferior padrão (2.5rem) vira 0.75rem: a janela do chat se
     estende até perto do rodapé */
  .portal-content:has(.portal-chat) {
    padding-bottom: 0.75rem;
    display: flex;
    flex-direction: column;
    min-height: 0;
  }

  .portal-content:has(.portal-chat) > .row {
    flex: 1;
    min-height: 0;
    /* `.row` do Bootstrap quebra linha, e num container que quebra a altura
       da LINHA vem do conteúdo — a coluna transbordava a row (medido em
       09/08/2026: row 791px, coluna 2338px) e a rolagem voltava para a
       página. Sem quebra há uma linha só, cuja altura é a do container, e
       aí `align-items: stretch` finalmente limita a coluna. A partir de
       `lg` as duas colunas (9 + 3) sempre cabem lado a lado, então proibir
       a quebra aqui não muda layout nenhum. */
    flex-wrap: nowrap;
  }

  /* `align-items: stretch` já iguala a altura das colunas; o que falta é elas
     serem contêineres flex para o chat e a lateral poderem ocupar essa altura
     e rolar por dentro. */
  .portal-content:has(.portal-chat) > .row > [class*="col-"] {
    display: flex;
    flex-direction: column;
    min-height: 0;
  }

  .portal-chat {
    flex: 1;
    min-height: 12rem;
  }
}

/* O rodapé do tema não precisa mais de reserva manual: ele é irmão do
   conteúdo no mesmo flex column, então a altura dele já sai da conta. */

@media (min-width: 1600px) {
  .portal-chat { --portal-chat-col: 70rem; }
}

@media (min-width: 2200px) {
  .portal-chat { --portal-chat-col: 84rem; }
}

@media (max-width: 991.98px) {
  /* Abaixo de `lg` as colunas empilham e a página rola de propósito — a
     cadeia flex acima não vale aqui. Sem teto algum o card crescia com a
     conversa (medido: 4176px num celular de 780px) e a caixa de escrever ia
     parar no fim de uma página quilométrica.

     O teto é da JANELA, não do cabeçalho: quanto o título, a descrição e a
     fila de botões ocupam varia, e foi exatamente essa variação que quebrou
     a constante do desktop. Com `max-height` o card ainda encolhe quando a
     conversa é curta, e o excedente rola dentro da lista.

     `dvh` porque no celular a barra do navegador entra e sai da tela; `vh`
     fica de reserva para quem não o suporta. */
  .portal-chat {
    max-height: 78vh;
    max-height: 78dvh;
  }
}

/* O miolo da conversa fica centralizado na largura da resolução
   (--portal-chat-col) — o padding lateral absorve o excedente. */
.portal-chat-messages {
  flex: 1;
  /* `min-height: auto` é o padrão de item flex e vale a altura do CONTEÚDO:
     com ele a lista não encolhe, empurra a janela do chat e a rolagem some
     justamente onde ela é necessária. */
  min-height: 0;
  overflow-y: auto;
  padding: 1.25rem max(1.25rem, calc((100% - var(--portal-chat-col)) / 2));
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
}

.portal-chat-empty { margin: auto; }

.portal-chat-message { display: flex; flex-direction: column; max-width: 85%; }

/* Quando a mensagem ocorreu — discreto de propósito: informa sem competir
   com o conteúdo. O `order` alto é o que garante que ela fique por ÚLTIMO
   mesmo quando o painel de execução, os anexos e os botões de sugestão são
   acrescentados DEPOIS dela no DOM (o chat monta a bolha antes de saber o
   que mais virá). O alinhamento acompanha o da bolha, porque o pai já
   define `align-items` por papel. */
.portal-chat-time {
  order: 99;
  font-size: 0.68rem;
  line-height: 1.4;
  color: var(--portal-color-text-muted);
  opacity: 0.75;
  margin: 0.15rem 0.2rem 0;
  font-variant-numeric: tabular-nums;
  /* Vazio até o script preencher: sem isto, um espaço em branco de 0.68rem
     empurraria as bolhas quando o horário não fosse renderizado. */
  min-height: 0;
}

.portal-chat-time:empty { display: none; }

.portal-chat-user { align-self: flex-end; align-items: flex-end; }

.portal-chat-assistant { align-self: flex-start; align-items: flex-start; }

/* Botão de ouvir/parar a leitura em voz alta da resposta */
.portal-chat-speak {
  border: 1px solid var(--portal-color-border);
  background: var(--portal-color-bg-surface);
  color: var(--portal-color-text-muted);
  border-radius: 2rem;
  font-size: 0.9rem;
  line-height: 1;
  padding: 0.3rem 0.55rem;
  margin-top: 0.35rem;
  transition: color 0.12s ease, border-color 0.12s ease;
}

.portal-chat-speak:hover {
  color: var(--portal-color-primary);
  border-color: var(--portal-color-primary);
}

/* Linha de ações da resposta: gap MAIOR separa funções distintas (ouvir × avaliar).
   `order` fixa a posição no balão (flex-column): ações logo antes do horário,
   sempre DEPOIS de sugestões/mídia (que o JS anexa em ordem variável). */
.portal-chat-actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.35rem;
  order: 90;
}
.portal-chat-time { order: 100; }
.portal-chat-actions .portal-chat-speak { margin-top: 0; }

/* Avaliação 👍/👎 numa bolha única (mesma pílula do 🔊) — os dois juntos são
   UMA função; gap PEQUENO aproxima os botões entre si dentro do grupo. */
.portal-chat-fb-group {
  display: inline-flex;
  align-items: center;
  gap: 0.1rem;
  border: 1px solid var(--portal-color-border);
  background: var(--portal-color-bg-surface);
  border-radius: 2rem;
  padding: 0.1rem 0.3rem;
}
.portal-fb-btn {
  appearance: none;
  background: none;
  border: none;
  cursor: pointer;
  font-size: 0.9rem;
  line-height: 1;
  padding: 0.1rem 0.28rem;
  color: var(--portal-color-text-muted);
  transition: color 0.12s ease;
}
.portal-fb-btn:hover {
  color: var(--portal-color-primary);
}
.portal-fb-btn.active {
  color: var(--portal-color-primary);
}

/* Modal do 👎 (sugestão de melhoria) — coerente com o tema (claro/escuro) */
.portal-fb-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.45);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1080;
}
.portal-fb-modal {
  background: var(--portal-color-bg-surface);
  color: var(--portal-color-text);
  border: 1px solid var(--portal-color-border);
  border-radius: 0.6rem;
  padding: 1rem 1.1rem;
  max-width: 420px;
  width: 92%;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3);
}
.portal-fb-title { margin: 0 0 0.5rem; font-size: 0.95rem; }
.portal-fb-text {
  width: 100%;
  border: 1px solid var(--portal-color-border);
  background: var(--portal-color-bg-body);
  color: var(--portal-color-text);
  border-radius: 0.4rem;
  padding: 0.4rem 0.5rem;
  font: inherit;
  resize: vertical;
}
.portal-fb-actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.5rem;
  margin-top: 0.6rem;
}

.portal-chat-bubble {
  padding: 0.7rem 1rem;
  border-radius: var(--portal-radius-surface);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  /* Teto DEFINIDO, e não é firula: um `pre` com `white-space: pre` não
     quebra linha, então sua largura MÍNIMA é a da maior linha. A bolha é
     dimensionada por conteúdo (`align-items: flex-start`), adota esse
     mínimo e passa dos 85% da mensagem — medido em 08/08/2026: bolha de
     1854px dentro de uma mensagem de 762px. E o chat inteiro ganha barra
     lateral porque `overflow-y: auto` no contêiner faz o `overflow-x`
     computar como `auto` pela especificação.
     Com o teto aqui, o `overflow-x: auto` do `pre` finalmente tem efeito e
     a rolagem fica DENTRO do bloco de código, onde deve estar. */
  min-width: 0;
  max-width: 100%;
  /* Alinhada ao corpo padrão do portal (menus, tabelas ~0.9rem) — a base
     de 1rem deixava a conversa maior que o resto da interface */
  font-size: 0.9rem;
  line-height: 1.55;
}

/* Resposta renderizada como Markdown: a estrutura vem das tags, não dos \n */
.portal-chat-md { white-space: normal; }

.portal-chat-md > :first-child { margin-top: 0; }

.portal-chat-md > :last-child { margin-bottom: 0; }

.portal-chat-md p, .portal-chat-md ul, .portal-chat-md ol { margin-bottom: 0.6rem; }

/* Título numa resposta é MARCADOR DE SEÇÃO, não título de página.
   Sem regra própria eles caíam no padrão do Bootstrap, que é dimensionado
   sobre 1rem (16px) enquanto a bolha usa 0,9rem (14,4px) — medido em
   08/08/2026: h1 a 2,57× o corpo, h2 a 2,10× e até o h4 62% maior. Numa
   conversa isso vira grito.
   A escala vai em `em` de propósito: fica presa ao corpo da bolha, então
   mexer no tamanho da conversa não desarranja a hierarquia de novo. */
.portal-chat-md h1,
.portal-chat-md h2,
.portal-chat-md h3,
.portal-chat-md h4,
.portal-chat-md h5,
.portal-chat-md h6 {
  font-weight: 600;
  line-height: 1.3;
  /* Mais espaço ACIMA que abaixo: o título pertence ao texto que vem
     depois dele, e não ao parágrafo que ficou para trás. */
  margin: 1.4em 0 0.4em;
}

.portal-chat-md h1 { font-size: 1.35em; }
.portal-chat-md h2 { font-size: 1.2em; }
.portal-chat-md h3 { font-size: 1.1em; }
/* Deste nível em diante o peso já separa: aumentar o corpo só faria a
   resposta parecer um documento dentro do balão. */
.portal-chat-md h4,
.portal-chat-md h5,
.portal-chat-md h6 { font-size: 1em; }

.portal-chat-md pre {
  background: color-mix(in srgb, var(--portal-color-text) 8%, transparent);
  border: 1px solid var(--portal-color-border);
  border-radius: var(--portal-radius-base);
  padding: 0.7rem 0.9rem;
  overflow-x: auto;
  margin-bottom: 0.6rem;
}

/* Bloco de código QUEBRA linha, em vez de rolar de lado.
   O padrão do `pre` é não quebrar, e num editor de código isso é certo:
   quebrar destrói alinhamento e indentação. Aqui não — o modelo embrulha em
   cerca de código coisas que não são código (texto corrido, listas, tabelas
   improvisadas), e aí a rolagem horizontal esconde a metade da frase e
   obriga a arrastar linha por linha para ler.
   `pre-wrap` preserva a indentação e as quebras que vieram do modelo;
   `anywhere` resolve o token único gigante (URL, hash) que não tem espaço
   onde quebrar. O `overflow-x` acima fica como rede para o que ainda assim
   não couber, como tabela dentro do bloco. */
.portal-code > pre,
.portal-chat-md pre,
[data-markdown] pre {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.portal-chat-md pre code { background: none; padding: 0; font-size: 0.82rem; }

.portal-chat-md table {
  border-collapse: collapse;
  margin-bottom: 0.6rem;
  font-size: 0.85rem;
  /* Tabela larga ROLA; não é espremida. Tratamento oposto ao do bloco de
     código logo acima, e de propósito: quebrar linha de texto ajuda, mas
     espremer coluna destrói a comparação que é o motivo de existir a tabela
     — com muitas colunas o portal picotava cada palavra ("colu / na 0").
     `display: block` + `width: max-content` deixam a caixa medir o conteúdo
     real; o `max-width` a prende na largura da bolha e o excedente vira
     rolagem DENTRO da tabela. */
  display: block;
  width: max-content;
  max-width: 100%;
  overflow-x: auto;
}

.portal-chat-md th, .portal-chat-md td {
  border: 1px solid var(--portal-color-border);
  padding: 0.35rem 0.6rem;
  /* A bolha usa `anywhere` para caber URL sem espaço; dentro da célula isso
     partia palavra no meio sem necessidade, já que agora há para onde rolar */
  overflow-wrap: normal;
}

.portal-chat-md blockquote {
  border-left: 3px solid var(--portal-color-border);
  padding-left: 0.8rem;
  color: var(--portal-color-text-muted);
  margin-bottom: 0.6rem;
}

.portal-chat-user .portal-chat-bubble {
  background: color-mix(in srgb, var(--portal-color-primary) 14%, var(--portal-color-bg-surface));
  border: 1px solid color-mix(in srgb, var(--portal-color-primary) 25%, var(--portal-color-border));
}

.portal-chat-assistant .portal-chat-bubble {
  background: color-mix(in srgb, var(--portal-color-bg-body) 65%, var(--portal-color-bg-surface));
  border: 1px solid var(--portal-color-border);
}

/* Indicador de atividade: o que o agente está fazendo + tempo decorrido */
.portal-chat-status {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.35rem;
  font-size: 0.8rem;
  color: var(--portal-color-text-muted);
}

.portal-chat-status .spinner-border {
  width: 0.85rem;
  height: 0.85rem;
  border-width: 0.14em;
  color: var(--portal-color-primary);
}

.portal-chat-typing::after {
  content: "▍";
  animation: portal-chat-blink 1s steps(2) infinite;
  color: var(--portal-color-text-muted);
}

@keyframes portal-chat-blink { to { visibility: hidden; } }

.portal-chat-error {
  margin-top: 0.35rem;
  font-size: 0.8rem;
  color: var(--bs-danger);
}

.portal-chat-composer {
  border-top: 1px solid var(--portal-color-border);
  padding: 0.9rem max(1.25rem, calc((100% - var(--portal-chat-col)) / 2));
}

.portal-chat-composer textarea { resize: none; }

.portal-conversation-list {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  overflow-y: auto;
}

/* Coluna lateral do agente: mesma altura do chat, dividida entre a
   apresentação e as conversas. Cada bloco rola POR DENTRO — texto longo de
   apresentação empurrava a página inteira para a rolagem, afastando o campo
   de escrever da tela. */
@media (min-width: 992px) {
  .portal-agent-side {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    /* Mesma correção da janela do chat: a altura vem do que sobra na coluna,
       não de uma constante subtraída da janela. */
    min-height: 0;
  }

  .portal-agent-side-block {
    flex: 1 1 0;
    /* min-height: 0 é o que permite o filho encolher e rolar dentro de um
       container flex — sem isso o bloco cresce e volta a empurrar a página */
    min-height: 0;
    overflow: hidden;
  }

  .portal-agent-side-block > .card-body {
    display: flex;
    flex-direction: column;
    min-height: 0;
    overflow-y: auto;
  }

  /* Bloco compacto (ex.: aviso dos documentos de referência): ocupa só a
     própria linha, sem disputar altura com a apresentação e as conversas */
  .portal-agent-side-compact { flex: 0 0 auto; }
}

.portal-conversation-item {
  display: flex;
  align-items: center;
  border-radius: var(--portal-radius-base);
  padding: 0.15rem 0.25rem 0.15rem 0.6rem;
}

.portal-conversation-item:hover,
.portal-conversation-item.active {
  background: color-mix(in srgb, var(--portal-color-text) 6%, transparent);
}

.portal-conversation-link {
  flex: 1;
  min-width: 0;
  padding: 0.35rem 0;
  color: var(--portal-color-text);
  text-decoration: none;
  font-size: 0.87rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.portal-conversation-delete {
  border: 0;
  color: var(--portal-color-text-muted);
  opacity: 0;
  padding: 0.15rem 0.4rem;
}

.portal-conversation-item:hover .portal-conversation-delete { opacity: 1; }

.portal-conversation-delete:hover { color: var(--bs-danger); }

/* ---------- Anexos no chat ---------- */

.portal-chat-attachments {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-bottom: 0.35rem;
}

.portal-chat-attachment-img {
  max-width: 14rem;
  max-height: 10rem;
  border-radius: var(--portal-radius-base);
  border: 1px solid var(--portal-color-border);
}

.portal-chat-attachment-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.3rem 0.65rem;
  border: 1px solid var(--portal-color-border);
  border-radius: 1rem;
  background: color-mix(in srgb, var(--portal-color-text) 5%, transparent);
  color: var(--portal-color-text);
  font-size: 0.8rem;
  text-decoration: none;
}

.portal-chat-attachment-chip:hover {
  border-color: color-mix(in srgb, var(--portal-color-primary) 40%, var(--portal-color-border));
  color: var(--portal-color-text);
}

.portal-chat-files {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  padding-bottom: 0.6rem;
}

.portal-chat-file-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.25rem 0.3rem 0.25rem 0.65rem;
  border: 1px solid var(--portal-color-border);
  border-radius: 1rem;
  font-size: 0.8rem;
  color: var(--portal-color-text);
  background: color-mix(in srgb, var(--portal-color-primary) 10%, var(--portal-color-bg-surface));
}

.portal-chat-file-remove {
  border: 0;
  background: transparent;
  color: var(--portal-color-text-muted);
  font-size: 1rem;
  line-height: 1;
  padding: 0 0.3rem;
}

.portal-chat-file-remove:hover { color: var(--bs-danger); }

/* ---------- Tags de agentes ---------- */

.portal-tag {
  background: color-mix(in srgb, var(--portal-color-primary) 12%, var(--portal-color-bg-surface));
  color: var(--portal-color-primary);
  border: 1px solid color-mix(in srgb, var(--portal-color-primary) 25%, transparent);
  font-weight: 600;
}

.portal-tag.active,
a.portal-tag:hover {
  background: var(--portal-color-primary);
  color: var(--portal-color-primary-contrast);
  border-color: var(--portal-color-primary);
}

/* Mídia gerada pelo modelo na resposta */

.portal-chat-attachment-media {
  max-width: 100%;
  border-radius: var(--portal-radius-base);
}

.portal-chat-attachment-video {
  max-width: 24rem;
  max-height: 15rem;
  border: 1px solid var(--portal-color-border);
  background: #000;
}

/* ---------- Ferramentas no chat ---------- */

.portal-chat-tools { display: flex; flex-wrap: wrap; gap: 0.35rem; margin-bottom: 0.35rem; }

.portal-chat-toolchip {
  display: inline-block;
  padding: 0.25rem 0.65rem;
  border: 1px dashed var(--portal-color-border);
  border-radius: 1rem;
  font-size: 0.78rem;
  color: var(--portal-color-text-muted);
  background: color-mix(in srgb, var(--portal-color-text) 4%, transparent);
  margin-bottom: 0.35rem;
}

.portal-checklist ul { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: 0.4rem 1.5rem; }

.portal-checklist li { display: flex; align-items: center; gap: 0.4rem; }

/* ---------- Página inicial e favoritos ---------- */

.portal-home-item {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  background: transparent;
  border-color: var(--portal-color-border);
  color: var(--portal-color-text);
  padding: 0.7rem 1.5rem;
}

.portal-home-item:hover {
  background: color-mix(in srgb, var(--portal-color-text) 5%, transparent);
  color: var(--portal-color-text);
}

.portal-home-item-title {
  font-weight: 600;
  font-size: 0.9rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.portal-fav-form {
  position: absolute;
  top: 0.6rem;
  right: 0.6rem;
  z-index: 2;
}

.portal-fav-btn {
  border: 0;
  background: transparent;
  color: var(--portal-color-text-muted);
  font-size: 1rem;
  padding: 0.2rem 0.4rem;
  border-radius: 0.4rem;
}

.portal-fav-btn:hover { color: var(--portal-color-primary); }

.portal-fav-btn.active { color: var(--portal-color-primary); }

/* ---------- Voltar (breadcrumb de um nível) ---------- */

.portal-back {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--portal-color-text-muted);
  text-decoration: none;
  margin-bottom: 0.6rem;
}

.portal-back:hover { color: var(--portal-color-primary); }

/* ---------- Modais no padrão do portal ---------- */

.portal-modal {
  background: var(--portal-color-bg-surface);
  border: 1px solid var(--portal-color-border);
  border-radius: var(--portal-radius-surface);
  box-shadow: var(--portal-shadow-raised);
  color: var(--portal-color-text);
}

.portal-modal .btn-close {
  filter: invert(0.5);
}

/* Fundo do modal: escurece de leve e desfoca, mantendo a tela visível
   atrás — cobrir tudo faria perder a referência do que se está lendo */
.modal-backdrop.show {
  opacity: 1;
  background-color: color-mix(in srgb, var(--portal-color-text) 20%, transparent);
  backdrop-filter: blur(2px);
}

/* Lista de documentos do fluxo: uma coluna por faixa de largura, com
   espaço suficiente para o título inteiro numa linha só */
.portal-flow-docs {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(26rem, 1fr));
  gap: 0.35rem 1rem;
}

.portal-flow-docs a {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.45rem 0.6rem;
  border-radius: var(--portal-radius-base);
  color: var(--portal-color-text);
  text-decoration: none;
}

.portal-flow-docs a:hover {
  background: color-mix(in srgb, var(--portal-color-primary) 10%, transparent);
  color: var(--portal-color-primary);
}

.portal-flow-docs i {
  color: var(--portal-color-text-muted);
  flex-shrink: 0;
}

/* Barra de copiar dos blocos de código (js/codecopy.js) — chat e base de
 * conhecimento. Permanente, e não só no hover: escondida ninguém achava, e
 * em tela de toque não existe hover. */

.portal-code {
  border: 1px solid var(--portal-color-border);
  border-radius: var(--portal-radius-base);
  margin-bottom: 0.6rem;
  max-width: 100%;
  /* SEM `overflow: hidden`. Ele arredondaria os cantos de graça, mas
     qualquer ancestral com overflow diferente de `visible` vira o contexto
     de rolagem do `position: sticky` — e o botão flutuante pararia de
     acompanhar a rolagem. Os cantos são feitos peça a peça, mais abaixo. */
}

.portal-code-bar {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.2rem 0.7rem;
  background: color-mix(in srgb, var(--portal-color-text) 6%, var(--portal-color-bg-surface));
  border-bottom: 1px solid var(--portal-color-border);
  border-radius: calc(var(--portal-radius-base) - 1px) calc(var(--portal-radius-base) - 1px) 0 0;
}

.portal-code-lang {
  font-size: 0.72rem;
  letter-spacing: 0.02em;
  color: var(--portal-color-text-muted);
  font-family: var(--bs-font-monospace);
}

/* Preso à rolagem: acompanha o bloco enquanto ele estiver na tela, e só sai
   junto com ele. Fica no canto direito por `margin-left: auto`, e o
   `margin-bottom` negativo evita que reserve altura própria — sem isso
   empurraria a primeira linha.

   NÃO usa `float`. O `pre` rola por dentro (`overflow: auto`) e isso faz
   dele um contexto de formatação próprio, que por regra DESVIA de
   flutuantes: ele encolhia a largura do botão e a moldura da saída ficava
   34px mais estreita que a do código (medido em 09/08/2026: 672 contra
   706). No bloco com linguagem o desvio caía sobre a faixa e passava
   despercebido; sem faixa, sobrava para o próprio `pre`. Bloco alinhado
   por margem não é flutuante, então ninguém desvia dele. */
.portal-code-copy {
  position: sticky;
  top: 0.4rem;
  width: fit-content;
  margin: 0.4rem 0.4rem -2.1rem auto;
  z-index: 2;
  /* Nível de BLOCO, não `inline-flex`: margem automática só empurra caixa de
     bloco. Em `inline-flex` o `margin-left: auto` vira zero e o botão volta
     para a esquerda do bloco. */
  display: flex;
  align-items: center;
  gap: 0.3rem;
  border: 1px solid transparent;
  /* Opaco de propósito: o botão passa por cima do código ao rolar, e sem
     fundo próprio as duas camadas de texto se sobrepõem e ficam ilegíveis. */
  background: var(--portal-color-bg-surface);
  color: var(--portal-color-text-muted);
  border-radius: 0.35rem;
  padding: 0.15rem 0.45rem;
  font-size: 0.78rem;
  line-height: 1.6;
  transition: color 0.12s ease, background-color 0.12s ease, border-color 0.12s ease;
}

.portal-code-copy:hover {
  color: var(--portal-color-primary);
  border-color: color-mix(in srgb, var(--portal-color-primary) 40%, transparent);
}

/* Em repouso, só o ícone: o botão fica sobre o código o tempo todo, e com o
   rótulo permanente rouba atenção de quem só quer ler. O nome acessível
   está no `aria-label`, então esconder o texto não tira nada de quem usa
   leitor de tela. O rótulo volta no hover, no foco por teclado e — o que
   importa — quando há resposta a dar (copiado / falhou).

   O rótulo é POSICIONADO FORA do fluxo, à esquerda do botão, e a folga do
   botão nunca muda. Antes ele entrava como `display: inline` e crescia a
   caixa: como o botão é `float`, o texto do bloco refluía em volta, o
   ponteiro saía de cima dele, o rótulo sumia, o texto voltava — e o bloco
   piscava sem parar enquanto o mouse estivesse por perto (relatado em
   09/08/2026). Geometria fixa quebra esse laço na origem. */
.portal-code-copy { padding: 0.25rem 0.4rem; }

.portal-code-copy > span {
  position: absolute;
  right: 100%;
  margin-right: 0.3rem;
  padding: 0 0.3rem;
  border-radius: 0.3rem;
  background: var(--portal-color-bg-surface);
  white-space: nowrap;
  opacity: 0;
  /* Sem isto o próprio rótulo receberia o ponteiro e criaria um segundo
     laço, agora entre estar sobre o botão e estar sobre o rótulo. */
  pointer-events: none;
  transition: opacity 0.12s ease;
}

.portal-code-copy:hover > span,
.portal-code-copy:focus-visible > span,
.portal-code-copy.copiado > span,
.portal-code-copy.falhou > span { opacity: 1; }

.portal-code-copy:focus-visible {
  outline: 2px solid var(--portal-color-primary);
  outline-offset: 1px;
}

.portal-code-copy.copiado { color: var(--portal-color-success); }

.portal-code-copy.falhou { color: var(--portal-color-warning); }

/* O bloco já tem contorno pela caixa: aqui só a área que rola. Os cantos
   de baixo são deste `pre`; os de cima, da faixa (ou dele mesmo, quando o
   bloco não declara linguagem e não há faixa). */
.portal-code > pre,
.portal-chat-md .portal-code > pre {
  border: 0;
  border-radius: 0 0 calc(var(--portal-radius-base) - 1px) calc(var(--portal-radius-base) - 1px);
  margin-bottom: 0;
  max-width: 100%;
}

/* Sem linguagem declarada não há faixa, então o `pre` faz os quatro cantos */
.portal-code.sem-faixa > pre {
  border-radius: calc(var(--portal-radius-base) - 1px);
}

/* Cartão de apresentação HTML gerada pelo agente (estilo artifact) */
.portal-artifact {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
  border: 1px solid var(--portal-color-border);
  background: color-mix(in srgb, var(--portal-color-primary) 6%, var(--portal-color-bg-surface));
  border-radius: var(--portal-radius-base);
  padding: 0.6rem 0.85rem;
  margin-bottom: 0.6rem;
}

.portal-artifact-icon {
  font-size: 1.4rem;
  color: var(--portal-color-primary);
}

.portal-artifact-info {
  display: flex;
  flex-direction: column;
  line-height: 1.3;
}

.portal-artifact-info span {
  font-size: 0.75rem;
  color: var(--portal-color-text-muted);
}

.portal-artifact-actions {
  margin-left: auto;
  display: flex;
  gap: 0.4rem;
}

/* Fonte do documento recolhido — o botão de código alterna */
.portal-artifact-source { display: none; }

.portal-html-preview {
  display: block;
  width: 100%;
  height: 78vh;
  border: 0;
  background: #fff;
  border-radius: 0 0 var(--portal-radius-surface) var(--portal-radius-surface);
}

/* Visualizador de imagem no modal do chat */
.portal-media-view {
  display: block;
  max-width: 100%;
  max-height: 78vh;
  margin: 0 auto;
  object-fit: contain;
}

/* Miniatura clicável no chat */
.portal-chat-attachment-img { cursor: zoom-in; }

/* Escopo da base de conhecimento no compositor do chat */
.portal-chat-kbscope {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
  font-size: 0.78rem;
  color: var(--portal-color-text-muted);
}

.portal-chat-kbscope select {
  width: auto;
  min-width: 16rem;
  font-size: 0.8rem;
}

/* ---------- Base de conhecimento ---------- */

/* Layout: árvore fixa à esquerda, conteúdo à direita */
.portal-kb-layout {
  display: grid;
  /* A árvore acompanha a tela: em monitor grande ela cresce e os títulos de
     documento param de quebrar em três linhas. O teto evita que a coluna
     roube espaço do conteúdo, que é o que se veio ler. */
  grid-template-columns: clamp(15.5rem, 19vw, 23rem) minmax(0, 1fr);
  gap: 1.25rem;
  align-items: start;
  /* A árvore já faz o papel de margem: encosta um pouco mais à esquerda
     para não somar respiro sobre o respiro do .portal-content */
  margin: -0.4rem 0 0 -0.4rem;
}

.portal-kb-side {
  position: sticky;
  top: 1rem;
  /* Preso a 1rem do topo + 1rem de respiro embaixo: a lista acompanha a
     altura da tela inteira. O desconto antigo (8rem) supunha um cabeçalho
     que não existe e deixava a árvore terminando bem antes do fim. */
  max-height: calc(100vh - 2rem);
  overflow-y: auto;
  padding-right: 0.25rem;
}

.portal-kb-search { margin-bottom: 0.85rem; }

.portal-kb-nav-header {
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--portal-color-text-muted);
  font-weight: 700;
  padding: 0 0.5rem 0.35rem;
}

/* Coleção: nível de destaque, como no Outline */
.portal-kb-collection-link {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.4rem 0.55rem;
  border-radius: var(--portal-radius-base);
  color: var(--portal-color-text);
  font-weight: 600;
  font-size: 0.87rem;
  text-decoration: none;
}

.portal-kb-collection-link i:first-child { color: var(--portal-color-primary); }

.portal-kb-collection-link:hover {
  background: color-mix(in srgb, var(--portal-color-primary) 8%, transparent);
  color: var(--portal-color-text);
}

.portal-kb-collection.active .portal-kb-collection-link {
  background: color-mix(in srgb, var(--portal-color-primary) 14%, transparent);
  color: var(--portal-color-primary);
}

/* Documentos aninhados */
.portal-kb-branch {
  list-style: none;
  padding-left: 0.85rem;
  margin: 0.1rem 0 0.35rem;
}

.portal-kb-branch .portal-kb-branch { padding-left: 0.75rem; }

.portal-kb-row {
  display: flex;
  align-items: center;
  gap: 0.15rem;
  border-radius: var(--portal-radius-base);
}

.portal-kb-row > a {
  flex: 1;
  min-width: 0;
  padding: 0.25rem 0.35rem;
  font-size: 0.82rem;
  color: var(--portal-color-text-muted);
  text-decoration: none;
  overflow-wrap: anywhere;
}

.portal-kb-row:hover { background: color-mix(in srgb, var(--portal-color-primary) 7%, transparent); }

.portal-kb-row:hover > a { color: var(--portal-color-text); }

.portal-kb-row.active { background: color-mix(in srgb, var(--portal-color-primary) 12%, transparent); }

.portal-kb-row.active > a { color: var(--portal-color-primary); font-weight: 600; }

/* Coluna do nível: a seta de expandir e o ícone do conteúdo nativo
   ocupam o MESMO espaço e ficam centrados nele — encostar cada um à
   esquerda deixaria os dois desalinhados entre si */
.portal-kb-caret,
.portal-kb-caret-space {
  width: 1.1rem;
  flex: 0 0 1.1rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  background: none;
  color: var(--portal-color-text-muted);
  font-size: 0.7rem;
  line-height: 1;
  padding: 0;
}

/* Vídeo e fluxo: o ícone é a única pista do tipo, então respira um pouco
   mais que a seta */
.portal-kb-caret-space i { font-size: 0.82rem; }

.portal-kb-caret i { transition: transform 0.12s ease; display: inline-block; }

.portal-kb-caret.expanded i { transform: rotate(90deg); }

/* Conteúdo */
.portal-kb-main { min-width: 0; }

.portal-kb-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1.1rem;
}

.portal-kb-title { font-size: 1.6rem; margin: 0 0 0.25rem; }

.portal-kb-breadcrumb {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex-wrap: wrap;
  font-size: 0.78rem;
  color: var(--portal-color-text-muted);
  margin-bottom: 0.75rem;
}

.portal-kb-breadcrumb a { color: inherit; text-decoration: none; }

.portal-kb-breadcrumb a:hover { color: var(--portal-color-primary); }

.portal-kb-tabs { border-bottom-color: var(--portal-color-border); }

.portal-kb-tabs .nav-link {
  color: var(--portal-color-text-muted);
  border: 0;
  border-bottom: 2px solid transparent;
  font-size: 0.87rem;
  padding: 0.4rem 0.85rem;
}

.portal-kb-tabs .nav-link.active {
  color: var(--portal-color-primary);
  background: none;
  border-bottom-color: var(--portal-color-primary);
}

/* Painéis das abas da coleção: mesma escala tipográfica da navegação
   lateral — as listas internas saíam com fonte MAIOR que o próprio menu
   de documentos, e cada aba parecia de uma tela diferente */
.portal-kb-panels { font-size: 0.85rem; }

.portal-kb-panels .portal-kb-tree a { font-size: 0.85rem; }

.portal-kb-panels .portal-table { font-size: 0.84rem; }

.portal-kb-panels .portal-table thead th {
  font-size: 0.68rem;
  padding: 0.6rem 0.85rem;
}

.portal-kb-panels .portal-table tbody td { padding: 0.55rem 0.85rem; }

@media (max-width: 992px) {
  .portal-kb-layout { grid-template-columns: 1fr; }
  .portal-kb-side { position: static; max-height: none; }
}

.portal-kb-tree {
  list-style: none;
  padding-left: 0;
  margin-bottom: 0;
}

.portal-kb-tree li { margin: 0.15rem 0; }

.portal-kb-tree a {
  display: inline-block;
  padding: 0.2rem 0.35rem;
  border-radius: var(--portal-radius-base);
  color: var(--portal-color-text);
  text-decoration: none;
}

.portal-kb-tree a:hover {
  background: color-mix(in srgb, var(--portal-color-primary) 10%, transparent);
  color: var(--portal-color-primary);
}

/* Corpo do documento: mesma escala do resto do portal, com respiro de
   leitura entre parágrafos (o padrão do chat é compacto demais aqui) */
.portal-kb-doc {
  font-size: 0.9rem;
  line-height: 1.65;
  color: var(--portal-color-text);
}

.portal-kb-doc p { margin: 0 0 0.9rem; }

/* Fidelidade com o Outline: imagem é BLOCO CENTRADO, na largura que o autor
   definiu lá (markdown.js aplica o meta que viaja no título da imagem) —
   sem isso a leitura sai diferente do que quem escreveu está vendo */
.portal-kb-doc img {
  display: block;
  margin: 0.6rem auto;
  max-width: 100%;
  height: auto;
}

.portal-kb-doc img.portal-kb-img-left {
  float: left;
  margin: 0.3rem 1.1rem 0.7rem 0;
}

.portal-kb-doc img.portal-kb-img-right {
  float: right;
  margin: 0.3rem 0 0.7rem 1.1rem;
}

/* Texto ao lado da imagem flutuada é escolha do autor, mas a seção seguinte
   recomeça em linha própria */
.portal-kb-doc h1,
.portal-kb-doc h2,
.portal-kb-doc h3,
.portal-kb-doc h4 {
  clear: both;
}

/* Tabela ocupa a coluna inteira, com grade visível nos dois esquemas de
   cor — o padrão do navegador encolhia ao conteúdo e sumia com as bordas */
.portal-kb-doc table {
  width: 100%;
  border-collapse: collapse;
  margin: 0 0 1rem;
  font-size: 0.875rem;
}

.portal-kb-doc th,
.portal-kb-doc td {
  border: 1px solid var(--portal-color-border);
  padding: 0.45rem 0.7rem;
  vertical-align: top;
}

/* Célula vazia mantém a altura de uma linha de texto, como no Outline —
   sem isso a linha em branco colapsava e a tabela parecia quebrada */
.portal-kb-doc td:empty::after {
  content: "\00a0";
}

.portal-kb-doc th {
  text-align: left;
  background: color-mix(in srgb, var(--portal-color-border) 30%, transparent);
}

/* Filtro compacto na linha do título do painel de conversas */
.portal-conversation-filter {
  max-width: 9.5rem;
  min-width: 0;
}

/* Imagem do chat com a ação "usar no próximo envio" embaixo — referência
   explícita para o pedido de ajuste, sem o modelo adivinhar a imagem */
.portal-chat-attachment-block {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  align-items: flex-start;
}

.portal-chat-attach-again {
  border: 0;
  background: none;
  padding: 0 0.15rem;
  font-size: 0.72rem;
  color: var(--portal-color-text-muted);
  cursor: pointer;
}

.portal-chat-attach-again:hover { color: var(--portal-color-primary); }

/* Diagrama Mermaid renderizado (markdown.js): rola na horizontal quando o
   fluxo é mais largo que a coluna de leitura, em vez de estourar o layout */
.portal-mermaid {
  overflow-x: auto;
  margin: 0 0 0.9rem;
  text-align: center;
}

.portal-mermaid svg { max-width: 100%; height: auto; }

.portal-kb-doc > :last-child { margin-bottom: 0; }

.portal-kb-doc h1 { font-size: 1.3rem; margin: 1.6rem 0 0.6rem; }

.portal-kb-doc h2 { font-size: 1.12rem; margin: 1.4rem 0 0.55rem; }

.portal-kb-doc h3 { font-size: 1rem; margin: 1.2rem 0 0.5rem; }

.portal-kb-doc h4,
.portal-kb-doc h5,
.portal-kb-doc h6 { font-size: 0.92rem; margin: 1rem 0 0.45rem; }

.portal-kb-doc > :first-child { margin-top: 0; }

.portal-kb-doc ul,
.portal-kb-doc ol { margin: 0 0 0.9rem; padding-left: 1.4rem; }

.portal-kb-doc li { margin-bottom: 0.3rem; }

.portal-kb-doc img { max-width: 100%; height: auto; border-radius: var(--portal-radius-base); }

/* Conteúdo nativo: player de vídeo e diagrama de fluxo */
.portal-kb-video {
  width: 100%;
  max-height: 72vh;
  border-radius: var(--portal-radius-base);
  background: #000;
}

/* Visualizador de fluxo: barra, área com zoom e nós clicáveis */
.portal-flow-frame { position: relative; }

/* Em tela cheia o bloco vira a própria tela: fundo próprio (o padrão do
   navegador é preto) e o diagrama ocupando toda a altura restante. */
.portal-flow-frame.fullscreen {
  background: var(--portal-color-bg-body);
  padding: 1rem;
  display: flex;
  flex-direction: column;
}

.portal-flow-frame.fullscreen .portal-flow-canvas {
  flex: 1;
  max-height: none;
}

.portal-flow-toolbar {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-bottom: 0.6rem;
}

.portal-flow-canvas {
  overflow: auto;
  max-height: 76vh;
  border: 1px solid var(--portal-color-border);
  border-radius: var(--portal-radius-base);
  background: #fff;
}

/* A mãozinha só aparece quando há mesmo o que arrastar (zoom > 100%) */
.portal-flow-canvas.pannable { cursor: grab; }

.portal-flow-canvas.dragging { cursor: grabbing; }

/* Em 100% o diagrama cabe na largura (como antes do zoom existir); o zoom
   multiplica a partir daí. */
.portal-flow-stage {
  position: relative;
  transform-origin: top left;
  transition: transform 0.12s ease;
  width: 100%;
}

.portal-flow-image {
  display: block;
  width: 100%;
  height: auto;
  /* Sem isso o navegador inicia o arrasto nativo da imagem e o cursor
     vira "bloqueado", com o gesto preso até o próximo clique */
  -webkit-user-drag: none;
  user-select: none;
}

/* Área clicável sobre o nó do diagrama */
.portal-flow-hit {
  position: absolute;
  border-radius: 0.2rem;
}

/* Discreto por padrão: o desenho é o conteúdo, o vínculo é só um indício */
.portal-flow-hit.linked {
  cursor: pointer;
  transition: box-shadow 0.15s ease;
}

/* Halo POR FORA do nó (sombra difusa, não borda): a linha do desenho
   continua intacta e o realce não invade a figura */
.portal-flow-hit.linked:hover {
  box-shadow:
    0 0 0.5rem 0.15rem color-mix(in srgb, var(--portal-color-primary) 35%, transparent),
    0 0 1.2rem 0.4rem color-mix(in srgb, var(--portal-color-primary) 18%, transparent);
}

/* Selo pequeno CENTRADO no canto superior direito da figura — fica por
   fora do desenho, sem cobrir o conteúdo do nó (como na PoC) */
/* O tamanho acompanha o nó (não o texto da página): o clipe é desenhado
   como imagem para encolher junto com o círculo em qualquer zoom */
.portal-flow-badge {
  position: absolute;
  top: 0;
  right: 0;
  transform: translate(50%, -50%);
  height: 26%;
  aspect-ratio: 1;
  min-height: 0.3rem;
  max-height: 0.6rem;
  border-radius: 50%;
  background-color: var(--portal-color-primary);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='white'%3E%3Cpath d='M4.5 3a2.5 2.5 0 0 1 5 0v9a1.5 1.5 0 0 1-3 0V5a.5.5 0 0 1 1 0v6.5a.5.5 0 0 0 1 0V3a1.5 1.5 0 1 0-3 0v9a2.5 2.5 0 0 0 5 0V5a.5.5 0 0 1 1 0v7a3.5 3.5 0 1 1-7 0z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: center;
  background-size: 55%;
  box-shadow: 0 0 0 0.05rem #fff;
}

/* Revisão: diferença linha a linha entre a publicada e a pendente */
/* Diff da revisão: BLOCOS renderizados como o documento fica na tela.
   Ler marcação crua não é tarefa de quem aprova conteúdo. */

.portal-kb-diffblocks {
  border: 1px solid var(--portal-color-border);
  border-radius: var(--portal-radius-base);
  padding: 0.6rem;
  max-height: 40rem;
  overflow-y: auto;
}

.portal-kb-diffblock {
  display: flex;
  gap: 0.5rem;
  padding: 0.35rem 0.5rem;
  border-left: 3px solid transparent;
  border-radius: 0.25rem;
}

.portal-kb-diffblock .portal-kb-doc { min-width: 0; flex: 1; }

.portal-kb-diffblock .portal-kb-doc > :last-child { margin-bottom: 0; }

.portal-kb-diffmark {
  width: 0.9rem;
  flex-shrink: 0;
  font-weight: 700;
  line-height: 1.7;
  color: var(--portal-color-text-muted);
}

.portal-kb-diffblock.adicionado {
  background: color-mix(in srgb, var(--bs-success) 10%, transparent);
  border-left-color: var(--bs-success);
}

.portal-kb-diffblock.adicionado .portal-kb-diffmark { color: var(--bs-success); }

.portal-kb-diffblock.removido {
  background: color-mix(in srgb, var(--bs-danger) 10%, transparent);
  border-left-color: var(--bs-danger);
  opacity: 0.75;
}

.portal-kb-diffblock.removido .portal-kb-diffmark { color: var(--bs-danger); }

/* Removido fica legível, mas visivelmente "saindo": risco só no texto */
.portal-kb-diffblock.removido .portal-kb-doc { text-decoration: line-through; }

.portal-kb-diffblock.igual { color: var(--portal-color-text-muted); }

.portal-kb-diffskip {
  margin: 0.35rem 0;
  padding: 0.25rem 0.5rem;
  text-align: center;
  font-size: 0.78rem;
  font-style: italic;
  color: var(--portal-color-text-muted);
  background: color-mix(in srgb, var(--portal-color-text) 4%, transparent);
  border-radius: 0.25rem;
}

/* Quadro de auditoria no rodapé do documento */

.portal-kb-audit {
  margin-top: 1.25rem;
  padding: 0.9rem 1.1rem;
  border: 1px solid var(--portal-color-border);
  border-radius: var(--portal-radius-surface);
  background: color-mix(in srgb, var(--portal-color-text) 3%, var(--portal-color-bg-surface));
  font-size: 0.84rem;
}

.portal-kb-audit-head {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
  font-weight: 600;
  margin-bottom: 0.6rem;
}

.portal-kb-audit-head a { text-decoration: none; font-weight: 500; }

.portal-kb-audit-grid {
  display: grid;
  grid-template-columns: minmax(10rem, auto) minmax(0, 1fr);
  gap: 0.25rem 1rem;
  margin: 0;
}

.portal-kb-audit-grid dt { font-weight: 500; color: var(--portal-color-text-muted); }

.portal-kb-audit-grid dd { margin: 0; }

/* Linha do tempo do histórico (modal) */

.portal-kb-timeline { list-style: none; margin: 0; padding: 0; }

.portal-kb-timeline-item {
  display: flex;
  gap: 0.9rem;
  padding: 0.55rem 0 0.55rem 0.6rem;
  border-left: 3px solid var(--portal-color-border);
}

.portal-kb-timeline-item.aprovado { border-left-color: var(--bs-success); }

.portal-kb-timeline-item.rejeitado,
.portal-kb-timeline-item.remocao_pendente,
.portal-kb-timeline-item.removido { border-left-color: var(--bs-danger); }

.portal-kb-timeline-item.publicado { border-left-color: var(--portal-color-primary); }

.portal-kb-timeline-when {
  flex-shrink: 0;
  width: 8.5rem;
  font-size: 0.8rem;
  color: var(--portal-color-text-muted);
}

.portal-kb-difflegend {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.75rem;
  color: var(--portal-color-text-muted);
}

.portal-kb-difflegend span {
  width: 0.75rem;
  height: 0.75rem;
  border-radius: 0.2rem;
  display: inline-block;
}

.portal-kb-difflegend .add { background: color-mix(in srgb, var(--bs-success) 45%, transparent); }

.portal-kb-difflegend .del { background: color-mix(in srgb, var(--bs-danger) 45%, transparent); }

.portal-kb-diff {
  white-space: pre-wrap;
  word-break: break-word;
  max-height: 26rem;
  overflow: auto;
  font-size: 0.78rem;
  background: color-mix(in srgb, var(--portal-color-text) 5%, transparent);
  border-radius: var(--portal-radius-base);
  padding: 0.75rem;
  margin: 0;
}

/* Remetente das respostas: legenda discreta com o modelo, acima do balão */
.portal-chat-modelnote {
  font-size: 0.72rem;
  color: var(--portal-color-text-muted);
  margin: 0 0.15rem 0.2rem;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

/* Aviso de anexo (cortado no teto ou desviado para análise por código):
   sempre visível, nunca atrás do contador de ferramentas — corte silencioso
   induz conclusão sobre um pedaço achando que era o todo. */
.portal-chat-notice {
  font-size: 0.78rem;
  color: var(--portal-color-text-muted);
  background: color-mix(in srgb, var(--portal-color-primary) 7%, transparent);
  border: 1px solid color-mix(in srgb, var(--portal-color-primary) 18%, transparent);
  border-radius: 0.5rem;
  padding: 0.35rem 0.6rem;
  margin: 0 0.15rem 0.35rem;
  max-width: fit-content;
}

/* Contador de ferramentas na linha do remetente — expande/recolhe os chips */
.portal-chat-tools-toggle {
  border: 1px solid var(--portal-color-border);
  background: var(--portal-color-bg-surface);
  color: var(--portal-color-text-muted);
  border-radius: 50px;
  font-size: 0.68rem;
  padding: 0 0.45rem;
  line-height: 1.4;
}

.portal-chat-tools-toggle:hover {
  color: var(--portal-color-primary);
  border-color: var(--portal-color-primary);
}

/* ---------- Ícone/avatar do agente ---------- */

.portal-avatar-img {
  object-fit: cover;
  border: 1px solid var(--portal-color-border);
}

.portal-avatar-inline {
  width: 1.15rem;
  height: 1.15rem;
  border-radius: 50%;
  object-fit: cover;
  margin-right: 0.35rem;
  vertical-align: -0.2rem;
}

.portal-icon-picker {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}

.portal-icon-option {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.4rem;
  height: 2.4rem;
  border: 1px solid var(--portal-color-border);
  border-radius: 0.6rem;
  cursor: pointer;
  color: var(--portal-color-text-muted);
  font-size: 1.05rem;
  transition: border-color 0.12s ease, color 0.12s ease, background 0.12s ease;
}

.portal-icon-option input { display: none; }

.portal-icon-option:hover {
  border-color: color-mix(in srgb, var(--portal-color-primary) 45%, var(--portal-color-border));
  color: var(--portal-color-primary);
}

.portal-icon-option:has(input:checked) {
  background: color-mix(in srgb, var(--portal-color-primary) 15%, var(--portal-color-bg-surface));
  border-color: var(--portal-color-primary);
  color: var(--portal-color-primary);
}

/* ---------- Avisos (flash) como overlay ---------- */

.portal-toast-stack {
  position: fixed;
  top: 1rem;
  right: 1rem;
  z-index: 1090; /* acima de modais (1055) — o aviso pós-ação deve aparecer */
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  width: min(24rem, calc(100vw - 2rem));
  pointer-events: none;
}

.portal-toast {
  pointer-events: auto;
  margin: 0;
  padding: 0.55rem 2.2rem 0.55rem 0.9rem;
  font-size: 0.85rem;
  border-radius: var(--portal-radius-base);
  box-shadow: var(--portal-shadow-raised);
}

.portal-toast .btn-close {
  padding: 0.55rem;
  font-size: 0.7rem;
}

/* Gravação de voz no composer */

#chat-mic.recording {
  color: var(--bs-danger);
  border-color: var(--bs-danger);
  animation: portal-mic-pulse 1.2s ease-in-out infinite;
}

@keyframes portal-mic-pulse {
  50% { box-shadow: 0 0 0 0.35rem color-mix(in srgb, var(--bs-danger) 25%, transparent); }
}

/* Status do ditado por voz */

.portal-mic-status {
  font-size: 0.8rem;
  color: var(--portal-color-text-muted);
  padding-bottom: 0.4rem;
}

.portal-mic-status.error { color: var(--bs-danger); }

/* Modal de upload: zona de arrastar-e-soltar */
.portal-dropzone {
  border: 2px dashed var(--portal-color-border);
  border-radius: var(--portal-radius-base);
  padding: 2rem 1rem;
  text-align: center;
  background: color-mix(in srgb, var(--portal-color-bg-surface) 60%, var(--portal-color-bg-body));
  transition: border-color 0.15s ease, background-color 0.15s ease;
}

.portal-dropzone.dragover {
  border-color: var(--portal-color-primary);
  background: color-mix(in srgb, var(--portal-color-primary) 8%, var(--portal-color-bg-surface));
}

.portal-dropzone-icon {
  font-size: 2rem;
  color: var(--portal-color-text-muted);
  display: block;
  margin-bottom: 0.25rem;
}

.portal-dropzone.dragover .portal-dropzone-icon { color: var(--portal-color-primary); }

.portal-upload-feedback {
  font-size: 0.85rem;
  max-height: 9rem;
  overflow-y: auto;
}

.portal-upload-feedback li { padding: 0.1rem 0; }

/* Lista de aprovadores na tela de revisão */

.portal-kb-seats {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.45rem;
}

.portal-kb-seats li {
  display: flex;
  gap: 0.6rem;
  align-items: start;
}

/* Lista de arquivos recolhível (revisão de conteúdo nativo) */

.portal-filelist summary {
  cursor: pointer;
  color: var(--portal-color-primary);
}

.portal-filelist-items {
  margin-top: 0.4rem;
  max-height: 22rem;
  overflow-y: auto;
  padding-right: 0.4rem;
}

/* Barra de busca e ordenação das listas */

.portal-list-filter {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 0.9rem;
}

/* flex-shrink: 0 — dividindo a linha com outro bloco (as tags do catálogo)
   o campo encolhia e cortava o texto do placeholder */
.portal-list-filter-search { width: min(26rem, 100%); flex: 0 0 auto; }

/* Tags do catálogo: linha própria, logo abaixo da busca */
.portal-tag-filter {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  margin: -0.35rem 0 1rem;
}

/* `width: auto` fazia o select encolher até o texto passar por baixo da
   seta; a largura mínima reserva espaço para a opção mais longa. */
.portal-list-filter-sort { width: auto; }

.portal-list-filter-sort .form-select {
  width: auto;
  min-width: 13.5rem;
}

/* Aviso de histórico compactado no chat */

.portal-chat-compacted {
  margin: 0 auto 0.75rem;
  padding: 0.4rem 0.75rem;
  border-radius: var(--portal-radius-base);
  background: color-mix(in srgb, var(--portal-color-text) 5%, transparent);
  color: var(--portal-color-text-muted);
  font-size: 0.8rem;
  text-align: center;
}

/* Apresentação do agente (Markdown) na coluna lateral */

.portal-agent-about {
  font-size: 0.86rem;
  line-height: 1.55;
}

.portal-agent-about > :first-child { margin-top: 0; }

.portal-agent-about > :last-child { margin-bottom: 0; }

.portal-agent-about h1,
.portal-agent-about h2,
.portal-agent-about h3 { font-size: 0.95rem; margin-bottom: 0.4rem; }

.portal-agent-about ul,
.portal-agent-about ol { padding-left: 1.1rem; margin-bottom: 0.6rem; }

/* Indicadores do htmx — CSS que ele injetaria via <style> em runtime, o
 * que a CSP com nonce descarta. Servido daqui (includeIndicatorStyles
 * desligado no base.html), o comportamento é o padrão do htmx. */
.htmx-indicator { opacity: 0; transition: opacity 200ms ease-in; }
.htmx-request .htmx-indicator { opacity: 1; }
.htmx-request.htmx-indicator { opacity: 1; }

/* ---------- Mapa mental (artefato interativo — js/mindmap.js) ---------- */

.portal-mindmap-embed {
  width: 100%;
  max-width: 46rem;
  border: 1px solid var(--portal-color-border);
  border-radius: var(--portal-radius-base);
  background: var(--portal-color-bg-surface);
  overflow: hidden;
}

.portal-mindmap-embed:fullscreen {
  max-width: none;
  display: flex;
  flex-direction: column;
}

.portal-mindmap-toolbar {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.4rem 0.6rem;
  border-bottom: 1px solid var(--portal-color-border);
}

.portal-mindmap-title {
  margin-right: auto;
  font-size: 0.85rem;
  color: var(--portal-color-text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.portal-mindmap-stage {
  height: 22rem;
  cursor: grab;
  touch-action: none;
}

.portal-mindmap-embed:fullscreen .portal-mindmap-stage { flex: 1; height: auto; }

.portal-mindmap-embed { position: relative; }

/* Explicação do nó final, sobreposta ao canto do palco */
.portal-mindmap-info {
  position: absolute;
  left: 0.75rem;
  right: 0.75rem;
  bottom: 0.75rem;
  padding: 0.6rem 0.75rem;
  font-size: 0.85rem;
  background: var(--portal-color-bg-surface);
  border: 1px solid var(--portal-color-primary);
  border-radius: var(--portal-radius-base);
  box-shadow: var(--portal-shadow-raised);
  max-height: 45%;
  overflow-y: auto;
}

/* Gráfico interativo (js/chartview.js) — mesma moldura do mapa mental */
.portal-chart-embed {
  position: relative;
  width: 100%;
  max-width: 52rem;
  border: 1px solid var(--portal-color-border);
  border-radius: var(--portal-radius-base);
  background: var(--portal-color-bg-surface);
  overflow: hidden;
}

.portal-chart-embed:fullscreen {
  max-width: none;
  display: flex;
  flex-direction: column;
}

.portal-chart-toolbar {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.4rem 0.6rem;
  border-bottom: 1px solid var(--portal-color-border);
}

.portal-chart-title {
  margin-right: auto;
  font-size: 0.85rem;
  color: var(--portal-color-text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.portal-chart-stage {
  padding: 0.5rem 0.75rem 0.75rem;
}

/* Tooltip rico que segue o cursor. Só left/top/exibição vêm do JS; toda a
   aparência fica aqui (a CSP bloqueia estilo inline). Fundo escuro invertendo
   os tokens, para contrastar nos dois temas. */
.portal-chart-tip {
  position: fixed;
  z-index: 3;
  pointer-events: none;
  max-width: 18rem;
  padding: 0.5rem 0.6rem;
  font-size: 0.78rem;
  line-height: 1.4;
  white-space: pre-line;
  background: var(--portal-color-text);
  color: var(--portal-color-bg-surface);
  border-radius: var(--portal-radius-base);
  box-shadow: var(--portal-shadow-raised);
}

.portal-chart-embed:fullscreen .portal-chart-stage {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}

.portal-chart-stage svg {
  width: 100%;
  height: auto;
}

.portal-chart-embed:fullscreen .portal-chart-stage svg {
  max-height: 100%;
}

/* Opções do painel "Gerar entregável" */
.portal-generate-option {
  padding: 0.45rem 0.6rem;
  border: 1px solid var(--portal-color-border);
  border-radius: var(--portal-radius-base);
  cursor: pointer;
}

.portal-generate-option:has(input:checked) {
  border-color: var(--portal-color-primary);
  background: color-mix(in srgb, var(--portal-color-primary) 8%, transparent);
}

/* ---- Experiência guiada (app/agents/guided.py) ---------------------------
   Botões de sugestão: alternativas da pergunta ativa, próximos passos e
   sugestões de partida usam o MESMO componente — para o usuário é sempre a
   mesma promessa (clicar preenche a caixa, quem envia é ele). */
.portal-suggestions {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
  margin-top: .75rem;
}
.portal-suggestion-btn {
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  max-width: 100%;
  padding: .45rem .9rem;
  /* Precisa PARECER clicável: a versão discreta demais era lida como texto
     apagado, e ninguém clicava no que não parece botão. */
  border: 1px solid color-mix(in srgb, var(--portal-color-primary) 45%, transparent);
  border-radius: 999px;
  background: var(--portal-color-bg-surface);
  color: var(--portal-color-primary);
  font-size: .875rem;
  font-weight: 500;
  line-height: 1.3;
  text-align: left;
  cursor: pointer;
  box-shadow: 0 1px 2px rgb(0 0 0 / .06);
  transition: background-color .12s ease, border-color .12s ease, transform .12s ease;
}
/* sem glifo: o contorno e o fundo ja marcam o botao */
.portal-suggestion-btn:hover:not(:disabled) {
  background: color-mix(in srgb, var(--portal-color-primary) 12%, var(--portal-color-bg-surface));
  border-color: var(--portal-color-primary);
  transform: translateY(-1px);
}
.portal-suggestion-btn:active:not(:disabled) { transform: none; }
.portal-suggestion-btn:focus-visible {
  outline: 2px solid var(--portal-color-primary);
  outline-offset: 2px;
}
.portal-suggestion-btn:disabled {
  opacity: .55;
  cursor: default;
  color: var(--portal-color-text);
  border-color: color-mix(in srgb, var(--portal-color-text) 18%, transparent);
  box-shadow: none;
}
/* Alternativas da pergunta ativa (A/B/C) pesam mais que próximos passos:
   são a decisão que destrava a conversa. */
.portal-suggestions-opcoes .portal-suggestion-btn {
  background: color-mix(in srgb, var(--portal-color-primary) 10%, var(--portal-color-bg-surface));
}
.portal-suggestions-opcoes .portal-suggestion-btn { font-weight: 600; }
.portal-suggestion-id {
  flex-shrink: 0;
  color: var(--portal-color-text);
  min-width: 1.35rem;
  height: 1.35rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: color-mix(in srgb, var(--portal-color-primary) 30%, transparent);
  font-weight: 600;
  font-size: .75rem;
}
.portal-start-suggestions { margin-top: 1.25rem; }

/* Formulário de partida, na tela vazia e no modal de novos parâmetros */
.portal-start-form {
  max-width: 44rem;
  margin: 1.5rem auto 0;
  padding: 1rem 1.25rem;
  border: 1px solid color-mix(in srgb, var(--portal-color-text) 14%, transparent);
  border-radius: var(--portal-radius-base);
  background: color-mix(in srgb, var(--portal-color-primary) 5%, transparent);
}
.modal-body > .portal-start-form { margin-top: 0; border: 0; background: none; padding: 0; }
.portal-start-form-head { color: var(--portal-color-text); }

/* Construtor do formulário, na tela do agente */
.portal-startform-field {
  padding: .6rem .75rem;
  margin-bottom: .5rem;
  border: 1px solid color-mix(in srgb, var(--portal-color-text) 12%, transparent);
  border-radius: var(--portal-radius-base);
}
.portal-startform-preview {
  padding: .6rem .75rem;
  border-radius: var(--portal-radius-base);
  background: color-mix(in srgb, var(--portal-color-text) 6%, transparent);
}
.portal-startform-preview pre { white-space: pre-wrap; }

/* Protocolo exibido ao criador: texto longo, somente leitura */
.portal-protocol {
  white-space: pre-wrap;
  max-height: 60vh;
  overflow: auto;
  padding: .75rem;
  border-radius: var(--portal-radius-base);
  background: color-mix(in srgb, var(--portal-color-text) 6%, transparent);
}

/* "Ver como foi calculado" — o painel que separa análise auditável de
   caixa-preta. Recolhido por padrão: quem só quer o número não tropeça no
   código, e quem desconfia do resultado tem onde conferir. */
.portal-exec {
  margin-top: 0.4rem;
  font-size: 0.72rem;
  border: 1px solid var(--portal-color-border);
  border-radius: var(--portal-radius-base);
  background: color-mix(in srgb, var(--portal-color-primary) 4%, var(--portal-color-bg-surface));
  /* Ocupa só a largura do conteúdo — o painel é secundário, não deve puxar a
     linha inteira; abre até 100% quando o código dentro é largo. */
  width: fit-content;
  max-width: 100%;
  min-width: 0;
}

.portal-exec > summary {
  cursor: pointer;
  padding: 0.28rem 0.55rem;
  color: var(--portal-color-text-muted);
  list-style: none;
}

.portal-exec > summary::-webkit-details-marker { display: none; }

.portal-exec > summary:hover { color: var(--portal-color-primary); }

.portal-exec-ver { opacity: 0.8; }

.portal-exec-item {
  padding: 0.25rem 0.75rem 0.75rem;
  border-top: 1px solid var(--portal-color-border);
}

.portal-exec-cab {
  font-size: 0.78rem;
  color: var(--portal-color-text-muted);
  margin: 0.5rem 0 0.35rem;
}

.portal-exec-rotulo {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--portal-color-text-muted);
  margin: 0.5rem 0 0.2rem;
}

.portal-exec-status { font-weight: 650; }

.portal-exec-ok { color: var(--portal-color-success); }

/* Qualquer desfecho que não seja `ok` merece a mesma atenção visual: o valor
   da trilha está justamente em enxergar a tentativa que não deu certo. */
.portal-exec-erro,
.portal-exec-tempo,
.portal-exec-memoria,
.portal-exec-recusado { color: var(--portal-color-warning); }

.portal-exec pre {
  background: color-mix(in srgb, var(--portal-color-text) 8%, transparent);
  border: 1px solid var(--portal-color-border);
  border-radius: var(--portal-radius-base);
  padding: 0.5rem 0.7rem;
  margin: 0;
  font-size: 0.78rem;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  max-width: 100%;
}

/* Página intersticial do login OIDC (redirect por meta-refresh no corpo,
   para o proxy do cliente não reescrever o host no cabeçalho Location). */
.portal-auth-redirect {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 2rem;
  text-align: center;
  color: var(--portal-color-text);
  background: var(--portal-color-bg-body);
}
.portal-auth-redirect a {
  color: var(--portal-color-primary);
}

/* Documentos filhos no rodapé de um documento da KB: mesma escala do corpo
   (0,9rem), para não ficar maior que o texto do próprio documento. */
.portal-kb-children { font-size: 0.9rem; }
.portal-kb-children-title { font-size: 0.95rem; font-weight: 600; }

/* Lista com busca (filterlist.js) — usada nos vínculos da área de negócio.
   Só tokens --portal-*: cor literal quebraria num dos dois temas. */
.portal-filtered-out { display: none !important; }

.portal-picklist {
  max-height: 15rem;
  overflow-y: auto;
  border: 1px solid var(--portal-color-border);
  border-radius: 0.5rem;
  background: var(--portal-color-bg-surface);
}

.portal-picklist-item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  /* Compacta de propósito: com nome e e-mail em linhas separadas cada item
     ocupava o dobro, e uma lista de 40 pessoas virava rolagem infinita */
  padding: 0.3rem 0.7rem;
  line-height: 1.35;
  font-size: 0.9rem;
  border-bottom: 1px solid color-mix(in srgb, var(--portal-color-border) 45%, transparent);
  cursor: pointer;
  margin: 0;
}

.portal-picklist-item:last-child { border-bottom: 0; }

.portal-picklist-item:hover {
  background: color-mix(in srgb, var(--portal-color-primary) 8%, transparent);
}

.portal-picklist-item small { font-size: 0.85em; }

/* Nome e e-mail dividem a linha; nome longo corta em vez de empurrar o layout */
.portal-picklist-item > span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.portal-group-missing {
  color: var(--portal-color-warning);
}
