/* Fontes vendorizadas localmente (static/fonts/), mesmo princípio já aplicado
   ao Sortable.js: nenhuma dependência de CDN em tempo de execução. Baixadas
   da Google Fonts API, restritas aos subsets latin/latin-ext (suficiente pra
   português) — subsets cirílico/grego/vietnamita do payload original da
   Google Fonts foram descartados de propósito. */
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/ibm-plex-mono-400-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: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/ibm-plex-mono-400-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: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('../fonts/ibm-plex-mono-500-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: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('../fonts/ibm-plex-mono-500-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: 'Inter';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('../fonts/inter-400-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: 'Inter';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('../fonts/inter-400-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: 'Outfit';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('../fonts/outfit-400-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: 'Outfit';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('../fonts/outfit-400-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;
}

:root {
  --primary:      #1B3A63;
  --secondary:    #2F6B62;
  --accent:       #B8863E;
  --bg:           #F5F3EE;
  --surface:      #FFFFFF;
  --surface-alt:  #ECE9E2;
  --ink:          #1B1F23;
  --ink-soft:     #565049;
  --border:       #DEDACE;
  --success:      #2F9E6E;
  --warning:      #C89B3C;
  --error:        #B3432D;
  --info:         #3B82F6;
  --sidebar-bg:      #161B2E;
  --sidebar-accent:  #6C63F5;

  --font-display: 'Outfit', -apple-system, sans-serif;
  --font-body:    'Inter', -apple-system, sans-serif;
  --font-mono:    'IBM Plex Mono', monospace;

  --radius: 12px;
  --radius-sm: 8px;
  --shadow: 0 1px 2px rgba(27, 31, 35, 0.05), 0 6px 20px rgba(27, 31, 35, 0.06);
  /* Sombra de CONTÊINER em repouso — card, tile, coluna. Mais leve que
     --shadow, que é de modal e popover: contêiner parado não deve parecer
     flutuando. Substitui a moldura, que ficou dura demais quando a --border
     ganhou contraste em 25/08. */
  --shadow-suave: 0 1px 2px rgba(27, 31, 35, 0.04), 0 2px 8px rgba(27, 31, 35, 0.06);
}

/* ---------- Paletas sequenciais para dados (gráficos/BI) — registradas 08/08/2026 ----------
   Ideais para dados ORDENADOS (ex.: evolução temporal, valores crescentes) — cada escala vai
   do passo 1 (mais claro) ao passo 6 (mais escuro). Não usar pra dados categóricos sem ordem
   (nesse caso, misturar hues diferentes, não passos da mesma escala). Consumidor previsto:
   módulo de Relatórios e BI e gráficos de KPI (ainda não implementados — ver PROJETO_STATUS.md
   e kpi-dashboard-builder). Não confundir com as paletas de tema da interface (tabela `paletas`,
   seed.sql) — aquelas são cores semânticas de UI; estas são escalas de dado pra visualização. */
:root {
  --seq-azul-1: #e9f0fb;    --seq-azul-2: #a6c2f0;    --seq-azul-3: #6294e5;
  --seq-azul-4: #2368d6;    --seq-azul-5: #184792;    --seq-azul-6: #0d264f;

  --seq-ciano-1: #e9f4fb;   --seq-ciano-2: #a6d4f0;   --seq-ciano-3: #62b3e5;
  --seq-ciano-4: #2391d6;   --seq-ciano-5: #186392;   --seq-ciano-6: #0d364f;

  --seq-indigo-1: #e9ebfb;  --seq-indigo-2: #a6aef0;  --seq-indigo-3: #6271e5;
  --seq-indigo-4: #2338d6;  --seq-indigo-5: #182692;  --seq-indigo-6: #0d154f;

  --seq-roxo-1: #f2e9fb;    --seq-roxo-2: #cba6f0;    --seq-roxo-3: #a462e5;
  --seq-roxo-4: #7c23d6;    --seq-roxo-5: #551892;    --seq-roxo-6: #2e0d4f;

  --seq-teal-1: #e9fbf7;    --seq-teal-2: #a6f0de;    --seq-teal-3: #62e5c5;
  --seq-teal-4: #23d6a9;    --seq-teal-5: #189274;    --seq-teal-6: #0d4f3e;

  --seq-verde-1: #effbe9;   --seq-verde-2: #c0f0a6;   --seq-verde-3: #90e562;
  --seq-verde-4: #62d623;   --seq-verde-5: #439218;   --seq-verde-6: #244f0d;

  --seq-magenta-1: #fbe9fb; --seq-magenta-2: #f0a6ee; --seq-magenta-3: #e562e1;
  --seq-magenta-4: #d623d0; --seq-magenta-5: #92188e; --seq-magenta-6: #4f0d4d;

  --seq-dourado-1: #fbf7e9; --seq-dourado-2: #f0dfa3; --seq-dourado-3: #e5c75d;
  --seq-dourado-4: #cea922; --seq-dourado-5: #886f16; --seq-dourado-6: #42360b;
}

html[data-theme="dark"] {
  --bg:           #14181C;
  --surface:      #1B2025;
  --surface-alt:  #23292F;
  --ink:          #EDEAE3;
  --ink-soft:     #A7A196;
  --border:       #30363C;
  --shadow: 0 1px 2px rgba(0,0,0,0.3), 0 6px 24px rgba(0,0,0,0.3);
  --shadow-suave: 0 1px 2px rgba(0,0,0,0.25), 0 2px 8px rgba(0,0,0,0.28);
}

@media (prefers-color-scheme: dark) {
  html:not([data-theme]) {
    --bg:           #14181C;
    --surface:      #1B2025;
    --surface-alt:  #23292F;
    --ink:          #EDEAE3;
    --ink-soft:     #A7A196;
    --border:       #30363C;
    --shadow: 0 1px 2px rgba(0,0,0,0.3), 0 6px 24px rgba(0,0,0,0.3);
  --shadow-suave: 0 1px 2px rgba(0,0,0,0.25), 0 2px 8px rgba(0,0,0,0.28);
  }
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.5;
  transition: background 0.2s ease, color 0.2s ease;
}

h1, h2, h3, .display {
  font-family: var(--font-display);
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--ink);
  margin: 0 0 4px;
}

a { color: inherit; text-decoration: none; }

/* ---------- Botões ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  /* 33px de altura, contra os 43px de antes. Medido em 25/08/2026: a barra de
     ferramentas do Pipeline sozinha ocupava 43px, e o Zoho e o ClickUp fazem o
     mesmo trabalho em ~32.
     `line-height` explícito porque sem ele a altura depende do line-height do
     body — foi por isso que 12px de fonte com 6px de padding produzia 39px de
     pílula, número que ninguém consegue prever lendo a regra. */
  padding: 7px 14px;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  font-family: var(--font-body);
  font-size: 13px;
  line-height: 1.4;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.15s ease;
}

.btn-primary { background: var(--primary); color: #fff; }
.btn-primary:hover { filter: brightness(1.1); }

/* Verde claro pedido por Rocélio, 31/08/2026, pro "Tornar Cliente" — mesmo
   tom suave (color-mix a 15%) já usado nos badges de sucesso/concluído. */
.btn-sucesso-suave { background: color-mix(in srgb, var(--success) 15%, var(--surface)); color: var(--success); }
.btn-sucesso-suave:hover { background: color-mix(in srgb, var(--success) 25%, var(--surface)); }

/* Sem borda, por decisão de Rocélio em 25/08/2026: a moldura em volta de cada
   botão de barra polui, e as referências (Zoho, ClickUp) usam botão limpo que
   só reage ao mouse.

   O preço é real e vale saber: sem borda e sem fundo, o botão em repouso é
   texto — a affordance passa a depender do hover, que não existe em tela de
   toque. Por isso o fundo de repouso é `surface-alt`, e não transparente: dá o
   contorno suave que diz "isto é clicável" sem desenhar moldura.

   Escala de escurecimento — pedido de Rocélio, 30/08/2026, revisado no
   mesmo dia: a barra (.pipeline-toolbar) não tinha fundo NENHUM (era
   transparente, mostrava o --bg da página por trás), e o botão usava
   `filter: brightness` sobre `--surface-alt` — que em temas customizados
   (Aparência deixa `bg`/`surface_alt`/`ink` todos livres) podem nascer
   próximos o bastante pra a diferença sumir. Daqui pra baixo os três
   níveis (barra < botão < selecionado) partem do MESMO `--bg` e só variam
   a porcentagem de `--ink` misturada — sempre visível nos dois temas,
   porque --ink É a cor escolhida pra ter contraste contra --bg (senão o
   texto normal da página já seria ilegível). Mistura maior = mais na
   direção de --ink: escurece no tema claro (--ink escuro), clareia no
   escuro (--ink claro) — que é a elevação certa em cada tema, não um
   capricho. */
/* O fundo da barra mistura --toolbar-cor (configurável em Configurações →
   Aparência → "Barra de ferramentas secundária") por cima da base neutra de
   sempre — não só --ink. Reescrito em 05/09/2026: a versão anterior (só
   color-mix(ink, X%, bg), 5% no claro / 9% no escuro por causa de um achado
   de contraste no escuro, ver histórico) dependia inteiramente de ink+bg
   pra existir, e dependia de dois números por tema. Um valor único (8% ink
   de base + 15% toolbar-cor por cima) resolve os dois temas sem precisar de
   `[data-theme="dark"]` nem `@media` — medido com o --toolbar-cor padrão
   (#1B3A63, mesmo valor de --primary): no claro o fundo desloca ~55 pontos
   de RGB do branco do card (sobra de longe), no escuro ~9-15 pontos do
   #1B2025 do card — pouco em termos absolutos, mas com matiz de verdade
   (não cinza puro), que o olho lê melhor perto do preto do que a mesma
   distância só em luminância. Pedido de Rocélio: reaproveitar a
   configuração já existente em vez de inventar uma cor nova só pra isto —
   por isso o token é `--toolbar-cor`, o mesmo que já tingia o HOVER dos
   botões da barra, não uma variável nova. */
.pipeline-toolbar {
  background: color-mix(in srgb, var(--toolbar-cor) 15%, color-mix(in srgb, var(--ink) 8%, var(--bg)));
  border-radius: var(--radius);
  padding: 8px 10px;
}
.btn-outline { background: color-mix(in srgb, var(--ink) 11%, var(--bg)); border-color: transparent; color: var(--ink); }
.btn-outline:hover { background: color-mix(in srgb, var(--primary) 12%, color-mix(in srgb, var(--ink) 11%, var(--bg))); color: var(--primary); }
/* Mesmo idioma de "selecionado" do .view-switch-btn.active — filtro rápido
   ativo (ex: "Atribuído a mim" em Tarefas) usa a mesma cor configurável.
   Base "16% ink" (mais que os 11% do botão comum) garante que o
   selecionado nasce mais escuro ANTES do tingimento de --toolbar-selecionado
   por cima — só tingir --surface (podendo ser mais claro que --bg, caso do
   tema padrão) não garantia a ordem barra < botão < selecionado pedida. */
.btn-outline.btn-selecionado {
  background: color-mix(in srgb, var(--toolbar-selecionado) 22%, color-mix(in srgb, var(--ink) 16%, var(--bg)));
  color: var(--toolbar-selecionado);
}
/* A barra do Pipeline usa a cor PRÓPRIA dela, não a --primary do app inteiro.
   Sem isto, "Cor principal" e "Botões da barra secundária" seriam sempre a
   mesma coisa na tela, e o campo novo existiria sem efeito visível — ambos
   nascem iguais na migração, mas só ficam independentes se a regra existir. */
.pipeline-toolbar .btn-outline:hover,
.pipeline-toolbar .ai-pill-btn:hover {
  background: color-mix(in srgb, var(--toolbar-cor) 12%, color-mix(in srgb, var(--ink) 11%, var(--bg)));
  color: var(--toolbar-cor);
}
/* O selo de filtro aplicado. Até 25/08/2026 esse estado não tinha cor
   nenhuma — só o texto "(2)" ao lado do rótulo dizia que havia filtro. Mesma
   fórmula do .view-switch-btn.active, para os dois lerem como um só idioma. */
.pipeline-toolbar .btn-outline.tem-filtro {
  background: color-mix(in srgb, var(--toolbar-selecionado) 22%, color-mix(in srgb, var(--ink) 16%, var(--bg)));
  color: var(--toolbar-selecionado);
}

.btn-block { width: 100%; }

.evento-form-vinculo-toggle { display: flex; gap: 20px; margin: 6px 0 14px; }
.evento-form-vinculo-toggle label { display: flex; align-items: center; gap: 6px; margin: 0; font-weight: 500; }

/* ---------- Formulários ---------- */

label {
  display: block;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-soft);
  margin: 14px 0 6px;
}

input[type="text"], input[type="password"], input[type="email"], input[type="number"], input[type="date"], input[type="datetime-local"], select, textarea {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 14px;
}

input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--primary) 25%, transparent);
}

/* ---------- Flash messages ---------- */

.flash { padding: 12px 16px; border-radius: var(--radius-sm); font-size: 14px; margin-bottom: 16px; }
.flash-success { background: color-mix(in srgb, var(--success) 15%, var(--surface)); color: var(--success); border: 1px solid color-mix(in srgb, var(--success) 35%, transparent); }
.flash-error   { background: color-mix(in srgb, var(--error) 15%, var(--surface));   color: var(--error);   border: 1px solid color-mix(in srgb, var(--error) 35%, transparent); }

/* ---------- Tela de login (portal) ---------- */

.portal-page { margin: 0; font-family: var(--font-body); background: var(--bg); }

.portal-theme-toggle {
  position: fixed; top: 20px; right: 20px; z-index: 10;
  width: 38px; height: 38px; border-radius: 50%; border: none;
  background: #161B2E; color: #fff; font-size: 16px; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 2px 8px rgba(0,0,0,0.25);
}
.portal-theme-toggle:hover { background: #232a45; }
.portal-layout { display: flex; min-height: 100vh; }

.portal-hero {
  display: none;
  width: 44%;
  flex-direction: column;
  justify-content: space-between;
  background-color: var(--sidebar-bg);
  background-size: cover;
  background-position: center;
  padding: 40px;
}
@media (min-width: 1024px) { .portal-hero { display: flex; } }

.portal-hero-logo { width: 140px; mix-blend-mode: screen; }
.portal-hero-title { color: #fff; font-family: var(--font-display); font-size: 1.5rem; font-weight: 700; line-height: 1.4; letter-spacing: -0.01em; margin: 64px auto 0; max-width: 30rem; text-align: center; }
.portal-hero-footer { color: rgba(255,255,255,0.6); font-size: 12px; margin: 0; text-align: center; }

.portal-main { flex: 1; display: flex; align-items: center; justify-content: center; padding: 40px 24px; }
.portal-panel { width: 100%; max-width: 440px; }

.portal-mobile-logo { display: block; width: 120px; margin: 0 auto 28px; }
@media (min-width: 1024px) { .portal-mobile-logo { display: none; } }

.portal-apps { display: flex; flex-direction: column; gap: 10px; margin-bottom: 24px; }
.portal-app {
  appearance: none; display: flex; align-items: center; gap: 14px; width: 100%;
  padding: 12px 14px; border-radius: var(--radius); border: 1px solid var(--border);
  background: var(--surface); font-family: inherit; text-align: left; cursor: pointer;
  transition: transform 0.15s cubic-bezier(.2,.8,.2,1), border-color 0.2s ease, background 0.2s ease, box-shadow 0.2s ease;
}
.portal-app:hover { transform: translateY(-2px); border-color: color-mix(in srgb, var(--card-color) 45%, var(--border)); }
.portal-app:active { transform: translateY(0) scale(0.99); }
.portal-app-selected {
  border-color: color-mix(in srgb, var(--card-color) 40%, var(--border));
  background: color-mix(in srgb, var(--card-color) 7%, var(--surface));
}

.portal-app-icon {
  flex-shrink: 0; width: 38px; height: 38px; border-radius: 9px;
  display: flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--card-color) 16%, var(--surface));
  color: var(--card-color);
}
.portal-app-icon svg { width: 18px; height: 18px; }

.portal-app-body { flex: 1; min-width: 0; }
.portal-app-name { display: block; font-size: 14px; font-weight: 700; color: var(--ink); }
.portal-app-desc { display: block; font-size: 11px; color: var(--ink-soft); line-height: 1.35; margin-top: 1px; }

.portal-app-arrow {
  flex-shrink: 0; width: 26px; height: 26px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--surface-alt); color: var(--ink-soft);
  transition: transform 0.2s cubic-bezier(.2,.8,.2,1), background 0.2s ease, color 0.2s ease;
}
.portal-app-arrow svg { width: 12px; height: 12px; }
.portal-app:hover .portal-app-arrow { transform: translateX(3px); background: var(--card-color); color: #fff; }

.auth-hint a { color: var(--primary); font-weight: 600; }

.auth-form { background: var(--surface); border-radius: var(--radius); box-shadow: var(--shadow); padding: 28px 26px; }
.auth-form .btn { margin-top: 22px; }

.auth-hint { margin-top: 20px; font-size: 12px; color: var(--ink-soft); text-align: center; line-height: 1.5; }

/* ---------- Layout raiz ---------- */

.app-shell { display: grid; grid-template-columns: 260px 1fr; min-height: 100vh; }
/* 60px, e não os 72px de antes: recolhida, a barra só precisa caber o ícone
   (20px) com respiro. Os 12px devolvidos vão para o conteúdo em toda tela. */
.app-shell.sidebar-collapsed { grid-template-columns: 60px 1fr; }
.app-shell > * { min-width: 0; }

/* ---------- Sidebar ---------- */

/* sticky + height de viewport para a sidebar não subir junto com a página.
   Sem isto o .app-shell usa min-height:100vh, a coluna da sidebar estica com o
   conteúdo, o .menu cresce até caber tudo e o overflow-y:auto dele nunca chega
   a valer — quem rolava era a página inteira, levando o menu embora. É o mesmo
   tratamento que o mobile e o drawer aberto já faziam com position:fixed
   (ver as media queries abaixo, que continuam vencendo esta regra).
   align-self:start é necessário: como item de grid a sidebar seria esticada
   até a altura da linha, e sticky não teria folga para grudar. */
/* Sem padding-top (02/09/2026, era 20px): a .topbar ao lado não tem nenhum
   respiro antes de si — height:48px começando em y=0 — então qualquer
   padding-top aqui empurrava o logo pra baixo da linha do título "Pipeline".
   O padding-bottom continua, é o respiro antes do :menu. */
.sidebar { background: var(--sidebar-bg); padding: 0 0 20px; display: flex; flex-direction: column; color: color-mix(in srgb, var(--sidebar-ink) 85%, transparent); position: sticky; top: 0; height: 100vh; align-self: start; }

.masthead { padding: 0 20px 20px; }
/* height fixo de 48px, igual ao de .topbar (não min-height:60px) — é isso que
   alinha o logo com o título "Pipeline" na mesma linha. Igual nos dois
   estados (aberto/recolhido) de propósito: antes o recolhido empilhava ícone
   e seta em coluna pra caber, e isso deslocava o ícone pra baixo — achado
   por Rocélio, 02/09/2026, comparando os dois estados lado a lado. A seta
   agora sai do fluxo (position:absolute, ver .sidebar-collapse-btn abaixo)
   só no recolhido, então o ícone não perde o centro por causa dela. */
.masthead-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; height: 48px; position: relative; }
.brand { font-family: var(--font-display); font-size: 20px; font-weight: 700; color: #fff; }
/* Escapou da migração para --sidebar-ink de 25/08: era branco fixo, e num
   tema de menu claro ficaria invisível. */
/* position:absolute (02/09/2026): sem isto, .tagline participa da altura
   de .brand-block, e como só existe no menu ABERTO (.sidebar-collapsed
   esconde), o bloco tinha alturas diferentes nos dois estados — centralizar
   um bloco de altura variável dentro de .masthead-top (align-items:center)
   fazia o ícone do logo pular de posição ao recolher/expandir. Achado real,
   comparando os dois estados lado a lado. Tirar do fluxo faz .brand-block
   ter sempre a altura de .brand sozinho, igual nos dois estados. */
.brand-block { position: relative; }
.tagline { position: absolute; top: 100%; left: 0; white-space: nowrap; font-size: 11px; color: color-mix(in srgb, var(--sidebar-ink) 50%, transparent); margin-top: 2px; }

.sidebar-collapse-btn {
  flex-shrink: 0; width: 28px; height: 28px; border-radius: 50%;
  border: 1px solid rgba(255,255,255,0.15); background: rgba(255,255,255,0.04);
  color: rgba(255,255,255,0.6); display: flex; align-items: center; justify-content: center;
  cursor: pointer; font-size: 15px;
}
.sidebar-collapse-btn:hover { color: var(--sidebar-ink); background: color-mix(in srgb, var(--sidebar-ink) 12%, transparent); }

.drawer-close-btn {
  display: none; flex-shrink: 0; width: 28px; height: 28px; border-radius: 50%;
  border: 1px solid rgba(255,255,255,0.15); background: rgba(255,255,255,0.04);
  color: rgba(255,255,255,0.6); align-items: center; justify-content: center;
  cursor: pointer; font-size: 20px; line-height: 1;
}
.drawer-close-btn:hover { color: #fff; background: rgba(255,255,255,0.12); }

.sidebar-scrim { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.4); z-index: 190; }
/* Recolhido, o favicon permanece no canto — é ele que identifica o sistema
   quando o nome não cabe. Antes a regra escondia `.brand-block` inteiro, e o
   ícone ia junto: o topo do menu ficava só com a seta. */
/* Sem padding lateral no recolhido: os 20px de cada lado do `.masthead`
   sobravam numa barra de 60px e empurravam o ícone para fora do centro. */
.sidebar-collapsed .masthead { padding: 0 0 20px; }
.sidebar-collapsed .masthead-top { justify-content: center; }
.sidebar-collapsed .brand { justify-content: center; }
/* A seta sai do fluxo normal e vira um badge no canto do ícone — não pode
   mais competir por espaço/altura com ele (era o empilhamento em coluna que
   descia o ícone, ver comentário em .masthead-top). Pequena o bastante pra
   não estourar os 60px da sidebar recolhida. */
.sidebar-collapsed .sidebar-collapse-btn {
  position: absolute; right: -2px; bottom: -2px; width: 20px; height: 20px; font-size: 12px;
}
.sidebar-collapsed .brand-nome, .sidebar-collapsed .tagline,
.sidebar-collapsed .menu-label-text, .sidebar-collapsed .soon-badge { display: none; }
.sidebar-collapsed .menu-item { justify-content: center; padding: 8px 0; }

/* display:flex + flex-direction:column (10/09/2026, menu arrastável) —
   antes bastava o empilhamento normal de bloco; a propriedade `order`
   que resolve a posição de cada item (ver app.py:inject_preferencias_visuais,
   ordem_menu_pos) só tem efeito dentro de um contêiner flex. Empilha
   igual ao bloco de antes — sem gap/margin herdado, não muda o espaçamento
   visual, só habilita o item a ser reordenado. */
.menu { display: flex; flex-direction: column; flex: 1; padding: 0 9px; overflow-y: auto; }
/* Barra de rolagem sutil, só no hover (07/09/2026) — o menu sempre teve
   overflow-y:auto (necessário: .sidebar é position:sticky + 100vh, é o
   .menu que rola, não a página toda), mas só passou a ESTOURAR de fato
   quando "Mapa de Dependências" virou item de topo (antes vivia dentro
   de um submenu fechado). Cor vem de --sidebar-ink (mesma base do hover
   de .menu-item, só que mais forte: 20% em vez de 8%, porque aqui
   precisa se notar contra o fundo escuro em vez de só sinalizar hover)
   — nunca uma cor nova, pra sobreviver a paleta customizada (ver
   templates/base.html, --sidebar-ink vem da paleta do usuário). Fica
   transparente em repouso nos dois motores (scrollbar-width mais
   scrollbar-color pro Firefox, ::-webkit-scrollbar pro Chrome/Safari) —
   nenhum dos padrões de scrollbar já existentes no projeto (kanban,
   filter-panel-scroll) cobria "visível só no hover", só "sempre
   escondida" ou "sempre fina". */
.menu { scrollbar-width: none; scrollbar-color: transparent transparent; }
.menu:hover { scrollbar-width: thin; scrollbar-color: color-mix(in srgb, var(--sidebar-ink) 20%, transparent) transparent; }
.menu::-webkit-scrollbar { width: 6px; }
.menu::-webkit-scrollbar-track { background: transparent; }
.menu::-webkit-scrollbar-thumb { background: transparent; border-radius: 999px; }
.menu:hover::-webkit-scrollbar-thumb { background: color-mix(in srgb, var(--sidebar-ink) 20%, transparent); }

/* Chip de usuário — movido do topbar pra base da sidebar em 02/09/2026
   (pedido de Rocélio, deixar a barra do topo mais limpa). .menu logo acima
   tem flex:1 e é quem tem overflow-y:auto; este bloco, de tamanho fixo,
   nasce empurrado pro fim da coluna sem precisar de margin-top:auto.
   position:relative ancora o painel — sem isto o absolute dele se penduraria
   no primeiro ancestral posicionado, que seria a sidebar inteira (sticky
   também conta como posicionado), não este chip especificamente. */
.sidebar-user { padding: 12px 9px 0; position: relative; }
.sidebar-collapsed .sidebar-user { padding: 12px 0 0; }
.sidebar-collapsed .user-meta { display: none; }
.sidebar-collapsed .sidebar-user .user-chip { justify-content: center; }

.menu-item {
  display: flex; align-items: center; justify-content: flex-start; gap: 10px;
  /* 8px de padding e fonte 13, contra 11px e 14 de antes. O menu tem 14 telas:
     cada pixel por item multiplica por catorze, e a barra precisava rolar em
     tela de 13".
     `line-height` explícito pela mesma razão dos botões — sem ele a altura
     herda a do body e o resultado não é previsível pela regra. */
  padding: 8px 12px; border-radius: var(--radius-sm); cursor: pointer;
  font-size: 14px; line-height: 1.4; font-weight: 400; color: color-mix(in srgb, var(--sidebar-ink) 75%, transparent);
}
.menu-item:hover { background: color-mix(in srgb, var(--sidebar-ink) 8%, transparent); color: var(--sidebar-ink); }

/* Tooltip do item de menu — só aparece quando o rótulo do texto está
   oculto (menu recolhido no desktop, ou o rail automático de 72px do
   tablet), controlado via JS (static/js/main.js) checando o display
   computado de .menu-label-text, não uma classe — funciona nos dois
   casos sem duplicar lógica por breakpoint. */
.sidebar-tooltip {
  position: fixed;
  z-index: 500;
  top: 0; left: 0;
  transform: translate(0, -50%);
  background: var(--sidebar-bg);
  color: #fff;
  font-size: 13px;
  font-weight: 500;
  padding: 7px 11px;
  border-radius: var(--radius-sm);
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.12s ease;
  box-shadow: 0 4px 14px rgba(0,0,0,0.25);
}
.sidebar-tooltip.visible { opacity: 1; visibility: visible; }

/* Ajuda de campo — mesmo mecanismo do .sidebar-tooltip (um elemento único
   reaproveitado, posicionado por getBoundingClientRect), mas com quebra de
   linha e largura máxima: aqui o conteúdo é uma frase explicando o campo, não
   um rótulo curto. Não usa o title nativo de propósito — ele só aparece depois
   de ~1s com o mouse parado, atraso que já tinha incomodado no menu lateral. */
.campo-tooltip {
  position: fixed; z-index: 500; top: 0; left: 0; max-width: 280px;
  background: var(--sidebar-bg); color: var(--sidebar-ink);
  font-size: 12px; font-weight: 400; line-height: 1.45;
  padding: 8px 11px; border-radius: var(--radius-sm);
  pointer-events: none; opacity: 0; visibility: hidden;
  transition: opacity 0.12s ease; box-shadow: 0 4px 14px rgba(0,0,0,0.25);
}
.campo-tooltip.visible { opacity: 1; visibility: visible; }

/* Componente: seletor de cor por paleta
   (templates/_componentes/seletor_cor.html + modules/paleta.py).

   Quebra em linha de propósito: dez amostras em fila única espremeriam o modal
   ou estourariam a largura dele. Aqui quebrar é o certo — é lista de conteúdo,
   não barra de ferramenta (ver a regra de barra, que é o caso oposto).

   A cor vem por --amostra inline, definida pela paleta; o CSS não tem uma classe
   por cor, senão acrescentar uma décima primeira exigiria mexer em CSS. */
.paleta-cores { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 4px; }
.paleta-cor-opcao {
  width: 28px; height: 28px; flex-shrink: 0; padding: 0; cursor: pointer;
  border-radius: 50%; background: var(--amostra);
  border: 2px solid transparent;
  /* O anel de seleção fica FORA da cor (box-shadow com spread), não como borda:
     borda comeria da própria amostra e mudaria o tamanho aparente conforme a
     seleção, fazendo as bolinhas dançarem ao escolher. */
  box-shadow: 0 0 0 1px var(--border);
  transition: box-shadow 0.12s ease, transform 0.12s ease;
}
.paleta-cor-opcao:hover { transform: scale(1.12); }
.paleta-cor-opcao.selecionada {
  box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px var(--amostra);
}
/* Sublinhado pontilhado avisa que o rótulo tem explicação — sem isso ninguém
   descobre que passar o mouse ali faz algo. */
label[data-ajuda] { cursor: help; text-decoration: underline dotted 1px; text-underline-offset: 3px; }
.menu-item.active { font-weight: 500; background: color-mix(in srgb, var(--sidebar-accent) 25%, transparent); color: var(--sidebar-ink); }
.menu-icon { width: 18px; height: 18px; opacity: 0.8; flex-shrink: 0; }
.menu-item.active .menu-icon { opacity: 1; }

.menu-item-disabled { cursor: not-allowed; opacity: 0.45; }
.menu-item-disabled:hover { background: none; color: color-mix(in srgb, var(--sidebar-ink) 75%, transparent); }
.soon-badge {
  font-size: 9px; text-transform: uppercase; letter-spacing: 0.04em;
  background: rgba(255,255,255,0.12); padding: 2px 6px; border-radius: 999px; flex-shrink: 0;
}

/* ---------- Topbar ---------- */

.topbar {
  /* 48px, e não os 64px de antes: com o título agora aqui dentro, a barra
     acumulava altura sem ganhar função. Medido em 25/08/2026 — o shell comia
     272px de 720px numa tela de 13", 38% antes do conteúdo começar.
     `gap` em vez de `space-between` porque agora são três blocos (título,
     busca, ações) e não dois. */
  height: 48px; display: flex; align-items: center; gap: 16px;
  padding: 0 20px; background: var(--surface); border-bottom: 1px solid transparent;
  box-shadow: var(--shadow-suave);
  position: sticky; top: 0; z-index: 10;
}

.topbar-search {
  /* margin-left: auto empurra a busca e tudo o que vem depois para a direita,
     deixando só o título à esquerda — o arranjo do Zoho.
     `flex-shrink` alto e `min-width` baixo fazem a BUSCA ser a primeira coisa
     a ceder quando a barra aperta. É sacrifício deliberado: ícone que some é
     função perdida, busca estreita continua servindo. */
  display: flex; align-items: center; gap: 8px; padding: 6px 12px; margin-left: auto;
  border-radius: 999px; background: var(--surface-alt); color: var(--ink-soft);
  width: 260px; min-width: 120px; flex-shrink: 4;
}
.topbar-search svg { width: 16px; height: 16px; flex-shrink: 0; }
.topbar-search input { border: none; background: none; padding: 0; font-size: 13px; width: 100%; }
.topbar-search input:focus { box-shadow: none; }

.topbar-actions { display: flex; align-items: center; gap: 10px; }

.icon-btn {
  /* 30px numa barra de 48: 36 numa barra de 48 deixaria 6px de respiro em
     cima e embaixo, e a barra pareceria cheia até a borda. */
  width: 30px; height: 30px; border-radius: 50%; border: none; background: transparent;
  color: var(--ink-soft); display: flex; align-items: center; justify-content: center; cursor: pointer;
}
.icon-btn:hover { background: var(--surface-alt); color: var(--ink); }
.icon-btn svg { width: 18px; height: 18px; }

.kanban-card-abrir {
  width: 26px; height: 26px; border-radius: 50%; flex-shrink: 0;
  color: var(--ink-soft); display: flex; align-items: center; justify-content: center;
}
.kanban-card-abrir:hover { background: var(--surface-alt); color: var(--primary); }
.kanban-card-abrir svg { width: 16px; height: 16px; }

.hamburger-btn {
  display: none; width: 36px; height: 36px; border-radius: 50%; border: none;
  background: transparent; color: var(--ink-soft); align-items: center; justify-content: center; cursor: pointer;
}
.hamburger-btn svg { width: 20px; height: 20px; }

.ai-pill-btn {
  display: flex; align-items: center; gap: 6px;
  /* Altura alinhada ao .btn novo (7px/13px), senão ele fica um degrau acima
     dos vizinhos na mesma barra. */
  padding: 7px 14px; border-radius: 999px; line-height: 1.4;
  /* Sem moldura, como os demais botões. A identidade roxa fica no FUNDO: ali a
     cor não é decoração, marca ação que envolve IA. */
  border: 1px solid transparent;
  background: color-mix(in srgb, #7C5CFC 12%, var(--surface));
  color: #7C5CFC; font-size: 13px; font-weight: 600; cursor: pointer;
}
.ai-pill-btn:hover { background: color-mix(in srgb, #7C5CFC 18%, var(--surface)); }
.ai-pill-btn svg { width: 14px; height: 14px; }
.ai-pill-btn:disabled { cursor: not-allowed; opacity: 0.5; }

/* Enriquecimento com IA em andamento/pendente (18/09/2026): ícone redondo ao
   lado do botão "IA", mesma família roxa. Pisca enquanto a IA processa e
   continua piscando até as sugestões serem aprovadas/descartadas — por isso
   o mesmo visual serve aos dois estados (o tooltip diz qual). O `display`
   próprio anularia o atributo [hidden], então o esconder é explícito. */
.ai-status-btn {
  display: flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; padding: 0; border-radius: 50%;
  border: 1px solid transparent; cursor: pointer;
  background: color-mix(in srgb, #7C5CFC 12%, var(--surface));
  color: #7C5CFC;
  animation: ai-status-piscar 1.2s ease-in-out infinite;
}
.ai-status-btn[hidden] { display: none; }
.ai-status-btn svg { width: 16px; height: 16px; }
.ai-status-btn:hover { background: color-mix(in srgb, #7C5CFC 22%, var(--surface)); }
@keyframes ai-status-piscar {
  0%, 100% { opacity: 1; box-shadow: 0 0 0 0 color-mix(in srgb, #7C5CFC 45%, transparent); }
  50% { opacity: 0.45; box-shadow: 0 0 0 5px color-mix(in srgb, #7C5CFC 0%, transparent); }
}
/* Sem animação pra quem pediu movimento reduzido: fica só destacado (borda
   roxa) — o estado continua legível sem depender de piscar. */
@media (prefers-reduced-motion: reduce) {
  .ai-status-btn { animation: none; border-color: #7C5CFC; }
}

/* Mesmo formato de pílula do .ai-pill-btn ao lado, mas tom neutro/suave —
   "Editar Lead" não tem identidade de cor própria, só precisa ser menos
   discreto que texto solto. Pedido de Rocélio, 31/08/2026. */
.btn-pill-suave {
  display: flex; align-items: center; gap: 6px;
  padding: 7px 14px; border-radius: 999px; line-height: 1.4;
  border: 1px solid transparent;
  background: color-mix(in srgb, var(--ink) 7%, var(--surface));
  color: var(--ink-soft); font-size: 13px; font-weight: 600; cursor: pointer;
}
.btn-pill-suave:hover { background: color-mix(in srgb, var(--ink) 12%, var(--surface)); color: var(--ink); }
.lead-toolbar-acoes .btn-pill-suave { padding: 5px 12px; font-size: 12px; font-weight: 400; }

/* Botão de ícone só (engrenagem do "Editar Layout") — mesmo tamanho/toque
   dos outros botões da barra, sem texto, tooltip via title= no HTML. */
.btn-icone-suave {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: var(--radius-sm); border: 1px solid transparent;
  background: color-mix(in srgb, var(--ink) 7%, var(--surface)); color: var(--ink-soft); cursor: pointer;
}
.btn-icone-suave:hover { background: color-mix(in srgb, var(--ink) 12%, var(--surface)); color: var(--ink); }
.btn-icone-suave svg { width: 15px; height: 15px; }

/* Texto de célula que NUNCA quebra: a linha da tabela mantém a mesma altura
   qualquer que seja o conteúdo (pedido de Rocélio, 10/10/2026, depois de ver
   uma linha de formulário com 7 linhas de texto). É a mesma receita de
   "Título nunca quebra em duas linhas" (CLAUDE.md), aplicada à célula:
   nowrap + overflow + reticências, e o limite de largura vem de `--max`, que
   cada tela define inline (ex.: style="--max: 460px;"). `display: block` é o
   que faz o max-width valer dentro de <td>. Sempre com `title=` no elemento,
   para o texto inteiro aparecer no hover. */
.celula-uma-linha {
  display: block; max-width: var(--max, 320px);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
}

/* Ações de uma linha de tabela, lado a lado. O <form> do botão de envio não
   pode empurrar nada: sem margem, e os filhos não encolhem. */
.acoes-linha { display: flex; align-items: center; gap: 4px; }
.acoes-linha > * { flex-shrink: 0; }
.acoes-linha form { margin: 0; }
/* Ocupa o lugar de uma ação que não existe nesta linha (mesmas medidas do
   .btn-icone-suave), para as ações restantes alinharem na coluna. */
.acoes-linha .acao-vazia { width: 28px; height: 28px; }

/* Janela de detalhes do menu Formulários. `pre-wrap` na mensagem preserva as
   quebras de linha que o visitante digitou, sem virar HTML. */
.entrada-mensagem {
  white-space: pre-wrap; overflow-wrap: anywhere; line-height: 1.55;
  background: var(--surface-alt); border-radius: var(--radius-sm);
  padding: 12px 14px; margin: 8px 0 12px;
}
.entrada-campos { display: grid; grid-template-columns: max-content 1fr; gap: 6px 16px; margin: 0; font-size: 13px; }
.entrada-campos dt { color: var(--ink-soft); }
.entrada-campos dd { margin: 0; overflow-wrap: anywhere; white-space: pre-wrap; }

/* Ícone de prazo de tarefa — três estados calculados por
   status_prazo_tarefa (concluída x prazo), não um campo gravado.
   Reaproveitado na grade de Tarefas do Lead e na Lista/Kanban do
   módulo geral (07/09/2026, ver §30 do reutilizável): mesma classe,
   tanto em cima de <span> (só leitura) quanto de .btn-icone-suave
   (clicável, na ficha do Lead) — as regras de cor abaixo vêm depois de
   .btn-icone-suave na cascata de propósito, pra vencer o cinza padrão
   dele quando as duas classes se combinam no mesmo elemento. */
.icone-status-prazo { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; flex-shrink: 0; }
.icone-status-prazo svg { width: 100%; height: 100%; }
.icone-status-prazo-no_prazo { color: var(--success); }
.icone-status-prazo-atrasada { color: var(--error); }
.icone-status-prazo-pendente { color: var(--ink-soft); }

/* Badge do status de FLUXO (coluna do Kanban) colado no Título da grade
   de Tarefas do Lead — diferente do ícone de prazo acima, que é sobre
   prazo, não sobre em qual coluna a tarefa está. A cor vem do banco
   (tarefas_status.cor, inline no HTML); currentColor deixa o fundo
   sempre uma versão clara da mesma cor, sem precisar de uma regra CSS
   por status. */
.badge-status-fluxo { margin-left: 6px; font-weight: 500; background: color-mix(in srgb, currentColor 15%, var(--surface)); }

.mode-switch { display: flex; gap: 2px; background: var(--surface-alt); border-radius: 999px; padding: 3px; }
.mode-btn { width: 30px; height: 30px; border-radius: 50%; border: none; background: transparent; color: var(--ink-soft); cursor: pointer; font-size: 14px; }
.mode-btn.active { background: var(--surface); color: var(--ink); box-shadow: var(--shadow); }

.palette-picker { position: relative; }
.palette-picker-panel {
  display: none; position: absolute; right: 0; top: 44px; background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius-sm); box-shadow: var(--shadow);
  padding: 6px; min-width: 220px; z-index: 20;
}
.palette-picker-panel.open { display: block; }

@media (max-width: 1023px) {
  .palette-picker-panel { max-width: calc(100vw - 24px); }
}

.notification-picker { position: relative; }
.notification-picker-panel {
  display: none; position: absolute; right: 0; top: 44px; background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius-sm); box-shadow: var(--shadow);
  padding: 6px; min-width: 280px; max-width: 340px; max-height: 360px; overflow-y: auto; z-index: 20;
}
.notification-picker-panel.open { display: block; }
.notification-item {
  display: flex; flex-direction: column; gap: 2px; padding: 8px 10px; border-radius: var(--radius-sm);
  color: var(--ink); text-decoration: none; font-size: 13px;
}
.notification-item:hover { background: var(--surface-alt); }
.notification-item.unread { font-weight: 600; background: color-mix(in srgb, var(--primary) 8%, transparent); }
.notification-item-data { font-size: 11px; color: var(--ink-soft); font-weight: 400; }
.notification-marcar-todas {
  width: 100%; margin-top: 4px; padding: 8px; border: none; background: none; color: var(--primary);
  font-size: 12px; cursor: pointer; text-align: center;
}
.notification-vazio { padding: 12px; font-size: 13px; color: var(--ink-soft); text-align: center; margin: 0; }

@media (max-width: 1023px) {
  .notification-picker-panel { max-width: calc(100vw - 24px); }
}

.palette-option-form { margin: 0; }
.palette-option {
  width: 100%; display: flex; align-items: center; gap: 10px; padding: 8px 10px;
  border: none; background: none; border-radius: var(--radius-sm); cursor: pointer;
  font-size: 13px; color: var(--ink); text-align: left;
}
.palette-option:hover { background: var(--surface-alt); }
.palette-option.selected { background: color-mix(in srgb, var(--primary) 12%, transparent); font-weight: 600; }
.palette-swatches { display: flex; gap: 3px; }
.swatch { width: 12px; height: 12px; border-radius: 50%; border: 1px solid rgba(0,0,0,0.1); }
.palette-name { flex: 1; }
.palette-check { color: var(--primary); }

.online-users-stack { display: flex; }
.online-avatar {
  width: 30px; height: 30px; border-radius: 50%; background: var(--primary); color: #fff;
  display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 700;
  border: 2px solid var(--surface); margin-left: -8px; position: relative;
}
.online-avatar:first-child { margin-left: 0; }
.online-dot { position: absolute; bottom: -2px; right: -2px; width: 11px; height: 11px; border-radius: 50%; background: var(--success); border: 2px solid var(--surface); }
.online-avatar-more { background: var(--surface-alt); color: var(--ink-soft); }
/* Inativo = navegador aberto, sem ação real além do limite de Configurações >
   Presença e sessão. Esmaecer o avatar e trocar a bolinha para cinza diz isso
   sem texto; o motivo e a hora da última ação ficam no tooltip. */
.online-avatar-inativo { opacity: 0.55; }
.online-dot-inativo { background: var(--ink-soft); }

.notification-badge {
  position: absolute; top: 4px; right: 4px; min-width: 14px; height: 14px; border-radius: 999px;
  background: var(--error); color: #fff; font-size: 9px; display: flex; align-items: center;
  justify-content: center; padding: 0 3px;
}

.user-chip { display: flex; align-items: center; gap: 10px; }
.user-avatar { width: 30px; height: 30px; border-radius: 50%; background: var(--secondary); color: #fff; display: flex; align-items: center; justify-content: center; font-size: 13px; font-weight: 700; flex-shrink: 0; }
.user-meta { display: flex; flex-direction: column; line-height: 1.2; min-width: 0; }
/* Sem cor própria de propósito: herda de .sidebar (color-mix com
   --sidebar-ink), que já é a cor certa pro fundo escuro da sidebar — mudou
   de lugar em 02/09/2026, era herdada do topbar claro antes. */
.user-name { font-size: 13px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Mesmo tom de "texto secundário" que .tagline já usa na sidebar — antes
   era --ink-soft, pensado pro fundo claro do topbar. */
.user-role { font-size: 11px; color: color-mix(in srgb, var(--sidebar-ink) 50%, transparent); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ---------- Conteúdo ---------- */

/* padding-top menor que as laterais: o respiro de cima competia com a
   divisória da topbar, que já separa visualmente. Vale para todas as telas —
   padrão de layout é do app, não da página. */
/* padding-left reduzido pela metade (32px -> 16px), só do lado esquerdo —
   pedido de Rocélio, 02/09/2026: distância grande demais entre o menu
   lateral e o início do corpo da página. Direita/topo/base sem mudança. */
.content { padding: 12px 32px 24px 16px; }

/* Título e barra mais perto do topo: era 24px aqui somados aos 28px de respiro
   do .content, empurrando o conteúdo útil para baixo em toda tela de listagem. */
.page-header { margin-bottom: 16px; display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 12px; }
.page-subtitle { color: var(--ink-soft); font-size: 14px; margin: 0; }

/* ---- Abaixo de 1024px (tablet + celular): comportamento compartilhado da
   gaveta aberta (usado pelo toque num item com submenu no rail do tablet —
   Task 3 — e pelo ☰ no celular) ---- */
@media (max-width: 1023px) {
  .sidebar-collapse-btn { display: none; }

  .app-shell.mobile-drawer-open .sidebar-scrim { display: block; }
  .app-shell.mobile-drawer-open .drawer-close-btn { display: flex; }
  .app-shell.mobile-drawer-open .sidebar {
    position: fixed; top: 0; left: 0; bottom: 0; width: 260px; z-index: 200;
  }
  .app-shell.mobile-drawer-open .sidebar .masthead-top { justify-content: space-between; }
  .app-shell.mobile-drawer-open .sidebar .brand-block,
  .app-shell.mobile-drawer-open .sidebar .tagline { display: block; }
  .app-shell.mobile-drawer-open .sidebar .menu-label-text,
  .app-shell.mobile-drawer-open .sidebar .soon-badge { display: inline; }
  .app-shell.mobile-drawer-open .sidebar .menu-item { justify-content: flex-start; padding: 11px 12px; }
}

/* ---- Tablet (768px-1023px): rail de ícones de 72px sempre visível por
   padrão — mesmo visual do `.sidebar-collapsed` manual do desktop, mas
   automático e sem depender de localStorage. ---- */
@media (min-width: 768px) and (max-width: 1023px) {
  .app-shell { grid-template-columns: 72px 1fr; }
  .app-shell.mobile-drawer-open > div:not(.sidebar-scrim) { grid-column: 2; }
  .content { padding: 24px; }
  .sidebar .masthead-top { justify-content: center; }
  .sidebar .brand-block, .sidebar .tagline,
  .sidebar .menu-label-text, .sidebar .soon-badge { display: none; }
  .sidebar .menu-item { justify-content: center; padding: 11px 0; }
}

/* ---- Celular (abaixo de 768px): sidebar totalmente fora da tela até a
   gaveta ser aberta pelo ☰. ---- */
@media (max-width: 767px) {
  .hamburger-btn { display: flex; }
  .app-shell, .app-shell.sidebar-collapsed { grid-template-columns: 1fr; }
  .content { padding: 16px; }
  .topbar-search { display: none; }
  .user-meta { display: none; }
  .mode-switch { flex-shrink: 0; }
  .online-users-stack { display: none; }
  .topbar { padding-left: 16px; padding-right: 16px; }
  .topbar-actions { gap: 6px; }

  .sidebar {
    position: fixed; top: 0; left: 0; bottom: 0; width: 260px; z-index: 200;
    transform: translateX(-100%); transition: transform 0.2s ease;
  }
  .app-shell.mobile-drawer-open .sidebar { transform: translateX(0); }
}

/* ---------- Indicadores e cartões ---------- */

.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 16px; margin-bottom: 24px; }

.stat-tile { background: var(--surface); border: 1px solid transparent; box-shadow: var(--shadow-suave); border-radius: var(--radius); padding: 18px 20px; display: flex; flex-direction: column; gap: 6px; }
.stat-label { font-size: 13px; color: var(--ink-soft); }
.stat-value { font-family: var(--font-display); font-size: 28px; font-weight: 600; }

.card { background: var(--surface); border: 1px solid transparent; border-radius: var(--radius); padding: 20px; box-shadow: var(--shadow-suave); }
.card-header { margin-bottom: 14px; }
.card-header h2 { font-size: 18px; margin: 0; }

/* Box da chave em texto puro (templates/formularios/index.html) — some da
   tela depois do primeiro request, então precisa chamar atenção: fundo
   e borda em --success (o card em volta já sinaliza "sucesso", isto marca
   o valor que precisa ser copiado agora). Fonte monoespaçada pra facilitar
   conferir caractere a caractere, e wrap pra chave longa não vazar do card. */
.chave-gerada-box { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; background: color-mix(in srgb, var(--success) 12%, var(--surface)); border: 1px solid var(--success); border-radius: var(--radius); padding: 12px 16px; margin-top: 8px; }
.chave-gerada-box code { font-family: var(--font-mono, monospace); font-size: 14px; word-break: break-all; }

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

/* Tela /contatos/, visão Cards — grid de tamanho automático, mesmo raciocínio
   de .feature-grid; card individual reaproveita .card (fundo/borda/sombra já
   definidos ali), só acrescenta clique. Só nome + empresa (pedido de
   Rocélio, 12/09/2026) — sem data de atualização nem cargo no card. */
.contatos-cards-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 12px; }
.contatos-card { cursor: pointer; transition: border-color 0.15s ease, box-shadow 0.15s ease; }
.contatos-card:hover { border-color: var(--primary); box-shadow: var(--shadow); }

/* Nome do contato como gatilho pra abrir o histórico (Lista ou Cards) —
   <button> estilizado pra parecer texto simples, não um botão. Sem
   sublinhado no hover (pedido de Rocélio, 12/09/2026) — só a cor muda,
   pra não parecer link clicável de navegador. */
.contato-nome-link { background: none; border: none; padding: 0; margin: 0; font: inherit; color: inherit; cursor: pointer; text-align: left; white-space: nowrap; }
.contato-nome-link:hover { color: var(--primary); }
/* Largura mínima da coluna Nome — antes era uma regra CSS fixa aqui;
   virou data-min-ch="20" no <th> (templates/contatos/index.html),
   aplicado por static/js/tabela_interativa.js junto com o
   redimensionamento por arrasto genérico (12/09/2026), que toda
   tabela com data-tabela-colunas-arrastaveis já ganha de graça. */

/* Bolinha de "filtro ativo" no ícone de Filtros — só aparece com algum
   filtro aplicado (querystring), inclusive a busca rápida. */
.contatos-filtro-ativo-ponto {
  position: absolute; top: 4px; right: 4px; width: 7px; height: 7px;
  border-radius: 50%; background: var(--primary); border: 1.5px solid var(--surface);
}

/* Grid de duas colunas da tela /contatos/ — listagem + histórico de Notas
   do contato clicado, mesmo mecanismo de .lead-layout/.lead-sidebar (ver
   comentário no template): 2ª coluna colapsável via classe, botão de
   recolher dentro da sidebar, botão de reabrir fora dela (position:
   absolute, só aparece quando recolhida). Nomes próprios — são páginas
   diferentes, só o mecanismo é reaproveitado. */
.contatos-layout { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: 20px; align-items: start; }
@media (max-width: 1023px) {
  .contatos-layout { grid-template-columns: 1fr; }
}
.contatos-sidebar { position: sticky; top: 16px; }
.contatos-sidebar-cabecalho { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.contatos-layout-sidebar-recolhida { grid-template-columns: minmax(0, 1fr) 0px !important; }
.contatos-layout-sidebar-recolhida .contatos-sidebar { display: none; }
.contatos-sidebar-expandir-btn {
  display: none; position: absolute; top: 16px; right: 0;
  align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: 50%;
  background: var(--surface-alt); color: var(--ink-soft); border: 1px solid var(--border);
  cursor: pointer; transition: background-color 0.15s ease, color 0.15s ease;
}
.contatos-sidebar-expandir-btn:hover { background: color-mix(in srgb, var(--primary) 14%, var(--surface-alt)); color: var(--primary); }
.contatos-sidebar-expandir-btn svg { width: 16px; height: 16px; }
.contatos-layout-sidebar-recolhida .contatos-sidebar-expandir-btn { display: flex; }

/* Grade de duas colunas do painel de Tags em Pipeline e Clientes
   (13/09/2026) — mesmo mecanismo do .contatos-layout acima, polaridade
   invertida: aqui a 2ª coluna nasce ESCONDIDA (nenhuma das duas telas tem
   um "Histórico" pra ocupar o espaço por padrão) e só aparece com a
   classe -aberta, ligada pelo ícone de Tag na toolbar
   (alternarPainelTags em static/js/pipeline.js). Nomes genéricos —
   Clientes reaproveita a mesma marcação e o mesmo JS, não duplica. */
.tags-sidebar-layout { display: grid; grid-template-columns: minmax(0, 1fr); gap: 20px; align-items: start; }
.tags-sidebar-layout-aberta { grid-template-columns: minmax(0, 1fr) 320px; }
.tags-sidebar-layout .tags-sidebar { display: none; }
.tags-sidebar-layout-aberta .tags-sidebar { display: block; position: sticky; top: 16px; }
@media (max-width: 1023px) {
  .tags-sidebar-layout-aberta { grid-template-columns: minmax(0, 1fr); }
}
.tags-sidebar-cabecalho { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }

.param-card { display: block; text-decoration: none; transition: border-color 0.15s ease, box-shadow 0.15s ease; }
.param-card:hover { border-color: var(--primary); box-shadow: var(--shadow); }
.param-card h2 { font-size: 17px; margin: 0 0 6px; }
.param-card p { font-size: 13px; color: var(--ink-soft); margin: 0 0 12px; }
.param-card-count { font-size: 12px; font-weight: 600; color: var(--primary); }
.param-card-disabled { cursor: not-allowed; opacity: 0.5; }
.param-card-disabled:hover { border-color: inherit; box-shadow: none; }

.param-row-actions { display: flex; gap: 8px; justify-content: flex-end; }
.param-inline-form { margin: 0; }

.estagio-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.estagio-row {
  display: flex; align-items: center; gap: 12px; padding: 12px 8px;
  border-bottom: 1px solid var(--border); cursor: grab;
}
.estagio-row:last-child { border-bottom: none; }
.estagio-row-arquivado { opacity: 0.5; }
.estagio-cor { width: 12px; height: 12px; border-radius: 50%; flex-shrink: 0; }
.estagio-nome { flex: 1; font-weight: 600; font-size: 14px; }

.categoria-group { margin-bottom: 16px; cursor: grab; }
.categoria-group:last-child { margin-bottom: 0; }
.categoria-header { display: flex; align-items: center; gap: 12px; padding-bottom: 12px; margin-bottom: 4px; border-bottom: 1px solid var(--border); }
.categoria-header h2 { flex: 1; font-size: 16px; margin: 0; }
.servico-codigo { font-size: 11px; color: var(--ink-soft); font-family: var(--font-mono); }
.servico-preco { font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; }

.duas-colunas { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; align-items: start; }
.servico-negocio { font-size: 12px; color: var(--ink-soft); }
.servico-descricao { display: block; font-size: 12px; font-weight: 400; color: var(--ink-soft); margin-top: 2px; white-space: pre-line; }
.modal-extra-action { margin-top: 12px; }

.badge-periodicidade-recorrente { background: color-mix(in srgb, var(--success) 15%, var(--surface)); color: var(--success); }
.badge-periodicidade-setup { background: color-mix(in srgb, var(--info) 15%, var(--surface)); color: var(--info); }
.badge-periodicidade-projeto_hora { background: color-mix(in srgb, var(--accent) 15%, var(--surface)); color: var(--accent); }

@media (max-width: 767px) {
  .estagio-row { flex-wrap: wrap; }
  .estagio-nome { flex: 1 1 100%; order: -1; }
  .categoria-header { flex-wrap: wrap; align-items: flex-start; }
  .categoria-header h2 { flex: 1 1 100%; }
  .categoria-header .param-row-actions { flex: 1 1 100%; justify-content: flex-start; margin-top: 8px; }
  .duas-colunas { grid-template-columns: 1fr; }
}

.data-table { width: 100%; border-collapse: collapse; font-size: 13px; }
/* Linha divisória suavizada e altura reduzida (pedido de Rocélio, 28/08/2026,
   testando com a Lista de Tarefas e do Pipeline) — mistura a cor do border
   com o fundo em vez de um cinza fixo mais escuro, mesma técnica de
   color-mix já usada nos badges de cor (ver §3 do catálogo). */
.data-table th { text-align: left; padding: 8px 12px; color: var(--ink-soft); font-size: 11px; text-transform: uppercase; letter-spacing: 0.03em; border-bottom: 1px solid var(--border); }
.data-table td { padding: 9px 12px; border-bottom: 1px solid color-mix(in srgb, var(--border) 55%, var(--surface)); }
.data-table tr:last-child td { border-bottom: none; }
.data-table tr.linha-clicavel { cursor: pointer; }
.data-table tr.linha-clicavel:hover { background: color-mix(in srgb, var(--surface-alt) 45%, var(--surface)); }
/* Realce ao passar o mouse em QUALQUER linha de dado — pedido de
   Rocélio, 12/09/2026, em Contatos, mas vale pra toda .data-table: ajuda
   a acompanhar a linha entre colunas ao escanear a tabela, mesmo quando
   a linha não é um único alvo de clique (Contatos tem duas ações
   diferentes na mesma linha — nome e Editar — por isso não usa
   .linha-clicavel, que implica a linha inteira navegar pra algum lugar). */
/* Mistura leve, não o --surface-alt cheio (pedido de Rocélio, 12/09/2026
   — a versão anterior ficava forte demais). Mesma técnica color-mix já
   usada nos badges (§3 do catálogo). */
.data-table tbody tr:hover { background: color-mix(in srgb, var(--surface-alt) 45%, var(--surface)); }

/* Cabeçalho ordenável — ver static/js/tabela_interativa.js. A seta só
   aparece na coluna ativa; nas outras fica reservado o espaço (não
   afastando o texto ao clicar) via ::after sempre presente, conteúdo vazio
   até a coluna ficar ativa. */
.data-table th.th-ordenavel { cursor: pointer; user-select: none; }
.data-table th.th-ordenavel:hover { color: var(--ink); }
.data-table th.th-ordenavel::after { display: inline-block; width: 10px; margin-left: 4px; content: ''; }
.data-table th.th-ordenavel-asc::after { content: '▲'; }
.data-table th.th-ordenavel-desc::after { content: '▼'; }

/* Colunas arrastáveis — o cursor de "mão" no cabeçalho já é o afford de
   arrastar; sem indicador visual a mais pra não competir com a seta de
   ordenação no mesmo <th>. position:relative ancora a alça de
   redimensionar (abaixo), que é position:absolute dentro do th. */
[data-tabela-colunas-arrastaveis] thead th { cursor: grab; position: relative; }
[data-tabela-colunas-arrastaveis] thead th:active { cursor: grabbing; }

/* Alça de redimensionar coluna (12/09/2026, static/js/tabela_interativa.js)
   — faixa fina na borda direita do th, cursor próprio, só fica visível
   (borda azul) no hover/enquanto arrasta, pra não empatar visualmente
   com a borda divisória de sempre quando ninguém está interagindo. */
.tabela-coluna-redimensionar {
  /* Achado real, 12/09/2026: 8px de alvo era estreito demais pra clicar
     de verdade — Rocélio reportou não conseguir arrastar. Straddle na
     borda (right:-5px) em vez de ficar só pra dentro da própria coluna:
     alvo mais largo (14px) sem empurrar a linha divisória visualmente. */
  position: absolute; top: 0; right: -5px; bottom: 0; width: 14px;
  cursor: col-resize; z-index: 2;
}
.tabela-coluna-redimensionar:hover, .tabela-coluna-redimensionar:active {
  background: color-mix(in srgb, var(--primary) 40%, transparent);
}

/* Select de status inline na Lista de Tarefas — mesma cor do status (a
   cor vem por style="" inline, uma por linha), fundo tingido dela via
   color-mix com currentColor em vez de repetir a cor em duas
   propriedades — muda a cor num lugar só. */
.status-select-inline {
  appearance: none; border: none; border-radius: 999px; padding: 3px 22px 3px 10px;
  font-size: 11px; font-weight: 600; cursor: pointer;
  background: color-mix(in srgb, currentColor 15%, var(--surface))
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23888' stroke-width='1.5'/%3E%3C/svg%3E") no-repeat right 8px center;
}

/* Painel lateral com abas — hoje só a Visão Lista do Pipeline (filtros +
   colunas), pensado pra ser o mesmo padrão de qualquer painel lateral
   futuro. Desliza da direita, não é dropdown pequeno tipo .filter-panel.
   Pedido de Rocélio, 28/08/2026. */
.painel-lateral-overlay { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.35); z-index: 600; }
.painel-lateral {
  position: fixed; top: 0; right: 0; height: 100vh; width: 340px; max-width: 90vw;
  background: var(--surface); box-shadow: var(--shadow); z-index: 601;
  display: flex; flex-direction: column; transform: translateX(100%); transition: transform 0.2s ease;
}
.painel-lateral.aberto { transform: translateX(0); }
.painel-lateral-abas { display: flex; align-items: center; border-bottom: 1px solid var(--border); flex-shrink: 0; }
.painel-lateral-aba {
  flex: 1; padding: 14px 8px; text-align: center; cursor: pointer; border: none;
  background: none; color: var(--ink-soft); font-weight: 600; font-size: 13px;
  border-bottom: 2px solid transparent;
}
.painel-lateral-aba.active { color: var(--primary); border-bottom-color: var(--primary); }
.painel-lateral-abas .modal-close { flex-shrink: 0; margin: 0 10px; }
.painel-lateral-corpo { flex: 1; overflow-y: auto; padding: 16px; }

/* Barra de progresso — ver templates/_componentes/barra_progresso.html */
.barra-progresso { position: relative; width: 100%; max-width: 110px; height: 16px; background: var(--surface-alt); border-radius: 999px; overflow: hidden; }
.barra-progresso-preenchimento { height: 100%; background: var(--success); border-radius: 999px; transition: width 0.2s ease; }
.barra-progresso-texto { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-size: 10px; font-weight: 600; color: var(--ink); }

/* Paginação client-side — ver static/js/tabela_interativa.js */
.tabela-paginacao { display: flex; align-items: center; justify-content: flex-end; gap: 10px; padding: 12px; flex-wrap: wrap; }
.tabela-paginacao-seletor { width: auto; }
.tabela-paginacao-texto { font-size: 12px; color: var(--ink-soft); }

.table-scroll { overflow-x: auto; }

/* Busca, totais e fixação da tabela interativa — ver
   static/js/tabela_interativa.js (fatia 1, outubro/2026). */

/* Barra acima da tabela (busca + Limpar + Exportar): sempre uma linha; se
   não couber, rola na horizontal (regra "Barra é sempre uma barra"). */
.tabela-barra { display: flex; align-items: center; gap: 8px; flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden; margin-bottom: 10px; }
.tabela-barra > * { flex-shrink: 0; }
/* Seletor composto de propósito: o estilo global de campo (input[type="text"],
   especificidade maior que uma classe só) trava width em 100%. */
.tabela-barra .tabela-busca { width: 260px; padding: 6px 10px; font-size: 13px; }

/* Escondida pela busca. Classe própria (e não style.display) porque a
   paginação já usa style.display pra esconder as outras páginas: as duas
   coisas não podem se atropelar. */
.linha-filtrada { display: none; }
.data-table .tabela-vazio-filtro td { text-align: center; color: var(--ink-soft); padding: 20px 12px; }

/* Rodapé de totais. Sticky no fim da área rolável: só tem efeito quando a
   tabela está numa área de altura limitada (.table-scroll-fixa); fora
   disso fica no fim da tabela, como um rodapé comum. */
.data-table tfoot td { position: sticky; bottom: 0; z-index: 2; font-weight: 600; background: var(--surface-alt); border-bottom: none; box-shadow: 0 -1px 0 var(--border); }

/* Cabeçalho e 1ª coluna fixos (data-tabela-fixa). Sombra de 1px em vez de
   border: com border-collapse: collapse a borda NÃO acompanha a célula
   sticky e fica pra trás ao rolar — a box-shadow vai junto. Fundo sólido
   por token (tema claro/escuro vêm de graça), senão o conteúdo rolando
   aparece por baixo. */
.table-scroll-fixa { overflow: auto; max-height: var(--tabela-altura-max, 70vh); }
.tabela-fixa thead th { position: sticky; top: 0; z-index: 3; background: var(--surface); border-bottom: none; box-shadow: 0 1px 0 var(--border); }
.tabela-fixa tbody td:first-child,
.tabela-fixa tfoot td:first-child,
.tabela-fixa thead th:first-child { position: sticky; left: 0; background: var(--surface); box-shadow: 1px 0 0 var(--border); }
.tabela-fixa tbody td:first-child { z-index: 1; }
.tabela-fixa tfoot td:first-child { z-index: 4; background: var(--surface-alt); box-shadow: 1px -1px 0 var(--border); }
/* Canto: precisa ficar acima do cabeçalho E da coluna fixa. */
.tabela-fixa thead th:first-child { z-index: 5; box-shadow: 1px 1px 0 var(--border); }

/* Alinhamento por coluna (macro tabela). */
.data-table .tabela-alinha-direita { text-align: right; }
.data-table .tabela-alinha-centro { text-align: center; }

.detalhes-execucao-lista { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 10px 16px; margin: 0 0 8px; }
.detalhes-execucao-item dt { font-size: 11px; color: var(--ink-soft); text-transform: uppercase; letter-spacing: 0.03em; margin-bottom: 2px; }
.detalhes-execucao-item dd { margin: 0; }
.detalhes-execucao-vazio { color: var(--ink-soft); }

.badge { display: inline-block; padding: 3px 10px; border-radius: 999px; font-size: 11px; font-weight: 600; }
.badge-status-criado               { background: color-mix(in srgb, var(--info) 15%, var(--surface)); color: var(--info); }
.badge-status-em-preenchimento     { background: color-mix(in srgb, var(--warning) 15%, var(--surface)); color: var(--warning); }
.badge-status-em-enriquecimento    { background: color-mix(in srgb, var(--secondary) 15%, var(--surface)); color: var(--secondary); }
.badge-status-aguardando-validacao { background: color-mix(in srgb, var(--accent) 15%, var(--surface)); color: var(--accent); }
.badge-status-concluido            { background: color-mix(in srgb, var(--success) 15%, var(--surface)); color: var(--success); }
.badge-status-erro                 { background: color-mix(in srgb, var(--error) 15%, var(--surface)); color: var(--error); }

/* ---------- Kanban (Diagnósticos) ---------- */

.kanban-board { display: flex; gap: 16px; overflow-x: auto; padding-bottom: 8px; scroll-snap-type: x proximity; }

/* flex: 1 0 146px — cresce, nunca encolhe, base de 146px.

   A base garante o PISO de 6 colunas na menor tela de 13/14" em uso: 1280px de
   viewport dá 956px úteis, e (956 - 5*16)/6 = 146. Com 172px fixos cabiam só
   5,17 em 1280 e 5,63 em 1366 — resoluções escaladas comuns nesses notebooks,
   onde a regra falhava.

   O flex-grow: 1 resolve a outra ponta. Com largura fixa, um monitor de 1920px
   deixava 672px vazios à direita, porque as 5 colunas existentes não ocupavam a
   tela. Agora elas dividem a sobra entre si.

   flex-shrink: 0 é o que preserva o piso: quando os estágios passam do que
   cabe, as colunas mantêm os 146px e o quadro rola na horizontal, em vez de
   espremer todas até ficarem ilegíveis.

   max-width evita o extremo oposto — num ultrawide com poucos estágios, cada
   coluna viraria uma faixa larguíssima de conteúdo ralo.

   Abaixo de 768px a media query de 82vw já manda. */
/* `height`, não `max-height` — pedido de Rocélio, 30/08/2026: com max-height a
   coluna só crescia até a mais alta das irmãs (stretch do flex), então um
   estágio com poucos cards parava de encher o fundo bem antes do rodapé da
   página, deixando um vão vazio. `height` fixo força todas a ocupar o espaço
   disponível até o fim da viewport, e quem sobra rola dentro de
   `.kanban-column-body` (overflow-y:auto), não da coluna inteira.
   152px é cabeçalho + barra de ações acima (~120px) mais o respiro abaixo
   (padding-bottom de .content e do próprio .kanban-board, 32px) — medido no
   navegador, não um chute; ajustar os dois se algum dia mudar de altura. */
/* min-width: 0 é obrigatório aqui, senão o flexbox se recusa a encolher a
   coluna abaixo do conteúdo dela — a coluna com mais cards/texto ficava bem
   mais larga que as outras, mesmo todas tendo o mesmo flex-grow (achado
   testando de verdade: 314px vs 146-199px nas colunas vizinhas, mesmo
   flex: 1 0 146px em todas). Mesma causa raiz que .kanban-column-nome já
   documenta, só que no item flex inteiro, não só no texto do título. */
.kanban-column { flex: 1 0 146px; min-width: 0; max-width: 320px; background: var(--surface-alt); border-radius: var(--radius); display: flex; flex-direction: column; height: calc(100vh - 152px); scroll-snap-align: start; }
/* "Cor do topo do card" do Estágio (30/08/2026, corrigido em seguida:
   pedido original mandava colorir o TOPO DE CADA CARD, mas o exemplo de
   referência — print de outro CRM — colore o topo da COLUNA/estágio, não
   os cards individuais; a barra ficou aqui). Cor vem inline
   (--cor-topo-coluna) porque é livre (dez opções da paleta), não uma classe
   fixa do CSS. overflow:hidden recorta as pontas retas da barra pelos
   cantos arredondados da coluna. */
.kanban-column-cor-topo { position: relative; overflow: hidden; }
.kanban-column-cor-topo::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 4px; background: var(--cor-topo-coluna, transparent); z-index: 1; }

@media (max-width: 767px) {
  .kanban-column { flex: 0 0 82vw; }
}

/* Duas linhas: nome + contador em cima, total em R$ embaixo. Continua uma
   altura FIXA para todas as colunas — as duas linhas existem sempre, e cada
   uma nunca quebra —, que é o que mantém os corpos das colunas alinhados. */
.kanban-column-header { display: flex; flex-direction: column; gap: 2px; padding: 12px 14px 8px; }
.kanban-column-titulo-linha {
  display: flex; align-items: center; justify-content: space-between; gap: 6px;
  /* Título de coluna é SEMPRE uma linha, nunca quebra.
     O uppercase e o letter-spacing continuam FORA, e isso não é estilo — é o
     que faz caber. Maiúscula custa ~30% de largura e era o maior vilão:
     "AGUARDANDO VALIDAÇÃO" não cabia de jeito nenhum numa coluna de 146px.

     O negrito voltou a pedido de Rocélio em 25/08/2026, contra a decisão
     anterior de deixá-lo em 400. Medido antes de aceitar: com 600 o nome mais
     longo do app ("Aguardando Validação") ainda cabe inteiro. As reticências
     seguem armadas para o estágio extremo que alguém cadastrar depois. */
  font-size: 13px; font-weight: 600; color: var(--ink); }
/* nowrap + ellipsis: a garantia de uma linha só. min-width:0 é obrigatório —
   filho de flex tem min-width auto por padrão e se recusa a encolher abaixo do
   próprio conteúdo, o que anularia o text-overflow. */
.kanban-column-nome { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
/* flex-shrink:0 para o contador não ser espremido quando o nome é longo — quem
   cede espaço é o texto, que tem as reticências para isso. */
.kanban-column-count { flex-shrink: 0; background: var(--surface); border-radius: 999px; padding: 1px 8px; font-size: 11px; font-weight: 400; color: var(--ink-soft); }
/* Peso normal e cor suave: o total informa, não compete com o nome do estágio.
   Uma linha só, pela mesma razão do título — altura de cabeçalho que varia
   desalinha os corpos das colunas vizinhas. */
.kanban-column-total {
  font-size: 11px; font-weight: 400; color: var(--ink-soft);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* ---------- Kanban compacto: mesmo quadro, card reduzido ----------
   Terceira visão, ao lado de Kanban e Lista. Não é outra tela nem outro
   template: é o MESMO quadro com o card mostrando menos. Duplicar o markup
   para isso criaria dois lugares para corrigir cada defeito de card.

   O que fica: nome do Lead, valor e temperatura — o suficiente para achar e
   arrastar. O que sai: segmento, responsável, data, tags e o rodapé. */
.kanban-compacto .kanban-card { padding: 8px 10px; }
.kanban-compacto .kanban-card-segmento,
.kanban-compacto .kanban-card-gerado-por,
.kanban-compacto .kanban-card-tags,
.kanban-compacto .kanban-card-footer { display: none; }
.kanban-compacto .kanban-card-empresa { margin-bottom: 2px; font-size: 12px; }
.kanban-compacto .kanban-card-linha-valor { margin-bottom: 0; }
.kanban-compacto .kanban-column-body { gap: 5px; }

/* Barra de rolagem completamente removida da vista — pedido de Rocélio,
   03/09/2026, depois de duas tentativas de só afiná-la/escondê-la em
   repouso (ver Padrão #27 no catálogo, que registra as tentativas
   anteriores e por que `scrollbar-gutter: stable` não serve aqui). Rolar
   continua funcionando normalmente por trackpad/roda do mouse/arrastar
   um card até a borda — só não existe mais indicador visual nenhum. */
.kanban-column-body { flex: 1; overflow-y: auto; overscroll-behavior-y: contain; padding: 0 10px 10px; display: flex; flex-direction: column; gap: 5px; min-height: 60px; scrollbar-width: none; }
.kanban-column-body::-webkit-scrollbar { display: none; }
/* overscroll-behavior-y: contain acima trava o "scroll chaining" — rolar o mouse sobre os
   cards de um estágio rola só aquela coluna, nunca escapa pra rolar a página inteira, mesmo
   quando a coluna chega no topo/fim do próprio scroll (padrão de qualquer Kanban de CRM). */

/* Padding inferior reduzido à metade do superior (02/09/2026, pedido de
   Rocélio): a margem depois da última linha do card estava folgada demais
   comparada ao respiro entre as linhas internas. */
.kanban-card { background: var(--surface); border-radius: var(--radius-sm); border: 1px solid transparent; box-shadow: var(--shadow-suave); padding: 10px 12px 5px; cursor: grab; box-shadow: var(--shadow); }
.kanban-card-badge-parado { display: inline-block; font-size: 10px; padding: 2px 6px; margin-bottom: 5px; }
/* Mesma regra do título de coluna: nome do Lead sempre em uma linha. Com a
   coluna podendo chegar a 146px, nome longo quebraria em duas ou três linhas e
   os cards da mesma coluna ficariam com alturas diferentes.
   margin-bottom: 4px é o mesmo valor usado por .kanban-card-segmento e
   .kanban-card-linha-valor logo abaixo — as três linhas do meio do card
   precisam do MESMO espaçamento entre si (pedido de Rocélio, 02/09/2026).
   Primeiro foram uniformizadas em 2px, mas o título (13px, negrito) tem
   menos respiro visual dentro da própria linha que texto de 11px normal —
   o mesmo valor em pixels parecia mais apertado ali do que embaixo. Subiu
   pra 4px nas três, ainda uniforme, resolvendo o aperto sem abrir exceção. */
.kanban-card-empresa { font-weight: 600; font-size: 13px; margin-bottom: 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kanban-card-linha-valor { display: flex; justify-content: space-between; align-items: center; gap: 8px; margin-bottom: 4px; }
.kanban-card-valor { font-size: 12px; font-weight: 600; color: var(--ink); white-space: nowrap; }
/* Estágio pode ocultar valor/temperatura do card (02/09/2026) — o elemento
   sempre existe no HTML (ver comentário em templates/pipeline/index.html),
   só fica display:none, pra o JS do drag-and-drop poder ligar/desligar isto
   sem precisar re-renderizar o card vindo do servidor. */
.kanban-card-campo-oculto { display: none; }
/* Responsável + data na mesma linha (30/08/2026) — eram 2 linhas (gerado-por
   sozinho, depois data+abrir no rodapé), viraram 1: `.kanban-card-footer`
   passou a ter os dois. Responsável cresce e trunca (min-width:0 é
   obrigatório em filho de flex, senão o texto se recusa a encolher e
   `.kanban-card-data-acoes` seria empurrado pra fora); data+abrir não
   encolhem (flex-shrink:0), sempre coladas uma na outra. */
.kanban-card-gerado-por { flex: 1; min-width: 0; font-size: 11px; color: var(--ink-soft); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kanban-card-data { font-size: 11px; color: var(--ink-soft); }
.kanban-card-footer { display: flex; justify-content: space-between; align-items: center; gap: 8px; }
.kanban-card-data-acoes { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
.kanban-card-responsavel { font-size: 11px; color: var(--primary); background: color-mix(in srgb, var(--primary) 12%, transparent); padding: 2px 8px; border-radius: 999px; }
.kanban-card-ghost { opacity: 0.4; }

/* ---------- Cartões de validação (Validações dos Agentes) ---------- */

.badge-neutro { background: var(--surface-alt); color: var(--ink-soft); }
.badge-vendedor { background: color-mix(in srgb, var(--info) 15%, var(--surface)); color: var(--info); }
.checkbox-label { display: flex; align-items: center; gap: 8px; margin: 14px 0 6px; font-size: 13px; font-weight: 600; color: var(--ink-soft); }
.checkbox-label input { width: auto; }

.badge-confianca-alta  { background: color-mix(in srgb, var(--success) 15%, var(--surface)); color: var(--success); }
.badge-confianca-media { background: color-mix(in srgb, var(--warning) 15%, var(--surface)); color: var(--warning); }
.badge-confianca-baixa { background: color-mix(in srgb, var(--error) 15%, var(--surface)); color: var(--error); }

.validacao-card-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; gap: 6px; }

.validacao-card-campo { font-size: 12px; color: var(--ink-soft); margin-bottom: 6px; }

.validacao-card-valores { display: flex; align-items: baseline; gap: 6px; font-size: 12px; margin-bottom: 8px; flex-wrap: wrap; }
.validacao-valor-atual { color: var(--ink-soft); text-decoration: line-through; }
.validacao-valor-seta { color: var(--ink-soft); }
.validacao-valor-sugerido { color: var(--ink); font-weight: 600; }
/* O valor sugerido virou <input> quando a sugestão está pendente — pedido de
   Rocélio para poder corrigir antes de aprovar. Zera a aparência de campo de
   formulário para continuar lendo como texto dentro da frase, e cresce só o
   necessário (input tem largura fixa por padrão do navegador). O foco marca
   com contorno visível — é a única pista de que aquilo é editável. */
.validacao-valor-editavel {
  font: inherit; font-weight: 600; color: var(--ink); background: none;
  border: 1px solid transparent; border-radius: var(--radius-sm);
  padding: 1px 4px; min-width: 60px; width: 220px; max-width: 100%;
  /* field-sizing: content mediria o texto de verdade, mas só existe em
     Chromium recente — sem fallback ele deixaria Firefox/Safari com o
     tamanho intrínseco do <input> (~170px), o mesmo defeito corrigido na
     aba Serviços do Lead (ver §22 do catálogo). 220px cobre e-mail,
     telefone e endereço curto sem depender do suporte do navegador. */
  field-sizing: content;
}
.validacao-valor-editavel:hover { border-color: var(--border); }
.validacao-valor-editavel:focus { border-color: var(--primary); outline: none; background: var(--surface); }

/* Tabela de revisão de sugestões (26/08/2026) — substituiu o card por campo,
   que ficava confuso com muitos campos pendentes de uma vez (achado por
   Rocélio). Reaproveita .data-table; só o que é específico daqui. */
.sugestao-valor-atual { color: var(--ink-soft); }
/* Confiança e fonte abaixo do valor editável, não em coluna própria — uma
   coluna a mais só pra isso deixaria a tabela mais larga sem ganhar leitura;
   como informação secundária do "Dados encontrados", cabe junto. */
.sugestao-meta { display: flex; align-items: center; gap: 8px; margin-top: 4px; font-size: 11px; }
.sugestoes-tabela .btn-sm { white-space: nowrap; }
/* Colunas "No site" e "Encontrado" (18/09/2026): valor de cada fonte ao lado do
   campo editável, com "usar" pra copiar pra ele. Valor longo (endereço) quebra
   dentro da célula em vez de alargar a tabela. */
.sugestao-valor-fonte { color: var(--ink-soft); max-width: 220px; overflow-wrap: anywhere; }
.sugestao-valor-fonte .btn-sm { margin-top: 4px; }
.badge-origem-receita { background: color-mix(in srgb, var(--info) 15%, var(--surface)); color: var(--info); }
.badge-origem-ia { background: var(--surface-alt); color: var(--ink-soft); }

.validacao-card-footer { justify-content: space-between; align-items: baseline; }

.validacao-card-fonte {
  font-size: 11px;
  color: var(--info);
  text-decoration: underline;
}
.validacao-card-fonte:hover { color: var(--primary); }

.validacao-card-data { font-size: 10px; color: var(--ink-soft); white-space: nowrap; }

/* ---------- Pipeline: temperatura do lead e segmento no card ---------- */

.kanban-card-header { display: flex; justify-content: flex-end; margin-bottom: 5px; }
/* Sem isto o Segmento quebrava em 2 linhas em cards estreitos (ex.: "Diagma",
   "Consultoria em Supply Chain e Logística") — mesma proteção que Empresa já
   tinha, e mesmo margin-bottom das outras linhas do meio do card (ver
   comentário em .kanban-card-empresa). Achado por Rocélio, 02/09/2026. */
.kanban-card-segmento { font-size: 11px; color: var(--ink-soft); margin-bottom: 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.badge-temperatura-quente { background: color-mix(in srgb, var(--error) 15%, var(--surface)); color: var(--error); }
.badge-temperatura-morno  { background: color-mix(in srgb, var(--warning) 15%, var(--surface)); color: var(--warning); }
.badge-temperatura-frio   { background: color-mix(in srgb, var(--info) 15%, var(--surface)); color: var(--info); }

/* Badge de temperatura virou <select> (30/08/2026, card do Kanban; 31/08/2026,
   ficha do Lead — 2ª ocorrência do mesmo padrão) — clicar abre as 3 opções
   sem precisar de mais nada. appearance:none tira a seta e a borda nativas do
   <select>, senão ele deixa de parecer um badge; cursor e font herdam do
   `.badge` (mesma classe, cor/fundo continuam vindo de `.badge-temperatura-*`
   acima). */
/* text-align-last (não só text-align): Firefox usa text-align-last pra
   decidir o alinhamento do VALOR fechado de um <select>, text-align sozinho
   não move nada lá — Chrome obedece os dois, então declarar os dois cobre
   ambos sem farejar navegador. */
/* line-height explícito pela mesma razão já documentada em .btn: um <select>
   nativo sem isto usa a métrica de altura do navegador, maior que uma linha
   de texto normal — deixava a linha de valor+temperatura do card do Kanban
   mais alta que as vizinhas (empresa, segmento), mesmo com o mesmo
   margin-bottom nas três. Achado por Rocélio, 02/09/2026, comparando os
   espaçamentos lado a lado. */
/* width: auto vence o `width: 100%` que todo <select> herda da regra global
   (linha ~285) — sem isto o badge estica pra ocupar todo o espaço livre do
   flex pai. Achado real, 02/09/2026: na ficha do Lead isto ficava mascarado
   enquanto o form de funil/estágio dividia a mesma linha (cada <select>
   "brigava" por 100%, então a divisão ficava proporcional e passava
   despercebido); ao sair o funil da linha 1, o badge de temperatura ficou
   sozinho e tomou a largura inteira. */
.badge-temperatura-select { border: none; appearance: none; -webkit-appearance: none; cursor: pointer; font-family: inherit; text-align: center; text-align-last: center; line-height: 1.4; width: auto; flex-shrink: 0; }
/* Mesmo tipo de hover que .btn-primary já usa (filter, não cor fixa) —
   funciona pras três cores de temperatura sem precisar de uma regra por
   cor. Pedido de Rocélio, 31/08/2026. */
.badge-temperatura-select:hover { filter: brightness(0.95); }
/* Tentativa revertida (02/09/2026): dar cor própria a cada <option> (classes
   .opcao-temperatura-*) pra corrigir o dropdown ABERTO mostrando as 3
   opções na cor do valor atual. `getComputedStyle` no select confirmava a
   regra certa (.badge-temperatura-*) sendo aplicada — mas na renderização
   REAL do controle nativo, algo na interação entre o <select> com
   appearance:none e as <option> com background-color próprio fez o
   FECHADO passar a mostrar a cor errada (achado por Rocélio: "Morno"
   aparecendo em azul). Como o fechado é o que importa no dia a dia (é o
   que aparece o tempo todo, sem precisar abrir o dropdown) e já funcionava
   perfeitamente antes, revertido — o problema do aberto (limitação de
   plataforma em macOS de qualquer forma) fica sem solução por enquanto. */
/* Só no card do Kanban: sem isto o navegador reserva a largura da MAIOR
   option ("Quente") mesmo mostrando "Morno" ou "Frio", que são mais curtas;
   isso empurrava "R$ 0,00" da linha e quebrava a linha inteira em duas. */
/* 68px cortava "Quente" (6 letras, a mais longa das três opções) em alguns
   navegadores — a margem contra o texto medido (~59px com padding) era
   pequena demais. 82px dá folga confortável. Rocélio, 31/08/2026. */
.kanban-card-temperatura-select { max-width: 82px; flex-shrink: 0; }

/* ---------- Tarefas: card do Kanban (07/09/2026) ----------
   Prioridade saiu do topo do card (que agora só tem o ícone de prazo,
   ver icone_status_prazo) e passou a dividir linha com a data de
   vencimento — mesmo motivo de .kanban-card-footer ter virado uma linha
   só (ver comentário acima): duas linhas concorrendo por espaço embaixo
   do título é informação demais empilhada sem necessidade. A hora fica
   de fora aqui (mostra só a data) — dentro do card já é resumo, quem
   quiser a hora abre o modal. */
.kanban-card-servico { display: flex; justify-content: space-between; align-items: center; gap: 6px; margin-bottom: 4px; font-size: 11px; color: var(--ink-soft); }

/* Badge de prioridade virou <select> (mesmo padrão do badge de
   temperatura acima) — clicar troca o valor direto no card, sem abrir
   o modal. `event.stopPropagation()` no HTML evita que o clique também
   dispare o onclick do card inteiro (abrirModalTarefa). */
.badge-prioridade-select { border: none; appearance: none; -webkit-appearance: none; cursor: pointer; font-family: inherit; text-align: center; text-align-last: center; line-height: 1.4; width: auto; flex-shrink: 0; }
.badge-prioridade-select:hover { filter: brightness(0.95); }
/* Mesma proteção de largura do .kanban-card-temperatura-select — sem
   isto o <select> reserva a largura da maior opção ("Normal"/"Baixa",
   6 letras) mesmo mostrando uma mais curta, disputando espaço com a
   data na mesma linha. */
.kanban-card-prioridade-select { max-width: 72px; flex-shrink: 0; }

/* Tarefa vencida e não concluída (status_prazo == "atrasada") ganha
   borda grossa vermelha — pedido de Rocélio, 07/09/2026. Não existia
   até aqui nenhum padrão de "borda grossa colorida" em card do sistema
   (Pipeline sinaliza estado com badge de texto, não borda); nasce aqui
   e fica registrado no catálogo pra quem precisar do mesmo efeito. */
.kanban-card-atrasada { border-color: var(--error); border-width: 2px; }

/* ---------- Tags (2026-08-21) ----------
   Ver docs/superpowers/specs/2026-08-21-tags-design.md. Paleta fixa, própria —
   deliberadamente NÃO reaproveita as escalas --seq-*, que o topo deste arquivo
   documenta como escalas de DADO (BI/gráficos), não cores semânticas de UI.
   O banco guarda a chave ('azul'), nunca um hex: assim retunar uma cor é
   mudança de CSS, não migração de dado. A fórmula color-mix deriva de
   --surface, então o contraste acompanha o tema por construção — mesma
   mecânica de .badge-temperatura-* acima. */

:root {
  --tag-azul:    #2368d6;   --tag-teal:   #148a6d;   --tag-verde:  #4a9218;
  --tag-dourado: #a07d10;   --tag-laranja:#c2620f;   --tag-vermelho:#b3432d;
  --tag-roxo:    #7c23d6;   --tag-cinza:  #5c6672;
}

html[data-theme="dark"] {
  /* Hues clareados pro fundo escuro — os tons acima foram escolhidos pra ler
     sobre superfície clara e ficam abafados no escuro. */
  --tag-azul:    #6294e5;   --tag-teal:   #3fc9a6;   --tag-verde:  #90e562;
  --tag-dourado: #e5c75d;   --tag-laranja:#f0954a;   --tag-vermelho:#e8705a;
  --tag-roxo:    #a462e5;   --tag-cinza:  #9aa4b0;
}

/* Uma classe só, no lugar das oito .badge-tag-<cor> que existiam. As oito
   morreram com a paleta: cor deixou de ser um nome fixo com classe própria e
   passou a vir do registro, então acrescentar uma décima primeira cor não exige
   mais mexer em CSS.

   O par claro/escuro chega inline (--tag-claro / --tag-escuro) pela macro
   badge_tag, e é o CSS que escolhe qual vale — a mesma mecânica de antes, só
   que a cor agora vem do dado em vez de uma variável por nome. */
.badge-tag { --tag-cor: var(--tag-claro); background: color-mix(in srgb, var(--tag-cor) 15%, var(--surface)); color: var(--tag-cor); }
html[data-theme="dark"] .badge-tag { --tag-cor: var(--tag-escuro); }

.tags-lista { display: flex; flex-wrap: wrap; gap: 4px; }
.kanban-card-tags { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 6px; }

/* Chip de tag clicável no modal de Tarefa (09/09/2026) — mesmo badge_tag
   já usado em Lead/Cliente, só com um wrapper de botão que dá o estado de
   selecionado sem precisar de uma segunda variante do badge: tag não
   marcada fica esmaecida, marcada fica em opacidade plena. */
.tarefa-tags-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
.tarefa-tag-chip { border: none; background: none; padding: 0; cursor: pointer; opacity: 0.4; }
.tarefa-tag-chip-selecionada { opacity: 1; }

/* Campo de tags dinâmico (12/09/2026, templates/_componentes/tags_dinamicas.html)
   — substitui o catálogo inteiro mostrado como chips (e, em Lead/Cliente, o
   modal de checkbox): aqui só aparecem as tags já vinculadas (removíveis
   por ×) mais um campo de texto que vira chip novo na hora (vírgula, Enter
   ou sair do campo) — cria a tag se o nome não existir, reaproveita se já
   existir. Nasce reutilizável: mesmo componente em Contato, Tarefa, Lead e
   Cliente (ver static/js/tags_dinamicas.js). */
.tags-dinamicas { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.tags-dinamicas-chips { display: inline-flex; flex-wrap: wrap; gap: 6px; }
.tags-dinamicas-input {
  border: 1px dashed var(--border); border-radius: 999px; padding: 3px 10px;
  font-size: 12px; background: none; color: var(--ink); width: 110px;
}
.tags-dinamicas-input:focus { border-style: solid; border-color: var(--primary); outline: none; }
.tags-dinamicas-remover {
  border: none; background: none; cursor: pointer; margin-left: 4px;
  color: inherit; opacity: 0.6; font-size: 13px; line-height: 1; padding: 0;
  vertical-align: middle;
}
.tags-dinamicas-remover:hover { opacity: 1; }

/* Amostra de cor no <select> do cadastro. */
.tag-cor-amostra { display: inline-block; width: 12px; height: 12px; border-radius: 3px; vertical-align: middle; margin-right: 6px; }

/* ---------- Pipeline: toolbar ---------- */

/* UMA faixa, alinhada à direita. Eram duas — .pipeline-toolbar-left/-right em
   cima e .pipeline-filters embaixo —, e a divisão entre elas não tinha
   critério: o período morava com as ações e o segmento com os filtros.

   `flex-wrap: wrap` continua aqui de propósito, contra a regra "barra é sempre
   uma barra". A saída padrão da regra é `overflow-x: auto`, e overflow cria
   contexto de recorte: os .filter-panel são `position: absolute` DENTRO desta
   barra e sumiriam ao abrir. Mesma exceção já registrada no CLAUDE.md. */
.pipeline-toolbar {
  display: flex; align-items: center; justify-content: flex-end;
  gap: 8px; flex-wrap: wrap;
  /* Respiro entre a barra e o conteúdo, a pedido de Rocélio em 25/08/2026.
     Com 12px o quadro colava na barra e as duas coisas liam como um bloco só;
     a barra é ferramenta, o quadro é conteúdo. Reduzido de 22px pra 16px em
     02/09/2026 (mesmo Rocélio, achou 22px folgado demais) — ainda bem acima
     dos 12px rejeitados, só um pouco mais compacto. */
  margin-bottom: 16px;
}
/* Modificador pra quem reaproveita .pipeline-toolbar sem ter painel suspenso
   `position: absolute` dentro dela (Tarefas, 27/08/2026: só <select> nativos,
   cujo menu é do sistema operacional — overflow do pai nunca corta ele,
   diferente do .filter-panel do Pipeline). Sem essa exceção pesando, a barra
   volta pra regra padrão do app: rola na horizontal em vez de quebrar linha.
   Combinado com .pipeline-toolbar de propósito, pra vencer o flex-wrap sem
   depender de ordem no arquivo. */
.pipeline-toolbar.pipeline-toolbar-rolar {
  /* justify-content:flex-end SAI aqui — é a causa do bug. Combinado com
     overflow, o Flexbox empurra o conteúdo que excede a largura pra fora
     do lado ESQUERDO (coordenadas negativas), e esse trecho fica
     inacessível por scroll: scrollLeft não vai negativo. Medido em
     27/08/2026 no Tarefas — os dois primeiros itens da barra (visão
     Kanban/Lista, filtro de Status) ficavam a left:-282px e left:-198px,
     fora da área visível, sem jeito de rolar até eles.

     justify-content:flex-start (o padrão, por isso nem precisa declarar) +
     margin-left:auto no PRIMEIRO filho tem o mesmo efeito visual quando
     cabe tudo (empurra o bloco pra direita), mas quando excede, o overflow
     acontece do jeito NORMAL — cresce pela direita, scrollLeft 0 mostra o
     início, rolar revela o resto. */
  flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden;
  /* Sobrescreve o flex-end da base explicitamente — herdar não bastaria,
     CSS só troca o que é declarado de novo, mesmo com seletor mais
     específico. */
  justify-content: flex-start;
}
.pipeline-toolbar-rolar > *:first-child { margin-left: auto; }
.pipeline-toolbar-rolar > * { flex-shrink: 0; }
/* O <select> de filtro fica dentro do .pipeline-filtros-grupo, um neto da
   barra — flex-shrink:0 no filho direto (o <form>) não impede os netos de
   se espremerem entre si dentro dele. */
.pipeline-toolbar-rolar .pipeline-filtros-grupo > * { flex-shrink: 0; }
/* Os filtros vivem num <form> no meio da barra — HTML não aninha formulário —,
   então ele precisa se comportar como um grupo de itens, não como bloco. */
.pipeline-filtros-grupo { display: flex; align-items: center; gap: 8px; margin: 0; }
/* Painel ancorado pela DIREITA nesta barra. O padrão `left: 0` funcionava
   quando a barra começava na esquerda; com ela encostada na borda direita, o
   painel do último botão (IA, a ~1135px numa tela de 1280) somava 200px de
   largura e saía da tela. Ancorar à direita nunca vaza aqui, porque à esquerda
   sempre há a largura da barra inteira sobrando. */
.pipeline-toolbar .filter-panel { left: auto; right: 0; }

.view-switch-form { display: flex; gap: 2px; background: var(--surface-alt); border-radius: var(--radius-sm); padding: 3px; margin: 0; }
.view-switch-btn { width: 34px; height: 32px; border-radius: 6px; border: none; background: transparent; color: var(--ink-soft); cursor: pointer; display: flex; align-items: center; justify-content: center; }
/* Cor de "selecionado" configurável por tema — pedido de Rocélio em
   25/08/2026. Mesmo idioma visual das .badge-tag e dos .chip de temperatura:
   fundo suave com color-mix, texto na cor cheia. Nunca fundo sólido + texto
   branco, que exigiria calcular contraste para uma cor livre e teria um
   caminho de falha (cor clara com texto claro) que o color-mix não tem. */
.view-switch-btn.active {
  background: color-mix(in srgb, var(--toolbar-selecionado) 15%, var(--surface));
  color: var(--toolbar-selecionado);
}

.pipeline-links-ia-panel {
  background: color-mix(in srgb, var(--accent) 8%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--accent) 25%, var(--border));
  border-radius: var(--radius); padding: 14px 16px; margin-bottom: 16px;
}
.pipeline-links-ia-panel-text { margin: 0; font-size: 13px; color: var(--ink-soft); }

/* ---------- Pipeline: modal "Novo" ---------- */

.modal-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.4); z-index: 500; display: flex; align-items: center; justify-content: center; padding: 20px; }
.modal-box { background: var(--surface); border-radius: var(--radius); padding: 24px; width: 100%; max-width: 420px; max-height: 90vh; overflow-y: auto; }
.modal-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.modal-header h2 { margin: 0; font-size: 18px; }
.modal-close { background: none; border: none; font-size: 22px; line-height: 1; color: var(--ink-soft); cursor: pointer; }

/* ---------- Pipeline: visão Lista ---------- */

.pipeline-list-table th, .pipeline-list-table td { white-space: nowrap; }

/* ---------- Pipeline: seletor de colunas e ordenação da Lista ---------- */

/* .column-picker/.column-picker-panel (dropdown solto) saíram em
   28/08/2026 — a escolha de colunas mudou de dropdown pra aba do painel
   lateral (.painel-lateral, mais acima). .column-picker-item continua,
   é o item de checkbox dentro dessa aba. */
.column-picker-item { display: flex; align-items: center; gap: 8px; padding: 6px 4px; font-size: 13px; }

.sortable-col { cursor: pointer; user-select: none; }
.sort-arrow { font-size: 9px; margin-left: 2px; }

/* ---------- Pipeline: filtros ---------- */


.filter-dropdown { position: relative; }
.filter-panel {
  display: none; position: absolute; top: 40px; left: 0; background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius-sm); box-shadow: var(--shadow);
  padding: 10px; min-width: 200px; z-index: 50;
}
/* O item do painel deixou de ser só <label> com checkbox: o painel do Funil
   usa <a>, o do IA usa <button> e <span>. Zerar aparência de botão e de link
   aqui é o que mantém os quatro com o mesmo desenho. */
.filter-panel-item {
  display: flex; align-items: center; gap: 8px; padding: 6px 6px; font-size: 13px;
  cursor: pointer; width: 100%; text-align: left; border: none; background: none;
  color: var(--ink); text-decoration: none; border-radius: var(--radius-sm);
  font-family: inherit; font-weight: 400;
}
a.filter-panel-item:hover, button.filter-panel-item:hover { background: var(--surface-alt); }
/* Divide dois tipos de item no mesmo painel — filtro por checkbox acima,
   segmento salvo por link abaixo. Sem a separação, a lista parece uma só e o
   clique num salvo (que TROCA os filtros) surpreende. */
.filter-panel-secao {
  margin-top: 10px; padding-top: 8px; border-top: 1px solid var(--border);
  font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--ink-soft);
}
.filter-panel-item.ativo { background: var(--surface-alt); font-weight: 600; }
/* "Em breve" mostra onde a função vai morar sem prometer o que não existe. */
.filter-panel-item-disabled { color: var(--ink-soft); cursor: default; justify-content: space-between; }
.filter-panel-item-disabled:hover { background: none; }
/* O ponto colorido de temperatura veio dos chips que a barra tinha. Sem ele o
   painel viraria três palavras iguais, e quente/morno/frio é justamente a
   informação que se lê pela cor. */
.dot-temperatura { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; }
.dot-temperatura-quente { background: var(--error); }
.dot-temperatura-morno  { background: var(--warning); }
.dot-temperatura-frio   { background: var(--info); }
.filter-panel .btn { margin-top: 8px; }
/* Item de 47px caía para 31px zerando a margem que todo <label> herda da
   regra global de formulário. Sem isso, quatro segmentos já não cabiam nos
   145px e o quarto ficava atrás de scroll — sem barra visível no macOS, o
   painel simplesmente MENTIA sobre quantos existem.

   O teto subiu junto: 260px mostram oito itens inteiros. Rolar continua sendo
   o comportamento para lista grande (vendedores, tags), que é o que a classe
   sempre serviu — o que não pode é rolar com quatro. */
.filter-panel-item { margin-bottom: 0; }
.filter-panel-scroll { max-height: 260px; overflow-y: auto; }
/* Medido em 25/08/2026, no Chromium: `::-webkit-scrollbar` é IGNORADO quando
   `scrollbar-width` está declarado, e nem `scrollbar-width: auto` reserva
   largura — só `scrollbar-gutter: stable` (11px). E reservar o espaço ainda
   não garante barra VISÍVEL: no macOS ela é overlay e só pinta enquanto rola.

   Ou seja: não existe garantia por CSS de que a pessoa veja que a lista
   continua. Por isso o aviso do total é texto no painel (.filter-panel-nota),
   e não uma barra bonita. O gutter fica porque estabiliza a largura — sem ele
   a lista pula 11px quando o scroll aparece. */
.filter-panel-scroll { scrollbar-gutter: stable; scrollbar-color: var(--border) transparent; }
/* Diz quantos existem quando nem todos cabem. Sem isto, um painel com 15
   vendedores e 4 visíveis parece um painel com 4 vendedores — foi assim que
   4 segmentos viraram 3 sem ninguém notar. */
.filter-panel-nota {
  font-size: 11px; color: var(--ink-soft); padding: 2px 6px 6px;
  border-bottom: 1px solid var(--border); margin-bottom: 6px;
}


/* width: auto vence o `width: 100%` que todo select herda da regra global de
   formulário. Sem isso o seletor de período esticava pela largura inteira da
   página e caía numa linha só dele; agora acompanha o texto da opção mais
   longa ("Últimos 30 dias") e cabe na barra de ferramentas. */
.periodo-select { width: auto; padding: 5px 8px; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface); color: var(--ink); font-size: 12px; }

/* Barra de ferramentas e de filtros sem negrito, em todas as páginas. O .btn
   nasce em 600 — o mesmo peso das abas e dos títulos — então cada barra
   competia com a navegação principal da tela. Aba continua 600: ela é
   navegação (onde estou); a barra é ação (o que posso fazer daqui). */
.pipeline-toolbar .btn, .pipeline-toolbar button,
.tarefas-filtro-form .btn, .tarefas-filtro-form button,
.servico-select-form .btn, .servico-select-form button { font-weight: 400; }

/* ---- Mobile: filter panels as bottom sheets, tighter modal padding ----
   Kept here (not next to .filter-panel/.modal-box's own rules above)
   because a media-query override must appear AFTER its selector's
   unconditional base rule to win the cascade — moving these rules
   earlier in the file will silently break them again. ---- */
@media (max-width: 767px) {
  .filter-panel {
    position: fixed; top: auto; left: 0; right: 0; bottom: 0;
    border-radius: var(--radius) var(--radius) 0 0;
    max-height: 70vh; overflow-y: auto; min-width: 0; z-index: 210;
  }

  .modal-box { padding: 16px; }
}

.premissas-card { max-width: 480px; }
.form-actions { margin-top: 20px; }
.form-secondary-action { margin-top: 12px; }
.modal-box-wide { max-width: 640px; }
/* Modal "Enriquecer com IA" (26/08/2026): a tabela de sugestões (Campo /
   Informação atual / Dados encontrados / ação) ficava espremida nos 640px
   de .modal-box-wide, com o valor editado e o "fonte" quase colados na
   borda. Classe própria, não um ajuste em .modal-box-wide — os outros
   modais que já usam essa classe (Links IA, Segmentos Salvos) não têm
   tabela, não precisam do espaço extra. */
.modal-box-xl { max-width: 900px; }
/* Azul marinho + fonte um pouco maior, pedido de Rocélio, 30/08/2026 —
   vale para toda tela que usa esta classe (cadastro de Lead/Cliente E a
   barra lateral da ficha), "padrão de layout é do app, não da tela". */
.modal-section-title { margin: 16px 0 8px; font-size: 14px; font-weight: 600; color: var(--primary); text-transform: uppercase; letter-spacing: 0.03em; }
/* Linha fina antes de cada seção do cadastro de Lead (Contato, Localização,
   Classificação) — pedido de Rocélio, 30/08/2026. Modificador próprio, não
   a classe `.modal-section-title` inteira: essa classe também aparece na
   barra lateral da ficha do Lead (Tags, Dados da Empresa, Dados de
   Contato), que já tem seu próprio `<hr class="lead-sidebar-divisor">`
   entre seções — herdar a borda ali duplicaria a linha. */
.modal-section-title-divisor { padding-top: 16px; border-top: 1px solid var(--border); }
/* Fecha o popup de leitura da tela Links IA com um caminho de ação, quando
   há sugestão pendente — ver static/js/links_ia.js. Sem isto o popup era um
   beco sem saída: mostrava o que a IA achou e não levava a lugar nenhum. */
.modal-footer-acoes { margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--border); }
.select-com-adicionar { display: flex; gap: 8px; align-items: center; }
.select-com-adicionar select { flex: 1; }

/* ---------- Formulário de Lead: campos agrupados por linha (peça extra pós-19/08,
   layout compacto tipo Frappe em vez de 1 campo por linha) ---------- */
.lead-form-secao { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 0 20px; }
.lead-form-campo-fixo label { margin-top: 0; }
.lead-form-campo-largo { grid-column: 1 / -1; }
/* Campo reduzido ao tamanho do que ele guarda, não ao tamanho da coluna do
   grid inteira — CNPJ formatado tem 18 caracteres, Grupo/Apelido não
   precisam da largura padrão de 260px+. Pedido de Rocélio, 28/08/2026.
   `select` entrou em 30/08/2026 (Estado/País/Segmento/Funcionários etc.,
   antes só cobria `input`). */
.lead-form-campo-estreito input, .lead-form-campo-estreito select { max-width: 190px; }
.campo-erro-inline { display: block; font-size: 12px; color: var(--error); margin-top: 2px; min-height: 16px; }

/* Aniversário do contato é dia+mês, sem ano (não existe <input> nativo
   pra isso) — dois <select> lado a lado no lugar do texto livre.
   Correção de Rocélio, 30/08/2026: a primeira versão pedia mês/ano. */
.lead-form-aniversario-dia-mes { display: flex; gap: 8px; }
.lead-form-aniversario-dia-mes select { max-width: 90px; }

/* Até 3 contatos no cadastro do Lead — cada contato é UMA linha (nome,
   e-mail, celular, favorito lado a lado), não uma célula do grid padrão
   junto dos outros campos: 3 inputs empilhados numa coluna de 260px
   ficaria espremido demais. Pedido de Rocélio, 28/08/2026. */
.lead-form-contatos-cadastro { display: flex; flex-direction: column; gap: 14px; }
.lead-contato-cadastro-bloco { display: flex; gap: 16px; align-items: flex-end; flex-wrap: wrap; }
.lead-contato-cadastro-bloco .lead-form-campo { flex: 1 1 160px; min-width: 160px; margin: 0; }
.lead-contato-cadastro-bloco .lead-form-campo-estreito { flex: 0 0 auto; }
.lead-contato-favorito-label { display: flex; align-items: center; gap: 4px; font-size: 13px; white-space: nowrap; padding-bottom: 10px; cursor: pointer; }
.lead-form-container.layout-editando .lead-form-secao { grid-template-columns: 1fr; }

/* Segmento/Funcionários/Lead-gerado-por/Origem numa linha só — pedido de
   Rocélio, 30/08/2026. `.lead-form-campo-estreito` (max-width fixo, 190px)
   não serve aqui: o grid de `.lead-form-secao` só cabe 3 colunas de 260px+
   na largura da seção Classificação, então um 4º campo sempre quebraria
   linha mesmo com o input estreito. Aqui os 4 dividem a linha em partes
   iguais (`flex: 1`), reduzindo a largura de cada um o suficiente pra
   caber os 4 — "reduzindo um pouco a largura", não 190px fixos. */
.lead-form-classificacao-linha { grid-column: 1 / -1; display: flex; gap: 20px; }
.lead-form-classificacao-linha .lead-form-campo { flex: 1; min-width: 0; }
.lead-form-container.layout-editando .lead-form-classificacao-linha { display: block; }

/* Serviços (40% da largura) ao lado de Temperatura/Previsão/Motivo
   empilhados verticalmente — pedido de Rocélio, 30/08/2026. Wrapper fora
   do grid de `.lead-form-secao` (mesmo truque de `.lead-form-campo-largo`,
   `grid-column: 1 / -1`, pra ocupar a linha inteira) porque o grid trataria
   as duas colunas como uma célula só. */
.lead-form-servicos-linha { grid-column: 1 / -1; display: flex; gap: 20px; align-items: flex-start; }
.lead-form-servicos-coluna { flex: 0 0 40%; min-width: 0; }
.lead-form-servicos-coluna-lateral { flex: 1; min-width: 0; display: flex; flex-direction: column; }
/* No editor de layout o grid vira 1 coluna só (ver regra acima) — a linha
   de Serviços some com ele, senão o wrapper flex ficaria espremido junto
   com os campos arrastáveis. */
.lead-form-container.layout-editando .lead-form-servicos-linha { display: block; }

/* Checklist de Serviços com valor por item (22/09/2026) — substituiu o
   <select multiple>; mesma altura visual de antes (~5 itens visíveis),
   rolagem vertical se o catálogo crescer (mesmo padrão de .table-scroll). */
.lead-form-servicos-lista { max-height: 160px; overflow-y: auto; border: 1px solid var(--border); border-radius: 6px; padding: 6px 10px; background: var(--surface); }
.lead-form-servico-item { display: flex; align-items: center; gap: 10px; padding: 4px 0; }
.lead-form-servico-checkbox { display: flex; align-items: center; gap: 6px; font-size: 13px; font-weight: 400; flex: 1; min-width: 0; }
.lead-form-servico-checkbox input { width: auto; }
.lead-form-servico-valor-input { max-width: 110px; padding: 4px 8px; font-size: 13px; }
.lead-form-servico-valor-fixo { font-size: 12px; color: var(--ink-soft); white-space: nowrap; }
.lead-form-servicos-total { margin-top: 6px; font-size: 13px; color: var(--ink-soft); }

/* ---------- Editor de layout do formulário de Lead (fatia C1) ---------- */
.modal-header-actions { display: flex; align-items: center; gap: 8px; }
.btn-sm { padding: 4px 10px; font-size: 12px; }
.layout-editando-on { display: none; }
.lead-form-container.layout-editando .layout-editando-on { display: inline-flex; }
.lead-form-container.layout-editando .layout-editando-off { display: none; }

.lead-form-campo.campo-oculto { display: none; }
.campo-drag-handle { display: none; cursor: grab; color: var(--ink-soft); }
.campo-visibilidade-toggle { display: none; }

.lead-form-container.layout-editando .lead-form-campo {
  display: flex;
  align-items: center;
  gap: 10px;
  border: 1px dashed var(--border);
  border-radius: var(--radius-sm);
  padding: 6px 10px;
  margin: 6px 0;
  cursor: grab;
}
.lead-form-container.layout-editando .lead-form-campo label { margin: 0; flex: 1; }
.lead-form-container.layout-editando .lead-form-campo > input,
.lead-form-container.layout-editando .lead-form-campo > select,
.lead-form-container.layout-editando .lead-form-campo > textarea,
.lead-form-container.layout-editando .lead-form-campo > .select-com-adicionar { display: none; }
.lead-form-container.layout-editando .campo-drag-handle { display: inline-block; }
.lead-form-container.layout-editando .campo-visibilidade-toggle { display: inline-flex; align-items: center; gap: 4px; font-size: 12px; font-weight: 400; margin: 0; white-space: nowrap; }
.lead-form-container.layout-editando .lead-form-campo.campo-oculto { display: flex; opacity: 0.5; }
.lead-form-campo-ghost { opacity: 0.4; }

/* ---------- Campos customizados do formulário de Lead (fatia C2) ---------- */
.lead-form-add-campo { margin: 4px 0 14px; }

/* ---------- Tela de detalhe do Lead, só leitura (fatia E1a) ---------- */
/* .voltar-link (o "← Voltar" por extenso) foi removido em 23/08/2026: as quatro
   telas que o usavam passaram para .voltar-seta. Classe sem uso engana quem vier
   depois achando que ainda é o padrão. */
.kanban-card-empresa a:hover,
.pipeline-list-table td a:hover { text-decoration: underline; }

.detalhe-lead-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 16px; margin-bottom: 24px; }
.detalhe-lead-campo { display: flex; justify-content: space-between; gap: 12px; padding: 8px 0; border-bottom: 1px solid var(--border); }
.detalhe-lead-campo:last-child { border-bottom: none; }
.detalhe-lead-label { color: var(--ink-soft); font-size: 13px; }
.detalhe-lead-valor { font-weight: 600; text-align: right; }

.detalhe-lead-tab-nav { display: flex; gap: 20px; margin-bottom: 12px; flex-wrap: wrap; }
/* Sublinhado (02/09/2026, referência: print do Flowlu) — trocou a pílula
   preenchida por texto + traço embaixo. Sem fundo/borda de caixa: só a
   cor do texto e o traço na cor primária marcam a aba ativa, que também
   ganha negrito (aqui o peso É o sinal de estado — nada mais indica). */
/* padding-bottom + margin-bottom negativo: o traço de 2px da aba ativa
   precisa cair EM CIMA do border-bottom de 1px de .lead-header-linha2, não
   um pouco abaixo dele — senão viram duas linhas visíveis em vez de uma só
   com um trecho mais grosso/colorido sob a aba selecionada. Ajuste real,
   02/09/2026, depois de ver as duas linhas separadas em produção. */
.detalhe-lead-tab-btn { display: inline-flex; align-items: center; gap: 6px; padding: 2px 6px 6px; margin: 0 -6px -1px; border: none; border-bottom: 2px solid transparent; border-radius: 6px 6px 0 0; background: transparent; font-size: 13px; line-height: 1.4; font-weight: 500; cursor: default; color: var(--ink-soft); white-space: nowrap; transition: background-color 0.15s ease, color 0.15s ease; }
/* Fundo leve no hover (02/09/2026) — sem pílula preenchida (isso ficou pro
   estado ativo/traço), mas precisa de ALGUM feedback visual ao passar o
   mouse, senão a aba parece não-interativa. */
.detalhe-lead-tab-btn:not(.active):not(:disabled):hover { color: var(--primary); background: color-mix(in srgb, var(--primary) 8%, transparent); }
.detalhe-lead-tab-btn.active { color: var(--primary); font-weight: 700; border-bottom-color: var(--primary); }
.detalhe-lead-tab-btn:disabled { cursor: not-allowed; opacity: 0.5; }

/* Cabeçalho da ficha do Lead em duas linhas (02/09/2026, referência: print
   do Flowlu) — linha 1 é voltar+nome+temperatura à esquerda; linha 2 é só
   o menu de abas, à direita. Cada linha rola na horizontal se não couber
   (mesmo padrão de ".pipeline-toolbar"/".kanban-board"), independente uma
   da outra. Fase 1 só no Lead; Cliente ganha o mesmo tratamento numa fase
   futura.
   A linha divisória vive em .lead-header-linha2, não aqui — é nela que o
   traço da aba ativa (.detalhe-lead-tab-btn.active) precisa coincidir, pra
   virar uma linha só (ajuste 02/09/2026, ver essa regra abaixo). */
.lead-header-unico {
  display: flex; flex-direction: column; gap: 0px;
  padding: 4px 0 0; margin-bottom: 16px;
}
.lead-header-linha1 {
  display: flex; align-items: center; gap: 18px; flex-wrap: nowrap;
  /* scrollbar-width:none (não "thin") + ::-webkit-scrollbar abaixo — mesmo
     motivo do .lead-header-linha2-scroll: uma barra "fantasma" reserva
     altura de verdade no box model mesmo com o conteúdo cabendo com folga,
     e isso empurraria a linha 2 pra baixo. Escondida, mas ainda rolável. */
  overflow-x: auto; overflow-y: hidden; scrollbar-width: none; -ms-overflow-style: none;
  /* +4px alinha a seta de voltar com o "P" de "Pipeline" no topbar acima:
     .topbar tem 20px de padding-left, .content agora tem 16px (reduzido
     pela metade, ver .content acima) — sobra 4px de diferença.
     O ajuste fica NA LINHA INTEIRA (aqui), não na seta em si: um elemento
     com margem própria dentro de outro com overflow-x:auto tem essa margem
     cortada pela área rolável do PAI (não dá pra rolar pra uma posição
     negativa) — achado real, 02/09/2026, a seta sumiu de vez com o menu
     lateral recolhido. .lead-header-linha1 tem overflow-x:auto pros SEUS
     FILHOS, mas a margem dela própria é relativa a .lead-header-unico, que
     não tem overflow — por isso é segura aqui. */
  margin-left: 4px;
}
.lead-header-linha1::-webkit-scrollbar { display: none; }
/* A borda vive aqui (elemento sem overflow); a rolagem vive só no
   .lead-header-linha2-scroll de dentro. Ver comentário no template —
   juntar as duas no mesmo elemento faz a barra de rolagem (quando
   aparece) empurrar a borda pra baixo, quebrando a coincidência com o
   traço da aba ativa. */
.lead-header-linha2 { border-bottom: 1px solid var(--border); min-width: 0; }
/* A rolagem (overflow-x:auto) fica só aqui, separada da borda em
   .lead-header-linha2 — ver comentário no template. Barra de rolagem
   ESCONDIDA de propósito (scrollbar-width:none + ::-webkit-scrollbar),
   mas a rolagem em si continua funcionando via trackpad/touch/shift+wheel
   — mesmo padrão de faixas horizontais tipo carrossel. Achado real,
   02/09/2026: mesmo quando o conteúdo cabe com folga (as 8 abas somam
   bem menos que a largura disponível), o navegador ainda arredondava
   scrollWidth/clientWidth pra valores ligeiramente diferentes e desenhava
   uma barra "fantasma" — que de qualquer forma reserva altura de verdade
   no box model e empurra a borda de baixo, quebrando a coincidência com
   o traço da aba ativa. Escondida, o problema desaparece não importa a
   causa exata do arredondamento. */
.lead-header-linha2-scroll {
  display: flex; align-items: center; justify-content: flex-end; gap: 22px; flex-wrap: nowrap;
  overflow-x: auto; overflow-y: hidden; scrollbar-width: none; -ms-overflow-style: none;
}
.lead-header-linha2-scroll::-webkit-scrollbar { display: none; }

.lead-header-voltar {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: 50%; flex-shrink: 0;
  background: var(--surface-alt); color: var(--ink-soft);
  transition: background-color 0.15s ease, color 0.15s ease;
}
.lead-header-voltar:hover { background: color-mix(in srgb, var(--primary) 14%, var(--surface-alt)); color: var(--primary); }
.lead-header-voltar svg { width: 19px; height: 19px; }

.lead-header-nome { margin: 0; font-size: 18px; white-space: nowrap; flex-shrink: 0; }

.lead-header-funil-btn {
  font-size: 12px; font-weight: 600; padding: 5px 10px; border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--ink) 7%, var(--surface)); color: var(--ink-soft);
  border: none; appearance: none; -webkit-appearance: none; cursor: pointer;
  white-space: nowrap;
}

/* Sinaliza visualmente que o modo "Editar Layout" está ligado — mesmo
   comportamento que .lead-header-compacto.layout-editando já tinha (pedido
   de Rocélio, 31/08/2026), migrado pro novo nome da barra única. */
.lead-header-unico.layout-editando { background: color-mix(in srgb, var(--warning) 18%, var(--bg)); }

.detalhe-lead-timeline { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 12px; }
.detalhe-lead-timeline li { display: flex; flex-direction: column; gap: 2px; padding-bottom: 12px; border-bottom: 1px solid var(--border); }
.detalhe-lead-timeline li:last-child { border-bottom: none; padding-bottom: 0; }
.detalhe-lead-timeline span { font-size: 13px; color: var(--ink-soft); }

.texto-vazio { color: var(--ink-soft); font-size: 14px; }

/* Tabela de Contatos (Lead e Cliente) — pedido de Rocélio, 30/08/2026,
   trocando a lista solta por tabela (referência visual: Flowlu).
   Nome sem quebra: .data-table genérica não tem white-space:nowrap (tem
   tabela demais reaproveitando a classe pra arriscar aplicar global sem
   auditar todas — 24 telas usam), então esta tabela específica ganha
   nowrap só na coluna Nome, escopado por data-tabela-id. */
.contato-tabela-cargo { font-size: 12px; color: var(--ink-soft); }
table[data-tabela-id="contatos-lead"] td[data-coluna="nome"],
table[data-tabela-id="contatos-lead"] th[data-coluna="nome"],
table[data-tabela-id="contatos-cliente"] td[data-coluna="nome"],
table[data-tabela-id="contatos-cliente"] th[data-coluna="nome"] { white-space: nowrap; }

/* Tabela de Atividades (Lead) — mesma lógica: "Tipo"/"Usuário"/"Quando"
   são rótulos curtos, não podem quebrar; "Descrição" pode ter texto
   longo (nota/comentário), aí quebrar linha é o certo, não rolar. */
table[data-tabela-id="atividades-lead"] td[data-coluna="tipo"],
table[data-tabela-id="atividades-lead"] th[data-coluna="tipo"],
table[data-tabela-id="atividades-lead"] td[data-coluna="usuario"],
table[data-tabela-id="atividades-lead"] th[data-coluna="usuario"],
table[data-tabela-id="atividades-lead"] td[data-coluna="quando"],
table[data-tabela-id="atividades-lead"] th[data-coluna="quando"] { white-space: nowrap; }

/* ---------- Edição do Lead (fatia E1b) ---------- */
.lead-edit-actions { display: flex; gap: 10px; margin-top: 20px; }

.servico-select-form { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 20px; }
.servico-select-form select { min-width: 0; width: auto; max-width: 220px; }
.badge-alerta { background: color-mix(in srgb, var(--error) 15%, var(--surface)); color: var(--error); }

/* Nível de acesso na aba Visão Geral de Gestão de Acesso (12/09/2026) —
   compacto (E/L, uma letra) de propósito: com 17+ telas em coluna, o rótulo
   por extenso faria a tabela rolar demais pra ficar "limpa e fácil de ver",
   que foi o pedido. Sem acesso não ganha badge nenhum, só o "—" padrão de
   campo vazio (.texto-vazio) — a maioria das células é isso, e destacar só
   quem TEM acesso é o que faz a tabela inteira ser legível de relance. */
.badge-nivel-leitura { background: color-mix(in srgb, var(--info) 15%, var(--surface)); color: var(--info); }
.badge-nivel-edicao  { background: color-mix(in srgb, var(--success) 15%, var(--surface)); color: var(--success); }

/* ---------- Notas do Lead (fatia E2) ---------- */
.detalhe-lead-nota-form { display: flex; flex-direction: column; gap: 10px; margin-bottom: 20px; }
.detalhe-lead-nota-form textarea { width: 100%; padding: 10px 12px; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface); color: var(--ink); font-family: var(--font-body); font-size: 14px; resize: vertical; }
.detalhe-lead-nota-form .btn { align-self: flex-end; }
.detalhe-lead-nota-texto { margin: 0 0 4px; white-space: pre-wrap; }
/* Texto da nota do painel de Histórico de Contato do mesmo tamanho que a
   linha de autor/data (.detalhe-lead-timeline span, 13px) — pedido de
   Rocélio, 12/09/2026. Escopado em #contato-notas-lista, não a classe
   base: ela é compartilhada com Notas/Comentários/Ações do Lead, que não
   pediram a mudança. */
#contato-notas-lista .detalhe-lead-nota-texto { font-size: 13px; }
/* Itálico na linha autor/data — diferencia visualmente do texto da nota
   em cima, mesmo tamanho de fonte que ela agora (pedido de Rocélio,
   12/09/2026). */
#contato-notas-lista span { font-style: italic; }

/* ---------- Tarefas do Lead (fatia E3) ---------- */
/* Prazo e Responsável dividem uma linha — mesmo recurso de grid auto-fit já
   usado em .lead-form-secao: lado a lado quando cabem, empilhados quando não,
   sem media query. Desde 07/09/2026 vive só dentro do modal "Nova Tarefa"
   (a lista virou grade, ver §30 do reutilizável); classe solta, não mais
   escopada em .detalhe-lead-tarefa-form — essa classe saiu do CSS junto com
   o formulário sempre visível que ela vestia (órfã depois da barra +
   modal substituírem a lista simples). */
.tarefa-form-linha { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 0 16px; }

/* Esconde o autocomplete de vínculo do modal de Tarefa quando ele abre de
   dentro de uma ficha (Lead/Cliente/futuro Projeto) — 08/09/2026, fatia do
   componente reutilizável. A entidade já é conhecida ali; mostrar a busca
   seria oferecer trocar pra um vínculo diferente do que a tela mostra. Ver
   abrirModalTarefa(tarefaId, entidadeFixa) em tarefas.js. */
.tarefa-form-vinculo-fixo #tarefa-form-vinculo-busca,
.tarefa-form-vinculo-fixo label[for="tarefa-form-vinculo-busca"] {
  display: none;
}

/* ---------- Comentários do Lead (fatia E4) ---------- */
.detalhe-lead-comentario-form { display: flex; flex-direction: column; gap: 10px; margin-bottom: 20px; }
.detalhe-lead-comentario-form textarea { width: 100%; padding: 10px 12px; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface); color: var(--ink); font-family: var(--font-body); font-size: 14px; resize: vertical; }
.detalhe-lead-comentario-form .btn { align-self: flex-end; }
/* Nota e Comentário fundidos na mesma tela (30/08/2026): mesmo textarea,
   dois botões (Salvar Nota / Comentar) lado a lado via `formaction`. */
.detalhe-lead-comentario-acoes { display: flex; gap: 8px; align-self: flex-end; }
.detalhe-lead-comentario-resposta-form { display: flex; flex-direction: column; gap: 8px; margin-top: 8px; }
.detalhe-lead-comentario-resposta-form textarea { width: 100%; padding: 8px 10px; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface); color: var(--ink); font-family: var(--font-body); font-size: 13px; resize: vertical; }
.detalhe-lead-comentario-resposta-form .btn { align-self: flex-end; }
.detalhe-lead-comentario-respostas { margin: 10px 0 0 20px; padding-left: 16px; border-left: 2px solid var(--border); }

/* ---------- Anexos do Lead (fatia E5) ---------- */
.detalhe-lead-anexo-form { display: flex; align-items: center; gap: 10px; margin-bottom: 20px; flex-wrap: wrap; }
.detalhe-lead-timeline li.detalhe-lead-anexo-item { flex-direction: row; align-items: flex-start; gap: 12px; }
.detalhe-lead-anexo-preview { flex-shrink: 0; display: flex; }
.detalhe-lead-anexo-thumb { width: 48px; height: 48px; object-fit: cover; border-radius: var(--radius-sm); border: 1px solid var(--border); }
.detalhe-lead-anexo-icone { width: 40px; height: 40px; color: var(--ink-soft); }
.detalhe-lead-anexo-info { display: flex; flex-direction: column; gap: 2px; }
.detalhe-lead-anexo-excluir-form { margin-top: 4px; }

/* ---------- Calendário (fatia Cal-1a) — variáveis do FullCalendar remapeadas pros tokens do app ---------- */
#calendario-app {
  /* Linha bem mais suave que a --border geral: no calendário ela desenha TODA
     célula, e com o contraste que a borda ganhou em 25/08 o mês inteiro
     passou a parecer planilha. Aqui a grade é orientação, não moldura. */
  --fc-border-color: color-mix(in srgb, var(--border) 45%, var(--surface));
  --fc-page-bg-color: var(--surface);
  --fc-neutral-bg-color: var(--surface-alt);
  --fc-neutral-text-color: var(--ink-soft);
  --fc-today-bg-color: color-mix(in srgb, var(--primary) 12%, var(--surface));
  --fc-button-text-color: #fff;
  --fc-button-bg-color: var(--primary);
  --fc-button-border-color: var(--primary);
  --fc-button-hover-bg-color: color-mix(in srgb, var(--primary) 85%, black);
  --fc-button-hover-border-color: color-mix(in srgb, var(--primary) 85%, black);
  --fc-button-active-bg-color: color-mix(in srgb, var(--primary) 70%, black);
  --fc-button-active-border-color: color-mix(in srgb, var(--primary) 70%, black);
  --fc-event-bg-color: var(--primary);
  --fc-event-border-color: var(--primary);
  --fc-event-text-color: #fff;
  --fc-list-event-hover-bg-color: var(--surface-alt);
  --fc-highlight-color: color-mix(in srgb, var(--primary) 15%, transparent);
  font-family: var(--font-body);
}
#calendario-app .fc-toolbar-title { font-family: var(--font-display); color: var(--ink); }

@media (max-width: 767px) {
  #calendario-app .fc-toolbar { flex-wrap: wrap; row-gap: 10px; }
  #calendario-app .fc-toolbar-title { font-size: 1.1em; }
}

/* ---------- Calendário (fatia Cal-1b) — popover de item, form do modal de Evento ---------- */
.calendario-popover {
  position: absolute;
  z-index: 600;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow);
  padding: 14px 16px;
  min-width: 220px;
  max-width: 280px;
  font-size: 14px;
}
.calendario-popover-horario { color: var(--ink-soft); font-size: 13px; margin-top: 4px; }
.calendario-popover-lead { color: var(--ink-soft); font-size: 13px; margin-top: 2px; }
.calendario-popover-acoes { display: flex; gap: 8px; margin-top: 12px; }

/* Badge de Tipo clicável na aba Ações (05/09/2026) — o <button> em volta
   não tem estilo próprio de botão (sem borda, sem fundo, sem padding); o
   badge_tag/badge-neutro de dentro já carrega toda a aparência visual, o
   botão só existe pra virar alvo de clique com cursor certo. */
.badge-tipo-clicavel {
  background: none; border: none; padding: 0; cursor: pointer; font: inherit;
}

/* Popover de cor — reaproveita .calendario-popover (posicionamento) com um
   modificador só pro layout interno (grade de amostras, não texto). Some o
   min-width de 220px do popover base: uma linha de amostras de 28px não
   precisa dessa largura, e min-width > max-width forçaria a largura maior
   mesmo com max-width declarado aqui. */
.popover-cor-tipo {
  display: flex; flex-wrap: wrap; gap: 6px; padding: 8px;
  min-width: 0; max-width: 180px; z-index: 999;
}

/* Renomeada de .calendario-toast em 25/08/2026: o aviso não é do Calendário,
   é do app. A classe antiga foi apagada em vez de virar alias — classe órfã
   engana quem vier depois achando que ainda é o padrão. */
.toast-erro {
  position: fixed;
  top: 20px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 700;
  padding: 12px 20px;
  border-radius: var(--radius-sm);
  font-size: 14px;
  background: color-mix(in srgb, var(--error) 15%, var(--surface));
  color: var(--error);
  border: 1px solid color-mix(in srgb, var(--error) 35%, transparent);
  box-shadow: var(--shadow);
}

/* Central de Alertas (12/09/2026, static/js/alertas_toast.js) — toast
   informativo (não erro, por isso não reaproveita .toast-erro), canto
   inferior direito, estilo Teams/Slack. Empilha do mais novo pro mais
   velho de baixo pra cima (column-reverse: o próximo toast entra por
   cima, empurrando os anteriores pra cima, igual mensageiro de
   verdade). Reutilizável: qualquer tipo de alerta futuro usa a mesma
   classe, só muda o texto. */
#toasts-alerta-container {
  position: fixed; bottom: 20px; right: 20px; z-index: 900;
  display: flex; flex-direction: column-reverse; gap: 10px;
  pointer-events: none; max-width: calc(100vw - 40px);
}
.toast-alerta {
  /* Fundo e texto próprios (Configurações > Aparência > Central de
     Alertas), não --surface/--ink — pedido de Rocélio, 12/09/2026: dá pra
     diferenciar o toast do resto dos cards sem mudar o tema inteiro. */
  background: var(--notificacao-bg); color: var(--notificacao-ink); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow); padding: 12px 16px;
  font-size: 13px; max-width: 320px;
  opacity: 0; transform: translateY(12px);
  transition: opacity 0.3s ease, transform 0.3s ease;
  pointer-events: auto;
}
.toast-alerta-visivel { opacity: 1; transform: translateY(0); }
/* Saída (12/09/2026, pedido de Rocélio: "deve subir e desaparecer
   suavemente") — continua subindo em vez de voltar pro translateY(12px)
   de origem, que lia como "afundar" de volta ao entrar em vez de flutuar
   pra cima e sumir. */
.toast-alerta-saindo { opacity: 0; transform: translateY(-12px); }

#form-evento label { display: block; margin-top: 14px; margin-bottom: 4px; font-size: 13px; color: var(--ink-soft); }
#form-evento input, #form-evento textarea, #form-evento select {
  width: 100%; padding: 10px 12px; border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface); color: var(--ink); font-size: 14px;
}
.modal-evento-acoes { display: flex; justify-content: space-between; gap: 8px; margin-top: 20px; }

/* ---------- Tarefas (fatia Tarefas-A) ---------- */
.tarefas-filtro-form { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 16px; }
.tarefas-filtro-form select {
  padding: 8px 10px; border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface); color: var(--ink); font-size: 13px;
}
.badge-prioridade-baixa  { background: color-mix(in srgb, var(--info) 15%, var(--surface));    color: var(--info); }
.badge-prioridade-normal { background: var(--surface-alt); color: var(--ink-soft); }
.badge-prioridade-alta   { background: color-mix(in srgb, var(--error) 15%, var(--surface));   color: var(--error); }

/* ---------- Gráficos de Tarefas ---------- */
.grafico-resumo-cards { display: flex; gap: 16px; margin-bottom: 20px; }
.grafico-resumo-card { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 20px; }
.grafico-resumo-numero { font-size: 32px; font-weight: 700; font-family: var(--font-display); }
.grafico-barras-card { margin-bottom: 20px; }
.grafico-barras-card h2 { margin-top: 0; margin-bottom: 16px; font-size: 16px; }
.grafico-barra-linha { display: flex; align-items: center; gap: 12px; margin-bottom: 10px; }
.grafico-barra-label { width: 140px; flex-shrink: 0; font-size: 13px; color: var(--ink-soft); }
.grafico-barra-trilho { flex: 1; height: 10px; background: var(--surface-alt); border-radius: 999px; overflow: hidden; }
.grafico-barra-preenchimento { height: 100%; border-radius: 999px; }
.grafico-barra-valor { width: 30px; text-align: right; font-size: 13px; font-variant-numeric: tabular-nums; }

/* ---------- Minhas Tarefas (fatia Tarefas-B) ---------- */
.minhas-tarefas-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
.minhas-tarefas-bloco-largo { grid-column: span 3; }
.minhas-tarefas-bloco h2 { margin-top: 0; font-size: 15px; }
.minhas-tarefas-bloco h3 { font-size: 12px; text-transform: uppercase; letter-spacing: .04em; color: var(--ink-soft); margin: 14px 0 6px; }
.minhas-tarefas-lista { list-style: none; padding: 0; margin: 0; }
.minhas-tarefas-lista li { padding: 8px 0; border-bottom: 1px solid var(--border); font-size: 13px; display: flex; align-items: center; gap: 8px; }
.minhas-tarefas-lista li:last-child { border-bottom: none; }
.minhas-tarefas-item-meta { margin-left: auto; color: var(--ink-soft); font-size: 12px; }
.minhas-tarefas-agenda-conectar { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; }
.minhas-tarefas-tabs { display: flex; gap: 4px; margin-bottom: 12px; background: var(--surface-alt); border-radius: var(--radius-sm); padding: 3px; width: fit-content; }
.minhas-tarefas-tab { padding: 6px 14px; border: none; background: none; border-radius: var(--radius-sm); cursor: pointer; font-size: 13px; color: var(--ink-soft); }
.minhas-tarefas-tab.active { background: var(--surface); color: var(--ink); box-shadow: var(--shadow); font-weight: 600; }

@media (max-width: 1023px) {
  .minhas-tarefas-grid { grid-template-columns: 1fr; }
  .minhas-tarefas-bloco-largo { grid-column: span 1; }
}

/* ---- Tela de Lead — layout Frappe (toolbar, abas, lateral) ---- */
/* margin-top zerada: com a seta de voltar agora dentro desta mesma linha, o
   título encosta no respiro do .content em vez de acumular três espaçamentos
   (padding do content + linha do voltar + margem própria). */
.lead-header-compacto { display: flex; align-items: center; gap: 12px; margin: 0 0 16px; flex-wrap: wrap; padding: 6px 10px; border-radius: var(--radius-sm); transition: background-color 0.15s; }
.lead-header-compacto h1 { margin: 0; font-size: 22px; }
/* Sinaliza visualmente que o modo "Editar Layout" está ligado — pedido de
   Rocélio, 31/08/2026. Classe ligada por JS em alternarEdicaoLayoutLeadForm
   (static/js/pipeline.js), não só CSS: .lead-header-compacto é irmão de
   .lead-pagina.layout-editando, não filho, então um seletor descendente não
   alcançaria daqui. */
.lead-header-compacto.layout-editando { background: color-mix(in srgb, var(--warning) 18%, var(--bg)); }
.voltar-seta {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; flex-shrink: 0;
  border-radius: 50%; color: var(--ink-soft); font-size: 18px; line-height: 1;
}
.voltar-seta:hover { background: var(--surface-alt); color: var(--ink); text-decoration: none; }
/* Seta em tela sem título para acompanhar (ex. Novo Lead): fica sozinha e
   precisa do respiro que a linha de título daria. */
.voltar-seta-sozinha { margin-bottom: 10px; }
/* Agrupa seta + h1 dentro de um .page-header, que é space-between — sem este
   agrupamento a seta iria para uma ponta e o título para a outra. */
.titulo-com-voltar { display: flex; align-items: center; gap: 8px; }
.titulo-com-voltar h1 { margin: 0; }
.lead-header-funil { color: var(--ink-soft); font-size: 14px; }

.lead-toolbar { display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 16px; padding-bottom: 12px; border-bottom: 1px solid var(--border); }
.lead-toolbar-abas { display: flex; gap: 8px; flex-wrap: wrap; }
/* gap 6px e não 8px: com os selects na mesma linha, a barra pedia 1122px e a
   coluna de conteúdo tem no máximo ~1116px — o "Tornar Cliente" quebrava para
   a linha de baixo por 6px. Apertar o respiro entre os itens devolve 10px e
   preserva as larguras pedidas para Funil e Estágio, que é o que foi
   especificado. Alargar a janela não resolveria: o conteúdo tem largura máxima
   e o espaço disponível não cresce depois de ~1116px. */
.lead-toolbar-acoes { display: flex; align-items: center; margin-bottom: 12px; }
/* "+ Adicionar card" (16/09/2026) precisa ficar FORA do grupo que rola
   horizontalmente — ele é um wrapper próprio, .lead-toolbar-acoes-fim,
   empurrado com margin-left:auto contra o CONTAINER de fora. Achado
   real: quando "+ Adicionar card" vivia direto dentro de
   .lead-toolbar-acoes (que tem overflow-x:auto), margin-left:auto o
   empurrava pro fim do CONTEÚDO ROLÁVEL inteiro — em barras longas
   (Funil+Estágio+Temperatura+botões) ele saía da área visível sem
   nenhum indício de que precisava rolar pra chegar lá; o clique
   funcionava (confirmado via toggleFilterPanel direto), só não tinha
   como alcançá-lo. min-width:0 é o que permite este item ENCOLHER
   dentro do flex de fora — sem isso o container externo tentaria
   caber o conteúdo inteiro e o botão fixo saía da tela de outro jeito. */
.lead-toolbar-acoes-scroll { display: flex; gap: 6px; align-items: center; min-width: 0; }

/* Sub-barra visivelmente menor que a barra de abas. As duas vinham quase no
   mesmo peso — 14px/600 nas abas contra 13px nas ações — e diferença de 1px
   não se lê como hierarquia: as duas competiam pela mesma atenção. Abas são
   navegação (onde estou), ações são secundárias (o que posso fazer daqui).

   O peso importa mais que o tamanho: .btn nasce com font-weight 600, o mesmo
   das abas, então mesmo menor a linha continuava disputando atenção com o menu
   principal. Sem negrito ela lê como secundária de imediato — inclusive o
   "Tornar Cliente", que segue destacado pelo fundo cheio, não pelo peso. */
.lead-toolbar-acoes .btn { padding: 5px 10px; font-size: 12px; font-weight: 400; }
.lead-toolbar-acoes .ai-pill-btn { padding: 5px 12px; font-size: 12px; font-weight: 400; }
.lead-toolbar-acoes .ai-pill-btn svg { width: 12px; height: 12px; }
.lead-toolbar-acoes select { padding: 5px 8px; font-size: 12px; font-weight: 400; }

/* ---------- Barra nunca quebra em duas linhas (regra do projeto) ----------
   Barra de ação, de abas ou de filtro é sempre UMA barra. Quando não cabe, ela
   rola na horizontal — mesmo padrão de .table-scroll e .kanban-board, já usados
   aqui — em vez de virar duas linhas e empurrar o conteúdo para baixo.

   flex-shrink: 0 nos filhos é o que faz a barra de fato transbordar e rolar;
   sem isso os itens se espremem até ficarem ilegíveis antes de qualquer scroll
   aparecer, e o select mostraria "Contabilidade Digi...".

   Não vale para lista de conteúdo — .tags-lista, .kanban-card-tags e afins
   continuam quebrando, que ali é o comportamento certo.

   DE FORA, e não por esquecimento: .pipeline-toolbar tem painéis suspensos
   position:absolute dentro dela (#column-picker-panel na visão lista, os
   .filter-panel de Segmento, Temperatura, Vendedor, Tag, Funil, Criado em e
   IA). overflow cria contexto de recorte, então o painel sumiria ao abrir.
   Para ela a regra só vale depois que o painel for renderizado fora da barra —
   trabalho maior, registrado como pendência. (.pipeline-filters, citada aqui
   antes, deixou de existir em 25/08: virou parte da faixa única.) */
.lead-toolbar-acoes-scroll,
.lead-toolbar-abas,
.detalhe-lead-tab-nav,
.tarefas-filtro-form,
.servico-select-form {
  flex-wrap: nowrap;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: thin;
}
.lead-toolbar-acoes-scroll > *,
.lead-toolbar-abas > *,
.detalhe-lead-tab-nav > *,
.tarefas-filtro-form > *,
.servico-select-form > * { flex-shrink: 0; }
/* Funil e Estágio na mesma linha dos botões. O <form> já era item flex da
   toolbar, mas por dentro não tinha regra nenhuma e continuava bloco — então os
   dois <select> viravam block-level, ocupavam a largura toda do form e
   empilhavam. Bastava o form virar flex também.
   Classe reaproveitada em 16/09/2026: tinha ficado órfã numa refatoração
   anterior (o HTML do Funil/Estágio passou a usar .lead-header-funil-form,
   sem nenhuma destas regras, voltando a empilhar) — voltou a ser usada aqui.
   As larguras fixas que existiam antes (168px/196px, calculadas só pro texto
   "Comercial"/"Proposta enviada") saíram: os selects ganharam o prefixo
   "Funil: "/"Estágio: " no mesmo commit, que não cabia mais nelas. Mesma
   lógica já documentada abaixo pro .select-como-btn — texto da opção
   marcada varia, então width:auto deixa o <select> acompanhar sozinho. */
.lead-toolbar-reclassificar { display: flex; gap: 6px; align-items: center; }
.lead-toolbar-reclassificar select[name="funil_id"],
.lead-toolbar-reclassificar select[name="estagio_id"] { width: auto; }
/* Funil/Estágio continuam <select> funcionais, mas parecem os mesmos botões
   da barra de filtros do Pipeline (.btn.btn-outline) — pedido de Rocélio,
   31/08/2026. Mesma técnica do .badge-temperatura-select: appearance:none
   tira a seta/borda nativas, cor/fundo vêm de .btn-outline já aplicada no
   HTML junto com esta classe. */
.select-como-btn { appearance: none; -webkit-appearance: none; }
/* Sem regra própria de fundo/borda aqui de propósito — o select de
   temperatura carrega `badge badge-temperatura-{{ lead.temperatura }}
   badge-temperatura-select` no HTML, que já resolve cor/fundo/formato.
   Achado por Rocélio, 31/08/2026: uma regra antiga aqui (`background:
   var(--surface)`) tinha a mesma especificidade de `.badge-temperatura-*`
   e vencia por vir depois no arquivo — o texto ficava colorido, o fundo
   sempre branco. `.lead-toolbar-acoes select` (abaixo) ainda cuida do
   tamanho, sem conflitar com fundo/cor. */

/* Botões de Editar/Salvar/Cancelar Layout na toolbar. O CSS já existente
   esconde .layout-editando-on por padrão em qualquer lugar da página e só
   mostra dentro de .lead-form-container.layout-editando — as regras
   abaixo estendem o mesmo comportamento pro .lead-pagina, que a toolbar
   usa (JS alterna a classe layout-editando nos dois elementos juntos). */
.lead-pagina.layout-editando .layout-editando-on { display: inline-flex; }
.lead-pagina.layout-editando .layout-editando-off { display: none; }

.lead-layout { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: 20px; align-items: start; max-width: 1536px; }
@media (max-width: 1023px) {
  .lead-layout { grid-template-columns: 1fr; }
}

.lead-sidebar { position: sticky; top: 16px; }

/* Resumo de Atividades da barra lateral (02/09/2026) — recolhível, mesmo
   padrão (classList.toggle + localStorage) do recolher da sidebar
   principal (toggleSidebarCollapse em main.js). */
.lead-sidebar-atividade-cabecalho { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.lead-sidebar-atividade-lista { font-size: 11px; }
.lead-sidebar-atividade-lista li { padding-bottom: 10px; }
.lead-sidebar-atividade-lista strong { font-size: 11px; }
.lead-sidebar-atividade-lista span { display: block; color: var(--ink-soft); font-size: 11px; }

.lead-layout-sidebar-recolhida { grid-template-columns: minmax(0, 1fr) 0px !important; }
.lead-layout-sidebar-recolhida .lead-sidebar { display: none; }

/* Botão de reabrir a sidebar — fora de .lead-sidebar de propósito (ver
   comentário no template): sem ele, recolher uma vez não tinha volta.
   position:absolute pra não disputar espaço na grid quando a segunda
   coluna encolhe pra 0px. */
.lead-sidebar-expandir-btn {
  display: none; position: absolute; top: 16px; right: 0;
  align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: 50%;
  background: var(--surface-alt); color: var(--ink-soft); border: 1px solid var(--border);
  cursor: pointer; transition: background-color 0.15s ease, color 0.15s ease;
}
.lead-sidebar-expandir-btn:hover { background: color-mix(in srgb, var(--primary) 14%, var(--surface-alt)); color: var(--primary); }
.lead-sidebar-expandir-btn svg { width: 16px; height: 16px; }
.lead-layout-sidebar-recolhida .lead-sidebar-expandir-btn { display: flex; }
.lead-sidebar-campo { display: flex; flex-direction: column; gap: 2px; padding: 8px 0; border-bottom: 1px solid var(--border); }
.lead-sidebar-campo:last-child { border-bottom: none; }
.lead-sidebar-label { color: var(--ink-soft); font-size: 12px; }
.lead-sidebar-valor { cursor: pointer; font-weight: 600; padding: 2px 4px; border-radius: 4px; }
/* Sem negrito na barra lateral: ela é leitura gerencial de varredura rápida, e
   com todo valor em 600 nada se destaca — o peso deixa de ser hierarquia e vira
   ruído. Escopado em .lead-sidebar-campo de propósito: a mesma classe serve as
   células da tabela de Serviços, onde o valor em negrito ainda é o que se quer
   enxergar primeiro. */
.lead-sidebar-campo .lead-sidebar-valor { font-weight: 400; }
/* Site cortado com reticências na barra: URL longa quebrava em duas linhas e
   estourava a leitura de relance. O corte é por largura do campo, não por
   contagem de caracteres — acompanha a coluna quando ela muda de tamanho, e
   nunca corta cedo demais numa URL curta. O valor completo continua no DOM,
   então o editor inline recebe a URL inteira; a versão integral fica na aba
   "Dados da Empresa". */
.lead-sidebar-campo[data-campo="site"] .lead-sidebar-valor {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.lead-sidebar-valor:hover { background: var(--surface-alt); }
/* Campo sem dado fica em branco de propósito — antes dizia "Adicionar...", que
   fazia campo vazio parecer campo preenchido. Sem texto, porém, o span mediria
   uns 8px e viraria um alvo de clique impossível de acertar, deixando o campo
   editável só na teoria. Daí a área reservada: invisível parada, revelada pelo
   :hover acima, que agora é o único sinal de que dá pra clicar ali. */
.lead-sidebar-valor:empty { display: inline-block; min-width: 80px; min-height: 1.4em; }
.lead-sidebar-input { width: 100%; padding: 4px 6px; border-radius: 4px; border: 1px solid var(--primary); font-size: 14px; }
/* box-sizing: border-box é o que falta para width:100% realmente caber DENTRO
   da coluna fixa acima — sem isso, padding+borda somam por cima do 100% e o
   campo estoura a célula por alguns pixels mesmo com a coluna travada. */
/* table-layout: fixed é o que faz a largura da coluna IGNORAR o conteúdo —
   com o padrão (auto), o <colgroup> abaixo é só sugestão, e um <input> sem
   `size` ainda pode forçar a coluna a crescer pelo min-content dele. Fixed
   trava nas larguras do colgroup e ponto, seja texto estático ou campo aberto.
   Contrapartida aceita: texto muito longo trunca em vez de esticar a coluna —
   não é o caso aqui (nome de serviço, valor e comentário curto). */
.lead-servicos-tabela { table-layout: fixed; }
.lead-servicos-tabela .lead-sidebar-input { box-sizing: border-box; }
.lead-sidebar-erro { color: var(--error); font-size: 12px; margin-top: 2px; }
.lead-sidebar-divisor { border: none; border-top: 1px solid var(--border); margin: 16px 0; }

.lead-servicos-total { text-align: right; margin-top: 12px; font-size: 15px; }

/* Página de acesso restrito (templates/acesso/sem_acesso.html).
   Resolve: dar ao usuário barrado uma tela que explica o motivo em vez de um
   erro cru. Armadilha que evita: sem um destino próprio, o before_request
   redirecionaria para o Dashboard — que pode ser justamente a tela negada,
   fechando um laço de redirecionamento. */
.sem-acesso-card { max-width: 560px; }
.sem-acesso-detalhe { color: var(--ink-soft); font-size: 14px; margin-top: 8px; }

/* Modo somente-leitura de uma tela (nível "Leitura" do Perfil de Acesso).
   Resolve: o servidor já recusa a gravação, mas sem isto a tela seguiria
   oferecendo "Salvar" e "Novo" — interface que promete o que vai negar.

   Escondido aqui em vez de um `{% if pode_editar %}` em volta de cada botão:
   são ~100 botões em 34 templates, e bastaria esquecer um para a tela voltar a
   mentir — pior, toda tela nova nasceria mentindo por padrão. Assim a regra
   vale por construção, inclusive para o que ainda não existe.

   Não é segurança, e não pretende ser: quem abrir o DevTools revela o botão. A
   recusa de verdade está no before_request de app.py, que roda no servidor.

   Duas famílias, e cada uma cobre o que a outra não alcança:
   1. Botão dentro de formulário POST — toda gravação direta. Nenhum filtro do
      app usa POST, então não há falso positivo.
   2. [data-acao-edicao] — os botões que só ABREM um formulário (modais, edição
      inline). Ficam fora de qualquer form, então a regra 1 não os pega. */
.somente-leitura form[method="POST"] button,
.somente-leitura form[method="POST"] input[type="submit"],
.somente-leitura [data-acao-edicao] { display: none !important; }

/* Edição inline em modo leitura: o valor CONTINUA visível, só deixa de ser
   clicável. Aqui `display: none` seria o remédio errado — esconderia o dado,
   e não a ação. Quem tem Leitura tem direito de ler.
   O cursor volta ao padrão porque mão apontando prometendo clique é a mesma
   mentira que o botão de Salvar que não salva. */
.somente-leitura [data-acao-edicao-inline] { pointer-events: none; cursor: default; }

/* Aviso de que o Pipeline mudou além do que o polling consegue aplicar sozinho
   (Lead que entrou de outro funil, estágio que este quadro não mostra).
   Clicável, porque a ação óbvia é recarregar. Reaproveita .toast-erro em vez
   de criar um segundo estilo de aviso flutuante. */
.kanban-aviso-mudanca { cursor: pointer; }

/* O nome do funil mora DENTRO do botão "Funil: <nome>". Segue as duas regras
   duras do projeto: `nowrap`+`ellipsis`+`min-width: 0` para nunca quebrar em
   duas linhas, e `flex-shrink: 0` para não ser espremido pelos irmãos. O
   `data-ajuda` mostra o nome inteiro no hover se for cortado. */
.pipeline-funil-btn {
  flex-shrink: 0; min-width: 0; max-width: 220px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: block;
}


/* Nome da tela na barra do topo (templates/base.html, bloco titulo_pagina).
   Resolve: o título morava dentro de cada tela, num .page-header que custava
   45px de altura em todas elas. Trazê-lo para o shell devolve essa faixa ao
   conteúdo e garante que toda tela tenha cabeçalho igual — regra dura do
   projeto: padrão de layout é do app, não da tela.

   Armadilha que evita: sem `min-width: 0` o `text-overflow` NÃO funciona em
   filho de flex, porque o padrão é `auto` e ele se recusa a encolher abaixo do
   conteúdo. Sem `flex-shrink: 0` num nome longo, o título espremeria a busca
   antes de reticenciar a si mesmo. */
.topbar-titulo {
  margin: 0;
  font-size: 17px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
  max-width: 320px;
}

/* O cabeçalho que sobrou nas telas guarda só as ações e a barra da tela — o
   título saiu. Vira uma linha de ferramentas, não um bloco de identidade. */
.page-header { margin-bottom: 10px; }

/* Tela Configurações > Aparência. */
.aparencia-card { max-width: 620px; margin-bottom: 16px; }
.aparencia-favicon-linha { display: flex; align-items: center; gap: 12px; }
/* Tamanho fixo com `object-fit: contain`: favicon enviado pode vir em qualquer
   proporção, e sem isso um retangular esticaria a linha inteira do formulário. */
.aparencia-favicon-atual {
  width: 32px; height: 32px; object-fit: contain; flex-shrink: 0;
  border-radius: 6px; background: var(--surface-alt);
}
.aparencia-dica { color: var(--ink-soft); font-size: 12px; margin: 4px 0 0; }

/* Marca no topo do menu: favicon + nome do sistema, ambos cadastrados em
   Configurações > Aparência. Antes o nome era texto fixo no template.
   `flex-shrink: 0` no ícone para o nome longo reticenciar em vez de espremer a
   imagem, e `min-width: 0` no nome porque sem ele o text-overflow não age em
   filho de flex (a mesma armadilha do título da barra do topo). */
.brand { display: flex; align-items: center; gap: 8px; min-width: 0; }
.brand-icone { width: 26px; height: 26px; object-fit: contain; flex-shrink: 0; border-radius: 4px; }
.brand-nome { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Campo de cor livre (templates/_componentes/campo_cor_livre.html).
   Resolve: cadastrar a cor do TEMA, único lugar onde a escolha livre é o ponto.
   Armadilha que evita: `id` fixo — são doze campos na mesma tela, e o JS liga
   por `data-cor-livre`, então duas instâncias nunca colidem. */
.campo-cor-livre { margin-bottom: 12px; }
.campo-cor-livre-linha { display: flex; align-items: center; gap: 8px; }
/* O seletor nativo traz padding próprio em cada navegador; zerar e dar tamanho
   fixo é o que faz a amostra ficar igual no Chrome, Safari e Firefox. */
.campo-cor-livre-amostra {
  width: 34px; height: 34px; padding: 0; border: 1px solid var(--border);
  border-radius: var(--radius-sm); background: none; cursor: pointer; flex-shrink: 0;
}
.campo-cor-livre-texto { width: 110px; font-family: var(--font-mono, monospace); text-transform: uppercase; }

/* Botão "favoritar" (★) e a fileira de favoritas do campo de cor livre
   (08/09/2026) — ver templates/_componentes/campo_cor_livre.html e
   modules/cores_favoritas.py. Mesma altura do input de texto ao lado
   (36px, herdado do padrão de botão pequeno do sistema) pra não quebrar
   o alinhamento da linha. */
.campo-cor-livre-favoritar {
  width: 36px; height: 36px; flex-shrink: 0; border-radius: var(--radius-sm);
  border: 1px solid var(--border); background: var(--surface); color: var(--ink-soft);
  cursor: pointer; font-size: 16px; line-height: 1; display: flex; align-items: center; justify-content: center;
}
.campo-cor-livre-favoritar:hover { color: #F5A623; border-color: #F5A623; }

/* Só ocupa espaço quando tem alguma favorita — lista vazia (usuário
   novo) não deve deixar um respiro em branco embaixo do campo. */
.campo-cor-livre-favoritas { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.campo-cor-livre-favoritas:empty { display: none; }
.campo-cor-livre-favorita {
  width: 20px; height: 20px; border-radius: 4px; border: 1px solid var(--border);
  padding: 0; cursor: pointer; flex-shrink: 0;
}
.campo-cor-livre-favorita:hover { transform: scale(1.15); }

/* Tela de Temas (Configurações > Aparência). */
.aparencia-card-larga { max-width: 100%; }
.aparencia-grupo { font-size: 14px; margin: 18px 0 4px; }
/* auto-fit com minmax: seis campos numa tela larga, dois numa estreita, sem
   media query. `minmax(0, ...)` e não `1fr` — o padrão `auto` deixa o campo
   estourar a coluna quando o rótulo é longo. */
.aparencia-grade-cores { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 4px 16px; }
.tema-amostras { display: inline-flex; gap: 3px; }
.tema-amostra { width: 18px; height: 18px; border-radius: 4px; border: 1px solid var(--border); display: inline-block; }
.tema-estrela { background: none; border: none; cursor: pointer; font-size: 18px; line-height: 1; color: var(--ink-soft); padding: 0; }
.tema-estrela-ativa { color: var(--warning); cursor: default; }


/* Calendário sem moldura: a grade fica só nas linhas horizontais, que é o que
   separa semana de semana. As verticais e a borda externa saem — elas não
   informam nada e eram o que dava o aspecto de planilha.
   O contêiner ganha a mesma sombra suave dos demais. */
.fc .fc-scrollgrid { border: none; box-shadow: var(--shadow-suave); border-radius: var(--radius); overflow: hidden; }
.fc .fc-scrollgrid td, .fc .fc-scrollgrid th { border-left: none; border-right: none; }
.fc .fc-scrollgrid-section > td { border: none; }

/* Painel do usuário — na base da sidebar desde 02/09/2026 (era na barra do
   topo). Mesmo mecanismo dos suspensos de notificação e tema — ligado por
   `data-painel`, alternado por `alternarPainelSuspenso`. */
.user-chip { cursor: pointer; border-radius: var(--radius-sm); padding: 8px 6px; width: 100%; }
/* Mesmo tom de hover que .menu-item usa — o chip mora entre os itens de
   menu agora, não mais na barra clara do topo (era --surface-alt). */
.user-chip:hover { background: color-mix(in srgb, var(--sidebar-ink) 8%, transparent); }
.user-panel {
  display: none; position: absolute; left: 0; bottom: calc(100% + 10px);
  min-width: 240px; background: var(--surface); border-radius: var(--radius);
  box-shadow: var(--shadow); padding: 14px; z-index: 60;
}
.user-panel.open { display: block; }
.user-panel-cabecalho { display: flex; align-items: center; gap: 10px; padding-bottom: 12px; }
.user-avatar-grande { width: 40px; height: 40px; font-size: 15px; }
/* min-width: 0 obrigatório em filho de flex, senão o text-overflow do nome
   não age e o painel estica para caber o nome inteiro. */
.user-panel-identidade { display: flex; flex-direction: column; min-width: 0; }
.user-panel-nome { font-weight: 600; font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.user-panel-login { font-size: 12px; color: var(--ink-soft); }
.user-panel-perfil { font-size: 11px; color: var(--ink-soft); margin-top: 2px; }
.user-panel-acao {
  display: block; padding: 8px 10px; border-radius: var(--radius-sm);
  font-size: 13px; color: var(--ink); text-decoration: none; cursor: pointer;
}
.user-panel-acao:hover { background: var(--surface-alt); color: var(--primary); }
/* O Sair fica separado do resto por um respiro e pela cor: é a única ação do
   painel que encerra a sessão, e não deve ser vizinha visual de uma
   preferência. */
.user-panel-sair { margin-top: 6px; border-top: 1px solid var(--border); padding-top: 12px; color: var(--error); }
.user-panel-sair:hover { background: color-mix(in srgb, var(--error) 10%, transparent); color: var(--error); }

/* ---------- Componente: abas de ficha (30/08/2026) ----------
   Nasceu na ficha do Lead/Cliente (onclick inline por tela); extraído
   aqui na 3ª ocorrência (Integrações) — CLAUDE.md do projeto já define
   isso como o sinal de que virou dívida. */
.abas-ficha-barra { display: flex; gap: 4px; border-bottom: 1px solid var(--border); margin-bottom: 16px; flex-wrap: nowrap; overflow-x: auto; }
.abas-ficha-btn { padding: 8px 14px; border: none; background: transparent; color: var(--ink-soft); cursor: pointer; border-bottom: 2px solid transparent; white-space: nowrap; flex-shrink: 0; }
.abas-ficha-btn.active { color: var(--primary); border-bottom-color: var(--primary); font-weight: 600; }

/* ---------- Módulo de Integrações (30/08/2026) ---------- */
.integracoes-lista { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 16px; }
.integracoes-card { display: block; text-decoration: none; color: inherit; }
.integracoes-card-topo { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; }
.integracoes-card-tipo { font-size: 12px; color: var(--ink-soft); text-transform: uppercase; letter-spacing: 0.03em; }
.integracoes-card-nome { font-weight: 600; }

/* Cabeçalho de seção (ícone + título + subtítulo) — ver
   templates/_componentes/cabecalho_secao.html. Nasceu na ficha de
   Integrações, 3 ocorrências na mesma tela. */
.secao-cabecalho { display: flex; align-items: flex-start; gap: 12px; margin-bottom: 20px; }
.secao-cabecalho-icone {
  width: 40px; height: 40px; border-radius: var(--radius-sm); flex-shrink: 0;
  background: color-mix(in srgb, var(--primary) 12%, var(--surface));
  color: var(--primary); display: flex; align-items: center; justify-content: center;
}
.secao-cabecalho-icone svg { width: 20px; height: 20px; }
.secao-cabecalho h3 { margin: 0; font-size: 16px; }
.secao-cabecalho p { margin: 2px 0 0; font-size: 13px; color: var(--ink-soft); }

/* Painel lateral de contexto (status, ajuda, log) ao lado de um formulário
   — reaproveita a proporção de .lead-layout (conteúdo + 320px), mas sem
   nenhum comportamento de edição inline do Lead. */
.painel-info-lateral h4 { margin: 0 0 12px; font-size: 11px; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-soft); }
.painel-info-lateral .campo-info { margin-bottom: 10px; }
.painel-info-lateral .campo-info-rotulo { display: block; font-size: 12px; color: var(--ink-soft); margin-bottom: 2px; }
.campo-ajuda { display: block; font-size: 12px; color: var(--ink-soft); margin-top: 4px; }
.campo-opcional-tag { font-weight: 400; color: var(--ink-soft); font-size: 12px; }

/* Badge/filtro "Importante" da página Ações (04/09/2026) — mesma cor de
   .badge-temperatura-quente (var(--error)), reaproveitada porque é o
   token vermelho já estabelecido no app, não uma cor nova. Dois
   contextos usam a mesma classe base: o CHIP de filtro na barra de
   ferramentas (estado ativo/inativo) e o BADGE fixo no item marcado
   (sempre "ativo" visualmente).

   `.badge` na frente é necessário, não estético: dentro da timeline de
   Ações, `.detalhe-lead-timeline span { color: var(--ink-soft) }` tem
   especificidade elemento+classe (0,1,1), que empata ou vence uma regra
   de classe só (0,1,0) mesmo vindo depois no arquivo — achado ao vivo,
   04/09/2026, o badge saía cinza em vez de vermelho até qualificar com
   `.badge` (0,2,0). */
.badge.badge-acao-importante {
  background: var(--surface); color: var(--ink-soft); border: 1px solid var(--border);
  cursor: pointer; font-family: inherit;
}
.badge.badge-acao-importante-ativa {
  background: color-mix(in srgb, var(--error) 15%, var(--surface));
  color: var(--error); border-color: transparent; cursor: default;
}
/* O chip de FILTRO (clicável, na barra) usa a mesma classe -ativa
   quando ligado, mas precisa continuar com cursor:pointer — a regra
   acima desliga o cursor pensando no badge fixo do item (não
   clicável). Sobrescreve só o cursor pro filtro, que é um <button>. */
#acoes-filtro-importante.badge-acao-importante-ativa { cursor: pointer; }

/* Toggle "Importante" dentro da modal — mesma cor, mas como
   checkbox-label (padrão já usado no projeto pra opções binárias em
   formulário), o texto acompanha a cor quando marcado. */
#acao-modal-importante:checked ~ #acao-modal-importante-rotulo {
  color: var(--error); font-weight: 700;
}

/* Os dois <select> da barra de ferramentas de Ações usam `.select-como-btn`
   (05/09/2026) — mesma técnica de .badge-temperatura-select: appearance:none
   tira a seta/borda nativas do <select>, e a cor/fundo vêm de .btn.btn-outline
   já aplicada junto no HTML, pra ele parecer um botão sutil igual ao filtro
   "Vendedor" do Pipeline, sem o texto "Todos" (o próprio rótulo do filtro já
   deixa implícito que nada marcado = todos). Antes usava `.periodo-select` +
   "Tipo: Todos"/"Criado por: Todos" — sem NENHUMA classe compacta, herdava
   `width: 100%` e padding de campo de formulário cheio (style.css:285),
   ficando largo e alto demais na barra (achado por Rocélio em produção,
   04/09/2026, corrigido primeiro com .periodo-select antes deste refinamento
   trocar pelo visual de botão).

   `.select-como-btn` sozinha NÃO basta pra largura — ela só tira a aparência
   nativa (achado por Rocélio, 05/09/2026: "Tipo" ficou extremamente largo de
   novo, mesmo bug do width:100% global por um caminho diferente). Os outros
   dois usos existentes da classe (Funil/Estágio de `.lead-toolbar-reclassificar`,
   algumas linhas abaixo) tinham ficado órfãos numa refatoração e, quando
   voltaram a ser usados em 16/09/2026, saíram do `width` fixo em pixel que
   tinham antes — o texto ganhou o prefixo "Funil: "/"Estágio: " no mesmo
   commit, que não cabia mais no pixel calculado pro texto antigo. Nenhum
   desses filtros tem um texto fixo pra medir (a opção marcada muda), então
   em vez de chutar um pixel, todos pedem width:auto — deixa o <select>
   nativo se ajustar ao texto da opção MARCADA no momento, exatamente como
   um <button> normal já faz.

   Na CLASSE, não nos ids (07/09/2026): a regra nasceu escopada a
   `#acoes-filtro-tipo, #acoes-filtro-criado-por` e a barra de Tarefas
   (`#tarefas-lead-filtro-responsavel`/`-status`, mesma classe
   `.select-como-btn`) ficou de fora sem ninguém perceber — larga demais,
   igual ao bug original, só que por um consumidor novo da mesma classe
   que "esqueceu" de entrar na lista. Um componente por classe não deveria
   exigir que cada tela nova também edite uma lista de ids central; a
   regra virou `.select-como-btn` direto, e qualquer `<select>` futuro que
   usar a classe já nasce certo, sem precisar lembrar deste comentário. */
.select-como-btn { width: auto; }
/* Linha Tipo + Data lado a lado na modal de Ações (05/09/2026) — Tipo ocupa
   uma fatia menor (flex-basis 35%, ~30% menor que uma divisão 50/50) e Data
   ocupa o resto, no lugar de cada um numa linha inteira própria. */
.acao-modal-linha-tipo-data { display: flex; gap: 12px; }
.acao-modal-campo-tipo { flex: 0 0 35%; min-width: 0; }
.acao-modal-campo-data { flex: 1; min-width: 0; }
.acao-modal-campo-tipo select, .acao-modal-campo-data input { width: 100%; }

/* Histórico de edição, dentro do modal (06/09/2026) — saiu da listagem
   principal (onde empilhava e virava ilegível) pra viver só aqui, que já
   é o lugar de "ver o que isto dizia antes". */
.acao-modal-historico {
  margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border);
  display: flex; flex-direction: column; gap: 8px;
}
.acao-modal-historico-item { font-size: 12px; color: var(--ink-soft); display: flex; flex-direction: column; gap: 2px; }
.acao-modal-historico-item strong { color: var(--ink); font-weight: 600; }

/* Cabeçalho de cada item da timeline de Ações: badge de Tipo e os quatro
   ícones de ação (Importante/Editar/Responder/Excluir), numa linha só —
   troca os botões cheios "Marcar Importante"/"Editar"/"Responder"/
   "Excluir" que ficavam espalhados em linhas próprias (pedido de Rocélio,
   05/09/2026: "fica mais sutil"). */
.detalhe-lead-acao-cabecalho { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
/* Autor+data de ocorrência: linha própria, alinhada à direita, depois do
   texto da ação e antes da linha divisória pro próximo item (pedido de
   Rocélio, 05/09/2026 — ficava no cabeçalho, junto do badge, e disputava
   espaço com os ícones). */
.detalhe-lead-acao-meta {
  text-align: right; color: var(--ink-soft); font-size: 13px; margin-top: 4px;
}
.detalhe-lead-acao-icones { display: flex; gap: 6px; flex-shrink: 0; }
.detalhe-lead-acao-icones form { display: inline-flex; }
/* Estado ativo do ícone de Importante — cor própria, não reaproveita
   .badge-acao-importante-ativa: aquela classe é pensada pro formato de
   badge (pill, padding largo) e entraria em conflito com o tamanho fixo
   28x28 de .btn-icone-suave. */
.btn-icone-suave.icone-importante-ativo {
  background: color-mix(in srgb, var(--error) 15%, var(--surface));
  color: var(--error);
}

/* ---------- Mapa de Dependências (07/09/2026) ---------- */
.mapa-aviso {
  background: color-mix(in srgb, var(--primary) 8%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--primary) 25%, transparent);
  border-radius: var(--radius-sm);
  padding: 10px 14px;
  font-size: 13px;
  color: var(--ink-soft);
  margin-bottom: 16px;
}
.mapa-controles { display: flex; justify-content: space-between; align-items: center; gap: 16px; margin-bottom: 12px; flex-wrap: wrap; }
.mapa-filtros { display: flex; gap: 16px; font-size: 13px; color: var(--ink-soft); }
.mapa-filtro-separado { padding-left: 16px; border-left: 1px solid var(--border, #ddd); }
.mapa-filtros label { display: flex; align-items: center; gap: 6px; cursor: pointer; }
.mapa-busca { padding: 6px 10px; border: 1px solid var(--border, #ddd); border-radius: var(--radius-sm); min-width: 220px; }
.mapa-area { display: flex; gap: 16px; }
.mapa-grafo-container { position: relative; flex: 1; height: 68vh; min-height: 420px; border: 1px solid var(--border, #ddd); border-radius: var(--radius-sm); overflow: hidden; background: var(--surface); }
.mapa-svg { width: 100%; height: 100%; touch-action: none; cursor: grab; }
.mapa-carregando { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: var(--ink-soft); font-size: 13px; }
.mapa-aresta { stroke: var(--ink-soft); stroke-opacity: 0.35; stroke-width: 1.2; transition: opacity .15s ease; }
.mapa-aresta-dimmed { opacity: .12; }
.mapa-no { cursor: pointer; }
/* Rótulo escondido por padrão (07/09/2026) — com ~200 nós o texto de todo
   mundo ligado ao mesmo tempo virava sopa de letrinhas. Só aparece no
   hover, com zoom suficiente (.mapa-no-rotulo-visivel, calculado em
   mapa.js a partir de pan.escala), em destaque de busca, ou no nó
   selecionado — nesses casos sempre dá pra saber o nome sem precisar
   caçar na lista lateral. */
.mapa-no-rotulo {
  font-size: 11px;
  fill: var(--ink, #1a1a1a);
  paint-order: stroke;
  stroke: var(--surface);
  stroke-width: 3px;
  opacity: 0;
  transition: opacity .12s ease;
  pointer-events: none;
}
.mapa-no:hover .mapa-no-rotulo,
.mapa-no.mapa-no-rotulo-visivel .mapa-no-rotulo,
.mapa-no.mapa-no-realce .mapa-no-rotulo,
.mapa-no.mapa-no-selecionado .mapa-no-rotulo {
  opacity: 1;
}
.mapa-no-realce circle { stroke: #ffb020; stroke-width: 3px; }
.mapa-no-selecionado circle { stroke: var(--primary); stroke-width: 3px; }
/* Clicar num nó "foca" nele — o resto do grafo esmaece (mas continua no
   lugar, só apagado), deixando visível o selecionado e seus vizinhos
   diretos. Clicar no fundo do grafo limpa o foco (ver limparFoco() em
   mapa.js). */
.mapa-no-dimmed { opacity: .18; transition: opacity .15s ease; }
.mapa-no-dimmed:hover { opacity: .6; }
.mapa-painel {
  width: 280px; flex-shrink: 0; border: 1px solid var(--border, #ddd); border-radius: var(--radius-sm);
  padding: 16px; position: relative; background: var(--surface);
}
.mapa-painel-fechar { position: absolute; top: 8px; right: 10px; border: none; background: none; font-size: 18px; cursor: pointer; color: var(--ink-soft); }
.mapa-painel-nome { font-weight: 600; margin: 4px 0 2px; word-break: break-word; }
.mapa-painel-arquivo { font-size: 12px; color: var(--ink-soft); margin: 0 0 12px; word-break: break-all; }
.mapa-painel-conexoes { list-style: none; margin: 8px 0 0; padding: 0; font-size: 13px; max-height: 40vh; overflow-y: auto; }
.mapa-painel-conexoes li { padding: 3px 0; border-bottom: 1px solid color-mix(in srgb, var(--ink-soft) 12%, transparent); }


/* ---------- Notas (07/09/2026) ---------- */
/* Cores de fundo/texto do cartão são o hex livre que a pessoa escolheu ao
   criar a nota — vêm inline via JS (style.background/color), nunca fixas
   aqui. O que este bloco estiliza é a moldura, o quadro e os controles ao
   redor, que sim seguem o tema claro/escuro do app normalmente. */

.notas-toolbar {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 16px;
}

.notas-busca {
  flex: 1 1 240px;
  min-width: 180px;
  padding: 8px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--ink);
}

.notas-view-toggle,
.notas-escopo-toggle {
  display: inline-flex;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
}

.notas-view-btn,
.notas-escopo-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 12px;
  background: var(--surface);
  color: var(--ink-soft);
  border: none;
  border-right: 1px solid var(--border);
  cursor: pointer;
  font-size: 13px;
}

.notas-view-btn:last-child,
.notas-escopo-btn:last-child {
  border-right: none;
}

.notas-view-btn.ativo,
.notas-escopo-btn.ativo {
  background: var(--primary);
  color: #fff;
}

.notas-aviso-leitura {
  background: var(--surface-alt);
  color: var(--ink-soft);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 8px 12px;
  font-size: 13px;
  margin-bottom: 16px;
}

.notas-vazio {
  color: var(--ink-soft);
  text-align: center;
  padding: 60px 20px;
}

/* Quadro livre do modo Cartão. Altura generosa e position:relative — os
   cartões são position:absolute dentro dele, coordenada vem do banco
   (pos_x/pos_y) ou, sem posição própria (grade automática de "Todas as
   notas"), calculada em notas.js. */
.notas-board {
  position: relative;
  min-height: 70vh;
  background: var(--surface-alt);
  border: 1px dashed var(--border);
  border-radius: var(--radius);
  overflow: auto;
}

.nota-card {
  position: absolute;
  width: 190px;
  min-height: 130px;
  padding: 12px 14px;
  border-radius: var(--radius-sm);
  box-shadow: 0 2px 6px rgba(0, 0, 0, .18);
  cursor: grab;
  display: flex;
  flex-direction: column;
  gap: 6px;
  touch-action: none;
  user-select: none;
}

.nota-card:active {
  cursor: grabbing;
}

.nota-card-somente-leitura {
  cursor: default;
  opacity: .92;
}

.nota-card-titulo {
  font-size: 14px;
  line-height: 1.3;
  word-break: break-word;
}

.nota-card-texto {
  font-size: 12px;
  line-height: 1.4;
  white-space: pre-wrap;
  word-break: break-word;
  opacity: .9;
  overflow: hidden;
  max-height: 4.2em;
}

.nota-card-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: auto;
}

.nota-tag {
  font-size: 10px;
  padding: 2px 7px;
  border-radius: 999px;
  background: rgba(0, 0, 0, .12);
}

.nota-card-autor,
.nota-card-rodape {
  font-size: 10px;
  opacity: .75;
}

.notas-fab {
  position: fixed;
  right: 32px;
  bottom: 32px;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: var(--primary);
  color: #fff;
  border: none;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 4px 12px rgba(0, 0, 0, .28);
  cursor: pointer;
  z-index: 40;
}

.notas-lista-container {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}

.nota-lixeira-swatch {
  display: inline-block;
  width: 16px;
  height: 16px;
  border-radius: 4px;
  border: 1px solid var(--border);
}

.nota-form-linha {
  display: flex;
  gap: 16px;
  align-items: flex-end;
}

.nota-form-linha > div {
  display: flex;
  flex-direction: column;
}

.nota-form-tags-campo {
  flex: 1;
}

#nota-form-cor {
  width: 48px;
  height: 36px;
  padding: 2px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  cursor: pointer;
}

/* Cards da Visão Geral do Lead (13/09/2026) — ver
   docs/superpowers/plans/2026-09-13-visao-geral-motor-de-cards.md e
   templates/_componentes/visao_geral_cards.html. Vivem dentro de
   .grid-stack-item-content (Gridstack.js), então preenchem 100% da
   altura/largura que o grid deu ao card. */
/* O CSS vendorizado do Gridstack aplica overflow-x:hidden nesse
   wrapper — sem isto o menu de config (mais largo que uma coluna de
   card) fica cortado ao abrir. O scroll vertical do conteúdo continua
   funcionando: quem rola é .visao-geral-card-corpo, não este wrapper. */
#visao-geral-grid .grid-stack-item-content { overflow: visible; }
/* O grid vive dentro do .card branco da aba (mesmo --surface do card de
   cada widget) — sem um fundo próprio, mais claro, os cards brancos
   não se destacam do próprio contêiner branco. */
#visao-geral-grid { background: var(--bg); border-radius: var(--radius); padding: 8px; }
.visao-geral-card {
  display: flex; flex-direction: column; height: 100%; padding: 14px 16px;
  background: var(--surface); border-radius: 12px; box-shadow: var(--shadow-suave);
  border-left: 3px solid transparent;
}
/* Faixa de cor por tipo — só identificação visual, sem carga semântica
   (não é status/alerta), por isso reaproveita os tokens de marca já
   existentes em vez de inventar hex novo. */
.visao-geral-card--tarefas         { border-left-color: var(--info); }
.visao-geral-card--atividades      { border-left-color: var(--secondary); }
.visao-geral-card--acoes           { border-left-color: var(--accent); }
.visao-geral-card--contatos        { border-left-color: var(--success); }
.visao-geral-card--servicos_valor  { border-left-color: var(--primary); }
.visao-geral-card--anexos          { border-left-color: var(--warning); }
/* email/mensagens (16/09/2026): sem cor de marca própria de propósito —
   são cards sem fonte de dado ainda (integração não existe), a faixa
   neutra sinaliza isso mesmo antes de abrir o card. */
.visao-geral-card--email           { border-left-color: var(--ink-soft); }
.visao-geral-card--mensagens       { border-left-color: var(--ink-soft); }
.visao-geral-card-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; flex-shrink: 0; position: relative; }
.visao-geral-card-titulo { font-size: 14px; font-weight: 600; margin: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
/* Some por padrão, só aparece no hover do card OU enquanto o próprio menu
   de config está aberto (senão sumiria debaixo do dedo em touch, sem
   hover real). */
.visao-geral-card-config-btn {
  opacity: 0; flex-shrink: 0; width: 24px; height: 24px; border: none; background: transparent;
  color: var(--ink-soft); cursor: pointer; border-radius: var(--radius-sm); font-size: 16px; line-height: 1;
  transition: opacity 0.1s ease, background-color 0.15s ease;
}
.grid-stack-item-content:hover .visao-geral-card-config-btn,
.visao-geral-card-config-btn.aberto { opacity: 1; }
.visao-geral-card-config-btn:hover { background: var(--surface-alt); }
.visao-geral-card-config-menu {
  display: none; position: absolute; top: 32px; right: 8px; z-index: 20;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-sm);
  box-shadow: var(--shadow); min-width: 160px; padding: 4px;
}
.visao-geral-card-config-menu.aberto { display: block; }
.visao-geral-card-config-item {
  display: block; width: 100%; text-align: left; padding: 7px 10px; border: none; background: none;
  border-radius: var(--radius-sm); cursor: pointer; font-size: 13px; color: var(--ink);
}
.visao-geral-card-config-item:hover { background: var(--surface-alt); }
.visao-geral-card-config-item.ativo { color: var(--primary); font-weight: 600; }
.visao-geral-card-config-separador { height: 1px; background: var(--border); margin: 4px 0; }
.visao-geral-card-corpo { flex: 1; overflow-y: auto; min-height: 0; }
.visao-geral-card-lista { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.visao-geral-card-item { display: flex; flex-direction: column; gap: 2px; padding-bottom: 8px; border-bottom: 1px solid var(--border); }
.visao-geral-card-item:last-child { border-bottom: none; padding-bottom: 0; }
.visao-geral-card-item-titulo { font-size: 13px; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.visao-geral-card-item-meta { font-size: 12px; color: var(--ink-soft); display: flex; align-items: center; gap: 6px; }
.visao-geral-card-rodape { display: block; margin-top: 10px; padding-top: 8px; border-top: 1px solid var(--border); font-size: 12px; font-weight: 600; color: var(--primary); text-decoration: none; flex-shrink: 0; }
.visao-geral-card-rodape:hover { text-decoration: underline; }
.visao-geral-card-servicos-total { font-size: 13px; font-weight: 600; margin: 8px 0 0; padding-top: 8px; border-top: 1px solid var(--border); }
/* "+ Adicionar card" entrou na mesma linha da barra de ação (16/09/2026,
   antes tinha linha própria com .visao-geral-toolbar, removida — único
   uso da classe). margin-left:auto empurra só este item pro fim da
   linha, sem precisar de wrapper/flex extra pros outros. */
.lead-toolbar-acoes-fim { margin-left: auto; }
/* ---------- Dashboard de vendas (outubro/2026) ----------
   Gráficos em CSS puro, sem biblioteca. Toda cor vem de token (--seq-*, --success,
   --error, --ink*, --surface*), então os dois temas funcionam sem regra própria:
   as escalas --seq-* não mudam no tema escuro e contrastam com --surface nos dois.
   O que pode quebrar linha aqui é lista de conteúdo; barra de filtro e título nunca. */

/* Campos De/Até dentro do painel de Período (o resto da barra é a `.pipeline-toolbar` do Pipeline). */
.dash-campo { display: flex; flex-direction: column; gap: 3px; font-size: 11px; color: var(--ink-soft); }
.dash-campo input {
  font: inherit; font-size: 13px; padding: 5px 8px; min-height: 30px; color: var(--ink);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-sm);
}
.dash-periodo-datas { display: flex; gap: 8px; padding: 0 12px 10px; }
.dash-periodo-datas .dash-campo { flex: 1; min-width: 0; }
.dash-periodo-datas input[type="date"] { width: 100%; }
.dash-periodo-datas + .btn { margin: 0 12px 10px; width: calc(100% - 24px); }
/* O ícone gira enquanto a requisição está em andamento. */
.dash-atualizar.girando svg { animation: dash-girar 0.8s linear infinite; }
@keyframes dash-girar { to { transform: rotate(360deg); } }

.dash-legenda { margin: 0 2px 14px; font-size: 12px; color: var(--ink-soft); }
.dash-aviso { color: var(--warning); }

.kpi-grid { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
@media (max-width: 640px) { .kpi-grid { gap: 12px; } .kpi-grid .stat-tile { padding: 14px 14px; } }
.kpi-tile { min-width: 0; text-decoration: none; color: inherit; }
.kpi-tile--link:hover { box-shadow: var(--shadow); }
.kpi-rotulo, .kpi-dica, .kpi-valor { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.kpi-linha { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.kpi-valor { flex-shrink: 1; }
.kpi-dica { font-size: 11px; color: var(--ink-soft); }
.kpi-tendencia { display: inline-flex; align-items: center; gap: 2px; flex-shrink: 0; font-size: 12px; font-weight: 700; color: var(--ink-soft); }
.kpi-tendencia svg { width: 14px; height: 14px; }
.kpi-tendencia--bom { color: var(--success); }
.kpi-tendencia--ruim { color: var(--error); }

.dash-grade { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr)); gap: 16px; align-items: start; }
.dash-grade > * { min-width: 0; }
.dash-nota { margin: 4px 0 0; font-size: 12px; color: var(--ink-soft); }
.dash-nota-destaque { color: var(--warning); margin: 0 0 10px; }
.dash-vazio-card { margin: 0; padding: 14px 0; font-size: 13px; color: var(--ink-soft); }
.dash-contagem { display: inline-block; margin-left: 6px; padding: 1px 8px; border-radius: 999px; font-size: 12px; background: color-mix(in srgb, var(--ink) 8%, var(--surface)); color: var(--ink-soft); }

/* Barras horizontais genéricas (macro barras_horizontais) e o funil, que reaproveita
   o trilho. --barra-cor é o único ponto de cor. */
.barras-h { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 9px; }
.barras-h-linha { display: grid; grid-template-columns: minmax(80px, 38%) 1fr auto; align-items: center; gap: 10px; font-size: 13px; }
.barras-h-nome { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.barras-h-trilho { display: block; height: 10px; border-radius: 999px; background: color-mix(in srgb, var(--ink) 8%, var(--surface)); overflow: hidden; }
.barras-h-preenchimento { display: block; height: 100%; min-width: 2px; border-radius: 999px; background: var(--barra-cor, var(--seq-azul-4)); }
.barras-h-valor { font-weight: 700; font-variant-numeric: tabular-nums; }

.dash-funil { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.dash-funil-linha { display: grid; grid-template-columns: minmax(90px, 200px) 1fr auto; align-items: center; gap: 12px; font-size: 13px; --barra-cor: var(--seq-azul-4); }
.dash-funil-linha--ganho { --barra-cor: var(--success); }
.dash-funil-linha--perdido { --barra-cor: var(--error); }
.dash-funil-nome { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; font-weight: 600; }
.dash-funil-valor { white-space: nowrap; color: var(--ink-soft); font-variant-numeric: tabular-nums; }
.dash-funil-valor strong { color: var(--ink); }
.dash-funil-conversao { padding-left: 2px; font-size: 11px; font-weight: 700; color: var(--ink-soft); }

.dash-evol-legenda { display: flex; gap: 14px; margin-bottom: 8px; font-size: 12px; color: var(--ink-soft); }
.dash-chip::before { content: ""; display: inline-block; width: 10px; height: 10px; margin-right: 6px; border-radius: 3px; vertical-align: -1px; background: var(--seq-azul-4); }
.dash-chip--ganhos::before { background: var(--success); }
.dash-evol { display: flex; align-items: stretch; gap: 4px; height: 210px; }
.dash-evol-col { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; }
.dash-evol-barras { flex: 1; display: flex; align-items: flex-end; justify-content: center; gap: 2px; border-bottom: 1px solid var(--border); }
.dash-evol-barra { flex: 1; max-width: 18px; min-height: 3px; border-radius: 3px 3px 0 0; background: var(--seq-azul-4); }
.dash-evol-barra--ganhos { background: var(--success); }
.dash-evol-barra--zero { min-height: 0; }
.dash-evol-rotulo { display: flex; justify-content: center; height: 18px; padding-top: 4px; font-size: 10px; color: var(--ink-soft); white-space: nowrap; overflow: visible; }
@media (max-width: 640px) {
  .dash-evol-col:nth-child(even) .dash-evol-rotulo { visibility: hidden; }
  .barras-h-linha { grid-template-columns: minmax(70px, 34%) 1fr auto; }
  .dash-funil-linha { grid-template-columns: minmax(70px, 30%) 1fr auto; gap: 8px; }
}

.dash-ranking .num { text-align: right; font-variant-numeric: tabular-nums; }

.dash-lista { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.dash-lista li { display: flex; flex-direction: column; gap: 2px; padding: 8px 0; border-bottom: 1px solid var(--border); min-width: 0; }
.dash-lista li:last-child { border-bottom: 0; }
.dash-lista-titulo { font-size: 13px; font-weight: 600; color: var(--ink); text-decoration: none; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dash-lista-titulo:hover { color: var(--primary); text-decoration: underline; }
.dash-lista-meta { font-size: 12px; color: var(--ink-soft); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dash-ver-mais { display: inline-block; margin-top: 8px; font-size: 12px; font-weight: 600; color: var(--primary); }

.dash-vazio, .dash-erro { text-align: center; padding: 36px 20px; }
.dash-vazio h2, .dash-erro p { margin: 0 0 8px; }
.dash-vazio p { margin: 0 0 16px; color: var(--ink-soft); }

/* Esqueleto de carregamento: mesma grade do painel pra não dar salto de layout. */
.dash-sk { gap: 10px; }
.dash-sk-linha, .dash-sk-bloco { display: block; height: 12px; border-radius: 6px; background: color-mix(in srgb, var(--ink) 9%, var(--surface)); animation: dash-pulsar 1.2s ease-in-out infinite; }
.dash-sk-linha.curta { width: 55%; }
.dash-sk-linha.grande { height: 26px; width: 70%; }
.dash-sk-bloco { height: 120px; margin-top: 14px; }
@keyframes dash-pulsar { 50% { opacity: 0.45; } }
@media (prefers-reduced-motion: reduce) {
  .dash-atualizar.girando svg, .dash-sk-linha, .dash-sk-bloco { animation: none; }
  .dash-atualizar.girando { opacity: 0.5; }
}

/* Abas do Dashboard (Vendas | Clientes | Formulários | Tarefas). Barra é sempre uma
   barra: uma linha, rola na horizontal quando não cabe, itens não encolhem. Cor só
   por token, então os dois temas funcionam sem regra própria. */
.dash-abas {
  display: flex; flex-wrap: nowrap; gap: 4px; margin-bottom: 12px; padding: 4px;
  width: max-content; max-width: 100%; overflow-x: auto; overflow-y: hidden; scrollbar-width: thin;
  background: var(--surface); border-radius: var(--radius); box-shadow: var(--shadow-suave);
}
.dash-aba {
  flex-shrink: 0; padding: 7px 16px; border-radius: var(--radius-sm); white-space: nowrap;
  font-size: 14px; font-weight: 500; color: var(--ink-soft); cursor: pointer;
}
.dash-aba:hover { color: var(--ink); background: color-mix(in srgb, var(--ink) 7%, var(--surface)); }
.dash-aba.ativa { background: var(--primary); color: #fff; }

/* `.filter-dropdown` define display; sem esta regra o Funil e o Vendedor apareciam nas abas em que
   não valem, mesmo com `hidden`. */
.dash-toolbar .filter-dropdown[hidden] { display: none; }

/* Layout do Dashboard no desenho do "Contas a Receber" do dashboard-binario — SÓ o layout
   (outubro/2026): topo com abas à esquerda e ações à direita, KPIs numa linha só, e a grade
   de três colunas (duas largas e uma estreita que empilha dois cartões). O conteúdo de cada
   bloco continua sendo o do Sales. Vale para as quatro abas (Vendas, Clientes, Formulários, Tarefas). */
.dash-topo { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 12px; }
.dash-topo .dash-abas { margin-bottom: 0; }
/* A barra do Pipeline sem a margem de baixo: aqui ela divide a linha com as abas. */
.dash-toolbar { margin-bottom: 0; flex-shrink: 0; }
.dash-atualizar { width: 30px; height: 30px; }

/* Os KPIs ocupam UMA linha, um tile por indicador, quando há largura. --kpis vem do template. */
@media (min-width: 1100px) {
  .dash-kpis-linha { grid-template-columns: repeat(var(--kpis, 6), minmax(0, 1fr)); gap: 12px; }
}

.dash-grade--3col { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1.15fr) minmax(0, 1fr); align-items: stretch; }
.dash-grade--3col .dash-c-12 { grid-column: 1 / 3; }
.dash-grade--3col .dash-c-123 { grid-column: 1 / -1; }
.dash-pilha { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.dash-pilha > .card { flex: 1 1 auto; }
@media (max-width: 1099px) {
  .dash-grade--3col { grid-template-columns: minmax(0, 1fr); }
  .dash-grade--3col .dash-c-12, .dash-grade--3col .dash-c-123 { grid-column: auto; }
}

/* Com 7 tiles numa linha cada um tem ~150px: o valor grande e a seta de tendência não cabem lado a
   lado. A seta passa para baixo do valor (flex-wrap), o valor ganha a largura toda e o tile fica
   mais compacto. Sem isto "66,7%" virava "66…" e "R$ 4.500" virava "R…". */
@media (min-width: 1100px) {
  .dash-kpis-linha .kpi-tile { padding: 14px 14px; }
  .dash-kpis-linha .kpi-linha { flex-wrap: wrap; gap: 0 8px; }
  .dash-kpis-linha .kpi-valor { font-size: 24px; }
}
