/* Jornadas — folha única.
   A persona primária não é técnica e usa isto no meio do dia de trabalho:
   a prioridade é legibilidade e densidade honesta, não efeito.

   Identidade de 2026-08-12: o protótipo "Visitantes · Jornadas", validado
   naquela tela, passa a valer para a plataforma inteira. Os tokens abaixo
   são a única fonte de verdade de cor, tipografia e forma — mexer aqui
   vale para todas as telas de uma vez, que é o ponto de existir um design
   system. Os NOMES seguem em português, pela convenção do resto do
   projeto. */

/* Self-hosted: a CSP do app é `style-src 'self'` de propósito (server.ts), e
   um `<link>` para fonts.googleapis.com seria bloqueado por ela. Servir por
   conta própria também evita entregar o IP de cada usuário ao Google a cada
   carregamento — num produto de rastreamento, isso não é detalhe. Todas as
   quatro são livres (Google Sans e Geist Mono viraram OFL; verificado em
   fonts.google.com/metadata/fonts, `"license":"ofl"`), de eixo variável, e
   vêm em dois subsets: `latin` cobre o português do dia a dia e carrega
   sozinho na maioria das telas; `latin-ext` só desce quando um caractere
   dele aparece. */
@font-face {
  font-family: 'Google Sans';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('/fonts/google-sans-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Google Sans';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('/fonts/google-sans-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Geist Mono';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('/fonts/geist-mono-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Geist Mono';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('/fonts/geist-mono-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* Estas duas não são mais o padrão, mas seguem servidas: são opções do
   catálogo de fontes em /admin → Aparência. */
@font-face {
  font-family: 'Plus Jakarta Sans';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url('/fonts/plus-jakarta-sans-variable.woff2') format('woff2');
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url('/fonts/jetbrains-mono-variable.woff2') format('woff2');
}

:root {
  /* Largura da coluna de navegação. Cabe o rótulo mais longo sem quebrar. */
  --lateral: 248px;

  /* Camadas de fundo: o protótipo distingue três, não duas — a página, o
     card, e um cinza intermediário para agrupar dentro do card (cabeçalho
     de tabela, linha de resumo). `--preenchimento` é uma quarta camada,
     opaca, para controle sobre superfície: botão secundário, chip, ícone
     de ação. Ela existe separada de `--superficie-2` porque as duas têm
     contraste e uso diferentes, e empilhar alpha sobre fundo desconhecido
     dá resultado imprevisível. */
  --fundo: #f9f9f9;
  --superficie: #ffffff;
  --superficie-2: #fafafa;
  --preenchimento: #f2f2f2;
  --preenchimento-hover: #eeeeee;
  /* Três tons de texto, e o do meio existe num alfa específico por
     contraste, não por gosto. O protótipo usa 56% (#2626268f) para
     rótulo de coluna, rótulo de KPI e domínio do cliente — medido, dá
     3.70:1 sobre branco e reprova no AA para texto pequeno. O próprio
     audit do design system diz isso ("black-alpha-56 → Large only; para
     texto pequeno relevante, prefira alpha 64 ou 72"). 65% é o menor
     alfa que cruza 4.5:1 nas três superfícies do app (branco 4.89,
     superfície-2 4.80, preenchimento 4.66) — mantém a hierarquia de três
     tons sem colapsar no `--texto-fraco`.

     `--texto-fraco-3` fica abaixo do limiar de propósito: é só para o
     que não carrega informação — placeholder, chevron, traço separador. */
  --texto: #262626;
  --texto-fraco: #262626b8;
  --texto-fraco-2: #262626a7;
  --texto-fraco-3: #26262666;
  --borda: #ededed;
  --borda-forte: #e0e0e0;

  /* ------------------------------------------------ a regra do acento
     Três tokens porque o laranja da marca NÃO serve como cor de texto, e
     esse é o erro que a separação evita. Números do audit do design
     system aprovado (seção 06):

       branco sobre #fa5d19 .... 3.16:1  ← reprova no AA (mín. 4.5:1)
       branco sobre #c63e00 .... 5.13:1  ← passa
       #262626 sobre #f9f9f9 ... 14.37:1

     `--acento`       só preenchimento e decoração: marca, pontos, ícones,
                      barras, tints, anel de foco. Nada de texto pequeno
                      em cima dele.
     `--acento-forte` preenchimento QUE CARREGA texto branco (botão CTA).
     `--acento-texto` o laranja como texto sobre fundo claro (link, hover).

     Onde o protótipo pedia laranja mas havia texto branco pequeno em cima
     — pílula de período ativa, avatar do seletor de cliente — a escolha é
     o preenchimento `--texto`, que é o que o próprio protótipo faz na
     pílula de operador selecionada. Laranja fica reservado à marca. */
  --acento: #fa5d19;
  --acento-forte: #c63e00;
  --acento-texto: #c63e00;
  --acento-fraco: #fa5d191f;
  --acento-tenue: #fa5d190a;
  --acento-anel: #fa5d1966;
  /* Hover do preenchimento forte. Token, e não hex na regra: sem ele a
     personalização do /admin repintava o botão mas não o hover dele. */
  --acento-forte-hover: #b83900;
  /* Distância vertical entre blocos de uma tela (§5.2, §6.2 do PRD). Um
     número só, para card, gráfico, fichas e seção não cada um o seu. */
  --espaco-secao: 20px;

  /* Semânticas. O par `-fraco`/`-texto` existe porque a cor cheia sobre o
     próprio tint não tem contraste: #42c366 sobre #e5f4e9 dá ~2:1.

     O verde de texto é o único valor que NÃO veio do protótipo: o
     #2b8c4a de lá dá 3.72:1 sobre o próprio tint, e reprova para texto
     pequeno. #25773f é o mesmo matiz escurecido até cruzar o limiar —
     4.87:1. Medido, não estimado. */
  --ok: oklch(45% 0.08 145);
  --ok-fraco: #e5f4e9;
  --ok-texto: #25773f;
  --erro: #eb3424;
  --erro-fraco: #f9e3e1;
  --erro-texto: #b3271a;
  --alerta: #ecb730;
  --alerta-fraco: #f9f1df;
  --alerta-texto: #8a6410;

  --raio-pequeno: 6px;
  --raio: 8px;
  --raio-medio: 10px;
  --raio-grande: 12px;
  --gap: 16px;
  --fonte: 'Google Sans', 'Product Sans', Roboto, -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
  --mono: 'Geist Mono', 'SFMono-Regular', ui-monospace, Consolas, monospace;

  --sombra-sm: 0 1px 2px 0 #0000000d;
  --sombra-pop: 0 12px 32px -8px #00000029, 0 2px 8px -2px #00000014;
  /* O brilho do botão primário e da marca — o que dá "temperatura" ao
     laranja sem depender de gradiente. */
  --sombra-marca: inset 0 -6px 12px #ff000033, 0 2px 4px #ff4d001f, 0 1px 1px #ff4d001f;

  /* Série do gráfico. Verde-orgânico em vez do laranja da marca: a cor
     passou por validação numérica documentada (DECISIONS.md, banda de
     luminosidade + piso de croma + ≥3:1 nas duas superfícies). Trocar
     exige revalidar — por isso ela NÃO acompanhou a virada de identidade. */
  --serie-1: oklch(45% 0.08 145);

  /* Tons de origem/canal de aquisição — 5 tons do protótipo (decisão #5 do
     redesign), substituindo os 11 pills coloridos que existiam antes. */
  --canal-organico: oklch(45% 0.08 145);
  --canal-direto: oklch(30% 0.01 60);
  --canal-pago: oklch(55% 0.13 55);
  --canal-referencia: oklch(45% 0.07 290);
  --canal-social: oklch(50% 0.12 25);

  /* Paleta determinística de avatar — hash do id escolhe o índice, sem
     guardar cor no banco. */
  --avatar-0: #9061ff;
  --avatar-1: #2a6dfb;
  --avatar-2: #42c366;
  --avatar-3: #eb3424;
  --avatar-4: #ecb730;
  --avatar-5: #fa5d19;
}

/* Paleta semântica de evento e canal — só modo claro. Dark mode foi
   removido do escopo do redesign (docs/02-delivery/redesign-design-system.md,
   decisão #6). */
:root {
  --identificacao: oklch(38% 0.03 290);
  --identificacao-fraco: oklch(93% 0.01 290);
  --informativo: oklch(40% 0.03 250);
  --informativo-fraco: oklch(93% 0.008 250);
  --clique: oklch(45% 0.06 55);
  --clique-fraco: oklch(93% 0.02 55);
  --retorno: oklch(50% 0.13 30);
  --retorno-fraco: oklch(93% 0.03 30);
}

* { box-sizing: border-box; }

/* `[hidden]` do navegador é regra de user-agent, e qualquer `display` escrito
   aqui a vence — um `button { display: inline-block }` faria o elemento
   escondido continuar na tela. O `!important` é o que devolve ao atributo o
   significado que ele já deveria ter. */
[hidden] { display: none !important; }

body {
  margin: 0;
  font-family: var(--fonte);
  /* 14px é a densidade do protótipo: são telas de tabela, lidas no meio do
     dia de trabalho, onde caber mais linha sem apertar vale mais do que
     corpo grande. */
  font-size: 14px;
  line-height: 1.5;
  color: var(--texto);
  background: var(--fundo);
  -webkit-font-smoothing: antialiased;
}

::selection { background: color-mix(in srgb, var(--acento) 20%, transparent); color: var(--acento); }

.pular {
  position: absolute;
  left: -9999px;
}
.pular:focus {
  left: 8px;
  top: 8px;
  padding: 8px 12px;
  background: var(--superficie);
  border: 2px solid var(--acento);
  border-radius: var(--raio);
  z-index: 10;
}

/* ---------------------------------------------------------------- topo */

.casca {
  display: grid;
  grid-template-columns: var(--lateral) 1fr;
  min-height: 100vh;
}

.lateral {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 12px 12px 16px;
  border-right: 1px solid var(--borda);
  background: var(--superficie-2);
  /* Fixa: a navegação some ao rolar uma lista longa se acompanhar o scroll,
     e Atividades e Ao Vivo são justamente listas longas. */
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
}

.area { min-width: 0; }

.marca {
  font-weight: 700;
  letter-spacing: -0.01em;
  text-decoration: none;
  color: var(--texto);
  padding: 6px 6px 14px;
}

/* Menu em seções, como o protótipo: rótulo em caixa alta + itens com ícone. */
.nav-secoes { display: flex; flex-direction: column; gap: 18px; flex: 1; }

.nav-secao { display: flex; flex-direction: column; gap: 1px; }

.nav-rotulo {
  font-family: var(--mono);
  font-size: 10px;
  color: var(--texto-fraco-2);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  padding: 0 6px 6px;
}

.nav-secao a {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 8px;
  border-radius: var(--raio);
  text-decoration: none;
  color: var(--texto-fraco);
  white-space: nowrap;
  font-size: 13px;
}

.nav-secao a:hover { color: var(--texto); background: color-mix(in oklch, var(--texto) 5%, transparent); }

.nav-secao a[aria-current="page"] {
  color: var(--texto);
  background: var(--superficie);
  font-weight: 550;
  box-shadow: inset 0 0 0 1px var(--borda);
}

.ico { width: 14px; height: 14px; opacity: 0.7; flex-shrink: 0; }
.nav-secao a[aria-current="page"] .ico { opacity: 1; }
.ico-vivo { display: grid; place-items: center; }

.ponto-vivo {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--acento);
  animation: pulso-vivo 1.8s infinite;
  display: inline-block;
}
@keyframes pulso-vivo {
  0% { box-shadow: 0 0 0 0 color-mix(in oklch, var(--acento) 45%, transparent); }
  70% { box-shadow: 0 0 0 5px transparent; }
  100% { box-shadow: 0 0 0 0 transparent; }
}

/* Rodapé do menu: Configurações + Sair da conta (protótipo). */
.lateral-rodape {
  margin-top: auto;
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding-top: 10px;
  border-top: 1px dotted var(--borda-forte);
}
.lateral-rodape a,
.lateral-rodape .rodape-sair {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 8px;
  border-radius: var(--raio);
  color: var(--texto-fraco);
  font-size: 13px;
  text-decoration: none;
}
.lateral-rodape form { margin: 0; display: flex; }
.lateral-rodape .rodape-sair {
  background: none; border: 0; cursor: pointer; width: 100%;
  font: inherit; font-size: 13px; text-align: left;
}
.lateral-rodape a:hover,
.lateral-rodape .rodape-sair:hover { color: var(--texto); background: color-mix(in oklch, var(--texto) 5%, transparent); }
.lateral-rodape a[aria-current="page"] {
  color: var(--texto);
  background: var(--superficie);
  font-weight: 550;
  box-shadow: inset 0 0 0 1px var(--borda);
}

/* Abaixo de 900px o menu deita e vira uma faixa no topo: uma coluna fixa de
   220px numa tela de celular come um terço da largura útil. */
@media (max-width: 900px) {
  .casca { grid-template-columns: 1fr; }
  .lateral {
    position: static;
    height: auto;
    flex-direction: row;
    align-items: center;
    gap: 12px;
    padding: 0 16px;
    border-right: none;
    border-bottom: 1px solid var(--borda);
  }
  .nav-secoes { flex-direction: row; overflow-x: auto; gap: 4px; align-items: center; }
  .nav-secao { flex-direction: row; }
  .nav-rotulo { display: none; }
  .nav-secao a[aria-current="page"] { box-shadow: inset 0 -2px 0 var(--acento); }
  .lateral-rodape { margin-top: 0; padding-top: 0; border-top: none; flex-direction: row; }
  .marca { padding: 14px 0; }
  .seletor-cliente { display: none; }
}

/* --------------------------------------------------------- seletor de cliente */
/* Só administração de plataforma vê isto (layout.ts renderiza condicionado a
   `options.companies`). `<details>` nativo em vez de JS: o mesmo padrão de
   `.dia` em Atividades, sem precisar de script para abrir/fechar. */

/* O gatilho é o avatar redondo de 36px da direita da topbar, do protótipo.
   Redondo, e não quadrado como o avatar de visitante, porque aqui é conta e
   não pessoa listada — a forma já diz que são coisas diferentes. */
.seletor-cliente {
  position: relative;
  flex: none;
}
.seletor-cliente summary {
  display: grid; place-items: center;
  width: 36px; height: 36px;
  border-radius: 999px;
  border: 1px solid var(--borda);
  background: var(--superficie);
  color: var(--texto);
  cursor: pointer;
  list-style: none;
}
.seletor-cliente summary::-webkit-details-marker { display: none; }
.seletor-cliente summary:hover { background: var(--superficie-2); border-color: var(--borda-forte); }
.seletor-cliente[open] summary {
  border-color: var(--acento);
  box-shadow: 0 0 0 3px var(--acento-fraco);
}
/* Com um cliente assumido, o avatar mostra as iniciais dele — é o que
   responde "em que conta eu estou?" sem ocupar linha nenhuma. Preto, e não
   a cor da marca: são iniciais brancas a 11px, tamanho em que os 3.16:1 do
   laranja reprovam. */
.sc-iniciais {
  display: grid; place-items: center;
  width: 100%; height: 100%;
  border-radius: 999px;
  background: var(--texto); color: #fff;
  font-size: 11px; font-weight: 700; letter-spacing: -0.02em;
}

.sc-menu {
  display: none;
  flex-direction: column;
  gap: 2px;
  position: absolute; top: calc(100% + 6px); right: 0; z-index: 60;
  width: 264px;
  max-height: 360px; overflow-y: auto;
  background: var(--superficie); border: 1px solid var(--borda); border-radius: var(--raio-grande);
  box-shadow: var(--sombra-pop); padding: 6px;
}
.seletor-cliente[open] .sc-menu { display: flex; }
.sc-menu form { margin: 0; }
.sc-item {
  display: flex; align-items: center; gap: 8px;
  width: 100%;
  padding: 7px 8px; border-radius: var(--raio);
  font-size: 12px; color: var(--texto);
  text-align: left;
  background: none; border: none; cursor: pointer;
}
.sc-item:hover { background: #00000008; }
/* O cliente em que se está usa o tint da marca, e o quadradinho de iniciais
   inverte para preto — o mesmo par do protótipo. */
.sc-item.active { background: var(--acento-tenue); font-weight: 500; }
.sc-item.active .sc-item-avatar { background: var(--texto); color: #fff; }
.sc-item-sem-workspace { opacity: 0.5; cursor: default; }
.sc-item-sem-workspace:hover { background: none; }
.sc-item-avatar {
  width: 18px; height: 18px; border-radius: 5px; flex: none;
  background: var(--superficie-2); color: var(--texto-fraco);
  display: grid; place-items: center;
  font-size: 8px; font-weight: 700;
}
/* O nome do cliente é o que se procura na lista; o domínio é desempate.
   Sem deixar o domínio encolher, ele mantinha a largura natural e comia o
   nome ("DEM…", "Clínica Be…") — agora quem trunca primeiro é o domínio. */
.sc-item-nome { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sc-item-dominio {
  flex: 0 1 auto; min-width: 0; max-width: 40%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-family: var(--mono); font-size: 10px; color: var(--texto-fraco-2);
}
/* Sair do workspace: separado da lista por um fio, porque é ação e não
   escolha — e é o único caminho de volta para a visão de plataforma desde
   que a faixa de aviso saiu do topo. */
.sc-sair {
  justify-content: center;
  margin-top: 2px;
  padding-top: 9px;
  border-top: 1px solid var(--borda);
  border-radius: 0;
  color: var(--acento-texto);
  font-weight: 500;
}
.sc-sair:hover { background: var(--acento-fraco); }
.sc-vertodos {
  display: block; text-align: center;
  padding: 8px; margin-top: 2px; border-top: 1px dotted var(--borda-forte);
  font-size: 12px; color: var(--texto-fraco);
}
.sc-vertodos:hover { color: var(--texto); }

/* -------------------------------------------------------------- corpo */

/* Sem teto de largura: são telas de dado, e um limite de 1180px deixava
   tabela larga rolando por dentro enquanto sobrava tela dos lados. */
main {
  max-width: none;
  margin: 0 auto;
  padding: 20px 24px 40px;
}

h1 {
  font-size: 24px;
  font-weight: 500;
  letter-spacing: -0.02em;
  margin: 0 0 4px;
}

h2 { font-size: 17px; font-weight: 500; margin: 0 0 8px; }

.legenda {
  color: var(--texto-fraco);
  margin: 0 0 20px;
  font-family: var(--mono);
  font-size: 13px;
}

/* Aviso tonal: fundo do tom + texto da versão escura dele. A cor cheia
   como texto sobre o próprio tint não tem contraste — mesma correção que
   `.etiqueta` faz. A borda fica neutra para o bloco não virar moldura
   colorida. */
.aviso {
  margin: 16px 24px 0;
  padding: 12px 16px;
  border-radius: var(--raio-grande);
  border: 1px solid var(--borda);
  background: var(--superficie);
  font-size: 13px;
}
.aviso.ok { background: var(--ok-fraco); color: var(--ok-texto); }
.aviso.erro { background: var(--erro-fraco); color: var(--erro-texto); }
.aviso.atencao { background: var(--alerta-fraco); color: var(--alerta-texto); }

.fraco { color: var(--texto-fraco); }

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

.filtros {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: flex-end;
  padding: 14px 16px;
  background: var(--superficie);
  border: 1px solid var(--borda);
  border-radius: var(--raio-grande);
  box-shadow: var(--sombra-sm);
  margin-bottom: 16px;
}

.campo { display: flex; flex-direction: column; gap: 5px; }
.campo label { font-size: 12px; font-weight: 450; color: var(--texto-fraco); }
/* Sobre superfície branca o campo precisa se distinguir do card que o
   contém: fundo levemente recuado, que vira branco ao focar. */
.filtros input, .filtros select, .filtros textarea { background: var(--superficie-2); }
.filtros input:focus, .filtros select:focus, .filtros textarea:focus { background: var(--superficie); }
/* Campo que merece a largura da linha — chave de API, URL longa. */
.campo-largo { flex: 1; min-width: 320px; }
/* Escopos da chave de API: um fieldset com dez checkboxes não cabe como mais
   um item da linha de `.filtros` — ele é bem mais alto que um campo de uma
   linha, e o `align-items: flex-end` do `.filtros` empurraria os campos
   curtos para o fim de uma linha tão alta quanto o fieldset. Por isso vem
   como bloco próprio, abaixo da linha de campos curtos, e não dentro dela. */
.escopos-da-chave {
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  padding: 12px;
  margin: 8px 0 16px;
}
.escopos-da-chave legend { font-size: 12px; color: var(--texto-fraco); padding: 0 4px; }
.opcao { display: inline-flex; align-items: center; gap: 4px; margin: 2px 12px 2px 0; font-size: 13px; }
/* Utilitárias para o que era `style="..."` inline — a CSP (style-src 'self')
   bloqueia atributo de estilo, então todo ajuste pontual de layout precisa
   ser classe, mesmo quando só um lugar usa. */
.flex-1 { flex: 1; }
.filtros.centralizado { align-items: center; }
.alinhar-centro { align-self: center; }

input, select, textarea, button {
  font: inherit;
  padding: 7px 10px;
  border-radius: var(--raio);
  border: 1px solid var(--borda);
  background: var(--superficie);
  color: var(--texto);
}
input::placeholder, textarea::placeholder { color: var(--texto-fraco-3); }

/* Campo focado: a borda vira laranja e um anel fino confirma. O anel é
   `--acento-fraco` (12%) e não a cor cheia porque ele fica *fora* da
   borda — cheio, viraria um segundo contorno competindo com ela. */
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--acento);
  box-shadow: 0 0 0 3px var(--acento-fraco);
}

/* Foco de teclado: 2px cheios com folga. Uma versão anterior desta folha
   usou `--acento` a 40% e sem `outline-offset` — some contra borda clara,
   e é justamente quem navega por teclado que não pode perder o rastro. */
input:focus-visible, select:focus-visible, textarea:focus-visible,
button:focus-visible, a:focus-visible, summary:focus-visible {
  outline: 2px solid var(--acento);
  outline-offset: 2px;
}

/* Botão primário: `--acento-forte`, não `--acento`. Texto branco a 13px
   sobre #fa5d19 dá 3.16:1 e reprova no AA; sobre #c63e00 dá 5.13:1. O
   brilho de marca (`--sombra-marca`) é o que devolve a temperatura do
   laranja que o tom mais fundo tira. */
button, .botao {
  cursor: pointer;
  background: var(--acento-forte);
  /* `border` inteiro, e `padding` explícito aqui — não só `border-color` —
     porque a regra `input, select, button` acima só mira o elemento
     `button`. Um `<a class="botao">` nunca herda nada dela: sem borda, só a
     cor não desenha nada; sem padding, o texto cola na borda. As duas
     faltando é o que deixa `.botao.secundario` feito de `<a>` (a maioria no
     app) parecendo texto solto em vez de botão — foi assim que "Insight
     desta tela" e "Exportar CSV" foram encontrados quebrados. */
  border: 1px solid var(--acento-forte);
  padding: 8px 14px;
  color: #fff;
  text-decoration: none;
  display: inline-block;
  border-radius: var(--raio-medio);
  font-size: 13px;
  font-weight: 450;
  box-shadow: var(--sombra-marca);
  transition: background .2s, box-shadow .1s, transform .1s;
}
button:hover, .botao:hover { background: var(--acento-forte-hover); }
button:active, .botao:active { transform: scale(.995); }

button.secundario, .botao.secundario {
  background: var(--preenchimento);
  color: var(--texto);
  border: 1px solid transparent;
  box-shadow: none;
}
button.secundario:hover, .botao.secundario:hover { background: var(--preenchimento-hover); }

/* Terceiro nível: só contorno, para ação destrutiva ou de saída. */
button.discreto, .botao.discreto {
  background: transparent;
  color: var(--texto-fraco);
  border: 1px solid var(--borda);
  box-shadow: none;
}
button.discreto:hover, .botao.discreto:hover { color: var(--texto); border-color: var(--borda-forte); }

button[disabled], .botao[disabled], button:disabled {
  background: #f4f4f4;
  border-color: transparent;
  color: var(--texto-fraco-3);
  box-shadow: none;
  cursor: not-allowed;
  transform: none;
}

/* Variante compacta, para barras de ferramenta. 28px é a altura de
   controle secundário do protótipo; o raio acompanha (8, não 10). */
button.pequeno, .botao.pequeno {
  padding: 4px 12px;
  border-radius: var(--raio);
  font-size: 12px;
}

/* O app usa `<button>` para coisas que não são botão primário — link,
   item de menu, ícone de ação, chip. Cada uma já zerava fundo e borda por
   conta própria; o brilho de marca é novo e precisa ser zerado no mesmo
   lugar, senão vaza um halo laranja em cima delas (foi assim que "Sair da
   conta" apareceu com fundo alaranjado na lateral). Lista explícita, e
   não `:not(...)` encadeado, para ser greppável quando surgir a próxima. */
.link,
.rodape-sair,
.sc-item,
.acao-icone,
.chip-adicionar,
.ia-fechar,
.pv-voltar,
.pv-campo-btn,
.pv-acao,
.abas a,
.periodos a {
  box-shadow: none;
}
/* A exceção da lista: a ação principal da barra é botão de verdade e leva o
   brilho de propósito. Vem depois para vencer o reset acima. */
.pv-acao-forte { box-shadow: var(--sombra-marca); }

/* `.link`, não `button.link`: as poucas ocorrências de `<a class="link">`
   pelo app (ex.: "Gerar imagem" em encurtador.ts) não bateriam em uma regra
   presa ao elemento `button` — mesma família de bug do `.botao`, e ficavam
   com a cor azul padrão do navegador em vez do estilo do app. */
.link {
  background: none;
  border: none;
  color: var(--texto-fraco);
  padding: 0;
  text-decoration: underline;
  border-radius: 0;
}
.link:hover { color: var(--texto); }

/* ---------------------------------------------------- ações de linha (ícone) */
/* Ação de tabela como ícone, não palavra sublinhada — "editar"/"excluir" e
   afins ganham reconhecimento visual imediato, e várias ações na mesma
   linha (Modais: pausar/duplicar/arquivar) deixam de competir por espaço
   como texto grudado. O rótulo continua existindo — em `aria-label` e
   `title` — só não fica desenhado o tempo todo. Divide `.acoes-linha` (linha
   468) com os grupos que ainda são texto — o gap dela já foi ajustado para
   servir aos dois. */
.acao-icone {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  border: none;
  border-radius: 6px;
  background: transparent;
  color: var(--texto-fraco);
  cursor: pointer;
}
.acao-icone .ico { opacity: 1; width: 15px; height: 15px; }
.acao-icone:hover { background: var(--superficie-2); color: var(--texto); }
.acao-icone.perigo:hover { background: var(--erro-fraco); color: var(--erro-texto); }

/* --------------------------------------------------- chips de filtro (fchip) */
/* Componente novo da Fase 0 — CSS pronto, ainda não ligado a nenhuma tela
   (isso é trabalho de P2 por página: Atividades, Visitantes, Ao Vivo,
   Páginas). Espelha `.fchip`/`.fdrop` do protótipo. */

.chips-filtro {
  display: flex; align-items: center; gap: 6px;
  padding: 8px 12px;
  background: var(--superficie);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  margin-bottom: 12px;
  flex-wrap: wrap;
  position: relative;
}

.fchip {
  display: inline-flex; align-items: stretch;
  background: var(--superficie);
  border: 1px solid var(--borda);
  border-radius: 100px;
  font-size: 11px; font-family: var(--mono);
  overflow: hidden;
  height: 22px;
}
.fchip:hover { border-color: var(--borda-forte); }
.fchip > span { display: inline-flex; align-items: center; padding: 0 8px; border-right: 1px solid var(--borda); }
.fchip > span:last-of-type { border-right: 0; }
.fchip .fc-campo { color: var(--texto-fraco); background: var(--superficie-2); }
.fchip .fc-op { color: var(--texto-fraco-2); padding: 0 6px; font-style: italic; }
.fchip .fc-valor { color: var(--texto); font-weight: 500; max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding-right: 6px; }
.fchip .fc-remover {
  padding: 0 8px 0 4px; color: var(--texto-fraco-2); cursor: pointer; border-left: 0 !important;
  text-decoration: none; display: inline-flex; align-items: center;
}
.fchip .fc-remover:hover { color: var(--erro-texto); }

.chip-adicionar {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 10px; font-size: 11px; color: var(--texto-fraco);
  border: 1px dashed var(--borda-forte); border-radius: 100px;
  background: transparent;
  font-family: var(--mono);
}
.chip-adicionar:hover { color: var(--texto); border-color: var(--texto-fraco); }

/* -------------------------------------------------------------- tabela */
/* Toda tabela do app vive dentro de um cartão de borda e canto — o mesmo
   desenho que a lista de Visitantes provou. O cabeçalho é sans e claro,
   não mono maiúsculo: em coluna estreita, versalete em mono come largura
   que o dado precisa. */

.tabela-wrap {
  overflow: auto;
  border: 1px solid var(--borda);
  border-radius: var(--raio-grande);
  background: var(--superficie);
  margin-bottom: 16px;
}

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

th, td {
  text-align: left;
  padding: 0 16px;
  border-bottom: 1px solid var(--borda);
  vertical-align: middle;
}

th {
  position: sticky;
  top: 0;
  z-index: 2;
  height: 46px;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--texto-fraco-2);
  font-weight: 500;
  font-family: var(--fonte);
  white-space: nowrap;
  background: var(--superficie);
}

td {
  height: 52px;
  color: var(--texto-fraco);
}
/* Célula que quebra em várias linhas (lista de escopos, URL longa) precisa
   crescer — a altura fixa vira mínima nesse caso. */
td.quebra, td .quebra { white-space: normal; }
tr:last-child td { border-bottom: 0; }

td.num, th.num { text-align: left; font-family: var(--mono); font-size: 12px; color: var(--texto); font-variant-numeric: tabular-nums; }

tbody tr:hover { background: #00000003; }

/* Linha clicável (P2 Clientes) — só quando há `data-goto-form` de fato,
   não a string vazia que `linha()` deixa em clientes sem workspace. */
tbody tr[data-goto-form]:not([data-goto-form=""]) { cursor: pointer; }

td a { color: var(--texto); text-decoration: none; }
td a:hover { color: var(--acento-texto); }

code, .mono { font-family: var(--mono); font-size: 12px; }

/* ---------------------------------------------------- etiqueta e status */
/* Um selo só para a plataforma inteira. Antes havia dois desenhos fazendo
   o mesmo trabalho — `.etiqueta` (contornada, mono, MAIÚSCULA) em 16
   telas e `.status-pill` (preenchida, sans) em Visitantes. Ganhou a
   preenchida: em tabela densa o contorno some, e MAIÚSCULA em mono
   custa largura que a coluna não tem.

   O tom preenchido usa sempre o par `-fraco`/`-texto`: a cor cheia sobre
   o próprio tint não tem contraste (#42c366 sobre #e5f4e9 dá ~2:1). O
   ponto à esquerda herda `currentColor`, então acompanha o tom sozinho —
   e é ele que faz o selo funcionar para quem não distingue as cores. */

.etiqueta, .status-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 24px;
  padding: 3px 9px;
  border: 0;
  border-radius: 999px;
  background: var(--preenchimento);
  color: var(--texto-fraco);
  font-family: var(--fonte);
  font-size: 11.5px;
  font-weight: 450;
  letter-spacing: 0;
  text-transform: none;
  white-space: nowrap;
}
.etiqueta::before, .status-pill::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}

.etiqueta.online, .etiqueta.ativa, .status-pill.sp-live {
  background: var(--ok-fraco);
  color: var(--ok-texto);
}
.etiqueta.erro { background: var(--erro-fraco); color: var(--erro-texto); }
.etiqueta.atencao { background: var(--alerta-fraco); color: var(--alerta-texto); }
.etiqueta.ignorada { opacity: 0.65; }

/* Lead é o único estado que usa a marca: virar lead é o evento que o
   produto existe para capturar, e o laranja marca isso. Como texto sobre
   tint, o tom é `--acento-texto` (5.13:1), nunca `--acento`. */
.status-pill.sp-lead { background: var(--acento-fraco); color: var(--acento-texto); }
.status-pill.sp-anon { background: var(--preenchimento); color: var(--texto-fraco-2); }

/* --------------------------------------------------------------- vazio */

.vazio {
  text-align: center;
  padding: 56px 24px;
  border: 1px dashed var(--borda);
  border-radius: var(--raio);
  color: var(--texto-fraco);
}
.vazio h2 { color: var(--texto); }
.vazio .botao { margin-top: 12px; }

/* -------------------------------------------------------------- login */

.login {
  max-width: 380px;
  margin: 12vh auto;
  padding: 28px;
  border: 1px solid var(--borda);
  border-radius: var(--raio-grande);
  background: var(--superficie);
}
.login h1 { margin-bottom: 20px; }
.login .campo { margin-bottom: 14px; }
.login input { width: 100%; }
.login button { width: 100%; padding: 10px; }
.login .erro { color: var(--erro-texto); margin-bottom: 14px; }
.login select { width: 100%; }
.login .link-secundário { margin-top: 14px; text-align: center; font-size: 0.9em; color: var(--texto-2); }

/* ------------------------------------------------------------ timeline */

.sessao {
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  margin-bottom: 16px;
  overflow: hidden;
}

.sessao > header {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: baseline;
  padding: 10px 14px;
  background: var(--superficie-2);
  border-bottom: 1px solid var(--borda);
  font-size: 14px;
}

.linha-evento {
  display: grid;
  grid-template-columns: 84px 1fr;
  gap: 12px;
  padding: 8px 14px;
  border-bottom: 1px solid var(--borda);
}
.linha-evento:last-child { border-bottom: none; }
.linha-evento .quando { color: var(--texto-fraco); font-variant-numeric: tabular-nums; }

/* ------------------------------------------------------------ paginação */

.paginacao {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 16px;
  color: var(--texto-fraco);
  font-size: 14px;
}

/* ----------------------------------------------------------------- abas */
/* Abas de seção dentro de um módulo. Sublinhado, e não pílula, para não
   disputar com .periodos — as duas linhas convivem na mesma tela. */

.abas {
  display: flex;
  gap: 2px;
  margin: 4px 0 18px;
  border-bottom: 1px solid var(--borda);
  flex-wrap: wrap;
}
.abas a {
  padding: 8px 14px;
  background: transparent;
  text-decoration: none;
  color: var(--texto-fraco);
  font-size: 13px;
  border: 0;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  margin-bottom: -1px;
}
.abas a:hover { color: var(--texto); }
/* O sublinhado pode ser `--acento` cheio: é traço, não texto — a regra de
   contraste vale para o que carrega letra em cima. */
.abas a.ativa {
  color: var(--texto);
  border-bottom-color: var(--acento);
  font-weight: 500;
}

/* Barra proporcional das listas "mais frequentes". SVG com `width` como
   atributo de geometria, e não CSS: a largura varia por linha, calculada no
   servidor, e a CSP (style-src 'self') bloqueia atributo `style` inline —
   um `width` em porcentagem no viewBox não é estilo, então não esbarra nela. */
.barra { width: 100%; height: 14px; display: block; overflow: visible; }
.barra rect { fill: var(--acento); opacity: 0.75; }
.col-volume { width: 38%; }
/* Barra + número lado a lado, quando a barra não é a coluna inteira. */
.barra-linha { display: flex; align-items: center; gap: 8px; }
.barra-linha .barra { flex: 1; width: auto; }

/* Passo a passo curto, para fluxo guiado. */
.passos { margin: 0 0 14px; padding-left: 22px; list-style: decimal; }
.passos li { margin-bottom: 6px; }

/* ------------------------------------------------------------- períodos */

.periodos { display: flex; gap: 4px; margin-bottom: 16px; flex-wrap: wrap; }
.periodos a {
  display: inline-flex;
  align-items: center;
  min-height: 32px;
  padding: 4px 14px;
  border: 1px solid var(--borda);
  border-radius: 999px;
  background: var(--superficie);
  text-decoration: none;
  color: var(--texto-fraco);
  font-size: 13px;
  white-space: nowrap;
}
.periodos a:hover { color: var(--texto); border-color: var(--borda-forte); background: var(--superficie-2); }
/* Preto, não laranja: branco sobre #fa5d19 dá 3.16:1 e reprova no AA, e o
   protótipo já resolve assim na pílula de operador selecionada — a marca
   fica reservada ao que não carrega texto. #262626 dá 14.37:1. */
.periodos a.ativo {
  background: var(--texto);
  border-color: var(--texto);
  color: #fff;
  font-weight: 500;
}
.periodos a.ativo:hover { background: var(--texto); color: #fff; }

/* --------------------------------------------------------------- fichas */
/* Tira de KPIs (equivalente a `.stat-strip` do protótipo): um container só,
   com divisórias entre células, em vez de cards soltos — reaproveita a mesma
   marcação (`.fichas` > `.ficha`) que toda tela já usa. */

/* O fio sai da própria célula, projetado para fora (`box-shadow` sem
   `inset`), e o `overflow: hidden` do container apara o que passa da
   borda. Assim a divisória aparece entre células em qualquer quebra de
   linha, e a sobra da última fileira continua branca — o `gap` sobre
   fundo colorido, que seria o caminho óbvio, pintava esse vazio de
   cinza. */
.fichas {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  background: var(--superficie);
  border: 1px solid var(--borda);
  border-radius: var(--raio-grande);
  margin-bottom: 16px;
  overflow: hidden;
}

.ficha {
  padding: 14px 16px;
  box-shadow: 1px 0 0 var(--borda), 0 1px 0 var(--borda);
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.ficha .rotulo {
  font-size: 10px; font-family: var(--mono); text-transform: uppercase; letter-spacing: 0.1em;
  color: var(--texto-fraco-2);
}

/* Figuras proporcionais: número grande com dígito de largura fixa fica
   frouxo. Tabular fica para as colunas das tabelas. */
/* 32px: o número é o que se lê de relance, e a variação embaixo dele
   passou a dividir o espaço — o destaque precisa vencer os dois vizinhos. */
.ficha .valor { font-size: 32px; line-height: 36px; font-weight: 500; letter-spacing: -0.02em; }

.ficha .delta { font-size: 11px; font-family: var(--mono); color: var(--texto-fraco); }
.ficha .delta.sobe { color: var(--ok-texto); }
.ficha .delta.desce { color: var(--erro-texto); }
.ficha .valor.alerta { color: var(--alerta-texto); }
.ficha .valor.valor-canal { font-size: 16px; }

@media (max-width: 720px) {
  .fichas { grid-template-columns: 1fr 1fr; }
}

/* -------------------------------------------------------------- gráfico */

.grafico {
  position: relative;
  margin: 0 0 24px;
  padding: 16px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  background: var(--superficie);
}

.grafico figcaption {
  font-size: 13px;
  color: var(--texto-fraco);
  margin-bottom: 8px;
}

/* Altura automática, não fixa: o `viewBox` mantém a proporção (`meet`), e
   travar a altura letterboxaria o desenho. Ver o comentário em chart.ts. */
.grafico svg { width: 100%; height: auto; display: block; overflow: visible; }

/* Grade e eixos recessivos: o dado é que precisa aparecer. */
.grafico .grade { stroke: var(--borda); stroke-width: 1; }
/* 14 é em unidade de `viewBox`, não em pixel de tela: com a caixa de 1200 de
   largura, numa janela usual isso cai perto dos 11px do resto da interface. */
.grafico .tick { fill: var(--texto-fraco); font-size: 14px; font-variant-numeric: tabular-nums; }

.grafico .linha {
  fill: none;
  stroke: var(--serie-1);
  stroke-width: 2;
  stroke-linejoin: round;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}

.grafico .area { fill: var(--serie-1); opacity: 0.1; stroke: none; }
.grafico .ponto-final { fill: var(--serie-1); stroke: var(--superficie); stroke-width: 2; }

.grafico .alvo rect { fill: transparent; }
.grafico .alvo:focus-visible rect { fill: var(--acento-fraco); outline: none; }

.grafico .cursor line { stroke: var(--texto-fraco); stroke-width: 1; stroke-dasharray: 3 3; }
.grafico .cursor circle { fill: var(--serie-1); stroke: var(--superficie); stroke-width: 2; }
.grafico .cursor[hidden] { display: none; }

.grafico .dica {
  position: absolute;
  bottom: 16px;
  transform: translateX(-50%);
  background: var(--texto);
  color: var(--fundo);
  padding: 5px 10px;
  border-radius: 6px;
  font-size: 12px;
  white-space: nowrap;
  pointer-events: none;
}

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

.colunas {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 24px;
}

/* ------------------------------------------------------------ atividades */

.resumo-feed {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
  padding: 10px 0;
  font-size: 14px;
  color: var(--texto-fraco);
}
.resumo-feed strong { color: var(--texto); font-variant-numeric: tabular-nums; }

.feed-topo {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
  justify-content: space-between;
  padding-bottom: 10px;
}

.ao-vivo { display: flex; gap: 10px; align-items: center; font-size: 13px; }

/* Atividades agrupadas por dia, como o histórico do navegador. */

.dia {
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  margin-bottom: 10px;
  overflow: hidden;
}

.dia > summary {
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding: 11px 14px;
  cursor: pointer;
  background: var(--superficie-2);
  /* Sem o marcador padrão, que muda de forma entre navegadores; o triângulo
     abaixo é desenhado por nós e gira igual em todos. */
  list-style: none;
  user-select: none;
}
.dia > summary::-webkit-details-marker { display: none; }

.dia > summary::before {
  content: "";
  width: 0;
  height: 0;
  border-left: 5px solid currentColor;
  border-top: 4px solid transparent;
  border-bottom: 4px solid transparent;
  transition: transform 120ms ease;
  color: var(--texto-fraco);
  flex: none;
}
.dia[open] > summary::before { transform: rotate(90deg); }

.dia-titulo { font-weight: 600; }
.dia > summary:hover { background: var(--acento-fraco); }
.dia .tabela-wrap { border: none; border-radius: 0; }

.atividade:hover { background: var(--superficie-2); }
.atividade .hora {
  color: var(--texto-fraco);
  font-variant-numeric: tabular-nums;
  font-size: 13px;
  white-space: nowrap;
}
.atividade a { color: var(--texto); }
.atividade .identificado { font-weight: 560; }
.atividade .categoria { margin-right: 6px; }

/* Item recém-inserido pela atualização automática. O realce é breve e some
   sozinho: ele existe para dizer "isto acabou de chegar", não para virar um
   estado permanente que se acumula na tela. */
.atividade.nova { animation: chegou 2.4s ease-out; }
@keyframes chegou {
  from { background: var(--acento-fraco); }
  to   { background: transparent; }
}
@media (prefers-reduced-motion: reduce) {
  .atividade.nova { animation: none; }
}

/* A categoria não depende só de cor (§7): o rótulo textual vem junto, e a
   borda apenas reforça o agrupamento. */
.categoria {
  font-size: 12px;
  color: var(--texto-fraco);
  border-left: 3px solid var(--borda);
  padding-left: 8px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.categoria[data-categoria="conversion"],
.categoria[data-categoria="identification"] { border-left-color: var(--identificacao); }
.categoria[data-categoria="form"],
.categoria[data-categoria="modal"] { border-left-color: var(--clique); }
.categoria[data-categoria="technical"] { border-left-color: var(--alerta); }

/* Selo de duas letras antes do nome do evento, no feed de Atividades. */
.evento-icone {
  display: inline-grid; place-items: center;
  width: 20px; height: 20px; border-radius: 4px;
  font-family: var(--mono); font-size: 9px; font-weight: 700;
  margin-right: 6px; vertical-align: middle;
  background: var(--superficie-2); color: var(--texto-fraco);
}
.evento-icone[data-categoria="page_view"],
.evento-icone[data-categoria="video"] { background: var(--informativo-fraco); color: var(--informativo); }
.evento-icone[data-categoria="click"],
.evento-icone[data-categoria="download"] { background: var(--clique-fraco); color: var(--clique); }
.evento-icone[data-categoria="form"],
.evento-icone[data-categoria="modal"] { background: var(--acento-fraco); color: var(--acento-texto); }
.evento-icone[data-categoria="identification"],
.evento-icone[data-categoria="campaign"] { background: var(--identificacao-fraco); color: var(--identificacao); }
.evento-icone[data-categoria="technical"] { color: var(--texto-fraco-2); }

@media (max-width: 720px) {
  .atividade { grid-template-columns: 1fr; gap: 4px; }
  .categoria { border-left: none; padding-left: 0; }
}

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

.ao-vivo-controle {
  display: flex;
  gap: 12px;
  align-items: center;
  font-size: 13px;
  padding-bottom: 10px;
}

.contador-vivo {
  display: flex;
  gap: 8px;
  align-items: baseline;
  padding: 12px 0 4px;
}
.contador-vivo strong {
  font-size: 32px;
  font-weight: 700;
  letter-spacing: -0.02em;
}
.contador-vivo span { font-size: 14px; }

.feed-sessao {
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  overflow: hidden;
}

/* ----------------------------------------------------------- definições */

.definicoes {
  display: grid;
  grid-template-columns: minmax(120px, auto) 1fr;
  gap: 6px 16px;
  margin: 0 0 16px;
  font-size: 14px;
}
.definicoes dt { color: var(--texto-fraco); }
/* min-width: 0 é o que permite o item de grid encolher; sem ele, um valor
   comprido — uma lista de campos, uma URL — alarga a página inteira e vira
   rolagem horizontal. A quebra cuida do resto. */
.definicoes dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }
.quebra { overflow-wrap: anywhere; }

/* --------------------------------------------------------------- snippet */

/* Escuro, como manda o design system. Não é decoração: o bloco é o único
   lugar da tela onde o conteúdo é para copiar e colar em outro programa, e
   o fundo escuro marca essa troca de contexto. Contraste #e7e7e7 sobre
   #151515 = 13.6:1. */
.snippet {
  background: #151515;
  border: 0;
  border-radius: var(--raio-grande);
  padding: 16px 18px;
  overflow-x: auto;
  margin: 8px 0 16px;
  color: #e7e7e7;
  font-size: 12px;
  line-height: 18px;
}
.snippet code { white-space: pre; color: inherit; font-size: inherit; }

section { margin-bottom: 32px; }
section h2 { margin-top: 24px; }

/* ------------------------------------------------------------- validação */

.passos {
  list-style: none;
  margin: 12px 0;
  padding: 0;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  overflow: hidden;
}

.passo {
  display: grid;
  grid-template-columns: 24px 1fr auto;
  gap: 10px;
  align-items: baseline;
  padding: 8px 14px;
  border-bottom: 1px solid var(--borda);
  font-size: 14px;
}
.passo:last-child { border-bottom: none; }
.passo.ok span:first-child { color: var(--ok-texto); }
.passo.falhou span:first-child { color: var(--erro-texto); }
.passo.pendente { color: var(--texto-fraco); }

/* --------------------------------------------------------------- QR Code */

.qr-preview {
  /* A prévia é limitada na tela; o arquivo baixado continua no tamanho pedido.
     Mostrar 2048 px em tela cheia não ajuda ninguém a conferir a leitura. */
  max-width: 260px;
  margin: 4px 0 16px;
  padding: 12px;
  background: #fff;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
}
/* O fundo branco fixo é do desenho, e não do tema: o leitor precisa da mesma
   imagem que vai para a gráfica. Um QR Code que muda com o tema da interface é
   um QR Code que pode ser baixado invertido sem ninguém perceber. */
.qr-preview svg { display: block; width: 100%; height: auto; }

.qr-item {
  display: flex;
  align-items: center;
  gap: 10px;
}
.qr-item svg {
  /* Tamanho fixo na tela: o SVG escala pelo viewBox, e assim uma peça com
     conteúdo maior não vira uma miniatura maior que a das outras linhas. */
  flex: none;
  width: 48px;
  height: 48px;
  padding: 2px;
  border-radius: 2px;
  background: #fff;
}

/* ------------------------------------------------------------ canal e URL */

/* Saúde de cliente (visão de administração de plataforma, tela Clientes)
   reaproveita esta pílula genérica — ver `[data-saude=...]` mais abaixo. */
.canal {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 550;
  line-height: 1.6;
  white-space: nowrap;
  background: var(--superficie-2);
  color: var(--texto-fraco);
  border: 1px solid var(--borda);
}

/* Origem/canal de aquisição: ponto colorido + rótulo, igual ao protótipo
   (`.source-cell`/`.source-dot`) — não é mais pílula preenchida. Renderizado
   por `origemCanal()` em `layout.ts`, que também mapeia os 11 canais do
   domínio para os 5 tons abaixo. */
.origem {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--texto);
  padding: 3px 9px;
  border-radius: 999px;
  border: 1px solid var(--borda);
  background: var(--superficie-2);
}
.origem-ponto {
  width: 6px;
  height: 6px;
  border-radius: 2px;
  flex-shrink: 0;
}
.origem-ponto[data-tom="organico"]   { background: var(--canal-organico); }
.origem-ponto[data-tom="direto"]     { background: var(--canal-direto); }
.origem-ponto[data-tom="pago"]       { background: var(--canal-pago); }
.origem-ponto[data-tom="referencia"] { background: var(--canal-referencia); }
.origem-ponto[data-tom="social"]     { background: var(--canal-social); }

/* A URL precisa caber sem empurrar a tabela: quebra em qualquer ponto e
   ocupa no máximo a largura da coluna. O `min-width` é o que impede a
   coluna de ser espremida a ponto de a URL quebrar letra a letra — sem
   ele, uma tabela com muitas colunas transforma a célula numa torre de
   um caractere. */
.url {
  font-size: 13px;
  overflow-wrap: anywhere;
  color: var(--texto);
}
/* Vale para as duas formas que o app usa para texto longo em tabela:
   `.url` (link curto) e `.quebra` (destino, seletor CSS, caminho). */
td .url, td .quebra {
  display: inline-block;
  min-width: 240px;
  max-width: 460px;
}
/* Célula com texto longo cresce em altura em vez de manter os 52px. */
td:has(.url), td:has(.quebra) { height: auto; padding-top: 10px; padding-bottom: 10px; }

/* ------------------------------------------------------- cartões e portas */

.cartoes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 10px;
  margin: 14px 0 18px;
}

.cartao {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 14px 16px;
  border: 1px solid var(--borda);
  border-radius: var(--raio-grande);
  background: var(--superficie);
}
.cartao-valor { font-size: 28px; line-height: 32px; font-weight: 500; font-variant-numeric: tabular-nums; letter-spacing: -0.02em; }
.cartao-titulo { font-size: 13px; font-weight: 500; }
.cartao-nota { font-size: 12px; color: var(--texto-fraco); line-height: 1.35; }
/* O tom só reforça o que o texto já diz: cor sozinha não é informação.
   O número usa o tom escuro do par — o amarelo cheio (#ecb730) sobre
   branco fica em ~1.9:1 e some para quem tem pouca visão. */
.cartao.alerta { border-color: var(--alerta); background: var(--alerta-fraco); }
.cartao.alerta .cartao-valor { color: var(--alerta-texto); }
.cartao.ok .cartao-valor { color: var(--ok-texto); }

.portas {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 10px;
  margin-bottom: 18px;
}

.porta {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 14px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  text-decoration: none;
  color: inherit;
  background: var(--superficie);
}
.porta:hover { border-color: var(--acento); background: var(--acento-fraco); }
.porta-titulo { font-weight: 600; color: var(--texto); }
.porta-nota { font-size: 13px; color: var(--texto-fraco); line-height: 1.4; }

.avancado {
  margin: 12px 0;
  padding: 0 14px 4px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
}
.avancado > summary { padding: 11px 0; cursor: pointer; font-weight: 550; }

/* ------------------------------------------------- administração de plataforma */

.canal[data-saude="active"]                   { background: #e7f4ec; color: #12603f; border-color: #cfe7da; }
.canal[data-saude="no_recent_data"]           { background: #fdf0dc; color: #8a5a06; border-color: #f4e0bd; }
.canal[data-saude="awaiting_first_detection"] { background: #e9f0fd; color: #23509e; border-color: #d6e2f8; }
.canal[data-saude="not_configured"]           { background: #fdeaf0; color: #93244c; border-color: #f6d4de; }

/* 8px, não os 12px de antes: o grupo passou a levar tanto texto sublinhado
   quanto `.acao-icone` — 12px era pensado só para separar palavras, e sobra
   demais entre ícones pequenos lado a lado. */
.acoes-linha { display: flex; align-items: center; gap: 8px; white-space: nowrap; }

/* ------------------------------------------------------- avatar e status */

/* Quadrado de canto arredondado, não círculo: acompanha a marca (que é um
   quadrado raio 8) e alinha melhor com o texto ao lado numa tabela. */
.avatar {
  width: 26px; height: 26px; border-radius: var(--raio);
  display: inline-grid; place-items: center;
  font-size: 10px; font-weight: 600; letter-spacing: -0.02em; color: #fff;
  flex-shrink: 0; vertical-align: middle; margin-right: 10px;
}
.avatar.anon {
  background: var(--preenchimento); color: var(--texto-fraco-2);
  border: 0;
}
/* Seis variações, escolhidas por hash do id — determinístico (a mesma pessoa
   sempre cai na mesma cor), sem precisar guardar cor nenhuma no banco.
   Chapado em vez de gradiente: no tamanho em que o avatar aparece (26px), o
   gradiente vira ruído, e as iniciais brancas perdem contraste na ponta
   clara dele. */
.avatar-cor-0 { background: var(--avatar-0); }
.avatar-cor-1 { background: var(--avatar-1); }
.avatar-cor-2 { background: var(--avatar-2); }
.avatar-cor-3 { background: var(--avatar-3); }
.avatar-cor-4 { background: var(--avatar-4); }
.avatar-cor-5 { background: var(--avatar-5); }
/* `.status-pill` mora junto de `.etiqueta`, lá em cima — os dois são o
   mesmo componente desde a unificação da identidade. */

/* ---------------------------------------------------------------- perfil */

.perfil { display: grid; grid-template-columns: 300px 1fr; gap: 20px; align-items: flex-start; }
.perfil-lateral {
  background: var(--superficie);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  padding: 20px;
  position: sticky; top: 16px;
}
.perfil-avatar {
  width: 56px; height: 56px; border-radius: var(--raio-grande);
  display: grid; place-items: center;
  color: #fff; font-size: 20px; font-weight: 600;
  margin-bottom: 12px;
}
.perfil-avatar.anon {
  background: var(--preenchimento); color: var(--texto-fraco-2);
  border: 0; font-size: 16px;
}
.perfil-nome { font-size: 18px; font-weight: 600; letter-spacing: -0.01em; }
.perfil-status { margin-top: 10px; }

.perfil-fatos {
  margin-top: 16px;
  display: grid; grid-template-columns: 1fr;
  gap: 4px;
  border-top: 1px dotted var(--borda-forte);
  padding-top: 14px;
}
.fato { display: flex; justify-content: space-between; gap: 8px; font-size: 12px; padding: 3px 0; align-items: center; }
.fato-rotulo { color: var(--texto-fraco); font-family: var(--mono); font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.05em; }
.fato-valor { color: var(--texto); font-family: var(--mono); text-align: right; font-size: 11.5px; }
.fato-valor.link { color: var(--acento-texto); }

.perfil-acoes {
  margin-top: 16px; padding-top: 14px;
  border-top: 1px dotted var(--borda-forte);
  display: flex; flex-direction: column; gap: 6px;
}
.perfil-acoes .botao { text-align: center; }

/* Resumo de IA (P3) — sob demanda, nunca automático. O acento roxo-claro
   ecoa a paleta semântica de "identificação" sem reaproveitá-la de fato:
   é categoria diferente (leitura da IA, não dado do domínio). */
.ficha-ia {
  margin-bottom: 20px;
  padding: 14px 16px;
  border-radius: var(--raio-grande);
  border: 1px solid var(--borda);
  background: var(--acento-tenue);
}
.ficha-ia-rotulo {
  font-family: var(--mono); font-size: 10px;
  text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--acento-texto);
  margin-bottom: 6px;
}
.ficha-ia p { margin: 0 0 8px; }
.ficha-ia-erro { border-color: var(--alerta); background: var(--alerta-fraco); color: var(--alerta-texto); }
/* Estado "ainda não gerado" nas listas: só o link, sem a moldura do cartão —
   um cartão roxo permanente no topo de toda tela seria alarme falso. */

/* ------------------------------------------------------- Loop IA */
/* O painel de chat do protótipo: botão fixo + coluna deslizante à direita. */

/* Topbar do protótipo: migalhas à esquerda, os botões de IA à direita. */
.topo {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 24px;
  border-bottom: 1px solid var(--borda);
  background: var(--fundo);
}
/* Título da tela + fio + migalha, na ordem do protótipo. O título é o que
   se lê de relance; a migalha diz de qual cliente é. */
.topo-esq {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
}
.topo-titulo {
  font-size: 15px;
  font-weight: 500;
  color: var(--texto);
  white-space: nowrap;
}
.topo-fio {
  width: 1px;
  height: 16px;
  background: var(--borda);
  flex: none;
}
.topo-migalhas {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--texto-fraco);
  min-width: 0;
}
.topo-migalhas .topo-sep { color: var(--texto-fraco-2); }
.topo-migalhas .topo-atual { color: var(--texto); font-weight: 550; }
/* Em tela estreita a migalha sai antes do título: ela repete o nome da tela
   e o do cliente, que o seletor ao lado já mostra. O título fica. */
@media (max-width: 720px) {
  .topo-fio, .topo-migalhas { display: none; }
}
.topo-acoes { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.topo-botao {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border: 1px solid var(--borda);
  border-radius: 999px;
  background: var(--superficie);
  color: var(--texto);
  font: inherit;
  font-size: 12.5px;
  font-weight: 550;
  text-decoration: none;
  cursor: pointer;
}
.topo-botao:hover { border-color: var(--borda-forte); }
.topo-botao-primario {
  background: var(--texto);
  color: var(--fundo);
  border-color: var(--texto);
}
.topo-botao-primario:hover { opacity: 0.9; }

.ia-painel {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: 70;
  width: 380px;
  max-width: 100vw;
  display: flex;
  flex-direction: column;
  background: var(--superficie);
  border-left: 1px solid var(--borda);
  box-shadow: -12px 0 32px color-mix(in oklch, var(--texto) 12%, transparent);
  transform: translateX(100%);
  transition: transform 0.2s ease;
}
.ia-painel.aberto { transform: translateX(0); }

.ia-cabeca {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 16px;
  border-bottom: 1px solid var(--borda);
}
.ia-titulo { font-weight: 700; font-size: 14px; }
.ia-fechar {
  border: 0; background: none; cursor: pointer;
  font-size: 18px; line-height: 1; color: var(--texto-fraco);
  padding: 2px 6px; border-radius: var(--raio);
}
.ia-fechar:hover { color: var(--texto); background: var(--superficie-2); }

.ia-corpo {
  flex: 1;
  overflow-y: auto;
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.ia-msg {
  font-size: 13px;
  line-height: 1.55;
  max-width: 92%;
  padding: 10px 12px;
  border-radius: 12px;
  white-space: pre-wrap;
  overflow-wrap: break-word;
}
.ia-msg-bot { background: var(--superficie-2); color: var(--texto); align-self: flex-start; }
.ia-msg-user { background: var(--texto); color: var(--fundo); align-self: flex-end; }
.ia-msg-pensando { color: var(--texto-fraco); font-style: italic; }

.ia-entrada {
  display: flex;
  gap: 8px;
  padding: 12px 16px;
  border-top: 1px solid var(--borda);
}
.ia-entrada input {
  flex: 1;
  min-width: 0;
  padding: 9px 12px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  background: var(--superficie-2);
  font: inherit;
  font-size: 13px;
}
.ia-entrada input:focus { border-color: var(--borda-forte); background: var(--superficie); outline: none; }
.ia-entrada button {
  padding: 9px 14px;
  border: 0;
  border-radius: var(--raio);
  background: var(--texto);
  color: var(--fundo);
  font: inherit;
  font-size: 13px;
  cursor: pointer;
}

@media (max-width: 900px) {
  .ia-painel { width: 100%; }
}

/* ------------------------------------------------------ prévia do modal */
/* A moldura e a réplica (§5.4). As cores vêm de /modais/:id/previa.css,
   gerada da configuração — a CSP não deixa estilo inline. */

.pv-cena {
  display: flex;
  justify-content: center;
  padding: 24px 0;
  background:
    repeating-linear-gradient(45deg, var(--superficie-2) 0 12px, transparent 12px 24px);
  border: 1px dotted var(--borda-forte);
  border-radius: var(--raio);
  margin-bottom: 16px;
}
.pv-viewport {
  position: relative;
  width: 100%;
  min-height: 420px;
  display: grid;
  place-items: center;
  overflow: hidden;
}
.pv-desktop .pv-viewport { max-width: 100%; }
.pv-tablet .pv-viewport { max-width: 768px; }
.pv-celular .pv-viewport { max-width: 375px; }
.pv-overlay { position: absolute; inset: 0; }
.pv-modal {
  position: relative;
  max-width: calc(100% - 32px);
  padding: 22px;
  box-shadow: 0 18px 48px color-mix(in oklch, black 30%, transparent);
}
.pv-fechar { position: absolute; top: 10px; right: 14px; font-size: 18px; opacity: 0.6; }
.pv-titulo { font-size: 18px; font-weight: 700; margin: 0 0 6px; }
.pv-subtitulo { margin: 0 0 6px; opacity: 0.85; }
.pv-auxiliar { margin: 0 0 10px; font-size: 12.5px; opacity: 0.7; }
.pv-campo { display: block; font-size: 12.5px; margin: 10px 0 0; opacity: 0.9; }
.pv-input {
  display: block;
  margin-top: 4px;
  padding: 8px 10px;
  border: 1px solid color-mix(in oklch, currentColor 25%, transparent);
  border-radius: 8px;
  font-size: 13px;
  opacity: 0.7;
  min-height: 17px;
}
.pv-consent { display: flex; gap: 8px; align-items: flex-start; font-size: 12px; margin-top: 12px; opacity: 0.85; }
.pv-check {
  width: 13px; height: 13px; flex-shrink: 0; margin-top: 1px;
  border: 1.5px solid color-mix(in oklch, currentColor 45%, transparent);
  border-radius: 3px;
}
.pv-botao {
  display: block;
  margin-top: 16px;
  padding: 11px 16px;
  border-radius: 8px;
  text-align: center;
  font-weight: 600;
  font-size: 14px;
}

/* -------------------------------------------------------------- jornada */


.visita-bloco { position: relative; padding-left: 26px; border-left: 2px solid var(--borda); padding-bottom: 24px; }
.visita-bloco:last-child { border-left-color: transparent; padding-bottom: 0; }
.visita-marcador {
  position: absolute; left: -8px; top: 2px;
  width: 14px; height: 14px; border-radius: 50%;
  background: var(--texto); border: 3px solid var(--superficie);
  box-shadow: 0 0 0 1px var(--borda);
}
.visita-marcador.entrada { background: var(--informativo); }
.visita-marcador.identificacao { background: var(--identificacao); box-shadow: 0 0 0 1px var(--borda), 0 0 0 3px var(--identificacao-fraco); }

.visita-titulo { font-size: 13px; font-weight: 600; margin-bottom: 2px; display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.visita-titulo .visita-num { font-family: var(--mono); font-size: 10px; color: var(--texto-fraco-2); text-transform: uppercase; letter-spacing: 0.1em; }
.visita-meta { font-family: var(--mono); font-size: 11px; color: var(--texto-fraco); margin-top: 2px; display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }

.visita-passos { margin-top: 12px; display: flex; flex-direction: column; background: var(--superficie-2); border: 1px solid var(--borda); border-radius: var(--raio); overflow: hidden; }
.passo-visita { display: grid; grid-template-columns: 28px 1fr auto; gap: 10px; padding: 7px 12px; align-items: center; font-size: 12px; border-bottom: 1px solid var(--borda); }
.passo-visita:last-child { border-bottom: 0; }
.passo-visita.identificacao { background: var(--identificacao-fraco); }
.pv-num { font-family: var(--mono); font-size: 10px; color: var(--texto-fraco-2); }
.pv-pagina { font-weight: 500; }
.pv-caminho { color: var(--texto-fraco); font-family: var(--mono); font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pv-duracao { font-family: var(--mono); font-size: 11px; color: var(--texto-fraco-2); text-align: right; white-space: nowrap; }

@media (max-width: 900px) {
  .perfil { grid-template-columns: 1fr; }
  .perfil-lateral { position: static; }
}

/* ------------------------------------------------ casca e telas de lista */
/* O desenho do protótipo aplicado à casca e às telas de lista. Os tokens
   que ele consome moram no `:root` lá em cima — foi assim que esta seção
   deixou de valer só para Visitantes e passou a valer para todas as telas.
   O que sobrou aqui é forma e composição, não cor solta. */

/* ---- casca: lateral branca com blur, marca laranja ---- */

.lateral {
  background: rgba(255, 255, 255, 0.82);
  backdrop-filter: blur(18px);
  padding: 14px;
}

/* A marca do protótipo: quadrado laranja "J" com brilho + "GoLoop"
   embaixo do nome. O markup é o mesmo `<a class="marca">Jornadas</a>` de
   todas as telas — o desenho extra é todo pseudo-elemento. */
.marca {
  display: block;
  padding: 0 8px 16px;
}
/* A marca é a imagem e nada mais. O quadrado "J" e o subtítulo em texto
   saíram: o logotipo traz o nome desenhado, e ter os dois dava dois nomes
   com duas tipografias na mesma linha.

   `object-fit: contain` porque a proporção é de quem desenhou — e vale
   igual para o logo enviado em /admin → Aparência, que pode ter qualquer
   formato. Esticar a marca de alguém é pior do que sobrar espaço. */
.marca-img {
  width: 100%;
  max-width: 168px;
  height: 30px;
  object-fit: contain;
  object-position: left center;
}

.nav-rotulo { color: #26262666; }
.nav-secao a { min-height: 28px; }
.nav-secao a[aria-current='page'] {
  background: #0000000a;
  box-shadow: inset 0 0 0 1px #00000008;
  font-weight: 450;
}
.ponto-vivo {
  background: #42c366;
}
@media (prefers-reduced-motion: no-preference) {
  .ponto-vivo { box-shadow: 0 0 0 4px #42c36629; animation: none; }
}
.lateral-rodape { border-top: 1px solid var(--borda); }

/* ---- topbar ---- */

/* Acima da barra de filtros (z 30): o `position: sticky` daqui cria um
   contexto de empilhamento, então o dropdown do seletor — por mais alto que
   seja o z-index dele — nunca passa deste número. Com 20 ele abria ATRÁS
   dos botões Exportar/Colunas. */
.topo {
  position: sticky;
  top: 0;
  z-index: 40;
  height: 64px;
  background: rgba(249, 249, 249, 0.86);
  backdrop-filter: blur(18px);
  border-bottom: 1px solid #dcdcdceb;
}
.topo-botao {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 36px;
  padding: 0 14px;
  border: 0;
  border-radius: 10px;
  background: #f2f2f2;
  color: var(--texto);
  font-size: 13px;
  font-weight: 450;
  white-space: nowrap;
}
.topo-botao:hover { background: #eeeeee; }
/* `--acento-forte`, como todo preenchimento que carrega texto branco. */
.topo-botao-primario { background: var(--acento-forte); color: #fff; border-color: var(--acento-forte); box-shadow: var(--sombra-marca); }
.topo-botao-primario:hover { background: var(--acento-forte-hover); }
.topo-botao-primario:active { transform: scale(0.995); }

/* ---- corpo ---- */

/* Sem teto de largura: o card ocupa a página, como numa tela de dados. */
main {
  max-width: none;
  padding: 20px 24px 40px;
}
.pv-oculto {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---- o card que envolve toolbar + tabela ---- */

.pv-card {
  border: 1px solid var(--borda);
  border-radius: 8px;
  background: var(--superficie);
  box-shadow: var(--sombra-sm);
}
.pv-vazio-wrap { padding: 16px; }
.pv-vazio-wrap .vazio { border: 0; }

.pv-toolbar {
  position: relative;
  z-index: 30;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--borda);
}
.pv-toolbar-dir {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-left: auto;
  flex: none;
}

/* ---- dropdowns da toolbar (details) ---- */

.pv-drop { position: relative; }
.pv-drop > summary {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 28px;
  padding: 4px 12px;
  border: 1px solid var(--borda);
  border-radius: 8px;
  background: var(--superficie);
  color: var(--texto);
  cursor: pointer;
  list-style: none;
  font-size: 12px;
  white-space: nowrap;
}
.pv-drop > summary::-webkit-details-marker { display: none; }
.pv-drop > summary:hover { border-color: var(--borda-forte); background: #fbfbfb; }
.pv-periodo > summary::after { content: '▾'; font-size: 9px; color: var(--texto-fraco-2); }

.pv-menu {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  z-index: 50;
  display: none;
  flex-direction: column;
  min-width: 170px;
  padding: 4px;
  border: 1px solid var(--borda);
  border-radius: 12px;
  background: var(--superficie);
  box-shadow: var(--sombra-pop);
}
.pv-drop[open] > .pv-menu { display: flex; }
.pv-menu-dir { left: auto; right: 0; }
.pv-menu a {
  padding: 7px 10px;
  border-radius: 8px;
  color: var(--texto);
  font-size: 12px;
  text-decoration: none;
}
.pv-menu a:hover { background: #00000008; }
.pv-menu a.ativo { font-weight: 600; }

.pv-custom {
  display: grid;
  gap: 6px;
  padding: 8px 6px 6px;
  margin-top: 2px;
  border-top: 1px solid var(--borda);
}
.pv-custom label {
  display: grid;
  gap: 3px;
  color: #26262666;
  font-family: var(--mono);
  font-size: 9px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.pv-custom input[type='date'] {
  width: 100%;
  box-sizing: border-box;
  padding: 6px 8px;
  border: 1px solid var(--borda);
  border-radius: 8px;
  background: var(--superficie-2);
  color: var(--texto);
  font-family: var(--mono);
  font-size: 12px;
  outline: 0;
}
.pv-custom input[type='date']:focus { border-color: var(--acento-anel); background: var(--superficie); }
.pv-custom button {
  min-height: 28px;
  padding: 4px 10px;
  border: 0;
  border-radius: 8px;
  background: var(--acento);
  color: #fff;
  cursor: pointer;
  font-size: 11px;
  font-weight: 450;
}

/* ---- chips de filtro ativos (sobrepõe o .fchip base para o desenho do
        protótipo: retângulo raio 8, 28px, segmentos campo·op·valor) ---- */

.fchip {
  min-height: 28px;
  height: auto;
  border-radius: 8px;
  font-family: var(--fonte);
  font-size: 11px;
}
.fchip .fc-campo { background: #f2f2f2; color: var(--texto-fraco-2); }
.fchip .fc-op { color: #26262666; }
.fchip .fc-valor { font-size: 12px; font-weight: 500; max-width: 220px; }

.chip-adicionar {
  min-height: 28px;
  padding: 4px 12px;
  border: 1px dashed #d9d9d9;
  border-radius: 8px;
  color: var(--texto-fraco-2);
  font-family: var(--fonte);
  font-size: 12px;
  cursor: pointer;
  list-style: none;
}
.chip-adicionar::-webkit-details-marker { display: none; }
.chip-adicionar:hover { color: var(--texto); border-color: var(--texto-fraco-2); }

.pv-limpar {
  color: var(--texto-fraco-2);
  font-size: 12px;
  text-decoration: underline;
}
.pv-limpar:hover { color: var(--acento-texto); }

/* ---- "+ adicionar filtro": as duas etapas ---- */

.pv-filtro-menu { width: 320px; padding: 0; overflow: hidden; }
.pv-menu-cab {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  border-bottom: 1px solid var(--borda);
  background: var(--superficie-2);
  color: var(--texto-fraco-2);
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.pv-menu-cab strong { color: var(--texto); }
.pv-voltar {
  border: 0;
  border-radius: 6px;
  padding: 2px 6px;
  background: transparent;
  color: var(--texto-fraco-2);
  cursor: pointer;
  font-family: var(--mono);
  font-size: 12px;
}
.pv-voltar:hover { background: #00000008; color: var(--texto); }

.pv-grupo { padding-top: 6px; }
.pv-grupo-rotulo {
  padding: 4px 12px;
  color: #26262666;
  font-family: var(--mono);
  font-size: 9px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.pv-campo-btn {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
  padding: 7px 12px;
  border: 0;
  border-radius: 0;
  background: transparent;
  cursor: pointer;
  font-size: 13px;
  color: var(--texto);
  text-align: left;
}
.pv-campo-btn:hover { background: #00000005; }
.pv-tipo {
  color: #26262666;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}
[data-passo-campos] { padding-bottom: 4px; }

.pv-valores { display: flex; flex-direction: column; max-height: 260px; overflow-y: auto; padding: 4px; }
.pv-valor {
  padding: 7px 10px;
  border-radius: 8px;
  color: var(--texto);
  font-size: 12px;
  text-decoration: none;
}
.pv-valor:hover { background: #00000005; }
.pv-valor.ativo { background: var(--acento-tenue); font-weight: 500; }

.pv-campo-form { display: grid; gap: 8px; padding: 12px; }
.pv-campo-form input[type='text'] {
  width: 100%;
  box-sizing: border-box;
  padding: 7px 10px;
  border: 1px solid var(--borda);
  border-radius: 10px;
  background: var(--superficie-2);
  color: var(--texto);
  font: inherit;
  font-size: 13px;
  outline: 0;
}
.pv-campo-form input[type='text']:focus { border-color: var(--acento-anel); background: var(--superficie); }
.pv-campo-form button {
  justify-self: end;
  min-height: 28px;
  padding: 4px 10px;
  border: 0;
  border-radius: 8px;
  background: var(--acento);
  color: #fff;
  cursor: pointer;
  font-size: 11px;
  font-weight: 450;
}

/* ---- ações à direita: Exportar / Colunas ---- */

.pv-acao {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 28px;
  padding: 0 12px;
  border: 0;
  border-radius: 8px;
  background: #f2f2f2;
  color: var(--texto);
  cursor: pointer;
  font-size: 12px;
  font-weight: 450;
  text-decoration: none;
  white-space: nowrap;
  list-style: none;
}
.pv-acao::-webkit-details-marker { display: none; }
.pv-acao:hover { background: #eeeeee; }

/* A ação principal da lista ("Cadastrar cliente", "Novo modal"). Usa
   `--acento-forte` porque carrega texto branco pequeno: a cor da marca pura
   dá 3.16:1 e reprova no AA. */
.pv-acao-forte {
  background: var(--acento-forte);
  color: #fff;
  font-weight: 500;
  box-shadow: var(--sombra-marca);
}
.pv-acao-forte:hover { background: var(--acento-forte-hover); }

/* As abas de recorte (situação, visão) quando ficam dentro do card: viram a
   primeira faixa dele, com fio embaixo separando da barra de filtros. */
.pv-card > .periodos,
.pv-card > .abas {
  margin: 0;
  padding: 10px 16px;
  border-bottom: 1px solid var(--borda);
}
/* Quando as abas dividem a faixa com a barra (tela sem campo de filtro),
   elas não carregam moldura própria — a da barra já basta. */
.pv-toolbar .ao-vivo-controle { padding: 0; gap: 8px; }
.pv-toolbar > .periodos,
.pv-toolbar > .abas {
  margin: 0;
  padding: 0;
  border: 0;
  flex: 1;
}

.pv-colunas .pv-menu { width: 210px; padding: 6px; }
.pv-coluna-opcao {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  border-radius: 8px;
  cursor: pointer;
  font-size: 12px;
  color: var(--texto);
}
.pv-coluna-opcao:hover { background: #00000005; }
.pv-coluna-opcao input { margin: 0; accent-color: var(--acento); }

/* ---- tabela ---- */

/* Uma `.tabela-wrap` comum dentro do card se encaixa nele sem que a tela
   precise trocar de marcação: a moldura já é dela, só falta o respiro. É o
   que permite converter as outras listas envolvendo o bloco no card, em vez
   de reescrever cada tabela. */
.pv-card > .tabela-wrap {
  margin: 16px;
  max-height: max(360px, calc(100vh - 280px));
}

.pv-tabela {
  overflow: auto;
  /* A altura acompanha a janela em vez de um teto fixo: topbar (64) + faixa
     de workspace + toolbar + paginação somam ~280px de moldura. O mínimo
     segura o caso de janela baixa sem esmagar a tabela. */
  max-height: max(360px, calc(100vh - 280px));
  margin: 16px;
  border: 1px solid var(--borda);
  border-radius: 12px;
}
.pv-tabela table { min-width: 940px; font-size: 13px; }
.pv-tabela th {
  position: sticky;
  top: 0;
  z-index: 2;
  height: 46px;
  padding: 0 16px;
  background: var(--superficie);
  vertical-align: middle;
  color: #787878;
  font-family: var(--fonte);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}
.pv-tabela td {
  height: 52px;
  padding: 0 16px;
  vertical-align: middle;
  white-space: nowrap;
  color: var(--texto-fraco);
}
.pv-tabela tbody tr:hover { background: #00000003; }
.pv-tabela tr:last-child td { border-bottom: 0; }
.pv-tabela td a {
  color: var(--texto);
  text-decoration: none;
}
.pv-tabela td a:hover { color: var(--acento-texto); }
.pv-tabela td .mono { font-size: 12px; }
.pv-tabela td.num,
.pv-tabela th.num { text-align: left; font-family: var(--mono); font-size: 12px; color: var(--texto); }

/* Primeira coluna fixa no scroll horizontal; a sombra entra pela ilha
   (`.rolado` no wrapper) quando a tabela sai da posição inicial. */
.pv-tabela th:first-child,
.pv-tabela td:first-child {
  position: sticky;
  left: 0;
  z-index: 1;
  background: var(--superficie);
  width: 230px;
}
.pv-tabela th:first-child { z-index: 4; }
.pv-tabela.rolado th:first-child,
.pv-tabela.rolado td:first-child {
  box-shadow: 6px 0 8px -4px #00000024;
}

/* Colunas escondidas pelo seletor. */
table.sem-status .col-status,
table.sem-origem .col-origem,
table.sem-dispositivo .col-dispositivo,
table.sem-sessoes .col-sessoes,
table.sem-eventos .col-eventos,
table.sem-prim .col-prim,
table.sem-ult .col-ult { display: none; }

/* O rodapé de contagem/paginação é a última faixa do card, com fio em cima.
   Vale para a `.paginacao` comum que as outras listas já escrevem. */
.pv-paginacao,
.pv-card > .paginacao {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 16px;
  border-top: 1px solid var(--borda);
  color: var(--texto-fraco-2);
  font-size: 12px;
}
/* Anula a margem da `.paginacao` solta, que existia para descolar da tabela
   quando não havia card em volta. */
.pv-card > .paginacao { margin: 0; }

/* Um h2 dentro do card é o cabeçalho dele: faixa própria, com fio embaixo,
   no lugar do título solto que flutuava acima de uma tabela. */
.pv-card > h2 {
  margin: 0;
  padding: 12px 16px;
  border-bottom: 1px solid var(--borda);
  font-size: 14px;
  font-weight: 550;
}
.pv-card > h2 + .legenda { margin: 12px 16px 0; }

/* Totais e curva dentro do card. O gráfico perde a moldura própria: a do
   card já é a dele, e duas bordas encaixadas viram um degrau. */
.pv-card > .cartoes { margin: 16px 16px 0; }
.pv-card > .grafico {
  margin: 16px;
  padding: 0;
  border: 0;
  background: transparent;
}

/* Os blocos que Ao Vivo e Atividades põem dentro do card ganham o mesmo
   respiro lateral da tabela, para tudo alinhar numa coluna só. */
.pv-card [data-vivo] > .contador-vivo,
.pv-card [data-vivo] > .fichas,
.pv-card > .fichas { margin: 16px 16px 0; }
.pv-card [data-vivo] > .tabela-wrap,
.pv-card [data-vivo] > .paginacao { margin: 16px; }
.pv-card > .feed-topo { margin: 16px 16px 0; }
.pv-card > [data-vivo-mensagem], .pv-card [data-vivo] > .vazio { margin: 16px; }
.pv-card > .dias, .pv-card > .dia { margin-left: 16px; margin-right: 16px; }
.pv-paginacao .botao.secundario,
.pv-card > .paginacao .botao.secundario {
  border-radius: 8px;
  font-size: 12px;
  padding: 4px 12px;
}

/* ---- painel Loop IA no tema ---- */

.ia-painel {
  width: min(360px, 88vw);
  background: var(--superficie);
  border-left: 1px solid var(--borda);
}
.ia-entrada button {
  border: 0;
  border-radius: var(--raio-medio);
  background: var(--acento-forte);
  color: #fff;
  font-weight: 450;
}

/* ------------------------------------------------------- marca (upload) */
/* Logo e favicon em /admin → Aparência. Cada peça mostra o que está no ar
   ao lado do formulário que a troca: sem a prévia, a única forma de saber
   o que está valendo seria recarregar a casca e olhar. */

.marca-peca {
  display: grid;
  grid-template-columns: 120px minmax(0, 1fr);
  gap: 20px;
  align-items: start;
  padding: 16px;
  margin-bottom: 12px;
  border: 1px solid var(--borda);
  border-radius: var(--raio-grande);
  background: var(--superficie);
}
/* Xadrez claro atrás da prévia: logo com fundo transparente sobre branco
   parece que não carregou. */
.marca-previa {
  display: grid;
  place-items: center;
  min-height: 72px;
  padding: 12px;
  border-radius: var(--raio);
  background-color: var(--superficie-2);
  background-image:
    linear-gradient(45deg, #00000008 25%, transparent 25%, transparent 75%, #00000008 75%),
    linear-gradient(45deg, #00000008 25%, transparent 25%, transparent 75%, #00000008 75%);
  background-position: 0 0, 8px 8px;
  background-size: 16px 16px;
  font-size: 12px;
}
.marca-previa img { max-width: 100%; height: auto; }
.marca-campos .legenda { margin: 4px 0 10px; font-family: var(--fonte); }
.marca-campos .filtros { margin-bottom: 0; }
/* O seletor de arquivo do navegador não aceita estilo por dentro; o que dá
   para fazer é deixar a caixa em volta coerente com os outros campos. */
.marca-campos input[type="file"] {
  padding: 6px 8px;
  font-size: 13px;
  cursor: pointer;
}

@media (max-width: 720px) {
  .marca-peca { grid-template-columns: 1fr; }
}

/* Aviso de erro ao lado do campo que o causou, para quem salva sem sair da
   página — a faixa do topo fica longe demais numa tabela de sete linhas. */
.erro-inline {
  color: var(--erro-texto);
  font-size: 12px;
}

/* A barra de ação da lista de sugestões da análise. */
.ideias-acoes {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0 0 12px;
}

/* Visitante anônimo: rótulo e identificador colados, como um par.
   Eram dois blocos separados por espaço de texto, e a folga entre eles
   fazia parecer duas informações em vez de uma. */
.visitante-anon {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  white-space: nowrap;
}
.visitante-anon .fraco { font-size: 12px; }
.visitante-anon .mono { font-size: 12px; color: var(--texto-fraco-2); }
/* O ponto separa rótulo e código: `Anônimo • 019FD871`. */
.visitante-anon .fraco::after {
  content: '•';
  margin-left: 5px;
  color: var(--texto-fraco-2);
}

/* Espaçamento vertical entre os blocos de uma tela.
   Cada bloco trazia a própria margem — `.pv-card` 24px, `.fichas` 16px,
   `.grafico` 24px — e a distância mudava conforme o que vinha antes. */
main > .pv-card,
main > .fichas,
main > .cartoes,
main > .grafico,
main > .filtros,
main > .abas,
main > h2 { margin-bottom: var(--espaco-secao); }
main > *:last-child { margin-bottom: 0; }

/* §7.1: a coluna de ações fica agrupada à direita, título junto. */
th.col-acoes, td.col-acoes { text-align: right; }
td.col-acoes .acoes-linha, td.col-acoes { justify-content: flex-end; }

/* §3.4: a volta para a lista divide a faixa com as abas do visitante. */
.perfil-topo {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 12px;
}
.perfil-topo .abas { margin: 0; flex: 1; }

/* Detalhe aberto na própria tabela (PRD §2.2, §7.2).
   A linha de origem escurece um tom para dizer de quem é o detalhe — sem
   isso, numa tabela de cinquenta linhas, o bloco parece solto no meio. */
tr.detalhe-aberto > td { background: var(--preenchimento); }
tr.detalhe-aberto > td:first-child { box-shadow: inset 2px 0 0 var(--acento); }

.detalhe-linha > td {
  padding: 16px;
  background: var(--superficie-2, #fafafa);
  border-bottom: 1px solid var(--borda);
}
/* Dentro do acordeão o conteúdo é dado, não uma página: os títulos das
   seções encolhem para não competir com a lista em volta. */
.detalhe-linha h2 {
  margin: 0 0 8px;
  font-size: 12px;
  font-family: var(--mono);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--texto-fraco-2);
  border: 0;
  padding: 0;
}
.detalhe-linha .colunas { gap: 24px; }
.detalhe-linha section + section { margin-top: 16px; }

/* Painel lateral de detalhe (PRD §9.4, §13.2).
   Mesma família do painel da IA — coluna à direita, lista visível atrás.
   A diferença de propósito: aquele é conversa, este é o registro que a
   linha selecionada representa. */
.painel-lateral {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  width: min(560px, 92vw);
  z-index: 60;
  display: flex;
  flex-direction: column;
  background: var(--superficie);
  border-left: 1px solid var(--borda);
  box-shadow: -12px 0 32px color-mix(in oklch, var(--texto) 12%, transparent);
}
.painel-lateral[hidden] { display: none; }

.painel-cabeca {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--borda);
}
.painel-cabeca strong { flex: 1; font-size: 14px; font-weight: 550; min-width: 0; }

.painel-corpo { flex: 1; overflow: auto; padding: 16px; }
/* Dentro do painel o conteúdo é dado, não página: os títulos encolhem para
   não competir com o cabeçalho do próprio painel. */
.painel-corpo h2 {
  margin: 20px 0 8px;
  font-size: 12px;
  font-family: var(--mono);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--texto-fraco-2);
  border: 0;
  padding: 0;
}
.painel-corpo > *:first-child { margin-top: 0; }
.painel-corpo .colunas { display: block; }
.painel-corpo .fichas { grid-template-columns: 1fr 1fr; }

/* A linha aberta fica marcada enquanto o painel mostra o detalhe dela. */
[data-painel][aria-current='true'] { font-weight: 600; color: var(--acento-texto); }

/* O insight enquanto pensa (PRD §12).
   Estado visível de propósito: mostra que há uma leitura acontecendo agora
   sobre o recorte que está na tela, em vez de o bloco surgir do nada. */
.ficha-ia-auto .ficha-ia-rotulo { display: inline-flex; align-items: center; gap: 6px; }
.ia-pensando {
  margin: 6px 0 0;
  color: var(--texto-fraco);
  font-size: 13px;
}
.ia-reticencias span {
  animation: ia-pulsa 1.4s infinite;
  opacity: 0.2;
}
.ia-reticencias span:nth-child(2) { animation-delay: 0.2s; }
.ia-reticencias span:nth-child(3) { animation-delay: 0.4s; }
@keyframes ia-pulsa {
  0%, 60%, 100% { opacity: 0.2; }
  30% { opacity: 1; }
}
/* Quem pediu menos movimento não recebe pontinho piscando. */
@media (prefers-reduced-motion: reduce) {
  .ia-reticencias span { animation: none; opacity: 0.6; }
}

/* ---------------------------------------------------------------- jornadas */

/* O `.link` genérico não tem variante de perigo (só `.acao-icone.perigo`,
   que é para botão de ícone). "Excluir" na lista de jornadas é texto, não
   ícone — a variante existe aqui em vez de forçar um ícone só para reusar
   a regra que já existia. */
.link.perigo { color: var(--erro-texto); }
.link.perigo:hover { color: var(--erro-texto); text-decoration-thickness: 2px; }

/* O construtor é um `<details>` com a moldura de `.pv-card` (mesma borda,
   fundo, raio e sombra das outras telas de lista) — "+ Nova jornada" fechado
   por padrão, e só o resumo aparece até alguém abrir. Editar uma jornada
   existente abre com `open` já no HTML, sem JavaScript. */
.jornada-construtor-details { margin-bottom: var(--espaco-secao); }
.jornada-construtor-resumo {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 14px 16px;
  cursor: pointer;
  list-style: none;
  font-size: 14px;
  color: var(--texto);
}
.jornada-construtor-resumo::-webkit-details-marker { display: none; }
.jornada-construtor-resumo::before {
  content: '+';
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px; height: 18px;
  border-radius: 50%;
  background: var(--acento-fraco);
  color: var(--acento-texto);
  font-size: 13px;
  line-height: 1;
  transition: transform 0.15s ease;
}
.jornada-construtor-details[open] > .jornada-construtor-resumo::before { content: '−'; }
.jornada-construtor-resumo:hover { background: #00000005; }
.jornada-construtor-details[open] > .jornada-construtor-resumo {
  border-bottom: 1px solid var(--borda);
}
.jornada-construtor-corpo { padding: 16px; }

.jornada-construtor {
  display: grid;
  grid-template-columns: minmax(260px, 340px) 1fr;
  gap: var(--espaco-secao);
  align-items: start;
  margin-bottom: var(--espaco-secao);
}
@media (max-width: 900px) {
  .jornada-construtor { grid-template-columns: 1fr; }
}

/* Caixas internas do construtor: fundo levemente distinto do card por trás
   (`--fundo`, não `--superficie`), para não empilhar duas bordas iguais uma
   dentro da outra. */
.caixa {
  background: var(--fundo);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  padding: 16px;
}
.caixa > h2 { margin: 0 0 12px; font-size: 13px; }

.jornada-info .campo { margin-bottom: 12px; }
.jornada-info textarea { resize: vertical; }

.acoes-linha { display: flex; gap: 8px; margin-top: 16px; }

.estimativa-acao { margin-top: 12px; }
.estimativa {
  margin: 8px 0 0;
  font-size: 13px;
  color: var(--texto);
}
.estimativa strong { font-variant-numeric: tabular-nums; }

.jornada-etapas [data-lista-etapas] {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 12px;
}

.etapa-linha {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  padding: 12px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  background: var(--superficie);
  cursor: grab;
}
.etapa-linha.arrastando { opacity: 0.4; }

.etapa-alca {
  color: var(--texto-fraco-3);
  font-size: 16px;
  line-height: 1;
  padding-top: 6px;
  user-select: none;
}

.etapa-corpo { flex: 1; display: flex; flex-direction: column; gap: 8px; min-width: 0; }

.etapa-cabeca {
  display: flex;
  gap: 8px;
  align-items: center;
}
.etapa-cabeca input[type='text'] { flex: 1; min-width: 0; }

.etapa-remover {
  background: none;
  border: none;
  color: var(--texto-fraco);
  font-size: 18px;
  line-height: 1;
  padding: 2px 6px;
  cursor: pointer;
}
.etapa-remover:hover { color: var(--erro-texto); }

.etapa-condicao {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.etapa-condicao > * { flex: 1; min-width: 160px; }
.etapa-condicao [data-condicao-de][hidden] { display: none; }

.jornada-alertas { margin-bottom: 0; }
.canais-alerta { display: flex; flex-wrap: wrap; gap: 16px; margin-top: 8px; }
.canal-alerta { display: flex; align-items: center; gap: 6px; font-size: 13px; }
.canal-alerta.desativado { color: var(--texto-fraco-3); }
.canal-alerta.desativado .etiqueta { margin-left: 4px; }

.acoes-tabela { display: flex; gap: 10px; white-space: nowrap; }
.acoes-tabela form { display: inline; }

/* Fichas à esquerda (2×2) e funil à direita, meio a meio — o funil sozinho
   ocupando a largura toda do card ficava desproporcional ao lado de só
   quatro números. Em telas estreitas empilha, fichas primeiro. */
.jornada-resumo {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
  align-items: start;
  margin-bottom: 16px;
}
@media (max-width: 900px) {
  .jornada-resumo { grid-template-columns: 1fr; }
}
.fichas-2x2 {
  grid-template-columns: repeat(2, 1fr);
  margin-bottom: 0;
  height: 100%;
}

/* ---- funil de colunas (journey-chart.ts) ----
   Autossuficiente: como agora divide `.jornada-resumo` com as fichas, não é
   mais filho direto de `.pv-card` e não herda a margem de `.pv-card > .grafico`. */
.funil { margin: 0; }
.funil svg { width: 100%; height: auto; display: block; }
.funil a { cursor: pointer; }
.funil a:hover .funil-barra { fill: var(--acento-forte); }
.funil a:hover .funil-trilha { stroke: var(--borda-forte); }
.funil-trilha { fill: var(--fundo); stroke: var(--borda); stroke-width: 1; }
.funil-barra { fill: var(--acento); transition: height 0.2s ease, y 0.2s ease; }
.funil-ativa .funil-barra { fill: var(--acento-forte); }
.funil-ativa .funil-trilha { stroke: var(--acento-forte); stroke-width: 1.5; }
.funil-rotulo {
  fill: var(--texto-fraco);
  font-size: 11px;
  font-family: var(--fonte);
}
.funil-rotulo-nome { fill: var(--texto); font-size: 12px; }
.funil-ativa .funil-rotulo-nome { fill: var(--acento-texto); font-weight: 500; }
.funil-valor {
  fill: var(--texto);
  font-size: 13px;
  font-weight: 500;
  font-family: var(--mono);
}

/* Linha da tabela "Por etapa" correspondente à barra aberta no funil — o
   mesmo tom do drill-down, para os dois se lerem como uma coisa só. */
.linha-ativa td { background: var(--acento-tenue); }

.negativo { color: var(--erro-texto); font-weight: 500; }

/* ---------------------------------------------- configurações no menu */

/* Um link só no rodapé da lateral — a lista de destinos mora dentro da
   própria tela (desenho de referência do fundador, 2026-08-18). O estilo é
   herdado de `.lateral-rodape a`, que já trata hover e página atual. */
.lateral-config { /* nada próprio: o rodapé já estiliza o link */ }

/* ---------------------------------------------- configurações: páginas */

.conf-topo { margin-bottom: 24px; }
.conf-topo h1 { margin: 0 0 4px; font-size: 24px; }
.conf-topo .legenda { margin: 0; }

/* Duas colunas: a lista de destinos e o conteúdo. A lista gruda no topo ao
   rolar porque as páginas longas (Instalação, Pessoas) passam bem da
   dobra, e trocar de seção não deveria exigir voltar ao início. */
.conf-layout {
  display: grid;
  grid-template-columns: 220px minmax(0, 1fr);
  gap: 32px;
  align-items: start;
}
.conf-nav {
  display: flex;
  flex-direction: column;
  gap: 2px;
  position: sticky;
  top: 16px;
}
.conf-nav a {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: var(--raio);
  text-decoration: none;
  color: var(--texto-fraco);
  font-size: 14px;
  white-space: nowrap;
}
.conf-nav a:hover {
  color: var(--texto);
  background: color-mix(in oklch, var(--texto) 5%, transparent);
}
.conf-nav a.ativo {
  color: var(--texto);
  background: var(--superficie-2, color-mix(in oklch, var(--texto) 6%, transparent));
  font-weight: 550;
}
.conf-conteudo { min-width: 0; }

/* Numa tela estreita a lista vira uma faixa acima do conteúdo. Ela
   **quebra linha** em vez de rolar na horizontal: rolando, o destino atual
   costuma nascer fora da vista — em Notificações a pessoa via "Instalação"
   e nenhum indicador do lugar onde está. Duas ou três linhas custam altura
   e devolvem a orientação. */
@media (max-width: 900px) {
  .conf-layout { grid-template-columns: 1fr; gap: 20px; }
  .conf-nav {
    position: static;
    flex-direction: row;
    flex-wrap: wrap;
    gap: 4px;
    padding-bottom: 12px;
    border-bottom: 1px solid var(--borda);
  }
  .conf-nav a { padding: 8px 12px; }
}

.conf-cabeca { margin-bottom: 20px; }
.conf-titulo { margin: 0 0 4px; font-size: 20px; }
.conf-cabeca .legenda { margin: 0; }

/* Cards de integrações — mesmo rosto dos cartões de boas-vindas. */
.conf-apps {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 16px;
  margin-bottom: var(--espaco-secao);
}
.conf-app {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 16px;
}
.conf-app-cabeca {
  display: flex;
  align-items: center;
  gap: 10px;
}
/* A inicial no quadrado faz o papel do logo da referência sem hospedar
   marca de terceiro: nada a baixar, nada a licenciar. */
.conf-app-marca {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: var(--raio);
  background: color-mix(in oklch, var(--texto) 8%, transparent);
  font-weight: 650;
  font-size: 14px;
  color: var(--texto);
  flex: none;
}
.conf-app-nome { display: flex; flex-direction: column; line-height: 1.25; }
.conf-app-nome .fraco { font-size: 12px; }
.conf-app-cabeca .etiqueta { margin-left: auto; }
.conf-app p { margin: 0; flex: 1; }
.conf-app .botao { align-self: flex-start; }

/* ------------------------------------------------------------ boas-vindas */

/* A tela de primeiro uso é mais estreita que as listas: uma coluna focada,
   sem competir com nada — a única tarefa é colocar o código no ar. */
.onb {
  display: flex;
  flex-direction: column;
  gap: 16px;
  max-width: 860px;
  margin: 0 auto;
}
.onb-cabeca { margin-bottom: 4px; }
.onb-titulo { margin: 0 0 4px; font-size: 24px; }

.onb-corpo {
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.onb-corpo .snippet { margin: 0; }
.onb-corpo textarea { resize: vertical; font-size: 13px; }

.onb-alternativas {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
  align-items: start;
}
@media (max-width: 720px) {
  .onb-alternativas { grid-template-columns: 1fr; }
}

/* Cartão-link e cartão-botão com o mesmo rosto: título forte + explicação
   fraca, todo o cartão clicável. O botão precisa desfazer o estilo nativo
   de <button> para vestir o .pv-card igual ao link. */
.onb-cartao {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  padding: 14px 16px;
  text-decoration: none;
  text-align: left;
  color: var(--texto);
  font: inherit;
  cursor: pointer;
}
.onb-cartao:hover { border-color: var(--borda-forte); }

/* O modal do programador — <dialog> nativo, aberto pela ilha. */
.onb-dialog {
  width: min(560px, calc(100vw - 32px));
  padding: 0;
  border: 1px solid var(--borda);
  border-radius: 12px;
  background: var(--superficie);
  color: var(--texto);
  box-shadow: 0 12px 40px -8px #00000040;
}
.onb-dialog::backdrop { background: #211c1873; }
.onb-dialog-cabeca {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--borda);
}
.onb-fechar {
  background: none;
  border: none;
  color: var(--texto-fraco);
  font-size: 20px;
  line-height: 1;
  padding: 2px 6px;
  cursor: pointer;
}
.onb-fechar:hover { color: var(--texto); }

.onb-rodape {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 16px;
  flex-wrap: wrap;
}
.onb-status {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--texto-fraco);
}
/* Aguardando = tom de atenção; recebendo = ok. A cor acompanha a palavra,
   nunca a substitui. */
.onb-status::before {
  content: '';
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--alerta-texto);
  flex: none;
}
.onb-status.ok::before { background: var(--ok-texto); }
