/* =============================================================================
   InsoftERP — camada de marca + experiência mobile
   Sobrepõe o Gradient Able. Carregada DEPOIS de style-preset.css.
   Nada em ui-core/ é alterado; tudo aqui é aditivo.

   Sistema de cor (derivado do logo InsoftERP):
     --ip-brand   #67AAF3  azul do símbolo. Acentos, item ativo, fim do gradiente.
     --ip-accent  #5987DE  o hexágono satélite mais escuro do próprio logo.
     --ip-action  #2559BB  derivado da matiz do acento, escurecido até AA.
                           6,51:1 com branco nos dois sentidos.
   O azul do logo é claro demais para carregar texto branco (2,44:1), por isso
   os papéis são separados em vez de usar uma cor só.
   ========================================================================== */

/* ----------------------------------------------------------------- 1. Paleta */
:root {
  --ip-brand: #67aaf3;
  --ip-accent: #5987de;
  --ip-brand-light: #95c4f7;
  --ip-brand-tint: #f3f8fe;
  --ip-action: #2559bb;
  --ip-action-dark: #1e4796;
  --ip-ink: #262624;
  --ip-muted: #6b7280;
  --ip-line: #e8edf5;

  --ip-radius: 12px;
  --ip-radius-sm: 9px;
  --ip-shadow: 0 1px 2px rgba(31, 41, 55, 0.04), 0 8px 24px -12px rgba(37, 89, 187, 0.18);

  --ip-tabbar-h: 58px;
  --ip-safe-b: env(safe-area-inset-bottom, 0px);
  --ip-safe-t: env(safe-area-inset-top, 0px);
}

/* Sobrescreve as variáveis do preset-1 (mesma especificidade, carrega depois) */
[data-pc-preset='preset-1'] {
  --bs-primary: #2559bb;
  --bs-primary-rgb: 37, 89, 187;
  --bs-primary-light: #f3f8fe;
  --bs-blue: #2559bb;
  --bs-link-color: #2559bb;
  --bs-link-color-rgb: 37, 89, 187;
  --bs-link-hover-color: #1e4796;
  --dt-row-selected: 37, 89, 187;
  /* o item ativo do menu usa o azul do logo: é onde a marca aparece */
  --pc-sidebar-active-color: #67aaf3;
}

/* Header: gradiente do azul de ação até o azul do logo.
   O logo (texto branco) fica sobre a ponta escura, onde há contraste.

   A mesma barra vale para a frente de caixa e para o portal do cliente. Ela
   estava declarada três vezes, com três valores diferentes — barra escura no
   PDV, um gradiente de dois pontos no portal, este aqui no ERP — e o resultado
   era que os três pareciam sistemas de empresas diferentes. Agora sai daqui,
   e --pc-header-background (que só existe dentro de [data-pc-header]) apenas
   aponta para ela. */
:root {
  --ip-barra-topo: linear-gradient(100deg, #2559bb 0%, #3f7fd9 55%, #67aaf3 100%);
}

[data-pc-header='header-1'] {
  --pc-header-background: var(--ip-barra-topo);
}

/* O tema traz .bg-grd-primary com gradiente hardcoded (#4099ff, #73b4ff),
   que ignora as variáveis. O fundo das telas de login usa essa classe, então
   sobrescrevemos com o mesmo gradiente do header. */
[data-pc-preset='preset-1'] .bg-grd-primary,
.bg-grd-primary {
  /* wallpaper corporativo: hexágonos, traços de circuito e o símbolo da marca.
     Gerado em /home/insoft/brand/wallpaper/login-bg.svg */
  background: #2559bb url('../images/brand/login-bg.svg') center / cover no-repeat;
}

/* --------------------------------------------------- 2. Harmonia com a marca */
body {
  color: var(--ip-ink);
}

.card {
  border-radius: var(--ip-radius);
  border: 1px solid var(--ip-line);
  box-shadow: var(--ip-shadow);
}
.card .card-header {
  border-bottom-color: var(--ip-line);
}
.card .card-header h5 {
  font-weight: 600;
  letter-spacing: -0.01em;
}

.btn {
  border-radius: var(--ip-radius-sm);
  font-weight: 500;
}
.btn-primary {
  background-color: var(--ip-action);
  border-color: var(--ip-action);
}
.btn-primary:hover,
.btn-primary:focus,
.btn-primary:active {
  background-color: var(--ip-action-dark);
  border-color: var(--ip-action-dark);
}

.form-control,
.form-select {
  border-radius: var(--ip-radius-sm);
  border-color: var(--ip-line);
}
.form-control:focus,
.form-select:focus {
  border-color: var(--ip-brand);
  box-shadow: 0 0 0 3px rgba(103, 170, 243, 0.22);
}

/* Anel de foco visível para teclado, na cor da marca */
:focus-visible {
  outline: 2px solid var(--ip-brand);
  outline-offset: 2px;
}

/* Barra horizontal: a marca aparece no item ativo */
.pc-horizontal .pc-sidebar .pc-navbar > li.pc-item.active > .pc-link,
.pc-horizontal .pc-sidebar .pc-navbar > li.pc-item.pc-trigger > .pc-link {
  color: var(--ip-action);
  background: var(--ip-brand-tint);
  border-radius: var(--ip-radius-sm);
}
.page-header h5 {
  font-weight: 600;
  letter-spacing: -0.01em;
}

/* O layout-horizontal.js re-renderiza o menu a cada resize: por ~500ms ele
   volta ao estado plano (todos os itens e as captions soltos) antes de
   reagrupar. Em vez de deixar o usuário ver isso piscar, escondemos a barra
   durante o reflow — ver o script em layouts/app.blade.php. */
.pc-sidebar.ip-remenu .pc-navbar {
  opacity: 0;
  pointer-events: none;
}
.pc-sidebar .pc-navbar {
  transition: opacity 0.12s ease;
}

/* Modais legados (inc/modais.blade.php + js_modal.js).

   Toda a aparência deles vinha do app.css, que o layout novo não carrega:
   sem isto o conteúdo aparece como texto solto em toda página (era o banner
   "Aconteceram os seguintes Erros" fixo no topo), e ao abrir apareceria no
   meio do fluxo, sem overlay e sem posicionamento.

   O js_modal.js abre com $(id).show(), que grava display inline e portanto
   vence estas regras — não é preciso adicionar classe nenhuma no JS. */
.window,
.modal_livre {
  display: none;
  position: fixed;
  z-index: 1055;
  /* !important porque o js_modal.js escreve top/left inline em pixels,
     calculados como (altura da janela / 2 - altura do modal / 2). Esse cálculo
     vinha de um layout sem transform: somado ao translate(-50%,-50%) daqui, o
     modal era deslocado duas vezes e saía meio corpo para fora da tela — foi
     o que aconteceu com o modal de tributação, que é alto. E como o top
     calculado fica negativo em modais altos, deixar o JS posicionar cortaria
     o topo do formulário. Centralizar no CSS resolve os dois casos e mantém
     o max-height/overflow abaixo funcionando. */
  top: 50% !important;
  left: 50% !important;
  transform: translate(-50%, -50%);
  width: min(900px, calc(100vw - 2rem));
  max-height: calc(100vh - 3rem);
  overflow: auto;
  background: #fff;
  border-radius: var(--bs-border-radius, 0.5rem);
  box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.25);
}
.window.md-modal,
.modal_livre.md-modal {
  width: min(750px, calc(100vw - 2rem));
}

/* O js_modal.js dimensiona e dá fadeIn no overlay, mas quem o posicionava
   e pintava era o app.css.

   O display:none é obrigatório. No app.css o overlay não tinha dimensão nenhuma
   até o JS defini-la ao abrir, então ficava 0x0 e inofensivo. Com inset:0 ele
   passa a cobrir a tela inteira desde o carregamento: invisível (sem opacidade
   aplicada) mas capturando TODO clique da página. O fadeIn() do js_modal.js
   grava display inline ao abrir, então continua funcionando. */
#fundo_preto,
#fundo_modal_livre {
  display: none;
  position: fixed;
  inset: 0;
  background: #000;
  z-index: 1050;
}

/* Telas de bloqueio, que não carregam o menu ($semNavegacao no layout).

   No layout horizontal o .pc-container é empurrado 120px para baixo (60 da
   barra de topo + 60 da barra de menu). Sem menu, esses 60px viram uma faixa
   branca no meio da tela. */
body.ip-sem-menu[data-pc-layout="horizontal"] .pc-container {
  top: 60px;
  min-height: calc(100vh - 120px);
}
body.ip-sem-menu[data-pc-layout="horizontal"] .pc-footer {
  top: 0;
}

/* Grade legada (.rows > .col-N) dentro dos modais.

   O template antigo tinha a própria grade: o container chamava-se .rows, e os
   filhos usavam .col-1 ... .col-12 — os MESMOS nomes de classe do Bootstrap.
   O Bootstrap 5 define a largura em .col-N sem exigir ancestral, mas o
   display:flex fica em .row (singular), que não existe aqui. Resultado: os
   .col-6 do modal ficavam empilhados um por linha, e um formulário de 62
   campos virava uma coluna de 62 linhas.

   Declarar .rows como linha flex reaproveita as larguras que o Bootstrap já
   define e devolve o layout de duas/três colunas de todos os modais legados
   sem tocar em nenhuma view. */
.rows {
  display: flex;
  flex-wrap: wrap;
  --bs-gutter-x: 1rem;
  /* sem margens negativas: o modal legado já tem padding próprio e a margem
     negativa jogava os campos por cima da borda */
  margin: 0;
}
.rows > [class^="col-"],
.rows > [class*=" col-"],
.rows > .col {
  padding-left: calc(0.5 * var(--bs-gutter-x));
  padding-right: calc(0.5 * var(--bs-gutter-x));
}
/* Os campos legados não têm largura declarada; sem isto, um input largo
   estica a coluna e estoura a linha para fora do modal. */
.rows > [class^="col-"] > .form-campo,
.rows > [class*=" col-"] > .form-campo {
  width: 100%;
  max-width: 100%;
}

/* Botão de fechar, que o app.css ancorava no canto do modal. */
.window .fechar,
.window .fechar_livre,
.modal_livre .fechar,
.modal_livre .fechar_livre {
  position: absolute;
  top: 0.5rem;
  right: 0.75rem;
  cursor: pointer;
  text-decoration: none;
}

/* =========================================================================
   3. MOBILE — experiência de aplicativo nativo (<= 1024px)
   O breakpoint do template é 1024px; tudo abaixo daqui vira "app".
   ========================================================================= */
@media (max-width: 1024px) {
  html,
  body {
    overscroll-behavior-y: none; /* mata o "bounce" de página do navegador */
  }
  body {
    -webkit-tap-highlight-color: transparent;
    -webkit-font-smoothing: antialiased;
  }

  /* ---- Header do app: compacto, fixo, respeitando o notch ---- */
  .pc-header {
    height: calc(56px + var(--ip-safe-t));
    padding-top: var(--ip-safe-t);
    box-shadow: 0 1px 0 rgba(255, 255, 255, 0.12);
  }
  .pc-header .m-header {
    display: flex !important;
    height: 56px;
    padding-left: 14px;
  }
  .pc-header .m-header .logo-lg {
    height: 22px;
    width: auto;
  }
  /* some com o que é ruído em tela pequena */
  .pc-header .theme-version,
  .pc-header .pc-h-item.pc-sidebar-collapse {
    display: none !important;
  }
  .pc-header .pc-head-link {
    width: 44px;
    height: 44px; /* alvo de toque mínimo */
  }

  .pc-container {
    top: calc(56px + var(--ip-safe-t));
    margin-left: 0;
    /* espaço para a tab bar não cobrir conteúdo */
    padding-bottom: calc(var(--ip-tabbar-h) + var(--ip-safe-b) + 12px);
  }
  .pc-content {
    padding: 16px 14px 0;
  }

  /* Cards mais próximos da borda e sem peso visual excessivo */
  .card {
    border-radius: var(--ip-radius);
    margin-bottom: 14px;
  }
  .card .card-body {
    padding: 16px;
  }

  /* Tabelas: rolagem horizontal com inércia, sem quebrar o layout */
  .table-responsive {
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .table-responsive::-webkit-scrollbar {
    display: none;
  }

  /* O rodapé de desktop não faz sentido em app */
  .pc-footer {
    display: none;
  }

  /* ---- Drawer de navegação: sensação de sheet nativo ---- */
  .pc-sidebar {
    top: 0;
    padding-top: var(--ip-safe-t);
    box-shadow: 0 0 40px rgba(15, 23, 42, 0.25);
  }
  .pc-sidebar .pc-link {
    padding-top: 13px;
    padding-bottom: 13px; /* itens confortáveis para o dedo */
  }
  .navbar-overlay {
    backdrop-filter: blur(2px);
  }

  /* =======================================================================
     Tab bar inferior — o principal gesto de navegação no mobile.
     Markup em resources/views/partials/tabbar.blade.php
     ======================================================================= */
  .ip-tabbar {
    position: fixed;
    z-index: 1030;
    left: 0;
    right: 0;
    bottom: 0;
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    height: calc(var(--ip-tabbar-h) + var(--ip-safe-b));
    padding-bottom: var(--ip-safe-b);
    background: rgba(255, 255, 255, 0.92);
    backdrop-filter: saturate(180%) blur(18px);
    -webkit-backdrop-filter: saturate(180%) blur(18px);
    border-top: 1px solid var(--ip-line);
  }
  .ip-tabbar__item {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    text-decoration: none;
    color: var(--ip-muted);
    font-size: 10.5px;
    font-weight: 500;
    line-height: 1;
    background: none;
    border: 0;
    padding: 0;
    -webkit-tap-highlight-color: transparent;
    transition: color 0.15s ease;
  }
  .ip-tabbar__item i {
    font-size: 22px;
    line-height: 1;
  }
  .ip-tabbar__item.active {
    color: var(--ip-action);
  }
  /* traço da marca sobre o item ativo */
  .ip-tabbar__item.active::before {
    content: '';
    position: absolute;
    top: 0;
    left: 50%;
    transform: translateX(-50%);
    width: 26px;
    height: 3px;
    border-radius: 0 0 3px 3px;
    background: var(--ip-brand);
  }
  .ip-tabbar__item:active {
    color: var(--ip-action-dark);
    transform: scale(0.94);
  }

  /* A aba "Menu" substitui o hambúrguer do header: tiramos ele do campo
     visual, mas mantemos no DOM e clicável (a tab bar delega o clique). */
  .pc-header .pc-h-item.pc-sidebar-popup {
    position: absolute;
    left: -9999px;
  }

  /* ---- Densidade de app: KPIs em duas colunas, cards mais enxutos ---- */
  .ip-kpi .card-body {
    padding: 14px;
  }
  .ip-kpi h4 {
    font-size: 1.15rem;
  }
  .ip-kpi p {
    font-size: 0.8rem;
  }
}

/* ===================================================================
   Telefone (<= 575px): a tabela vira lista, como em app nativo.
   Uso: <table class="table ip-stack"> + data-label em cada <td>.
   =================================================================== */
@media (max-width: 575.98px) {
  .ip-stack thead {
    display: none;
  }
  .ip-stack,
  .ip-stack tbody,
  .ip-stack tr,
  .ip-stack td {
    display: block;
    width: 100%;
  }
  .ip-stack tr {
    padding: 12px 4px;
    border-bottom: 1px solid var(--ip-line);
  }
  .ip-stack tr:last-child {
    border-bottom: 0;
  }
  .ip-stack td {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    border: 0;
    padding: 5px 16px;
  }
  .ip-stack td::before {
    content: attr(data-label);
    color: var(--ip-muted);
    font-size: 0.75rem;
    font-weight: 500;
    white-space: nowrap;
  }
  /* a primeira célula é o título da "linha-card" */
  .ip-stack td:first-child {
    padding-bottom: 8px;
  }
  .ip-stack td:first-child::before {
    display: none;
  }
  .ip-stack .table-responsive,
  .ip-stack.table-responsive {
    overflow: visible;
  }

  /* A célula de ações não precisa de rótulo: os ícones já dizem o que são.
     Ela vira uma faixa de botões alinhada à direita, colada no item. */
  .ip-stack td[data-label='Ação'],
  .ip-stack td[data-label='Ações'] {
    justify-content: flex-end;
    gap: 18px;
    padding-top: 2px;
  }
  .ip-stack td[data-label='Ação']::before,
  .ip-stack td[data-label='Ações']::before {
    display: none;
  }
  /* linhas vazias ("Nada aguardando...") não devem virar cartão */
  .ip-stack td[colspan] {
    justify-content: center;
  }
  .ip-stack td[colspan]::before {
    display: none;
  }
}

/* Telefone: os KPIs ficam com metade da largura, então o valor precisa
   caber sem quebrar. Escala menor e valor sem wrap. */
@media (max-width: 575.98px) {
  .ip-kpi .card-body {
    padding: 12px;
  }
  .ip-kpi p {
    font-size: 0.75rem;
    line-height: 1.25;
  }
  .ip-kpi h4 {
    font-size: 1rem;
    white-space: nowrap;
  }
  .ip-kpi .text-sm {
    font-size: 0.7rem;
  }
  .ip-kpi i {
    font-size: 1rem !important;
  }

  /* linhas da lista um pouco mais compactas */
  .ip-stack tr {
    padding: 8px 4px;
  }
  .ip-stack td {
    padding: 4px 16px;
  }
}

/* A tab bar só existe no mobile */
@media (min-width: 1025px) {
  .ip-tabbar {
    display: none;
  }
}

/* --------------------------------------- 4. Modo escuro: mantém a marca ---- */
[data-pc-theme='dark'] {
  --ip-line: #2a3448;
  --ip-ink: #e6eaf2;
}
[data-pc-theme='dark'] .card {
  border-color: var(--ip-line);
}
[data-pc-theme='dark'] .ip-tabbar {
  background: rgba(20, 26, 38, 0.92);
  border-top-color: var(--ip-line);
}
[data-pc-theme='dark'] .ip-tabbar__item {
  color: #94a3b8;
}
[data-pc-theme='dark'] .ip-tabbar__item.active {
  color: var(--ip-brand);
}

/* ------------------------------------------------- 5. Acessibilidade ------- */
@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* ---------------------------------------------------------------------------
   Autocompletes legados (.listaClientes, .listaProdutos, ...).

   Vários formulários do ERP têm busca ao vivo: um <input> de texto e um
   <ol class="listaX"> que o JS injeta logo depois com os resultados. Toda a
   aparência vinha do app.css, com top/left/right fixos calibrados para o grid
   antigo — sem isto a lista aparece como uma lista solta no meio da página.

   No layout novo o posicionamento é relativo ao campo: basta envolver o input
   num elemento com a classe .ip-autocomplete.
   --------------------------------------------------------------------------- */
.ip-autocomplete {
  position: relative;
}

.listaClientes,
.listaProdutos,
.listaServicos,
.listaFornecedores,
.listaTransportadoraPesquisado,
.listaTipoDespesa,
.listaVendedor,
.listaTecnico,
.listaCategorias {
  position: absolute;
  z-index: 1050;
  top: 100%;
  left: 0;
  right: 0;
  margin: 0.125rem 0 0;
  padding: 0;
  list-style: none;
  max-height: 15rem;
  overflow-y: auto;
  background: var(--bs-body-bg, #fff);
  border: 1px solid var(--bs-border-color, #dbe0e5);
  border-radius: var(--bs-border-radius, 0.5rem);
  box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.12);
}

.listaClientes:empty,
.listaProdutos:empty,
.listaServicos:empty,
.listaFornecedores:empty,
.listaTransportadoraPesquisado:empty,
.listaTipoDespesa:empty,
.listaVendedor:empty,
.listaTecnico:empty,
.listaCategorias:empty {
  display: none;
}

.listaClientes li,
.listaProdutos li,
.listaServicos li,
.listaFornecedores li,
.listaTransportadoraPesquisado li,
.listaTipoDespesa li,
.listaVendedor li,
.listaTecnico li,
.listaCategorias li {
  display: block;
}

.listaClientes a,
.listaProdutos a,
.listaServicos a,
.listaFornecedores a,
.listaTransportadoraPesquisado a,
.listaTipoDespesa a,
.listaVendedor a,
.listaTecnico a,
.listaCategorias a {
  display: block;
  padding: 0.5rem 0.75rem;
  color: var(--bs-body-color, #5b6b79);
  text-decoration: none;
  border-bottom: 1px solid var(--bs-border-color, #dbe0e5);
}

.listaClientes li:last-child a,
.listaProdutos li:last-child a,
.listaServicos li:last-child a,
.listaFornecedores li:last-child a,
.listaTransportadoraPesquisado li:last-child a,
.listaTipoDespesa li:last-child a,
.listaVendedor li:last-child a,
.listaTecnico li:last-child a,
.listaCategorias li:last-child a {
  border-bottom: 0;
}

.listaClientes a:hover,
.listaProdutos a:hover,
.listaServicos a:hover,
.listaFornecedores a:hover,
.listaTransportadoraPesquisado a:hover,
.listaTipoDespesa a:hover,
.listaVendedor a:hover,
.listaTecnico a:hover,
.listaCategorias a:hover {
  background: var(--bs-tertiary-bg, #f8f9fa);
}

/* O atributo hidden do HTML vale display:none pela folha do navegador, que tem
   especificidade menor que qualquer classe. Componentes do Bootstrap que
   declaram display (.card e .d-flex são flex, .row é flex, .btn é inline-block)
   continuavam visíveis mesmo com hidden=true. Como usamos el.hidden para
   esconder blocos por JS, a regra precisa vencer. */
[hidden] {
  display: none !important;
}

/* ---------------------------------------------------------------------------
   Avisos flutuantes do JS legado (.msg).

   MostrarUmaMsgSucesso() e MostrarMsgErros(), do js_util.js, montam um <span
   class="msg msg-verde position-fixed right top"> e o injetam num container da
   página. São usados em quase todo lançamento por AJAX do sistema — inserir
   item de entrada, de saída, de venda — e toda a aparência vinha do app.css.

   Sem estas regras o aviso sai como texto solto no meio do conteúdo.
   Bootstrap já tem .position-fixed e .top-0/.end-0, mas o markup legado usa
   .right e .top, que não existem no Bootstrap 5.
   --------------------------------------------------------------------------- */
.msg {
  position: relative;
  display: block;
  max-width: min(28rem, calc(100vw - 2rem));
  padding: 0.75rem 2rem 0.75rem 1rem;
  border: 1px solid transparent;
  border-radius: var(--bs-border-radius, 0.5rem);
  box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
}

.msg.position-fixed {
  z-index: 1060;
}
.msg.position-fixed.top {
  top: 1rem;
}
.msg.position-fixed.bottom {
  bottom: 1rem;
}
.msg.position-fixed.right {
  right: 1rem;
}
.msg.position-fixed.left {
  left: 1rem;
}

.msg.msg-verde {
  background: #d1f0dd;
  border-color: #8fcea6;
  color: #1c6b3f;
}
.msg.msg-vermelho {
  background: #fbdada;
  border-color: #e8a3a3;
  color: #8c2d2d;
}
.msg.msg-amarelo {
  background: #fbf3d0;
  border-color: #e8cf8a;
  color: #8a6318;
}

.msg ul,
.msg ol {
  margin: 0.5rem 0 0;
  padding-left: 1.25rem;
}
.msg li {
  line-height: 1.5;
}

.msg a.sair {
  position: absolute;
  top: 0.35rem;
  right: 0.6rem;
  font-weight: 600;
  color: inherit;
  text-decoration: none;
}

/* ===========================================================================
   Frente de caixa (resources/views/Frente)
   ===========================================================================
   A frente veio da aplicação avulsa /home/insoft/pdv e trouxe o CSS dela:
   .bg-topo, .btn-verde, .btn-amarelo, .caixa, .conteudo-fluido. As telas de
   venda têm 700 linhas cada e estão amarradas a esses nomes — mapear as
   classes aqui troca o visual sem reescrever cinco arquivos grandes.

   A barra de operação é escura de propósito: a frente é usada em pé, muitas
   vezes sob luz de loja, e o contraste alto ajuda a bater o olho no estado do
   caixa. O conteúdo abaixo dela usa o mesmo claro do resto do ERP.
   =========================================================================== */

body.ip-frente {
  background: var(--bs-body-bg, #f7f8fa);
  margin: 0;
}

.ip-frente-topo {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0 1.25rem;
  height: 60px;
  background: var(--ip-barra-topo);
  color: #fff;
  position: sticky;
  top: 0;
  z-index: 1030;
}

.ip-frente-marca {
  display: flex;
  align-items: baseline;
  gap: .6rem;
  text-decoration: none;
  flex: none;
}
.ip-frente-marca img { height: 22px; display: block; }
.ip-frente-marca span {
  font-size: .72rem;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .8);
}

/* Estado do caixa: é a informação que o operador mais consulta. */
.ip-caixa {
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  padding: .32rem .75rem;
  border-radius: 999px;
  font-size: .84rem;
  font-weight: 600;
  white-space: nowrap;
}
/* Pílulas sólidas: as anteriores eram translúcidas e só funcionavam sobre a
   barra escura — sobre o azul claro da ponta direita viravam borrões. */
.ip-caixa.aberto  { background: #e3f7ec; color: #176944; }
.ip-caixa.fechado { background: #fde8e6; color: #9d2a1d; }

.ip-frente-acoes { display: flex; gap: .5rem; }
.ip-frente-acoes .ip-acao {
  display: inline-flex; align-items: center; gap: .4rem;
  padding: .35rem .85rem;
  border-radius: 999px;
  font-size: .86rem; font-weight: 500;
  text-decoration: none;
  background: rgba(0, 0, 0, .22);
  color: #fff;
  white-space: nowrap;
}
.ip-frente-acoes .ip-acao:hover { background: rgba(0, 0, 0, .34); color: #fff; }
/* Iniciar venda é a ação que o operador repete o dia inteiro: é a única coisa
   sólida na barra, para achar sem procurar. */
.ip-frente-acoes .ip-acao.principal { background: #fff; color: #1f4fa6; font-weight: 600; }
.ip-frente-acoes .ip-acao.principal:hover { background: #eef4fb; color: #1a4390; }

.ip-frente-menu { margin-left: auto; }
.ip-frente-menu .btn-link-light { color: rgba(255,255,255,.85); }
.ip-frente-menu .btn-link-light:hover { color: #fff; }

.ip-frente-usuario {
  display: flex;
  align-items: center;
  gap: .75rem;
  font-size: .88rem;
  color: #fff;
  /* Fica na ponta clara do gradiente, onde texto branco solto não se lê. */
  background: rgba(0, 0, 0, .22);
  border-radius: 999px;
  padding: .3rem .8rem;
}
.ip-frente-usuario a { color: rgba(255,255,255,.85); text-decoration: none; font-size: 1.05rem; }
.ip-frente-usuario a:hover { color: #fff; }

.ip-frente-menu .btn-link-light,
.ip-frente-menu .btn-link-light:hover { background: rgba(0, 0, 0, .22); border-radius: 999px; }

.ip-frente-conteudo { padding: 1.5rem; }

@media (max-width: 820px) {
  .ip-frente-marca span,
  .ip-frente-usuario span { display: none; }
  .ip-frente-topo { gap: .6rem; padding: 0 .75rem; }
  .ip-frente-conteudo { padding: 1rem .75rem; }
}

/* ---- classes do template antigo do PDV ---- */

.ip-frente .bg-topo,
.ip-frente .conteudo-fluido { background: transparent; }

.ip-frente .caixa,
.ip-frente .conteudo {
  background: var(--bs-card-bg, #fff);
  border: 1px solid var(--bs-border-color, #e5e7eb);
  border-radius: var(--bs-border-radius, .5rem);
  padding: 1.25rem;
  margin-bottom: 1.25rem;
}

.ip-frente .btn-amarelo,
.ip-frente .btn-laranja {
  display: inline-flex; align-items: center; gap: .4rem;
  padding: .45rem .9rem; border: 0; border-radius: var(--bs-border-radius, .375rem);
  background: #b7791f; color: #fff; text-decoration: none; font-size: .88rem; cursor: pointer;
}
.ip-frente .btn-amarelo:hover { filter: brightness(1.1); color: #fff; }

.ip-frente .text-verde   { color: #2e7d5b; font-weight: 600; }
.ip-frente .text-vermelho{ color: #c0392b; font-weight: 600; }
.ip-frente .text-branco  { color: inherit; }

/* O título das telas vinha branco sobre a barra colorida do template antigo;
   no fundo claro ele sumia. */
.ip-frente .bg-title,
.ip-frente .titulo-pagina {
  background: transparent;
  color: var(--bs-heading-color, #12202e);
  font-weight: 600;
  padding: 0 0 .75rem;
}

/* Sobreposição de carregamento do js_util.js */
.ip-frente .window.load {
  display: none;
  position: fixed; inset: 0;
  background: rgba(18, 32, 46, .55);
  z-index: 1060;
  align-items: center; justify-content: center;
}
.ip-frente .window.load .text-load {
  background: #fff; color: #12202e;
  padding: .9rem 1.5rem; border-radius: .5rem; font-weight: 600;
}

/* Botões de contorno do template antigo do PDV. */
.ip-frente .btn-outline-verde,
.ip-frente .btn-outline-azul,
.ip-frente .btn-outline-roxo {
  display: inline-flex; align-items: center; gap: .35rem;
  padding: .3rem .7rem; font-size: .82rem;
  border: 1px solid currentColor; border-radius: var(--bs-border-radius, .375rem);
  background: transparent; text-decoration: none; cursor: pointer;
}
.ip-frente .btn-outline-verde { color: #2e7d5b; }
.ip-frente .btn-outline-azul  { color: #1b5fb0; }
.ip-frente .btn-outline-roxo  { color: #6f42c1; }
.ip-frente .btn-outline-verde:hover { background: #2e7d5b; color: #fff; }
.ip-frente .btn-outline-azul:hover  { background: #1b5fb0; color: #fff; }
.ip-frente .btn-outline-roxo:hover  { background: #6f42c1; color: #fff; }

.ip-frente .btn-pequeno { padding: .28rem .6rem; font-size: .8rem; }

/* Campos do template antigo → aparência dos campos do UI novo. */
.ip-frente .form-campo {
  display: block; width: 100%;
  padding: .5rem .75rem;
  font-size: .9rem; line-height: 1.5;
  color: var(--bs-body-color, #12202e);
  background: var(--bs-body-bg, #fff);
  border: 1px solid var(--bs-border-color, #dde3ec);
  border-radius: var(--bs-border-radius, .375rem);
}
.ip-frente .form-campo:focus {
  outline: 0;
  border-color: #1b5fb0;
  box-shadow: 0 0 0 .2rem rgba(27, 95, 176, .15);
}

/* O DataTables já traz busca própria; a caixa de filtro do template antigo
   ficava ao lado dela, duas "Pesquisar" na mesma tela. */
.ip-frente .mostraFiltro { margin-bottom: 1rem; }

/* ---- telas de venda (tela cheia) ---- */

body.ip-frente-venda { background: #eef1f6; }

.ip-venda-topo {
  display: flex; align-items: center; gap: 1.5rem;
  padding: 0 1.25rem; height: 62px;
  background: var(--ip-barra-topo); color: #fff;
  position: sticky; top: 0; z-index: 1030;
}
.ip-venda-topo .ip-frente-marca img { height: 22px; }

.ip-venda-dados { display: flex; gap: 2rem; margin: 0; flex: 1; }
.ip-venda-dados > div { display: flex; flex-direction: column; }
.ip-venda-dados dt {
  font-size: .68rem; letter-spacing: .08em; text-transform: uppercase;
  color: rgba(255,255,255,.78); font-weight: 500;
}
.ip-venda-dados dd {
  margin: 0; font-size: .95rem; font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.ip-venda-sair {
  color: #fff; font-size: 1.15rem; text-decoration: none;
  background: rgba(0,0,0,.22); border-radius: 999px;
  padding: .25rem .55rem; line-height: 1;
}
.ip-venda-sair:hover { color: #fff; }

.ip-venda-conteudo { padding: 1.25rem; }

@media (max-width: 900px) {
  .ip-venda-dados { gap: 1rem; overflow-x: auto; }
  .ip-venda-dados dd { font-size: .85rem; }
}

/* Atalhos da frente de caixa: alvos grandes, porque a tela costuma ser
   tocada com o dedo, em pé, e às vezes com a mão ocupada. */
.ip-atalhos {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  gap: 1rem;
  max-width: 60rem;
  margin: 1rem auto;
}
.ip-atalho {
  display: flex; flex-direction: column; align-items: center; gap: .35rem;
  padding: 1.75rem 1rem;
  background: var(--bs-card-bg, #fff);
  border: 1px solid var(--bs-border-color, #e5e7eb);
  border-radius: var(--bs-border-radius, .5rem);
  text-decoration: none; text-align: center;
  color: var(--bs-body-color, #12202e);
  transition: border-color .12s ease, transform .12s ease;
}
.ip-atalho:hover { border-color: #1b5fb0; transform: translateY(-2px); color: var(--bs-body-color, #12202e); }
.ip-atalho i { font-size: 2.1rem; color: #1b5fb0; }
.ip-atalho strong { font-size: 1.02rem; }
.ip-atalho span { font-size: .84rem; color: var(--bs-secondary-color, #6b7280); }

@media (prefers-reduced-motion: reduce) { .ip-atalho { transition: none; } .ip-atalho:hover { transform: none; } }

/* A build do Gradient Able não traz todas as utilidades do Bootstrap —
   .mx-auto, por exemplo, não existe. Em vez de depender do que o vendor
   incluiu, a frente centraliza com uma classe própria. */
.ip-centro { margin-left: auto !important; margin-right: auto !important; }

/* Atalhos de operação do painel: precisam parecer clicáveis sem virar mais
   um cartão de número entre os indicadores. */
.ip-atalho-op { border: 1px solid var(--bs-border-color, #e5e7eb); transition: border-color .12s ease; }
.ip-atalho-op:hover { border-color: #1b5fb0; }
@media (prefers-reduced-motion: reduce) { .ip-atalho-op { transition: none; } }

/* ═══════════════════════════════════════════════════════════════════════
   Canais e acessos (Admin > Configurações > Canais)
   Listas "rótulo / explicação" e os dois quadros de tipo de senha.
   ═══════════════════════════════════════════════════════════════════════ */
.ip-canal-dl { margin: 0 0 .25rem; }
.ip-canal-dl dt {
  font-size: .75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--bs-secondary, #5b6b79);
  margin-top: .85rem;
}
.ip-canal-dl dt:first-child { margin-top: 0; }
.ip-canal-dl dd { margin: .15rem 0 0; }

.ip-canal-senha { display: grid; gap: .9rem; }
.ip-canal-senha > div {
  border-left: 3px solid rgba(0, 0, 0, .08);
  padding-left: .8rem;
}

/* O campo do link é readonly só para não ser editado por engano — mas o tema
   pinta readonly em cinza-claro, e o endereço ficava com cara de placeholder,
   como se estivesse vazio. Aqui ele é o conteúdo principal do cartão. */
[data-pc-direction] .ip-copiar-campo[readonly],
.ip-copiar-campo[readonly] {
  background-color: var(--bs-body-bg, #fff);
  color: var(--bs-body-color, #1b2431);
  font-weight: 500;
}

/* ═══════════════════════════════════════════════════════════════════════════
   PDV — camada de compatibilidade, parte 2.

   O template e o cabeçalho da frente de caixa foram para o sistema visual
   novo, mas a maioria das telas de dentro continua com o markup do PDV antigo.
   A camada existente cobria 8 classes; as 18 abaixo não tinham mapeamento
   nenhum, e era por isso que o PDV parecia outro sistema mesmo depois da
   migração: 240 botões (.btn-verde/.btn-azul/.btn-vermelho) saíam como links
   sem forma, 234 rótulos sem estilo, e o grid inteiro (.rows) desmontava,
   porque a classe do Bootstrap é .row — no singular — e os .col-N dentro dela
   ficavam sem contêiner flex.

   Isto não substitui reescrever as telas; é o que faz o módulo ficar coerente
   enquanto elas não são reescritas uma a uma.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ---- grid: .rows é o .row do Bootstrap com outro nome ---- */
.ip-frente .rows {
  --bs-gutter-x: 1rem;
  --bs-gutter-y: 0;
  display: flex;
  flex-wrap: wrap;
  margin-right: calc(-0.5 * var(--bs-gutter-x));
  margin-left: calc(-0.5 * var(--bs-gutter-x));
}
.ip-frente .rows > [class*="col-"] {
  flex-shrink: 0;
  max-width: 100%;
  padding-right: calc(var(--bs-gutter-x) * 0.5);
  padding-left: calc(var(--bs-gutter-x) * 0.5);
}
/* O template antigo usava estes dois nomes onde hoje se escreve justify-content. */
.ip-frente .justify-content-space-between { justify-content: space-between; }
.ip-frente .center-middle { display: flex; align-items: center; }

/* ---- botões: mesma família visual dos botões do tema ---- */
.ip-frente .btn-verde,
.ip-frente .btn-azul,
.ip-frente .btn-vermelho,
.ip-frente .btn-cinza {
  display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
  padding: .45rem .9rem;
  border: 0; border-radius: var(--bs-border-radius, .375rem);
  font-size: .88rem; font-weight: 500; line-height: 1.5;
  text-decoration: none; cursor: pointer;
  color: #fff;
}
.ip-frente .btn-azul     { background: #2559bb; }
.ip-frente .btn-verde    { background: #1a7a4f; }
.ip-frente .btn-vermelho { background: #b03024; }
.ip-frente .btn-cinza    { background: #5b6b79; }
.ip-frente .btn-verde:hover,
.ip-frente .btn-azul:hover,
.ip-frente .btn-vermelho:hover,
.ip-frente .btn-cinza:hover { filter: brightness(1.12); color: #fff; }

/* O amarelo era #b7791f, um marrom que não existe na paleta: virava a cor mais
   forte da tela sem ser a ação mais importante. */
.ip-frente .btn-amarelo,
.ip-frente .btn-laranja { background: #b06f00; }

.ip-frente .btn-medio  { padding: .55rem 1.1rem; font-size: .95rem; }
.ip-frente .btn-grande { padding: .8rem 1.4rem; font-size: 1.05rem; width: 100%; }

.ip-frente .base-botoes {
  display: flex; flex-wrap: wrap; gap: .5rem; align-items: center;
}

/* ---- rótulos e textos ---- */
.ip-frente .text-label {
  display: block;
  font-size: .75rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: .03em;
  color: var(--bs-secondary, #5b6b79);
  margin-bottom: .2rem;
}
.ip-frente .text-azul    { color: #2559bb; font-weight: 600; }
.ip-frente .text-amarelo { color: #b06f00; font-weight: 600; }
.ip-frente .text-escuro  { color: var(--bs-heading-color, #12202e); font-weight: 600; }

/* ---- blocos e utilitários de medida ---- */
/* .base-pdv envolve a tela de venda inteira, que precisa da largura toda.
   Um max-width aqui espremia a venda em 544px numa tela de 1440. */
.ip-frente .base-pdv { width: 100%; }
.ip-frente .bg-title2 {
  background: var(--bs-card-bg, #fff);
  color: var(--bs-body-color, #1b2431);
}
.ip-frente .barra {
  border-top: 1px solid var(--bs-border-color, #e5e7eb);
  margin-top: 1rem; padding-top: .75rem;
  font-size: .88rem; color: var(--bs-secondary, #5b6b79);
}
.ip-frente .width-100 { width: 100%; }
.ip-frente .width-30  { width: 30%; }
.ip-frente .radius-0  { border-radius: 0; }
.ip-frente .radius-4  { border-radius: .25rem; }
.ip-frente .radius-10 { border-radius: .625rem; }
.ip-frente .img-fluido { max-width: 100%; height: auto; }

/* ---- Caixa livre: tela de espera do balcão ---- */
.ip-livre { display: flex; justify-content: center; padding-top: 2rem; }
.ip-livre-cartao { width: 100%; max-width: 26rem; }
.ip-livre-estado {
  display: inline-flex; align-items: center; gap: .3rem;
  font-size: 1.35rem; font-weight: 600;
  color: #1a7a4f;
  margin-bottom: .25rem;
}
.ip-livre-relogio {
  display: flex; justify-content: center; gap: 3rem;
  margin: 1.75rem 0 0; padding-top: 1.25rem;
  border-top: 1px solid var(--bs-border-color, #e5e7eb);
}
.ip-livre-relogio dt {
  font-size: .72rem; text-transform: uppercase; letter-spacing: .05em;
  color: var(--bs-secondary, #5b6b79); font-weight: 600;
}
.ip-livre-relogio dd {
  margin: 0; font-size: 1.5rem; font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* ---- Abas (jQuery UI) dentro do PDV ----
   js_util.js chama $('#tabs').tabs(), e o jQuery UI marca o elemento com
   .ui-tabs/.ui-widget — mas o CSS do jQuery UI nunca foi carregado. Resultado:
   as abas de "Resgatar venda" apareciam como uma lista de marcadores, e o
   operador não percebia que eram botões. Em vez de trazer o tema inteiro do
   jQuery UI (que traria o visual de 2012 junto), as poucas classes usadas são
   desenhadas aqui na linguagem do UI novo. */
.ip-frente .ui-tabs > .ui-tabs-nav {
  display: flex; flex-wrap: wrap; gap: .25rem;
  list-style: none; margin: 0 0 1rem; padding: 0;
  border-bottom: 1px solid var(--bs-border-color, #e5e7eb);
}
.ip-frente .ui-tabs > .ui-tabs-nav li { list-style: none; margin-bottom: -1px; }
.ip-frente .ui-tabs > .ui-tabs-nav li a {
  display: block; padding: .55rem 1rem;
  color: var(--bs-secondary, #5b6b79); text-decoration: none;
  border: 1px solid transparent;
  border-radius: .375rem .375rem 0 0;
  font-size: .92rem; font-weight: 500;
}
.ip-frente .ui-tabs > .ui-tabs-nav li a:hover {
  color: #2559bb; background: rgba(37, 89, 187, .06);
}
.ip-frente .ui-tabs > .ui-tabs-nav li.ui-tabs-active a {
  color: #2559bb; font-weight: 600;
  background: var(--bs-card-bg, #fff);
  border-color: var(--bs-border-color, #e5e7eb);
  border-bottom-color: var(--bs-card-bg, #fff);
}
.ip-frente .ui-tabs .ui-tabs-panel { padding: 0; }
.ip-frente .ui-helper-hidden-accessible { display: none; }

/* ---- Botão de tela cheia da frente de caixa ----
   Alvo grande: a frente é operada em pé, às vezes com a mão ocupada e em
   monitor de toque. Segue a mesma pílula translúcida dos outros controles da
   barra, que é o que dá contraste sobre a ponta clara do gradiente. */
.ip-tela-cheia {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2rem; height: 2rem;
  padding: 0; border: 0;
  border-radius: 999px;
  background: transparent;
  color: rgba(255, 255, 255, .85);
  font-size: 1.05rem; line-height: 1;
  cursor: pointer;
}
.ip-tela-cheia:hover { background: rgba(255, 255, 255, .18); color: #fff; }
.ip-tela-cheia:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
/* Em tela cheia o botão fica marcado: é a única pista de que o F11 não é a
   única saída. */
.ip-tela-cheia.ativo { background: rgba(255, 255, 255, .22); color: #fff; }

/* Na tela de venda o botão fica ao lado do X de sair. */
.ip-venda-acoes { display: flex; align-items: center; gap: .5rem; margin-left: auto; }
.ip-venda-acoes .ip-venda-sair { margin-left: 0; }

/* ---- Indicador de carregamento ----
   O sistema usava cinco GIFs animados diferentes (load2.gif, loading.gif,
   ajax-loader_1.gif, load.gif...), e DOIS deles nem existiam no disco: 14
   telas mostravam o ícone de imagem quebrada no lugar do "aguarde". Um
   elemento em CSS não tem arquivo para faltar, acompanha a cor do tema e não
   pesa nada. */
.ip-spinner {
  display: inline-block;
  width: 2.25rem; height: 2.25rem;
  border: 3px solid rgba(37, 89, 187, .18);
  border-top-color: #2559bb;
  border-radius: 50%;
  animation: ip-girar .7s linear infinite;
  vertical-align: middle;
}
.ip-spinner.pequeno { width: 1.1rem; height: 1.1rem; border-width: 2px; }
.ip-spinner.claro   { border-color: rgba(255,255,255,.3); border-top-color: #fff; }

@keyframes ip-girar { to { transform: rotate(360deg); } }

/* Quem prefere menos movimento vê um pulso discreto em vez do giro. */
@media (prefers-reduced-motion: reduce) {
  .ip-spinner { animation: ip-pulsar 1.4s ease-in-out infinite; }
  @keyframes ip-pulsar { 50% { opacity: .35; } }
}

/* ---- Atalhos de teclado da tela de venda ----
   Eram links azuis corridos, cinco por coluna, formando uma parede de texto em
   que a tecla e o nome da ação tinham o mesmo peso. Quem opera o caixa procura
   a TECLA; o nome é a confirmação. */
.ip-frente .ip-atalhos-teclado { display: flex; flex-direction: column; gap: .3rem; }
.ip-frente .ip-atalhos-teclado a {
  display: flex; align-items: center; gap: .5rem;
  padding: .3rem .5rem;
  border-radius: .375rem;
  color: var(--bs-body-color, #1b2431);
  text-decoration: none;
  font-size: .86rem;
}
.ip-frente .ip-atalhos-teclado a:hover { background: rgba(37, 89, 187, .07); }
.ip-frente .ip-atalhos-teclado kbd {
  flex: none; min-width: 3.6rem; text-align: center;
  padding: .2rem .45rem;
  background: #fff;
  border: 1px solid #ccd6e4;
  border-bottom-width: 2px;
  border-radius: .3rem;
  color: #2559bb;
  font-family: inherit; font-size: .76rem; font-weight: 600;
}
.ip-frente .ip-atalhos-teclado span { color: var(--bs-secondary, #5b6b79); }

/* O quadro do produto tem altura fixa para a tela não pular a cada troca de
   item. O placeholder ocupa parte dele, não o quadro inteiro. */
.ip-frente .area-prod { display: flex; align-items: center; justify-content: center; }
.ip-frente .area-prod .tmb-prog { width: 100%; }
/* O SVG do placeholder não tinha tamanho intrínseco: com width:auto o
   navegador resolvia para 0 e a imagem sumia, deixando um traço de 1px. */
.ip-frente .area-prod img {
  max-width: 100%; max-height: 14rem; height: auto;
  margin: 0 auto; display: block;
}

/* ═══════════════════════════════════════════════════════════════════════════
   Tela de venda da frente de caixa (Frente/Pdv/Create)

   O layout antigo dava metade da tela ao formulário de entrada e metade à
   lista, e o total da venda — o número que operador e cliente conferem em voz
   alta — era um campo de formulário do mesmo tamanho de "Volumes". Aqui a
   lista é a protagonista e o total é o maior elemento da tela.
   ═══════════════════════════════════════════════════════════════════════════ */
.ip-venda { display: flex; flex-direction: column; gap: 1rem; }

.ip-venda-grade {
  display: grid;
  grid-template-columns: minmax(22rem, 32%) 1fr;
  gap: 1rem;
  align-items: start;
}

.ip-venda-entrada .card-body { padding: 1.25rem; }

/* Nome do produto lido. É a confirmação de que o bipe pegou o item certo,
   então tem peso de título e não de legenda. */
.ip-venda-produto {
  margin: 0 0 1rem;
  font-size: 1.15rem; font-weight: 600;
  color: var(--bs-heading-color, #12202e);
  min-height: 1.6em;
}

.ip-venda-foto {
  display: flex; align-items: center; justify-content: center;
  aspect-ratio: 1;
  background: #f4f7fb;
  border: 1px solid var(--bs-border-color, #e5e7eb);
  border-radius: .5rem;
  overflow: hidden;
}
.ip-venda-foto img { max-width: 80%; max-height: 80%; height: auto; }

.ip-venda-rodape-esq {
  display: grid; grid-template-columns: 1fr 1fr; gap: .5rem;
  margin-top: 1.25rem; padding-top: 1rem;
  border-top: 1px solid var(--bs-border-color, #e5e7eb);
}

/* ---- cupom (coluna da direita) ---- */
.ip-venda-cupom { display: flex; flex-direction: column; }
.ip-venda-cliente { font-size: .88rem; color: var(--bs-secondary, #5b6b79); }

.ip-venda-lista {
  flex: 1;
  min-height: 18rem; max-height: calc(100vh - 24rem);
  overflow-y: auto;
}
.ip-venda-lista thead th {
  position: sticky; top: 0; z-index: 1;
  background: var(--bs-card-bg, #fff);
}
/* A tabela é lida de relance, com o cliente esperando: números alinhados e
   com largura fixa de dígito evitam que a coluna "dance" a cada item. */
.ip-venda-lista td { font-variant-numeric: tabular-nums; }
.ip-venda-lista .fw-600 { font-weight: 600; }

.ip-venda-vazio {
  padding: 3rem 1rem; margin: 0;
  text-align: center; color: var(--bs-secondary, #5b6b79);
}
/* Some sozinho quando o JS escreve a primeira linha em #itensDaVenda.
   O combinador irmão (~) não servia: o <tbody> está dentro da <table> e o
   aviso é irmão da tabela, não do tbody — a regra nunca casava e o "passe o
   primeiro produto" continuava embaixo dos itens. :has() olha para dentro. */
.ip-venda-lista:has(#itensDaVenda tr) .ip-venda-vazio { display: none; }

.ip-venda-total {
  padding: 1rem 1.25rem;
  border-top: 1px solid var(--bs-border-color, #e5e7eb);
}
.ip-venda-total-linha {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 1rem; margin-bottom: .5rem;
}
.ip-venda-total-linha > span {
  font-size: .78rem; text-transform: uppercase; letter-spacing: .05em;
  color: var(--bs-secondary, #5b6b79); font-weight: 600;
}
.ip-venda-total-linha input {
  border: 0; background: transparent; padding: 0;
  text-align: right; font-variant-numeric: tabular-nums;
  color: var(--bs-body-color, #1b2431);
}
.ip-venda-volume { width: 6rem; font-size: 1rem; }
.ip-venda-total-linha.grande { margin-bottom: 1rem; }
.ip-venda-total-linha.grande > span { font-size: .9rem; color: var(--bs-body-color, #1b2431); }
.ip-venda-valor {
  width: 12rem;
  font-size: 2.4rem; font-weight: 700; line-height: 1.1;
  color: #12202e;
}

/* kbd dentro de botão: a tecla é uma dica, não o rótulo. */
.ip-venda .btn kbd {
  margin-left: .4rem; padding: .1rem .35rem;
  background: rgba(255,255,255,.22); border-radius: .25rem;
  font-family: inherit; font-size: .72rem; font-weight: 600;
}

/* ---- barra de ações ---- */
.ip-venda-barra {
  display: flex; flex-wrap: wrap; gap: .25rem;
  background: var(--bs-card-bg, #fff);
  border: 1px solid var(--bs-border-color, #e5e7eb);
  border-radius: .5rem;
  padding: .4rem;
}
.ip-venda-barra a {
  display: inline-flex; align-items: center; gap: .4rem;
  padding: .5rem .9rem; border-radius: .375rem;
  color: var(--bs-body-color, #1b2431); text-decoration: none;
  font-size: .9rem;
}
.ip-venda-barra a:hover { background: rgba(37, 89, 187, .07); color: #2559bb; }
.ip-venda-barra a.perigo:hover { background: rgba(176, 48, 36, .08); color: #b03024; }

@media (max-width: 1100px) {
  .ip-venda-grade { grid-template-columns: 1fr; }
  .ip-venda-lista { max-height: none; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   Recebimento da venda (Frente/Pdv/Pagamento)
   ═══════════════════════════════════════════════════════════════════════════ */
.ip-pagto-grade {
  display: grid;
  grid-template-columns: 1fr minmax(20rem, 26%);
  gap: 1rem;
  align-items: start;
}

.ip-pagto-titulo {
  font-size: .78rem; text-transform: uppercase; letter-spacing: .05em;
  color: var(--bs-secondary, #5b6b79); font-weight: 600;
  margin-bottom: .6rem;
}

/* ---- formas de pagamento ----
   Eram seis botões azuis com o nome em LARANJA e a tecla em branco, maior que
   o nome. Aqui o nome manda e a tecla é uma dica; a forma escolhida fica
   sólida, que é a única coisa que o operador precisa distinguir de relance. */
.ip-formas { display: flex; flex-wrap: wrap; gap: .5rem; margin-bottom: 1.25rem; }
.ip-formas .ip-forma {
  display: inline-flex; align-items: center; gap: .45rem;
  padding: .65rem 1rem;
  border: 1px solid var(--bs-border-color, #dde3ec);
  border-radius: .5rem;
  background: var(--bs-card-bg, #fff);
  color: var(--bs-body-color, #1b2431);
  text-decoration: none;
  font-size: .95rem; font-weight: 500;
}
.ip-formas .ip-forma i { font-size: 1.15rem; color: #2559bb; }
.ip-formas .ip-forma kbd {
  padding: .1rem .4rem; border-radius: .25rem;
  background: #eef3fa; color: #2559bb;
  font-family: inherit; font-size: .72rem; font-weight: 600;
}
.ip-formas .ip-forma:hover { border-color: #2559bb; background: #f5f9ff; }
/* js_pagamento.js marca a escolhida com .ativo / .selecionado, conforme o
   caminho; as duas são aceitas para não depender de qual ramo rodou. */
.ip-formas .ip-forma.ativo,
.ip-formas .ip-forma.selecionado {
  background: #2559bb; border-color: #2559bb; color: #fff;
}
.ip-formas .ip-forma.ativo i,
.ip-formas .ip-forma.selecionado i { color: #fff; }
.ip-formas .ip-forma.ativo kbd,
.ip-formas .ip-forma.selecionado kbd { background: rgba(255,255,255,.22); color: #fff; }

/* Enquanto nenhuma forma foi escolhida não há o que preencher. js_pagamento.js
   tira a classe .bloquear quando libera o campo. */
.ip-pagto .bloquear .ip-pagto-entrada { opacity: .45; pointer-events: none; }

.ip-pagto-lista { min-height: 6rem; }
.ip-pagto-lista td { font-variant-numeric: tabular-nums; }
.ip-pagto-lista .fw-600 { font-weight: 600; }
.ip-pagto-vazio {
  padding: 1.5rem 1rem; margin: 0;
  text-align: center; color: var(--bs-secondary, #5b6b79);
}
.ip-pagto-lista:has(#lista_pagamento tr) .ip-pagto-vazio { display: none; }

.ip-pagto-atalhos {
  display: flex; flex-wrap: wrap; gap: .25rem;
  margin-top: 1.25rem; padding-top: 1rem;
  border-top: 1px solid var(--bs-border-color, #e5e7eb);
}
.ip-pagto-atalhos a { flex: none; }

/* ---- painel de valores ---- */
.ip-pagto-valores dl { margin: 0; }
.ip-pagto-valores dl > div {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 1rem; padding: .45rem 0;
  border-bottom: 1px solid var(--bs-border-color, #eef1f5);
}
.ip-pagto-valores dt { font-weight: 400; color: var(--bs-secondary, #5b6b79); font-size: .9rem; }
.ip-pagto-valores dd { margin: 0; font-variant-numeric: tabular-nums; font-weight: 600; }
.ip-pagto-valores .liquido dt,
.ip-pagto-valores .liquido dd { color: var(--bs-body-color, #1b2431); font-size: 1.02rem; }
.ip-pagto-valores .recebido dd { color: #1a7a4f; }

/* "Falta receber" decide se a venda fecha; era só mais uma linha igual às
   outras cinco. */
.ip-pagto-restante {
  margin-top: 1rem; padding: .9rem 1rem;
  background: #fdf2f0; border-radius: .5rem;
  display: flex; align-items: baseline; justify-content: space-between; gap: 1rem;
}
.ip-pagto-restante span {
  font-size: .78rem; text-transform: uppercase; letter-spacing: .05em;
  color: #9d2a1d; font-weight: 600;
}
.ip-pagto-restante strong {
  font-size: 1.9rem; line-height: 1; color: #9d2a1d;
  font-variant-numeric: tabular-nums;
}

.ip-pagto .btn kbd {
  margin-left: .4rem; padding: .1rem .35rem;
  background: rgba(255,255,255,.22); border-radius: .25rem;
  font-family: inherit; font-size: .72rem; font-weight: 600;
}
.ip-pagto .btn-light-danger kbd { background: rgba(157,42,29,.12); color: inherit; }

@media (max-width: 1100px) {
  .ip-pagto-grade { grid-template-columns: 1fr; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   Modais da frente de caixa

   O posicionamento e a moldura de .window já vêm do bloco geral lá em cima
   (fixed, centralizado, cantos, sombra). O que faltava era o DENTRO: os 19
   modais do PDV não tinham respiro nenhum — o texto encostava na borda, o
   cabeçalho da tabela vazava pela base do cartão e o "X" de fechar era uma
   letra solta no canto.

   Tudo aqui é escopado em .ip-frente de propósito: os 102 modais do Admin
   usam o mesmo .window e já compensam com padding próprio; mexer no geral
   mudaria as duas coisas de uma vez.
   ═══════════════════════════════════════════════════════════════════════════ */
.ip-frente .window:not(.load) {
  padding: 0;
  display: none;              /* mantido: js_modal.js abre com .show() inline */
  flex-direction: column;
}
/* .show() do jQuery grava display:block; o flex volta por aqui. */
.ip-frente .window:not(.load)[style*="display: block"],
.ip-frente .window:not(.load)[style*="display:block"] { display: flex !important; }

/* Título: era um <h4 class="text-center"> solto colado no topo. */
.ip-frente .window:not(.load) > h4,
.ip-frente .window:not(.load) > h5 {
  margin: 0;
  padding: 1rem 3rem 1rem 1.25rem;
  border-bottom: 1px solid var(--bs-border-color, #e5e7eb);
  font-size: 1.05rem; font-weight: 600;
  text-align: left !important;   /* a view traz .text-center herdado do tema antigo */
  color: var(--bs-heading-color, #12202e);
  flex: none;
}

/* Corpo rolável: modais altos (desconto, crediário) estouravam a tela. */
.ip-frente .window:not(.load) > *:not(h4):not(h5):not(.fechar) {
  padding-left: 1.25rem; padding-right: 1.25rem;
}
.ip-frente .window:not(.load) > *:first-of-type { margin-top: 0; }
.ip-frente .window:not(.load) > *:last-child { padding-bottom: 1.25rem; }

/* Botão de fechar: era a letra "X" em texto puro. */
.ip-frente .window .fechar {
  position: absolute; top: .6rem; right: .75rem;
  display: inline-flex; align-items: center; justify-content: center;
  width: 2rem; height: 2rem;
  border-radius: 999px;
  background: transparent; color: var(--bs-secondary, #5b6b79);
  font-size: 0;               /* esconde o "X" digitado na view */
  cursor: pointer; z-index: 2;
}
.ip-frente .window .fechar::before {
  content: "\eb55";           /* ti-x */
  font-family: "tabler-icons" !important;
  font-size: 1.15rem; line-height: 1;
}
.ip-frente .window .fechar:hover { background: #f1f4f8; color: #12202e; }

/* Tabelas dentro do modal: sem cabeçalho fixo, rolar a lista escondia os
   rótulos das colunas. */
.ip-frente .window .tabela-responsiva { overflow: auto; max-height: 50vh; }
.ip-frente .window table { width: 100%; border-collapse: collapse; }
.ip-frente .window table th {
  position: sticky; top: 0; z-index: 1;
  background: #f7f9fc;
  padding: .55rem .6rem;
  font-size: .78rem; text-transform: uppercase; letter-spacing: .03em;
  color: var(--bs-secondary, #5b6b79); font-weight: 600;
  text-align: left; white-space: nowrap;
}
.ip-frente .window table td {
  padding: .55rem .6rem;
  border-top: 1px solid var(--bs-border-color, #eef1f5);
  font-size: .9rem;
}
.ip-frente .window table tbody tr:hover { background: #f5f9ff; }

/* As linhas de campos do modal legado (.rows > .col-N): o bloco geral já as
   trata, mas dentro de .ip-frente a minha regra do PDV reintroduzia margem
   negativa e os campos encostavam na borda do modal. */
.ip-frente .window .rows { margin-left: 0; margin-right: 0; }
.ip-frente .window .rows > [class*="col-"] { padding-left: 0; padding-right: .75rem; }
.ip-frente .window .rows > [class*="col-"]:last-child { padding-right: 0; }

/* Rodapé de ação dos modais do PDV.

   O par era "Cancelar" em VERMELHO sólido e "Confirmar" em verde sólido, com
   o mesmo peso: duas cores de alerta disputando atenção, e a ação destrutiva
   tão convidativa quanto a construtiva. Cancelar vira discreto; confirmar
   fica sendo o único botão sólido. O bloco também desceu para a direita, que
   é onde o olho procura o botão de concluir. */
.ip-frente .window .base-botoes {
  display: flex; justify-content: flex-end; gap: .5rem;
  width: 100%;
  margin-top: 1rem; padding-top: 1rem;
  border-top: 1px solid var(--bs-border-color, #e5e7eb);
}
.ip-frente .window .base-botoes .btn-vermelho {
  background: transparent;
  color: var(--bs-secondary, #5b6b79);
  border: 1px solid var(--bs-border-color, #dde3ec);
}
.ip-frente .window .base-botoes .btn-vermelho:hover {
  background: #f1f4f8; color: #12202e; filter: none;
}
.ip-frente .window .base-botoes .btn-verde,
.ip-frente .window .base-botoes .btn-azul { background: #2559bb; }

/* Quando o rodapé é a ação de EXCLUIR/CANCELAR a venda, o vermelho é a ação
   principal e deve continuar sólido. */
.ip-frente .window#cancelarvenda .base-botoes .btn-vermelho,
.ip-frente .window#cancelaritem .base-botoes .btn-vermelho,
.ip-frente .window#sairPdv .base-botoes .btn-vermelho,
.ip-frente .window#fecharCaixa .base-botoes .btn-vermelho {
  background: #b03024; color: #fff; border-color: #b03024;
}
.ip-frente .window#cancelarvenda .base-botoes .btn-vermelho:hover,
.ip-frente .window#cancelaritem .base-botoes .btn-vermelho:hover,
.ip-frente .window#sairPdv .base-botoes .btn-vermelho:hover,
.ip-frente .window#fecharCaixa .base-botoes .btn-vermelho:hover { filter: brightness(1.1); color: #fff; }

/* O h4 de alguns modais já trazia border-bottom próprio do tema antigo:
   somado ao meu, virava linha dupla. */
.ip-frente .window > h4.border-bottom { border-bottom-width: 1px; }

/* ---- Modais de confirmação do PDV ----
   O par Sim/Não vinha verde/vermelho, com a ação destrutiva em VERDE e a
   segura em VERMELHO. No balcão, com pressa, vermelho é lido como "pare" —
   o operador ia clicar justamente no botão que preservava a venda achando
   que a estava cancelando. Aqui a cor acompanha a consequência. */
.ip-frente .window.ip-confirmar { width: min(460px, calc(100vw - 2rem)); }
.ip-frente .ip-confirmar-corpo p { margin: 1rem 0 0; color: var(--bs-body-color, #1b2431); }
.ip-frente .ip-confirmar-acoes {
  display: flex; justify-content: flex-end; gap: .5rem;
  margin-top: 1.25rem; padding-top: 1rem;
  border-top: 1px solid var(--bs-border-color, #e5e7eb);
}
.ip-frente .ip-confirmar-acoes .btn {
  display: inline-flex; align-items: center; gap: .4rem;
  padding: .5rem 1rem; border-radius: .375rem;
  font-size: .92rem; font-weight: 500; text-decoration: none; border: 1px solid transparent;
}
.ip-frente .btn-neutro {
  background: transparent; color: var(--bs-secondary, #5b6b79);
  border-color: var(--bs-border-color, #dde3ec);
}
.ip-frente .btn-neutro:hover { background: #f1f4f8; color: #12202e; }
.ip-frente .btn-principal { background: #2559bb; color: #fff; }
.ip-frente .btn-principal:hover { background: #1f4fa6; color: #fff; }
.ip-frente .btn-perigo { background: #b03024; color: #fff; }
.ip-frente .btn-perigo:hover { background: #96271d; color: #fff; }

/* Modal de venda concluída: é o único que dá uma boa notícia. */
.ip-frente .window.ip-sucesso > h4 { color: #176944; }
.ip-frente .window.ip-sucesso > h4 i { margin-right: .35rem; }

/* ═══════════════════════════════════════════════════════════════════════════
   Fechamento de caixa (Frente/Caixa/Fechamento)

   Os campos do resumo eram inputs somente-leitura com .text-branco — texto
   branco sobre fundo claro, ou seja, ilegíveis. E os sete valores tinham o
   mesmo peso, incluindo "Total na Gaveta", que é o único que o operador
   compara com o dinheiro que acabou de contar.
   ═══════════════════════════════════════════════════════════════════════════ */
.ip-fecha-resumo { margin: 0; }
.ip-fecha-resumo > div {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 1rem; padding: .5rem 0;
  border-bottom: 1px solid var(--bs-border-color, #eef1f5);
}
.ip-fecha-resumo dt { font-weight: 400; color: var(--bs-secondary, #5b6b79); font-size: .92rem; }
.ip-fecha-resumo dt span {
  display: block; font-size: .7rem; text-transform: uppercase; letter-spacing: .04em;
}
.ip-fecha-resumo .saida   dt span { color: #9d2a1d; }
.ip-fecha-resumo .entrada dt span { color: #176944; }
.ip-fecha-resumo dd { margin: 0; }
.ip-fecha-resumo dd input,
.ip-fecha-gaveta input {
  border: 0; background: transparent; padding: 0;
  text-align: right; font-variant-numeric: tabular-nums;
  font-weight: 600; color: var(--bs-body-color, #1b2431);
  width: 8rem;
}

.ip-fecha-gaveta {
  display: flex; align-items: baseline; justify-content: space-between; gap: 1rem;
  margin-top: 1rem; padding: .9rem 1rem;
  background: #eef4fb; border-radius: .5rem;
}
.ip-fecha-gaveta span {
  font-size: .78rem; text-transform: uppercase; letter-spacing: .05em;
  color: #1f4fa6; font-weight: 600;
}
.ip-fecha-gaveta input {
  width: 10rem; font-size: 1.8rem; line-height: 1; color: #1f4fa6; font-weight: 700;
}

.ip-frente .table tfoot th {
  border-top: 2px solid var(--bs-border-color, #e5e7eb);
  font-variant-numeric: tabular-nums;
}
.ip-frente .fw-600 { font-weight: 600; }

/* ═══════════════════════════════════════════════════════════════════════════
   Conferência de caixa (Frente/Caixa/Contagem)
   ═══════════════════════════════════════════════════════════════════════════ */
.ip-contagem {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
  gap: .75rem;
}
.ip-nota {
  display: flex; flex-direction: column; gap: .3rem;
  padding: .65rem;
  border: 1px solid var(--bs-border-color, #dde3ec);
  border-radius: .5rem;
  cursor: text;
}
.ip-nota.preenchida { border-color: #2559bb; background: #f5f9ff; }
.ip-nota .valor {
  font-size: .82rem; font-weight: 600;
  color: var(--bs-body-color, #1b2431);
  font-variant-numeric: tabular-nums;
}
.ip-nota.moeda .valor { color: #8a6d1f; }
.ip-nota input { text-align: center; font-size: 1.1rem; font-weight: 600; }
/* O subtotal por denominação evita o erro mais comum da contagem: contar as
   notas certo e errar a multiplicação. */
.ip-nota .subtotal {
  text-align: center; font-size: .78rem;
  color: var(--bs-secondary, #5b6b79);
  font-variant-numeric: tabular-nums;
}
.ip-nota.preenchida .subtotal { color: #1f4fa6; font-weight: 600; }

.ip-contado {
  display: flex; align-items: baseline; justify-content: space-between; gap: 1rem;
  margin-top: .5rem; padding: .9rem 1rem;
  border: 1px solid var(--bs-border-color, #dde3ec); border-radius: .5rem;
}
.ip-contado span {
  font-size: .78rem; text-transform: uppercase; letter-spacing: .05em;
  color: var(--bs-secondary, #5b6b79); font-weight: 600;
}
.ip-contado strong { font-size: 1.5rem; font-variant-numeric: tabular-nums; }

/* A diferença é a razão de existir desta tela: cor por consequência. */
.ip-diferenca {
  display: flex; align-items: baseline; justify-content: space-between; gap: 1rem;
  margin-top: .5rem; padding: .9rem 1rem; border-radius: .5rem;
  background: #f1f4f8;
}
.ip-diferenca span {
  font-size: .78rem; text-transform: uppercase; letter-spacing: .05em; font-weight: 600;
}
.ip-diferenca strong { font-size: 1.8rem; line-height: 1; font-variant-numeric: tabular-nums; }
.ip-diferenca.certo  { background: #e3f7ec; }
.ip-diferenca.certo  span, .ip-diferenca.certo  strong { color: #176944; }
.ip-diferenca.sobra  { background: #fff4d6; }
.ip-diferenca.sobra  span, .ip-diferenca.sobra  strong { color: #7a5a00; }
.ip-diferenca.falta  { background: #fdf2f0; }
.ip-diferenca.falta  span, .ip-diferenca.falta  strong { color: #9d2a1d; }

/* Total de sangrias/suplementos do caixa: o sinal deixa claro se o dinheiro
   entrou ou saiu, que é o que confunde quem está aprendendo. */
.ip-mov-total { font-weight: 600; font-variant-numeric: tabular-nums; }
.ip-mov-total.saida   { color: #9d2a1d; }
.ip-mov-total.entrada { color: #176944; }

/* Números do detalhe da venda. Eram cinco blocos verdes idênticos, incluindo
   "Desconto" — que subtrai. Só o valor a receber tem destaque. */
.ip-venda-numeros { display: flex; flex-wrap: wrap; gap: 2.5rem; margin: 0; }
.ip-venda-numeros dt {
  font-size: .76rem; text-transform: uppercase; letter-spacing: .04em;
  color: var(--bs-secondary, #5b6b79); font-weight: 600;
}
.ip-venda-numeros dd {
  margin: .2rem 0 0; font-size: 1.25rem; font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.ip-venda-numeros .desconto dd { color: #9d2a1d; }
.ip-venda-numeros .liquido dd { font-size: 1.9rem; color: #1f4fa6; }

/* ---- Vendas guardadas (Resgate) ----
   Eram cartões .col-4 num grid que não funcionava, com três botões coloridos
   (verde/vermelho/laranja) de peso igual. Receber é a ação; o resto é apoio. */
.ip-resgates {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
  gap: .75rem;
  padding-top: .5rem;
}
.ip-resgate {
  border: 1px solid var(--bs-border-color, #dde3ec);
  border-radius: .5rem;
  padding: .85rem;
  background: var(--bs-card-bg, #fff);
}
.ip-resgate header { display: flex; flex-direction: column; gap: .15rem; margin-bottom: .75rem; }
.ip-resgate .num {
  font-size: .74rem; text-transform: uppercase; letter-spacing: .04em;
  color: var(--bs-secondary, #5b6b79); font-weight: 600;
}
.ip-resgate .titulo { font-size: 1rem; font-weight: 600; }
.ip-resgate .titulo.valor { font-variant-numeric: tabular-nums; color: #1f4fa6; }
.ip-resgate footer { display: flex; gap: .35rem; }
.ip-resgate-vazio {
  grid-column: 1 / -1;
  padding: 2.5rem 1rem; margin: 0;
  text-align: center; color: var(--bs-secondary, #5b6b79);
}

/* Cabeçalho da busca de resgate: data e total da venda encontrada. */
.ip-resgate-cab { font-size: .9rem; font-variant-numeric: tabular-nums; }
.ip-resgate-cab .rotulo {
  font-size: .72rem; text-transform: uppercase; letter-spacing: .04em;
  color: var(--bs-secondary, #5b6b79); font-weight: 600; margin-left: .75rem;
}
.ip-resgate-cab .rotulo:first-child { margin-left: 0; }
.ip-resgate-vazio-busca {
  padding: 2.5rem 1rem; margin: 0;
  text-align: center; color: var(--bs-secondary, #5b6b79);
}
.table-responsive:has(#listaVendasParaResgate tr) .ip-resgate-vazio-busca { display: none; }

/* ---- Conteúdo do site: blog e FAQ ---- */
.ip-faq-cat {
  font-size: .76rem; text-transform: uppercase; letter-spacing: .05em;
  color: var(--bs-secondary, #5b6b79); font-weight: 600;
  margin: 1.5rem 0 .5rem;
}
.ip-faq-cat:first-child { margin-top: 0; }

.ip-editor { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .9rem; line-height: 1.6; }

/* Conferência de SEO ao lado do editor: lembrete, não bloqueio. */
.ip-seo__titulo {
  font-size: .72rem; text-transform: uppercase; letter-spacing: .05em;
  color: var(--bs-secondary, #5b6b79); font-weight: 600; margin-bottom: .5rem;
}
.ip-seo ul { list-style: none; margin: 0; padding: 0; display: grid; gap: .35rem; }
.ip-seo li { display: flex; align-items: flex-start; gap: .4rem; font-size: .86rem; line-height: 1.4; }
.ip-seo li.ok    { color: #176944; }
.ip-seo li.falta { color: var(--bs-secondary, #5b6b79); }
.ip-seo li i { flex: none; margin-top: .1rem; }
