682 lines
16 KiB
CSS
682 lines
16 KiB
CSS
.ips-header {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
justify-content: space-between;
|
|
gap: var(--space-4);
|
|
margin-bottom: var(--space-5);
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.ips-header h2 {
|
|
font-size: 1.05rem;
|
|
font-weight: 700;
|
|
}
|
|
|
|
.ips-header-actions {
|
|
display: flex;
|
|
gap: var(--space-3);
|
|
}
|
|
|
|
.ips-subtitle {
|
|
font-size: 0.85rem;
|
|
color: var(--text-muted);
|
|
margin-top: 2px;
|
|
}
|
|
|
|
.ips-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);
|
|
}
|
|
|
|
/* Ordenação por coluna no histórico (#ips-list-table) — mesma linguagem
|
|
visual do ícone ↕ estático de ramais-lookup.js, só que com classes
|
|
próprias (esta página não carrega ramais-lookup.css). */
|
|
#ips-list-table th[data-sort] {
|
|
cursor: pointer;
|
|
user-select: none;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.ips-sort-icon {
|
|
color: var(--text-muted);
|
|
font-size: 0.75rem;
|
|
}
|
|
|
|
#ips-list-table th[data-sort].is-sort-asc .ips-sort-icon,
|
|
#ips-list-table th[data-sort].is-sort-desc .ips-sort-icon {
|
|
color: var(--accent);
|
|
}
|
|
|
|
/* Paginação do histórico — só Anterior/Próxima + "Página X de Y", sem
|
|
numeração de páginas (lista tende a ser curta; um seletor de tamanho de
|
|
página, como em ramais-lookup.js, seria demais pra esse caso). */
|
|
.ips-list-pagination {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: var(--space-3);
|
|
margin-top: var(--space-4);
|
|
}
|
|
|
|
.ips-list-pagination__info {
|
|
font-size: 0.85rem;
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
/* Quantidade de registros do histórico, abaixo da paginação. */
|
|
.ips-list-count {
|
|
text-align: center;
|
|
font-size: 0.8rem;
|
|
color: var(--text-muted);
|
|
margin-top: var(--space-2);
|
|
}
|
|
|
|
/* Coluna de checkbox de seleção (primeira do #ips-list-table). */
|
|
.ips-select-col {
|
|
width: 36px;
|
|
text-align: center;
|
|
}
|
|
|
|
/* Barra de exclusão em lote — só aparece com pelo menos 1 linha selecionada
|
|
(ver updateBulkActionsUI em importacao-plano-saude.js). */
|
|
.ips-list-bulk-actions {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: var(--space-3);
|
|
margin-bottom: var(--space-3);
|
|
padding: var(--space-3) var(--space-4);
|
|
border: 1px solid var(--border-subtle);
|
|
border-radius: var(--radius-sm);
|
|
background: var(--bg-surface);
|
|
}
|
|
|
|
.ips-list-bulk-actions span {
|
|
font-size: 0.85rem;
|
|
color: var(--text-secondary);
|
|
}
|
|
|
|
/* Formulário de nova importação */
|
|
.ips-form {
|
|
background: var(--bg-surface);
|
|
border: 1px solid var(--border-subtle);
|
|
border-radius: var(--radius-md);
|
|
padding: var(--space-5);
|
|
max-width: 640px;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
.ips-upload-box {
|
|
border: 1px solid var(--border-subtle);
|
|
border-radius: var(--radius-sm);
|
|
padding: var(--space-3);
|
|
margin-bottom: var(--space-3);
|
|
}
|
|
|
|
.ips-upload-box:last-child {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
.ips-upload-box__title {
|
|
font-size: 0.85rem;
|
|
font-weight: 600;
|
|
color: var(--text-primary);
|
|
}
|
|
|
|
.ips-upload-box__hint {
|
|
font-size: 0.78rem;
|
|
color: var(--text-muted);
|
|
margin-top: 2px;
|
|
margin-bottom: var(--space-3);
|
|
}
|
|
|
|
.ips-file-field {
|
|
position: relative;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--space-3);
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.ips-file-field__btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: var(--space-2);
|
|
cursor: pointer;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.ips-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;
|
|
}
|
|
|
|
.ips-file-field__input:focus-visible + .ips-file-field__name {
|
|
outline: 2px solid var(--accent);
|
|
outline-offset: 2px;
|
|
border-radius: var(--radius-sm);
|
|
}
|
|
|
|
.ips-file-field__name {
|
|
font-size: 0.85rem;
|
|
color: var(--text-muted);
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
max-width: 260px;
|
|
}
|
|
|
|
.ips-file-field__remove {
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
/* Resultado da pré-validação (endpoint /validar-arquivo/), abaixo do campo
|
|
de upload — some enquanto não há arquivo anexado ou enquanto a validação
|
|
está em andamento. */
|
|
.ips-file-field__status {
|
|
font-size: 0.8rem;
|
|
margin-top: var(--space-2);
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
.ips-file-field__status--pendente {
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
.ips-file-field__status--ok {
|
|
color: #2f9e6e;
|
|
}
|
|
|
|
.ips-file-field__status--erro {
|
|
color: var(--danger);
|
|
}
|
|
|
|
/* "Tipo de importação" fica visualmente bem separado do quadro "2. Arquivo
|
|
da operadora" logo acima — sem esse respiro extra, os dois blocos ficavam
|
|
colados o bastante pra confundir onde termina um e começa o outro. */
|
|
.ips-tipo-field {
|
|
margin-top: var(--space-7);
|
|
}
|
|
|
|
/* Regra de custeio salva — fica no início do modal, antes até de "Operadora"
|
|
(decisão explícita do usuário: aplicar uma regra já preenche a operadora
|
|
junto, então escolher a regra é o primeiro passo natural do fluxo, não um
|
|
apêndice no final). Por vir antes de tudo, a borda de separação fica
|
|
embaixo (não em cima), pra separar do campo "Operadora" logo abaixo. */
|
|
.ips-regra-field {
|
|
margin-bottom: var(--space-5);
|
|
padding-bottom: var(--space-5);
|
|
border-bottom: 1px solid var(--border-subtle);
|
|
}
|
|
|
|
.ips-regra-actions {
|
|
display: flex;
|
|
gap: var(--space-2);
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.ips-regra-actions button,
|
|
.ips-regra-actions label {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: var(--space-2);
|
|
}
|
|
|
|
.ips-regra-actions__hint {
|
|
font-size: 0.78rem;
|
|
color: var(--text-muted);
|
|
margin: 0;
|
|
}
|
|
|
|
/* Combobox pesquisável genérico — usado tanto por "Regra de custeio salva"
|
|
(#ips-regra-combo) quanto por "Operadora" (#ips-operadora-combo). O
|
|
<input> já herda o estilo padrão de .modal-field input (components.css);
|
|
aqui só cuida do posicionamento (ocupa o espaço de um <select>) e da
|
|
lista flutuante de resultados filtrados. */
|
|
.ips-combo {
|
|
position: relative;
|
|
flex: 1;
|
|
min-width: 220px;
|
|
}
|
|
|
|
.ips-combo__list {
|
|
position: absolute;
|
|
top: calc(100% + 4px);
|
|
left: 0;
|
|
right: 0;
|
|
z-index: 20;
|
|
max-height: 220px;
|
|
overflow-y: auto;
|
|
background: var(--bg-surface);
|
|
border: 1px solid var(--border-subtle);
|
|
border-radius: var(--radius-sm);
|
|
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
|
|
}
|
|
|
|
.ips-combo__item {
|
|
padding: var(--space-2) var(--space-3);
|
|
font-size: 0.88rem;
|
|
cursor: pointer;
|
|
color: var(--text-primary);
|
|
}
|
|
|
|
.ips-combo__item:hover {
|
|
background: var(--accent);
|
|
color: var(--accent-contrast);
|
|
}
|
|
|
|
.ips-combo__empty {
|
|
padding: var(--space-2) var(--space-3);
|
|
font-size: 0.85rem;
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
.ips-regra-observacoes {
|
|
margin: var(--space-2) 0 0;
|
|
padding: var(--space-2) var(--space-3);
|
|
border-radius: var(--radius-sm);
|
|
background: var(--bg-canvas);
|
|
border: 1px solid var(--border-subtle);
|
|
font-size: 0.82rem;
|
|
color: var(--text-muted);
|
|
white-space: pre-wrap;
|
|
}
|
|
|
|
/* "Salvar regra atual..." fica no final do formulário (não mais junto de
|
|
Aplicar/Limpar/Ver regras salvas no topo) — salvar só faz sentido depois
|
|
de parametrizar o custeio abaixo, é o último passo do fluxo de
|
|
parametrização de uma regra nova. */
|
|
.ips-regra-salvar-field {
|
|
margin-top: var(--space-5);
|
|
padding-top: var(--space-5);
|
|
border-top: 1px solid var(--border-subtle);
|
|
}
|
|
|
|
/* Lista de regras salvas (#ips-regras-modal) — reaproveita .checklist-box
|
|
como moldura rolável, mas cada linha tem seus próprios botões de ação em
|
|
vez do checkbox usado pelos outros consumidores de .checklist-box. */
|
|
.ips-regras-lista {
|
|
max-height: 320px;
|
|
}
|
|
|
|
.ips-regra-row {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
justify-content: space-between;
|
|
gap: var(--space-3);
|
|
padding: var(--space-2) 0;
|
|
border-bottom: 1px solid var(--border-subtle);
|
|
}
|
|
|
|
.ips-regra-row:last-child {
|
|
border-bottom: none;
|
|
}
|
|
|
|
.ips-regra-row__info {
|
|
min-width: 0;
|
|
flex: 1;
|
|
}
|
|
|
|
.ips-regra-row__nome {
|
|
margin: 0;
|
|
font-weight: 600;
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
.ips-regra-row__meta {
|
|
margin: 2px 0 0;
|
|
font-size: 0.78rem;
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
.ips-regra-row__obs {
|
|
margin: var(--space-1) 0 0;
|
|
font-size: 0.78rem;
|
|
color: var(--text-muted);
|
|
white-space: pre-wrap;
|
|
overflow-wrap: break-word;
|
|
}
|
|
|
|
.ips-regra-row__actions {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--space-2);
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.ips-tipo-option {
|
|
border: 1px solid var(--border-subtle);
|
|
border-radius: var(--radius-sm);
|
|
padding: var(--space-3);
|
|
margin-bottom: var(--space-3);
|
|
}
|
|
|
|
.ips-tipo-option:last-child {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
.ips-custeio-radios {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-4);
|
|
margin-top: var(--space-3);
|
|
padding-left: var(--space-6);
|
|
}
|
|
|
|
/* "Regra empresa" — alternativa ao custeio manual de mensalidade
|
|
(.ips-custeio-radios acima), por isso o mesmo recuo/espaçamento, mas só
|
|
com um texto de estado atual + botão, sem radios titular/dependente. */
|
|
.ips-regra-empresa-box {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-2);
|
|
align-items: flex-start;
|
|
margin-top: var(--space-3);
|
|
padding-left: var(--space-6);
|
|
}
|
|
|
|
.ips-regra-empresa-box__hint,
|
|
.ips-regra-empresa-box__atual {
|
|
margin: 0;
|
|
font-size: 0.82rem;
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
.ips-regra-empresa-box__atual {
|
|
font-weight: 600;
|
|
color: var(--text-primary);
|
|
}
|
|
|
|
/* Cada tipo de lançamento tem uma regra própria pra titular e outra pra
|
|
dependente — este é o agrupamento visual dessas duas sub-listas de
|
|
radios dentro de .ips-custeio-radios. */
|
|
.ips-custeio-pessoa {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-2);
|
|
}
|
|
|
|
.ips-custeio-pessoa__label {
|
|
font-size: 0.72rem;
|
|
font-weight: 700;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.04em;
|
|
color: var(--text-muted);
|
|
margin: 0;
|
|
}
|
|
|
|
.ips-regra-especifica {
|
|
margin-top: var(--space-3);
|
|
margin-left: var(--space-6);
|
|
padding: var(--space-3);
|
|
border: 1px solid var(--border-subtle);
|
|
border-radius: var(--radius-sm);
|
|
background: var(--bg-canvas);
|
|
}
|
|
|
|
.ips-regra-especifica .modal-field {
|
|
margin-bottom: var(--space-3);
|
|
}
|
|
|
|
.ips-regra-especifica .modal-field:last-of-type {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
.ips-regra-especifica__hint {
|
|
font-size: 0.78rem;
|
|
color: var(--text-muted);
|
|
margin-top: var(--space-2);
|
|
}
|
|
|
|
/* Resumo por tipo, acima de cada tabela da revisão */
|
|
.ips-resumo {
|
|
display: flex;
|
|
gap: var(--space-5);
|
|
flex-wrap: wrap;
|
|
margin-bottom: var(--space-4);
|
|
font-size: 0.85rem;
|
|
color: var(--text-secondary);
|
|
}
|
|
|
|
.ips-resumo strong {
|
|
color: var(--text-primary);
|
|
}
|
|
|
|
/* Tabela editável da revisão */
|
|
.ips-table-input {
|
|
width: 100%;
|
|
/* Só o suficiente pra não ficar colado na borda — a largura real da coluna
|
|
agora vem do <colgroup> (JS), ajustável até PID_IPS_COL_MIN_WIDTH (60px)
|
|
pela alça de redimensionar; um min-width maior aqui faria o input vazar
|
|
do <td> antes desse limite. */
|
|
min-width: 30px;
|
|
padding: var(--space-2);
|
|
border: 1px solid transparent;
|
|
border-radius: var(--radius-sm);
|
|
background: transparent;
|
|
color: var(--text-primary);
|
|
font-size: 0.85rem;
|
|
outline: none;
|
|
}
|
|
|
|
.ips-table-input:hover {
|
|
border-color: var(--border-subtle);
|
|
}
|
|
|
|
.ips-table-input:focus {
|
|
border-color: var(--accent);
|
|
background: var(--bg-canvas);
|
|
}
|
|
|
|
.ips-table-scroll {
|
|
width: 100%;
|
|
height: 420px;
|
|
min-width: 320px;
|
|
min-height: 160px;
|
|
max-height: 80vh;
|
|
max-width: 100%;
|
|
/* `resize` exige overflow != visible pra mostrar a alça de redimensionar no
|
|
canto inferior direito — o usuário arrasta pra ver mais linhas (altura) e
|
|
mais colunas de uma vez (largura), até 100% da largura de .page-content
|
|
(que aqui é .page-content--wide, 1600px em vez do padrão 1200px, ver
|
|
layout.css). */
|
|
resize: both;
|
|
overflow-y: auto;
|
|
/* .pa-table-wrap (perfis-acesso.css) tem overflow:hidden, que corta colunas
|
|
em vez de rolar quando a tabela é mais larga que o container — sobrescreve
|
|
aqui porque esta tabela tem 10 colunas editáveis, bem mais larga que as
|
|
tabelas normais de .pa-table. */
|
|
overflow-x: auto;
|
|
}
|
|
|
|
.ips-table-scroll .pa-table {
|
|
width: auto;
|
|
/* `table-layout: fixed` + <colgroup> (importacao-plano-saude.js) é o que
|
|
permite cada coluna ter uma largura própria e ajustável — com o `auto`
|
|
padrão o navegador recalcula a largura pelo conteúdo e ignora o que a
|
|
alça de redimensionar define. */
|
|
table-layout: fixed;
|
|
}
|
|
|
|
.ips-table-scroll .pa-table th,
|
|
.ips-table-scroll .pa-table td {
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
/* Coluna de ações (ícone fixo) não recebe alça de redimensionar, então fica
|
|
de fora do `position: relative` — evita conflitar com o `position: sticky`
|
|
dela (ver regra mais abaixo). */
|
|
.ips-table-scroll .pa-table th:not(.ips-table-actions) {
|
|
position: relative;
|
|
}
|
|
|
|
.ips-col-resize-handle {
|
|
position: absolute;
|
|
top: 0;
|
|
right: -3px;
|
|
bottom: 0;
|
|
width: 6px;
|
|
cursor: col-resize;
|
|
z-index: 2;
|
|
}
|
|
|
|
.ips-col-resize-handle:hover,
|
|
.ips-col-resize-handle:active {
|
|
background: var(--accent);
|
|
opacity: 0.5;
|
|
}
|
|
|
|
/* Enquanto arrasta, trava o cursor em col-resize e desliga seleção de texto
|
|
na página inteira — sem isso, passar o mouse sobre um <input> da tabela
|
|
durante o arraste troca o cursor pra texto e pode selecionar conteúdo. */
|
|
body.is-resizing-column,
|
|
body.is-resizing-column * {
|
|
cursor: col-resize !important;
|
|
user-select: none;
|
|
}
|
|
|
|
/* Clicar no cabeçalho ordena a tabela por aquela coluna (alterna asc/desc) —
|
|
mesmo ícone ↕ estático de #ips-list-table (ver th[data-sort] mais acima),
|
|
só que aqui aplicado a qualquer .ips-col-sortable. As colunas em si têm
|
|
ordem fixa (não são mais arrastáveis) — só as linhas são reordenáveis,
|
|
por ordenação. */
|
|
.ips-col-sortable {
|
|
cursor: pointer;
|
|
user-select: none;
|
|
}
|
|
|
|
.ips-col-sortable.is-sort-asc .ips-sort-icon,
|
|
.ips-col-sortable.is-sort-desc .ips-sort-icon {
|
|
color: var(--accent);
|
|
}
|
|
|
|
/* Coluna de ações fixa na primeira posição — fica visível mesmo rolando a
|
|
tabela pra ver as colunas mais à direita (ex.: Descrição). */
|
|
.pa-table th.ips-table-actions,
|
|
.pa-table td.ips-table-actions {
|
|
position: sticky;
|
|
left: 0;
|
|
z-index: 1;
|
|
text-align: center;
|
|
}
|
|
|
|
.pa-table td.ips-table-actions {
|
|
background: var(--bg-surface);
|
|
}
|
|
|
|
.pa-table th.ips-table-actions {
|
|
background: var(--bg-surface-raised);
|
|
}
|
|
|
|
.ips-remove-linha {
|
|
width: 28px;
|
|
height: 28px;
|
|
}
|
|
|
|
.ips-remove-linha:hover {
|
|
color: var(--danger);
|
|
}
|
|
|
|
.ips-add-row {
|
|
margin-top: var(--space-3);
|
|
}
|
|
|
|
.ips-add-row button {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: var(--space-2);
|
|
}
|
|
|
|
.ips-auditoria-motivo {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
padding: 2px 10px;
|
|
border-radius: var(--radius-pill);
|
|
font-size: 0.72rem;
|
|
font-weight: 700;
|
|
color: var(--danger);
|
|
background: rgba(var(--danger-rgb), 0.14);
|
|
white-space: nowrap;
|
|
}
|
|
|
|
/* Coluna "Ação" da aba Auditoria: botão pra vincular manualmente (motivos de
|
|
leitura/grafia de nome) ou o selo de já resolvido — mesmo verde de
|
|
.status-pill--ativo (perfis-acesso.css), pra reaproveitar a mesma
|
|
linguagem visual de "confirmado/ativo" já usada no resto do portal. */
|
|
.ips-auditoria-resolvido {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
padding: 2px 10px;
|
|
border-radius: var(--radius-pill);
|
|
font-size: 0.72rem;
|
|
font-weight: 700;
|
|
color: #2f9e6e;
|
|
background: rgba(47, 158, 110, 0.14);
|
|
white-space: normal;
|
|
}
|
|
|
|
.ips-empty-cell {
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
/* Aba "Alterações" — badge de tipo (edição/inclusão/exclusão) e selo de
|
|
"Revertida", mesma linguagem visual de .ips-auditoria-motivo/
|
|
.ips-auditoria-resolvido acima. Cores por tipo: dourado (edição — uma
|
|
mudança de valor, neutra), teal (inclusão — algo foi adicionado), vermelho
|
|
(exclusão — algo foi removido, mesmo tom de alerta de .ips-auditoria-motivo). */
|
|
.ips-alteracao-tipo {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
padding: 2px 10px;
|
|
border-radius: var(--radius-pill);
|
|
font-size: 0.72rem;
|
|
font-weight: 700;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.ips-alteracao-tipo--edicao {
|
|
color: var(--gold);
|
|
background: rgba(var(--gold-rgb), 0.16);
|
|
}
|
|
|
|
.ips-alteracao-tipo--inclusao {
|
|
color: var(--teal);
|
|
background: rgba(var(--teal-rgb), 0.16);
|
|
}
|
|
|
|
.ips-alteracao-tipo--exclusao {
|
|
color: var(--danger);
|
|
background: rgba(var(--danger-rgb), 0.14);
|
|
}
|
|
|
|
.ips-alteracao-revertida {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
padding: 2px 10px;
|
|
border-radius: var(--radius-pill);
|
|
font-size: 0.72rem;
|
|
font-weight: 700;
|
|
color: #2f9e6e;
|
|
background: rgba(47, 158, 110, 0.14);
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.ips-vincular-resumo {
|
|
font-size: 0.85rem;
|
|
color: var(--text-secondary);
|
|
margin-bottom: var(--space-3);
|
|
}
|