/* ===========================================================================
   Direction — Sistema de Monitoramento
   Sistema de design. Identidade visual extraída do CSS real de
   directionsolucoes.com; as cores de marca e de status nascem em config.py.

   Ordem do arquivo:
     1. Tokens (tema claro)      5. Cartões e grade
     2. Tokens (tema escuro)     6. Gráficos
     3. Base e tipografia        7. Tabela
     4. Estrutura (lateral+topo) 8. Estados e utilidades

   REGRA DE COR: as cores de status NÃO se escrevem aqui no olho. Elas saem de
   config.py, foram aprovadas por validar_paleta.py e existem em duas versões
   (clara e escura) porque cada tema tem sua própria superfície.
   =========================================================================== */

/* ── 1. Tokens — tema claro ──────────────────────────────────────────────── */
:root {
  /* Marca (do site) */
  --azul: #0763a0;
  --azul-claro: #32b6f6;
  --azul-escuro: #055b8f;
  --azul-medio: #108dc9;
  --verde: #77b62a;

  /* Status — espelham CORES_STATUS de config.py (superfície #ffffff) */
  --st-andamento: #0763a0;
  --st-concluido: #74a315;
  --st-standby: #7d3c00;
  --st-critico: #a02020;
  /* Afastado (cadastro de colaboradores) — validado com validar_paleta.py
     contra as 4 cores acima (--pairs all): passa em todas as checagens que
     não sejam a colisão pré-existente critico↔standby (não introduzida por
     esta cor). Não reusar --azul aqui: férias já usa essa cor. */
  --st-afastado: #7c3aed;
  /* Amarelo de verdade (não o marrom de --st-standby) — pedido explícito
     do usuário (25/08): "a bolinha esta marrom eu quero amarelo", pro
     aviso de lavagem do veículo. Usado sozinho (nunca ao lado de
     --st-concluido/--st-critico no mesmo elemento — são 3 estados
     mutuamente exclusivos do mesmo indicador), por isso a separação
     daltonismo mais apertada contra o verde (`validar_paleta.py`) é
     aceitável aqui — não é um par que precisa ser lido lado a lado. */
  --st-lavagem: #c9a227;

  /* Categórica genérica (dashboard de RH) — 2ª cor para pares do tipo
     "categoria A x categoria B" (contrato, gênero, recrutamento por ano) que
     não são status. NÃO reusar --verde aqui: no tema escuro ela não tem
     variante própria (cai pro valor claro #77b62a) e falha a faixa de
     luminosidade e o piso de visão normal contra --azul escuro — visto na
     prática com validar_paleta.py. --teal já validado contra --azul nos dois
     temas: `validar_paleta.py "#0763a0,#0f8a6c" --mode light --pairs all` e
     `validar_paleta.py "#3b9ce5,#128066" --mode dark --surface "#161a20" --pairs all`. */
  --teal: #0f8a6c;

  /* Superfícies */
  --fundo: #f2f5f9;
  --superficie: #ffffff;
  --superficie-2: #f7f9fc;   /* fundo de trilho, linha zebrada, chip */
  --superficie-3: #eaeff5;   /* trilho de barra, botão fantasma */
  --lateral: #0b2f4a;        /* azul profundo da marca, para a barra lateral */
  --lateral-tinta: #dbe9f4;

  /* Tinta */
  --tinta: #1f2124;
  --tinta-2: #4d5866;
  --tinta-3: #7b8798;
  --borda: #e3e9f0;
  --borda-2: #d3dce6;

  /* Realce de marca em fundo claro */
  --lavagem-azul: #eaf4fb;
  --lavagem-verde: #f2f9e8;
  --lavagem-ambar: #fdf4e7;
  --lavagem-vermelho: #fdeded;

  /* Forma */
  --raio-sm: 8px;
  --raio: 12px;
  --raio-lg: 16px;
  --raio-pill: 999px;

  /* Elevação — sombras curtas e suaves; nada de "caixa flutuando" */
  --sombra-1: 0 1px 2px rgba(16, 30, 48, .05);
  --sombra-2: 0 1px 2px rgba(16, 30, 48, .04), 0 6px 18px rgba(16, 30, 48, .06);
  --sombra-3: 0 8px 30px rgba(16, 30, 48, .14);
  --anel-foco: 0 0 0 3px rgba(50, 182, 246, .45);

  /* Pedido do usuário (03/08): "quero que o sistema esteja mais SOFT com
     animações mais suavizadas" — praticamente todo hover/transição do
     sistema usa esta variável, então um ajuste aqui vale pro sistema
     inteiro de uma vez só (era 160ms). */
  --transicao: 200ms cubic-bezier(.4, 0, .2, 1);
  --largura-lateral: 236px;

  /* Tokens "vidro" (04/08) — pedido do usuário: reforma visual estilo
     "iOS 26 / Liquid Glass" pro sistema todo, "seguindo os padrões de
     colorimetria e fontes do sistema Direction" (nenhuma cor nova — só
     `--superficie`/`--azul`/`--lateral` já validados, com transparência).
     Cada superfície de vidro (topo, modal, lateral) usa estas 4 variáveis
     em vez de valor solto, pra ficar consistente e fácil de ajustar num
     lugar só. `--vidro-blur` fica pesado achado o suficiente pra precisar
     do fallback de Modo Leve (ver `[data-modo-leve="1"]` mais abaixo). */
  /* Mais transparente que a 1ª versão desta reforma (era .62) — pedido
     do usuário: "quero que os visuais de vidro de fato sejam iguais ao
     do IOS 26, transparentes com o fundo distorcido". `--vidro-blur`
     abaixo ganha o filtro de DISTORÇÃO de verdade (não só desfoque) via
     `@supports`, mais embaixo neste arquivo. */
  --vidro-bg: rgba(255, 255, 255, .42);
  --vidro-borda: rgba(255, 255, 255, .7);
  --vidro-realce: rgba(255, 255, 255, .85);
  --vidro-sombra: 0 8px 32px rgba(16, 30, 48, .10);
  --vidro-blur: blur(20px) saturate(180%);
  /* Versão SEM blur, mais opaca — pros ~100 cartões espalhados pelo
     sistema (`.cartao`, `.setor-cartao`...) que ficam em documento normal,
     sem nada de verdade atrás pra desfocar (blur numa cor lisa não muda
     nada visualmente, só gasta GPU à toa). Mais opaca que `--vidro-bg`
     pra não perder contraste contra `--fundo` (os dois são bem claros no
     tema claro). */
  --vidro-bg-solido: rgba(255, 255, 255, .9);
}

/* ── 2. Tokens — tema escuro ─────────────────────────────────────────────── */
/*
   O tema escuro é ESCOLHIDO, não é o claro invertido. A superfície dos cartões
   é #161a20 — exatamente a superfície contra a qual as cores de status foram
   validadas. Se mudar #161a20, revalide as cores (ver config.py).
*/
:root[data-tema="escuro"] {
  --azul: #3b9ce5;
  --azul-claro: #5fc4fb;
  --azul-escuro: #2b7cb8;

  --st-andamento: #3b9ce5;
  --st-concluido: #48711e;
  --st-standby: #c48139;
  --st-critico: #e06666;
  --st-afastado: #8b5cf6;
  --st-lavagem: #d9b64a;
  --teal: #128066;

  --fundo: #0e1116;
  --superficie: #161a20;
  --superficie-2: #1c2129;
  --superficie-3: #262d37;
  --lateral: #10151c;
  --lateral-tinta: #aebbcc;

  --tinta: #e8edf4;
  --tinta-2: #a3aebd;
  --tinta-3: #6f7d8f;
  --borda: #262d37;
  --borda-2: #333c48;

  --lavagem-azul: #12283a;
  --lavagem-verde: #1a2415;
  --lavagem-ambar: #2b2013;
  --lavagem-vermelho: #2e1719;

  --sombra-1: 0 1px 2px rgba(0, 0, 0, .4);
  --sombra-2: 0 1px 2px rgba(0, 0, 0, .3), 0 6px 18px rgba(0, 0, 0, .35);
  --sombra-3: 0 8px 30px rgba(0, 0, 0, .55);

  /* Tokens "vidro" — versão escura (mesmo raciocínio da seção 1). */
  --vidro-bg: rgba(22, 26, 32, .38);
  --vidro-borda: rgba(255, 255, 255, .09);
  --vidro-realce: rgba(255, 255, 255, .14);
  --vidro-sombra: 0 8px 32px rgba(0, 0, 0, .5);
  --vidro-blur: blur(20px) saturate(180%);
  --vidro-bg-solido: rgba(24, 29, 36, .92);
}

/* ── 3. Base e tipografia ────────────────────────────────────────────────── */
* { box-sizing: border-box; }

html { color-scheme: light; }
html[data-tema="escuro"] { color-scheme: dark; }

/* Rede de segurança contra rolagem horizontal da PÁGINA (10/08, auditoria
   mobile pedida pelo usuário — "olha todas as telas"). Achado real: sem
   isso, qualquer componente que vaze um pouco além da viewport (um select
   de filtro com nome de empresa comprido, um rótulo de gráfico com
   `position: absolute` sem clip, uma fileira de botões sem `flex-wrap`)
   empurra `document.documentElement.scrollWidth` além da viewport — e
   isso tem um efeito colateral muito pior que a rolagem em si: todo
   elemento `position: fixed` sem ancestral com `transform` (o leque de
   botões de canto, por exemplo) passa a calcular `right`/`bottom` contra
   esse layout viewport EXPANDIDO em vez da tela visível, e literalmente
   some pra fora da tela. `overflow-x: hidden` aqui não afeta em nada a
   rolagem horizontal PROPOSITAL de dentro de um container (`.rolagem`
   nas tabelas, `.calendario` no celular — ver abaixo) — só impede que o
   documento inteiro role de lado. Ainda assim, cada causa raiz encontrada
   na auditoria foi corrigida em separado (ver `.filtro select`,
   `.topo-dir`, `.calendario-cabecalho`/`.calendario-semana` mais abaixo)
   — isto aqui é só a rede de segurança pra qualquer vazamento que ainda
   não tiver sido encontrado.

   BUG REAL causado por esta regra e corrigido no mesmo dia (achado pelo
   usuário: "quando eu rolo o scroll fica bugado a barra esquerda"): a
   versão original aplicava `overflow-x: hidden` em `html` E `body`. Só
   declarar `overflow-x` (sem declarar `overflow-y` junto) dispara uma
   regra pouco conhecida do CSS — se um eixo é diferente de "visible" e o
   outro fica "visible" (o padrão, já que não tocamos nele), o navegador
   converte o eixo "visible" pra "auto" sozinho, SEM avisar. Resultado
   confirmado com `getComputedStyle`: tanto `html` quanto `body` passaram
   a ter `overflow-y: auto` computado, os dois virando "container de
   rolagem" ao mesmo tempo — e a busca do `position: sticky` da barra
   lateral (`.lateral`) por um ancestral rolável parava no `body`
   primeiro (que nunca rola de verdade — quem rola é o `html`), tratando
   ele como se fosse o "viewport" da barra. Resultado: `.lateral` parava
   de ficar fixa, saindo de tela junto com o resto do conteúdo ao rolar
   (confirmado com Playwright: `lateral.getBoundingClientRect().top`
   virava `-1500` depois de rolar 1500px, em vez de continuar em `0`).
   Corrigido tirando `body` da regra — só `html` (que já é o elemento que
   de fato rola nesta página, confirmado no mesmo teste:
   `document.documentElement.scrollTop` mudava, `document.body.scrollTop`
   não) recebe o `overflow-x: hidden`, então só ELE vira o "container de
   rolagem" pro cálculo do sticky, que volta a bater com quem realmente
   rola. Continua contendo a rolagem horizontal de página igual antes
   (reconferido nas 80 rotas depois da correção) — só não quebra mais o
   sticky. **Lição pra não repetir**: nunca declarar só `overflow-x` (ou
   só `overflow-y`) num elemento ancestral de algo com `position: sticky`
   sem also declarar o outro eixo explicitamente (`overflow-y: visible`
   não adianta sozinho — o navegador reconverte pra `auto` de qualquer
   jeito; o jeito seguro é escopar a regra só no elemento que já é o
   scroller de verdade, como foi feito aqui). */
html { overflow-x: hidden; }

body {
  margin: 0;
  font-family: 'Inter', -apple-system, 'Segoe UI', Roboto, sans-serif;
  background: var(--fundo);
  color: var(--tinta);
  font-size: 14px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3 {
  font-family: 'IBM Plex Sans', 'Inter', sans-serif;
  margin: 0;
  letter-spacing: -.015em;
  line-height: 1.25;
}
a { color: var(--azul); }

/* Números sempre com dígitos de mesma largura: evita a coluna "dançar". */
.num, .val-b, .tile-num, .dias, .avanco-v, .podio-q, td .num { font-variant-numeric: tabular-nums; }

/* Foco visível e consistente — quem navega por teclado precisa ver onde está. */
:where(a, button, select, input, [tabindex]):focus-visible {
  outline: none;
  box-shadow: var(--anel-foco);
  border-radius: var(--raio-sm);
}

/* ── 4. Estrutura: barra lateral + topo ──────────────────────────────────── */
.app { display: flex; min-height: 100vh; }

/* Barra lateral em "vidro" (04/08) — pedido do usuário: "a barra lateral
   eu quero que seja também em vidro também, acho que fica bem premium".
   Gradiente FIXO (não muda com o tema claro/escuro) — mesma decisão já
   tomada pro login/Visão Geral: é a "espinha dorsal" do sistema, sempre
   visível, sempre a mesma cara, dá consistência ao trocar de tema no
   conteúdo. Sem `backdrop-filter` aqui — a lateral não tem nada
   visualmente ATRÁS dela pra desfocar (fica ao lado do conteúdo, não por
   cima), então blur seria custo à toa; o "vidro" vem do gradiente em
   camadas + a borda com realce de luz (`box-shadow: inset`), estilo
   "Liquid Glass" pedido: "vidros que tem as bordas bem diferenciadas". */
.lateral {
  width: var(--largura-lateral);
  flex-shrink: 0;
  color: var(--lateral-tinta);
  display: flex;
  flex-direction: column;
  padding: 20px 14px;
  gap: 26px;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
  overflow-x: hidden;
  /* Gradiente reforçado (04/08) — pedido do usuário DUAS vezes ("quero
     que o menu lateral esquerdo também esteja gradiente") depois de ver
     a 1ª versão, sutil demais pra notar de cara. Manchas maiores/mais
     fortes + gradiente linear com mais contraste entre os tons (de um
     azul mais vivo no topo até quase preto embaixo, em vez de 3 tons de
     azul próximos entre si). */
  background:
    radial-gradient(620px 480px at 8% -10%, rgba(59, 156, 229, .42), transparent 62%),
    radial-gradient(520px 460px at 105% 96%, rgba(18, 138, 214, .4), transparent 58%),
    linear-gradient(175deg, #123f66 0%, #0b2f4a 40%, #061a2e 100%);
  border-right: 1px solid rgba(255, 255, 255, .1);
  box-shadow: inset -1px 0 0 rgba(255, 255, 255, .09), 8px 0 34px rgba(2, 8, 16, .28);
}

.marca { display: flex; align-items: center; gap: 11px; padding: 0 8px; }
.marca-logo {
  width: 34px; height: 34px; flex-shrink: 0; object-fit: contain;
}
.marca-texto { flex: 1; min-width: 0; }
.marca-nome { font-family: 'IBM Plex Sans', sans-serif; font-weight: 800; font-size: 16px; color: #fff; letter-spacing: -.02em; }
.marca-sub {
  font-size: 9.5px; text-transform: uppercase; letter-spacing: .13em;
  color: var(--lateral-tinta); opacity: .65; font-weight: 500; margin-top: -2px;
}

/* Cada setor é um <details> — clica no rótulo, abre/fecha as opções.
   Fica sem marcador nativo (temos a setinha própria via ::after). */
.nav-secao > summary {
  cursor: pointer; list-style: none; display: flex; align-items: center; gap: 9px;
  border-radius: var(--raio-sm); padding: 8px; transition: background var(--transicao);
}
.nav-secao > summary::-webkit-details-marker { display: none; }
.nav-secao > summary:hover { background: rgba(255, 255, 255, .07); }
.nav-secao > summary .nav-txt { flex: 1; }
.nav-secao > summary::after {
  content: '⌄'; font-size: 10px; opacity: .5; transition: transform var(--transicao);
}
.nav-secao[open] > summary::after { transform: rotate(180deg); }

/* Painel do setor é SUSPENSO (flutua por cima do que vem depois dele NA
   PRÓPRIA COLUNA lateral), não um acordeão que empurra o resto da lateral pra
   baixo — pedido do usuário (16/07): só o nome do setor fica na lista, o
   clique abre o menu logo abaixo do rótulo, sobrepondo os itens seguintes em
   vez de deslocá-los. */
.nav-secao { position: relative; }
.nav-secao > nav.nav { display: none; }
.nav-secao[open] > nav.nav {
  display: flex; flex-direction: column; gap: 2px;
  position: absolute; top: 100%; left: 0; right: 0; margin-top: 2px;
  background: var(--lateral); border: 1px solid rgba(255, 255, 255, .12);
  border-radius: var(--raio); padding: 8px; box-shadow: var(--sombra-3); z-index: 100;
}

/* Cabeçalho de setor — mais em destaque que um rótulo pequeno de seção,
   pedido do usuário ("menu suspenso dos setores fica em maior destaque"):
   maior, mais opaco, com fundo no hover pra parecer clicável de verdade. */
.nav-rotulo {
  font-size: 13px; text-transform: none; letter-spacing: 0;
  color: #fff; opacity: .92; font-weight: 700;
}
.nav-rotulo-estatico {
  font-size: 10px; text-transform: uppercase; letter-spacing: .12em;
  color: var(--lateral-tinta); opacity: .5; font-weight: 600; padding: 8px 8px 0; margin-bottom: 4px;
}
.nav { display: flex; flex-direction: column; gap: 2px; }
.nav-i {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 10px; border-radius: var(--raio-sm);
  color: var(--lateral-tinta); text-decoration: none;
  font-size: 13.5px; font-weight: 500;
  transition: background var(--transicao), color var(--transicao);
}
.nav-i:hover { background: rgba(255, 255, 255, .07); color: #fff; }
.nav-i.ativa { background: rgba(255, 255, 255, .11); color: #fff; font-weight: 600; }
.nav-i.ativa .nav-ico { color: var(--azul-claro); }
.nav-ico { width: 17px; text-align: center; font-size: 13px; opacity: .85; flex-shrink: 0; }
.nav-ico-svg { display: inline-flex; align-items: center; justify-content: center; }

/* Painel de Tarefas — destaque "premium" (25/08, pedido do usuário: "com um
   destaque visual premium e sofisticado"). Vidro sutil com borda em
   --azul-claro (mesma cor da marca, nada inventado) + selo com pulso tipo
   indicador "ao vivo" (bolinha branca/azul-claro que expande e some). */
.nav-i-destaque {
  position: relative;
  background: linear-gradient(135deg, rgba(95, 196, 251, .16), rgba(255, 255, 255, .04));
  border: 1px solid rgba(95, 196, 251, .28);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .08);
}
.nav-i-destaque:hover { background: linear-gradient(135deg, rgba(95, 196, 251, .24), rgba(255, 255, 255, .06)); border-color: rgba(95, 196, 251, .45); }
.nav-i-destaque.ativa { background: linear-gradient(135deg, rgba(95, 196, 251, .3), rgba(255, 255, 255, .08)); border-color: var(--azul-claro); }
.nav-i-pulso {
  width: 7px; height: 7px; border-radius: 50%; margin-left: auto; flex-shrink: 0;
  background: radial-gradient(circle at 35% 35%, #fff, var(--azul-claro));
  box-shadow: 0 0 0 0 rgba(95, 196, 251, .55);
  animation: nav-pulso 2.2s cubic-bezier(.4, 0, .6, 1) infinite;
}
@keyframes nav-pulso {
  0% { box-shadow: 0 0 0 0 rgba(95, 196, 251, .55); }
  70% { box-shadow: 0 0 0 7px rgba(95, 196, 251, 0); }
  100% { box-shadow: 0 0 0 0 rgba(95, 196, 251, 0); }
}

/* Setores que ainda não existem. Ficam à vista de propósito: mostram o caminho
   do projeto sem fingir que já funcionam. */
.nav-i.breve { opacity: .38; cursor: not-allowed; }
.nav-i.breve:hover { background: none; color: var(--lateral-tinta); }
.breve-selo {
  margin-left: auto; font-size: 8.5px; text-transform: uppercase; letter-spacing: .07em;
  border: 1px solid currentColor; border-radius: var(--raio-pill); padding: 1px 5px; font-weight: 600;
}

.lateral-usuario { display: flex; align-items: center; gap: 10px; padding: 0 8px; }
.lateral-usuario-textos { min-width: 0; overflow: hidden; }
.lateral-usuario-nome {
  font-size: 12.5px; font-weight: 600; color: #fff;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 140px;
}
.lateral-usuario-sair {
  font-size: 11px; color: var(--lateral-tinta); opacity: .7; text-decoration: none;
}
.lateral-usuario-sair:hover { opacity: 1; text-decoration: underline; }
/* Pedido do usuário (03/08): "quebra a linha pra o 'minha conta' ficar na
   parte de baixo" — antes ficava espremido do lado do seletor de status
   na mesma linha. Virou `<div>` (bloco) de propósito: qualquer elemento
   bloco força quebra de linha sozinho, não precisou de `<br>`. */
.lateral-usuario-links { margin-top: 3px; }

/* Seletor de status (online/ausente/ocupado), 03/08 — `<select>` nativo
   (`_status_presenca.html`), o emoji de cada opção já entrega ícone+cor
   (🟢/🌙/⛔), sem precisar de bolinha/botão separados como nas versões
   anteriores. Existe em DOIS lugares: dentro da lateral escura (cor
   `--lateral-tinta`, feita pra fundo escuro) e dentro do chat, numa
   superfície normal (`--tinta-3`, cor padrão de texto secundário) — por
   isso a cor base é `--tinta-3` e só a lateral sobrescreve. */
.lateral-usuario-status {
  font: inherit; font-size: 11px; color: var(--tinta-3);
  background: none; border: 1px solid currentColor; border-radius: 999px;
  padding: 2px 8px; margin: 2px 0; cursor: pointer; opacity: .85;
}
.lateral-usuario-status:hover { opacity: 1; }
.lateral-usuario-textos .lateral-usuario-status { color: var(--lateral-tinta); }
/* Bug real corrigido (03/08, print do usuário): o POPUP nativo do
   `<select>` (a listinha que abre ao clicar) é desenhado pelo
   navegador/SO, não pela nossa CSS de tema — sem isso, saía cinza-claro
   com texto quase da mesma cor (baixíssimo contraste, "as letras estão
   claras"). `background-color`/`color` no `<option>` são as DUAS
   propriedades que os navegadores baseados em Chromium (Edge/Chrome, o
   que a Direction usa) respeitam nesse popup — força fundo escuro da
   marca (`--lateral`, sempre escuro nos dois temas) com texto branco,
   contraste alto garantido independente do tema claro/escuro do SO. */
.lateral-usuario-status option { background-color: var(--lateral); color: #fff; }

.chat-meu-status-linha { margin-bottom: 8px; flex-shrink: 0; }
.chat-meu-status-linha .lateral-usuario-status { font-size: 12px; }

.lateral-pe { margin-top: auto; display: flex; flex-direction: column; gap: 12px; }
.lateral-nota { font-size: 10.5px; opacity: .45; line-height: 1.5; padding: 0 8px; }
.lateral-versao { font-size: 10px; opacity: .4; padding: 0 8px; letter-spacing: .04em; }

/* Alternador de tema — ícone fixo no canto superior direito, visível em
   qualquer tela (não depende dos blocos topo_filtro/topo_acoes, que cada
   página sobrescreve de um jeito diferente). */
/* Vidro (04/08, achado na revisão: "melhorar botão de enviar bug, e
   outros botões que estão fora do padrão") — eram círculos lisos, sem
   nada do material "vidro" do resto do sistema. `--vidro-bg-solido` (sem
   blur — são ícones pequenos flutuando sobre conteúdo normal de página,
   mesmo raciocínio de `.cartao`) + realce de borda no topo, igual ao
   resto. */
.tema-troca-canto {
  /* Canto inferior direito, não superior — em cima colidia com botões do
     topo (Atualizar, filtros) em algumas telas. Embaixo é uma zona livre,
     sem nenhuma informação por perto pra tapar. */
  position: fixed; bottom: 20px; right: 22px; z-index: 60;
  display: flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; border-radius: 50%;
  background: var(--vidro-bg-solido); border: 1px solid var(--vidro-borda);
  color: var(--tinta); font-size: 16px; cursor: pointer;
  box-shadow: inset 0 1px 0 var(--vidro-realce), var(--sombra-2);
  transition: border-color var(--transicao), transform var(--transicao), box-shadow var(--transicao);
}
.tema-troca-canto:hover {
  border-color: var(--azul); transform: scale(1.08) translateY(-1px);
  box-shadow: inset 0 1px 0 var(--vidro-realce), var(--sombra-3);
}

/* Botão de reportar bug — mesmo estilo do de tema, um pouco à esquerda dele
   pra não sobrepor (ver .tema-troca-canto acima). */
.bug-botao-canto { right: 66px; font-size: 15px; }

/* Ativar notificação do Windows (23/07) — mesmo estilo, mais um passo à
   esquerda pra não sobrepor os outros dois. Começa `hidden` no HTML (só
   JS sabe se `Notification.permission` já foi decidido) — ver base.html.
   Precisa do `[hidden] { display: none }` explícito porque `.tema-troca-
   canto` já define `display: flex` com a MESMA especificidade do que o
   navegador usa pro atributo `hidden` — sem isso, o atributo é ignorado
   e o botão fica sempre visível (bug real, pego testando com
   Notification.permission mockado antes de ir pro ar). */
.notificacao-botao-canto { right: 110px; font-size: 15px; }
.notificacao-botao-canto[hidden] { display: none; }

/* Atalhos de teclado (10/08) — mesmo estilo circular. CORRIGIDO no mesmo
   dia: `right: 198px` supunha os outros botões, todos círculos de 38px
   com 44px de vão entre si — mas o Modo Leve (logo abaixo) é uma PÍLULA
   larga (texto "MODO LEVE" + trilho, ~138px de largura própria), então
   seu início real fica bem mais à esquerda do que `right: 154px` sozinho
   sugere (medido ao vivo: vai até `right: ~292px`). `right: 198px`
   caía DENTRO da pílula — o ícone de teclado ficava por cima do toggle.
   `right: 300px` deixa uma folga de verdade além da borda esquerda da
   pílula (mesmos ~6px de vão que os outros pares já usam). */
#bt-atalhos { right: 300px; font-size: 15px; }

/* Botões de canto: leque atrás de uma seta "↑" (05/08, no mobile só;
   ampliado 10/08 pra QUALQUER tamanho de tela — pedido do usuário:
   "coloque o icone recolhivel, coloque uma up arrow no canto direito e
   ao clicar o restante das opções aparecem igual ao mobile"). O grupo
   (`#cantos-flutuantes`, ver base.html) fica escondido por padrão — só a
   seta (`.cantos-toggle`) aparece sozinha no canto; clicar (`.aberto`,
   JS em base.html) empilha os outros 4 na VERTICAL, subindo a partir
   dela, e ela gira 180° (de "↑" pra "↓") indicando que agora fecha.
   `:not([hidden])` no seletor da notificação é de propósito — sem isso,
   esta regra (que vem DEPOIS de `.notificacao-botao-canto[hidden]` no
   arquivo) venceria a cascata e reapareceria o sino mesmo quando o JS já
   decidiu escondê-lo (permissão já concedida). Sem `@media` nenhum —
   antes só valia abaixo de 860px, agora é o comportamento padrão em
   qualquer largura.

   `--cantos-base` (10/08, correção no mesmo dia — "o icone de seta
   suavizado no chat fica sobrepondo o botão de enviar mensagem"): a
   coluna da conversa do Chat estica até quase a borda direita da tela
   em telas de ~1300px, e o botão "➤" enviar fica exatamente onde a
   seta flutua (`bottom: 20px; right: 20px`) — colidem em cheio. Em vez
   de mexer tela por tela, todo o leque usa essa variável como base
   (`calc(var(--cantos-base) + Npx)`), e `body:has(#chat-shell)` sobe o
   valor só na tela de Chat (`#chat-shell` só existe lá), medido contra
   a altura real do formulário de mensagem (`.chat-form-envolt`, ~77px
   do rodapé da tela) com folga. Usa `:has()` (só Chromium/Edge) — o
   mesmo compromisso já aceito no resto do sistema (filtro de distorção
   "Liquid Glass", cursor customizado). */
:root { --cantos-base: 20px; }
body:has(#chat-shell) { --cantos-base: 86px; }

.cantos-toggle {
  display: flex; align-items: center; justify-content: center;
  position: fixed; bottom: var(--cantos-base); right: 20px; z-index: 65;
  width: 42px; height: 42px; border-radius: 50%;
  background: var(--vidro-bg-solido); border: 1px solid var(--vidro-borda);
  color: var(--tinta-2); cursor: pointer;
  box-shadow: inset 0 1px 0 var(--vidro-realce), var(--sombra-2);
  transition: transform var(--transicao), background var(--transicao), color var(--transicao), border-color var(--transicao);
}
.cantos-toggle svg { transition: transform var(--transicao); }
.cantos-toggle:hover { border-color: var(--azul-claro); color: var(--azul); transform: translateY(-1px); }
.cantos-toggle.aberto { background: var(--azul); color: #fff; border-color: var(--azul); }
.cantos-toggle.aberto svg { transform: rotate(180deg); }

.cantos-flutuantes .tema-troca-canto,
.cantos-flutuantes .modo-leve-toggle {
  display: none; right: 20px !important; bottom: var(--cantos-base);
}
.cantos-flutuantes.aberto .tema-troca-canto:not([hidden]),
.cantos-flutuantes.aberto .modo-leve-toggle {
  display: flex;
}
.cantos-flutuantes #bt-tema { bottom: calc(var(--cantos-base) + 52px); }
.cantos-flutuantes #bt-modo-leve { bottom: calc(var(--cantos-base) + 104px); }
.cantos-flutuantes #bt-atalhos { bottom: calc(var(--cantos-base) + 156px); }
.cantos-flutuantes #bt-bug { bottom: calc(var(--cantos-base) + 208px); }
.cantos-flutuantes #bt-notificacao { bottom: calc(var(--cantos-base) + 260px); }

/* Modo leve (04/08) — virou um TOGGLE de verdade (pedido do usuário: "o
   botão light tem que ser o toggle"), não mais um botão-ícone redondo
   igual tema/bug/notificação. Pílula com rótulo "LIGHT" + trilho/bolinha
   deslizante, mesmo vocabulário visual (`--raio-pill`, cores da marca) do
   resto da reforma "vidro". Fica no MESMO canto/altura dos outros botões
   (`bottom: 20px`), só que com posição/largura próprias por não ser mais
   um círculo de 36px. */
.modo-leve-toggle {
  position: fixed; bottom: 20px; right: 154px; z-index: 60;
  display: flex; align-items: center; gap: 8px;
  background: var(--superficie-2); border: 1px solid var(--borda-2);
  border-radius: var(--raio-pill); padding: 6px 12px 6px 14px;
  cursor: pointer; box-shadow: var(--sombra-2);
  font: inherit; font-size: 10.5px; font-weight: 800; letter-spacing: .08em;
  color: var(--tinta-2);
  transition: border-color var(--transicao), color var(--transicao), box-shadow var(--transicao);
}
.modo-leve-toggle:hover { border-color: var(--azul); color: var(--azul); }
.modo-leve-toggle-trilho {
  width: 32px; height: 19px; border-radius: var(--raio-pill); flex-shrink: 0;
  background: var(--borda-2); position: relative;
  transition: background var(--transicao);
}
.modo-leve-toggle-bolinha {
  position: absolute; top: 2px; left: 2px; width: 15px; height: 15px; border-radius: 50%;
  background: #fff; box-shadow: 0 1px 3px rgba(0, 0, 0, .3);
  transition: transform var(--transicao);
}
.modo-leve-toggle.ativo { color: var(--azul); border-color: var(--azul); box-shadow: var(--sombra-2), 0 0 0 3px rgba(7, 99, 160, .12); }
.modo-leve-toggle.ativo .modo-leve-toggle-trilho { background: linear-gradient(90deg, var(--azul-claro), var(--azul)); }
.modo-leve-toggle.ativo .modo-leve-toggle-bolinha { transform: translateX(13px); }

.conteudo { flex: 1; min-width: 0; display: flex; flex-direction: column; }

/* Cabeçalho em vidro de verdade (04/08) — candidato mais autêntico da
   reforma "Liquid Glass": diferente da lateral, `.topo` é `position:
   sticky` com o CONTEÚDO da página rolando por baixo dele de verdade
   (tabelas, cards) — então `backdrop-filter` aqui tem algo real pra
   desfocar, não é só decoração. Aparece em TODA página do sistema (é
   `base.html`), então esta mudança sozinha já leva o "vidro" pro sistema
   inteiro sem precisar tocar nos 100+ templates individuais. Usa os
   tokens `--vidro-*` (T1/T2) — adapta sozinho com o tema claro/escuro,
   diferente do login/lateral/hero (que são propositalmente fixos). */
.topo {
  background: var(--vidro-bg);
  backdrop-filter: var(--vidro-blur); -webkit-backdrop-filter: var(--vidro-blur);
  border-bottom: 1px solid var(--vidro-borda);
  box-shadow: inset 0 1px 0 var(--vidro-realce), var(--vidro-sombra);
  padding: 0 26px;
  position: sticky; top: 0; z-index: 40;
}
.topo-linha { display: flex; align-items: center; gap: 18px; min-height: 66px; flex-wrap: wrap; padding: 10px 0; }
.topo-tit h1 { font-size: 19px; font-weight: 800; }
/* Cabeçalho compacto (26/08, pedido do usuário: "certas telas não
   precisam de um cabeçalho tão grande, principalmente o chat" — ganha
   espaço vertical de volta pra tela densa de mensagens). Só encolhe
   altura/respiro — o hamburguer continua do mesmo tamanho (é alvo de
   toque, não reduz). */
.topo.topo-compacto .topo-linha { min-height: 40px; padding: 6px 0; }
.topo-tit p { margin: 1px 0 0; font-size: 12px; color: var(--tinta-3); }
.topo-dir { margin-left: auto; display: flex; align-items: center; gap: 14px; flex-wrap: wrap; justify-content: flex-end; }

/* Favoritar página (10/08) — estrela simples ao lado do título, vazia
   (☆) ou cheia (★, cor de destaque) conforme `localStorage.favoritos`. */
.topo-favoritar {
  background: none; border: 0; cursor: pointer; font-size: 19px; line-height: 1;
  color: var(--tinta-3); padding: 4px; flex-shrink: 0;
  transition: color var(--transicao), transform var(--transicao);
}
.topo-favoritar:hover { transform: scale(1.15); }
.topo-favoritar.favoritado { color: #e8a723; }

/* Lista de favoritos na barra lateral — mesmo idioma visual de "Outros
   setores" (`.nav-rotulo-estatico`), item comum reaproveita `.nav-i`.
   `[hidden]` precisa de reforço explícito: `.nav { display: flex }` tem a
   MESMA especificidade que o `[hidden]` padrão do navegador e vence
   (mesmo bug já achado em `.notificacao-botao-canto[hidden]`, 05/08). */
#nav-favoritos[hidden] { display: none; }
#nav-favoritos .nav-i { position: relative; }
#nav-favoritos .nav-i-remover {
  background: none; border: 0; color: var(--tinta-3); cursor: pointer;
  font-size: 11px; padding: 2px 4px; margin-left: auto; flex-shrink: 0;
}
#nav-favoritos .nav-i-remover:hover { color: var(--st-critico); }

/* Busca global (08/08) — pílula compacta no topo, sempre visível (mora
   FORA de qualquer bloco Jinja sobrescrevível, ver base.html). Mesma
   identidade de `.filtro-busca`, só arredondada como pílula pra combinar
   com o resto dos elementos "flutuantes" do topo em vidro. */
.busca-global-caixa { position: relative; min-width: 200px; flex: 0 1 260px; }
.busca-global {
  display: flex; align-items: center; gap: 8px;
  background: var(--superficie-2); border: 1px solid var(--borda-2);
  border-radius: var(--raio-pill); padding: 8px 14px; color: var(--tinta-3);
  transition: border-color var(--transicao), background var(--transicao);
  width: 100%;
}
.busca-global:focus-within { border-color: var(--azul); color: var(--azul); background: var(--superficie); }
.busca-global svg { flex-shrink: 0; }
.busca-global input {
  border: 0; background: transparent; outline: none; font: inherit;
  font-size: 13px; color: var(--tinta); width: 100%;
}
@media (max-width: 860px) {
  .busca-global-caixa { flex: 1 1 100%; order: 3; }
}

/* Dropdown de resultado ao vivo (10/08) — mesmo material "vidro" do
   resto do sistema (`.cartao`/`.modal-caixa`), flutua sobre o conteúdo
   sem empurrar layout nenhum. */
.busca-global-dropdown {
  position: absolute; top: calc(100% + 8px); left: 0; right: 0;
  background: var(--vidro-bg-solido); border: 1px solid var(--borda-2);
  border-radius: var(--raio); box-shadow: 0 12px 32px rgba(0,0,0,.22);
  max-height: 70vh; overflow-y: auto; z-index: 500; padding: 6px;
}
.busca-global-dropdown-grupo + .busca-global-dropdown-grupo { margin-top: 4px; border-top: 1px solid var(--borda-2); padding-top: 4px; }
.busca-global-dropdown-titulo {
  font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
  color: var(--tinta-3); padding: 6px 10px 2px;
}
.busca-global-item {
  display: flex; align-items: center; gap: 10px; padding: 8px 10px;
  border-radius: var(--raio-sm); text-decoration: none; color: inherit;
}
.busca-global-item:hover, .busca-global-item.selecionado { background: var(--superficie-2); }
.busca-global-item-corpo { flex: 1; min-width: 0; }
.busca-global-item-titulo { font-size: 13px; color: var(--tinta); display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.busca-global-item-sub { font-size: 11.5px; color: var(--tinta-3); display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.busca-global-dropdown-rodape {
  display: block; text-align: center; padding: 8px 10px; margin-top: 4px;
  font-size: 12px; color: var(--azul); text-decoration: none; border-top: 1px solid var(--borda-2);
}
.busca-global-dropdown-vazio { padding: 14px 10px; font-size: 12.5px; color: var(--tinta-3); text-align: center; }

/* Botão "apoiar" de Sugestões de melhoria (08/08) — pílula compacta,
   estado "apoiado" preenchido com a cor da marca (mesmo vocabulário de
   `--lavagem-azul` já usado em outros papéis do sistema). */
.btn-apoiar {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--superficie-2); border: 1px solid var(--borda-2);
  border-radius: var(--raio-pill); padding: 4px 11px; font: inherit; font-size: 12.5px;
  color: var(--tinta-2); cursor: pointer; transition: all var(--transicao);
}
.btn-apoiar:hover { border-color: var(--azul); color: var(--azul); }
.btn-apoiar.apoiado { background: var(--lavagem-azul); border-color: var(--azul); color: var(--azul); font-weight: 700; }
.btn-apoiar:disabled { opacity: .6; cursor: default; }

/* Barra de filtro em linha PRÓPRIA, abaixo de título/ações — antes o filtro
   vivia dentro de `.topo-linha`, disputando espaço com título e `.topo-dir`
   na mesma linha (pedido do usuário, 20/07: "novo layout... desse jeito ta
   muito mal organizado" / "fica não muito visual"). Linha separada por
   `border-top` dá o respiro que faltava e tira de vez a disputa de espaço
   que já tinha causado um bug real antes (ver comentário de
   `.topo-filtro-caixa` abaixo). */
.topo-filtro-barra { padding: 14px 0; border-top: 1px solid var(--borda); }
.carimbo { font-size: 11.5px; color: var(--tinta-3); text-align: right; line-height: 1.4; }
.carimbo strong { color: var(--tinta-2); font-weight: 600; }

/* Botão primário "vidro/glossy" (04/08, reforma "Liquid Glass") — gradiente
   sutil de cima pra baixo (claro→escuro, mesmas 3 cores da marca já
   validadas) + realce `inset` no topo simulando luz numa superfície
   arredondada, inspirado nos botões do próprio site directionsolucoes.com
   (pílula, com brilho). `filter: brightness()` no hover em vez de trocar
   `background` — funciona igual em cima de gradiente, sem precisar de um
   2º gradiente só pro estado de hover. */
.btn-att {
  display: inline-flex; align-items: center; gap: 7px;
  background: linear-gradient(180deg, var(--azul-claro) 0%, var(--azul) 55%, var(--azul-escuro) 100%);
  color: #fff; border: 0;
  padding: 9px 18px; border-radius: var(--raio-pill);
  font: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .35), 0 6px 16px rgba(7, 99, 160, .28);
  transition: filter var(--transicao), transform var(--transicao), box-shadow var(--transicao);
  /* Sem isso, todo `.btn-att` que é um `<a>` (não `<button>`) sai sublinhado
     pelo padrão do navegador — achado na padronização de botões de 05/08,
     nunca tinha sido definido explicitamente. */
  text-decoration: none;
}
.btn-att:hover {
  filter: brightness(1.07); transform: translateY(-1px);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .4), 0 10px 26px rgba(7, 99, 160, .34);
}
.btn-att:active { transform: translateY(1px); filter: brightness(.97); }
.btn-att:disabled { opacity: .6; cursor: progress; }

/* Variantes de cor pro mesmo botão "glossy" (04/08) — pedido do usuário:
   "todos os botões tem que ser no mesmo padrão com gradientes, azuis,
   vermelhos, etc" — achado revisando: vários "Excluir"/"Marcar como
   devolvido"/etc usavam `.btn-att`/`.btn-auth` com um `background: var(
   --st-critico/concluido/standby)` CHAPADO no `style=` do próprio
   template, destoando do gradiente que virou o padrão. `color-mix()`
   deriva os tons claro/escuro do gradiente A PARTIR das cores de status
   JÁ VALIDADAS (`--st-critico`/`--st-concluido`/`--st-standby`), sem
   nenhum hex novo — mesma cor que a `.tag`/selo já usa, só com gradiente
   e brilho por cima. Aplicar via `class="btn-att btn-perigo"` (ou
   `btn-sucesso`/`btn-atencao`) no lugar do `style="background: ..."`.
   Seletor composto (`.btn-att.btn-perigo` etc., não só `.btn-perigo`
   sozinho) DE PROPÓSITO — precisa ganhar de `.btn-auth` em
   especificidade nem que `.btn-auth` seja declarada DEPOIS no arquivo
   (é, está mais abaixo); com só uma classe, a ordem no arquivo decidiria
   e o azul de `.btn-auth` venceria por vir depois. */
.btn-att.btn-perigo, .btn-auth.btn-perigo, .btn-salvar.btn-perigo {
  background: linear-gradient(180deg, color-mix(in srgb, var(--st-critico) 100%, white 22%) 0%, var(--st-critico) 55%, color-mix(in srgb, var(--st-critico) 100%, black 18%) 100%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .3), 0 6px 16px rgba(160, 32, 32, .3);
}
.btn-att.btn-perigo:hover, .btn-auth.btn-perigo:hover, .btn-salvar.btn-perigo:hover {
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .35), 0 10px 26px rgba(160, 32, 32, .36);
}
.btn-att.btn-sucesso, .btn-auth.btn-sucesso, .btn-salvar.btn-sucesso {
  background: linear-gradient(180deg, color-mix(in srgb, var(--st-concluido) 100%, white 22%) 0%, var(--st-concluido) 55%, color-mix(in srgb, var(--st-concluido) 100%, black 18%) 100%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .3), 0 6px 16px rgba(20, 90, 20, .28);
}
.btn-att.btn-sucesso:hover, .btn-auth.btn-sucesso:hover, .btn-salvar.btn-sucesso:hover {
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .35), 0 10px 26px rgba(20, 90, 20, .34);
}
.btn-att.btn-atencao, .btn-auth.btn-atencao, .btn-salvar.btn-atencao {
  background: linear-gradient(180deg, color-mix(in srgb, var(--st-standby) 100%, white 24%) 0%, var(--st-standby) 55%, color-mix(in srgb, var(--st-standby) 100%, black 16%) 100%);
  color: #fff;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .3), 0 6px 16px rgba(140, 90, 20, .28);
}
.btn-att.btn-atencao:hover, .btn-auth.btn-atencao:hover, .btn-salvar.btn-atencao:hover {
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .35), 0 10px 26px rgba(140, 90, 20, .34);
}

/* Variante NEUTRA do mesmo botão "glossy" (05/08, achado numa varredura
   pedida pelo usuário: "deixe todos os botões padronizados" / "deixe tudo
   padrão tudo mesmo") — 81 botões "voltar"/secundário ("← Voltar",
   "Editar", "Exportar Excel" etc.) em 60 templates usavam o MESMO
   `style="background: var(--superficie-3); color: var(--tinta-2);"` cru
   no `class="btn-att"`, plano/sem gradiente — sobrevivência de antes da
   reforma "Liquid Glass" (04/08), nunca convertido junto com
   `.btn-perigo`/`.btn-sucesso`/`.btn-atencao`. `.btn-secundario` aplica o
   MESMO tratamento gradiente/brilho, só que em cima de `--superficie-3`
   (neutro, adapta com o tema) em vez de uma cor de status — troca
   `class="btn-att" style="background: ...; color: ...;"` por
   `class="btn-att btn-secundario"`, sem `style=` nenhum. */
.btn-att.btn-secundario, .btn-auth.btn-secundario, .btn-salvar.btn-secundario {
  background: linear-gradient(180deg, color-mix(in srgb, var(--superficie-3) 100%, white 35%) 0%, var(--superficie-3) 55%, color-mix(in srgb, var(--superficie-3) 100%, black 10%) 100%);
  color: var(--tinta-2);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 4px 12px rgba(0, 0, 0, .1), 0 0 0 1px var(--borda) inset;
}
.btn-att.btn-secundario:hover, .btn-auth.btn-secundario:hover, .btn-salvar.btn-secundario:hover {
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .3), 0 8px 18px rgba(0, 0, 0, .14), 0 0 0 1px var(--borda) inset;
}

/* Confirmação temporária do botão "Copiar link" (10/08) — mesmo verbo
   visual de "Salvo ✓" (autosave de Contatos Importantes), reaproveitando
   a cor de sucesso já validada. */
.copiar-link-bt.copiar-link-ok {
  background: linear-gradient(180deg, color-mix(in srgb, var(--st-concluido) 100%, white 35%) 0%, var(--st-concluido) 55%, color-mix(in srgb, var(--st-concluido) 100%, black 10%) 100%);
  color: #fff;
}

/* `.btn-salvar` (04/08, achado real na revisão) — só tinha estilo dentro
   de `.tabela-usuarios` (tabela de admin/usuários); usado SOLTO em outros
   3 lugares (botão "Enviar" do modal de reportar bug, "Criar"/"Salvar"
   em admin/usuários fora da tabela, "Marcar resolvido"/"Reabrir" em
   admin/bugs) — sem essa regra base, esses botões caíam no visual CRU do
   navegador (cinza, sem raio, sem nada), bem fora do padrão do resto do
   sistema. Mesmo gradiente de `.btn-att`. */
.btn-salvar {
  font: inherit; font-size: 14px; font-weight: 600; color: #fff;
  background: linear-gradient(180deg, var(--azul-claro) 0%, var(--azul) 55%, var(--azul-escuro) 100%);
  border: 0; border-radius: var(--raio-pill);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .35), 0 6px 16px rgba(7, 99, 160, .28);
  padding: 10px 18px; cursor: pointer;
  transition: filter var(--transicao), transform var(--transicao), box-shadow var(--transicao);
  text-decoration: none;
}
.btn-salvar:hover { filter: brightness(1.07); transform: translateY(-1px); }
.btn-salvar:active { transform: translateY(1px); filter: brightness(.97); }
/* Dentro da tabela de usuários continua compacto (linha de tabela, sem
   espaço pra um botão de tamanho normal) — só padding/fonte menores,
   herda o gradiente da regra acima em vez de redefinir tudo. */
.tabela-usuarios .btn-salvar { font-size: 12.5px; padding: 7px 13px; white-space: nowrap; }

.pagina {
  padding: 22px 26px 56px; max-width: 1460px; width: 100%;
  /* Pedido do usuário (03/08): "quero movimentação... algo mais
     profissional" — o conteúdo entra com uma leve subida + fade a cada
     carregamento de página (sistema inteiro, `.pagina` é o `<main>` de
     `base.html`).
     BUG REAL corrigido (04/08, achado testando o modal de avisos —
     "fica scrollável e bugado"): era `both` antes, que mantém o
     `transform` do último frame (`translateY(0)`) PRA SEMPRE depois que
     a animação termina — e QUALQUER elemento com `transform` (mesmo
     "zerado") vira "containing block" novo pros descendentes
     `position: fixed`, fazendo-os se posicionar relativo à `.pagina` em
     vez da JANELA. Todo modal que mora DENTRO de `.pagina` (os que
     `geral.html` define no próprio template — avisos, calendário; os de
     `base.html`, tipo o modal genérico de drill-down, ficam FORA de
     `.pagina` e nunca tiveram esse problema) acabava indo parar
     centenas de pixels fora da tela. `backwards` resolve: aplica o
     `opacity: 0` ANTES da animação começar (evita flash), mas depois que termina o
     `transform` volta a `none` de vez (não fica "preso" em
     `translateY(0)`) — visualmente idêntico (opacidade final 1, sem
     deslocamento nenhum), só sem o efeito colateral. */
  animation: pagina-entrar .42s cubic-bezier(.2, .8, .2, 1) backwards;
}
@keyframes pagina-entrar {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}

/* ── 5. Cartões e grade ──────────────────────────────────────────────────── */
/* "Vidro" (04/08) — usa `--vidro-bg-solido` (sem blur, ver tokens no topo
   do arquivo) porque este é O cartão genérico usado em ~100 templates do
   sistema inteiro (dashboards, filtros, formulários) — é a mudança de
   MAIOR alcance desta reforma, tocando um lugar só. Raio maior
   (`--raio-lg`) + realce de borda no topo = a mesma linguagem "Liquid
   Glass" do resto, só sem o custo de `backdrop-filter` (que aqui não
   teria nada de verdade pra desfocar). */
.cartao {
  background: var(--vidro-bg-solido);
  border: 1px solid var(--vidro-borda);
  border-radius: var(--raio-lg);
  box-shadow: inset 0 1px 0 var(--vidro-realce), var(--sombra-2);
  padding: 20px 22px;
  margin-bottom: 18px;
}
.cartao-topo { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; }
.cartao > h2, .cartao-topo h2 { font-size: 15px; font-weight: 700; }
.cartao-sub { font-size: 12px; color: var(--tinta-3); margin: 3px 0 16px; max-width: 68ch; }
.cartao-topo .cartao-sub { margin-bottom: 0; }
/* Texto formatado (negrito/itálico/tópicos) do Ofício/Comunicado Circular
   (18/08) — ver formatacao_texto.py. Espaçamento próximo do que
   `white-space: pre-wrap` dava antes, agora com <p>/<ul> de verdade. */
.texto-formatado p { margin: 0 0 12px; line-height: 1.55; }
.texto-formatado p:last-child { margin-bottom: 0; }
.texto-formatado ul { margin: 0 0 12px; padding-left: 20px; line-height: 1.55; }
.texto-formatado li { margin-bottom: 4px; }
/* Dica discreta "clique pra filtrar" embaixo do título de gráfico de
   barra clicável (31/07, financeiro de Mobilizações) — mais apagada que
   `.cartao-sub` de propósito (aquela é legenda/explicação de dado; esta é
   só um empurrãozinho de UI, não precisa competir visualmente). */
.cartao-sub-clique { font-size: 11px; color: var(--tinta-3); opacity: .6; margin: 2px 0 14px; }

.grade { display: grid; gap: 18px; align-items: start; }
.g-2 { grid-template-columns: 1fr 1fr; }
.g-3 { grid-template-columns: 1fr 1fr 1fr; }
.g-3-2 { grid-template-columns: 3fr 2fr; }
/* `.g-5` (10/08, auditoria mobile) — Treinamentos (valores da sessão:
   treinamento/alimentação/impostos/material/pagamento do instrutor)
   tinha `grid-template-columns: repeat(5, 1fr)` FIXO num `style=` inline
   em vez de classe — `style=` ganha de qualquer `@media` baseado em
   classe (especificidade inline sempre vence), então em tela de celular
   o grid continuava 5 colunas iguais, apertando cada campo até a última
   coluna vazar pra fora da viewport. Virou classe própria, que entra na
   MESMA regra de colapso das outras `.g-*` abaixo. */
.g-5 { grid-template-columns: repeat(5, 1fr); gap: 12px; }
@media (max-width: 1080px) { .g-2, .g-3, .g-3-2 { grid-template-columns: 1fr; } }
@media (max-width: 640px) { .g-5 { grid-template-columns: 1fr 1fr; } }
@media (max-width: 420px) { .g-5 { grid-template-columns: 1fr; } }

/* Base de todo `label.chk` (checkbox + rótulo) fora dos contextos que já
   tinham essa regra (`.multi-select-opcoes`, `.tabela-usuarios`,
   `.calc-campo-check`) — sem isso o navegador alinha a caixinha pela
   baseline do texto, ficando visualmente "fora de eixo" dentro de uma
   `.grade.g-2` (ex.: encaminhar Chamado pra setor). Regras mais
   específicas (as três acima) continuam vencendo por especificidade. */
label.chk { display: flex; align-items: center; gap: 7px; cursor: pointer; }
label.chk input[type="checkbox"] { flex-shrink: 0; }

/* ── Painéis de número ───────────────────────────────────────────────────── */
.tiles { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; margin-bottom: 18px; }
@media (max-width: 900px) { .tiles { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 420px) { .tiles { grid-template-columns: 1fr; } }

/* Mesmo material "vidro" de `.cartao` (04/08, "visuais impressionadores")
   — raio maior + realce de borda no topo, consistente com o resto do
   sistema. `--vidro-bg-solido` no lugar de `--superficie` sólido. */
.tile {
  background: var(--vidro-bg-solido);
  border: 1px solid var(--vidro-borda);
  border-radius: var(--raio-lg);
  box-shadow: inset 0 1px 0 var(--vidro-realce), var(--sombra-1);
  padding: 16px 18px 15px;
  position: relative; overflow: hidden;
  transition: box-shadow var(--transicao), transform var(--transicao);
}
.tile:hover {
  box-shadow: inset 0 1px 0 var(--vidro-realce), var(--sombra-2);
  transform: translateY(-2px);
}
/* Faixa de cor à esquerda: identidade do status sem tingir o texto. */
.tile::before {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: var(--cor, var(--azul));
}
/* Brilho discreto da cor do status, só no canto. */
.tile::after {
  content: ''; position: absolute; right: -30px; top: -30px; width: 110px; height: 110px;
  border-radius: 50%; background: var(--cor, var(--azul)); opacity: .06; pointer-events: none;
}
.tile-rot {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: .09em; color: var(--tinta-3);
  font-weight: 600; display: flex; align-items: center; gap: 7px;
}
.tile-ico { color: var(--cor, var(--azul)); font-size: 10px; }
.tile-num { font-family: 'IBM Plex Sans', sans-serif; font-size: 36px; font-weight: 800; line-height: 1.1; margin-top: 8px; letter-spacing: -.03em; }
.tile-pe { font-size: 11.5px; color: var(--tinta-3); margin-top: 2px; }

/* Versão compacta do `.tile`, pra ficar bem no topo da tela (19/08, Banco
   de Currículos — pedido do usuário: "tenha esses kpi's ao lado", imitando
   os números junto do título no dashboard de referência do Power BI que
   ele mostrou). Mesmo material "vidro"/faixa de cor de `.tile`, só menor —
   não é um componente novo, é `.tile` com padding/fonte reduzidos. `wrap`
   (em vez de esconder num celular, como um header cheio faria) — os 2
   números continuam visíveis, só empilham. */
.tiles-mini { display: flex; flex-wrap: wrap; gap: 8px; align-items: stretch; margin-bottom: 14px; }
.tile-mini { padding: 7px 14px 6px; flex: 0 0 auto; }
.tile-mini .tile-rot { font-size: 9px; white-space: nowrap; }
.tile-mini .tile-num { font-size: 21px; margin-top: 2px; }

/* ── Resumo automático ───────────────────────────────────────────────────── */
.resumo { border-left: 3px solid var(--azul-claro); }
.selo {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--lavagem-azul); color: var(--azul);
  font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .09em;
  padding: 4px 10px; border-radius: var(--raio-pill);
}
.resumo p { margin: 0 0 9px; padding-left: 16px; position: relative; color: var(--tinta-2); font-size: 13.5px; }
.resumo p:last-child { margin-bottom: 0; }
.resumo p::before {
  content: ''; position: absolute; left: 0; top: 8px; width: 6px; height: 6px;
  border-radius: 50%; background: var(--tinta-3);
}
.resumo p.bom::before { background: var(--st-concluido); }
.resumo p.alerta::before { background: var(--st-standby); }
.resumo p strong { color: var(--tinta); font-weight: 600; }

/* ── 6. Gráficos ─────────────────────────────────────────────────────────── */
/* Barras. Marcas finas, pontas arredondadas, 2px de folga entre segmentos —
   a folga é o que deixa os pedaços empilhados legíveis sem borda. */
.barras { display: flex; flex-direction: column; gap: 10px; }
/* `text-decoration: none` — quando a linha é um `<a>` clicável (filtro por
   clique, ver `barras_simples`/`link_filtro` nos templates), o navegador
   sublinha tudo dentro por padrão; sem isso ficava um sublinhado por baixo
   do nome/valor em toda barra clicável do sistema (RH, PDI, Absenteísmo,
   Mobilizações etc. — mesmo componente reaproveitado, corrigido aqui uma
   vez só). Pedido do usuário, 31/07. */
.linha-b { display: grid; grid-template-columns: 176px 1fr 46px; align-items: center; gap: 12px; text-decoration: none; color: inherit; }
.linha-b.simples { grid-template-columns: 200px 1fr 40px; }
.rot-b { font-size: 12.5px; color: var(--tinta-2); display: flex; align-items: center; gap: 8px; min-width: 0; }
.rot-b .nome { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.linha-b-larga { grid-template-columns: 220px 1fr 46px; }
/* Pra linha com valor em R$ no lugar de contagem simples — 46px não cabe
   "R$ 1.362.850,23" numa linha só (quebrava em "R$" + o número embaixo).
   Coluna do nome também mais estreita — sobrava espaço vazio à toa antes
   da trilha começar em nomes curtos ("FMM", "LEAR"). */
.linha-b-moeda { grid-template-columns: 128px 1fr 104px; }
.linha-b-moeda .val-b { white-space: nowrap; }
/* Gargalos do fluxo (`/parados`) — mesma ideia de `.linha-b-moeda`, só
   que o valor é "12 · 5,3d méd." (mais largo que um número solto), então
   tinha `style="grid-template-columns: 270px 1fr 96px"` INLINE no
   template. Virou classe (10/08, auditoria mobile) — inline nunca
   respeitaria a regra de celular abaixo (especificidade inline sempre
   vence `@media` baseado em classe). */
.linha-b-gargalo { grid-template-columns: 270px 1fr 96px; }
/* Celular (10/08, auditoria mobile): as 176-270px fixos da coluna de
   rótulo, somados aos 46-104px da coluna de valor, não cabem numa tela
   estreita — o rótulo já trunca com reticências (`.rot-b .nome`), então
   encolher a coluna aqui só mostra menos texto, sem quebrar layout;
   coluna de valor também encolhe, ainda cabendo qualquer número normal
   do sistema. Cobre as 4 variantes + a classe nova acima, ~15 templates
   de uma vez (RH, Absenteísmo, Mobilizações, Treinamentos, Mão de obra,
   PDI — mesmo componente, mesma correção). */
@media (max-width: 480px) {
  .linha-b, .linha-b.simples { grid-template-columns: 120px 1fr 40px; gap: 8px; }
  .linha-b-larga { grid-template-columns: 128px 1fr 40px; gap: 8px; }
  .linha-b-moeda { grid-template-columns: 90px 1fr 74px; gap: 8px; }
  .linha-b-gargalo { grid-template-columns: 110px 1fr 74px; gap: 8px; }
}
.rot-b-duplo { flex-direction: column; align-items: flex-start; gap: 1px; }
.rot-b-duplo .nome { white-space: normal; overflow: visible; text-overflow: clip; }
.rot-sub { font-size: 11px; color: var(--tinta-3); line-height: 1.2; }

.trilho {
  background: var(--superficie-3); border-radius: var(--raio-pill); height: 14px;
  display: flex; gap: 2px; overflow: hidden; padding: 0; position: relative;
  /* Sulco com leve profundidade (04/08, "visuais impressionadores") — a
     trilha (`.barra` colorida por dentro, cor definida por instância no
     próprio template, não mexida aqui) ganha um vinco sutil, como se
     fosse esculpida no cartão em vez de só um retângulo cinza. */
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, .08);
}
/* Linha de meta (target) nos gráficos de barra/coluna com nota de corte —
   pedido do usuário 17/07, mesma referência visual nos dois formatos. */
.trilho-alvo {
  position: absolute; top: 0; bottom: 0; width: 2px;
  background: var(--tinta-3); opacity: .6; z-index: 2; pointer-events: none;
}
.barra {
  height: 100%; min-width: 3px; border-radius: 0;
  transition: opacity var(--transicao), filter var(--transicao);
}
.barra:first-child { border-radius: var(--raio-pill) 0 0 var(--raio-pill); }
.barra:last-child { border-radius: 0 var(--raio-pill) var(--raio-pill) 0; }
.barra:only-child { border-radius: var(--raio-pill); }
.trilho:hover .barra { opacity: .5; }
.trilho .barra:hover { opacity: 1; filter: brightness(1.06); }

.val-b { font-family: 'IBM Plex Sans', sans-serif; font-size: 13px; font-weight: 700; text-align: right; }
.val-b small { font-weight: 400; color: var(--tinta-3); }

/* Cores de status como classe: o hex vem do tema, não do template. Com
   gradiente sutil (04/08, "visuais impressionadores") — mesma técnica de
   `.col-b`, `color-mix()` em cima da MESMA cor validada, sem hex novo.
   É a classe que colore a maior parte das barras HORIZONTAIS de ranking
   do sistema (`.barra.c-marca` etc., ~15 templates: RH, Treinamentos,
   Mobilizações, Absenteísmo, PDI...) — mudar aqui uma vez só chega em
   quase todo lugar, mesmo achado de maior-alcance já usado em
   `.topo`/`.cartao`/`.col-b`. */
.c-andamento { background: linear-gradient(180deg, color-mix(in srgb, var(--st-andamento) 100%, white 28%) 0%, var(--st-andamento) 100%); }
.c-concluido { background: linear-gradient(180deg, color-mix(in srgb, var(--st-concluido) 100%, white 28%) 0%, var(--st-concluido) 100%); }
.c-standby   { background: linear-gradient(180deg, color-mix(in srgb, var(--st-standby) 100%, white 28%) 0%, var(--st-standby) 100%); }
.c-marca     { background: linear-gradient(180deg, color-mix(in srgb, var(--azul) 100%, white 28%) 0%, var(--azul) 100%); }

/* Velocímetro de combustível do veículo (10/08, "igual painel do carro") —
   mesmo semicírculo do `velocimetro()` do PDI, só que com zonas coloridas
   fixas (vermelho/âmbar/verde, `veiculo.GAUGE_ZONAS`) + marcas de escala
   0-8 + agulha de verdade (SVG puro, geometria calculada em
   `veiculo._ponto_gauge`), no lugar do arco de progresso único do PDI. */
.combustivel-gauge { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.gauge-svg { max-width: 100%; height: auto; }
.combustivel-leitura { font-family: 'IBM Plex Sans', sans-serif; font-size: 26px; font-weight: 700; margin-top: -18px; }
.combustivel-leitura-max { font-size: 15px; font-weight: 400; color: var(--tinta-3); }
.combustivel-leitura.combustivel-ok      { color: var(--st-concluido); }
.combustivel-leitura.combustivel-atencao { color: var(--st-standby); }
.combustivel-leitura.combustivel-critico { color: var(--st-critico); }

/* Colunas (linha do tempo) */
.abas-mini { display: flex; gap: 3px; background: var(--superficie-3); padding: 3px; border-radius: var(--raio-sm); flex-shrink: 0; }
.abas-mini button, .abas-mini a {
  border: 0; background: transparent; font: inherit; font-size: 12px; font-weight: 600;
  color: var(--tinta-2); padding: 5px 13px; border-radius: 6px; cursor: pointer;
  transition: background var(--transicao), color var(--transicao);
  text-decoration: none; display: inline-block;
}
.abas-mini button.ativa, .abas-mini a.ativa { background: var(--superficie); color: var(--azul); box-shadow: var(--sombra-1); }

.colunas { display: flex; align-items: flex-end; gap: 5px; height: 168px; padding-top: 24px; margin-top: 8px; position: relative; }
/* Área de meta (target) do gráfico de colunas — mesmo padding-top:24px do
   `.colunas` acima, pra alinhar exatamente com a régua 0-5 das barras. */
.col-alvo-area { position: absolute; top: 24px; right: 0; bottom: 0; left: 0; pointer-events: none; }
.col-alvo-linha { position: absolute; left: 0; right: 0; border-top: 1px dashed var(--tinta-3); opacity: .5; }
.col-alvo-rot {
  position: absolute; right: 0; bottom: 100%; transform: translateY(2px);
  font-size: 9.5px; color: var(--tinta-3); background: var(--superficie); padding: 0 4px 1px 0;
}
/* `min-width: 0` (10/08, auditoria mobile) — mesma pegadinha do CSS Grid
   já corrigida no calendário semanal (`minmax(0, 1fr)`), só que na
   versão flex: por padrão, um item `flex: 1` ainda tem um piso de
   `min-width: auto`, que o navegador calcula a partir do CONTEÚDO (aqui,
   o rótulo do mês em `.col-r`, `white-space: nowrap`) — sem isso, um
   gráfico com 6+ colunas nunca encolhe abaixo da largura desse rótulo
   somada, e a fileira inteira (`.colunas`) vaza pra fora da tela num
   celular em vez de comprimir. */
.col { flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: center; height: 100%; justify-content: flex-end; gap: 6px; cursor: default; }
/* Barras com gradiente sutil (04/08, pedido do usuário: "quero mudar o
   layout de todos os cards, dashboards com barras gradientes... quero
   visuais impressionadores") — `.col-b` é a barra de coluna usada em
   DEZENAS de gráficos do sistema (Mobilizações, RH, absenteísmo, mão de
   obra...), então é o ponto de maior alcance pra essa mudança.
   `color-mix()` deriva um tom mais claro da MESMA cor de status já
   validada (não é cor nova) — o SIGNIFICADO da cor continua idêntico
   (verde=ok, âmbar=atenção, vermelho=crítico), só o preenchimento virou
   gradiente vertical claro→cor-de-verdade em vez de chapado. */
.col-b {
  width: 100%; max-width: 44px;
  background: linear-gradient(180deg, color-mix(in srgb, var(--st-concluido) 100%, white 28%) 0%, var(--st-concluido) 100%);
  border-radius: 4px 4px 0 0; min-height: 2px; position: relative;
  transition: opacity var(--transicao), filter var(--transicao);
}
.colunas:hover .col-b { opacity: .45; }
.col:hover .col-b { opacity: 1; filter: brightness(1.08); }
.col-v { position: absolute; top: -19px; left: 50%; transform: translateX(-50%); font-family: 'IBM Plex Sans', sans-serif; font-size: 11.5px; font-weight: 700; color: var(--tinta-2); white-space: nowrap; }
/* Celular (10/08, auditoria mobile): `.col-v` é o valor centralizado
   ACIMA de cada barra (ex.: "R$ 29,4 mil") — com `white-space: nowrap` e
   centralizado por `transform`, um valor mais longo que a própria coluna
   (comum: coluna de gráfico financeiro tem uns 40-50px, o texto formatado
   passa de 60px) vaza pros dois lados; na última coluna de um gráfico
   colado na borda direita do cartão, isso empurrava a página inteira mais
   larga que a tela. Truncar com reticências só em telas estreitas —
   passar o mouse/dedo não é o gesto principal aqui (é só um rótulo, o
   valor completo já está no tooltip da própria barra, `data-tt`). */
@media (max-width: 640px) {
  .col-v { max-width: 58px; overflow: hidden; text-overflow: ellipsis; }
}
.col-b.zero { background: var(--superficie-3); }
.col-b-negativo { background: linear-gradient(180deg, color-mix(in srgb, var(--st-critico) 100%, white 28%) 0%, var(--st-critico) 100%); }
.col-r { font-size: 10px; color: var(--tinta-3); white-space: nowrap; }
@media (max-width: 640px) {
  .col-r { max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
}

/* Eixo (linha de zero) que sobe do rodapé — usado por `colunas_moeda`
   (treinamentos_dashboard.html) quando a série tem valor negativo, pra
   barra negativa crescer PRA BAIXO a partir do eixo em vez de a partir do
   chão do gráfico. `.col-pista` troca o `.col-b` de item de fluxo normal
   (como em `.col` sozinho, usado no resto do sistema) pra item posicionado
   de forma absoluta, sem mexer na regra base `.col-b`/`.col` que outras
   telas (RH, absenteísmo, mobilizações) reaproveitam sem valor negativo. */
.col-pista { position: relative; width: 100%; height: 100%; }
.col-pista .col-b { position: absolute; left: 0; right: 0; margin: 0 auto; }
.col-b-baixo { border-radius: 0 0 4px 4px; }
.col-eixo-area { position: absolute; top: 24px; right: 0; bottom: 0; left: 0; pointer-events: none; }
.col-eixo-linha { position: absolute; left: 0; right: 0; border-top: 1px dashed var(--tinta-3); opacity: .5; }

/* Barra de PROJEÇÃO (mês que ainda não aconteceu) — `colunas_moeda` com
   `campo_projetado` (31/07, financeiro de Mobilizações; 3ª revisão desta
   mesma tela: passou por "tracinho solto" e "linha conectada" antes de o
   usuário pedir a virada certa — projetar o FUTURO, não suavizar o
   passado). Tracejada e sem preenchimento sólido, pra nunca confundir
   com faturamento de verdade. */
.col-b-projetado { background: transparent; border: 2px dashed var(--azul); opacity: .8; }
/* Selo de variação % vs. mesmo mês do ano anterior, embaixo do rótulo do
   mês (`campo_variacao` no mesmo macro). */
.col-variacao { display: block; font-size: 9.5px; font-weight: 700; margin-top: 1px; }
.col-variacao-pos { color: var(--st-concluido); }
.col-variacao-neg { color: var(--st-critico); }

/* Legenda — para 2+ séries ela existe sempre: identidade nunca é só a cor. */
.legenda { display: flex; gap: 16px; flex-wrap: wrap; margin-bottom: 14px; }
.leg-i { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--tinta-2); }
.leg-c { width: 9px; height: 9px; border-radius: 3px; flex-shrink: 0; }

/* Tooltip. Uma camada só, movida por JS — em vez do title do navegador, que
   demora 1s para aparecer e não dá para estilizar. */
.tt {
  position: fixed; z-index: 90; pointer-events: none;
  background: var(--tinta); color: var(--superficie);
  border-radius: var(--raio-sm); padding: 7px 11px;
  font-size: 12px; line-height: 1.45; box-shadow: var(--sombra-3);
  max-width: 260px; opacity: 0; transform: translateY(3px);
  transition: opacity 110ms ease, transform 110ms ease;
}
:root[data-tema="escuro"] .tt { background: #2b333f; color: var(--tinta); border: 1px solid var(--borda-2); }
.tt.ver { opacity: 1; transform: translateY(0); }
.tt b { font-weight: 600; }
.tt-tit { font-weight: 700; margin-bottom: 2px; }
.tt-sub { opacity: .75; }

/* Avatares */
.ava {
  width: 26px; height: 26px; border-radius: 50%; flex-shrink: 0; object-fit: cover;
  border: 1.5px solid var(--superficie); box-shadow: 0 0 0 1px var(--borda-2);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 9.5px; font-weight: 700; color: #fff; background: var(--azul);
}
.ava.g { width: 42px; height: 42px; font-size: 13px; }
/* Sem foto = logo da Direction, não mais iniciais coloridas (26/08,
   pedido do usuário: "as pessoas que não têm foto, coloque a foto da
   logo da direction no perfil" — confirmado que vale em TODO avatar
   pequeno do sistema, não só um lugar). `span.ava` (não `img.ava`) pega
   só a variante SEM foto de verdade — as ~10 templates que usam esse
   componente (`{% if r.foto %}<img>{% else %}<span>{% endif %}`) nunca
   precisaram mudar, o fallback é 100% CSS aqui. `logo-icone-alt.png` (não
   o `logo-icone.png` puro) de propósito — é a versão com plaquinha
   branca atrás, pensada exatamente pra ficar legível em cima de
   QUALQUER cor de fundo (mesmo motivo de já ser usada em login/minha
   conta). `!important` é necessário mesmo (não tem outro jeito): cada
   template ainda escreve `style="background: {{ r.cor }}"` inline pra
   essa pessoa, e `style=` inline sempre vence especificidade de classe —
   só `!important` consegue substituir. */
span.ava {
  background: url('/static/logo-icone-alt.png') center / 72% no-repeat, var(--superficie-3) !important;
  color: transparent;
}

/* Pódio */
.podio { display: flex; flex-direction: column; gap: 8px; }
.podio-l {
  display: flex; align-items: center; gap: 12px; padding: 9px 11px;
  border-radius: var(--raio-sm); background: var(--superficie-2); border: 1px solid var(--borda);
}
.podio-l.p1 { background: var(--lavagem-verde); border-color: var(--st-concluido); }
:root[data-tema="escuro"] .podio-l.p1 { border-color: var(--borda-2); }
.podio-pos { font-family: 'IBM Plex Sans', sans-serif; font-weight: 800; font-size: 15px; color: var(--tinta-3); width: 20px; text-align: center; }
.podio-l.p1 .podio-pos { color: var(--st-concluido); }
:root[data-tema="escuro"] .podio-l.p1 .podio-pos { color: var(--verde); }
.podio-nome { font-weight: 600; font-size: 13px; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.podio-q { font-family: 'IBM Plex Sans', sans-serif; font-weight: 800; font-size: 17px; color: var(--tinta); }
.podio-q small { font-family: 'Inter', sans-serif; font-size: 10.5px; font-weight: 500; color: var(--tinta-3); margin-left: 3px; }

/* Botãozinho de info lúdico no fim de cada linha do pódio (21/08, pedido
   do usuário: "coloque mais lúdico, um botãozinho de info do lado
   direito no final do card, algo mais bonitinho") — troca o `title`
   nativo do navegador (sem graça) por um balãozinho com cara própria do
   sistema. `tabindex="0"` + `:focus` também funcionam por teclado/touch,
   não só mouse. */
.podio-info { position: relative; display: inline-flex; flex-shrink: 0; }
.podio-info-icone {
  width: 20px; height: 20px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
  background: var(--azul-claro); color: #fff; font-size: 11.5px; font-weight: 800; font-style: italic;
  font-family: Georgia, 'Times New Roman', serif; cursor: help; user-select: none;
  transition: transform var(--transicao), background var(--transicao);
}
.podio-info:hover .podio-info-icone, .podio-info:focus .podio-info-icone,
.podio-info:focus-visible .podio-info-icone {
  transform: scale(1.15) rotate(-6deg); background: var(--azul);
  outline: none;
}
.podio-info-bolha {
  /* #1f2124 fixo (não `var(--tinta)`) DE PROPÓSITO — achado real (21/08,
     "no modo noturno as letras ficam brancas"): `--tinta` é a cor do
     TEXTO, que troca de escura (tema claro) pra quase branca (tema
     escuro) — usada como FUNDO do balão, no escuro virava balão branco
     com letra branca em cima, ilegível. Balão de dica é pra ficar
     sempre escuro nos dois temas, igual tooltip nativo. */
  position: absolute; right: -6px; bottom: calc(100% + 10px); z-index: 5;
  width: max-content; max-width: 210px; padding: 8px 12px; border-radius: var(--raio-sm);
  background: #1f2124; color: #fff; font-size: 12px; font-weight: 600; line-height: 1.35; text-align: left;
  box-shadow: 0 12px 28px rgba(0, 0, 0, .24);
  opacity: 0; visibility: hidden; transform: translateY(4px) scale(.96); transform-origin: bottom right;
  transition: opacity .16s ease, transform .16s ease, visibility .16s;
  pointer-events: none;
}
.podio-info-bolha::after {
  content: ''; position: absolute; top: 100%; right: 12px;
  border: 6px solid transparent; border-top-color: #1f2124;
}
.podio-info:hover .podio-info-bolha, .podio-info:focus .podio-info-bolha, .podio-info:focus-visible .podio-info-bolha {
  opacity: 1; visibility: visible; transform: translateY(0) scale(1);
}

/* ── 7. Tabela ───────────────────────────────────────────────────────────── */
.rolagem { overflow-x: auto; margin: 0 -22px; padding: 0 22px; }
table { width: 100%; border-collapse: collapse; font-size: 13px; }
th {
  text-align: left; font-size: 10px; text-transform: uppercase; letter-spacing: .08em;
  color: var(--tinta-3); font-weight: 700; padding: 0 10px 10px;
  border-bottom: 1px solid var(--borda); white-space: nowrap;
  position: sticky; top: 0; background: var(--superficie);
}
td { padding: 11px 10px; border-bottom: 1px solid var(--borda); vertical-align: middle; }
tr:last-child td { border-bottom: 0; }
tbody tr { transition: background var(--transicao); }
tbody tr:hover { background: var(--superficie-2); }

/* Campo dentro de tabela editável (Almoxarifado, catálogo de EPI, Contatos
   Importantes, Convocações — cada linha vira um formulário próprio, ver
   `form="form-N"` na linha) — pedido do usuário (30/07): "esses campos que
   você criou, no catálogo, são boxes muito simples não tem aquela sutileza
   e o layout padrão da direction". Sem esta regra, o `<input>` cru dentro
   de `<td>` ficava no estilo padrão do navegador, sem nada da identidade
   do sistema — `.campo input` (usado nos formulários normais) não alcança
   porque esses campos não estão dentro de um `.campo`. Mesma superfície/
   borda/raio/foco de `.campo input`, só mais compacto pra caber na
   densidade de uma linha de tabela. */
table input[type="text"], table input[type="number"], table input[type="date"],
table input[type="search"], table input[type="tel"], table select, table textarea {
  width: 100%; font: inherit; font-size: 13px; color: var(--tinta);
  background: var(--superficie-2); border: 1px solid var(--borda-2);
  border-radius: var(--raio-sm); padding: 6px 9px;
  transition: border-color var(--transicao), background var(--transicao);
}
table input[type="text"]:focus, table input[type="number"]:focus, table input[type="date"]:focus,
table input[type="search"]:focus, table input[type="tel"]:focus, table select:focus, table textarea:focus {
  border-color: var(--azul); outline: none; background: var(--superficie);
}
table textarea { resize: vertical; min-height: 34px; }
.proc-nome { font-weight: 600; color: var(--tinta); text-decoration: none; display: inline-flex; align-items: center; gap: 6px; }
.proc-nome:hover { color: var(--azul); }
.proc-nome .link-ico { opacity: 0; font-size: 10px; transition: opacity var(--transicao); }
tr:hover .proc-nome .link-ico { opacity: .6; }

/* Etiquetas */
.tag {
  display: inline-flex; align-items: center; gap: 5px; font-size: 11px; font-weight: 600;
  padding: 3px 9px; border-radius: var(--raio-pill);
  background: var(--superficie-3); color: var(--tinta-2); white-space: nowrap;
}
.tag-st { color: #fff; }
:root[data-tema="escuro"] .tag-st { color: #0e1116; }
/* Precisa vencer o "background" de .tag acima — mesma especificidade (uma
   classe só), e .tag vem depois no arquivo, então sem isto a cor do status
   nunca aparecia (a etiqueta ficava sempre cinza-neutro). */
.tag-st.c-andamento { background: var(--st-andamento); }
.tag-st.c-concluido { background: var(--st-concluido); }
.tag-st.c-standby   { background: var(--st-standby); }
.tag-cli { background: var(--lavagem-azul); color: var(--azul); text-transform: uppercase; font-size: 10px; letter-spacing: .04em; }

.dias { font-family: 'IBM Plex Sans', sans-serif; font-weight: 700; white-space: nowrap; }
.dias.alerta { color: var(--st-standby); }
.dias.critico { color: var(--st-critico); }
.dias.critico::before, .dias.alerta::before { content: '▲ '; font-size: 9px; }

/* Avanço */
.avanco { display: flex; align-items: center; gap: 9px; min-width: 112px; }
.avanco-t {
  flex: 1; height: 8px; background: var(--superficie-3); border-radius: var(--raio-pill);
  overflow: hidden; box-shadow: inset 0 0 0 1px var(--borda-2);
}
.avanco-b {
  /* `display: block` é o bug de verdade por trás de "a barrinha fica
     vazia mesmo com progresso" (26/08, achado renderizando a página de
     visdade com Playwright, não só lendo o CSS): `.avanco-b` é um
     `<span>`, que por padrão é `display: inline` — e elemento inline
     IGNORA `width`/`height` completamente, sempre (regra do CSS, não
     bug de navegador). Sem isso, o `style="width: X%"` de cada linha
     nunca fez efeito nenhum, pra NENHUM processo, em NENHUM tema —
     `offsetWidth` media 0px mesmo com `width: 50%` no HTML. O ajuste de
     brilho/contraste feito antes (comentário abaixo) era real, mas
     mexia numa barra que na prática nunca teve tamanho nenhum pra
     mostrar aquele brilho. */
  display: block;
  height: 100%; background: var(--st-concluido); border-radius: var(--raio-pill);
  /* Realce claro no topo (mesmo truque "glossy" de `.btn-att`) em vez de
     só um contorno escuro — achado num print real do usuário no celular
     (25/08): no tema escuro, `--st-concluido` é um verde ESCURO de
     propósito (ver comentário grande em "Decisões que já foram tomadas"
     no CLAUDE.md — separação pra daltônicos exige isso), o que deixava o
     preenchimento quase invisível sobre o trilho cinza-escuro numa tela
     pequena. O brilho por cima não muda o HEX em si (a paleta continua a
     mesma, já validada), só ajuda o olho a perceber onde o preenchido
     termina. */
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .4), inset 0 0 0 1px rgba(0, 0, 0, .2);
  filter: brightness(1.15) saturate(1.2);
  min-width: 2px;
}
:root[data-tema="escuro"] .avanco-b { filter: brightness(1.7) saturate(1.35); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5), inset 0 0 0 1px rgba(0, 0, 0, .3); }

/* Rosca "Parados em alerta" */
.rosca-linha { display: flex; align-items: center; gap: 28px; flex-wrap: wrap; }
.rosca-svg circle { transition: opacity var(--transicao); }
.rosca-svg:hover circle[data-tt] { opacity: .55; }
.rosca-svg circle[data-tt]:hover { opacity: 1 !important; }
.rosca-num {
  font-family: 'IBM Plex Sans', sans-serif; font-size: 26px; font-weight: 800; fill: var(--tinta);
}
.rosca-rot { font-size: 9px; fill: var(--tinta-3); text-transform: uppercase; letter-spacing: .07em; }
.rosca-legenda { display: flex; flex-direction: column; gap: 10px; }
.rosca-item { display: flex; align-items: center; gap: 9px; font-size: 13px; color: var(--tinta-2); }
.rosca-item strong { color: var(--tinta); font-family: 'IBM Plex Sans', sans-serif; font-size: 15px; margin-left: 2px; }
.rosca-cor { width: 11px; height: 11px; border-radius: 50%; flex-shrink: 0; }
.avanco-v { font-family: 'IBM Plex Sans', sans-serif; font-size: 11.5px; color: var(--tinta-3); width: 30px; text-align: right; }

/* ── 8. Filtro, avisos, estados ──────────────────────────────────────────── */
.filtro { display: flex; align-items: center; gap: 12px; row-gap: 10px; flex-wrap: wrap; }
/* Algumas telas (financeiro de Mobilizações, Performance dos Gestores,
   Medidas Disciplinares, Treinamentos) sobrescrevem `.filtro` pra
   `flex-direction: column` e agrupam os campos em `<div style="display:
   flex; flex-wrap: wrap;">` (uma linha de filtro por div). Sem largura
   explícita, esse div-linha fica com o tamanho mínimo de conteúdo em vez
   de esticar pra 100% do formulário (pegadinha real de CSS Grid/Flex:
   `align-items: stretch` no pai não força isso quando o próprio filho já
   é `flex-wrap: wrap`) — no celular isso fazia a linha inteira ficar mais
   larga que a tela, cortando o último campo (achado na auditoria mobile
   de 10/08). `width: 100%` aqui resolve pra qualquer uma dessas 7 telas
   de uma vez, sem depender de largura fixa em cada `style=` inline. */
.filtro > div { width: 100%; }
.filtro label { font-size: 11px; font-weight: 600; color: var(--tinta-3); text-transform: uppercase; letter-spacing: .07em; }
.filtro select {
  font: inherit; font-size: 13px; color: var(--tinta);
  background: var(--superficie-2); border: 1px solid var(--borda-2);
  border-radius: var(--raio-sm); padding: 9px 12px; cursor: pointer; min-width: 200px;
  /* `max-width: 100%` (10/08, auditoria mobile) — sem isso, um `<select>`
     cuja opção mais comprida seja um nome de empresa grande (ex.:
     Financeiro de Mobilizações) cresce pra caber o texto inteiro, mesmo
     estourando a viewport inteira num celular — `min-width` é só um
     piso, nunca um teto. */
  max-width: 100%;
  transition: border-color var(--transicao);
}
.filtro select:hover { border-color: var(--azul); }
/* Data solta no filtro de topo (ex.: "desde"/"até" em acoes.html, "mês" em
   prioridades.html) — mesmo visual de `.filtro select`, só que pra
   `<input type="date">`/`<input type="month">` sem a classe
   `.filtro-busca` (30/07, achado numa auditoria depois do usuário
   apontar campo sem o padrão visual do sistema). */
.filtro input[type="date"], .filtro input[type="month"] {
  font: inherit; font-size: 13px; color: var(--tinta);
  background: var(--superficie-2); border: 1px solid var(--borda-2);
  border-radius: var(--raio-sm); padding: 9px 12px; cursor: pointer;
  transition: border-color var(--transicao);
}
.filtro input[type="date"]:hover, .filtro input[type="date"]:focus,
.filtro input[type="month"]:hover, .filtro input[type="month"]:focus { border-color: var(--azul); outline: none; }
.filtro-busca {
  font: inherit; font-size: 13px; color: var(--tinta);
  background: var(--superficie-2); border: 1px solid var(--borda-2);
  border-radius: var(--raio-sm); padding: 9px 12px; width: 180px;
  transition: border-color var(--transicao);
}
.filtro-busca:hover, .filtro-busca:focus { border-color: var(--azul); }
.filtro-busca::placeholder { color: var(--tinta-3); }
.btn-filtro { font: inherit; font-size: 13px; background: var(--azul); color: #fff; border: 0; border-radius: var(--raio-sm); padding: 8px 14px; cursor: pointer; }
.filtro-ativo {
  font-size: 12px; color: var(--azul); background: var(--lavagem-azul);
  padding: 5px 11px; border-radius: var(--raio-pill); display: inline-flex; align-items: center; gap: 7px;
}
.filtro-ativo a { color: inherit; opacity: .7; text-decoration: none; font-weight: 700; }
.filtro-ativo a:hover { opacity: 1; }

/* Retrair filtros — pedido do usuário: "em qualquer tela... os filtros
   dependendo do caso poluem muito a tela". Envolve o topo_filtro de
   QUALQUER template (ver base.html) sem precisar de CSS por tela. */
/* SEM `flex-grow`/`min-width: 0` de propósito — bug real que já aconteceu
   aqui (20/07, visto em print pelo usuário): quando o filtro ainda vivia
   DENTRO de `.topo-linha` (disputando espaço com título e `.topo-dir`),
   essas duas propriedades deixavam a caixa ENCOLHER abaixo do min-content
   dos `<select>` filhos — virava uma coluna estreita e cada campo quebrava
   numa linha própria, pilha vertical confusa. Hoje o filtro já está numa
   `.topo-filtro-barra` própria (não compete mais por espaço com nada), mas
   a regra continua correta e barata de manter. */
.topo-filtro-caixa { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.topo-filtro-retrair {
  flex-shrink: 0; width: 26px; height: 26px; border-radius: 50%;
  border: 1px solid var(--borda-2); background: var(--superficie-2); color: var(--tinta-2);
  display: flex; align-items: center; justify-content: center; cursor: pointer;
  transition: transform var(--transicao), border-color var(--transicao), background var(--transicao);
}
.topo-filtro-retrair:hover { border-color: var(--azul); color: var(--azul); }
.topo-filtro-retrair svg { transition: transform var(--transicao); }
.topo-filtro-conteudo { min-width: 0; }
/* Estado retraído: some o conteúdo, gira a seta pra apontar "fechado" (pra
   baixo vira pra cima) e troca o fundo do botão pra deixar claro que tem
   filtro escondido ali. Selecionado por atributo no <html> (igual o tema),
   decidido ANTES do primeiro paint — sem isso a tela "pisca" aberta a
   cada navegação pra quem já retraiu. */
:root[data-filtro-retraido="1"] .topo-filtro-conteudo { display: none; }
:root[data-filtro-retraido="1"] .topo-filtro-retrair { background: var(--lavagem-azul); border-color: var(--azul); color: var(--azul); }
:root[data-filtro-retraido="1"] .topo-filtro-retrair svg { transform: rotate(-90deg); }

.multi-select { position: relative; }
.multi-select summary {
  font: inherit; font-size: 13px; color: var(--tinta);
  background: var(--superficie-2); border: 1px solid var(--borda-2);
  border-radius: var(--raio-sm); padding: 8px 11px; cursor: pointer; min-width: 140px;
  list-style: none; transition: border-color var(--transicao);
}
.multi-select summary::-webkit-details-marker { display: none; }
.multi-select summary::after { content: "▾"; float: right; color: var(--tinta-3); font-size: 11px; margin-left: 8px; }
.multi-select summary:hover { border-color: var(--azul); }
.multi-select[open] summary { border-color: var(--azul); }
.multi-select-opcoes {
  position: absolute; top: calc(100% + 4px); left: 0; z-index: 20;
  background: var(--superficie-2); border: 1px solid var(--borda-2);
  border-radius: var(--raio-sm); box-shadow: var(--sombra-3);
  padding: 10px 13px; display: flex; flex-direction: column; gap: 8px;
  min-width: 160px; white-space: nowrap;
}
.multi-select-opcoes label.chk { display: flex; align-items: center; gap: 7px; font-size: 13px; color: var(--tinta); cursor: pointer; text-transform: none; }

/* Ícone "i" de ajuda — círculo pequeno que abre um painel flutuante com
   texto explicativo, mesmo mecanismo do .multi-select (details/summary
   nativo, sem JS) só que com um badge redondo no lugar do pill de filtro
   e o painel permite quebra de linha (não é white-space: nowrap). */
.ajuda-info { position: relative; display: inline-block; vertical-align: middle; margin-left: 8px; }
.ajuda-info summary {
  display: flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; border-radius: 50%;
  background: var(--superficie-3); border: 1px solid var(--borda-2);
  color: var(--tinta-2); font-size: 12px; font-weight: 700; font-style: italic;
  font-family: Georgia, 'Times New Roman', serif;
  cursor: pointer; list-style: none; user-select: none;
}
.ajuda-info summary::-webkit-details-marker { display: none; }
.ajuda-info summary:hover, .ajuda-info[open] summary { border-color: var(--azul); color: var(--azul); }
.ajuda-info-painel {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 20;
  background: var(--superficie-2); border: 1px solid var(--borda-2);
  border-radius: var(--raio-sm); box-shadow: var(--sombra-3);
  padding: 14px 16px; width: 320px; max-width: 82vw;
  font-size: 12.5px; font-weight: 400; color: var(--tinta-2); line-height: 1.55;
  text-transform: none;
}
.ajuda-info-painel strong { display: block; color: var(--tinta); margin-bottom: 4px; }
.ajuda-info-painel ul { margin: 6px 0 0; padding-left: 16px; }
.ajuda-info-painel li { margin-bottom: 4px; }
.ajuda-info-painel li:last-child { margin-bottom: 0; }

.aviso {
  background: var(--lavagem-ambar); border: 1px solid var(--borda);
  border-left: 3px solid var(--st-standby); border-radius: var(--raio);
  padding: 13px 17px; margin-bottom: 18px; font-size: 13px; color: var(--tinta-2);
}
.aviso.erro { background: var(--lavagem-vermelho); border-left-color: var(--st-critico); }
.aviso.ok { background: var(--lavagem-verde); border-left-color: var(--st-concluido); }
.aviso strong { display: block; margin-bottom: 3px; color: var(--tinta); }

/* Subtarefas dentro de uma célula da tabela (Financeiro) — <details> nativo,
   sem JS, mesmo espírito do multi-select de Status em /rh/colaboradores. */
.subtarefas-detalhe summary {
  cursor: pointer; font-size: 12.5px; color: var(--tinta-2);
  white-space: nowrap; list-style: none;
}
.subtarefas-detalhe summary::-webkit-details-marker { display: none; }
.subtarefas-detalhe summary::before { content: "▸ "; }
.subtarefas-detalhe[open] summary::before { content: "▾ "; }
.subtarefas-lista { margin: 6px 0 0; padding-left: 4px; list-style: none; }
.subtarefas-lista li {
  font-size: 12px; padding: 2px 0; white-space: nowrap; color: var(--tinta-2);
}
.subtarefas-lista li a { color: inherit; }
.subtarefas-lista li.concluida { text-decoration: line-through; color: var(--tinta-3); }

/* Indicadores automáticos ao lado do "Lançar ação/projeto" (Performance dos
   Gestores) — números de agora do setor, pra pontuar com base no dado. */
.indicadores-setor {
  background: var(--superficie-2); border: 1px solid var(--borda);
  border-radius: var(--raio); padding: 12px 16px; margin-bottom: 14px;
}
.indicadores-setor-legenda { font-size: 12px; color: var(--tinta-3); margin-bottom: 10px; }
.indicadores-setor-linha { display: flex; flex-wrap: wrap; gap: 20px; }
.indicadores-setor-item { min-width: 90px; }
.indicadores-setor-valor { font-size: 19px; font-weight: 700; color: var(--tinta); }
.indicadores-setor-rot { font-size: 11.5px; color: var(--tinta-2); }

/* Selo de status do item de desempenho (pendente/aceito/recusado) — mesmo
   idioma visual de .setor-selo, só com cor por estado. */
.selo-status {
  display: inline-block; padding: 2px 9px; border-radius: 999px;
  font-size: 11px; font-weight: 600; white-space: nowrap;
}
.selo-status-pendente, .selo-status-standby, .selo-status-atencao { background: var(--lavagem-ambar); color: var(--st-standby); }
.selo-status-aceito, .selo-status-aprovado, .selo-status-concluido { background: var(--lavagem-verde); color: var(--st-concluido); }
.selo-status-recusado, .selo-status-critico { background: var(--lavagem-vermelho); color: var(--st-critico); }
.selo-status-andamento { background: var(--lavagem-azul); color: var(--st-andamento); }

/* Selo "Salvo" do autosave de Contatos Importantes (30/07). */
.contato-salvo { font-size: 11.5px; font-weight: 600; color: var(--st-concluido); margin-right: 8px; }

/* Destaque "🏆 Mais votada" em Melhoria Contínua (17/08) — mesma família
   visual de .selo-status-*, mas com padding/formato PRÓPRIO (não depende
   de combinar com .selo-status, que os selos de status também não fazem
   hoje) pra garantir a forma de pílula mesmo sozinho. */
.selo-destaque {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 9px; border-radius: 999px; font-size: 11px; font-weight: 700;
  white-space: nowrap; background: var(--lavagem-ambar); color: var(--st-standby);
  margin-left: 8px;
}

/* Slider de pontos (Performance dos Gestores) — só deixa escolher dentro
   da faixa válida da categoria, em vez de digitar um número livre. */
.campo-slider { display: flex; align-items: center; gap: 10px; }
.campo-slider input[type="range"] {
  flex: 1; -webkit-appearance: none; appearance: none; height: 5px;
  background: var(--borda-2); border-radius: 999px; outline: none;
}
.campo-slider input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none; width: 17px; height: 17px;
  border-radius: 50%; background: var(--azul); cursor: pointer;
  border: 2px solid var(--superficie);
}
.campo-slider input[type="range"]::-moz-range-thumb {
  width: 17px; height: 17px; border-radius: 50%; background: var(--azul);
  cursor: pointer; border: 2px solid var(--superficie);
}
.campo-slider output {
  font-variant-numeric: tabular-nums; font-weight: 700; color: var(--tinta);
  min-width: 38px; text-align: right;
}
.vazio { text-align: center; color: var(--tinta-3); padding: 34px; font-size: 13px; }

/* Espera do "Atualizar" — vidro, mesmos tokens do modal/topo. */
.trabalhando {
  position: fixed; inset: 0; z-index: 80;
  background: rgba(11, 20, 32, .45);
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  display: flex; align-items: center; justify-content: center;
}
.trabalhando[hidden] { display: none; }
/* A tela de "trocando de página" precisa cobrir TUDO, inclusive um modal
   aberto e o cursor customizado (z-index 2000, ver .cursor-ponto/.cursor-halo)
   — é a última coisa que a pessoa vê antes da página trocar de verdade. */
#pagina-carregando { z-index: 2050; }
/* Achado real (04/08, reportado pelo usuário): "o texto carregando no
   centro da tela ficou preto, consegue deixar branco e o box de loading
   mais escuro?" — `.trabalhando`/`.modal-fundo` escurecem o fundo SEMPRE
   (não seguem o tema claro/escuro do site), então o cartão flutuando por
   cima também devia ser SEMPRE vidro escuro com texto claro — usar
   `--vidro-bg` (que troca de cor com o tema) criava um cartão CLARO
   flutuando num fundo escurecido, com texto escuro por cima: contraste
   ruim, além de destoar do resto (regra geral: "toda vez que abrir um
   box transparente com fundo branco, fica difícil a leitura"). Fixo,
   não usa os tokens `--vidro-*` (que são por tema) de propósito. */
.trabalhando-caixa {
  background: rgba(15, 22, 32, .78); color: #fff;
  backdrop-filter: var(--vidro-blur); -webkit-backdrop-filter: var(--vidro-blur);
  border: 1px solid rgba(255, 255, 255, .14); border-radius: var(--raio-lg);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .18), 0 20px 50px rgba(0, 0, 0, .4);
  padding: 30px 38px; text-align: center; max-width: 340px;
}
.trabalhando-caixa strong { display: block; margin-bottom: 5px; font-size: 15px; color: #fff; }
.trabalhando-caixa span { color: rgba(255, 255, 255, .72); font-size: 13px; }
.trabalhando-caixa .girando { border-color: rgba(255, 255, 255, .25); border-top-color: #fff; }
.girando {
  width: 30px; height: 30px; margin: 0 auto 16px;
  border: 3px solid var(--borda-2); border-top-color: var(--azul);
  border-radius: 50%; animation: girar .8s linear infinite;
}
@keyframes girar { to { transform: rotate(360deg); } }

.rodape { text-align: center; color: var(--tinta-3); font-size: 11.5px; margin-top: 28px; line-height: 1.7; }
.rodape-copyright { opacity: .7; margin-top: 2px; }

/* ── Telas estreitas: a lateral vira uma faixa no topo ───────────────────── */
/* Menu de celular: em vez de espremer TODOS os itens numa barra horizontal
   rolável (jeito antigo, ruim de usar com tantos setores), o menu lateral
   vira uma gaveta (off-canvas) que abre por cima da tela, com fundo escuro
   atrás — pedido do usuário (21/07): "é possível que fique bem direitinho
   no celular?". `.lateral` já é `flex-direction: column` por padrão
   (desktop) — no celular só precisa trocar `position: sticky` por `fixed`
   e deslizar pra fora da tela (`translateX`) até o botão-hambúrguer abrir. */
.menu-hamburguer {
  display: none; align-items: center; justify-content: center;
  width: 36px; height: 36px; border-radius: var(--raio-sm);
  border: 1px solid var(--borda-2); background: var(--superficie);
  color: var(--tinta); cursor: pointer; flex-shrink: 0;
}
.lateral-fundo {
  display: none; position: fixed; inset: 0; background: rgba(10, 20, 35, .5);
  z-index: 190;
}
@media (max-width: 860px) {
  .menu-hamburguer { display: inline-flex; }
  .app.menu-aberto .lateral-fundo { display: block; }
  .lateral {
    position: fixed; top: 0; left: 0; width: min(84vw, 300px);
    transform: translateX(-100%); transition: transform var(--transicao);
    z-index: 200; box-shadow: var(--sombra-3);
  }
  .app.menu-aberto .lateral { transform: translateX(0); }
  .pagina, .topo { padding-left: 16px; padding-right: 16px; }
  .rolagem { margin: 0 -16px; padding: 0 16px; }
  .topo-linha { flex-wrap: wrap; gap: 10px; }

  /* Usuários e permissões, no celular (27/08, achado real do usuário:
     "fica totalmente não responsivo... layout horrível de mexer") —
     `table-layout: fixed` (estilo.css, `.tabela-usuarios`) faz sentido no
     desktop, mas no celular ESPREME as 6 colunas pra caber na tela em vez
     de rolar, mesmo já estando dentro do `.rolagem` (que só ajuda quando
     a tabela tem permissão de ficar mais larga que o container). Aqui ela
     ganha essa permissão de volta: `table-layout: auto` + `min-width`
     generoso — cada coluna (nome, setores, PDI, admin/gestor, senha,
     ações) volta a ter espaço de verdade pros checkboxes/botões, e o
     `.rolagem` já existente passa a rolar de verdade em vez de espremer. */
  .tabela-usuarios { table-layout: auto; min-width: 760px; }
}

/* Respeita quem desliga animações no sistema. */
@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
  .girando { animation-duration: 2.4s !important; }
}

/* ── Liquid Glass de verdade (04/08) — pedido do usuário: "quero que os
   visuais de vidro de fato sejam iguais ao do IOS 26, transparentes com
   o fundo distorcido no vidro igual ao liquid glass". `backdrop-filter:
   blur()` sozinho só EMBAÇA (é "vidro fosco", geração anterior de
   glassmorphism) — o Liquid Glass de verdade DISTORCE o que está atrás,
   como uma lupa/vidro curvo de verdade. O filtro `#vidro-liquido` (SVG,
   ver `base.html`/`login.html`/`criar_conta.html`) faz isso combinando
   ruído orgânico (`feTurbulence`) com deslocamento de pixel
   (`feDisplacementMap`).
   **Só Chrome/Edge (Chromium) aceitam `backdrop-filter: url(#filtro-svg)`
   hoje — Safari e Firefox ainda não** (pesquisado nesta sessão). Por
   isso o token `--vidro-blur` (definido lá em cima, seções 1/2) começa
   como um `blur()` simples, seguro em QUALQUER navegador, e só vira a
   versão com distorção de verdade dentro deste `@supports` — quem não
   suporta nunca chega a pedir o filtro, cai automaticamente pro blur
   simples sem quebrar nada. */
@supports (backdrop-filter: url(#vidro-liquido)) {
  :root { --vidro-blur: url(#vidro-liquido) blur(10px) saturate(180%); }
  :root[data-tema="escuro"] { --vidro-blur: url(#vidro-liquido) blur(10px) saturate(180%); }
}

/* ── Modo leve (04/08) — pedido do usuário: "também preciso de uma opção
   LIGHT do sistema para os computadores fracos". Mesmo raciocínio do
   `prefers-reduced-motion` acima (reaproveitado, não duplicado), mas
   ativado manualmente por escolha da PESSOA (`[data-modo-leve="1"]` no
   `<html>`, mesmo mecanismo do tema claro/escuro — lido ANTES de pintar a
   tela, salvo em localStorage; botão em `base.html`/`login.html`/
   `criar_conta.html`) — desliga só os efeitos mais CAROS de desenhar
   (`backdrop-filter`, `filter: blur` animado contínuo), não é sobre gosto
   visual. O resto do sistema (cor, layout, dado) fica idêntico. */
:root[data-modo-leve="1"] * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
:root[data-modo-leve="1"] .girando { animation-duration: 2.4s !important; }
:root[data-modo-leve="1"] .auth-blob,
:root[data-modo-leve="1"] .boas-vindas-linha::before,
:root[data-modo-leve="1"] .boas-vindas-linha::after {
  display: none;
}
/* ⚠️ GOTCHA — vale ler antes de adicionar qualquer `animation: ...
   infinite` nova no CSS (achado real, 05/08, usuário: "a frase que fica
   rodando na fotinha... fica girando bem rápido" no modo leve).
   `animation-duration: .01ms !important` (regra `*` acima) NÃO PARA uma
   animação `infinite` — ela faz o ciclo inteiro (giro, pulso, o que for)
   completar em .01ms e recomeçar pra sempre, ou seja, a "otimização"
   vira uma animação absurdamente RÁPIDA em vez de parada (funciona bem
   só pra animação de UMA VEZ SÓ, tipo entrada de página, que só precisa
   "terminar logo"). Pra tudo que é `infinite` (giro contínuo, pulso,
   mancha de luz flutuando), a correção é `animation: none` explícito
   aqui embaixo — mesmo padrão já usado pro letreiro de avisos
   (`.avisos-ticker-trilho`, achado em 04/08, MESMA causa) e agora
   replicado pros outros 4 que tinham esse mesmo problema escondido:
   anel de texto girando (Visão Geral), logo pulsando (tela de
   "Entrando..."), sino pulsando (pop-up de lembrete "na hora") e o
   indicador de "gravando áudio" do Chat. Se already existe
   `display:none` (blobs) ou um valor fixo mais lento (`.girando`), não
   precisa de mais nada — já é seguro por natureza. */
:root[data-modo-leve="1"] .boas-vindas-foto-svg,
:root[data-modo-leve="1"] .boas-vindas-logo,
:root[data-modo-leve="1"] .lembrete-alerta-icone,
:root[data-modo-leve="1"] .chat-gravando-pulso,
:root[data-modo-leve="1"] .tv-blob {
  animation: none;
}
/* `backdrop-filter` é o efeito mais pesado dos dois (recalcula o desfoque
   de tudo que está atrás, a cada frame) — sem ele, o cartão de vidro fica
   ilegível (quase transparente) se não trocar o fundo por algo sólido
   também. Repetido pra cada superfície com `backdrop-filter` de verdade
   (`.topo`, `.modal-caixa`, `.trabalhando-caixa` — a lateral e os
   `.cartao`/`.setor-cartao` genéricos NÃO usam `backdrop-filter`, ver
   comentário deles, então não precisam de nada aqui). */
:root[data-modo-leve="1"] .auth-caixa {
  backdrop-filter: none; -webkit-backdrop-filter: none;
  background: rgba(11, 47, 74, .92);
}
:root[data-modo-leve="1"] .topo {
  backdrop-filter: none; -webkit-backdrop-filter: none;
  background: var(--superficie);
}
:root[data-modo-leve="1"] .modal-fundo {
  backdrop-filter: none; -webkit-backdrop-filter: none;
}
:root[data-modo-leve="1"] .trabalhando {
  backdrop-filter: none; -webkit-backdrop-filter: none;
}
:root[data-modo-leve="1"] .trabalhando-caixa {
  backdrop-filter: none; -webkit-backdrop-filter: none;
  background: rgb(15, 22, 32);
}

/* ── 9. Login e criar conta ──────────────────────────────────────────────── */
/* Reforma "vidro" (04/08) — pedido do usuário depois de ver 3 opções de
   maquete visual num navegador ("opção A", ver `_backups/2026-08-04-
   visual-vidro/README.md` pro antes/depois e como reverter): fundo em
   gradiente com a cor da marca (fixo, NÃO acompanha o alternador de tema
   claro/escuro do resto do sistema — é a "cara" da tela de entrada,
   sempre a mesma, igual o mockup aprovado) + cartão de vidro fosco
   (`backdrop-filter: blur`) por cima. Só ESTE grupo (`.tela-auth`) usa
   gradiente/vidro — o resto do sistema continua exatamente como estava. */
.tela-auth {
  min-height: 100vh; display: flex; align-items: center; justify-content: center;
  padding: 24px; position: relative; overflow: hidden;
  background:
    radial-gradient(1100px 700px at 12% 8%, rgba(59, 156, 229, .5), transparent 60%),
    radial-gradient(900px 900px at 90% 90%, rgba(7, 99, 160, .45), transparent 55%),
    linear-gradient(160deg, #0b2f4a, #0d3a5c 55%, #0a2740);
}
/* Manchas de luz suaves, à deriva, atrás do cartão de login — pedido do
   usuário (03/08): "quero movimentação... com parallax algo do tipo".
   Parallax de verdade (camadas se movendo em velocidades diferentes ao
   rolar a página) não se aplica bem aqui — a tela de login não rola, e o
   resto do sistema é painel/tabela, onde esse efeito tende a distrair mais
   que ajudar. Isto é a interpretação mais próxima que cabe numa tela sem
   rolagem: um fundo "vivo", devagar, comum em produtos SaaS modernos.
   `will-change: transform` só nesses 3 elementos (não em `*`), evita
   forçar composição em coisa que não precisa. Some sozinho em Modo leve
   (ver seção "Modo leve" mais abaixo) — filtro de blur contínuo animado é
   justamente o tipo de efeito mais pesado pra computador fraco. */
.auth-blob {
  position: absolute; border-radius: 50%; filter: blur(90px);
  pointer-events: none; will-change: transform; z-index: 0;
}
.auth-blob-1 { width: 520px; height: 520px; top: -160px; left: -140px; background: #3b9ce5; opacity: .55; animation: auth-flutuar-a 24s ease-in-out infinite; }
.auth-blob-2 { width: 460px; height: 460px; bottom: -180px; right: -120px; background: #7bd0ff; opacity: .35; animation: auth-flutuar-b 30s ease-in-out infinite; }
.auth-blob-3 { width: 300px; height: 300px; top: 38%; right: 5%; background: #ffffff; opacity: .08; animation: auth-flutuar-a 34s ease-in-out infinite reverse; }
@keyframes auth-flutuar-a {
  0%, 100% { transform: translate(0, 0) scale(1); }
  50% { transform: translate(38px, 28px) scale(1.08); }
}
@keyframes auth-flutuar-b {
  0%, 100% { transform: translate(0, 0) scale(1); }
  50% { transform: translate(-32px, -24px) scale(1.05); }
}
@keyframes auth-caixa-entrar {
  from { opacity: 0; transform: translateY(14px) scale(.98); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}
.auth-caixa {
  position: relative; z-index: 1; color: #fff;
  /* `backwards`, não `both` — mesmo motivo do bug corrigido em `.pagina`
     (ver comentário lá): `both`/`forwards` deixa um `transform` "preso"
     depois que a animação termina, o que quebra qualquer `position:
     fixed` que um dia more dentro deste elemento. Preventivo aqui (hoje
     não há nenhum `position: fixed` dentro de `.auth-caixa`), mas
     consistente com a correção real feita em `.pagina`. */
  animation: auth-caixa-entrar .5s cubic-bezier(.2, .8, .2, 1) backwards;
  background: rgba(255, 255, 255, .14);
  /* Achado na revisão (04/08): isto ainda usava um `blur()` fixo, escrito
     ANTES do sistema de tokens `--vidro-*` existir — nunca tinha sido
     atualizado, então este cartão (o primeiro "vidro" do sistema,
     login) ficava de fora tanto do filtro de distorção de verdade
     quanto do fallback automático do Modo Leve pro `backdrop-filter`
     (o fallback de `background` sólido continuava funcionando, só o
     `backdrop-filter: none` não tinha efeito nenhum porque não tinha
     `var()` pra sobrescrever). Trocado por `var(--vidro-blur)`. */
  backdrop-filter: var(--vidro-blur); -webkit-backdrop-filter: blur(28px) saturate(160%);
  border: 1px solid rgba(255, 255, 255, .28); border-radius: var(--raio-lg);
  box-shadow: 0 30px 70px rgba(5, 20, 35, .35), inset 0 1px 0 rgba(255, 255, 255, .25);
  padding: 40px 36px; width: 100%; max-width: 390px;
}
.auth-marca { display: flex; align-items: center; gap: 11px; margin-bottom: 26px; }
.auth-logo {
  width: 40px; height: 40px; flex-shrink: 0; object-fit: contain;
}
.auth-marca-nome { font-family: 'IBM Plex Sans', sans-serif; font-weight: 800; font-size: 17px; }
.auth-marca-sub { font-size: 11.5px; color: rgba(255, 255, 255, .68); margin-top: -1px; }
/* Lema da marca — pedido do usuário (24/07): texto de verdade (não a
   imagem que ele mandou, que estava em baixa resolução), pra ficar nítido
   em qualquer tela. */
.auth-lema { font-size: 13px; font-weight: 600; color: #bfe3ff; margin-bottom: 20px; }
.auth-titulo { font-size: 19px; font-weight: 800; margin-bottom: 4px; }
.auth-sub { font-size: 12.5px; color: rgba(255, 255, 255, .68); margin-bottom: 22px; }

/* Descendentes de `.auth-caixa` que reaproveitam classes GLOBAIS do
   sistema (`.campo`, `.btn-auth`, `.aviso`, `.campo-senha-olho` — usadas
   em dezenas de outras telas) — escopados aqui, nunca nas classes base,
   pra não vazar o visual de vidro pro resto do sistema. */
.auth-caixa .campo label { color: rgba(255, 255, 255, .7); }
.auth-caixa .campo input {
  background: rgba(255, 255, 255, .1); border-color: rgba(255, 255, 255, .25); color: #fff;
}
.auth-caixa .campo input::placeholder { color: rgba(255, 255, 255, .4); }
.auth-caixa .campo input:focus {
  border-color: #7bd0ff; background: rgba(255, 255, 255, .16);
  box-shadow: 0 0 0 4px rgba(123, 208, 255, .18);
}
.auth-caixa .btn-auth {
  background: #fff; color: var(--lateral); box-shadow: 0 10px 24px rgba(0, 0, 0, .18);
}
.auth-caixa .btn-auth:hover { background: #f0f6fb; filter: none; transform: translateY(-2px); box-shadow: 0 14px 30px rgba(0, 0, 0, .24); }
.auth-caixa .campo-senha-olho { color: rgba(255, 255, 255, .75); }
.auth-caixa .campo-senha-olho:hover { background: rgba(255, 255, 255, .14); color: #fff; }
.auth-caixa .aviso { background: rgba(255, 255, 255, .1); border-color: rgba(255, 255, 255, .2); border-left-color: #fff; color: rgba(255, 255, 255, .85); }
.auth-caixa .aviso strong { color: #fff; }
.auth-caixa .aviso.erro { background: rgba(255, 90, 90, .18); border-left-color: #ff9d9d; color: #ffdcdc; }

.campo { margin-bottom: 16px; }
.campo label {
  display: block; font-size: 11.5px; font-weight: 600; color: var(--tinta-2);
  text-transform: uppercase; letter-spacing: .06em; margin-bottom: 6px;
}
/* `label.chk` (checkbox + nome, ex.: "Encaminhar pro setor", "Quem recebe
   o lembrete") dentro de um `.campo` tinha a MESMA especificidade da
   regra acima — como `.campo label` vem depois no arquivo, ela vencia por
   engano e desmontava o layout do checkbox (virava bloco maiúsculo em vez
   de checkbox ao lado do texto normal). Achado real, 05/08 (usuário: "a
   caixinha ficar exatamente ao lado do nome"). */
.campo label.chk {
  /* `align-items: flex-start` (não `center`, que `label.chk` usa por
     padrão) — achado real, 05/08 (usuário: "corrigir o box dos
     funcionários na tela de lembretes"): nome de duas palavras (ex.:
     "Túlio Prestrelo") quebra em 2 linhas numa coluna estreita, e
     `align-items: center` centralizava o checkbox no MEIO das 2 linhas —
     parecia flutuar solto, longe da primeira linha do nome. Com
     `flex-start`, o checkbox fica alinhado com a PRIMEIRA linha, como
     em qualquer lista de checkbox com texto que pode quebrar. */
  display: flex; align-items: flex-start; text-transform: none; letter-spacing: normal;
  font-size: 13.5px; font-weight: 500; color: var(--tinta); margin-bottom: 0;
}
.campo label.chk input[type="checkbox"] { margin-top: 3px; }
/* `:not([type=checkbox]):not([type=radio])` — achado real, 05/08
   (usuário: "corrigir o box dos funcionários na tela de lembretes"):
   `input` sem qualificador casa TAMBÉM com `<input type="checkbox">`
   (ex.: `label.chk` dentro de um `.campo`, como "Quem recebe o lembrete"/
   "Encaminhar pro setor") — o `width: 100%` esticava o checkbox pra
   preencher a coluna inteira (ex.: 288px), empurrando o nome bem pra
   longe da caixinha visualmente, mesmo o glifo do checkbox continuando
   pintado só no canto esquerdo. Texto/data/número continuam width:100%
   normal. */
.campo input:not([type="checkbox"]):not([type="radio"]), .campo select, .campo textarea {
  width: 100%; font: inherit; font-size: 14px; color: var(--tinta);
  background: var(--superficie-2); border: 1px solid var(--borda-2);
  border-radius: var(--raio-sm); padding: 10px 12px;
  transition: border-color var(--transicao);
}
.campo input:focus, .campo select:focus, .campo textarea:focus { border-color: var(--azul); outline: none; }
.campo textarea { resize: vertical; min-height: 60px; }

/* Seletor de arquivo (upload de anexo/foto, ex.: admin_anuncios.html,
   minha_conta.html) — o "escolher arquivo" nativo do navegador não dá pra
   restilizar por completo, mas o BOTÃO (`::file-selector-button`) sim;
   sem isso ficava com o cinza cru do sistema operacional, destoando de
   todo o resto (achado numa auditoria de consistência, 30/07). */
input[type="file"] {
  font: inherit; font-size: 12.5px; color: var(--tinta-2);
}
input[type="file"]::file-selector-button {
  font: inherit; font-size: 12.5px; font-weight: 600; color: var(--tinta-2);
  background: var(--superficie-3); border: 1px solid var(--borda-2); border-radius: var(--raio-sm);
  padding: 6px 12px; margin-right: 8px; cursor: pointer; transition: border-color var(--transicao);
}
input[type="file"]::file-selector-button:hover { border-color: var(--azul); color: var(--azul); }

/* Anexo escolhido "um de cada vez" (26/08, correção de bug real: o
   `<input type="file" multiple>` cru em ocorrencias.html/mao_de_obra_
   supervisao_detalhe.html tinha um problema de fábrica do próprio
   navegador — abrir o seletor de novo pra adicionar MAIS um arquivo
   SUBSTITUÍA a escolha anterior em vez de somar, e não tinha como tirar
   um arquivo escolhido errado antes de salvar. Pedido do usuário:
   "escolher um, depois escolher outro separadamente" + "excluir o anexo
   caso escolha errado". O `<input>` de verdade fica oculto (`hidden`,
   `name="anexos"`) e só recebe a lista via `DataTransfer` reconstruída
   pelo JS a cada adição/remoção — ver `script_extra` dos dois
   templates. Este chip é só a PRÉVIA antes de salvar; o anexo já salvo
   usa o chip de `.anuncio-aviso-anexo` (outro, com link de download). */
.anexo-pendente-lista { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
.anexo-pendente-lista:empty { display: none; }
.anexo-pendente {
  display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600;
  color: var(--tinta-2); background: var(--superficie-2); border: 1px solid var(--borda-2);
  border-radius: var(--raio-sm); padding: 4px 6px 4px 10px; max-width: 260px;
}
.anexo-pendente-nome { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.anexo-pendente-remover {
  flex-shrink: 0; background: none; border: 0; cursor: pointer; color: var(--tinta-3);
  font-size: 14px; line-height: 1; padding: 2px 4px; transition: color var(--transicao);
}
.anexo-pendente-remover:hover { color: var(--st-critico); }

/* Busca + chips de "Pessoas específicas" nos Chamados (27/08, pedido do
   usuário: "melhorar parte de marcar individualmente os chamados" — o
   `<select multiple>` antigo exigia Ctrl/Cmd+clique, sem busca, ninguém
   achava sozinho). Chip reaproveita `.anexo-pendente*` acima (mesmo
   componente visual, só o conteúdo muda) — a lista de sugestões abaixo do
   campo é só isso: um menu suspenso simples que aparece ao digitar. */
.pessoas-sugestoes {
  position: relative; margin-top: 4px; max-height: 180px; overflow-y: auto;
  background: var(--vidro-bg-solido); border: 1px solid var(--vidro-borda);
  border-radius: var(--raio-sm); box-shadow: var(--sombra-1);
}
.pessoas-sugestoes:empty { display: none; }
.pessoas-sugestao-item {
  display: block; width: 100%; text-align: left; background: none; border: 0;
  padding: 8px 12px; font-size: 13px; color: var(--tinta); cursor: pointer;
}
.pessoas-sugestao-item:hover, .pessoas-sugestao-item.realce { background: var(--superficie-2); }

.campo-senha { position: relative; }
.campo-senha input { padding-right: 40px; }
.campo-senha-olho {
  position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
  width: 32px; height: 32px; display: flex; align-items: center; justify-content: center;
  background: none; border: 0; cursor: pointer; font-size: 15px; border-radius: var(--raio-sm);
  opacity: .65; transition: opacity var(--transicao), background var(--transicao);
}
.campo-senha-olho:hover { opacity: 1; background: var(--superficie-3); }

/* Mesmo tratamento "glossy" de `.btn-att` (ver comentário lá) — `.btn-auth`
   é o botão de ação usado em DEZENAS de formulários do sistema inteiro
   (fora das telas de login/criar conta, que sobrescrevem com o próprio
   estilo branco, ver `.auth-caixa .btn-auth`). */
.btn-auth {
  width: 100%; font: inherit; font-size: 14px; font-weight: 600; color: #fff;
  background: linear-gradient(180deg, var(--azul-claro) 0%, var(--azul) 55%, var(--azul-escuro) 100%);
  border: 0; border-radius: var(--raio-pill);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .35), 0 6px 16px rgba(7, 99, 160, .28);
  padding: 11px; cursor: pointer;
  transition: filter var(--transicao), transform var(--transicao), box-shadow var(--transicao);
  text-decoration: none; display: inline-block; text-align: center;
  margin-top: 4px;
}
.btn-auth:hover {
  filter: brightness(1.07); transform: translateY(-1px);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .4), 0 10px 26px rgba(7, 99, 160, .34);
}
.btn-auth:active { transform: translateY(1px); filter: brightness(.97); }

.auth-rodape { text-align: center; font-size: 12.5px; color: rgba(255, 255, 255, .68); margin-top: 20px; }
.auth-rodape a { font-weight: 600; color: #fff; }

/* Tela de "Bem-vindo" ao entrar (03/08) — pedido do usuário: "assim que
   clicar no login, quero que tenha um loading de BEM VINDO". Cobre a
   tela inteira assim que o formulário é enviado (login ou criar conta),
   até a próxima página (`/geral` ou o próprio login com erro) substituir
   o documento. Gradiente com as cores da marca, não o mesmo cinza-azulado
   escurecido do `#trabalhando`/`#pagina-carregando` — este é o primeiro
   contato, vale um pouco mais de personalidade. */
.boas-vindas-carregando {
  position: fixed; inset: 0; z-index: 2060;
  background: linear-gradient(160deg, var(--lateral), var(--azul-escuro));
  display: flex; align-items: center; justify-content: center;
}
.boas-vindas-carregando[hidden] { display: none; }
.boas-vindas-conteudo {
  text-align: center; color: #fff;
  animation: boas-vindas-entrar .5s cubic-bezier(.2, .8, .2, 1) backwards;
}
.boas-vindas-logo {
  width: 60px; height: 60px; object-fit: contain; margin: 0 auto 18px; display: block;
  animation: boas-vindas-pulso 1.8s ease-in-out infinite;
}
.boas-vindas-titulo { font-family: 'IBM Plex Sans', sans-serif; font-weight: 800; font-size: 21px; margin-bottom: 6px; }
.boas-vindas-sub { font-size: 13px; opacity: .8; margin-bottom: 22px; }
.boas-vindas-conteudo .girando { margin: 0 auto; border-color: rgba(255, 255, 255, .25); border-top-color: #fff; }
@keyframes boas-vindas-entrar {
  from { opacity: 0; transform: translateY(10px) scale(.97); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}
@keyframes boas-vindas-pulso {
  0%, 100% { transform: scale(1); opacity: 1; }
  50% { transform: scale(1.08); opacity: .85; }
}

/* Saudação grande pós-login (03/08) — "BEM VINDO FULANO!" bem maior que a
   tela de espera do login (`.boas-vindas-titulo`), some sozinha depois de
   ~2,6s ou no clique (`.saindo`, ver script em base.html). `pointer-events:
   none` só depois de sair — enquanto visível, cobre a tela de propósito
   (celebração rápida, não interativa por baixo até fechar). Só
   `opacity`/`transform` na animação — leve, sem custo de repintura. */
.boas-vindas-saudacao {
  position: fixed; inset: 0; z-index: 2055;
  background: linear-gradient(160deg, var(--lateral), var(--azul-escuro));
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  animation: boas-vindas-entrar .5s cubic-bezier(.2, .8, .2, 1) backwards;
}
.boas-vindas-saudacao.saindo { animation: boas-vindas-sair .45s ease both; pointer-events: none; }
@keyframes boas-vindas-sair { from { opacity: 1; } to { opacity: 0; } }
.boas-vindas-saudacao-titulo {
  font-family: 'IBM Plex Sans', sans-serif; font-weight: 800;
  font-size: clamp(30px, 6vw, 54px); line-height: 1.15; margin: 16px 0 8px;
}

/* Pop-up de Lembretes (05/08) — pedido do usuário: "quando chegar próximo
   da data e hora, a pessoa recebe um pop up, e quando chega na hora
   exata, automaticamente o pop up aparece [...] muito chamativo" (mesmo
   espírito do pedido original de 30/07). Reaproveita a estrutura de
   `.boas-vindas-saudacao` (overlay cheio de tela, mesma animação de
   entrada/saída) — DUAS variantes de cor: âmbar pra "está chegando a
   hora" (menos urgente), vermelho vivo com ícone pulsando pra "é AGORA"
   (mais urgente, cor fora da paleta de status validada de propósito —
   mesmo precedente já usado na coroa da sala "Gestores" do Chat, aqui é
   só o fundo de um alerta isolado, não um par categórico). Fica ACIMA de
   tudo (inclusive `.boas-vindas-saudacao`, 2055) — um lembrete pode
   disparar bem na hora que a pessoa loga. */
.lembrete-alerta {
  /* z-index ABAIXO do cursor customizado (2000, `.cursor-ponto`/`.cursor-
     halo`) DE PROPÓSITO — achado real (05/08, usuário: "e o mouse
     some") — diferente de `#pagina-carregando`/`.boas-vindas-saudacao`
     (que cobrem o cursor de propósito, são telas transitórias que a
     pessoa só espera passar), o alerta de lembrete é INTERATIVO (precisa
     clicar "Entendi" com precisão, pode empilhar vários em fila) — sem
     o cursor visível por cima, o mouse "sumia" (nem seta nativa — `*
     { cursor: none !important }` global —, nem a bolinha customizada,
     escondida atrás do overlay). */
  position: fixed; inset: 0; z-index: 1990;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; padding: 20px;
  animation: boas-vindas-entrar .4s cubic-bezier(.2, .8, .2, 1) backwards;
}
.lembrete-alerta.saindo { animation: boas-vindas-sair .35s ease both; pointer-events: none; }
.lembrete-alerta-antecedencia {
  background: linear-gradient(160deg, color-mix(in srgb, var(--st-standby) 85%, black 25%), color-mix(in srgb, var(--st-standby) 100%, black 8%));
}
.lembrete-alerta-hora {
  background: linear-gradient(160deg, #7a0f0f, #b81f1f);
}
.lembrete-alerta-conteudo {
  background: var(--vidro-bg-solido); backdrop-filter: var(--vidro-blur);
  -webkit-backdrop-filter: blur(20px);
  border: 1px solid var(--vidro-borda); border-radius: var(--raio-lg);
  box-shadow: 0 30px 70px rgba(0, 0, 0, .4), inset 0 1px 0 var(--vidro-realce);
  padding: 34px 38px; max-width: 440px; width: 100%; text-align: center;
  cursor: default;
}
.lembrete-alerta-icone { font-size: 44px; line-height: 1; margin-bottom: 10px; }
.lembrete-alerta-hora .lembrete-alerta-icone { animation: boas-vindas-pulso 1s ease-in-out infinite; }
.lembrete-alerta-titulo { font-family: 'IBM Plex Sans', sans-serif; font-weight: 800; font-size: 22px; color: var(--tinta); margin-bottom: 10px; }
.lembrete-alerta-texto { font-size: 16px; color: var(--tinta); font-weight: 600; margin-bottom: 6px; white-space: pre-wrap; }
.lembrete-alerta-meta { font-size: 13px; color: var(--tinta-3); margin-bottom: 18px; }
.lembrete-alerta-ok { width: auto; padding-left: 26px; padding-right: 26px; }
[data-modo-leve="1"] .lembrete-alerta-conteudo { background: var(--superficie); backdrop-filter: none; -webkit-backdrop-filter: none; }

/* ── 10. Visão geral (cartões de setor) ──────────────────────────────────── */
/* Cabeçalho "vidro" (04/08) — mesma reforma da tela de login (ver seção 9),
   aplicada aqui depois que o usuário aprovou a Opção A ("gostei muito do
   login A e a geral A também"). Gradiente FIXO (não acompanha claro/
   escuro, mesmo raciocínio do login: é a "cara" da Visão Geral, sempre a
   mesma) com as manchas de luz em `::before`/`::after` (reaproveitando as
   MESMAS animações `auth-flutuar-a/b` da seção 9 — não duplica keyframe) em
   vez de `<div>` extras no HTML, então `geral.html` não precisou de
   nenhuma mudança de estrutura pra ganhar isso. */
.boas-vindas-linha {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 16px; margin-bottom: 20px; flex-wrap: wrap;
  position: relative; overflow: hidden;
  padding: 34px 38px; border-radius: var(--raio-lg);
  background:
    radial-gradient(700px 500px at 12% 0%, rgba(59, 156, 229, .38), transparent 60%),
    radial-gradient(600px 500px at 96% 100%, rgba(7, 99, 160, .32), transparent 55%),
    linear-gradient(135deg, #0b2f4a, #0d4870 60%, #146ba3);
  box-shadow: 0 20px 50px rgba(11, 47, 74, .22);
}
.boas-vindas-linha::before, .boas-vindas-linha::after {
  content: ''; position: absolute; border-radius: 50%; filter: blur(70px);
  pointer-events: none; z-index: 0; will-change: transform;
}
.boas-vindas-linha::before { width: 320px; height: 320px; top: -130px; right: 6%; background: #58c4ff; opacity: .45; animation: auth-flutuar-a 26s ease-in-out infinite; }
.boas-vindas-linha::after { width: 240px; height: 240px; bottom: -110px; left: 3%; background: #0763a0; opacity: .4; animation: auth-flutuar-b 22s ease-in-out infinite; }
.boas-vindas { margin-bottom: 0; position: relative; z-index: 1; color: #fff; }
.boas-vindas h1 { font-size: 26px; margin-bottom: 4px; }
.boas-vindas p { color: rgba(255, 255, 255, .78); font-size: 13.5px; }
/* Lema da marca, virou nosso lema (pedido do usuário, 24/07) — cor clara
   pra se destacar em cima do gradiente escuro. */
.boas-vindas-lema { color: #bfe3ff; font-weight: 600; margin-top: 2px; }

/* Foto da pessoa + lema girando ao redor, no lado direito do cartão de
   saudação (04/08) — pedido do usuário, inspirado nos badges com brilho
   ao redor da foto do hero de directionsolucoes.com (referência real,
   capturada nesta sessão), adaptado pro tema "vidro" escuro já usado
   aqui. `startOffset`/tamanho de fonte calibrados pra encher o anel
   inteiro (~396px de circunferência num raio de 63px) sem sobrar vazio
   nem cortar a frase de um jeito feio. */
.boas-vindas-foto-anel {
  position: relative; z-index: 1; width: 132px; height: 132px; flex-shrink: 0;
}
.boas-vindas-foto-svg {
  position: absolute; inset: 0; width: 100%; height: 100%;
  animation: boas-vindas-foto-girar 30s linear infinite;
}
@keyframes boas-vindas-foto-girar { to { transform: rotate(360deg); } }
.boas-vindas-foto-texto {
  font-family: 'Inter', sans-serif; font-size: 7.6px; font-weight: 700;
  letter-spacing: .05em; text-transform: uppercase;
  fill: rgba(255, 255, 255, .58);
}
.boas-vindas-foto-img {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: 86px; height: 86px; border-radius: 50%; object-fit: cover;
  border: 3px solid rgba(255, 255, 255, .55);
  box-shadow: 0 10px 26px rgba(4, 12, 22, .35), inset 0 0 0 1px rgba(255, 255, 255, .15);
}
@media (max-width: 640px) {
  .boas-vindas-linha { padding: 26px 24px; }
  .boas-vindas h1 { font-size: 22px; }
  .boas-vindas-foto-anel { width: 92px; height: 92px; }
  .boas-vindas-foto-img { width: 60px; height: 60px; }
  .boas-vindas-foto-texto { font-size: 8.6px; }
}

/* "O que tem pra mim hoje?" (10/08, pedido do usuário) — agenda pessoal
   do dia, lista simples de linhas clicáveis (reunião/chamado/lembrete). */
.hoje-lista { display: flex; flex-direction: column; gap: 6px; margin-top: 10px; }
.hoje-item {
  display: flex; align-items: center; gap: 10px; padding: 8px 10px;
  border-radius: var(--raio-sm); background: var(--superficie-2);
  text-decoration: none; color: var(--tinta); font-size: 13px;
  transition: background var(--transicao);
}
.hoje-item:hover { background: var(--superficie-3); }
.hoje-item-hora { font-weight: 700; font-variant-numeric: tabular-nums; color: var(--azul); min-width: 40px; }

/* Participantes (Salas, 10/08, pedido do usuário: "lista suspensa pra
   economizar espaço onde podemos digitar pra encontrar") — chips
   removíveis + campo de busca com dropdown, no lugar da grade de
   checkbox com TODAS as contas do sistema. */
.participantes-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
.participantes-chips:empty { margin-bottom: 0; }
.participante-chip {
  display: flex; align-items: center; gap: 6px; background: var(--lavagem-azul);
  color: var(--azul); border-radius: var(--raio-pill); padding: 4px 6px 4px 10px;
  font-size: 12.5px; font-weight: 600;
}
.participante-chip-remover {
  display: flex; align-items: center; justify-content: center; width: 16px; height: 16px;
  border-radius: 50%; border: 0; background: rgba(7, 99, 160, .15); color: var(--azul);
  cursor: pointer; font-size: 9px; line-height: 1; flex-shrink: 0;
}
.participante-chip-remover:hover { background: var(--azul); color: #fff; }
.participantes-dropdown {
  position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 20;
  background: var(--superficie); border: 1px solid var(--borda); border-radius: var(--raio-sm);
  box-shadow: var(--sombra-3); max-height: 220px; overflow-y: auto; padding: 4px;
}
.participantes-dropdown-item {
  display: block; width: 100%; text-align: left; padding: 7px 10px; border-radius: var(--raio-sm);
  border: 0; background: none; color: var(--tinta); font-size: 13px; cursor: pointer;
}
.participantes-dropdown-item:hover { background: var(--superficie-2); }

/* Avisos do dia (DDS + ASO agendado) — faixa de largura TOTAL, estilo
   letreiro de estação (31/07, pedido do usuário: antes era uma coluna
   fixa flutuando ao lado do "bom dia", que ficava vazia sem nenhum aviso
   e disputava espaço com o card de campanha do RH quando ativo). Um botão
   fixo abre o detalhe completo em modal (reaproveita .dds-aviso, .modal-
   fundo/.modal-caixa já existentes); o miolo rola sozinho em loop. */
.avisos-ticker {
  display: flex; align-items: stretch; margin-bottom: 20px;
  border: 1px solid var(--st-standby); border-radius: var(--raio);
  background: var(--lavagem-ambar); overflow: hidden;
}
.avisos-ticker-botao {
  display: flex; align-items: center; gap: 7px; flex-shrink: 0;
  border: 0; border-right: 1px solid var(--st-standby); background: transparent;
  color: var(--tinta); font: inherit; font-weight: 600; font-size: 12.5px;
  padding: 10px 14px; cursor: pointer; white-space: nowrap;
}
.avisos-ticker-botao:hover { background: rgba(0, 0, 0, .05); }
.avisos-ticker-botao svg { flex-shrink: 0; }
.avisos-ticker-contagem {
  background: var(--st-standby); color: #fff; border-radius: 999px;
  font-size: 10.5px; font-weight: 700; padding: 1px 6px; line-height: 1.4;
}
.avisos-ticker-viewport {
  flex: 1; overflow: hidden; position: relative; display: flex; align-items: center;
  min-width: 0;
}
/* Pausa o loop ao passar o mouse — pra quem quiser ler com calma sem
   precisar abrir o modal. */
.avisos-ticker-viewport:hover .avisos-ticker-trilho { animation-play-state: paused; }
.avisos-ticker-trilho {
  display: flex; align-items: center; gap: 40px; white-space: nowrap;
  padding-left: 24px; animation-name: avisos-rolar; animation-timing-function: linear;
  animation-iteration-count: infinite;
}
@keyframes avisos-rolar {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}
.avisos-ticker-item { display: inline-flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--tinta-2); }
.avisos-ticker-item strong { color: var(--tinta); }
.avisos-ticker-item.aviso-hoje strong { color: var(--st-critico); }
.avisos-ticker-foto {
  width: 20px; height: 20px; border-radius: 50%; object-fit: cover;
  flex-shrink: 0; border: 1px solid var(--borda);
}
.avisos-ticker-iniciais {
  width: 20px; height: 20px; border-radius: 50%; flex-shrink: 0;
  background: var(--azul); color: #fff; display: flex; align-items: center;
  justify-content: center; font-size: 7.5px; font-weight: 700;
  font-family: 'Syne', sans-serif;
}
@media (max-width: 860px) {
  .avisos-ticker-rotulo { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .avisos-ticker-trilho { animation: none; }
  .avisos-ticker-viewport { overflow-x: auto; }
}
/* Modo leve (04/08) — mesmo tratamento acima, mas fora do `@media`: a
   regra geral `:root[data-modo-leve="1"] * { animation-duration: .01ms
   !important; }` (ver mais abaixo) atropelava a duração PRÓPRIA do
   letreiro (calculada em `geral.html`, `total_avisos * 9`s, via `style=`
   inline) — resultado: o letreiro girava rápido demais em vez de sumir
   (achado real, reportado pelo usuário testando ao vivo). `animation:
   none` aqui tem mais especificidade que a duração inline, então some
   igual ao caso de `prefers-reduced-motion`. */
:root[data-modo-leve="1"] .avisos-ticker-trilho { animation: none; }
:root[data-modo-leve="1"] .avisos-ticker-viewport { overflow-x: auto; }

/* Scroller de KPIs do PDI (06/08) — "onde melhoramos/pioramos" entre os 2
   últimos trimestres, passando na tela do dashboard e do perfil individual.
   Mesmo mecanismo de rolagem do `.avisos-ticker` (reaproveita o MESMO
   `@keyframes avisos-rolar` já definido acima), só neutro (não é alerta) —
   cada item se colore sozinho por melhorou/piorou. */
.kpi-ticker {
  display: flex; align-items: stretch; margin-bottom: 20px;
  border: 1px solid var(--borda); border-radius: var(--raio);
  background: var(--superficie-2); overflow: hidden;
}
.kpi-ticker-viewport {
  flex: 1; overflow: hidden; position: relative; display: flex; align-items: center;
  min-width: 0;
}
.kpi-ticker-viewport:hover .kpi-ticker-trilho { animation-play-state: paused; }
.kpi-ticker-trilho {
  display: flex; align-items: center; gap: 40px; white-space: nowrap;
  padding: 11px 24px; animation-name: avisos-rolar; animation-timing-function: linear;
  animation-iteration-count: infinite;
}
.kpi-ticker-item { display: inline-flex; align-items: center; gap: 7px; font-size: 12.5px; color: var(--tinta-2); }
.kpi-ticker-item strong { color: var(--tinta); }
.kpi-ticker-item.melhorou .kpi-ticker-seta { color: var(--st-concluido); }
.kpi-ticker-item.piorou .kpi-ticker-seta { color: var(--st-critico); }
.kpi-ticker-seta { font-weight: 700; font-size: 13px; }
@media (prefers-reduced-motion: reduce) {
  .kpi-ticker-trilho { animation: none; }
  .kpi-ticker-viewport { overflow-x: auto; }
}
:root[data-modo-leve="1"] .kpi-ticker-trilho { animation: none; }
:root[data-modo-leve="1"] .kpi-ticker-viewport { overflow-x: auto; }

/* Velocímetro (06/08) — mesmo meio-círculo do Modo TV (`.tv-gauge-svg`),
   versão pra tela normal (light/dark do sistema, não o fundo escuro fixo
   da TV). Usado no dashboard de PDI e no perfil individual, um por
   trimestre recente. */
.velocimetros-linha { display: flex; gap: 20px; flex-wrap: wrap; justify-content: center; padding: 6px 0; }
.velocimetro { display: flex; flex-direction: column; align-items: center; gap: 2px; }
.velocimetro-num {
  font-family: 'Syne', sans-serif; font-size: 22px; font-weight: 700; fill: var(--tinta);
}
.velocimetro-rotulo { font-size: 12px; color: var(--tinta-2); font-weight: 600; }
.velocimetro-seta { font-weight: 700; }
.velocimetro-seta.melhorou { color: var(--st-concluido); }
.velocimetro-seta.piorou { color: var(--st-critico); }

/* Aviso de ASO agendado pra hoje (24/07) — mesmo componente visual do
   aviso do DDS (mesma classe .dds-aviso, mesmo tamanho de "foto"). Hoje
   usado só dentro do modal de detalhe da faixa de avisos acima (31/07;
   antes ficava direto na tela, ver comentário de cima). Cor âmbar/atenção,
   igual ao DDS em dia comum. */
.dds-aviso-iniciais {
  width: 34px; height: 34px; border-radius: 50%; flex-shrink: 0;
  background: var(--azul); color: #fff; display: flex; align-items: center;
  justify-content: center; font-size: 9.5px; font-weight: 700;
  font-family: 'Syne', sans-serif; border: 1px solid var(--borda);
}

/* Aviso do DDS (Diário de Segurança) — discreto, mas com cor de atenção
   pra chamar o olho sem competir com os cards de setor (pedido do
   usuário: sutil, mas que "chame atenção mesmo sendo sutil"). Vira
   vermelho no próprio dia do DDS, em vez de âmbar o tempo todo. */
.dds-aviso {
  display: flex; align-items: center; gap: 10px; max-width: 340px;
  background: var(--lavagem-ambar); border: 1px solid var(--st-standby);
  border-radius: var(--raio); padding: 9px 14px; font-size: 12.5px;
  color: var(--tinta-2); line-height: 1.45;
}
.dds-aviso-hoje { background: var(--lavagem-vermelho); border-color: var(--st-critico); }
.dds-aviso-foto {
  width: 34px; height: 34px; border-radius: 50%; object-fit: cover;
  flex-shrink: 0; border: 1px solid var(--borda);
}
.dds-aviso strong { color: var(--tinta); }

/* Destaque do aniversariante do dia — diferente do DDS de propósito: aqui é
   celebração, não alerta, então usa a cor "verde" da marca em vez de âmbar/
   vermelho. Virou um bloco PRÓPRIO, de largura cheia, abaixo da linha de
   saudação/DDS (não mais espremido ao lado do aviso do DDS) — pedido do
   usuário (21/07, 2ª revisão): "a foto de aniversário tem que ficar bem
   maior... pode deixar bem destaque mesmo", porque tem texto escrito
   junto e precisa ler bem de longe. */
.aniversario-destaque {
  display: flex; align-items: center; gap: 18px;
  background: var(--lavagem-verde); border: 1px solid var(--verde);
  border-radius: var(--raio-lg); padding: 16px 22px; margin-bottom: 16px;
  color: var(--tinta-2);
}
.aniversario-destaque-foto {
  width: 76px; height: 76px; border-radius: 50%; object-fit: cover;
  flex-shrink: 0; border: 3px solid var(--verde);
}
.aniversario-destaque-texto { font-size: 19px; line-height: 1.4; }
.aniversario-destaque-texto strong { color: var(--tinta); }

/* Aniversário de EMPRESA (tempo de casa, +1 ano) — pedido do usuário
   (29/07), mesmo molde do aniversário de nascimento acima, só sem foto
   (não faz sentido buscar foto do ClickUp aqui) e em azul pra diferenciar
   visualmente dos dois cartões um do lado do outro. */
.tempo-empresa-destaque {
  display: flex; align-items: center; gap: 12px;
  background: var(--lavagem-azul); border: 1px solid var(--azul);
  border-radius: var(--raio-lg); padding: 14px 22px; margin-bottom: 16px;
  color: var(--tinta-2);
}
.tempo-empresa-destaque-texto { font-size: 17px; line-height: 1.4; }
.tempo-empresa-destaque-texto strong { color: var(--tinta); }

/* Anúncio/aviso publicado pelo admin (pedido do usuário, 22/07: "essas
   coisas que o clickup tem") — banner dispensável, um por anúncio ativo,
   empilhados acima das campanhas/aniversariante. */
.anuncio-aviso {
  display: flex; align-items: flex-start; gap: 14px;
  background: var(--lavagem-azul); border: 1px solid var(--azul);
  border-radius: var(--raio-lg); padding: 14px 16px; margin-bottom: 12px;
}
/* Anúncio marcado como URGENTE (18/08, pedido do usuário: "é pra ficar
   esse quadrado vermelho") — mesma cor de destaque já validada
   (--st-critico/--lavagem-vermelho), reaproveitada de `.dds-aviso-hoje`. */
.anuncio-aviso-urgente { background: var(--lavagem-vermelho); border-color: var(--st-critico); }
/* `>` (filho direto), não descendente — o `<strong>` do TÍTULO é filho
   direto de `.anuncio-aviso-corpo` (ver geral.html), mas depois do texto
   ganhar negrito/itálico (18/08) o corpo passou a ter MUITO mais
   `<strong>`/`<em>` espalhados dentro de `.texto-formatado p` — com
   seletor descendente (sem `>`), essa regra pegava TODO `<strong>` do
   aviso, não só o título: cada palavra em negrito no texto virava bloco
   (`display: block`, quebrava linha sozinha) com fonte maior — bug real
   relatado pelo usuário ("não ficou muito legal... ficou os textos
   quebrados" / "deixe tudo no mesmo tamanho de fonte, do texto
   principal"). Com `>`, só o título é afetado; negrito/itálico dentro
   do corpo usam o `<strong>`/`<em>` cru do navegador (inline, mesmo
   tamanho do texto ao redor — sem CSS nenhum, é o comportamento certo). */
.anuncio-aviso-urgente .anuncio-aviso-corpo > strong { color: var(--st-critico); }
.anuncio-aviso-corpo > strong { display: block; color: var(--tinta); font-size: 14.5px; margin-bottom: 3px; }
.anuncio-aviso-corpo .texto-formatado p { color: var(--tinta-2); font-size: 13px; line-height: 1.5; margin: 0; }
.anuncio-aviso-corpo .texto-formatado p + p { margin-top: 8px; }
/* Anexo do anúncio (23/07) — geralmente cartaz de vaga pra divulgar. Link
   abre numa aba nova (`target="_blank"`, back-end serve com
   `Content-Disposition: inline`) — imagem/PDF já renderiza direto ali; a
   pessoa baixa depois só se quiser, pela própria opção do navegador
   (pedido do usuário, revisado no mesmo dia: "abre primeiro, depois a
   pessoa escolhe se quer baixar" — trocado do comportamento anterior, que
   baixava direto ao clicar). */
.anuncio-aviso-anexos { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.anuncio-aviso-anexo {
  display: inline-flex; align-items: center; gap: 5px; font-size: 12px; font-weight: 600;
  color: var(--azul); background: var(--superficie); border: 1px solid var(--borda);
  border-radius: var(--raio-sm); padding: 4px 9px; text-decoration: none;
  transition: background var(--transicao);
}
.anuncio-aviso-anexo:hover { background: var(--superficie-2); }
.anuncio-aviso-fechar {
  background: none; border: 0; cursor: pointer; color: var(--tinta-3);
  font-size: 14px; line-height: 1; padding: 2px 4px; margin-left: auto; flex-shrink: 0;
}
.anuncio-aviso-fechar:hover { color: var(--tinta); }

/* Ações gerais do mês com anexo (ex.: cartaz do Julho Amarelo registrado
   em Registro de Ações) — pedido do usuário (22/07): "quero que as ações
   do mês fique exibindo o anexo na visão geral". Cards em grade, cada um
   com a imagem (ou um link de arquivo, se o anexo não for imagem) e o
   nome da ação embaixo. */
.acao-mes-lista {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
  gap: 12px; margin-bottom: 18px; max-width: 640px;
}
.acao-mes-card {
  background: var(--superficie-3); border-radius: var(--raio-lg);
  overflow: hidden; border: 1px solid var(--borda);
}
.acao-mes-imagem {
  width: 100%; height: 130px; object-fit: contain; display: block;
  cursor: zoom-in; background: var(--superficie-2);
}

/* Lightbox da "arte completa" — pedido do usuário (22/07): "quero que
   quando clique, abra a arte completa" + "aí depois a pessoa fecha". */
.lightbox-fundo {
  display: none; position: fixed; inset: 0; background: rgba(0,0,0,.85);
  z-index: 999; align-items: center; justify-content: center; padding: 32px;
}
.lightbox-fundo.aberto { display: flex; }
.lightbox-imagem { max-width: 90vw; max-height: 90vh; border-radius: 8px; box-shadow: 0 8px 40px rgba(0,0,0,.5); }
.lightbox-fechar {
  position: absolute; top: 18px; right: 24px; background: none; border: 0;
  color: #fff; font-size: 30px; line-height: 1; cursor: pointer; padding: 6px;
}
.lightbox-fechar:hover { color: rgba(255,255,255,.7); }
.acao-mes-arquivo {
  display: flex; align-items: center; gap: 6px; padding: 24px 14px;
  color: var(--azul); font-size: 13px; text-decoration: none; font-weight: 600;
}
.acao-mes-titulo { padding: 8px 12px; font-size: 12.5px; color: var(--tinta-2); font-weight: 600; }

/* Campanha do RH em destaque (Julho Amarelo etc.) — pedido do usuário
   (22/07): "essa ação tem que ficar em destaque mesmo, bem grande". Banner
   de largura cheia, bem maior que o aviso de DDS/aniversário de propósito
   (é arte gráfica do time de criativos, precisa de espaço pra respirar).
   Com 2+ campanhas ativas ao mesmo tempo vira carrossel (JS no próprio
   geral.html), trocando sozinho a cada ~5s. */
.campanha-rh-carrossel {
  position: relative; width: 100%; height: clamp(180px, 26vw, 360px);
  border-radius: var(--raio-lg); overflow: hidden; margin-bottom: 18px;
  background: var(--superficie-3);
}
/* Ao lado de Veículo/Salas (pedido do usuário, 23/07) a campanha divide
   a grade com uma coluna de dois cards empilhados — usa a altura da
   própria célula da grade (esticada por align-items: stretch no
   geral.html) em vez do clamp em vw pensado pra largura cheia, senão
   ficaria alta e estreita demais fora de proporção. */
/* 27/08, pedido do usuário: "as campanhas do lado direito tem um gap muito
   grande em cima e embaixo... ocupando muito espaço" — vinha esticando
   até a altura da coluna vizinha (`height: 100%`, `align-items: stretch`
   do `.geral-topo`), bem mais alta que a arte retrato precisa (`contain`
   sobra vazio nas pontas quando a caixa é mais alta que o proporcional).
   `align-self: start` tira esse card da esticada automática — agora ele
   só ocupa a altura que a própria arte (`aspect-ratio` do pôster, ~A4)
   pede, sem sobra à toa. */
.campanha-rh-carrossel-lateral { height: auto; aspect-ratio: 1131 / 1600; max-height: 420px; align-self: start; margin-bottom: 0; }
.campanha-rh-slide { position: absolute; inset: 0; opacity: 0; transition: opacity .5s ease; }
.campanha-rh-slide.ativo { opacity: 1; }
/* `contain`, não `cover` (pedido do usuário, 30/07) — a arte que o RH sobe
   é um cartaz RETRATO (ex.: 1131×1600, formato A4), bem mais alto que
   largo, mas o espaço reservado aqui é PAISAGEM (mais largo que alto,
   ver `.campanha-rh-carrossel-lateral`) — com `cover` o cartaz inteiro
   nunca cabia, cortava título em cima e a logo/rodapé embaixo. `contain`
   sempre mostra o cartaz inteiro; sobra um respiro vazio nas laterais
   (preenchido pelo `background` de `.campanha-rh-carrossel`), preferível
   a perder conteúdo da arte. */
.campanha-rh-slide img { width: 100%; height: 100%; object-fit: contain; display: block; }
.campanha-rh-pontos {
  position: absolute; bottom: 12px; left: 50%; transform: translateX(-50%);
  display: flex; gap: 7px; z-index: 2;
}
.campanha-rh-ponto {
  width: 9px; height: 9px; border-radius: 50%; border: none; padding: 0;
  background: rgba(255,255,255,.5); cursor: pointer; transition: background .2s;
}
.campanha-rh-ponto.ativo { background: #fff; }

/* Chat interno — pedido do usuário (22/07): "o clickup chegou ao limite de
   mensagens, preciso de um chat no sistema". Layout de duas colunas (lista
   de salas + conversa), sem framework, mesmo espírito do resto do app.
   Altura calculada direto do viewport (`calc(100vh - Npx)`), NÃO com
   flexbox esticando `.pagina`/`.conteudo`/`.app` até o fundo — tentei essa
   via (23/07) e quebrou o scroll INTERNO da lista de mensagens (`.app` só
   tem `min-height: 100vh`, não é um teto de verdade; sem uma altura
   travada em algum ponto da cadeia, `.chat-mensagens` parava de conter o
   próprio scroll e a PÁGINA INTEIRA passava a rolar, arrastando a caixa
   de digitar mensagem junto — bug relatado pelo usuário). `calc(100vh -
   Npx)` evita esse problema de vez: calcula um valor absoluto direto do
   viewport, sem depender de nenhum ancestral propagar altura certinho. */
/* `225px` RECALIBRADO pra `140px` (26/08, "no chat tem um gap muito
   grande de espaço na parte inferior da tela") — consequência direta do
   cabeçalho compacto (`.topo-compacto`, ver base.html; só o Chat usa por
   enquanto). O `225px` antigo cobria o PIOR caso do cabeçalho GRANDE
   (título+subtítulo+busca global, podendo quebrar em 2 linhas — 141px)
   + 78px de `.pagina`. Com o cabeçalho compacto, o Chat perdeu
   título/subtítulo/busca — sobra só 1 linha enxuta (~40px de altura +
   12px de padding + 1px de borda ≈ 53px), e sem texto nenhum pra
   quebrar, nunca mais vira 2 linhas. `53 + 78 (.pagina) ≈ 131px`;
   `140px` é esse número com uma margem pequena, mesmo espírito do valor
   antigo. `.chat-shell` é exclusiva do Chat (conferido) — se outra tela
   um dia ganhar cabeçalho compacto, esse número aqui não afeta ela. */
.chat-shell { display: flex; gap: 18px; height: calc(100vh - 140px); min-height: 440px; }
/* Rodapé (texto + copyright, ver base.html) escondido só nesta tela —
   pedido do usuário (23/07), o chat já ocupa a tela inteira sozinho, não
   tem função nenhuma ali embaixo. `~` (irmão geral, não só o imediato)
   porque pode haver `<script>` do chat entre os dois. O `170px` original
   já era o valor SEM o rodapé (era `240px` quando o rodapé ainda
   aparecia). Se um dia sobrar/faltar um pouco de espaço aqui, ajustar
   esse número direto, não reintroduzir o esquema de flexbox acima.

   RECALIBRADO pra `225px` (17/08, bug real reportado pelo usuário: "eu
   consigo scrollar uma parte que não deveria ser scrollável... existe a
   rolagem do chat, dos contatos e da tela geral" — a PÁGINA inteira
   ganhava um scroll indevido, além dos scrolls internos de verdade). O
   `170px` datava de 23/07 e nunca foi revisto depois da busca global
   (08/08, `.busca-global-caixa` em TODA tela) — em telas mais estreitas
   (~1024-1085px) a barra de busca empurra `.topo-linha` pra QUEBRAR em 2
   linhas, o `.topo` passa de 67px pra ~141px, e o resto da conta
   (`.pagina` tem `padding: 22px ... 56px`, 78px fixos de sobra vertical)
   nunca cresceu junto — sobrando 30 a 49px de conteúdo além da viewport
   em telas de laptop comuns (confirmado medindo com Playwright real,
   sessão via cookie assinado, sem tocar em dado nenhum: 1920×1080 cabia
   certinho, 1440×900/1280×800 vazavam 30px, 1024×768 vazava 49px).
   `225px` cobre o pior caso medido (topo em 2 linhas, 141px + 78px de
   `.pagina` = 219px) com uma margem pequena. Ainda é um número fixo, não
   dinâmico — se o topo ganhar MAIS altura no futuro (3ª linha de busca,
   novo aviso fixo etc.), vai precisar subir de novo; não tem como esse
   `calc(100vh - Npx)` se auto-ajustar sem JS medindo o topo de verdade
   (trade-off aceito aqui, mesmo espírito de manter simples). */
.chat-shell ~ .rodape { display: none; }
.chat-salas {
  width: 250px; flex-shrink: 0; display: flex; flex-direction: column; min-height: 0;
  border-right: 1px solid var(--borda); padding-right: 12px;
}
/* Busca de conversa — pedido do usuário (22/07): "nas conversas coloque
   um text box pra a gente pesquisar as conversas". */
.chat-busca-linha { display: flex; align-items: center; gap: 6px; margin-bottom: 10px; flex-shrink: 0; }
.chat-busca-salas {
  width: 100%; padding: 7px 10px; border-radius: 999px;
  border: 1px solid var(--borda); background: var(--superficie-2); color: var(--tinta);
  font: inherit; font-size: 12.5px;
}
.chat-busca-salas:focus { outline: none; border-color: var(--azul); }
/* Marcar tudo como lido — pedido do usuário (22/07): "ao clicar no chat
   tem que ter uma opção em algum lugar de 'marcar como lido tudo'". */
.chat-marcar-tudo-bt {
  width: 30px; height: 30px; flex-shrink: 0; border-radius: 50%; border: 1px solid var(--borda);
  background: var(--superficie-2); color: var(--tinta-2); font-size: 12px; cursor: pointer;
  transition: background var(--transicao);
}
.chat-marcar-tudo-bt:hover { background: var(--superficie-3); color: var(--azul); }
#chat-lista-salas { flex: 1; min-height: 0; overflow-y: auto; }
/* Cada grupo (Setores/Gestores/Conversas) é um <details> — pedido do
   usuário (22/07): "quero que os setores no chat possa expandir e
   retrair". Empurra o conteúdo abaixo ao fechar (diferente do menu
   principal, que flutua por cima) — faz mais sentido aqui, é uma lista
   comprida, não um menu compacto. */
.chat-grupo { margin-top: 14px; }
.chat-grupo:first-child { margin-top: 0; }
.chat-grupo-titulo {
  display: flex; align-items: center; gap: 6px; cursor: pointer; list-style: none;
  font-size: 11px; text-transform: uppercase; letter-spacing: .05em;
  color: var(--tinta-3); margin: 0 0 6px; font-weight: 700; padding: 2px 0;
}
.chat-grupo-titulo::-webkit-details-marker { display: none; }
.chat-grupo-titulo::after { content: '⌄'; font-size: 10px; opacity: .6; transition: transform var(--transicao); margin-left: auto; }
.chat-grupo[open] > .chat-grupo-titulo::after { transform: rotate(180deg); }
.chat-sala-item {
  display: flex; align-items: center; gap: 8px; padding: 8px 10px; border-radius: var(--raio);
  text-decoration: none; color: var(--tinta-2); font-size: 13.5px; margin-bottom: 2px;
}
.chat-sala-item:hover { background: var(--superficie-3); }
.chat-sala-item.ativa { background: var(--azul); color: #fff; }
.chat-sala-avatar { width: 34px; height: 34px; border-radius: 50%; object-fit: cover; flex-shrink: 0; }

/* Bolinha de status (24/07, pedido do usuário: "botar uma bolinha de
   online no chat... pra quem estiver online no sistema aparece", depois
   "quem tiver offline fique com a bolinha cinza" — SEMPRE visível). Ganhou
   um 3º estágio (31/07, "inserir nos status offline ausente ou online") e
   um 4º (03/08, "tem que ter o ocupado, que é um vermelho bem forte") —
   cinza (offline, padrão), âmbar (ausente), vermelho forte (ocupado,
   reaproveita `--st-critico` — mesma cor já usada em NOK/crítico no resto
   do sistema, nenhum hex novo) ou verde (online de verdade). Só existe em
   avatar de PESSOA (colegas/DM), nunca em sala de setor/gestores.
   `.chat-avatar-envolt` é só um wrapper posicionador (não muda tamanho/
   layout do avatar em si, `display:inline-flex` acompanha o tamanho do
   filho); a cor troca conforme `.chat-presenca-*` (renderizado já certo
   no 1º carregamento pelo servidor, e atualizada depois pelo JS que já
   faz o polling de não-lidas a cada 45s — ver base.html). */
.chat-avatar-envolt { position: relative; display: inline-flex; flex-shrink: 0; }
.chat-online-dot {
  display: block; position: absolute; right: -1px; bottom: -1px;
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--tinta-3); border: 2px solid var(--superficie);
}
.chat-online-dot.chat-presenca-online { background: var(--st-concluido); }
.chat-online-dot.chat-presenca-ocupado { background: var(--st-critico); }
/* "Ausente" virou luazinha amarela, não mais bolinha marrom (26/08,
   pedido do usuário: "queria que o ausente em vez de ficar uma bola
   marrom, ficasse uma luazinha AMARELA") — `--st-standby` (usado antes
   aqui) É de fato marrom no tema claro (mesmo problema já corrigido no
   indicador do Veículo, ver `--st-lavagem`), então trocar só de cor não
   bastava, o pedido foi mudar pro GLIFO 🌙 mesmo (que já é amarelo por
   natureza, nenhuma cor nova pra validar). Maior que o ponto normal
   (precisa caber o emoji), mesmo tratamento de `.chat-presenca-juridico`
   logo abaixo — `content` em vez de emoji direto no HTML porque aqui é
   sempre a MESMA imagem pros 4 estados (online/ausente/ocupado/offline
   compartilham a mesma linha no template, só troca a classe). */
.chat-online-dot.chat-presenca-ausente {
  width: 14px; height: 14px; right: -3px; bottom: -3px;
  background: var(--superficie); font-size: 10px; line-height: 1;
  display: flex; align-items: center; justify-content: center;
}
.chat-online-dot.chat-presenca-ausente::before { content: '🌙'; }
.chat-conversa-avatar .chat-online-dot.chat-presenca-ausente { width: 12px; height: 12px; font-size: 8.5px; right: -2px; bottom: -2px; }
.chat-conversa-avatar .chat-online-dot { width: 9px; height: 9px; }

/* Selo jurídico (05/08) — pedido do usuário: "quando danilo estiver em
   ações externas mude a bolinha do perfil dele para um simbolo
   juridico". Maior que o ponto normal de presença (precisa caber o
   glifo ⚖, não é só uma cor) — `--st-afastado` (roxo, já validado pra
   "afastado" no cadastro de colaboradores) reaproveitado aqui: mesma
   ideia semântica de "longe por um motivo formal", nenhuma cor nova. */
.chat-online-dot.chat-presenca-juridico {
  width: 16px; height: 16px; right: -4px; bottom: -4px;
  font-style: normal; font-size: 11px; line-height: 1;
  display: flex; align-items: center; justify-content: center;
  background: var(--st-afastado);
}
.chat-conversa-avatar .chat-online-dot.chat-presenca-juridico { width: 14px; height: 14px; font-size: 9px; right: -3px; bottom: -3px; }

/* Selo de "Humor do dia" (28/07) — mesmo espírito da bolinha de online,
   só no canto OPOSTO (superior-esquerdo) pra não disputar espaço com ela;
   só aparece pra quem registrou o humor HOJE (`humor.todos_hoje()`), sem
   selo nenhum pra quem não registrou — nunca um emoji neutro "por padrão"
   à toa. Estilo diferente do CSS: dot são um ponto de cor, humor é o
   emoji de verdade (`font-style: normal` porque `<i>` normalmente vem
   itálico). */
.chat-humor-selo {
  display: block; position: absolute; left: -3px; top: -3px;
  font-style: normal; font-size: 13px; line-height: 1;
  background: var(--superficie); border-radius: 50%;
  width: 16px; height: 16px; text-align: center;
}
.chat-conversa-avatar .chat-humor-selo { font-size: 11px; width: 13px; height: 13px; }
.chat-sala-avatar-grupo {
  display: flex; align-items: center; justify-content: center; background: var(--superficie-3);
  font-size: 14px;
}
.chat-sala-item.ativa .chat-sala-avatar-grupo { background: rgba(255,255,255,.2) !important; }
/* Sala "Gestores" — pedido do usuário (22/07): "coloca uma coroa e um
   background vermelho para chamar atenção como se fosse a foto do grupo",
   depois refinado pra "vermelhão mesmo, tipo #ff0000" — vermelho vivo
   deliberadamente FORA da paleta de status (é só o fundo de um emblema
   isolado, sempre com ícone branco por cima, não precisa do validador). */
.chat-sala-avatar-gestores {
  display: flex; align-items: center; justify-content: center; background: #e8262f;
  font-size: 15px;
}

/* Sala "Recepção" (28/07, pedido do usuário: "criar um chat com todos da
   empresa chamado RECEPÇÃO") — laranja vivo, mesmo raciocínio de Gestores
   acima: cor decorativa isolada só desse emblema, fora da paleta de status
   validada de propósito, escolhida só pra ficar visualmente distinta das
   cores já usadas em `CORES_SETOR` (chat.html). */
.chat-sala-avatar-recepcao {
  display: flex; align-items: center; justify-content: center; background: #e8720c;
}

/* Arquivar/Silenciar por conversa — pedido do usuário (22/07): "opção de
   arquivar grupo e silenciar mensagem também". */
.chat-sala-mudo { font-size: 11px; opacity: .7; }
.chat-sala-silenciada .chat-sala-preview { opacity: .65; }
.chat-sala-menu { position: relative; flex-shrink: 0; align-self: flex-start; margin-top: 2px; }
.chat-sala-menu-bt {
  background: none; border: 0; cursor: pointer; font-size: 14px; line-height: 1;
  color: var(--tinta-3); opacity: 0; padding: 2px 4px; border-radius: 4px; transition: opacity var(--transicao), background var(--transicao);
}
.chat-sala-item:hover .chat-sala-menu-bt, .chat-sala-menu.aberto .chat-sala-menu-bt { opacity: .7; }
.chat-sala-menu-bt:hover { opacity: 1 !important; background: rgba(0,0,0,.08); }
.chat-sala-item.ativa .chat-sala-menu-bt { color: rgba(255,255,255,.85); }
.chat-sala-menu-lista {
  display: none; position: absolute; top: calc(100% + 2px); right: 0; min-width: 130px;
  background: var(--superficie-2); border-radius: 8px; box-shadow: var(--sombra-2); overflow: hidden; z-index: 6;
}
.chat-sala-menu.aberto .chat-sala-menu-lista { display: block; }
.chat-sala-menu-item {
  display: block; width: 100%; text-align: left; background: none; border: 0; cursor: pointer;
  padding: 8px 12px; font-size: 12.5px; color: var(--tinta); white-space: nowrap;
}
.chat-sala-menu-item:hover { background: var(--superficie-3); }
.chat-sala-corpo { flex: 1; min-width: 0; }
.chat-sala-linha1 { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.chat-sala-nome { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chat-sala-hora { font-size: 10.5px; color: var(--tinta-3); flex-shrink: 0; }
.chat-sala-item.ativa .chat-sala-hora { color: rgba(255,255,255,.75); }
.chat-sala-linha2 { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: 2px; }
.chat-sala-preview {
  font-size: 12px; color: var(--tinta-3); overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; flex: 1; min-width: 0;
}
.chat-sala-preview-vazio { font-style: italic; }
.chat-sala-item.ativa .chat-sala-preview { color: rgba(255,255,255,.75); }
.chat-badge {
  background: var(--azul); color: #fff; font-size: 11px; font-weight: 700;
  border-radius: 999px; padding: 1px 7px; min-width: 18px; text-align: center;
  line-height: 1.5; flex-shrink: 0;
}
.chat-sala-item.ativa .chat-badge { background: rgba(255,255,255,.3); }
.chat-badge-mencao { background: var(--st-critico) !important; }

.chat-conversa { flex: 1; display: flex; flex-direction: column; min-width: 0; min-height: 0; }

/* Resumo de humor da equipe (10/08) — só aparece ANTES de abrir uma
   conversa (pedido do usuário: "antes de abrir conversa com alguém
   quero que mostre a quantidade de pessoas que tem por humor"). Centraliza
   junto com o "Selecione uma conversa ao lado." de sempre. */
.chat-humor-resumo-tela {
  flex: 1; display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: 22px; padding: 24px;
}
.chat-humor-resumo { text-align: center; }
.chat-humor-resumo-titulo { font-size: 13px; font-weight: 700; color: var(--tinta-2); margin: 0 0 14px; }
.chat-humor-resumo-linha { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; }
.chat-humor-resumo-item {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  background: var(--vidro-bg-solido); border: 1px solid var(--borda-2);
  border-radius: var(--raio); padding: 10px 16px; min-width: 64px;
}
.chat-humor-resumo-emoji { font-size: 24px; line-height: 1; }
.chat-humor-resumo-qtd { font-family: 'Syne', sans-serif; font-size: 18px; font-weight: 700; color: var(--tinta); }
.chat-humor-resumo-rotulo { font-size: 10.5px; color: var(--tinta-3); }
/* Cabeçalho da conversa (nome + foto + voltar) — pedido do usuário (23/07):
   "tem que seguir os padrões do whatsapp para fazer o chat mobile". O botão
   voltar só aparece dentro do media query mobile (ver abaixo); em telas
   largas a lista já fica sempre visível ao lado, não precisa de volta. */
.chat-conversa-cabecalho {
  display: flex; align-items: center; gap: 10px; flex-shrink: 0;
  padding-bottom: 12px; margin-bottom: 10px; border-bottom: 1px solid var(--borda);
}
.chat-conversa-voltar {
  display: none; align-items: center; justify-content: center; flex-shrink: 0;
  width: 32px; height: 32px; border-radius: 50%; border: 0; background: none;
  color: var(--tinta-2); cursor: pointer; transition: background var(--transicao);
}
.chat-conversa-voltar:hover { background: var(--superficie-3); }
.chat-conversa-avatar .chat-sala-avatar { width: 32px; height: 32px; }
/* `flex: 1; min-width: 0;` (25/08, achado revisando o celular: sem isso,
   um flex item com `white-space: nowrap` não encolhe abaixo do próprio
   conteúdo — `min-width` implícito é `auto`, não `0` — então o texto
   NUNCA truncava de verdade, só "prometia" com `text-overflow: ellipsis`;
   um nome de grupo/contato mais comprido empurrava o botão de busca pra
   fora da tela em vez de cortar com "…", exatamente o tipo de "fora de
   enquadramento" que aparece só em nome longo + tela estreita). */
.chat-conversa-nome { flex: 1; min-width: 0; font-weight: 700; font-size: 14.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Mensagem fixada no topo da sala (10/08, pedido do usuário) — faixa fina
   entre o cabeçalho da conversa e a lista de mensagens, mesmo espírito de
   "pin" do WhatsApp/Telegram: estado da SALA (visível pra qualquer um que
   acessa ela), não uma preferência por pessoa. `[hidden]` explícito porque
   `.chat-fixada` já define `display: flex` — mesma classe de bug de
   especificidade já documentada em outros `[hidden]` do sistema. */
.chat-fixada {
  display: flex; align-items: center; gap: 8px; flex-shrink: 0;
  padding: 7px 10px; margin-bottom: 8px; border-radius: var(--raio-sm);
  background: var(--lavagem-azul); border: 1px solid var(--azul-claro);
}
.chat-fixada[hidden] { display: none; }
.chat-fixada-ico { flex-shrink: 0; font-size: 14px; }
.chat-fixada-corpo {
  flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0;
  cursor: pointer;
}
.chat-fixada-corpo strong { font-size: 11.5px; color: var(--azul); }
.chat-fixada-corpo span { font-size: 12px; color: var(--tinta-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chat-fixada-remover {
  flex-shrink: 0; width: 22px; height: 22px; border-radius: 50%; border: 0;
  background: none; color: var(--tinta-3); cursor: pointer; font-size: 13px;
  display: flex; align-items: center; justify-content: center;
  transition: background var(--transicao), color var(--transicao);
}
.chat-fixada-remover:hover { background: var(--superficie-3); color: var(--st-critico); }

.chat-mensagens {
  flex: 1; min-height: 0; overflow-y: auto; display: flex; flex-direction: column;
  gap: 10px; padding: 4px 6px 10px;
}
/* Divisor de data flutuante, estilo WhatsApp — pedido do usuário (22/07):
   "em vez de a data ficar fixada em toda mensagem ela pode ficar na parte
   superior [...] quando virar o dia aí atualiza". `position: sticky` faz o
   rótulo grudar no topo da rolagem enquanto o grupo daquele dia estiver
   visível, sem precisar de JS — some sozinho quando o próximo divisor
   (dia seguinte) chega no topo.
   `.chat-dia-grupo` (um por dia, ver chat.html) é o que faz esse "some
   sozinho" funcionar de verdade — bug corrigido (24/07): o limite de até
   onde um elemento sticky fica grudado é o rodapé do PAI dele, não do dia
   seguinte. Sem esse agrupamento, todo divisor era irmão solto direto de
   `.chat-mensagens` (o chat inteiro), então nenhum soltava nunca — dois+
   rótulos de dia ficavam sobrepostos no topo ao mesmo tempo ao rolar.
   Com o agrupamento, cada rótulo só fica preso enquanto o próprio dia
   está passando. */
.chat-dia-grupo { display: flex; flex-direction: column; gap: 10px; }
.chat-data-divisor { position: sticky; top: 2px; z-index: 2; display: flex; justify-content: center; margin: 6px 0; pointer-events: none; }
.chat-data-divisor span {
  background: var(--superficie-2); color: var(--tinta-2); font-size: 11px; font-weight: 600;
  padding: 4px 14px; border-radius: 999px; box-shadow: var(--sombra-1);
}

.chat-msg { display: flex; gap: 8px; align-items: flex-end; max-width: 72%; align-self: flex-start; }
.chat-msg-minha { align-self: flex-end; flex-direction: row-reverse; }
.chat-msg-avatar {
  width: 26px; height: 26px; border-radius: 50%; object-fit: cover; flex-shrink: 0;
  box-shadow: 0 0 0 2px var(--fundo);
}
/* Clicar na foto de quem mandou a mensagem (num grupo/setor) abre direto a
   conversa particular com essa pessoa — pedido do usuário (31/07). */
.chat-msg-avatar-clicavel { cursor: pointer; transition: box-shadow .12s; }
.chat-msg-avatar-clicavel:hover { box-shadow: 0 0 0 2px var(--azul); }
.chat-msg-corpo {
  background: var(--superficie-3); border-radius: var(--raio); padding: 8px 12px; min-width: 0;
  box-shadow: 0 1px 1px rgba(0,0,0,.06), 0 2px 6px rgba(0,0,0,.05);
}
.chat-msg-minha .chat-msg-corpo { background: var(--azul); color: #fff; box-shadow: 0 2px 8px rgba(15, 99, 178, .28); }
.chat-msg-minha .chat-msg-hora { color: rgba(255,255,255,.75); }
.chat-msg-autor { font-size: 11.5px; font-weight: 700; margin-bottom: 2px; color: var(--tinta-2); }
.chat-msg-texto { font-size: 13.5px; line-height: 1.45; white-space: pre-wrap; word-break: break-word; }
.chat-msg-texto strong { font-weight: 700; }
.chat-msg-texto em { font-style: italic; }
/* Link dentro da mensagem — pedido do usuário (22/07): "fica clicável
   porém invisível" (sem cor própria, ficava igual ao resto do texto).
   Cor diferente pra cada fundo de bolha: azul-claro sobre o balão azul
   (mensagem própria), azul normal sobre o balão cinza (mensagem alheia). */
.chat-msg-texto a { color: var(--azul); text-decoration: underline; word-break: break-all; }
.chat-msg-minha .chat-msg-texto a { color: #cfe8ff; }
.chat-msg-rodape { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 4px; }
.chat-msg-hora { font-size: 10px; color: var(--tinta-3); }
.chat-msg-mencionou-voce .chat-msg-corpo { outline: 2px solid var(--st-critico); outline-offset: -1px; }
.chat-msg-imagem { max-width: 100%; max-height: 260px; border-radius: 8px; display: block; margin-bottom: 4px; cursor: zoom-in; }
.chat-msg-resposta {
  border-left: 2px solid var(--azul-claro); padding: 3px 8px; margin-bottom: 5px;
  font-size: 11.5px; color: var(--tinta-3); background: rgba(0,0,0,.04); border-radius: 4px;
  display: flex; flex-direction: column; gap: 1px; max-width: 100%; overflow: hidden;
  cursor: pointer; transition: background var(--transicao);
}
.chat-msg-resposta:hover { background: rgba(0,0,0,.09); }
.chat-msg-minha .chat-msg-resposta { background: rgba(255,255,255,.12); color: rgba(255,255,255,.8); }
.chat-msg-minha .chat-msg-resposta:hover { background: rgba(255,255,255,.2); }
.chat-msg-resposta strong { font-size: 11px; }
.chat-msg-resposta span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Destaque temporário ao pular pra mensagem original (clique na citação
   acima) — pedido do usuário (23/07): "ao clicar na mensagem que a pessoa
   respondeu redirecione para a mensagem". `.chat-msg-destaque` é removida
   por JS ~1.5s depois (setTimeout em chat.html), só pra chamar o olho pro
   lugar certo depois do scroll. */
.chat-msg-destaque .chat-msg-corpo { animation: chat-destaque-flash 1.5s ease-out; }
@keyframes chat-destaque-flash {
  0%, 100% { background: transparent; }
  20% { background: var(--lavagem-azul); }
}

/* Buscar dentro do conteúdo das mensagens (10/08, pedido do usuário) —
   botão de lupa no cabeçalho da conversa + barrinha de busca (input +
   contador + anterior/próximo) que filtra as mensagens já carregadas.
   `.chat-msg-busca-oculta` esconde mensagem/grupo de dia que não bate
   com o termo digitado — mesma técnica de "esconder o que não interessa"
   já usada no filtro de sala (`#chat-busca-salas`, `estilo.css`). */
.chat-busca-msgs-bt {
  flex-shrink: 0; margin-left: auto; width: 30px; height: 30px; border-radius: 50%;
  border: 0; background: none; color: var(--tinta-2); cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background var(--transicao), color var(--transicao);
}
.chat-busca-msgs-bt:hover { background: var(--superficie-3); color: var(--azul); }
.chat-busca-msgs-barra {
  display: flex; align-items: center; gap: 6px; flex-shrink: 0;
  padding: 6px 8px; margin-bottom: 8px; border-radius: var(--raio-sm);
  background: var(--superficie-2); border: 1px solid var(--borda);
}
.chat-busca-msgs-barra[hidden] { display: none; }
#chat-busca-msgs-input {
  flex: 1; min-width: 0; border: 0; background: none; color: var(--tinta);
  font: inherit; font-size: 13px; outline: none;
}
.chat-busca-msgs-contador { font-size: 11.5px; color: var(--tinta-3); white-space: nowrap; }
.chat-busca-msgs-nav, .chat-busca-msgs-fechar {
  flex-shrink: 0; width: 24px; height: 24px; border-radius: 50%; border: 0;
  background: none; color: var(--tinta-2); cursor: pointer; font-size: 11px;
  display: flex; align-items: center; justify-content: center;
  transition: background var(--transicao), color var(--transicao);
}
.chat-busca-msgs-nav:hover, .chat-busca-msgs-fechar:hover { background: var(--superficie-3); color: var(--azul); }
.chat-msg.chat-msg-busca-oculta, .chat-dia-grupo.chat-msg-busca-oculta { display: none; }

/* Menu "⋮" (Responder/Excluir) — pedido do usuário (22/07): "se clicar
   nos 3 pontinhos ao lado da mensagem aparece a opção de excluir"
   (duplo-clique no corpo da mensagem responde direto, ver chat.html). */
.chat-msg-menu { position: relative; }
.chat-msg-menu-bt {
  background: none; border: 0; cursor: pointer; font-size: 14px; line-height: 1;
  color: var(--tinta-3); opacity: .6; padding: 2px 4px; border-radius: 4px; transition: opacity var(--transicao), background var(--transicao);
}
.chat-msg-menu-bt:hover { opacity: 1; background: rgba(0,0,0,.06); }
.chat-msg-minha .chat-msg-menu-bt { color: rgba(255,255,255,.8); }
.chat-msg-minha .chat-msg-menu-bt:hover { background: rgba(255,255,255,.18); }
/* Padrão SEMPRE abrindo pra DIREITA (`left: 0`) — pedido do usuário
   (29/07), depois de ver na prática que abrir pra esquerda cortava o
   menu (emoji de reação + "Responder" + "Excluir") em mensagem de outra
   pessoa (bolha encostada na esquerda da tela, sem espaço sobrando pra
   esquerda): "tem como padronizar ele abrir somente pra direita pra isso
   não acontecer?". Só volta pra esquerda (`.chat-msg-menu-abre-esquerda`,
   caso raro) quando abrir pra direita estouraria a borda direita da área
   de mensagens — ex.: mensagem "minha", já colada na direita. */
.chat-msg-menu-lista {
  display: none; position: absolute; bottom: calc(100% + 4px); left: 0; min-width: 130px;
  background: var(--superficie-2); border-radius: 8px; box-shadow: var(--sombra-2); overflow: hidden; z-index: 5;
}
.chat-msg-menu.aberto .chat-msg-menu-lista { display: block; }
/* Menu abrindo pra baixo em vez de pra cima — pedido do usuário (29/07),
   ver JS em chat.html (o menu mede a própria posição ao abrir e troca pra
   esta classe quando não sobra espaço acima, dentro da área rolável de
   mensagens). */
.chat-msg-menu-abre-baixo .chat-msg-menu-lista { bottom: auto; top: calc(100% + 4px); }
.chat-msg-menu-abre-esquerda .chat-msg-menu-lista { left: auto; right: 0; }
.chat-msg-menu-item {
  display: block; width: 100%; text-align: left; background: none; border: 0; cursor: pointer;
  padding: 8px 12px; font-size: 12.5px; color: var(--tinta); white-space: nowrap;
}
.chat-msg-menu-item:hover { background: var(--superficie-3); }
.chat-msg-menu-item-excluir { color: var(--st-critico); }

/* Reagir à mensagem — pedido do usuário (29/07): "quero que no chat tenha
   a opção de reagir a mensagem". Fileira de emoji (EMOJI_REACAO em
   chat.py) no topo do menu "⋮"; as reações já dadas aparecem como "pill"
   embaixo da mensagem — clicar numa pill de novo alterna a SUA reação
   (ver chat.alternar_reacao: uma reação por pessoa por mensagem).
   Caractere nativo do sistema operacional, não imagem (20/08 — ver nota
   em `chat.linkify()`/`chat.py`); `.chat-emoji-nativo` só ajusta o
   tamanho da fonte pra ocupar o mesmo espaço que a imagem ocupava. */
.chat-msg-menu-reacoes { display: flex; gap: 2px; padding: 6px 8px; border-bottom: 1px solid var(--borda); }
.chat-msg-menu-reacao-bt {
  background: none; border: 0; cursor: pointer; padding: 4px; border-radius: 6px;
  display: flex; align-items: center; justify-content: center; transition: background var(--transicao);
}
.chat-msg-menu-reacao-bt:hover { background: var(--superficie-3); }
.chat-msg-menu-reacao-bt .chat-emoji-nativo { font-size: 18px; line-height: 1; }

.chat-msg-reacoes { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 4px; }
.chat-msg-reacoes:empty { display: none; margin: 0; }
.chat-reacao-pill {
  display: flex; align-items: center; gap: 3px; background: var(--superficie-2);
  border: 1px solid var(--borda); border-radius: 999px; padding: 1px 7px; cursor: pointer;
  font-size: 11px; color: var(--tinta-2); transition: background var(--transicao), border-color var(--transicao);
}
.chat-reacao-pill:hover { background: var(--superficie-3); }
.chat-reacao-pill .chat-emoji-nativo { font-size: 13px; line-height: 1; }
.chat-reacao-minha { border-color: var(--azul); background: var(--lavagem-azul); color: var(--azul); }
.chat-msg-minha .chat-msg-reacoes { justify-content: flex-end; }

/* Enquete rápida (10/08, pedido do usuário) — cartão PRÓPRIO dentro da
   bolha de mensagem (não só as opções soltas — a 1ª versão ficava sem
   nenhuma moldura separando do resto da bolha, pedido do usuário: "arruma
   essa enquete, não está com um layout muito agradável"). Fundo/borda em
   `rgba()` em vez de token de superfície — acompanha a cor da bolha
   (cinza numa mensagem normal, azul na "minha"), mesma técnica já usada
   em `.chat-msg-resposta` (citação). Barra de progresso ATRÁS do texto,
   mesma ideia dos gráficos de barra do resto do sistema. */
.chat-enquete {
  min-width: 230px; max-width: 280px; margin-top: 4px;
  background: rgba(0,0,0,.035); border: 1px solid rgba(0,0,0,.08);
  border-radius: var(--raio-sm); padding: 10px;
}
.chat-enquete-pergunta {
  display: flex; align-items: flex-start; gap: 7px;
  font-size: 13px; font-weight: 700; line-height: 1.35; margin-bottom: 9px;
}
.chat-enquete-pergunta-ico {
  flex-shrink: 0; width: 22px; height: 22px; border-radius: 50%;
  background: var(--lavagem-azul); display: flex; align-items: center; justify-content: center;
  font-size: 12px;
}
.chat-msg-minha .chat-enquete-pergunta-ico { background: rgba(255,255,255,.2); }
.chat-enquete-opcao {
  position: relative; display: block; width: 100%; text-align: left;
  border: 1px solid rgba(0,0,0,.1); border-radius: var(--raio-sm);
  background: var(--fundo); padding: 7px 10px; margin-bottom: 6px; cursor: pointer; overflow: hidden;
  transition: border-color var(--transicao), transform var(--transicao);
}
.chat-enquete-opcao:last-of-type { margin-bottom: 0; }
.chat-enquete-opcao:hover { border-color: var(--azul-claro); transform: translateY(-1px); }
.chat-enquete-opcao.chat-enquete-minha { border-color: var(--azul); background: var(--lavagem-azul); }
.chat-enquete-opcao-barra {
  position: absolute; top: 0; left: 0; bottom: 0; background: var(--lavagem-azul);
  transition: width var(--transicao); z-index: 0;
}
.chat-enquete-opcao.chat-enquete-minha .chat-enquete-opcao-barra { background: rgba(7, 99, 160, .16); }
.chat-enquete-opcao-conteudo {
  position: relative; z-index: 1; display: flex; align-items: center; justify-content: space-between; gap: 10px;
}
.chat-enquete-opcao-texto { font-size: 12.5px; color: var(--tinta); font-weight: 500; }
.chat-enquete-opcao.chat-enquete-minha .chat-enquete-opcao-texto { font-weight: 700; color: var(--azul); }
.chat-enquete-opcao.chat-enquete-minha .chat-enquete-opcao-texto::before { content: '✓ '; }
.chat-enquete-opcao-pct { font-size: 11px; color: var(--tinta-3); white-space: nowrap; flex-shrink: 0; font-variant-numeric: tabular-nums; }
.chat-enquete-total { font-size: 11px; color: var(--tinta-3); margin-top: 8px; padding-top: 8px; border-top: 1px solid rgba(0,0,0,.08); }
.chat-msg-minha .chat-enquete { background: rgba(255,255,255,.1); border-color: rgba(255,255,255,.2); }
.chat-msg-minha .chat-enquete-opcao { background: rgba(255,255,255,.1); border-color: rgba(255,255,255,.28); }
.chat-msg-minha .chat-enquete-opcao.chat-enquete-minha { background: rgba(255,255,255,.22); border-color: #fff; }
.chat-msg-minha .chat-enquete-opcao-texto { color: #fff; }
.chat-msg-minha .chat-enquete-opcao.chat-enquete-minha .chat-enquete-opcao-texto { color: #fff; }
.chat-msg-minha .chat-enquete-opcao-pct { color: rgba(255,255,255,.75); }
.chat-msg-minha .chat-enquete-opcao-barra { background: rgba(255,255,255,.22); }
.chat-msg-minha .chat-enquete-opcao.chat-enquete-minha .chat-enquete-opcao-barra { background: rgba(255,255,255,.3); }
.chat-msg-minha .chat-enquete-total { color: rgba(255,255,255,.7); border-top-color: rgba(255,255,255,.2); }

/* Campo de opção dentro do modal "Nova enquete" — mesma classe `.campo`
   do resto do sistema, só mais compacto (várias linhas seguidas), com um
   número de ordem discreto pra ficar claro que é uma lista, não campos
   soltos sem relação. */
.chat-enquete-opcao-campo { margin-bottom: 10px; }
.chat-enquete-opcao-campo label { font-size: 11px; }

/* Editor de imagem do chat (cortar/desenhar), estilo WhatsApp — pedido
   do usuário (12/08). Ferramentas em cima do canvas, cor selecionável só
   quando o Lápis está ativo. */
.chat-imagem-editor-ferramentas { display: flex; gap: 8px; margin-bottom: 10px; flex-wrap: wrap; }
.chat-imagem-editor-ferramentas button.ativa { background: var(--azul); color: #fff; border-color: var(--azul); }
.chat-imagem-editor-cores { display: flex; gap: 8px; margin-bottom: 4px; }
/* `[hidden]` do navegador (UA stylesheet, baixa prioridade) perde pra
   qualquer regra de classe que já defina `display` — mesmo bug já visto
   em `.notificacao-botao-canto[hidden]` — por isso o override explícito
   nos dois blocos que ligam/desligam via `.hidden = true/false` no JS. */
.chat-imagem-editor-cores[hidden] { display: none; }
.chat-imagem-cor {
  width: 26px; height: 26px; border-radius: 50%; border: 2px solid transparent;
  cursor: pointer; padding: 0;
}
.chat-imagem-cor.ativa { box-shadow: 0 0 0 2px var(--superficie), 0 0 0 4px var(--azul); }
.chat-imagem-editor-tela {
  display: flex; justify-content: center; background: var(--superficie-2);
  border-radius: var(--raio); padding: 10px;
}
.chat-imagem-editor-canvas-wrap { position: relative; display: inline-block; line-height: 0; max-width: 100%; }
/* Bug real relatado pelo usuário (12/08): "a imagem sai do esquadro e não
   cabe na tela" — uma foto bem ALTA (retrato) só tinha `max-width:100%`,
   sem nenhum teto de ALTURA; o navegador então respeitava a largura
   disponível mas deixava a altura crescer sem limite (`height: auto`
   preserva proporção, mas nada segurava o outro eixo), estourando pra
   fora da tela em qualquer foto mais alta que larga. `max-height` +
   `width: auto` junto com `max-width`/`height: auto` faz o navegador
   escolher sozinho qual dos dois eixos é o mais apertado e encolher os
   DOIS proporcionalmente — mesma técnica de sempre pra `<img>`, funciona
   igual em `<canvas>` (também é um elemento substituído com proporção
   intrínseca). `#chat-imagem-overlay` tem sempre o MESMO tamanho interno
   do canvas base (JS mantém os dois em sincronia), então herda a mesma
   regra e escala igual, sem desalinhar as alças de corte. */
.chat-imagem-editor-canvas-wrap canvas {
  display: block; max-width: 100%; max-height: 46vh; width: auto; height: auto; border-radius: 4px;
}
#chat-imagem-overlay { position: absolute; top: 0; left: 0; touch-action: none; }
/* O modal inteiro já tem `max-height: 72vh` (ver `.modal-caixa`) — sem
   isso, ferramentas/canvas/botões que não coubessem nesse teto ficavam
   simplesmente CORTADOS (invisíveis, sem como rolar até "Aplicar corte"/
   "Enviar"). Rola só o CONTEÚDO, a barra de título (`.modal-caixa-topo`)
   continua sempre visível — mesmo tratamento já usado em `#cal-modal-corpo`. */
.chat-imagem-editor-conteudo { padding: 16px 18px; overflow-y: auto; flex: 1; min-height: 0; }
/* Aparece só com "Cortar" ativo — o retângulo de corte com alças (12/08)
   exige uma ação explícita de "Aplicar", diferente de antes (soltar o
   mouse já aplicava). */
.chat-imagem-editor-cortar-acoes { display: flex; gap: 8px; justify-content: flex-end; margin-top: 10px; }
.chat-imagem-editor-cortar-acoes[hidden] { display: none; }

/* Player de áudio próprio — pedido do usuário (22/07): "opção de mandar
   áudio seria legal também", com player customizado. */
.chat-audio-player { display: flex; align-items: center; gap: 8px; min-width: 190px; padding: 2px 0 6px; }
.chat-audio-play {
  width: 28px; height: 28px; border-radius: 50%; border: 0; cursor: pointer; flex-shrink: 0;
  background: var(--azul); color: #fff; font-size: 11px; display: flex; align-items: center; justify-content: center;
}
.chat-msg-minha .chat-audio-play { background: #fff; color: var(--azul); }
.chat-audio-barra { flex: 1; height: 4px; border-radius: 999px; background: rgba(0,0,0,.12); overflow: hidden; }
.chat-msg-minha .chat-audio-barra { background: rgba(255,255,255,.3); }
.chat-audio-progresso { height: 100%; width: 0%; background: var(--azul); border-radius: 999px; }
.chat-msg-minha .chat-audio-progresso { background: #fff; }
.chat-audio-tempo { font-size: 10.5px; color: var(--tinta-3); flex-shrink: 0; font-variant-numeric: tabular-nums; }
.chat-msg-minha .chat-audio-tempo { color: rgba(255,255,255,.75); }

.chat-resposta-preview {
  display: flex; align-items: center; gap: 10px; padding: 6px 10px;
  background: var(--superficie-3); border-left: 3px solid var(--azul);
  border-radius: 6px; margin-bottom: 6px; font-size: 12px; color: var(--tinta-2);
}
.chat-resposta-preview-texto { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#chat-resposta-cancelar { background: none; border: 0; cursor: pointer; color: var(--tinta-3); font-size: 13px; }

/* Menuzinho de formatação (negrito/itálico/tópico) ao selecionar texto —
   pedido do usuário (22/07): "adiciona aquilo de ao selecionar o texto
   aparece um menuzinho [...] mais parecido com o ZAP". */
.chat-formatar-barra {
  display: flex; gap: 4px; margin-bottom: 6px; padding: 4px; width: fit-content;
  background: var(--superficie-2); border-radius: 8px; box-shadow: var(--sombra-1);
}
.chat-formatar-barra button {
  background: none; border: 0; cursor: pointer; min-width: 30px; padding: 5px 8px;
  border-radius: 6px; font-size: 12.5px; color: var(--tinta);
}
.chat-formatar-barra button:hover { background: var(--superficie-3); }

/* Painel de emojis — pedido do usuário (22/07): "também coloque emojis".
   `max-height`+`overflow-y` (19/08, pedido do usuário: "se tiver muitos,
   coloca uma rolagem") — hoje a lista é curta e curada (`EMOJI_CHAT_ORDEM`
   em emoji_util.py) e cabe sem rolar, mas evita o painel esticar a tela
   pra baixo sem limite se a lista crescer de novo no futuro. Caractere
   emoji nativo, não imagem (20/08 — Chat saiu do Twemoji, ver nota em
   `chat.linkify()`/`chat.py`). */
.chat-emoji-painel {
  grid-template-columns: repeat(8, 1fr); gap: 2px; margin-bottom: 6px; padding: 8px;
  background: var(--superficie-2); border-radius: 10px; box-shadow: var(--sombra-1);
  max-width: 280px; max-height: 220px; overflow-y: auto;
}
.chat-emoji-item {
  background: none; border: 0; cursor: pointer; padding: 5px;
  border-radius: 6px; line-height: 1;
}
.chat-emoji-item:hover { background: var(--superficie-3); }
.chat-emoji-item .chat-emoji-nativo { font-size: 20px; }

/* Emoji com imagem própria EM TODA TELA (19/08, pedido do usuário:
   "espalhar pro sistema inteiro") — vale pro resto do sistema (JS de
   `base.html` troca o caractere por esta imagem em qualquer tela, EXCETO
   Visão Geral e Chat, que mostram o emoji nativo — ver aquele script).
   Tamanho proporcional ao texto ao redor via `em`. */
.emoji-img { width: 1.15em; height: 1.15em; vertical-align: -0.2em; display: inline-block; }
.emoji-tonavel { cursor: pointer; }

/* Popover do seletor de cor de pele (19/08, pedido do usuário: "ao
   clicar no emoji poder escolher a cor de pele") — "padrão" + 5 tons;
   clicar troca a tela toda e salva a preferência (localStorage). */
.emoji-tom-popover {
  position: absolute; z-index: 500; display: flex; gap: 3px; padding: 6px;
  background: var(--superficie-2); border: 1px solid var(--borda); border-radius: 10px;
  box-shadow: var(--sombra-2);
}
.emoji-tom-opcao {
  background: none; border: 2px solid transparent; cursor: pointer; padding: 3px;
  border-radius: 8px; line-height: 1; display: flex;
}
.emoji-tom-opcao:hover { background: var(--superficie-3); }
.emoji-tom-opcao.ativa { border-color: var(--azul); }
.emoji-tom-opcao img { width: 22px; height: 22px; display: block; }

/* Barra de gravação de áudio — substitui o formulário de texto enquanto
   grava (ver JS, `MediaRecorder`). */
.chat-gravando {
  display: flex; align-items: center; gap: 10px; padding-top: 12px; border-top: 1px solid var(--borda);
}
.chat-gravando-ponto {
  width: 10px; height: 10px; border-radius: 50%; background: var(--st-critico); flex-shrink: 0;
  animation: chat-gravando-pulso 1.1s ease-in-out infinite;
}
@keyframes chat-gravando-pulso { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }
.chat-gravando-tempo { font-variant-numeric: tabular-nums; font-weight: 700; font-size: 13px; }
.chat-gravando-aviso { flex: 1; color: var(--tinta-2); font-size: 13px; }
.chat-gravando-bt {
  width: 36px; height: 36px; border-radius: 50%; border: 0; cursor: pointer; flex-shrink: 0;
  background: var(--superficie-3); color: var(--tinta-2); font-size: 15px;
}
.chat-gravando-enviar { background: var(--azul); color: #fff; }

/* Barrinha "documento selecionado" (12/08, pedido do usuário: "tambem nos
   anexos tem que ser permitido enviar pdfs" + "e .zip") — reaproveita
   `.chat-gravando` (mesma altura/borda/gap da barra de áudio), só troca o
   pontinho pulsante por um ícone fixo + nome do arquivo, que pode ser
   comprido (`text-overflow: ellipsis` evita estourar a largura do chat). */
.chat-doc-ico { font-size: 20px; flex-shrink: 0; line-height: 1; }
.chat-doc-nome {
  flex: 1; font-size: 13px; color: var(--tinta-2); white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}

/* Anexo de documento DENTRO da bolha de mensagem — cartãozinho clicável
   (abre/baixa em aba nova), mesmo idioma visual de `.chat-msg-resposta`
   (fundo translúcido, acompanha a cor da bolha própria/alheia). */
.chat-msg-documento {
  display: flex; align-items: center; gap: 8px; padding: 8px 10px; margin-bottom: 6px;
  border-radius: var(--raio-sm); background: rgba(0, 0, 0, .06); text-decoration: none;
  color: inherit; max-width: 260px;
}
.chat-msg-minha .chat-msg-documento { background: rgba(255, 255, 255, .16); }
.chat-msg-documento-ico { font-size: 20px; flex-shrink: 0; }
.chat-msg-documento-nome {
  flex: 1; font-size: 13px; font-weight: 600; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
.chat-msg-documento-baixar { flex-shrink: 0; opacity: .7; font-size: 14px; }

/* "Digitando…" (10/08) — mesmo espírito discreto da bolinha de presença,
   texto pequeno acima do campo de mensagem, sem empurrar layout quando
   `hidden` (some por completo, não vira espaço vazio). */
.chat-digitando {
  font-size: 12px; color: var(--tinta-3); padding: 2px 4px 0; font-style: italic;
}

.chat-form-envolt { position: relative; }
.chat-form { display: flex; align-items: flex-end; gap: 8px; padding-top: 12px; border-top: 1px solid var(--borda); }
#chat-texto {
  flex: 1; resize: none; max-height: 120px; padding: 9px 14px; border-radius: 20px;
  border: 1px solid var(--borda); background: var(--superficie-2); color: var(--tinta);
  font: inherit; font-size: 13.5px; line-height: 1.4; transition: border-color var(--transicao), box-shadow var(--transicao);
}
#chat-texto:focus { outline: none; border-color: var(--azul); box-shadow: 0 0 0 3px rgba(15, 99, 178, .12); }
.chat-icon-bt {
  width: 38px; height: 38px; border-radius: 50%; border: 0; cursor: pointer; flex-shrink: 0;
  background: var(--superficie-3); color: var(--tinta-2); font-size: 15px; transition: background var(--transicao), transform var(--transicao);
}
.chat-icon-bt:hover { background: var(--superficie-2); }
.chat-icon-bt-enviar { background: var(--azul); color: #fff; }
.chat-icon-bt-enviar:hover { background: var(--azul); opacity: .9; }
.chat-icon-bt-enviar:active { transform: scale(.93); }

/* Sugestões de @menção — pedido do usuário (22/07): "quando eu digitar @
   aparecer as sugestões de marcações". */
.chat-mencao-lista {
  position: absolute; bottom: 100%; left: 0; margin-bottom: 6px;
  background: var(--superficie); border: 1px solid var(--borda); border-radius: var(--raio);
  box-shadow: 0 4px 16px rgba(0,0,0,.15); overflow: hidden; min-width: 160px; z-index: 20;
}
.chat-mencao-item { padding: 7px 12px; font-size: 13px; color: var(--tinta-2); cursor: pointer; }
.chat-mencao-item.ativa, .chat-mencao-item:hover { background: var(--azul); color: #fff; }
.chat-anexo-bt {
  display: flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; border-radius: var(--raio); cursor: pointer;
  font-size: 16px; background: var(--superficie-3); flex-shrink: 0;
}
.chat-anexo-bt:hover { background: var(--borda); }
.chat-preview-imagem {
  display: flex; align-items: center; gap: 10px; padding: 8px 10px;
  background: var(--superficie-3); border-radius: var(--raio); margin-bottom: 8px;
}
.chat-preview-imagem img { height: 52px; width: 52px; object-fit: cover; border-radius: 6px; }
.chat-preview-imagem-remover, #chat-preview-imagem-remover {
  background: none; border: 0; cursor: pointer; color: var(--tinta-3); font-size: 14px; margin-left: auto;
}

/* Chat no celular — pedido do usuário (23/07): "tem que corrigir o layout
   no celular, o chat está muito mal feito [...] tem que seguir os padrões
   do whatsapp para fazer o chat mobile". Antes lista+conversa ficavam
   espremidas empilhadas na mesma tela (lista com 180px de altura, conversa
   com 48vh) — ilegível. Agora só UMA tela cheia por vez: lista OU conversa,
   nunca as duas juntas, trocando via `.chat-mostrando-conversa` no
   #chat-shell (classe renderizada certa já no primeiro load pelo servidor,
   e alternada pelo JS depois — ver script em chat.html). Mesma altura fixa
   via calc(100vh) do desktop (não `height: auto`) — trocar por flexbox
   esticando os ancestrais já quebrou o scroll interno da lista de
   mensagens antes (ver comentário grande acima de `.chat-shell`). */
@media (max-width: 860px) {
  .chat-shell { flex-direction: column; gap: 0; }
  .chat-salas {
    width: 100%; max-height: none; flex: 1; min-height: 0;
    border-right: 0; padding-right: 0; padding-bottom: 0;
  }
  .chat-conversa { display: none; }
  .chat-conversa-voltar { display: flex; }

  .chat-shell.chat-mostrando-conversa .chat-salas { display: none; }
  .chat-shell.chat-mostrando-conversa .chat-conversa { display: flex; flex: 1; }
}

/* Badge de não lidas no menu lateral — pedido do usuário: "preciso de tipo
   notificações". Atualiza sozinho por polling (ver base.html). */
.nav-chat-badge {
  background: var(--azul); color: #fff; font-size: 10.5px; font-weight: 700;
  border-radius: 999px; padding: 1px 6px; min-width: 16px; text-align: center;
  margin-left: auto; line-height: 1.5;
}
.nav-chat-badge-mencao { background: var(--st-critico); }
.nav-chat-badge:empty { display: none; }

/* Central de notificações (27/07, virou pop-up centralizado no mesmo dia —
   pedido do usuário: um dropdown ao lado do sino "fica estranho", melhor um
   pop-up de verdade, com fundo escurecido, que dá ênfase no que abriu). O
   pop-up em si reaproveita `.modal-fundo`/`.modal-caixa` (ver base.html);
   aqui só sobra o estilo do sino na lateral e da lista de itens dentro do
   pop-up. */
/* Atalhos de teclado (10/08) — modal reaproveita `.modal-fundo`/
   `.modal-caixa` de sempre, só a lista/kbd são deste bloco. */
.atalhos-lista { display: flex; flex-direction: column; gap: 4px; padding: 6px 18px 18px; }
.atalhos-item { display: flex; align-items: center; gap: 8px; padding: 8px 0; border-bottom: 1px solid var(--borda-2); font-size: 13px; }
.atalhos-item:last-child { border-bottom: 0; }
.atalhos-item-desc { color: var(--tinta-2); margin-left: 4px; }
kbd {
  display: inline-block; min-width: 22px; text-align: center; padding: 2px 7px;
  background: var(--superficie-2); border: 1px solid var(--borda-2); border-bottom-width: 2px;
  border-radius: var(--raio-sm); font-family: 'Syne', sans-serif; font-size: 11.5px;
  color: var(--tinta); box-shadow: 0 1px 0 var(--borda-2);
}

.notificacoes-nav { position: relative; cursor: pointer; user-select: none; }
.notificacoes-painel-cab {
  display: flex; align-items: center; justify-content: flex-end; gap: 8px;
  padding: 10px 18px; border-bottom: 1px solid var(--borda);
}
#notificacoes-marcar-todas {
  background: none; border: none; color: var(--azul); font-size: 11.5px; cursor: pointer; padding: 0;
}
#notificacoes-marcar-todas:hover { text-decoration: underline; }
/* Botão destrutivo (03/08, pedido do usuário: "excluir as notificações
   todas") — mesma cor de "excluir"/"remover" já usada no resto do
   sistema (var(--st-critico)), separado do azul de "marcar lidas" pra
   não parecer a mesma categoria de ação. */
#notificacoes-excluir-todas {
  background: none; border: none; color: var(--st-critico); font-size: 11.5px; cursor: pointer; padding: 0;
}
#notificacoes-excluir-todas:hover { text-decoration: underline; }
.notificacoes-lista { max-height: 60vh; overflow-y: auto; }
.notificacoes-vazio { padding: 22px 14px; text-align: center; font-size: 12.5px; color: var(--tinta-3); }
.notificacoes-item {
  display: flex; gap: 10px; align-items: flex-start; padding: 10px 14px;
  text-decoration: none; color: var(--tinta); border-bottom: 1px solid var(--borda-2);
  transition: background var(--transicao);
}
.notificacoes-item:last-child { border-bottom: none; }
.notificacoes-item:hover { background: var(--superficie-2); }
.notificacoes-item.nao-lida { background: var(--lavagem-azul); }
.notificacoes-item-ico { font-size: 16px; line-height: 1.3; flex-shrink: 0; }
.notificacoes-item-corpo { min-width: 0; display: flex; flex-direction: column; gap: 2px; flex: 1; }
.notificacoes-item-texto { font-size: 12.5px; line-height: 1.4; }
.notificacoes-item-quando { font-size: 10.5px; color: var(--tinta-3); }
/* Botão "excluir" de UMA notificação — só aparece no hover da linha, pra
   não poluir a lista inteira de "✕" o tempo todo (mesmo padrão discreto
   já usado em Contatos Importantes/EPI pra ação por linha). */
.notificacoes-item-excluir {
  background: none; border: none; color: var(--tinta-3); cursor: pointer;
  font-size: 13px; padding: 2px 4px; flex-shrink: 0; opacity: 0; transition: opacity var(--transicao), color var(--transicao);
}
.notificacoes-item:hover .notificacoes-item-excluir { opacity: 1; }
.notificacoes-item-excluir:hover { color: var(--st-critico); }

/* Caixinha de mensagem nova, canto superior direito (23/07) — pedido do
   usuário: "se tiver com o sistema aberto [...] apareça uma caixinha ao
   lado direito", "bem sutil", some sozinha depois de 5s (ver
   base.html/mostrarToast). Só aparece quando a aba JÁ está em foco — é o
   par sutil da notificação do Windows, que cobre o caso de fora de foco;
   nunca as duas juntas pro mesmo evento. */
.toast-nao-lidas {
  position: fixed; top: 20px; right: 22px; z-index: 70; max-width: 300px;
  background: var(--superficie); border: 1px solid var(--borda-2); border-left: 3px solid var(--azul);
  border-radius: var(--raio-sm); padding: 10px 14px; font-size: 13px; color: var(--tinta);
  box-shadow: var(--sombra-2); cursor: pointer; pointer-events: none; opacity: 0;
  transform: translateX(12px); transition: opacity .25s ease, transform .25s ease;
}
.toast-nao-lidas.toast-visivel { opacity: 1; transform: translateX(0); pointer-events: auto; }
.toast-nao-lidas.toast-saindo { opacity: 0; transform: translateX(12px); }
@media (max-width: 480px) {
  .toast-nao-lidas { left: 14px; right: 14px; top: 14px; max-width: none; }
}

.setores-grade { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; }
@media (max-width: 900px) { .setores-grade { grid-template-columns: 1fr; } }

.setor-cartao {
  background: var(--vidro-bg-solido); border: 1px solid var(--vidro-borda); border-radius: var(--raio-lg);
  box-shadow: inset 0 1px 0 var(--vidro-realce), var(--sombra-1);
  padding: 22px 24px; text-decoration: none; color: inherit;
  display: block; position: relative;
  transition: box-shadow var(--transicao), transform var(--transicao), border-color var(--transicao);
}
/* Sombra mais funda/macia + leve subida no hover (04/08, reforma "vidro") —
   só nos cards que são LINK de verdade (humor/calendário não são clicáveis,
   não ganham esse hover). Aplica a TODO card que usa `.setor-cartao`
   (grade de setores, veículo, salas) de graça, sem precisar tocar em cada
   template. */
a.setor-cartao:hover {
  box-shadow: 0 20px 44px rgba(11, 47, 74, .16); transform: translateY(-4px);
  border-color: rgba(7, 99, 160, .18);
}
.setor-cartao.desligado { opacity: .55; cursor: not-allowed; }
.setor-cartao-topo { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 14px; }
.setor-cartao h2 { font-size: 16px; font-weight: 700; }
.setor-selo {
  font-size: 9.5px; text-transform: uppercase; letter-spacing: .07em; font-weight: 700;
  padding: 3px 9px; border-radius: var(--raio-pill);
  background: var(--superficie-3); color: var(--tinta-3);
}
.setor-cartao-numeros { display: flex; flex-wrap: wrap; gap: 18px 22px; }
.setor-num-v { font-family: 'IBM Plex Sans', sans-serif; font-size: 28px; font-weight: 800; }
.setor-num-r { font-size: 11px; color: var(--tinta-3); margin-top: 2px; }
.setor-num-r-alerta { color: var(--st-critico); font-weight: 700; }

/* Título do card vira link (cada estatística abaixo já é clicável por
   conta própria) — sem sublinhado, sem cor de link padrão, só um leve
   destaque de cor no hover pra ainda parecer clicável. */
.setor-cartao-titulo { text-decoration: none; color: inherit; }
.setor-cartao-titulo:hover h2 { color: var(--azul); }

/* "Conheça a Direction" — grade de quadros de apresentação (21/08,
   pedido do usuário: "diversos quadros [...] estilo cursos de hotmart",
   depois refinado com uma referência visual: capa de curso em pé —
   imagem de fundo cheia + degradê escuro embaixo + título, "só que
   padronizado" entre os quadros). Fundo é sempre uma das 2 imagens
   geradas (`cd-capa-geral.png` com o logo / `cd-capa-setor.png` sem —
   MESMO gradiente/orbe/marca-d'água nas duas, só isso já garante o
   "padronizado"); o card em si só desenha o texto por cima. */
.cd-quadros-grade { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 18px; }
.cd-quadro {
  position: relative; display: block; aspect-ratio: 640 / 900; border-radius: var(--raio-lg);
  overflow: hidden; text-decoration: none; color: inherit; background-size: cover; background-position: center;
  box-shadow: var(--sombra-1);
  transition: transform var(--transicao), box-shadow var(--transicao);
}
a.cd-quadro:hover { transform: translateY(-4px); box-shadow: var(--sombra-2); }
.cd-quadro-legenda {
  position: absolute; left: 0; right: 0; bottom: 0; padding: 18px 16px 16px;
  display: flex; flex-direction: column; gap: 3px;
}
.cd-quadro-nome {
  font-family: 'IBM Plex Sans', sans-serif; font-weight: 800; font-size: 17px; line-height: 1.25;
  color: #fff; text-shadow: 0 2px 10px rgba(0, 0, 0, .5);
}
.cd-quadro-sub { font-size: 11px; color: rgba(255, 255, 255, .75); }
/* Bloqueado — "estilo cursos de hotmart": esmaecido, cadeado por cima,
   nunca vira link de verdade (nem `<a>`, ver template) mesmo que alguém
   inspecione o HTML. */
.cd-quadro.cd-quadro-bloqueado { opacity: .68; cursor: not-allowed; filter: grayscale(.35); }
.cd-quadro-cadeado {
  position: absolute; top: 12px; right: 12px; width: 32px; height: 32px; border-radius: 50%;
  background: rgba(0, 0, 0, .45); backdrop-filter: blur(4px);
  display: flex; align-items: center; justify-content: center; font-size: 14px;
}
.cd-quadro-selo-breve {
  align-self: flex-start; font-size: 9.5px; text-transform: uppercase; letter-spacing: .07em; font-weight: 700;
  padding: 3px 9px; border-radius: var(--raio-pill); background: rgba(255, 255, 255, .16); color: #fff; margin-top: 4px;
}

/* Grade de espaços do Painel de Tarefas (25/08) — mesma ideia de cartão
   bloqueado/"em breve" de `.cd-quadro` acima, só que em formato
   landscape (ferramenta, não capa de curso): ícone glossy (mesmo
   gradiente de `.btn-att`) + nome do setor + selo. Ícone de cada setor é
   o MESMO usado no menu lateral (ver `painel_tarefas_selecao.html`), pra
   ficar reconhecível na hora. */
.pt-espacos-grade { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 16px; }
.pt-espaco {
  position: relative; display: flex; flex-direction: column; gap: 12px;
  padding: 20px; border-radius: var(--raio-lg); overflow: hidden;
  background: linear-gradient(160deg, var(--superficie-2) 0%, var(--superficie) 100%);
  border: 1px solid var(--borda); box-shadow: var(--sombra-1);
  text-decoration: none; color: inherit;
  transition: transform var(--transicao), box-shadow var(--transicao), border-color var(--transicao);
}
.pt-espaco::before {
  content: ''; position: absolute; inset: 0; opacity: 0; pointer-events: none;
  background: radial-gradient(420px 220px at 0% 0%, rgba(95, 196, 251, .16), transparent 60%);
  transition: opacity var(--transicao);
}
a.pt-espaco:hover { transform: translateY(-4px); box-shadow: var(--sombra-2); border-color: rgba(95, 196, 251, .4); }
a.pt-espaco:hover::before { opacity: 1; }
.pt-espaco-icone {
  width: 42px; height: 42px; border-radius: 13px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: linear-gradient(160deg, var(--azul-claro) 0%, var(--azul) 60%, var(--azul-escuro) 100%);
  color: #fff; box-shadow: inset 0 1px 0 rgba(255, 255, 255, .35), 0 6px 16px rgba(7, 99, 160, .24);
}
.pt-espaco-icone svg { width: 19px; height: 19px; }
.pt-espaco-nome { font-family: 'IBM Plex Sans', sans-serif; font-weight: 800; font-size: 15px; }
.pt-espaco-selo {
  align-self: flex-start; font-size: 10px; text-transform: uppercase; letter-spacing: .06em; font-weight: 700;
  padding: 4px 10px; border-radius: var(--raio-pill);
}
.pt-espaco-selo.pronto { background: color-mix(in srgb, var(--st-concluido) 22%, transparent); color: var(--st-concluido); }
.pt-espaco-selo.breve { background: var(--superficie-3); color: var(--tinta-3); }
.pt-espaco-bloqueado { opacity: .6; cursor: not-allowed; filter: grayscale(.3); }
.pt-espaco-bloqueado .pt-espaco-icone { background: var(--superficie-3); color: var(--tinta-3); box-shadow: none; }
.pt-espaco-cadeado {
  position: absolute; top: 14px; right: 14px; width: 28px; height: 28px; border-radius: 50%;
  background: var(--superficie-3); display: flex; align-items: center; justify-content: center; font-size: 12px;
}

/* Tela de transição ao clicar em "Conheça a Direction" no menu (21/08,
   pedido do usuário: "ficaria legal") — overlay fixo, fundo escuro da
   marca (mesma família do carrossel em si, `.tv-tela`), logo entra com
   escala+fade. `pointer-events: none` enquanto invisível — não pode
   bloquear clique em NADA do resto do sistema fora do momento da
   transição. */
.cd-transicao {
  position: fixed; inset: 0; z-index: 9999; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 18px;
  background: radial-gradient(circle at 50% 40%, #0a3f63 0%, #050b12 78%);
  opacity: 0; pointer-events: none; transition: opacity .35s ease;
}
.cd-transicao-ativa { opacity: 1; pointer-events: all; }
.cd-transicao-logo {
  width: 84px; height: 84px; object-fit: contain; transform: scale(.7);
  opacity: 0; filter: drop-shadow(0 10px 30px rgba(50, 182, 246, .45));
}
/* Entra com escala+fade (.5s) e, assim que assenta, fica pulsando em loop
   até a navegação disparar (2s, ver `setTimeout` em base.html) — pedido
   do usuário (21/08): "coloque a animação [...] por 2 segundos, e deixe
   o símbolo pulsando" — só o SÍMBOLO pulsa ("símbolo da direction
   apenas"), o nome abaixo ("faltou o nome grandão") fica parado depois
   que entra. */
.cd-transicao-ativa .cd-transicao-logo {
  animation: cd-transicao-logo-entra .5s cubic-bezier(.22, 1, .36, 1) forwards,
             cd-transicao-logo-pulso 1.1s ease-in-out .5s infinite;
}
@keyframes cd-transicao-logo-entra {
  0% { transform: scale(.7); opacity: 0; }
  100% { transform: scale(1); opacity: 1; }
}
.cd-transicao-texto {
  font-family: 'IBM Plex Sans', sans-serif; font-weight: 800; font-size: clamp(26px, 3.4vw, 40px);
  color: #fff; letter-spacing: -.01em; opacity: 0; transform: translateY(8px);
}
.cd-transicao-ativa .cd-transicao-texto { animation: cd-transicao-texto-entra .5s ease .35s forwards; }
@keyframes cd-transicao-texto-entra {
  to { opacity: 1; transform: translateY(0); }
}
@keyframes cd-transicao-logo-pulso {
  0%, 100% { transform: scale(1); filter: drop-shadow(0 10px 30px rgba(50, 182, 246, .45)); }
  50% { transform: scale(1.12); filter: drop-shadow(0 10px 40px rgba(50, 182, 246, .75)); }
}

/* Boxes individuais por estatística — pedido do usuário (20/07): "cada
   valor fica dentro de um box, que tenha cor, algo mais lúdico". Mesma
   identidade visual do .tile (faixa de cor à esquerda + brilho no canto),
   só compacto pra caber vários por card.

   14/08: tentadas várias revisões visuais neste bloco a pedido do
   usuário (sem bolha/sem caixa/número colorido/cores neutras/caixa com
   borda animada) — no fim das contas ele preferiu voltar exatamente
   pro que já estava aqui desde 20/07. Nenhuma mudança líquida ficou
   deste episódio; documentado só pra quem notar o histórico de commits
   "ir e voltar" no CSS não estranhar. */
.setor-mini-grade { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; margin-top: 4px; }
.setor-mini-tile {
  background: var(--superficie-2); border: 1px solid var(--borda); border-radius: var(--raio-sm);
  padding: 10px 12px 9px; position: relative; overflow: hidden; display: block;
  text-decoration: none; color: inherit;
  transition: box-shadow var(--transicao), transform var(--transicao), border-color var(--transicao);
}
.setor-mini-tile:hover { box-shadow: var(--sombra-2); transform: translateY(-1px); border-color: var(--cor, var(--azul)); }
.setor-mini-tile::before {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: var(--cor, var(--azul));
}
.setor-mini-tile::after {
  content: ''; position: absolute; right: -18px; top: -18px; width: 64px; height: 64px;
  border-radius: 50%; background: var(--cor, var(--azul)); opacity: .07; pointer-events: none;
}
.setor-mini-num { font-family: 'IBM Plex Sans', sans-serif; font-size: 21px; font-weight: 800; position: relative; line-height: 1.1; }
.setor-mini-rot { font-size: 10.5px; color: var(--tinta-3); margin-top: 2px; position: relative; }
.setor-mini-barra { height: 3px; border-radius: var(--raio-pill); background: var(--superficie-3); margin-top: 7px; position: relative; overflow: hidden; }
.setor-mini-barra-v { height: 100%; background: var(--cor, var(--azul)); border-radius: var(--raio-pill); }

.veiculo-cartao {
  margin-bottom: 16px; border-left: 3px solid var(--cor, var(--azul));
}
.veiculo-status { display: flex; align-items: center; gap: 8px; font-size: 14px; margin-bottom: 4px; }
.veiculo-bolinha {
  width: 9px; height: 9px; border-radius: 50%; background: var(--cor, var(--azul)); flex-shrink: 0;
}

/* ── Topo da Visão Geral: Veículo/Salas + Calendário + campanha ─────────────
   Pedido do usuário (23/07): Veículo e Salas empilhados numa coluna,
   Calendário sempre do lado, e a campanha do RH (quando ativa) entra como
   3ª coluna. Sem campanha, só 2 colunas; com campanha, aperta um pouco as
   duas primeiras pra dar mais espaço pro banner (é arte gráfica, precisa
   respirar — mesmo motivo do tamanho grande de `.campanha-rh-carrossel`). */
.geral-topo {
  display: grid; gap: 18px; align-items: stretch; margin-bottom: 18px;
  grid-template-columns: minmax(260px, 1fr) minmax(240px, .85fr);
}
.geral-topo.com-campanha { grid-template-columns: minmax(240px, .9fr) minmax(230px, .8fr) minmax(260px, 1.3fr); }
@media (max-width: 1240px) {
  .geral-topo.com-campanha { grid-template-columns: 1fr 1fr; }
  .geral-topo.com-campanha > .campanha-rh-carrossel-lateral { grid-column: 1 / -1; }
}
@media (max-width: 860px) {
  .geral-topo, .geral-topo.com-campanha { grid-template-columns: 1fr; }
  .geral-topo.com-campanha > .campanha-rh-carrossel-lateral { grid-column: auto; }
}
/* Veículo + Salas ficam COLADOS um no outro (pedido do usuário, 23/07: "o
   uso de veículo fique junto de salas") — sem `space-between` (que antes
   espalhava os dois pra cobrir a altura toda da coluna, deixando um vão
   vazio no meio). O espaço que sobra até a altura do Calendário (que o
   `align-items: stretch` do .geral-topo já estica a coluna pra bater) vai
   pro `.avisos-coluna` logo abaixo — `flex: 1` absorve exatamente esse
   sobra, com os avisos/anúncios dentro dele; sem nenhum aviso ativo, fica
   só espaço vazio ali (aceito pelo usuário: "caso não tenha vai ficar lá
   sem avisos no momento"). */
.geral-topo-coluna { display: flex; flex-direction: column; }
.geral-topo-coluna .veiculo-cartao:last-child { margin-bottom: 0; }
.avisos-coluna { flex: 1; display: flex; flex-direction: column; gap: 10px; margin-top: 14px; overflow-y: auto; }
.avisos-coluna .anuncio-aviso { margin-bottom: 0; }
/* Carrossel de avisos (18/08, item #5 da lista grande; rolagem/altura
   fixa/10s pedidos numa leva seguinte) — 2+ ativos ao mesmo tempo
   mostram só 1 por vez, ROLANDO pra cima (JS em geral.html, translateY).
   Diferente de `.campanha-rh-slide` (altura fixa em CSS, cartaz sempre
   do mesmo tamanho): aqui o texto tem altura variável, então o JS mede
   o maior aviso e trava a altura do `.avisos-viewport` nesse valor —
   sem isso, trocar de aviso mudava o tamanho da coluna e balançava o
   resto da página (incômodo relatado pelo usuário). Com 0/1 aviso
   ativo, `.avisos-viewport` fica sem estilo nenhum (JS nem roda). */
/* Horizontal, não vertical (27/08, pedido do usuário: "consigo ver as
   bordas de outro [aviso]... o mais interessante é o carrossel ser
   horizontal") — a versão anterior empilhava os cards com `position:
   absolute` + `translateY`, e a borda/sombra do card ficando por cima
   vazava por baixo do que ainda estava saindo, sensível a arredondamento
   de subpixel. Rolagem horizontal nativa do navegador (`scroll-snap`) não
   sobrepõe elemento nenhum — só 1 card por vez fica na área visível,
   sem cálculo de posição manual, sem esse tipo de vazamento. */
.avisos-coluna.avisos-carrossel .avisos-viewport {
  display: flex; overflow-x: hidden; scroll-snap-type: x mandatory;
  scroll-behavior: smooth; border-radius: var(--raio-lg);
  /* 28/08: a altura agora acompanha o card ATIVO (ver medirAlturaAtiva em
     geral.html), não mais o maior entre todos — essa transição deixa a
     mudança de altura suave entre um card curto e um longo, em vez de
     travar sempre no tamanho do maior (sobrava espaço vazio enorme nos
     cards curtos). */
  transition: height .25s ease;
  /* `align-items: flex-start` (28/08) — sem isso, o padrão do flexbox
     (`stretch`) fazia cada `.anuncio-aviso` esticar até a altura do
     PRÓPRIO `.avisos-viewport`; como `.avisos-coluna` tem `flex: 1` (pra
     acompanhar a coluna do Calendário ao lado), na primeira carga (antes
     do JS travar a altura) o viewport já nascia esticado até o tamanho
     da coluna vizinha, e o JS acabava MEDINDO esse valor já inflado —
     travava um card curto do tamanho de um card longo, um espaço vazio
     enorme dentro da própria borda do aviso. Com `flex-start`, o card
     sempre nasce do tamanho do próprio conteúdo, e é ESSA medida (a
     certa) que o JS trava.
  */
  align-items: flex-start;
}
.avisos-coluna.avisos-carrossel .anuncio-aviso {
  flex: 0 0 100%; scroll-snap-align: start; margin: 0;
}
.avisos-pontos { display: flex; justify-content: center; gap: 7px; margin-top: 2px; }
.avisos-ponto {
  width: 7px; height: 7px; border-radius: 50%; border: none; padding: 0;
  background: var(--borda); cursor: pointer; transition: background .2s;
}
.avisos-ponto.ativo { background: var(--azul); }

/* Contador + setas no topo do carrossel de avisos (27/08, pedido do
   usuário: "pare a rolagem automática... coloque um contador... pra pessoa
   selecionar se quer avançar ou regredir porque dependendo do comunicado,
   não dá tempo de ler") — troca a rolagem sozinha (`setInterval`) por
   navegação manual só. Mesma altura/posição em toda tela: a pessoa sempre
   sabe quantos avisos tem e em qual está, sem precisar contar as bolinhas
   pequenas de `.avisos-pontos` (que continuam existindo, como atalho pra
   pular direto pra um aviso específico). */
.avisos-nav { display: flex; align-items: center; justify-content: center; gap: 12px; margin-bottom: 4px; }
.avisos-nav-seta {
  width: 26px; height: 26px; border-radius: 50%; border: 1px solid var(--borda-2);
  background: var(--superficie-2); color: var(--tinta-2); font-size: 14px; line-height: 1;
  cursor: pointer; display: flex; align-items: center; justify-content: center;
  transition: background var(--transicao), color var(--transicao);
}
.avisos-nav-seta:hover { background: var(--azul); color: #fff; }
.avisos-nav-contador { font-size: 12px; font-weight: 700; color: var(--tinta-3); min-width: 52px; text-align: center; }

/* Aviso de despedida no fim do expediente (27/08) — toast discreto no
   canto, diferente do overlay cheio de tela do logout
   (`.boas-vindas-saudacao`): aqui a pessoa pode estar no meio de
   trabalhar, um overlay bloqueando a tela seria intrusivo demais pra um
   aviso que não pede ação nenhuma. */
.despedida-toast {
  position: fixed; right: 22px; bottom: 22px; z-index: 300; max-width: 300px;
  display: flex; align-items: flex-start; gap: 12px; padding: 14px 16px;
  background: var(--vidro-bg-solido); border: 1px solid var(--vidro-borda);
  border-radius: var(--raio-lg); box-shadow: var(--sombra-3);
  backdrop-filter: var(--vidro-blur); -webkit-backdrop-filter: var(--vidro-blur);
  opacity: 0; transform: translateY(12px); transition: opacity .35s ease, transform .35s ease;
}
.despedida-toast.mostrando { opacity: 1; transform: translateY(0); }
.despedida-toast-emoji { font-size: 22px; line-height: 1; flex-shrink: 0; }
.despedida-toast-texto { font-size: 13px; color: var(--tinta-2); line-height: 1.4; }
.despedida-toast-texto strong { display: block; color: var(--tinta); font-size: 14px; margin-bottom: 2px; }
.despedida-toast-fechar {
  background: none; border: 0; cursor: pointer; color: var(--tinta-3);
  font-size: 13px; line-height: 1; padding: 2px 4px; margin-left: auto; flex-shrink: 0;
}
.despedida-toast-fechar:hover { color: var(--tinta); }
@media (max-width: 560px) { .despedida-toast { right: 12px; left: 12px; bottom: 12px; max-width: none; } }

/* ── Calendário de eventos (23/07) ─────────────────────────────────────────
   Passou por vários ajustes de tamanho no mesmo dia: "menor" → "pode
   manter" → "maior" → "está gigante, diminuir uns 40%" → "aumente a
   largura" → "aumente mais a largura e diminua a altura". Grade com
   largura TRAVADA e centralizada (não estica pra acompanhar a coluna
   inteira, que ficou mais estreita também em .geral-topo acima); célula
   do dia (`.cal-dia`) usa `aspect-ratio: 1.4` (mais larga que alta) em
   vez de quadrada — é o que deixa a grade mais larga SEM crescer em
   altura junto (largura maior, cada linha mais baixa). */
/* ── Coluna Humor + Calendário (28/07) ──────────────────────────────────────
   Pedido do usuário: o widget de "Humor do dia" fica acima do Calendário,
   "sem mover a estrutura pra baixo" — resolvido empilhando os dois DENTRO
   do mesmo slot de grade que só o Calendário ocupava (não vira uma 3ª
   coluna nem um bloco de largura cheia acima de `.geral-topo`, então nada
   fora dessa coluna se move). */
/* `align-self: start` (27/08) — sem isso, `align-items: stretch` do
   `.geral-topo` esticava essa coluna até a altura da coluna mais alta
   (Veículo+Salas+Avisos, que absorve sobra com `.avisos-coluna { flex:
   1 }`), deixando um vão vazio embaixo do Calendário sem nada pra
   preencher (achado real do usuário: "ficou um gap de espaço enorme,
   abaixo do calendário e das campanhas"). Agora a coluna só ocupa a
   altura que o próprio Calendário precisa. */
.geral-topo-coluna-calendario { display: flex; flex-direction: column; gap: 18px; align-self: start; }
.humor-cartao { margin-bottom: 0; }
.humor-opcoes { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin: 12px 0 10px; }
.humor-botao {
  display: flex; align-items: center; justify-content: center; padding: 10px 4px;
  border-radius: var(--raio); border: 1px solid var(--borda); background: var(--superficie-2);
  cursor: pointer; transition: background var(--transicao), border-color var(--transicao), transform var(--transicao);
}
.humor-botao:hover { background: var(--superficie-3); transform: scale(1.08); }
.humor-botao.ativo { border-color: var(--azul); background: var(--lavagem-azul); }
.humor-emoji { font-size: 28px; line-height: 1; }
.humor-status { font-size: 12.5px; color: var(--tinta-2); margin: 0; text-align: center; }

.calendario-cartao { display: flex; flex-direction: column; }
.calendario-nav { display: flex; align-items: center; justify-content: space-between; margin: 2px auto 8px; font-size: 12px; max-width: 460px; width: 100%; }
.calendario-nav button {
  width: 22px; height: 22px; border-radius: 50%; border: 1px solid var(--borda);
  background: var(--superficie-2); color: var(--tinta-2); cursor: pointer; font-size: 13px; line-height: 1;
  transition: background var(--transicao), color var(--transicao);
}
.calendario-nav button:hover { background: var(--superficie-3); color: var(--azul); }
/* `.evcal-dias-semana` (NÃO `.calendario-semana`) de propósito — essa
   classe genérica já é usada pelo calendário "grade completa" do
   Financeiro/Absenteísmo (ver mais abaixo, bloco de 20/07). CSS herda por
   PROPRIEDADE, não por bloco inteiro: usar o mesmo nome aqui vazava
   max-width/margin pra aquele calendário e espremia as linhas de dia numa
   faixa estreita, sem afetar o cabeçalho (classe diferente) — a cara de
   "calendário quebrado" que o usuário reportou (23/07) no dashboard
   financeiro. Corrigido isolando com nome próprio. */
.evcal-dias-semana, .calendario-grade { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; max-width: 460px; margin: 0 auto; width: 100%; }
.evcal-dias-semana span { text-align: center; font-size: 9px; color: var(--tinta-3); font-weight: 700; padding-bottom: 3px; }
.cal-dia {
  aspect-ratio: 1.4; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 1px; border: 0; border-radius: var(--raio-sm); background: transparent; color: var(--tinta);
  font: inherit; font-size: 10px; cursor: pointer; transition: background var(--transicao);
}
.cal-dia:hover { background: var(--superficie-2); }
.cal-dia-vazio { cursor: default; }
.cal-dia-vazio:hover { background: transparent; }
.cal-dia-hoje { font-weight: 800; color: var(--azul); }
.cal-pontos { display: flex; gap: 1.5px; }
.cal-dot { width: 4px; height: 4px; border-radius: 50%; display: inline-block; }
.cal-dot-aniversario { background: var(--st-afastado); }
.cal-dot-aniversario_empresa { background: var(--verde); }
.cal-dot-campanha { background: var(--teal); }
.cal-dot-acao { background: var(--azul); }
.cal-dot-evento { background: var(--st-standby); }
.cal-dot-aso { background: var(--azul-claro); }
.cal-dot-procedimento { background: var(--st-critico); }
.calendario-legenda { display: flex; flex-wrap: wrap; gap: 8px 12px; margin-top: 10px; font-size: 10.5px; color: var(--tinta-3); }
.calendario-legenda span { display: inline-flex; align-items: center; gap: 4px; }
.cal-evento {
  display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 12.5px;
  padding: 6px 8px; border-radius: var(--raio-sm); background: var(--superficie-2);
  border-left: 3px solid var(--cor-evento, var(--azul));
}
.cal-evento-aniversario { --cor-evento: var(--st-afastado); }
.cal-evento-aniversario_empresa { --cor-evento: var(--verde); }
.cal-evento-campanha { --cor-evento: var(--teal); }
.cal-evento-acao { --cor-evento: var(--azul); }
.cal-evento-evento { --cor-evento: var(--st-standby); }
.cal-evento-aso { --cor-evento: var(--azul-claro); }
.cal-evento-procedimento { --cor-evento: var(--st-critico); }
.cal-evento-remover { border: 0; background: transparent; color: var(--tinta-3); cursor: pointer; font-size: 12px; flex-shrink: 0; }
.cal-evento-remover:hover { color: var(--st-critico); }
.cal-evento-vazio { font-size: 12px; color: var(--tinta-3); font-style: italic; }
.cal-form-novo { display: flex; flex-direction: column; gap: 6px; margin-top: 4px; }
.cal-form-novo input {
  padding: 7px 9px; border-radius: var(--raio-sm); border: 1px solid var(--borda);
  background: var(--superficie); color: var(--tinta); font: inherit; font-size: 12.5px;
}
/* Botão "Adicionar" do popup de dia do Calendário (Visão Geral) — achado
   na padronização de 05/08 (usuário: "padronize botões de adicionar,
   calendario, voltar"): estava sem NENHUMA classe de botão do sistema
   (`<button type="submit">` cru dentro de uma string JS), caindo no
   visual padrão do navegador. Mesmo gradiente "glossy" de `.btn-att`,
   compacto pra caber no popup pequeno. */
.cal-form-novo button {
  align-self: flex-start; font: inherit; font-size: 12.5px; font-weight: 600; color: #fff;
  background: linear-gradient(180deg, var(--azul-claro) 0%, var(--azul) 55%, var(--azul-escuro) 100%);
  border: 0; border-radius: var(--raio-pill); padding: 7px 16px; cursor: pointer;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .35), 0 4px 10px rgba(7, 99, 160, .24);
  transition: filter var(--transicao), transform var(--transicao);
}
.cal-form-novo button:hover { filter: brightness(1.07); transform: translateY(-1px); }
.cal-form-novo button:active { transform: translateY(1px); filter: brightness(.97); }

/* ── 11. Administração de usuários ───────────────────────────────────────── */
.tabela-usuarios { width: 100%; table-layout: fixed; border-collapse: collapse; font-size: 13px; }
.tabela-usuarios th {
  text-align: left; font-size: 10.5px; text-transform: uppercase; letter-spacing: .07em;
  color: var(--tinta-3); font-weight: 600; padding: 0 10px 10px;
}
.tabela-usuarios td { padding: 12px 10px; border-top: 1px solid var(--borda); vertical-align: middle; overflow-wrap: break-word; word-break: break-word; }
.tabela-usuarios label.chk { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; margin-right: 12px; margin-bottom: 4px; white-space: normal; }
.usuario-nome { font-weight: 600; }
.usuario-email { font-size: 11.5px; color: var(--tinta-3); margin-top: 2px; overflow-wrap: break-word; word-break: break-word; }
/* `.btn-salvar` base + variante compacta de tabela agora vivem juntas lá
   em cima (seção dos botões "glossy", perto de `.btn-att`) — não
   duplicar aqui. */
.tabela-usuarios .btn-x-remover {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; flex-shrink: 0;
  font: inherit; font-size: 14px; font-weight: 700; line-height: 1;
  color: var(--tinta-2); background: var(--superficie-3);
  border: 0; border-radius: var(--raio-sm); cursor: pointer;
  transition: background var(--transicao), color var(--transicao);
}
.tabela-usuarios .btn-x-remover:hover { background: var(--st-critico); color: #fff; }
.tabela-usuarios .ajuda-campo { font-size: 11px; color: var(--tinta-3); margin: 6px 0 0; }
.tabela-usuarios .vazio-inline { font-size: 12.5px; color: var(--tinta-3); font-style: italic; }

.tabela-usuarios label.chk-admin { white-space: nowrap; }
/* Setor público (Almoxarifado/Arquivos/CIPA/Melhorias) na tela de
   permissões — pedido do usuário (29/07): "os que são públicos pode
   ficar marcado como check lá automaticamente sem poder retirar" +
   "ai pode ficar com um check cinza". Cursor padrão (não-clicável) e
   texto/ícone acinzentados, pra ficar claro que é só informativo. */
.tabela-usuarios label.chk-publico { color: var(--tinta-3); cursor: default; }
.tabela-usuarios label.chk-publico input { cursor: default; }

.troca-senha-caixa { position: relative; display: inline-block; }
.btn-trocar-senha {
  font: inherit; font-size: 12.5px; font-weight: 600; color: var(--azul); background: var(--superficie-3);
  border: 0; border-radius: var(--raio-sm); padding: 7px 13px; cursor: pointer; white-space: nowrap;
  transition: background var(--transicao);
}
.btn-trocar-senha:hover { background: var(--superficie-2); }
.senha-popover {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 30; width: 210px;
  background: var(--superficie); border: 1px solid var(--borda); border-radius: var(--raio-sm);
  box-shadow: var(--sombra-2); padding: 12px;
}
.senha-popover .campo-senha input {
  width: 100%; font: inherit; font-size: 12.5px; color: var(--tinta);
  background: var(--superficie-2); border: 1px solid var(--borda-2);
  border-radius: var(--raio-sm); padding: 7px 8px;
}

/* ── Dashboard de RH ─────────────────────────────────────────────────────── */

/* Qualquer elemento com data-drill abre o modal de nomes (base.html) —
   um único seletor global em vez de repetir "cursor: pointer" em cada gráfico. */
[data-drill] { cursor: pointer; }

/* Colunas agrupadas (2 barras por mês) — reaproveita .colunas/.col/.col-r de
   painel.html, só adiciona o par de barras lado a lado dentro de cada .col. */
.col-par { display: flex; align-items: flex-end; justify-content: center; gap: 3px; height: 100%; width: 100%; }
.col-b2 {
  flex: 1; max-width: 16px; min-height: 2px; border-radius: 3px 3px 0 0; position: relative;
  transition: opacity var(--transicao), filter var(--transicao);
}
.col-par:hover .col-b2 { opacity: .45; }
.col-b2:hover { opacity: 1 !important; filter: brightness(1.08); }
.col-b2.zero { background: var(--superficie-3) !important; }
.col-v2 {
  position: absolute; top: -15px; left: 50%; transform: translateX(-50%);
  font-size: 9.5px; font-weight: 700; color: var(--tinta-2); white-space: nowrap;
}
/* Mesmo tratamento de `.col-v` (10/08, auditoria mobile) — ver comentário
   lá em cima. */
@media (max-width: 640px) {
  .col-v2 { max-width: 48px; overflow: hidden; text-overflow: ellipsis; }
}

/* Modal de drill-down (base.html) */
/* Modal em vidro (04/08, reforma "Liquid Glass") — `.modal-fundo` desfoca
   a PRÓPRIA tela por trás (efeito "sheet" do iOS), `.modal-caixa` usa os
   mesmos tokens `--vidro-*` do topo, então acompanha o tema claro/escuro
   sozinho. */
.modal-fundo {
  position: fixed; inset: 0; z-index: 200; display: flex; align-items: center; justify-content: center;
  background: rgba(10, 14, 20, .38);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  padding: 24px;
}
.modal-fundo[hidden] { display: none; }
/* Usa `--vidro-bg-solido` (opaca, sem depender de blur pra ler bem) em vez
   de `--vidro-bg` — achado real (04/08): "sempre que abrir um box
   transparente com o fundo branco, fica difícil a leitura". Modal tem
   conteúdo de verdade (busca, listas, formulários com texto normal do
   sistema, não escopado igual `.auth-caixa`) — precisa de opacidade
   confiável, não vale a pena arriscar legibilidade só pelo efeito. Sem
   `backdrop-filter` aqui por consequência (com fundo quase opaco, o
   desfoque/distorção quase não apareceria — `.modal-fundo` (o fundo
   escurecido atrás do modal inteiro) continua com blur de verdade, esse
   efeito É visível. */
.modal-caixa {
  /* `--superficie` (opaca de verdade, 100%) em vez de `--vidro-bg-solido`
     (90-92% de alfa) — achado real (12/08): mesmo "opaco pra ler bem", os
     8-10% de transparência deixavam texto de conteúdo atrás (ex.: uma
     mensagem do chat, bem atrás do modal de enquete) sangrar de leve por
     trás do próprio texto do modal, um "fantasma" visível perto de rótulos
     como "OPÇÃO 1". Modal não precisa do efeito vidro, só precisa nunca
     falhar em legibilidade — `--vidro-bg-solido` continua servindo card/
     tile, onde um pouco de translucidez é intencional. */
  background: var(--superficie);
  border: 1px solid var(--vidro-borda); border-radius: var(--raio-lg);
  box-shadow: inset 0 1px 0 var(--vidro-realce), var(--vidro-sombra), 0 30px 70px rgba(0, 0, 0, .22);
  width: 100%; max-width: 420px; max-height: 72vh;
  display: flex; flex-direction: column;
}
.modal-caixa-topo {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 16px 18px; border-bottom: 1px solid var(--vidro-borda);
}
.modal-caixa-topo h3 { font-size: 15px; }
.modal-fechar {
  border: 0; background: transparent; color: var(--tinta-3); font-size: 15px;
  cursor: pointer; line-height: 1; padding: 4px;
}
.modal-fechar:hover { color: var(--tinta); }
.modal-busca { padding: 12px 18px 0; }
.modal-busca input {
  width: 100%; font: inherit; font-size: 13px; padding: 8px 11px; border-radius: var(--raio-sm);
  border: 1px solid var(--borda-2); background: var(--superficie-2); color: var(--tinta);
}
.modal-busca input:focus { outline: none; border-color: var(--azul); }
.modal-lista { overflow-y: auto; padding: 10px 18px 18px; }
/* Achado real (04/08, reportado pelo usuário): "ao clicar no calendário,
   quando tem evento, fica scrollável e bugado" — o corpo do modal de
   evento do dia (`#cal-modal-corpo`, geral.html) é um `<div>` cru dentro
   de `.modal-caixa` (que já é `display: flex; flex-direction: column;
   max-height: 72vh`), sem `overflow-y`/`min-height: 0` próprios — sem
   isso, um flex column com altura máxima não sabe rolar o filho que
   estoura o espaço, e cresce/rola de um jeito estranho em vez de só
   rolar o conteúdo por dentro (mesmo bug que `.modal-lista` já resolve
   pro modal de drill-down genérico — este aqui só não tinha o mesmo
   tratamento). Provavelmente já existia antes da reforma "vidro", só
   ficou mais visível agora que o usuário testou de novo. */
#cal-modal-corpo { overflow-y: auto; flex: 1; min-height: 0; }
.modal-lista ul { list-style: none; margin: 0; padding: 0; }
.modal-lista li {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: 0 8px;
  font-size: 13px; padding: 7px 2px; border-bottom: 1px solid var(--borda);
}
.modal-lista li:last-child { border-bottom: 0; }
.modal-nome { color: var(--tinta); font-weight: 500; }
/* Item de drill-down com link (03/08, Painel de Prioridades) — mesma cor
   de link do resto do sistema, sublinhado só no hover pra não parecer
   texto sublinhado à toa no repouso. */
.modal-nome-link { color: var(--azul); text-decoration: none; cursor: pointer; }
.modal-nome-link:hover { text-decoration: underline; }
.modal-cargo { color: var(--tinta-3); font-size: 11.5px; }
.modal-data { color: var(--tinta-3); font-size: 11.5px; flex-basis: 100%; }
.modal-vazio { font-size: 13px; color: var(--tinta-3); padding: 8px 2px; }

/* Cartão de sessão/tarefa de Treinamentos (30/07, calendário + Integrações
   LEAR) — "mais lúdico" pedido pelo usuário: selo de status colorido, tags
   como chips (reaproveita .tag/.selo-status já existentes, nenhuma cor
   nova) e observação num bloco de texto próprio. */
.cartao-treino {
  padding: 12px 14px; border: 1px solid var(--borda); border-radius: var(--raio-sm);
  background: var(--superficie-2); margin-bottom: 10px;
}
.cartao-treino:last-child { margin-bottom: 0; }
.cartao-treino-topo { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.cartao-treino-nome { color: var(--tinta); font-weight: 600; font-size: 13.5px; text-decoration: none; }
.cartao-treino-nome:hover { color: var(--azul); text-decoration: underline; }
.cartao-treino-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.cartao-treino-resp { color: var(--tinta-2); font-size: 12px; margin: 8px 0 0; }
.cartao-treino-obs {
  color: var(--tinta-3); font-size: 12px; margin: 6px 0 0; white-space: pre-line;
  border-left: 2px solid var(--borda-2); padding-left: 8px;
}

/* Cursor customizado: ponto sólido + halo desfocado seguindo o mouse, em vez
   da seta padrão do sistema operacional. Só em dispositivo com mouse de
   verdade (hover+ponteiro fino) — em touch a seta nem existe, então não faz
   sentido esconder nada lá. */
@media (hover: hover) and (pointer: fine) {
  * { cursor: none !important; }

  .cursor-ponto, .cursor-halo {
    position: fixed; top: 0; left: 0; border-radius: 50%;
    pointer-events: none; z-index: 2000; transform: translate(-50%, -50%);
    transition: width var(--transicao), height var(--transicao), opacity var(--transicao);
  }
  /* Bordinha clara + sombra escura sutil por fora — sem isso, a bolinha azul
     quase some em cima de qualquer botão/tag que já seja azul (pedido do
     usuário depois de notar na prática). */
  .cursor-ponto {
    width: 10px; height: 10px; background: var(--azul);
    box-shadow: 0 0 0 1.5px rgba(255, 255, 255, .95), 0 1px 4px rgba(0, 0, 0, .35);
  }
  .cursor-halo { width: 30px; height: 30px; background: var(--azul); opacity: .18; filter: blur(8px); }
  .cursor-ponto.grande { width: 16px; height: 16px; }
  .cursor-halo.grande { width: 46px; height: 46px; opacity: .24; }

  /* "Negativo" sobre fundo escuro (pedido do usuário, 05/08: "nas partes
     brancas fica azul como era, e na parte azul fica branca") — JS
     (`_cursor.html`) calcula a cor de fundo de verdade embaixo do cursor
     (varrendo os ancestrais até achar um `background-color` ou o meio de
     um `background-image` em gradiente) e aplica a MESMA fórmula YIQ já
     usada em `metricas._texto_legivel` (texto branco/preto sobre etiqueta
     colorida) — fundo escuro o bastante (brilho < 140) troca `.cursor-
     ponto`/`.cursor-halo` pra branco; fundo claro mantém o azul de
     sempre. Não é troca condicionada literalmente a "azul" — generaliza
     pra qualquer fundo escuro o bastante (inclusive botão vermelho/verde),
     mesmo raciocínio de contraste, sem precisar listar cor por cor. */
  .cursor-ponto.invertido {
    background: #fff;
    box-shadow: 0 0 0 1.5px rgba(7, 99, 160, .55), 0 1px 4px rgba(0, 0, 0, .45);
  }
  .cursor-halo.invertido { background: #fff; }

  /* Variante triangular — pedido do usuário (22/07): "alguns não foram
     adeptos ao bolinha [...] formato triangular mas em formato mais
     moderno". Pedido depois de ver a 1ª versão (um triângulo puro):
     "tente seguir o conceito de um cursor mais bonito, esse é um
     triângulo PURO" — trocado pro contorno clássico de cursor/seta (com
     o "rabinho" característico), em vez de 3 pontas retas. `clip-path`
     recorta o quadrado nesse contorno; a borda de contraste vira
     `drop-shadow` empilhado (4 direções sem blur) porque `box-shadow` não
     acompanha o recorte do clip-path.

     Cor: azul escuro com borda branca no tema claro; branco com borda
     escura no tema escuro (pedido do usuário) — cada combinação garante
     contraste com o fundo predominante daquele tema. */
  /* Depois de várias tentativas em CSS puro (clip-path) ficarem tortas ou
     sem o acabamento do print de referência do usuário (CURSOR.png,
     inclinado, pontas arredondadas), a forma virou uma IMAGEM de verdade
     — processada a partir do próprio print (fundo removido, virou PNG
     transparente), garantindo a mesma inclinação e acabamento em vez de
     tentar adivinhar coordenadas de novo. Duas versões pré-geradas:
     branca (tema escuro) e azul escura (tema claro) — ver
     `static/cursor_tri_branco.png` / `cursor_tri_azul.png`. */
  .cursor-ponto.tri {
    width: 20px; height: 22px; border-radius: 0; background: transparent;
    background-image: url('/static/cursor_tri_azul.png');
    background-size: contain; background-repeat: no-repeat; background-position: top left;
    clip-path: none; box-shadow: none;
    /* Ponto de clique na PONTA do triângulo, não no centro da imagem
       (pedido do usuário, 03/08: "o clique do mouse... está centralizado,
       tem como colocar ele mais para a ponta"). A base `.cursor-ponto`
       usa `translate(-50%, -50%)` pra centralizar (faz sentido pra uma
       bolinha, onde o "clique" É o centro) — pra um cursor em formato de
       seta, o ponto de clique de verdade é a PONTA, não o meio do
       retângulo da imagem. Medido pixel a pixel no PNG de origem (264×296,
       ponta em ~(90,68)) — vale tanto pro tamanho normal quanto pro
       `.grande` porque `%` num `transform: translate()` é relativo ao
       próprio tamanho do elemento, escala sozinho. */
    transform: translate(-34%, -23%);
    /* Brilho/bordinha suave branca — pedido do usuário (22/07): "quero
       que brilhe um pouco mais claro o cursor triângulo, pra destacar um
       pouco mais, ou senão ter uma bordinha suave branca". */
    filter: drop-shadow(0 0 1px rgba(255, 255, 255, .55));
  }
  :root[data-tema="escuro"] .cursor-ponto.tri {
    background-image: url('/static/cursor_tri_branco.png');
    filter: drop-shadow(0 0 1px rgba(0, 0, 0, .45));
  }
  /* Triângulo também vira branco sobre fundo escuro (mesmo pedido do
     ".invertido" acima, 05/08 — "o cursor também", não só o halo). Sem
     isso o triângulo continuava trocando de cor só pelo TEMA do site
     (claro/escuro), nunca pelo fundo LOCAL embaixo do mouse — igual ao
     `.cursor-ponto` normal tinha antes de ganhar `.invertido`. Precisa de
     especificidade maior que a regra de tema escuro logo acima (mesma
     contagem de seletor, `:root[data-tema] .tri` x `.tri.invertido` —
     por isso a variante escura tem sua própria linha abaixo, senão o tema
     escuro venceria a cascata e a borda ficaria escura em vez de azul
     mesmo com o fundo já claro o bastante pra precisar da borda). */
  .cursor-ponto.tri.invertido {
    background-image: url('/static/cursor_tri_branco.png');
    filter: drop-shadow(0 0 1px rgba(7, 99, 160, .65)) drop-shadow(0 1px 3px rgba(0, 0, 0, .4));
  }
  :root[data-tema="escuro"] .cursor-ponto.tri.invertido {
    filter: drop-shadow(0 0 1px rgba(7, 99, 160, .65)) drop-shadow(0 1px 3px rgba(0, 0, 0, .4));
  }
  .cursor-ponto.tri.grande { width: 28px; height: 31px; }
  /* Sobre cartão clicável (tile, fatia de rosca, barra de drill-down) o halo
     BRILHA mais forte, não só cresce — pedido do usuário pra diferenciar de
     um link/botão comum. Declarada depois de .grande de propósito: quando os
     dois se acumulam, o brilho tem que vencer o opacity do .grande. */
  .cursor-halo.brilho { opacity: .55; filter: blur(10px); }

  /* Campo de texto: a bolinha some (JS zera a opacidade) e o cursor NATIVO
     volta aqui — sem isso ficaria impossível ver onde o texto vai ser
     inserido/selecionado. */
  input[type="text"], input[type="search"], input[type="email"],
  input[type="number"], input[type="date"], input[type="password"], textarea {
    cursor: text !important;
  }

  /* A barra de rolagem é controle nativo do navegador — cursor:none não a
     alcança, a setinha do SO volta a aparecer em cima dela em qualquer site
     com esse tipo de cursor customizado. Só dá pra deixar ela discreta. */
  * { scrollbar-width: thin; scrollbar-color: var(--borda-2) transparent; }
  *::-webkit-scrollbar { width: 10px; height: 10px; }
  *::-webkit-scrollbar-track { background: transparent; }
  *::-webkit-scrollbar-thumb { background: var(--borda-2); border-radius: var(--raio-pill); }
  *::-webkit-scrollbar-thumb:hover { background: var(--azul); }
}

/* O cursor customizado (`.cursor-ponto`/`.cursor-halo`, bolinha OU o
   triângulo — ver bloco acima) é um overlay FIXO na tela, não parte do
   documento — sem isso ele saía "congelado" na posição do mouse em
   QUALQUER impressão do sistema (pedido do usuário, 03/08: "quando eu
   vou imprimir aparece a setinha do mouse, porque?"). Regra GLOBAL (fora
   do `@media (hover: hover)` acima, que só controla a tela) — corrige de
   uma vez toda tela que imprime, sem precisar repetir em cada template. */
@media print {
  .cursor-ponto, .cursor-halo { display: none !important; }
}

/* Conquistas (Minha Conta, 10/08, pedido do usuário: "quero que os
   badges fiquem lá na aba de minha conta, lá vai ter as conquistas que
   eu tenho e as que eu não tenho ainda") — vitrine de badges em grade,
   cada um com a própria cor quando CONQUISTADO; o que ainda falta vira
   cinza (`filter: grayscale`), com a "dica" de quanto falta. */
.conquistas-grupo { margin-top: 14px; }
.conquistas-grupo:first-of-type { margin-top: 10px; }
.conquistas-grupo-titulo { font-size: 12px; font-weight: 700; color: var(--tinta-2); text-transform: uppercase; letter-spacing: .03em; margin-bottom: 8px; }
.conquistas-lista { display: flex; flex-wrap: wrap; gap: 10px; }
.conquista-badge {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  width: 108px; padding: 12px 8px; border-radius: var(--raio); text-align: center;
  border: 1.5px solid var(--borda); background: var(--superficie-2);
  transition: transform var(--transicao), box-shadow var(--transicao);
}
.conquista-badge.conquistada {
  border-color: var(--cor-conquista); background: color-mix(in srgb, var(--cor-conquista) 12%, var(--superficie-2));
  box-shadow: 0 2px 8px color-mix(in srgb, var(--cor-conquista) 25%, transparent);
}
.conquista-badge.conquistada:hover { transform: translateY(-2px); }
.conquista-badge.bloqueada { filter: grayscale(1); opacity: .55; }
.conquista-badge-emoji { font-size: 26px; line-height: 1; }
.conquista-badge.bloqueada .conquista-badge-emoji { filter: grayscale(1); }
.conquista-badge-titulo { font-size: 13px; font-weight: 800; color: var(--tinta); line-height: 1.2; margin-top: 2px; }
.conquista-badge-rotulo { font-size: 10.5px; color: var(--tinta-2); line-height: 1.25; }
.conquista-badge-dica { font-size: 10px; color: var(--tinta-3); }

/* Botões de escolha de cursor (Minha conta) — cada um mostra uma prévia
   estática da forma (bolinha ou triângulo) fora do @media de hover, porque
   a tela de configuração precisa ficar visível em QUALQUER dispositivo,
   mesmo touch. */
.cursor-opcoes { display: flex; gap: 12px; margin-top: 10px; }
.cursor-opcao {
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  padding: 14px 18px; border-radius: var(--raio); border: 1.5px solid var(--borda);
  background: var(--superficie-3); cursor: pointer; font-size: 12.5px; color: var(--tinta-2);
}
.cursor-opcao.selecionada { border-color: var(--azul); background: var(--lavagem-azul); color: var(--tinta); font-weight: 600; }
.cursor-opcao-prev {
  width: 30px; height: 30px; display: flex; align-items: center; justify-content: center;
  border-radius: 8px; background: var(--tinta-3);
}
.cursor-opcao-prev-bolinha { width: 14px; height: 14px; border-radius: 50%; background: var(--azul); box-shadow: 0 0 0 1.5px rgba(255,255,255,.95), 0 1px 4px rgba(0,0,0,.35); }
.cursor-opcao-prev-triangulo {
  width: 20px; height: 22px; background-image: url('/static/cursor_tri_azul.png');
  background-size: contain; background-repeat: no-repeat; background-position: top left;
}
:root[data-tema="escuro"] .cursor-opcao-prev-triangulo { background-image: url('/static/cursor_tri_branco.png'); }

/* ── Heatmap de severidade (dashboard de absenteísmo) ─────────────────────
   O print de referência (Power BI) usa uma escala arco-íris (azul→verde→
   amarelo→vermelho) pra magnitude — a skill dataviz proíbe isso de propósito
   (rainbow em magnitude engana a leitura). Em vez disso, reaproveita as
   MESMAS cores de status já validadas no projeto (verde/âmbar/vermelho),
   como uma severidade de 3 graus — mesma linguagem visual de `.dias.alerta`/
   `.dias.critico` que "Onde está parado" já usa. */
.heatmap { display: flex; flex-wrap: wrap; gap: 8px; }
.heatmap-celula {
  width: 64px; height: 64px; border-radius: var(--raio-sm); border: 1px solid transparent;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  cursor: pointer; transition: transform var(--transicao);
}
.heatmap-celula:hover { transform: translateY(-2px); }
.heatmap-celula .valor { font-family: 'IBM Plex Sans', sans-serif; font-weight: 800; font-size: 14px; }
.heatmap-celula .rotulo { font-size: 9.5px; text-transform: uppercase; letter-spacing: .04em; opacity: .75; }
.heatmap-celula.ok { background: var(--lavagem-verde); color: var(--st-concluido); border-color: var(--st-concluido); }
.heatmap-celula.atencao { background: var(--lavagem-ambar); color: var(--st-standby); border-color: var(--st-standby); }
.heatmap-celula.critico { background: var(--lavagem-vermelho); color: var(--st-critico); border-color: var(--st-critico); }
.heatmap-legenda { display: flex; gap: 16px; margin-top: 12px; font-size: 11.5px; color: var(--tinta-3); }
.heatmap-legenda span { display: flex; align-items: center; gap: 6px; }
.heatmap-legenda i { width: 10px; height: 10px; border-radius: 3px; display: inline-block; }

/* Barras do "Comparativo Mensal" (.colunas/.col-b já existentes) coloridas
   pela mesma severidade de 3 graus do heatmap — reaproveita as cores de
   status como preenchimento sólido em vez do fundo claro (lavagem-*). */
.col-b.ok { background: linear-gradient(180deg, color-mix(in srgb, var(--st-concluido) 100%, white 28%) 0%, var(--st-concluido) 100%); }
.col-b.atencao { background: linear-gradient(180deg, color-mix(in srgb, var(--st-standby) 100%, white 28%) 0%, var(--st-standby) 100%); }
.col-b.critico { background: linear-gradient(180deg, color-mix(in srgb, var(--st-critico) 100%, white 28%) 0%, var(--st-critico) 100%); }

/* Calendário do "Comparativo Diário" — grade semana x dia, célula colorida
   pela mesma severidade. */
.calendario-titulo { font-weight: 700; font-size: 13px; margin: 16px 0 8px; color: var(--tinta); }
.calendario-titulo:first-child { margin-top: 0; }
.calendario { display: flex; flex-direction: column; gap: 4px; margin-bottom: 4px; }
/* `minmax(0, 1fr)`, não só `1fr` (10/08, auditoria mobile) — clássica
   pegadinha do CSS Grid: uma trilha `1fr` sozinha não encolhe abaixo do
   conteúdo mínimo da célula (o número/quantidade dentro de `.calendario-
   dia`), então num celular estreito a grade de 7 dias ficava maior que a
   tela e estourava a página inteira. `minmax(0, 1fr)` deixa a trilha
   encolher de verdade — mesmo componente usado em Absenteísmo,
   Treinamentos (Escritório) e Integrações LEAR, corrigido aqui uma vez
   só. */
.calendario-cabecalho, .calendario-semana { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 4px; }
.calendario-cabecalho span {
  text-align: center; font-size: 10px; text-transform: uppercase; letter-spacing: .05em;
  color: var(--tinta-3); font-weight: 600;
}
.calendario-dia {
  position: relative; aspect-ratio: 1; border-radius: var(--raio-sm); border: 1px solid transparent;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; transition: transform var(--transicao); text-decoration: none;
}
.calendario-dia:hover { transform: translateY(-1px); }
.calendario-dia.vazio { visibility: hidden; cursor: default; }
.calendario-dia .num {
  position: absolute; bottom: 3px; right: 5px;
  font-family: 'IBM Plex Sans', sans-serif; font-weight: 700; font-size: 9.5px; opacity: .8;
}
.calendario-dia .qtd { font-family: 'IBM Plex Sans', sans-serif; font-weight: 800; font-size: 20px; line-height: 1; }
.calendario-dia.ok { background: var(--lavagem-verde); color: var(--st-concluido); border-color: var(--st-concluido); }
.calendario-dia.atencao { background: var(--lavagem-ambar); color: var(--st-standby); border-color: var(--st-standby); }
.calendario-dia.critico { background: var(--lavagem-vermelho); color: var(--st-critico); border-color: var(--st-critico); }
.calendario-dia.futuro { background: var(--superficie-3); color: var(--tinta-3); cursor: default; }
.calendario-dia.futuro:hover { transform: none; }

/* ── Calculadora de custo (RH) — cada colaborador vira 2 linhas: identidade
   + resultado numa, campos de lançamento na de baixo (20/07). Revisão de
   23/07, pedido do usuário: cálculo ao vivo em JS (sem clicar "Calcular"),
   hora extra/noturno OPCIONAIS ("+ adicionar", até 4 lançamentos — polui
   menos que mostrar os 4 sempre), extrato bem estratificado por pessoa,
   vale-alimentação virou marcação simples (soma um valor fixo, não mais
   número livre), mês em edição + "Finalizar o mês" vira histórico local
   (localStorage, nunca vai pro servidor). Classes `.calc-*` (JS-renderizado
   — ver folha_pagamento.html) substituem as antigas `.lanc-linha`/
   `.lanc-campo`/`.lanc-grupo-rot`/`.lanc-detalhe` (Jinja estático). */
.lanc-topo td { border-bottom: 0; padding-bottom: 4px; }
.lanc-campos td { padding-top: 0; }
/* Linha de lançamento recolhida por padrão (12/08, pedido do usuário:
   "seria melhor ficar suspenso toda a parte que fica abaixo do nome do
   colaborador, e ao clicar, abria essa visão" — "ficaria mais compacto").
   `.lanc-campos` nasce escondida; `.aberta` (JS, clique na linha do nome)
   é o que mostra. Especificidade de 2 classes vence a regra de base sem
   precisar de `!important` — e como o filtro de busca (mais abaixo no
   JS) só mexe em `style.display` (inline), continua funcionando por
   cima: linha filtrada fica escondida não importa o estado de aberta/
   fechada; linha que passa no filtro volta a obedecer esta regra (some
   de novo, precisa clicar) — decisão deliberada de manter compacto
   mesmo depois de buscar por nome. */
.lanc-campos { display: none; }
.lanc-campos.aberta { display: table-row; }
.lanc-topo { cursor: pointer; }
.lanc-topo:hover td { background: var(--superficie-2); }
.lanc-topo-seta {
  display: inline-flex; margin-right: 6px; vertical-align: -3px;
  color: var(--tinta-3); transition: transform var(--transicao);
}
.lanc-topo.aberta .lanc-topo-seta { transform: rotate(180deg); }

.calc-mes-barra { display: flex; align-items: flex-end; justify-content: space-between; flex-wrap: wrap; gap: 14px; }
.calc-mes-campo label {
  display: block; font-size: 10px; font-weight: 700; color: var(--tinta-3);
  text-transform: uppercase; letter-spacing: .05em; margin-bottom: 5px;
}
.calc-mes-campo input[type="month"] {
  font: inherit; font-size: 15px; font-weight: 700; color: var(--tinta); background: var(--superficie-2);
  border: 1px solid var(--borda-2); border-radius: var(--raio-sm); padding: 8px 12px;
}
.calc-mes-acoes { display: flex; gap: 10px; flex-wrap: wrap; }
.calc-mes-acoes button:hover { background: var(--superficie-3) !important; }

.calc-historico-lista { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; }
.calc-historico-item {
  border: 1px solid var(--borda); border-radius: var(--raio-sm); padding: 10px 14px;
  background: var(--superficie-2);
}
.calc-historico-item-topo { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.calc-historico-item-topo strong { font-family: 'IBM Plex Sans', sans-serif; text-transform: capitalize; }
.calc-historico-item-topo span { font-size: 12.5px; color: var(--tinta-2); flex: 1; }
.calc-historico-item-topo button {
  background: none; border: 0; cursor: pointer; font-size: 12.5px; font-weight: 600; color: var(--azul);
}

/* Corpo de lançamento de UM colaborador — cartão dentro da célula da
   tabela, não mais uma linha crua de inputs soltos. */
.calc-linha { display: flex; flex-direction: column; gap: 12px; padding: 4px 0 10px; }
.calc-linha-topo, .calc-linha-extra { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px; }
.calc-campo label {
  display: block; font-size: 10px; font-weight: 700; color: var(--tinta-3);
  text-transform: uppercase; letter-spacing: .05em; margin-bottom: 4px; white-space: nowrap;
}
.calc-campo input[type="number"], .calc-campo input[type="text"] {
  font: inherit; font-size: 13.5px; color: var(--tinta); background: var(--superficie-2);
  border: 1px solid var(--borda-2); border-radius: var(--raio-sm); padding: 7px 9px;
  width: 90px; transition: border-color var(--transicao); font-variant-numeric: tabular-nums;
}
.calc-campo input[type="number"]:focus, .calc-campo input[type="text"]:focus { border-color: var(--azul); outline: none; }
.calc-pct-fixo {
  display: inline-block; font-size: 13.5px; color: var(--tinta-2); background: var(--superficie-3);
  border-radius: var(--raio-sm); padding: 7px 9px; font-variant-numeric: tabular-nums;
}
.calc-campo-check { padding-bottom: 2px; }
.calc-campo-check label.chk {
  display: inline-flex; align-items: center; gap: 8px; cursor: pointer; font-size: 13px;
  color: var(--tinta); text-transform: none; font-weight: 500; white-space: nowrap;
}
.calc-campo-check input[type="checkbox"] { width: 16px; height: 16px; accent-color: var(--azul); cursor: pointer; }

/* Hora extra / adicional noturno — grupo com botão "+ adicionar" (some
   quando bate no máximo de 4) e uma lista de lançamentos, cada um
   removível. Fundo levemente destacado do resto do cartão, pra separar
   visualmente "isto é uma lista" do resto dos campos. */
.calc-grupo-slots {
  border: 1px solid var(--borda); border-radius: var(--raio-lg); padding: 12px 14px;
  background: var(--superficie); box-shadow: 0 1px 2px rgba(15, 23, 42, .04);
}
.calc-grupo-topo { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.calc-grupo-rot { font-size: 12px; font-weight: 700; color: var(--tinta); }
.calc-grupo-max { font-size: 11px; color: var(--tinta-3); font-style: italic; }
.calc-btn-add {
  background: none; border: 1px dashed var(--borda-2); border-radius: var(--raio-pill);
  padding: 4px 12px; font-size: 11.5px; font-weight: 700; color: var(--azul); cursor: pointer;
  transition: background var(--transicao), border-color var(--transicao), transform var(--transicao);
}
.calc-btn-add:hover { background: var(--lavagem-azul); border-color: var(--azul); transform: translateY(-1px); }
.calc-slots-lista { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; }
.calc-slots-vazio { font-size: 12px; color: var(--tinta-3); font-style: italic; margin: 8px 0 0; }
.calc-slot {
  display: flex; align-items: flex-end; gap: 10px; flex-wrap: wrap;
  padding: 9px 11px; background: var(--superficie-2); border-radius: var(--raio-sm);
  border-left: 3px solid var(--azul-claro);
}
.calc-slot-valor {
  flex: 1; min-width: 160px; font-size: 12px; color: var(--tinta-2); padding-bottom: 7px;
  font-variant-numeric: tabular-nums;
}
.calc-slot-valor-num { font-weight: 700; color: var(--tinta); }
.calc-slot-remover {
  background: none; border: 0; cursor: pointer; color: var(--st-critico); font-size: 13px;
  padding: 6px 4px; flex-shrink: 0; border-radius: var(--raio-sm); transition: background var(--transicao);
}
.calc-slot-remover:hover { background: rgba(160, 32, 32, .1); }

/* Extrato — o resumo "bem estratificado, detalhado e bem elaborado"
   pedido pelo usuário (23/07): cada linha nomeada, alinhada rótulo-
   esquerda/valor-direita, terminando num total bem em destaque (mesma
   linguagem visual do `.tile-num`, IBM Plex Sans) — visual "premium"
   pedido explicitamente: cartão com borda de destaque à esquerda (mesmo
   idioma visual do `.tile`/`.setor-cartao` do resto do sistema), sombra
   sutil, e o total com fundo próprio pra puxar o olho na hora certa. */
.calc-extrato {
  background: var(--superficie); border: 1px solid var(--borda); border-left: 3px solid var(--azul);
  border-radius: var(--raio-lg); padding: 14px 16px; margin-top: 2px;
  box-shadow: 0 2px 6px rgba(15, 23, 42, .05);
}
.calc-extrato-item {
  display: flex; align-items: baseline; justify-content: space-between; gap: 14px;
  font-size: 12.5px; padding: 4px 0; color: var(--tinta-2);
}
.calc-extrato-rot small { color: var(--tinta-3); font-size: 10.5px; }
.calc-extrato-val { font-variant-numeric: tabular-nums; font-weight: 600; color: var(--tinta); flex-shrink: 0; }
.calc-extrato-sep { height: 1px; background: var(--borda-2); margin: 8px 0; }
.calc-extrato-total {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  margin-top: 8px; padding: 10px 14px; border-radius: var(--raio-sm);
  background: var(--lavagem-azul); font-size: 13px; font-weight: 800; color: var(--azul);
}
.calc-extrato-total span:last-child {
  font-family: 'IBM Plex Sans', sans-serif; font-size: 21px; font-variant-numeric: tabular-nums;
  letter-spacing: -.02em;
}

/* ── PDI (Plano de Desenvolvimento Individual) ───────────────────────────── */
.pdi-voz { margin-bottom: 22px; }
.pdi-voz:last-child { margin-bottom: 0; }
.pdi-voz-titulo {
  font-family: 'IBM Plex Sans', sans-serif; font-weight: 800; font-size: 14px; color: var(--azul);
  margin: 0 0 10px; padding-bottom: 6px; border-bottom: 2px solid var(--borda);
}
.pdi-criterio { padding: 14px 0; border-top: 1px solid var(--borda); }
.pdi-criterio:first-child { border-top: 0; padding-top: 0; }
.pdi-criterio-cab { margin-bottom: 10px; }
.pdi-criterio-cab strong { display: block; font-size: 13.5px; color: var(--tinta); }
.pdi-criterio-cab span { display: block; font-size: 12px; color: var(--tinta-3); margin-top: 2px; }
.pdi-acao-melhoria { border-left: 3px solid var(--st-critico); background: var(--lavagem-vermelho); border-radius: var(--raio-sm); padding: 10px 12px; margin-top: 2px; }

.pdi-pendencia { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; padding: 10px 0; border-top: 1px solid var(--borda); }
.pdi-pendencia:first-child { border-top: 0; }
.pdi-pendencia-texto { font-size: 13px; color: var(--tinta-2); }
.pdi-pendencia-texto strong { color: var(--tinta); }
.pdi-pendencia-acoes { display: flex; gap: 6px; flex-shrink: 0; }
.pdi-pendencia-acoes button {
  font: inherit; font-size: 11.5px; font-weight: 600; border: 1px solid var(--borda-2);
  background: var(--superficie-2); color: var(--tinta-2); border-radius: var(--raio-sm);
  padding: 6px 10px; cursor: pointer; transition: background var(--transicao);
}
.pdi-pendencia-acoes button:hover { background: var(--superficie-3); }
.pdi-pendencia-acoes button.cumprida:hover { background: var(--lavagem-verde); color: var(--st-concluido); border-color: var(--st-concluido); }
.pdi-pendencia-acoes button.nao-cumprida:hover { background: var(--lavagem-vermelho); color: var(--st-critico); border-color: var(--st-critico); }

.pdi-media { display: inline-flex; align-items: baseline; gap: 3px; font-family: 'IBM Plex Sans', sans-serif; font-weight: 800; font-size: 17px; }
.pdi-media small { font-family: 'Inter', sans-serif; font-weight: 500; font-size: 11px; color: var(--tinta-3); }
.pdi-media.critica { color: var(--st-critico); }
.pdi-media.ok { color: var(--st-concluido); }

.pdi-selo-termo { font-size: 11px; font-weight: 600; padding: 3px 9px; border-radius: var(--raio-pill); }
.pdi-selo-termo.assinado { background: var(--lavagem-verde); color: var(--st-concluido); }
.pdi-selo-termo.pendente { background: var(--lavagem-ambar); color: var(--st-standby); }

/* Setinha de tendência entre uma avaliação e a anterior (pedido 17/07: ver
   se o colaborador melhorou ou piorou de uma avaliação pra outra). */
.pdi-tendencia { display: inline-block; margin-left: 6px; font-size: 11px; font-weight: 600; }
.pdi-tendencia.melhorou { color: var(--st-concluido); }
.pdi-tendencia.piorou { color: var(--st-critico); }
.pdi-tendencia.estavel { color: var(--tinta-3); }

.pdi-criterio-cab .pdi-nota-anterior { color: var(--azul-claro); font-weight: 500; margin-top: 4px; }
.pdi-tendencia-live { display: inline-block; margin-top: 4px; font-size: 11.5px; }

/* Exportar PDF dos dashboards — pedido do usuário (22/07): "em todos os
   dashboards tenha a permissão de extrair um relatório [...] pdf dos
   gráficos e dados presentes na página". Botão só chama window.print();
   a regra global abaixo esconde menu/filtro/botões em QUALQUER página do
   sistema na hora de imprimir, deixando só título + gráficos/números —
   evita repetir CSS de impressão em cada template (mesmo espírito das
   páginas de etiqueta do Almoxarifado, que já faziam isso individualmente). */
.btn-exportar-pdf { background: var(--superficie-3); color: var(--tinta-2); }
@media print {
  .lateral, .lateral-fundo, .menu-hamburguer, .tema-troca-canto,
  .topo-dir, .topo-filtro-barra, .tt, #tt {
    display: none !important;
  }
  .pagina { padding: 12px !important; }
  .topo-linha { border: 0 !important; }
}

/* ── Modo TV (05/08) ──────────────────────────────────────────────────────
   Painel de PAREDE — tela cheia, sem menu, pedido do usuário depois de eu
   sugerir "algo mt top": deixar aberto numa TV do escritório girando
   sozinho entre os principais números do sistema. Página INDEPENDENTE
   (`modo_tv.html` não estende `base.html`, mesmo padrão de `login.html`)
   — fundo escuro FIXO (não segue tema claro/escuro, é uma "vitrine", igual
   login/lateral já são fixos por design). */
.tv-tela {
  position: fixed; inset: 0; overflow: hidden;
  background:
    radial-gradient(900px 700px at 15% 10%, rgba(59, 156, 229, .28), transparent 60%),
    radial-gradient(700px 600px at 90% 90%, rgba(7, 99, 160, .26), transparent 55%),
    linear-gradient(160deg, var(--lateral), var(--azul-escuro));
  color: #fff; display: flex; flex-direction: column;
  font-family: 'Inter', sans-serif;
}
.tv-blob { position: absolute; border-radius: 50%; filter: blur(90px); pointer-events: none; }
.tv-blob-a { width: 420px; height: 420px; top: -140px; right: 8%; background: #58c4ff; opacity: .35; animation: auth-flutuar-a 30s ease-in-out infinite; }
.tv-blob-b { width: 340px; height: 340px; bottom: -120px; left: 4%; background: #0763a0; opacity: .32; animation: auth-flutuar-b 26s ease-in-out infinite; }

.tv-topo {
  position: relative; z-index: 1; display: flex; align-items: center; justify-content: space-between;
  padding: 28px 44px 0;
}
.tv-marca { display: flex; align-items: center; gap: 14px; }
.tv-logo { height: 40px; width: auto; }
.tv-marca-nome { font-family: 'IBM Plex Sans', sans-serif; font-weight: 700; font-size: 18px; }
.tv-marca-sub { font-size: 13px; color: rgba(255, 255, 255, .65); }
.tv-relogio { text-align: right; }
/* `IBM Plex Sans` (não `Syne`) de propósito — pedido do usuário: "as
   fontes tem que ser padrão também". `Syne` é citada em vários lugares do
   CLAUDE.md como fonte de número de destaque, mas NUNCA é carregada de
   verdade no link do Google Fonts do resto do sistema (`base.html`/
   `login.html` só pedem Inter + IBM Plex Sans) — ou seja, todo `.tile-num`
   etc. já cai no fallback `sans-serif` na prática. Carregar `Syne` só
   aqui faria o Modo TV parecer DIFERENTE do resto (o contrário do
   pedido) — usa o que realmente aparece em todo o resto do sistema. */
.tv-hora { font-family: 'IBM Plex Sans', sans-serif; font-weight: 800; font-size: clamp(28px, 3.4vw, 46px); line-height: 1; font-variant-numeric: tabular-nums; }
.tv-data { font-size: 14px; color: rgba(255, 255, 255, .65); margin-top: 4px; }

/* Janela do carrossel — `overflow: hidden` de propósito, é o "palco" onde
   o painel que sai e o que entra ficam empilhados por cima um do outro
   durante a rolagem. `.tv-corpo` (dentro) é o `position: relative` que os
   painéis `position: absolute` usam como referência. Reforma de 07/08
   ("menos telas, mas ricas em gráficos/indicadores"): cada tela agora é
   um PAINEL com uma GRADE de vários blocos, não mais 1 gráfico + 1 extra. */
.tv-corpo-janela {
  position: relative; z-index: 1; flex: 1; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  padding: 20px 84px;
}
.tv-corpo { position: relative; width: 100%; height: 100%; max-width: 1500px; }
.tv-vazio { font-size: 18px; color: rgba(255, 255, 255, .6); text-align: center; }

/* Botões de navegação manual (07/08, pedido do usuário: "coloque opção de
   avançar e ir também") — discretos até o mouse chegar perto (útil numa
   TV controlada por controle remoto/apontador, sem distrair quem só está
   olhando de longe). */
.tv-nav {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 2;
  width: 52px; height: 52px; border-radius: 50%; border: 1px solid rgba(255, 255, 255, .18);
  background: rgba(255, 255, 255, .07); color: rgba(255, 255, 255, .55);
  font-size: 26px; line-height: 1; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background var(--transicao), color var(--transicao), transform var(--transicao);
}
.tv-nav:hover { background: rgba(255, 255, 255, .16); color: #fff; transform: translateY(-50%) scale(1.08); }
.tv-nav-esq { left: 14px; }
.tv-nav-dir { right: 14px; }

.tv-painel {
  position: absolute; inset: 0; text-align: center;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  transform: translateY(0); opacity: 1;
  transition: transform .6s cubic-bezier(.4, 0, .2, 1), opacity .6s ease;
}
.tv-slide-entrando { transform: translateY(60px); opacity: 0; }
.tv-slide-saindo { transform: translateY(-60px); opacity: 0; }
.tv-painel-titulo {
  font-family: 'IBM Plex Sans', sans-serif; font-weight: 800;
  font-size: clamp(24px, 2.8vw, 36px); margin-bottom: 28px;
  color: color-mix(in srgb, var(--cor-slide) 70%, white 30%);
}

/* Grade de blocos — cada `.tv-bloco-slot` reserva o espaço (pequeno = 1
   coluna, médio = 1-2, grande = 2-3, ajustado sozinho pelo `auto-fit`), o
   `.tv-bloco` de dentro é a "superfície de vidro" comum a todos os tipos. */
.tv-painel-grade {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 20px; width: 100%; align-items: stretch;
}
.tv-bloco-slot-grande { grid-column: span 2; }
@media (max-width: 900px) {
  .tv-bloco-slot-grande { grid-column: span 1; }
}
.tv-bloco-link { text-decoration: none; color: inherit; display: block; height: 100%; }
.tv-bloco {
  height: 100%; display: flex; flex-direction: column; align-items: center;
  background: rgba(255, 255, 255, .07); border: 1px solid rgba(255, 255, 255, .14);
  border-radius: var(--raio-lg); padding: 22px 20px;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .12), 0 20px 50px rgba(0, 0, 0, .25);
  transition: background var(--transicao), transform var(--transicao);
}
.tv-bloco-link:hover .tv-bloco { background: rgba(255, 255, 255, .12); transform: translateY(-3px); }
.tv-bloco-titulo {
  font-size: 13.5px; font-weight: 700; color: rgba(255, 255, 255, .75);
  margin-bottom: 16px; text-align: center;
}

.tv-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  gap: 16px; width: 100%;
}
.tv-item { text-align: center; min-width: 0; }
.tv-item-valor {
  font-family: 'IBM Plex Sans', sans-serif; font-weight: 800; font-size: clamp(15px, 2.2vw, 40px);
  line-height: 1.15; color: color-mix(in srgb, var(--cor-slide) 85%, white 15%);
  font-variant-numeric: tabular-nums; overflow-wrap: break-word;
}
/* Valor NÃO numérico (texto, ex.: nome de pessoa/status) — fonte menor e
   peso reduzido, senão um nome comprido (ex.: "JOHN BARROS") força quebra
   feia com hífen no meio da palavra num item pensado pra número curto. */
.tv-item-valor.tv-item-texto { font-size: clamp(13px, 1.5vw, 22px); font-weight: 700; }
.tv-item-rotulo { font-size: 12.5px; color: rgba(255, 255, 255, .72); margin-top: 6px; }

.tv-dots { position: relative; z-index: 1; display: flex; justify-content: center; gap: 9px; padding-bottom: 30px; }
.tv-dot { width: 8px; height: 8px; border-radius: 50%; background: rgba(255, 255, 255, .25); cursor: pointer; transition: background var(--transicao), transform var(--transicao); }
.tv-dot.ativo { background: #fff; transform: scale(1.3); }
.tv-dot:hover { background: rgba(255, 255, 255, .6); }

.tv-sair {
  position: fixed; bottom: 14px; right: 18px; z-index: 2;
  font-size: 12px; color: rgba(255, 255, 255, .35); text-decoration: none;
  transition: color var(--transicao);
}
.tv-sair:hover { color: rgba(255, 255, 255, .85); }
/* Mesmo link, mas no canto OPOSTO (esquerdo) — usado pro "✏ Editar" de
   "Conheça a Direction" ficar do lado do "✕ Sair", sem disputar espaço. */
.tv-sair-esq { left: 18px; right: auto; }

/* "Conheça a Direction" (17/08) — reaproveita a MESMA moldura do Modo TV
   (.tv-tela/.tv-topo/.tv-corpo-janela/.tv-nav/.tv-dots/.tv-painel,
   pedido do usuário: "algo parecido com o modo tv"); só o CONTEÚDO de
   cada slide muda — texto/imagem/vídeo/anexo livre escrito pelo admin,
   não dado de dashboard. Sem timer automático (confirmado com o
   usuário: navegação SÓ manual — sem `iniciarAuto()` no JS). */
.cd-slide {
  max-width: 1160px; width: 100%; max-height: 100%; overflow-y: auto;
  padding: 12px 8px; text-align: left;
}
/* Slide "só imagem" (21/08) — apresentações montadas fora do sistema
   (PowerPoint → PDF → PNG por slide) chegam aqui como uma imagem só,
   com todo o conteúdo já desenhado nela. `object-fit: contain` garante
   que a imagem NUNCA estoura o palco (`.tv-corpo-janela` já corta com
   `overflow: hidden`) — resolve de vez o pedido de "não deixe
   scrollável a parte dos slides", sem precisar de scrollbar nenhuma. */
.cd-slide-imagem-unica {
  width: 100%; height: 100%; display: flex; align-items: center; justify-content: center;
  position: relative;
}
.cd-slide-imagem-unica img {
  max-width: 100%; max-height: 100%; width: auto; height: auto;
  object-fit: contain; border-radius: var(--raio-lg);
  box-shadow: 0 24px 70px rgba(0, 0, 0, .45);
}
.cd-slide-imagem-unica .cd-slide-anexos {
  position: absolute; left: 50%; bottom: -46px; transform: translateX(-50%);
  margin: 0;
}
/* "Olho" (eyebrow) — pequena etiqueta acima do título, recurso clássico
   de slide corporativo (Canva/PowerPoint) pra dar contexto sem competir
   com o título. Fixo ("CONHEÇA A DIRECTION") em vez de campo novo —
   confirmado com o usuário: um slide é uma tela LIVRE, sem categorias;
   isto é só decoração, não dado. */
.cd-slide-olho {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  margin-bottom: 10px; text-align: center;
}
.cd-slide-olho::before, .cd-slide-olho::after {
  content: ''; height: 1px; width: 34px;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .35));
}
.cd-slide-olho::after { background: linear-gradient(90deg, rgba(255, 255, 255, .35), transparent); }
.cd-slide-olho span {
  font-size: 11.5px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase;
  color: var(--azul-claro);
}
.cd-slide-titulo {
  font-family: 'IBM Plex Sans', sans-serif; font-weight: 800;
  font-size: clamp(28px, 3.4vw, 46px); margin-bottom: 28px; text-align: center;
  letter-spacing: -.015em;
}
/* Painel de vidro — mesma família visual de `.tv-bloco` (superfície
   translúcida com borda/realce), pedido do usuário (17/08): "preciso que
   seja mais profissional assim como um slide corporativo" — texto solto
   direto no fundo gradiente lia como rascunho; um card de verdade com
   moldura dá o acabamento de apresentação. */
.cd-slide-corpo {
  display: flex; gap: 36px; align-items: flex-start; flex-wrap: wrap;
  background: rgba(255, 255, 255, .06); border: 1px solid rgba(255, 255, 255, .14);
  border-radius: var(--raio-lg); padding: 34px 38px;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .12), 0 24px 60px rgba(0, 0, 0, .28);
}
.cd-slide-imagem {
  flex: 1 1 320px; max-width: 420px; border-radius: var(--raio);
  overflow: hidden; border: 1px solid rgba(255, 255, 255, .18);
  box-shadow: 0 16px 40px rgba(0, 0, 0, .35);
}
.cd-slide-imagem img { width: 100%; display: block; }
.cd-slide-texto { flex: 2 1 380px; font-size: 16.5px; line-height: 1.75; color: rgba(255, 255, 255, .92); }
.cd-slide-texto p { margin: 0 0 14px; }
.cd-slide-texto p:last-child { margin-bottom: 0; }
/* Linha que começa com •/-/* na hora de digitar vira bullet DE VERDADE
   (marcador colorido, recuo, espaçamento) — melhor esforço em cima de
   texto livre, sem precisar de editor rico nem campo novo. */
.cd-slide-texto ul { margin: 0 0 14px; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 9px; }
.cd-slide-texto ul:last-child { margin-bottom: 0; }
.cd-slide-texto li { display: flex; gap: 11px; align-items: baseline; }
.cd-slide-texto li::before {
  content: ''; width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0;
  background: var(--azul-claro); margin-top: 2px; transform: translateY(2px);
  box-shadow: 0 0 0 3px rgba(95, 196, 251, .18);
}
/* Hierarquia de texto dentro do slide (21/08, pedido do usuário: "coloque
   em negrito partes importantes, mude um pouco a hierarquia das fontes" +
   "tenta trazer algo que chame mais atenção") — 3 níveis novos, todos
   escritos como texto puro (**negrito**, "## subtítulo", "> destaque"),
   sem precisar de editor rico: ver `formatarInline`/`montarTextoHtml` no
   script deste template. */
.cd-slide-texto strong { color: #fff; font-weight: 800; }
.cd-slide-subtitulo {
  font-family: 'IBM Plex Sans', sans-serif; font-weight: 700; font-size: 15.5px;
  color: var(--azul-claro); text-transform: uppercase; letter-spacing: .05em;
  margin: 18px 0 8px; padding-top: 4px;
}
.cd-slide-texto h3.cd-slide-subtitulo:first-child { margin-top: 0; }
/* Bloco de destaque — a "chamar mais atenção": frase isolada, grande,
   com friso colorido do lado, tipo citação de revista. */
.cd-slide-destaque {
  margin: 6px 0 18px; padding: 4px 0 4px 22px; border-left: 3px solid var(--azul-claro);
  font-family: 'IBM Plex Sans', sans-serif; font-weight: 700; font-style: normal;
  font-size: 20px; line-height: 1.5; color: #fff;
}
.cd-slide-video {
  flex: 1 1 100%; aspect-ratio: 16 / 9; border-radius: var(--raio);
  overflow: hidden; border: 1px solid rgba(255, 255, 255, .18);
  box-shadow: 0 16px 40px rgba(0, 0, 0, .35); margin-top: 4px;
}
.cd-slide-video iframe { width: 100%; height: 100%; border: 0; }
.cd-slide-anexos { flex: 1 1 100%; display: flex; gap: 10px; flex-wrap: wrap; margin-top: 2px; }
.cd-slide-anexo {
  display: inline-flex; align-items: center; gap: 6px; padding: 8px 14px;
  border-radius: var(--raio-pill); background: rgba(255, 255, 255, .1);
  border: 1px solid rgba(255, 255, 255, .18); color: #fff;
  text-decoration: none; font-size: 13px; transition: background var(--transicao);
}
.cd-slide-anexo:hover { background: rgba(255, 255, 255, .18); }
@media (max-width: 720px) { .cd-slide-corpo { padding: 24px 20px; } }

/* Gráfico de barras — mesmo princípio de `.colunas`/`.col-b` (trilho atrás
   + barra com altura em %, gradiente sutil), redesenhado pro fundo escuro
   fixo da TV. Série ÚNICA sempre (uma cor só, `--cor-slide`). */
.tv-chart {
  display: flex; align-items: flex-end; justify-content: center; gap: 18px;
  width: 100%; height: 230px; padding: 0 6px;
}
.tv-chart-col {
  display: flex; flex-direction: column; align-items: center; justify-content: flex-end;
  height: 100%; flex: 1; max-width: 110px;
}
.tv-chart-valor {
  font-family: 'IBM Plex Sans', sans-serif; font-weight: 800;
  font-size: clamp(11px, 1.1vw, 15px); white-space: nowrap;
  color: color-mix(in srgb, var(--cor-slide) 85%, white 15%);
  margin-bottom: 8px; font-variant-numeric: tabular-nums;
}
.tv-chart-trilho {
  width: 100%; max-width: 46px; flex: 1;
  display: flex; align-items: flex-end;
  background: rgba(255, 255, 255, .06); border-radius: 8px; overflow: hidden;
}
.tv-chart-barra {
  width: 100%; min-height: 4px; border-radius: 6px 6px 0 0;
  background: linear-gradient(180deg, color-mix(in srgb, var(--cor-slide) 100%, white 30%) 0%, var(--cor-slide) 100%);
  transition: height .6s cubic-bezier(.4, 0, .2, 1);
}
.tv-chart-rotulo {
  margin-top: 10px; font-size: 12.5px; color: rgba(255, 255, 255, .72);
  font-variant-numeric: tabular-nums;
}

/* Rosca (donut) — mesma matemática/visual de `rosca_multi` (macro
   compartilhada por RH/PDI/Absenteísmo), redesenhada pro fundo escuro da
   TV. Círculo de fundo em branco translúcido (não `--superficie-3`, que
   é claro — ficaria invisível aqui). */
.tv-rosca-linha { display: flex; flex-direction: column; align-items: center; gap: 12px; }
.tv-rosca-num {
  font-family: 'IBM Plex Sans', sans-serif; font-weight: 800; font-size: 22px; fill: #fff;
}
.tv-rosca-rot { font-size: 8px; fill: rgba(255, 255, 255, .6); text-transform: uppercase; letter-spacing: .04em; }
.tv-rosca-legenda { display: flex; flex-direction: column; gap: 5px; width: 100%; }
.tv-rosca-item {
  display: flex; align-items: center; gap: 7px; font-size: 12px; color: rgba(255, 255, 255, .8);
  white-space: nowrap;
}
.tv-rosca-item strong { margin-left: auto; font-variant-numeric: tabular-nums; }
.tv-rosca-cor { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; }

/* Velocímetro (gauge, meio-círculo 0-100%). Cor por severidade
   (`modo_tv._cor_severidade`, reusa as 3 cores de status já validadas —
   verde/âmbar/vermelho —, nunca hex novo; ou `cor=` explícita passada
   pelo chamador, ex.: PDI usa a escala própria de `criterios_pdi.cor_media`). */
.tv-gauge-svg { overflow: visible; }
.tv-gauge-num {
  font-family: 'IBM Plex Sans', sans-serif; font-weight: 800; font-size: 26px;
  fill: color-mix(in srgb, var(--cor-gauge) 85%, white 15%);
  font-variant-numeric: tabular-nums;
}
.tv-gauge-rotulo {
  margin-top: 4px; font-size: 12px; color: rgba(255, 255, 255, .72); text-align: center;
}

/* Lista/ranking — nome à esquerda, barra proporcional no meio (só quando
   o item tem magnitude), valor à direita em destaque. */
.tv-lista { display: flex; flex-direction: column; gap: 11px; width: 100%; }
.tv-lista-linha {
  display: grid; grid-template-columns: minmax(110px, 1fr) minmax(60px, 1.1fr) auto;
  align-items: center; gap: 12px;
}
.tv-lista-nome {
  font-size: clamp(12.5px, 1.1vw, 15px); color: rgba(255, 255, 255, .88); text-align: left;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tv-lista-trilho { height: 8px; border-radius: 6px; background: rgba(255, 255, 255, .08); overflow: hidden; }
.tv-lista-barra {
  height: 100%; min-width: 3%; border-radius: 6px;
  background: linear-gradient(90deg, var(--cor-slide) 0%, color-mix(in srgb, var(--cor-slide) 100%, white 30%) 100%);
  transition: width .6s cubic-bezier(.4, 0, .2, 1);
}
.tv-lista-valor {
  font-family: 'IBM Plex Sans', sans-serif; font-weight: 800; font-size: clamp(12.5px, 1.2vw, 16px);
  color: color-mix(in srgb, var(--cor-slide) 85%, white 15%); white-space: nowrap; font-variant-numeric: tabular-nums;
  text-align: right;
}

/* Destaque (texto grande) — "última ação de RH"/"última ação da CIPA",
   registro sem número natural pra virar gráfico. */
.tv-destaque-texto {
  font-size: clamp(14px, 1.3vw, 18px); font-weight: 600; line-height: 1.4;
  color: color-mix(in srgb, var(--cor-slide) 90%, white 10%);
}
.tv-destaque-rotulo { margin-top: 12px; font-size: 12.5px; color: rgba(255, 255, 255, .65); }

@media (max-width: 900px) {
  .tv-corpo-janela { padding: 16px 56px; }
  .tv-nav { width: 40px; height: 40px; font-size: 20px; }
  .tv-lista-linha { grid-template-columns: 1fr; row-gap: 6px; }
  .tv-lista-valor { text-align: left; }
}
