portal_publico/static/css/indicador-desempenho.css

725 lines
18 KiB
CSS

.ind-header {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: var(--space-4);
margin-bottom: var(--space-5);
flex-wrap: wrap;
}
.ind-header h2 {
font-size: 1.05rem;
font-weight: 700;
}
.ind-header-actions {
display: flex;
gap: var(--space-3);
}
.ind-subtitle {
font-size: 0.85rem;
color: var(--text-muted);
margin-top: 2px;
}
/* Input de competência (<input type="month">) — o ícone/popup nativo do
browser não segue o tema do site por padrão; color-scheme faz o Chrome/Edge
desenharem os dois de acordo, em vez do ícone de calendário escuro-sobre-nada
ilegível no fundo escuro do site. */
#ind-form-competencia {
color-scheme: dark;
cursor: pointer;
}
:root[data-theme="light"] #ind-form-competencia {
color-scheme: light;
}
/* Botão "Selecionar arquivo" com nome do arquivo ao lado, no lugar do
<input type="file"> nativo (feio e sem padronização entre browsers) — mesmo
padrão de .ips-file-field em importacao-plano-saude.css. */
.ind-file-field {
position: relative;
display: flex;
align-items: center;
gap: var(--space-3);
flex-wrap: wrap;
}
.ind-file-field__btn {
display: inline-flex;
align-items: center;
gap: var(--space-2);
cursor: pointer;
flex-shrink: 0;
}
.ind-file-field__input {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
.ind-file-field__input:focus-visible + .ind-file-field__name {
outline: 2px solid var(--accent);
outline-offset: 2px;
border-radius: var(--radius-sm);
}
.ind-file-field__name {
font-size: 0.85rem;
color: var(--text-muted);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
max-width: 320px;
}
.ind-file-field__remove {
flex-shrink: 0;
}
.ind-empty {
text-align: center;
color: var(--text-muted);
font-size: 0.9rem;
padding: var(--space-6);
border: 1px dashed var(--border-subtle);
border-radius: var(--radius-md);
}
.ind-avisos {
background: rgba(var(--danger-rgb), 0.1);
border: 1px solid var(--danger);
border-radius: var(--radius-md);
padding: var(--space-3) var(--space-4);
margin-bottom: var(--space-4);
font-size: 0.85rem;
}
.ind-avisos ul {
margin: var(--space-2) 0 0;
padding-left: var(--space-5);
}
.ind-lote-bar {
display: flex;
align-items: center;
gap: var(--space-3);
background: var(--bg-surface);
border: 1px solid var(--border-subtle);
border-radius: var(--radius-md);
padding: var(--space-3) var(--space-4);
margin-bottom: var(--space-4);
position: sticky;
top: 0;
z-index: 5;
}
.ind-lote-bar select {
padding: 6px 10px;
border-radius: var(--radius-sm);
border: 1px solid var(--border-subtle);
background: var(--bg-surface);
color: var(--text-primary);
}
/* "Cada gerente representa um grupo" e "cada departamento tem sua própria
meta de Departamento" (CLAUDE.md): a Meta de Departamento (uma por
IndicadorDepartamento) e a Meta de cada Grupo (por gerente) são
preenchidas de uma vez só nesta tabela, no início da revisão — não mais
espalhadas pela lista de colaboradores, que fica livre pra ser filtrada
por departamento (ver .ind-departamento-filtros, que também filtra esta
própria tabela) sem afetar o cálculo de nenhuma meta. */
.ind-metas-section {
margin-bottom: var(--space-5);
}
.ind-metas-section .ind-subtitle {
margin-bottom: var(--space-3);
}
/* Aviso pra colaboradores cujo gerente ainda não está mapeado a nenhum
IndicadorDepartamento (ver Configurações → Departamentos) — a linha de
Meta de Departamento não tem select nesse caso, só o texto explicando. */
.ind-meta-sem-departamento-aviso {
margin: 4px 0 0;
font-size: 0.78rem;
color: var(--danger);
}
/* Botões de filtro por departamento — substituem o antigo <select> de
filtro por gerente; afetam tanto esta tabela de Metas (só mostra o
departamento selecionado e os gerentes dele) quanto a lista de
colaboradores abaixo. Mesmo espírito visual de .filter-chip
(calendario.css), mas essa classe não está disponível aqui
(indicador-desempenho.html não carrega calendario.css). */
.ind-departamento-filtros {
display: flex;
flex-wrap: wrap;
gap: var(--space-2);
margin-bottom: var(--space-4);
}
.ind-departamento-chip {
padding: var(--space-2) var(--space-4);
border-radius: var(--radius-pill);
border: 1px solid var(--border-subtle);
font-size: 0.8rem;
font-weight: 600;
color: var(--text-secondary);
background: var(--bg-surface);
transition: border-color var(--transition-fast), color var(--transition-fast), background var(--transition-fast);
}
.ind-departamento-chip:hover {
border-color: var(--accent);
color: var(--text-primary);
}
.ind-departamento-chip.is-active {
background: var(--accent);
border-color: var(--accent);
color: var(--accent-contrast);
}
/* Filtro por departamento dentro dos modais "Ajuste Indicador em Lote" e
"Gerar Recibos" — combina com a busca por nome (.checklist-search, logo
acima) pra restringir a lista de colaboradores; mesmo visual do campo de
busca, só que <select>. */
.ind-checklist-departamento-select {
width: 100%;
padding: var(--space-2) var(--space-3);
border-radius: var(--radius-sm);
border: 1px solid var(--border-subtle);
background: var(--bg-canvas);
color: var(--text-primary);
font-size: 0.85rem;
outline: none;
margin-bottom: var(--space-2);
}
.ind-checklist-departamento-select:focus {
border-color: var(--accent);
}
/* Fica ao lado do campo "Adicionar gerente" (.modal-field-row), que estica
pra preencher a altura da linha por padrão (grid) — alinhado ao rodapé
pra ficar na mesma altura do input, não do label. */
.ind-departamento-gerente-add-btn {
align-self: end;
}
/* Sugestão clicável (nome de gerente visto na última apuração, ainda sem
departamento) — reseta a aparência padrão de <button> pra ficar igual a
um .checklist-item comum, mesmo padrão de .ind-corrigir-resultado (busca
de empresa em "Corrigir Responsável"). */
.ind-departamento-gerente-sugestao {
width: 100%;
justify-content: space-between;
background: none;
border: none;
text-align: left;
cursor: pointer;
border-radius: var(--radius-sm);
}
.ind-departamento-gerente-sugestao:hover {
background: var(--bg-surface-raised);
}
.ind-departamento-gerente-sugestao__acao {
color: var(--accent);
font-size: 0.8rem;
font-weight: 600;
flex-shrink: 0;
}
.ind-meta-label {
font-weight: 700;
}
/* Lista os critérios que compõem aquele nível de meta — mesma informação
que já aparece na tabela "Individual"/"Grupo"/"Departamento" dentro do
card do colaborador, só que aqui fica ao lado do campo que o RH preenche,
pra deixar claro o que aquele percentual está medindo. */
.ind-meta-criterios {
list-style: none;
margin: 4px 0 0;
padding: 0;
font-size: 0.92rem;
color: var(--text-muted);
}
.ind-meta-criterios li {
margin-top: 4px;
display: flex;
align-items: center;
gap: var(--space-2);
flex-wrap: wrap;
}
.ind-meta-criterios li.is-apagado {
text-decoration: line-through;
opacity: 0.6;
}
.ind-meta-criterios__peso {
color: var(--text-muted);
}
.ind-meta-criterios-vazio {
margin: 4px 0 0;
font-size: 0.78rem;
color: var(--text-muted);
font-style: italic;
}
.ind-meta-select {
padding: 6px 8px;
border-radius: var(--radius-sm);
border: 1px solid var(--border-subtle);
background: var(--bg-surface);
color: var(--text-primary);
font-size: 0.85rem;
}
.ind-meta-acao {
width: 40px;
text-align: center;
}
.ind-colaboradores-toolbar {
display: flex;
align-items: center;
gap: var(--space-3);
margin-bottom: var(--space-4);
}
/* Cor de atenção (mesma linguagem visual do input/selo de "honorário não
encontrado", que já usam --danger) — deixa claro que o botão leva a algo
pendente de resolver, não é uma ação neutra como as outras do toolbar. */
.ind-empresas-sem-honorario-btn {
border-color: var(--danger);
color: var(--danger);
}
.ind-empresas-sem-honorario-btn:hover {
background: var(--danger);
color: #fff;
}
/* Empresa com honorário não encontrado (código sem casamento na planilha de
Honorários Por Cliente) — em vez do valor formatado, um campo pra o RH
preencher direto na tabela (ver IndicadorApuracaoEmpresaViewSet) ou no
modal "Empresas sem Honorário" (ver .ind-esh-*). */
.ind-empresa-honorario-input {
width: 110px;
padding: 4px 8px;
border-radius: var(--radius-sm);
border: 1px solid var(--danger);
background: var(--bg-surface);
color: var(--text-primary);
font-size: 0.85rem;
}
.ind-esh-modal-card {
max-width: 640px;
/* Sem isso, uma apuração com muitas empresas sem honorário fazia o modal
inteiro crescer além da altura da tela (título/aviso/lista/ações saindo
do viewport, sem nenhuma rolagem) — mesmo raciocínio de min-height:0 já
documentado em CLAUDE.md pra .calendar-day: um filho de flex-column só
realmente rola (em vez de esticar o pai) quando o próprio pai também
para de contribuir com o min-content pro cálculo de altura. */
max-height: 85vh;
min-height: 0;
}
/* Um único popup cobre as duas listas ("sem honorário", sempre visível, e
"ajustadas manualmente", escondida atrás de .ind-esh-toggle-btn até o
usuário clicar) — por isso quem rola é este wrapper em volta das duas, não
cada lista separada; título e "Fechar" ficam sempre visíveis fora dele. */
.ind-esh-scroll {
overflow-y: auto;
min-height: 0;
padding-right: var(--space-2);
}
.ind-esh-section-title {
font-size: 0.9rem;
font-weight: 700;
margin: 0 0 0;
padding-top: var(--space-4);
}
/* Fica no final da lista "sem honorário", antes da seção "ajustadas
manualmente" (escondida por padrão) — largura cheia pra marcar bem que é
um divisor entre as duas listas, não mais um botão do toolbar. */
.ind-esh-toggle-btn {
width: 100%;
justify-content: center;
margin-top: var(--space-5);
}
.ind-esh-item {
border: 1px solid var(--border-subtle);
border-radius: var(--radius-md);
padding: var(--space-3) var(--space-4);
margin-bottom: var(--space-3);
}
.ind-esh-item:last-child {
margin-bottom: 0;
}
.ind-esh-header {
display: flex;
justify-content: space-between;
align-items: baseline;
gap: var(--space-3);
font-weight: 700;
}
.ind-esh-codigo {
font-weight: 400;
font-size: 0.8rem;
color: var(--text-muted);
white-space: nowrap;
}
.ind-esh-responsaveis {
margin: var(--space-2) 0;
padding-left: 1.1rem;
font-size: 0.82rem;
color: var(--text-muted);
}
.ind-esh-form {
display: flex;
gap: var(--space-2);
}
.ind-esh-form .ind-empresa-honorario-input {
flex: 1;
width: auto;
}
/* Resultado de busca do popup "Corrigir Responsável" — reaproveita
.checklist-item pro layout, mas é um <button>, não um <label>, então
precisa resetar a aparência nativa de botão. */
.ind-corrigir-resultado {
width: 100%;
background: none;
border: none;
text-align: left;
cursor: pointer;
border-radius: var(--radius-sm);
}
.ind-corrigir-resultado:hover {
background: var(--bg-surface-raised);
}
.ind-corrigir-responsaveis li {
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
gap: var(--space-3);
padding: var(--space-2) 0;
}
.ind-corrigir-responsavel-form {
display: flex;
align-items: center;
gap: var(--space-2);
}
.ind-corrigir-responsavel-form select {
padding: 4px 8px;
border-radius: var(--radius-sm);
border: 1px solid var(--border-subtle);
background: var(--bg-surface);
color: var(--text-primary);
font-size: 0.82rem;
}
.ind-colaborador-card {
border: 1px solid var(--border-subtle);
border-radius: var(--radius-md);
margin-bottom: var(--space-4);
overflow: hidden;
transition: border-color var(--transition-fast);
}
/* Checklist de revisão do RH — sem relação com nenhum cálculo, só ajuda a
controlar quem já foi conferido numa apuração com muitos colaboradores.
Mesma largura de borda de sempre (só muda a cor) pra não deslocar o layout
ao marcar/desmarcar. */
.ind-colaborador-card.is-validado {
border-color: #2f9e6e;
}
.ind-colaborador-card__header {
display: grid;
grid-template-columns: auto 1fr minmax(260px, 1fr) 200px minmax(90px, 140px);
align-items: center;
gap: var(--space-3);
padding: var(--space-3) var(--space-4);
background: var(--bg-surface);
cursor: pointer;
}
.ind-colaborador-card__validado {
display: flex;
cursor: pointer;
}
.ind-colaborador-card__validado input {
width: 18px;
height: 18px;
cursor: pointer;
accent-color: #2f9e6e;
}
@media (max-width: 900px) {
.ind-colaborador-card__header {
display: flex;
flex-wrap: wrap;
}
.ind-colaborador-card__pcts {
display: flex !important;
flex-wrap: wrap;
gap: var(--space-3);
}
.ind-colaborador-card__composicao {
flex-basis: 100%;
text-align: left;
}
}
.ind-colaborador-card__nome {
font-weight: 700;
}
.ind-colaborador-card__gerente {
font-size: 0.8rem;
color: var(--text-muted);
}
.ind-colaborador-card__pcts {
display: contents;
font-size: 0.8rem;
color: var(--text-muted);
}
.ind-pct-field--resumo {
/* "Total Indicador: 74,29%" + lápis nunca pode quebrar entre si (pedido
explícito do usuário — o lápis "ao lado do valor", não embaixo); só o
selo "ajustado manualmente" + botão de recalcular, que aparecem numa
segunda linha (.ind-pct-field__principal isola a primeira), podem
quebrar quando a coluna (200px, ver .ind-colaborador-card__header) não
é larga o bastante para tudo junto. */
font-size: 0.85rem;
flex-direction: column;
row-gap: 2px;
}
.ind-pct-field__principal {
display: flex;
align-items: center;
gap: 4px;
white-space: nowrap;
}
.ind-pct-field--resumo .ind-pct-value {
font-size: 0.95rem;
}
.ind-pct-field {
display: flex;
justify-content: center;
align-items: center;
gap: 4px;
white-space: nowrap;
}
.ind-pct-value {
color: var(--text-primary);
font-weight: 600;
}
/* Cada percentual da composição (Individual/Grupo/Departamento) só bate 100%
quando foi de fato atingido — verde/vermelho comunicam isso de cara, sem
precisar abrir o card. Mesmo verde de .status-pill--ativo. Reaproveitado
tanto pelo valor em .ind-pct-value quanto pelos <b> de
.ind-colaborador-card__composicao — o "Total Indicador" em si fica neutro
(ver renderPctResumoHtml), só os 3 níveis abaixo dele são coloridos. */
.is-atingido {
color: #2f9e6e;
}
.is-nao-atingido {
color: var(--danger);
}
.ind-colaborador-card__composicao {
text-align: center;
font-size: 0.78rem;
color: var(--text-muted);
}
.ind-colaborador-card__composicao b {
/* Sem "color" aqui de propósito — todo <b> deste bloco sempre carrega
.is-atingido/.is-nao-atingido (ver renderComposicaoIndicadorHtml), que
definem a cor. */
font-weight: 600;
}
.ind-pct-edit-btn,
.ind-pct-reset-btn {
border: none;
background: transparent;
color: var(--text-muted);
cursor: pointer;
font-size: 0.9rem;
line-height: 1;
padding: 2px;
}
.ind-pct-edit-btn:hover,
.ind-pct-reset-btn:hover {
color: var(--accent);
}
.ind-colaborador-card__total {
font-weight: 700;
font-size: 1rem;
text-align: right;
}
.ind-colaborador-card__body {
padding: var(--space-4);
border-top: 1px solid var(--border-subtle);
}
.ind-colaborador-card__body[hidden] {
display: none;
}
.ind-section-title {
font-size: 0.85rem;
font-weight: 700;
margin: var(--space-4) 0 var(--space-2);
}
.ind-section-title:first-child {
margin-top: 0;
}
.ind-respostas-table select {
padding: 4px 8px;
border-radius: var(--radius-sm);
border: 1px solid var(--border-subtle);
background: var(--bg-surface);
color: var(--text-primary);
font-size: 0.85rem;
}
/* Botão "i" no cabeçalho "Honorário Ajustado" (.ind-empresas-table) — explica
de onde vem o valor. Popover próprio, mesmo espírito de `.notif-dropdown`
(components.css): absoluto, some ao clicar fora (ver indicador-desempenho.js). */
.ind-info-wrap {
position: relative;
display: inline-flex;
vertical-align: middle;
margin-left: 4px;
}
.ind-info-btn {
display: inline-flex;
align-items: center;
justify-content: center;
width: 16px;
height: 16px;
padding: 0;
border-radius: 50%;
border: 1px solid var(--border-subtle);
color: var(--text-muted);
background: transparent;
cursor: pointer;
transition: color var(--transition-fast), border-color var(--transition-fast);
}
.ind-info-btn:hover {
color: var(--accent);
border-color: var(--accent);
}
.ind-info-popover {
position: absolute;
top: calc(100% + 6px);
left: 50%;
transform: translateX(-50%);
z-index: 20;
width: 220px;
padding: var(--space-3);
border-radius: var(--radius-md);
border: 1px solid var(--border-subtle);
background: var(--bg-surface-raised);
box-shadow: var(--shadow-lg);
animation: pidFadeSlideUp 140ms ease;
/* .pa-table th (perfis-acesso.css) força uppercase/letter-spacing/tamanho
pequeno no cabeçalho — resetado aqui pra virar texto normal de novo. */
font-size: 0.78rem;
font-weight: 400;
text-transform: none;
letter-spacing: normal;
line-height: 1.4;
color: var(--text-secondary);
white-space: normal;
text-align: left;
}
.ind-respostas-table .is-ajustado,
.ind-empresas-table .is-ajustado {
color: var(--accent);
font-size: 0.75rem;
margin-left: var(--space-2);
}
.ind-respostas-table tr.is-apagado {
opacity: 0.45;
}
.ind-respostas-table tr.is-apagado td {
text-decoration: line-through;
text-decoration-color: var(--text-muted);
}
.ind-respostas-table tr.is-apagado select {
text-decoration: none;
}
.ind-apagado-badge {
color: var(--text-muted);
font-size: 0.75rem;
font-style: italic;
margin-left: var(--space-2);
text-decoration: none;
}
.ind-select-col {
width: 32px;
text-align: center;
}