/* ===========================================================================
   CAMADA 4 - COMPONENTES
   Todo componente reaproveitavel do produto. Nenhuma pagina redeclara nada
   daqui.

   MECANISMO CONTRA DUPLICACAO: cada componente expoe custom properties
   locais (--btn-bg, --card-padding, --alert-fg). Os modificadores SO
   reatribuem essas variaveis, nunca repetem declaracao de layout. Por isso
   `.ipr-btn` tem ~15 declaracoes escritas uma vez e `.ipr-btn--danger` tem
   duas linhas.

   Toda variavel tem VALOR PADRAO no bloco base. Sem isso, um `.ipr-btn` sem
   modificador (ou um alerta cuja categoria nao bateu no mapa) resolveria para
   "invalido no tempo de computacao": o botao ficaria transparente e o texto
   herdaria a cor do card. Falha silenciosa e o pior modo de falha.
   =========================================================================== */

/* --------------------------------------------------------------- BOTAO --- */
.ipr-btn {
  /* Padroes: um botao sem modificador continua legivel. */
  --btn-bg: var(--color-surface-2);
  --btn-fg: var(--color-text-primary);
  --btn-border: transparent;
  --btn-height: var(--control-h);
  --btn-padding-inline: var(--space-4);
  --btn-radius: var(--radius-md);
  --btn-shadow: none;

  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  height: var(--btn-height);
  padding-inline: var(--btn-padding-inline);
  border: 1px solid var(--btn-border);
  border-radius: var(--btn-radius);
  background: var(--btn-bg);
  color: var(--btn-fg);
  box-shadow: var(--btn-shadow);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  line-height: 1;
  text-decoration: none;
  white-space: nowrap;
  /* BOTAO NAO ENCOLHE: na barra do topo do celular, "Salvar rascunho" virava
     "ar rasc". Quem cede espaco e a fileira, que quebra ou rola. */
  flex-shrink: 0;
  cursor: pointer;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
  transition: background-color var(--dur-fast), border-color var(--dur-fast),
              color var(--dur-fast), box-shadow var(--dur-fast);
}
.ipr-btn .ipr-icon { width: 1rem; height: 1rem; }

/* O PRINCIPAL E SOLIDO: o azul da marca chapado, texto branco e uma sombra
   de um pixel, como o botao do shadcn/ui. E o unico botao da tela que tem
   cor, e isso basta para chamar o clique: o degrade, o relevo e o reflexo da
   primeira versao foram o que o cliente chamou de "sutil demais".

   O hover ESCURECE: clarear o azul reduziria o contraste do texto branco
   justamente quando a pessoa vai clicar. */
.ipr-btn--primary {
  --btn-bg: var(--color-accent-600);
  --btn-fg: var(--color-text-on-accent);
  --btn-shadow: var(--shadow-xs);
}
.ipr-btn--primary:hover { --btn-bg: var(--color-accent-700); }

/* O SECUNDARIO E CONTORNO (o `variant="outline"`): o fundo do cartao, borda
   de 1px que se ve e a mesma sombra de um pixel. */
.ipr-btn--secondary {
  --btn-bg: var(--color-surface-1);
  --btn-border: var(--color-border);
  --btn-shadow: var(--shadow-xs);
}
.ipr-btn--secondary:hover { --btn-bg: var(--color-surface-2); }

.ipr-btn--ghost { --btn-bg: transparent; --btn-fg: var(--color-text-secondary); }
.ipr-btn--ghost:hover { --btn-bg: var(--color-surface-3); --btn-fg: var(--color-text-primary); }

.ipr-btn--danger {
  --btn-bg: var(--color-danger-solid);
  --btn-fg: var(--color-danger-solid-fg);
  --btn-shadow: var(--shadow-xs);
}
.ipr-btn--danger:hover { filter: brightness(.94); }
/* Perigo DISCRETO: vermelho no texto, fundo so no hover.
   Acao destrutiva nao pode ser o botao mais chamativo da tela. Solido, o
   "Excluir" puxava o olho antes do "Editar", que e o que se vai fazer em
   noventa e nove de cada cem visitas. E o mesmo desenho do
   `ipr-acao--perigo`, que e a versao em icone da mesma acao. */
.ipr-btn--danger-ghost { --btn-bg: transparent; --btn-fg: var(--color-danger); }
.ipr-btn--danger-ghost:hover { --btn-bg: var(--color-danger-bg); --btn-fg: var(--color-danger); }

.ipr-btn--sm {
  --btn-height: var(--control-h-sm);
  --btn-padding-inline: var(--space-3);
}
.ipr-btn--lg {
  --btn-height: var(--control-h-lg);
  --btn-padding-inline: var(--space-6);
}
.ipr-btn--block { width: 100%; }

.ipr-btn:disabled,
.ipr-btn[aria-disabled="true"] { opacity: .5; cursor: not-allowed; pointer-events: none; }

/* ENVIANDO: o indicador entra ANTES do rotulo, e o rotulo continua la.
   Antes o rotulo ficava invisivel e o botao virava uma caixa azul vazia,
   inclusive nos botoes escritos a mao, que nao tem indicador: quem clicou nao
   via nada. Agora o texto diz o que esta acontecendo ("Entrando...", quando o
   formulario declara) e o indicador diz que nao travou. */
.ipr-btn.is-loading { pointer-events: none; }
.ipr-btn.is-loading .ipr-btn__spinner { display: block; order: -1; }
/* O icone da acao sai enquanto ela acontece: seta e convite, e o convite ja
   foi aceito. */
.ipr-btn.is-loading > .ipr-icon { display: none; }

/* ------------------------------------------ ICONE NA LINHA DO TEXTO --- */
/*
  Icone que precisa ficar alinhado com a PRIMEIRA LINHA de um texto ao lado,
  e nao com o topo da caixa.

  O PROBLEMA que isto resolve: num flex com `align-items: flex-start`, o icone
  encosta no topo e o texto nao. A caixa da linha de texto e mais alta que o
  glifo, entao o centro optico do texto fica abaixo do centro do icone. O olho
  ve isso na hora e le como "torto".

  A CORRECAO: a caixa do icone passa a valer exatamente UMA LINHA de texto, e
  o glifo e centrado dentro dela. Ai o topo das duas caixas coincide E os
  centros tambem. Vale para uma linha e para varias.
*/
.ipr-icone-linha {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  block-size: calc(1em * var(--line-normal));
}

/* ------------------------------------------------------------- SPINNER --- */
/* Um arco que gira, e nao um anel inteiro com um pedaco faltando: o arco tem
   uma ponta, e a ponta e o que o olho segue. Usa currentColor, entao serve em
   qualquer variante de botao sem versao propria. */
.ipr-spinner {
  width: var(--spinner-size, 1rem);
  aspect-ratio: 1;
  border-radius: var(--radius-pill);
  border: 2px solid transparent;
  border-top-color: currentColor;
  border-right-color: currentColor;
  animation: ipr-spin .7s cubic-bezier(.5, .15, .5, .85) infinite;
  display: none;
}

/* ---------------------------------------------------------------- CAMPO --- */
.ipr-field { display: flex; flex-direction: column; gap: var(--space-2); min-inline-size: 0; }

/* O rotulo e ESCURO e medio, como o `Label` do shadcn/ui. Cinza, ele sumia
   ao lado do campo, e o formulario inteiro parecia apagado. */
.ipr-field__label {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-primary);
  line-height: var(--line-snug);
}
.ipr-field__required { color: var(--color-accent-400); margin-inline-start: 2px; }

.ipr-field__control { position: relative; display: flex; align-items: center; }

.ipr-field__icon {
  position: absolute;
  inset-inline-start: var(--space-3);
  display: grid;
  color: var(--color-text-muted);
  pointer-events: none;
  transition: color var(--dur-base);
}
.ipr-field__icon .ipr-icon { width: 1rem; height: 1rem; }

.ipr-field__input {
  width: 100%;
  height: var(--field-height, var(--control-h));
  padding-inline: var(--space-3);
  background: var(--color-input-bg);
  color: var(--color-text-primary);
  border: 1px solid var(--color-border-control);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-xs);
  font-size: var(--font-size-md);
  transition: border-color var(--dur-base), box-shadow var(--dur-base), background var(--dur-base);
}
.ipr-field__input::placeholder { color: var(--color-text-muted); opacity: 1; }
/* O campo ESCURECE a borda sob o mouse: diz "aqui se escreve" antes do
   clique, sem mudar de cor (cor e reservada ao foco). */
.ipr-field__input:hover:not(:focus-visible):not(:disabled) { border-color: var(--color-text-muted); }
.ipr-field--with-icon   .ipr-field__input { padding-inline-start: 2.5rem; }
.ipr-field--with-action .ipr-field__input { padding-inline-end: 2.75rem; }

.ipr-field__input:focus-visible {
  border-color: var(--color-focus);
  box-shadow: var(--shadow-focus);
  outline: none;
}
/* O icone acende junto com o foco: detalhe barato que faz parecer produto. */
.ipr-field__control:focus-within .ipr-field__icon { color: var(--color-accent-400); }

/* Desligado e so-leitura sao estados DIFERENTES e se parecem diferente:
   desligado nao se usa (apagado, cursor de proibido); so-leitura se le e se
   copia, entao continua nitido, so sem a borda de quem convida a escrever. */
.ipr-field__input:disabled {
  background: var(--color-surface-2);
  color: var(--color-text-muted);
  box-shadow: none;
  cursor: not-allowed;
}
.ipr-field__input[readonly] {
  background: var(--color-surface-2);
  border-color: var(--color-border);
  box-shadow: none;
}

.ipr-field__action {
  position: absolute;
  inset-inline-end: var(--space-1);
  width: 2rem;
  height: 2rem;
  display: grid;
  place-items: center;
  border: 0;
  background: transparent;
  color: var(--color-text-muted);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background var(--dur-fast), color var(--dur-fast);
}
.ipr-field__action:hover { color: var(--color-text-primary); background: var(--color-surface-2); }

.ipr-field__hint { font-size: var(--font-size-xs); color: var(--color-text-muted); line-height: var(--line-snug); }

/* --- Faixa: dois campos que sao um criterio so -------------------------
   `1fr auto 1fr` e nao flex com `flex: 1`: com flex, um campo que recebesse
   "120" e outro vazio teriam larguras diferentes, porque o conteudo entra na
   conta. Em grid as duas trilhas sao iguais por definicao, e a faixa fica
   simetrica em volta do separador. */
.ipr-faixa {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: var(--space-2);
}
.ipr-faixa__ate {
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
}
/* Numero centrado: os dois campos sao curtos e ficam lado a lado, entao
   alinhado a esquerda um "18" e um "120" nao se encaram. */
.ipr-faixa .ipr-field__input {
  text-align: center;
  padding-inline: var(--space-2);
  font-variant-numeric: tabular-nums;
}

/* O erro sempre vem acompanhado do icone: cor nunca e o unico portador da
   informacao (daltonismo). */
.ipr-field__error {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-medium);
  color: var(--color-danger);
}
.ipr-field__error .ipr-icon { width: 1rem; height: 1rem; }
.ipr-field--invalid .ipr-field__input {
  border-color: var(--color-danger);
  box-shadow: var(--shadow-focus-danger);
}
.ipr-field--invalid .ipr-field__input:focus-visible { animation: ipr-shake 320ms var(--ease-in-out); }

/* ------------------------------------------------------------- CHECKBOX --- */
.ipr-checkbox {
  /* Ancora do input invisivel: sem ela, o input absoluto se posiciona pelo
     primeiro ancestral posicionado, que pode estar fora de um quadro que
     rola, e escapa do recorte dele. */
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  cursor: pointer;
  font-size: var(--font-size-md);
  color: var(--color-text-secondary);
}
/* O input real fica invisivel mas focavel e legivel por leitor de tela.
   O tamanho e uma variavel para quem usa poder aumentar sem reescrever o
   componente: numa tabela clicavel, 18px e um alvo pequeno demais. */
.ipr-checkbox { --check-size: 1rem; }
.ipr-checkbox__input {
  position: absolute;
  opacity: 0;
  width: var(--check-size);
  height: var(--check-size);
  margin: 0;
}
.ipr-checkbox__box {
  width: var(--check-size);
  height: var(--check-size);
  flex-shrink: 0;
  border: 1px solid var(--color-border-control);
  border-radius: var(--radius-xs);
  background: var(--color-input-bg);
  box-shadow: var(--shadow-xs);
  display: grid;
  place-items: center;
  transition: background var(--dur-fast), border-color var(--dur-fast), box-shadow var(--dur-fast);
}
.ipr-checkbox:hover .ipr-checkbox__box { border-color: var(--color-text-muted); }
.ipr-checkbox__box::after {
  content: "";
  width: .275rem;
  height: .5rem;
  border: 2px solid var(--color-text-on-accent);
  border-top: 0;
  border-left: 0;
  transform: rotate(45deg) translateY(-1px) scale(.6);
  opacity: 0;
  transition: opacity var(--dur-fast), transform var(--dur-base) var(--ease-expo);
}
.ipr-checkbox__input:checked ~ .ipr-checkbox__box {
  background: var(--color-accent-600);
  border-color: var(--color-accent-600);
}
/* O visto ESTALA: cresce de 60% ao tamanho cheio. E o retorno que confirma o
   clique numa caixa de 18px. */
.ipr-checkbox__input:checked ~ .ipr-checkbox__box::after {
  opacity: 1;
  transform: rotate(45deg) translateY(-1px) scale(1);
}
.ipr-checkbox__input:focus-visible ~ .ipr-checkbox__box {
  outline: var(--ring-width) solid var(--color-focus);
  outline-offset: var(--ring-offset);
}

/* ----------------------------------------------------------------- CARD --- */
/* O CARTAO DO SHADCN/UI: fundo branco, borda de 1px, raio de 12px, sombra de
   um pixel e 24px de respiro. Os modificadores de vidro, faixa acesa e sombra
   alta sairam junto com o cartao de vidro do login, que era o unico a usa-los. */
.ipr-card {
  --card-padding: var(--space-6);
  --card-bg: var(--color-surface-1);
  --card-border: var(--color-border);
  --card-shadow: var(--shadow-sm);
  --card-radius: var(--radius-xl);

  position: relative;
  padding: var(--card-padding);
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: var(--card-radius);
  box-shadow: var(--card-shadow);
}

/* --------------------------------------------------------------- ALERTA --- */
/* --- Pop-up ------------------------------------------------------------
   <dialog> nativo. O `dialog` fechado ja e invisivel pelo proprio navegador,
   entao nao ha estado de exibicao para o CSS controlar: o que fica aqui e
   so aparencia. */
.ipr-modal {
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  max-inline-size: min(34rem, calc(100vw - var(--space-8)));
  inline-size: 100%;
}
.ipr-modal::backdrop { background: var(--color-overlay); }
.ipr-modal__caixa {
  display: grid;
  gap: 0;
  border-radius: var(--radius-xl);
  border: 1px solid var(--color-border);
  background: var(--color-surface-1);
  box-shadow: var(--shadow-xl);
  overflow: hidden;
}
.ipr-modal__topo {
  display: grid;
  gap: var(--space-1);
  padding: var(--space-6) var(--space-6) var(--space-4);
}
.ipr-modal__titulo {
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-semibold);
  letter-spacing: var(--tracking-snug);
}
.ipr-modal__sub { font-size: var(--font-size-sm); color: var(--color-text-muted); }
.ipr-modal__corpo { padding: 0 var(--space-6) var(--space-6); display: grid; gap: var(--space-4); }
/* O topo sem corpo logo abaixo (a conversa, a escolha) precisa da regua: sem
   ela o titulo encosta na lista que rola. */
.ipr-modal__topo:not(:has(+ .ipr-modal__corpo)) {
  padding-block-end: var(--space-5);
  border-bottom: 1px solid var(--color-border-subtle);
}
.ipr-modal__pe {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-2);
  padding: 0 var(--space-6) var(--space-6);
}

/* Entrada curta: o pop-up aparece, e nao desliza de longe. Movimento grande
   numa caixa que interrompe a tarefa cansa em vez de agradar. */
.ipr-modal[open] { animation: ipr-modal-in var(--dur-base) var(--ease-expo) both; }
.ipr-modal[open]::backdrop { animation: ipr-fade var(--dur-base) var(--ease-out) both; }
@keyframes ipr-modal-in {
  from { opacity: 0; transform: translate3d(0, 10px, 0) scale(.97); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  @keyframes ipr-modal-in { from { opacity: 0; } to { opacity: 1; } }
}

/* Pergunta: caixa curta, sem grade de campos, so um texto e dois botoes. */
.ipr-modal--pergunta { max-inline-size: min(28rem, calc(100vw - var(--space-8))); }
.ipr-modal__texto {
  font-size: var(--font-size-md);
  color: var(--color-text-secondary);
}

/* ---------------------------------------------------------------------------
   AVISO FLUTUANTE (toast)

   Substituiu a faixa colorida no topo do conteudo. A faixa empurrava a tela
   a cada acao e ficava ate a proxima navegacao; confirmacao e coisa de
   segundo, entao o aviso agora vive FORA do fluxo, some sozinho e nao mexe
   no layout.

   A saida e do CSS, nao do JavaScript: `animation ... forwards` termina o
   trabalho mesmo que o script nao carregue. O JS so acrescenta o botao de
   fechar. Aviso que depende de JS para sumir e uma caixa presa na tela.
   --------------------------------------------------------------------------- */
.ipr-toasts {
  position: fixed;
  inset-block-end: var(--space-5);
  inset-inline-end: var(--space-5);
  z-index: var(--z-toast);
  display: grid;
  gap: var(--space-3);
  inline-size: min(24rem, calc(100vw - var(--space-8)));
  /* O container nao intercepta clique: so os avisos dentro dele. Sem isto,
     uma faixa invisivel de 24rem cobriria o canto da tela. */
  pointer-events: none;
}
.ipr-toast {
  --toast-accent: var(--color-accent-500);
  --toast-tempo: 4.5s;

  position: relative;
  overflow: hidden;
  pointer-events: auto;
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-4);
  border-radius: var(--radius-lg);
  border: 1px solid var(--color-border);
  background: var(--color-surface-opaco);
  box-shadow: var(--shadow-lg);
  /*
    O atraso sai de --reveal-offset, o mesmo que segura o cartao de login: na
    tela de credencial a cortina de abertura cobre ate o aviso (--z-intro e
    maior que --z-toast), entao sem isto ele entrava e comecava a contar o
    tempo dele ATRAS de uma tela opaca. Onde nao ha cortina a variavel nao
    existe e o fallback e 0ms.
  */
  animation: ipr-toast-in var(--dur-slow) var(--ease-expo) var(--reveal-offset, 0ms) both;
}
/* So o icone na cor do nivel, na altura da primeira linha: o tom se le de
   longe, e o texto continua sobre superficie neutra, entao o contraste nao
   depende do nivel do aviso. */
.ipr-toast__icon {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  block-size: calc(var(--font-size-md) * var(--line-snug));
  color: var(--toast-accent);
}
.ipr-toast__icon .ipr-icon { width: 1rem; height: 1rem; }
.ipr-toast__corpo { flex: 1; min-width: 0; }
.ipr-toast__titulo {
  font-size: var(--font-size-md);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-primary);
  line-height: var(--line-snug);
}
.ipr-toast__texto {
  margin-block-start: 2px;
  font-size: var(--font-size-sm);
  color: var(--color-text-secondary);
  overflow-wrap: anywhere;
}
.ipr-toast__close {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  inline-size: 1.75rem;
  block-size: 1.75rem;
  margin: calc(var(--space-1) * -1) calc(var(--space-1) * -1) 0 0;
  padding: 0;
  border: 0;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--color-text-muted);
  cursor: pointer;
  transition: background var(--dur-fast), color var(--dur-fast);
}
.ipr-toast__close:hover { background: var(--color-surface-2); color: var(--color-text-primary); }
.ipr-toast__close .ipr-icon { width: 1rem; height: 1rem; }

.ipr-toast--success { --toast-accent: var(--color-success); }
.ipr-toast--danger  { --toast-accent: var(--color-danger); }
.ipr-toast--warning { --toast-accent: var(--color-warning); }
.ipr-toast--info    { --toast-accent: var(--color-info); }

/* Some sozinho depois de ler. O `visibility` no fim do keyframe tira o
   elemento do caminho do clique sem depender do JS para remove-lo. */
.ipr-toast--auto {
  animation: ipr-toast-in var(--dur-slow) var(--ease-expo) var(--reveal-offset, 0ms) both,
             ipr-toast-out var(--dur-slow) var(--ease-out)
                           calc(var(--reveal-offset, 0ms) + var(--toast-tempo)) forwards;
}
/* O TEMPO QUE FALTA, desenhado. Um fio na base do aviso que encolhe ate a
   saida: quem esta lendo ve quanto tempo ainda tem, em vez de ser
   surpreendido pela caixa sumindo no meio da frase. */
.ipr-toast--auto::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  block-size: 2px;
  background: var(--toast-accent);
  opacity: .55;
  transform-origin: left;
  animation: ipr-toast-tempo var(--toast-tempo) linear var(--reveal-offset, 0ms) both;
}
@keyframes ipr-toast-tempo { from { transform: scaleX(1); } to { transform: scaleX(0); } }
/* Passar o mouse (ou focar o botao de fechar) congela a contagem: ninguem
   perde o texto no meio da leitura. O fio congela junto, senao ele mentiria
   sobre o tempo que falta. */
.ipr-toast:hover,
.ipr-toast:focus-within,
.ipr-toast:hover::after,
.ipr-toast:focus-within::after { animation-play-state: paused; }
.ipr-toast.is-saindo {
  animation: ipr-toast-out var(--dur-base) var(--ease-out) forwards;
}

@keyframes ipr-toast-in {
  from { opacity: 0; transform: translate3d(0, 12px, 0) scale(.97); }
  to   { opacity: 1; transform: none; }
}
@keyframes ipr-toast-out {
  to { opacity: 0; transform: translate3d(0, 8px, 0) scale(.97); visibility: hidden; }
}

@media (width < 40rem) {
  .ipr-toasts {
    inset-inline: var(--space-3);
    inset-block-end: var(--space-3);
    inline-size: auto;
  }
}
@media (prefers-reduced-motion: reduce) {
  /* Sem movimento, mas COM a saida: o atraso e a razao de ser do aviso, e
     zerar a animacao deixaria a caixa parada na tela para sempre. */
  @keyframes ipr-toast-in  { from { opacity: 0; } to { opacity: 1; } }
  @keyframes ipr-toast-out { to { opacity: 0; visibility: hidden; } }
}


/* ---------------------------------------------------------------- MARCA --- */
/*
  O LOCKUP OFICIAL, nao uma reconstrucao dele.

  A palavra "iPresto Pro" e imagem, recortada do proprio arquivo de
  identidade. Nenhuma fonte tem o desenho exato do logo, entao escrever a
  palavra em texto seria uma imitacao dela.

  Tudo deriva de --brand-size, entao existe UM numero por tamanho e as
  proporcoes do logo se mantem em qualquer escala.
*/
.ipr-brand {
  display: inline-flex;
  align-items: center;
  /* 0.15 e o vao do arquivo original (91px de folga para 625px de marca).
     Copiar a medida do logo e o que impede o conjunto de parecer duas
     imagens encostadas. */
  gap: calc(var(--brand-size, 2.75rem) * .15);
}
.ipr-brand__mark { width: var(--brand-size, 2.75rem); height: auto; }
.ipr-brand__word {
  block-size: var(--brand-size, 2.75rem);   /* mesma altura da marca, como no logo */
  inline-size: auto;
  /* Guarda contra deformacao: `img { max-width: 100% }` (base.css) encolheria
     a LARGURA num container estreito enquanto a altura acima continua fixa.
     `contain` prefere mostrar menor a mostrar deformado. */
  object-fit: contain;
  /* No lockup oficial a palavra fica 4,3% da altura da marca ACIMA do centro
     dela. Nao e imprecisao de recorte: e o alinhamento optico do proprio
     logo, medido no arquivo. Sem isto o conjunto fica "certo" e parece
     errado. */
  translate: 0 calc(var(--brand-size, 2.75rem) * -.043);
}
.ipr-brand--sm { --brand-size: 2.25rem; }
.ipr-brand--lg { --brand-size: 3.5rem; }
/* SO O ICONE, NUM QUADRADO: o "icone de app" que abre o login, como na
   referencia do cliente. O quadro e da superficie do tema, com borda de 1px e
   sombra baixa; o icone respira dentro dele, e nao encosta na borda. */
.ipr-brand--icone {
  /* O quadro e o icone crescem JUNTOS: quem precisa do quadro maior muda so
     --icone-quadro, e o icone de dentro acompanha na mesma razao (4/7). */
  --icone-quadro: 3.5rem;
  --brand-size: calc(var(--icone-quadro) * 4 / 7);
  display: grid;
  place-items: center;
  inline-size: var(--icone-quadro);
  block-size: var(--icone-quadro);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  background: var(--color-surface-1);
  box-shadow: var(--shadow-sm);
}
/* ------------------------------------------------------------ AUXILIARES --- */
/*
  O ROTULO, UMA VEZ SO: o texto pequeno que diz "do que e" o numero ou o bloco
  logo abaixo. Estava escrito oito vezes, uma por componente, com pequenas
  diferencas que ninguem escolheu; agora todos leem esta regra.

  CAIXA NORMAL, e nao alta. A primeira versao escrevia estes rotulos em 11px,
  maiusculos e espacados, e eram dez na mesma tela: foi o que mais deu a ela
  a cara de apagada. No desenho do shadcn/ui o rotulo e frase, em peso medio.
  O rotulo do cartao de numero e o titulo de grupo de campos sao mais fortes
  e tem regra propria, na secao de cada um.
*/
.ipr-eyebrow,
.ipr-mini__rotulo,
.ipr-oferta__rotulo,
.ipr-gaveta__rotulo,
.ipr-criterios dt,
.ipr-folha__base-rotulo,
.ipr-bandas__cabeca,
.ipr-folha__legenda {
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-medium);
  line-height: var(--line-snug);
  color: var(--color-text-muted);
}
/* Sobretitulo vazio some por completo. Sem isto, a tela que nao tem
   sobretitulo (o login) ainda pagaria o `gap` do .ipr-stack em volta de um
   paragrafo em branco, e o cabecalho do cartao ficaria com um vao sem
   explicacao. */
.ipr-eyebrow:empty { display: none; }

.ipr-link {
  color: var(--color-accent-300);
  font-size: var(--font-size-md);
  font-weight: var(--font-weight-medium);
  text-decoration: none;
  border-radius: var(--radius-xs);
}
.ipr-link:hover { text-decoration: underline; }

.ipr-icon {
  width: 1.25em;
  height: 1.25em;
  flex-shrink: 0;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* --- Abas --------------------------------------------------------------
   Sao LINKS para paginas diferentes, nao paineis trocados no lugar. O
   sublinhado do item atual e um traco proprio, com as pontas arredondadas, e
   nao uma borda: borda somaria altura e empurraria o conteudo dois pixels ao
   trocar de aba. */
.ipr-abas {
  display: flex;
  gap: var(--space-1);
  border-bottom: 1px solid var(--color-border);
  overflow-x: auto;
  scrollbar-width: none;
}
.ipr-abas__item {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-3) var(--space-4);
  white-space: nowrap;
  color: var(--color-text-muted);
  font-size: var(--font-size-md);
  font-weight: var(--font-weight-medium);
  text-decoration: none;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  transition: color var(--dur-fast);
}
.ipr-abas__item .ipr-icon { width: 1rem; height: 1rem; }
.ipr-abas__item::after {
  content: "";
  position: absolute;
  inset-inline: var(--space-3);
  inset-block-end: -1px;
  block-size: 2px;
  background: var(--color-accent-600);
  transform: scaleX(0);
  transition: transform var(--dur-base) var(--ease-expo);
}
.ipr-abas__item:hover { color: var(--color-text-primary); }
.ipr-abas__item.is-atual { color: var(--color-text-primary); }
.ipr-abas__item.is-atual .ipr-icon { color: var(--color-accent-500); }
.ipr-abas__item.is-atual::after { transform: scaleX(1); }
/* No celular, menos ar entre as abas: as tres do cliente passavam da tela
   por uns 20px, e a ultima saia "Simulaco" cortada. */
@media (width < 40rem) {
  .ipr-abas__item { padding-inline: var(--space-2); }
  .ipr-abas__item::after { inset-inline: var(--space-2); }
}
/* QUANDO AINDA SOBRA ABA ESCONDIDA, a borda direita esmaece: a palavra
   cortada parecia defeito, e nao convite para rolar. O veu e preso na borda
   e aceso pela rolagem, visivel enquanto ha aba escondida e apagado no fim.
   Ele pinta a cor do fundo, que muda dentro de um cartao. Sem esse recurso,
   ou com movimento reduzido, as abas rolam do mesmo jeito, so sem o veu. */
.ipr-abas { --abas-fundo: var(--color-bg-base); }
.ipr-card .ipr-abas { --abas-fundo: var(--color-surface-1); }
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: scroll()) {
    .ipr-abas { scroll-timeline: --ipr-abas-rolagem inline; }
    .ipr-abas::after {
      content: "";
      position: sticky;
      inset-inline-end: 0;
      flex: none;
      inline-size: 2.5rem;
      margin-inline-start: -2.5rem;
      background: linear-gradient(to right, transparent, var(--abas-fundo));
      pointer-events: none;
      opacity: 0;
      animation: ipr-abas-veu linear both;
      animation-timeline: --ipr-abas-rolagem;
    }
    @keyframes ipr-abas-veu { from { opacity: 1; } to { opacity: 0; } }
  }
}

/* --- Seletor de periodo ------------------------------------------------
   <details> nativo: abre, fecha, responde ao teclado e funciona sem uma
   linha de JavaScript. Cada mes e um link, entao o calendario inteiro
   continua de pe com o script desligado. */
.ipr-periodo { position: relative; }
.ipr-periodo__botao {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  block-size: var(--control-h-sm);
  padding-inline: var(--space-3) var(--space-2);
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border);
  background: var(--color-surface-1);
  box-shadow: var(--shadow-xs);
  color: var(--color-text-primary);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  cursor: pointer;
  list-style: none;          /* tira o triangulo padrao do <summary> */
  white-space: nowrap;
  transition: border-color var(--dur-fast), background var(--dur-fast);
}
.ipr-periodo__botao::-webkit-details-marker { display: none; }
.ipr-periodo__botao .ipr-icon { width: 1rem; height: 1rem; color: var(--color-text-muted); }
.ipr-periodo__botao:hover { background: var(--color-surface-2); }
.ipr-periodo[open] .ipr-periodo__botao { border-color: var(--color-focus); box-shadow: var(--shadow-focus); }
.ipr-periodo__seta { display: grid; transition: transform var(--dur-fast); }
.ipr-periodo[open] .ipr-periodo__seta { transform: rotate(180deg); }

/* O painel FLUTUA: aberto no fluxo, ele empurraria a tabela inteira para
   baixo a cada vez que alguem so quisesse conferir o mes. */
.ipr-periodo__painel {
  position: absolute;
  inset-inline-end: 0;
  inset-block-start: calc(100% + var(--space-2));
  z-index: var(--z-dropdown);
  inline-size: 17rem;
  display: grid;
  gap: var(--space-3);
  padding: var(--space-4);
  border-radius: var(--radius-lg);
  border: 1px solid var(--color-border);
  background: var(--color-surface-opaco);
  box-shadow: var(--shadow-lg);
  animation: ipr-periodo-in var(--dur-base) var(--ease-expo) both;
}
@keyframes ipr-periodo-in {
  from { opacity: 0; transform: translate3d(0, -6px, 0) scale(.98); }
  to   { opacity: 1; transform: none; }
}
.ipr-periodo__ano {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.ipr-periodo__valor { font-variant-numeric: tabular-nums; font-size: var(--font-size-lg); }
/* A seta de avancar e a mesma de voltar, girada: um icone a menos para
   manter, e as duas nunca saem desalinhadas. */
.ipr-periodo__frente { transform: rotate(180deg); }
.ipr-periodo__meses {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-1);
}
.ipr-periodo__mes {
  padding: var(--space-2);
  border-radius: var(--radius-sm);
  text-align: center;
  text-decoration: none;
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-secondary);
  transition: background var(--dur-fast), color var(--dur-fast);
}
.ipr-periodo__mes:hover { background: var(--color-surface-2); color: var(--color-text-primary); }
.ipr-periodo__mes.is-atual {
  background: var(--color-accent-600);
  color: var(--color-text-on-accent);
}
.ipr-periodo__limpar { justify-self: stretch; }

/* ---------------------------------------------------------------------------
   CABECALHO DE PERFIL

   Desenhado pela mesma macro no perfil da empresa e no do usuario. Fica aqui,
   e nao no CSS de uma pagina, porque a tela que nao carregasse aquele arquivo
   mostraria o cabecalho sem estilo nenhum.
   --------------------------------------------------------------------------- */
.ipr-perfil__topo {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  flex-wrap: wrap;
}
.ipr-perfil__ident { flex: 1; min-width: 12rem; }
.ipr-perfil__nome  { font-size: var(--font-size-xl); font-weight: var(--font-weight-semibold); letter-spacing: var(--tracking-tight); }
.ipr-perfil__razao {
  font-size: var(--font-size-md);
  color: var(--color-text-secondary);
}
/* Os dados soltos viram uma linha de itens separados por ponto. O separador e
   `::before` do irmao, e nao um caractere no HTML: assim o primeiro item
   nunca comeca com um ponto solto e o texto copiado sai limpo.

   O MESMO DESENHO SERVE A LINHA DO CLIENTE NA CONSULTA (`ipr-cliente__meta`):
   estava copiado em consultar.css, igual, e a primeira mudanca de um deixaria
   o outro para tras. */
.ipr-perfil__meta,
.ipr-cliente__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-1) var(--space-3);
  margin-block-start: var(--space-2);
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
  font-variant-numeric: tabular-nums;
}
.ipr-perfil__meta > span + span::before,
.ipr-cliente__meta > span + span::before {
  content: "";
  display: inline-block;
  inline-size: 3px;
  block-size: 3px;
  margin-inline-end: var(--space-3);
  vertical-align: middle;
  border-radius: var(--radius-pill);
  background: var(--color-border-strong);
}
.ipr-perfil__selos { margin-inline-start: auto; }
.ipr-perfil__nota {
  margin-block-start: var(--space-5);
  padding-block-start: var(--space-4);
  border-top: 1px solid var(--color-border-subtle);
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
}

/* Campo corrigido na tela: barra lateral, como a divida ajustada. A mesma
   marca para a mesma ideia, para nao existirem dois vocabularios visuais. */
.ipr-dados__item.is-corrigido {
  border-color: var(--color-accent-500);
  box-shadow: inset 3px 0 0 var(--color-accent-500);
}
.ipr-cliente__acoes {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

/* Nota de rodape de um painel: a ressalva que fecha uma tabela ou um cartao.
   Vale para qualquer tela, e nao so para a consulta. */
.ipr-nota {
  margin-block-start: var(--space-5);
  padding-block-start: var(--space-4);
  border-top: 1px solid var(--color-border-subtle);
  font-size: var(--font-size-xs);
  line-height: var(--line-normal);
  color: var(--color-text-muted);
}
/* Variante sem a regua de cima: usada quando a nota ja esta num corpo
   proprio do painel, logo abaixo de uma tabela que ja tem borda. Duas linhas
   coladas parecem defeito de renderizacao. */
.ipr-nota--topo {
  margin-block-start: 0;
  padding-block-start: 0;
  border-top: 0;
}
/* Nota solta no painel, logo depois de uma tabela de ponta a ponta: sem o
   recuo do corpo, o texto encostava na borda do cartao (campanha, comissoes,
   registro de atividade). A linha de cima continua de ponta a ponta, como as
   divisas das linhas da tabela. */
.ipr-panel > .ipr-nota {
  margin: 0;
  padding: var(--space-4) var(--space-6) var(--space-5);
}
/* ---------------------------------------------------------------------------
   ESCOLHA EM BOTOES (radio em forma de pilula)

   Por dentro sao radios de verdade: o input fica invisivel mas focavel, e o
   <label> em volta e o que a pessoa ve e clica. Teclado com setas, leitor de
   tela anunciando "opcao 2 de 4" e envio sem JavaScript vem tudo de graca.
   --------------------------------------------------------------------------- */
.ipr-opcoes { border: 0; padding: 0; margin: 0; display: grid; gap: var(--space-3); }
.ipr-opcoes__lista { display: flex; flex-wrap: wrap; gap: var(--space-2); }

.ipr-opcao { position: relative; display: inline-flex; cursor: pointer; }
/* Invisivel, mas NAO `display: none`: escondido assim, o campo sai da ordem
   de foco e quem navega por teclado nunca alcanca a opcao. */
.ipr-opcao__input {
  position: absolute;
  inset: 0;
  opacity: 0;
  margin: 0;
  cursor: pointer;
}
.ipr-opcao__texto {
  display: inline-flex;
  align-items: center;
  min-block-size: var(--control-h-sm);
  padding: 0 var(--space-4);
  border-radius: var(--radius-pill);
  border: 1px solid var(--color-border-strong);
  background: var(--color-surface-1);
  box-shadow: var(--shadow-xs);
  color: var(--color-text-secondary);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  transition: background var(--dur-fast), border-color var(--dur-fast),
              color var(--dur-fast), box-shadow var(--dur-fast);
}
.ipr-opcao:hover .ipr-opcao__texto {
  border-color: var(--color-border-control);
  color: var(--color-text-primary);
}
/* A escolhida e o botao principal em pilula: o mesmo azul chapado. Entre
   quatro opcoes, a marcada tem que ser lida antes de qualquer texto. */
.ipr-opcao__input:checked ~ .ipr-opcao__texto {
  background: var(--color-accent-600);
  border-color: var(--color-accent-600);
  color: var(--color-text-on-accent);
}
/* O anel de foco vai no CHIP, e nao no input invisivel: foco que nao se ve e
   o mesmo que foco nenhum para quem navega por teclado. */
.ipr-opcao__input:focus-visible ~ .ipr-opcao__texto {
  outline: var(--ring-width) solid var(--color-focus);
  outline-offset: var(--ring-offset);
}

/* Marca de "sem valor" numa celula. Existe para o vazio parecer vazio, e nao
   um dado que faltou carregar. */
.ipr-vazio { color: var(--color-text-muted); }

/* --- Avatar ----------------------------------------------------------------
   Iniciais num circulo. Tingido no uso comum (uma lista com cinquenta deles
   nao pode virar um mar de azul), e na COR DA MARCA quando e a propria pessoa
   logada: e o unico avatar da tela que e "voce". */
.ipr-avatar {
  width: 2rem;
  height: 2rem;
  flex-shrink: 0;
  display: grid;
  place-items: center;
  border-radius: var(--radius-pill);
  background: var(--color-accent-tint);
  box-shadow: inset 0 0 0 1px var(--color-accent-tint-strong);
  color: var(--color-accent-300);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  letter-spacing: .02em;
}
.ipr-avatar--lg {
  inline-size: 3.25rem;
  block-size: 3.25rem;
  font-size: var(--font-size-lg);
  border-radius: var(--radius-lg);
}
.ipr-avatar--marca {
  background: var(--color-accent-600);
  box-shadow: none;
  color: var(--color-text-on-accent);
}

/* Entrada escalonada dos filhos, sem uma linha de JavaScript.
   `--reveal-offset` empurra o grupo INTEIRO para frente no tempo. E por ele
   que o cartao de login espera a cortina de abertura sair, sem que este bloco
   precise saber que existe uma cortina. */
.ipr-reveal > * { animation: ipr-rise var(--dur-slow) var(--ease-out) both; }
.ipr-reveal > *:nth-child(1) { animation-delay: calc(var(--reveal-offset, 0ms) +   0ms); }
.ipr-reveal > *:nth-child(2) { animation-delay: calc(var(--reveal-offset, 0ms) +  60ms); }
.ipr-reveal > *:nth-child(3) { animation-delay: calc(var(--reveal-offset, 0ms) + 120ms); }
.ipr-reveal > *:nth-child(4) { animation-delay: calc(var(--reveal-offset, 0ms) + 180ms); }
.ipr-reveal > *:nth-child(5) { animation-delay: calc(var(--reveal-offset, 0ms) + 240ms); }


/* ---------------------------------------------------------------- BRILHO --- */
/*
  Brilho que acompanha o ponteiro.

  DIVISAO DE TRABALHO: o modulo JS `pointer-glow` escreve DUAS variaveis
  (--pointer-x e --pointer-y, em pixels relativos ao elemento) e nada mais.
  Cor, raio, forma e quando acende sao decisao do CSS. E por isso que o mesmo
  modulo serve o cartao de login e o holofote da apresentacao sem uma linha de
  JavaScript a mais.

  Sem o modulo montado (celular, movimento reduzido, JS desligado) os valores
  padrao deixam o brilho parado no alto e nada quebra.
*/
.ipr-sheen { position: relative; isolation: isolate; }
.ipr-sheen::after {
  content: "";
  position: absolute;
  inset: 0;
  /* Negativo: pinta SOBRE o fundo do cartao e SOB o texto. Positivo lavaria
     a leitura do formulario. */
  z-index: -1;
  border-radius: inherit;
  pointer-events: none;
  opacity: 0;
  background: radial-gradient(
    var(--sheen-size, 18rem) circle at var(--pointer-x, 50%) var(--pointer-y, 0%),
    var(--color-sheen), transparent 70%);
  transition: opacity var(--dur-slow) var(--ease-out);
}
.ipr-sheen.is-lit::after { opacity: 1; }


/* -------------------------------------------------------------- ABERTURA --- */
/*
  A ABERTURA DAS TELAS DE CREDENCIAL: o icone que pousa no login.

  09/10/2026: substituiu a cortina da primeira versao (luz desfocada, reflexo
  atravessando, icone inflando com dois aneis, 2,5 segundos), que o cliente
  achou ruim "em tudo". Esta e curta, plana e termina NO login:

    0 a 0,5s   no mesmo fundo do login, o icone aparece no centro e um fio
               azul se enche embaixo dele, como um carregamento;
    0,9s       (--intro-exit) o icone desliza e encolhe ate o lugar do icone
               do login, o fundo da abertura some e o formulario aparece;
    1,3s       o icone do login acende exatamente embaixo do que pousou, e a
               abertura sai.

  DUAS DECISOES SUSTENTAM ESTE COMPONENTE:

  1. A coreografia e 100% CSS e TERMINA SOZINHA (`forwards` na saida). Sem
     JavaScript, o icone some no centro em vez de pousar, e a tela aparece do
     mesmo jeito. O modulo `intro` so acrescenta o que CSS nao sabe: medir o
     caminho do pouso, nao repetir na mesma aba, pular no primeiro clique e
     tirar o elemento do DOM.

  2. `pointer-events: none` desde o primeiro quadro. A abertura nunca engole
     um clique nem uma tecla: quem ja sabe a senha comeca a digitar por baixo.
*/
.ipr-intro {
  position: fixed;
  inset: 0;
  z-index: var(--z-intro);
  display: grid;
  place-items: center;
  pointer-events: none;
  /* O MESMO FUNDO DO LOGIN: nao ha cortina que se levanta, ha uma tela que
     se completa. */
  background-color: var(--color-bg-base);
  animation: ipr-intro-fundo 300ms var(--ease-out) var(--intro-exit) forwards,
             ipr-intro-sai 140ms linear calc(var(--intro-exit) + var(--intro-pouso)) forwards;
}
@keyframes ipr-intro-fundo { to { background-color: transparent; } }
@keyframes ipr-intro-sai   { to { opacity: 0; visibility: hidden; } }

/* O invólucro e o que POUSA: o modulo mede o centro dele contra o do icone
   do login e escreve --intro-dx, --intro-dy e --intro-escala. Sem as
   variaveis, o pouso e no proprio lugar. */
.ipr-intro__marca {
  display: grid;
  animation: ipr-intro-pousa var(--intro-pouso) var(--ease-expo) var(--intro-exit) forwards;
}
@keyframes ipr-intro-pousa {
  to {
    transform: translate(var(--intro-dx, 0), var(--intro-dy, 0)) scale(var(--intro-escala, 1));
  }
}
/* No centro o icone e maior que no cabecalho: e a assinatura da tela. O
   pouso encolhe ate o tamanho de la, e como quadro e icone crescem na mesma
   razao, o que pousa e identico ao que estava esperando. */
.ipr-intro .ipr-brand--icone {
  --icone-quadro: 4.5rem;
  border-radius: var(--radius-2xl);
  animation: ipr-intro-chega 420ms var(--ease-expo) 60ms both;
}
@keyframes ipr-intro-chega {
  from { opacity: 0; transform: scale(.92); }
}

/* O FIO DE CARREGAMENTO, fora do fluxo: assim o icone fica no centro exato
   da tela, que e de onde o pouso e medido. O trilho e a borda do tema; o
   azul que se enche e o mesmo da barra de progresso entre as telas. */
.ipr-intro__fio {
  position: absolute;
  inset-block-start: calc(50% + 3.5rem);
  inset-inline-start: 50%;
  inline-size: 6rem;
  block-size: 2px;
  translate: -50% 0;
  border-radius: var(--radius-pill);
  background: var(--color-border);
  overflow: hidden;
  animation: ipr-fade 200ms var(--ease-out) 220ms both,
             ipr-intro-some 160ms linear calc(var(--intro-exit) - 80ms) forwards;
}
.ipr-intro__fio::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--color-accent-500);
  transform-origin: left;
  animation: ipr-intro-enche 560ms var(--ease-in-out) 280ms both;
}
@keyframes ipr-intro-enche { from { transform: scaleX(0); } }
@keyframes ipr-intro-some  { to { opacity: 0; } }

/*
  Enquanto a abertura EXISTE no DOM, tudo que vem depois dela espera a vez de
  entrar (--reveal-offset), e o icone do login fica apagado ate o pouso
  terminar: o icone que pousou cobre o lugar dele, e os dois nao aparecem ao
  mesmo tempo. Quando o modulo remove a abertura (aba repetida, movimento
  reduzido, ou a pessoa pulou), os seletores deixam de casar e a pagina
  aparece na hora.

  A PRESENCA DO ELEMENTO E O ESTADO. Nao existe classe para o JS e o CSS
  manterem em sincronia, entao nao existe como os dois discordarem.
*/
/* A tela de baixo comeca a aparecer um pouco DEPOIS do pouso comecar: o
   icone sobe passando pelo titulo, e com o texto ja visivel os dois se
   cruzavam no caminho. */
.ipr-intro ~ * { --reveal-offset: calc(var(--intro-exit) + 120ms); }
.ipr-intro ~ * .ipr-brand--icone {
  animation: ipr-fade 1ms linear calc(var(--intro-exit) + var(--intro-pouso)) both;
}

/* ----------------------------------------------------------------- MENU --- */
.ipr-nav { display: flex; flex-direction: column; gap: 2px; }
.ipr-nav__link {
  position: relative;
  display: flex;
  align-items: center;
  white-space: nowrap;
  gap: var(--space-3);
  min-block-size: 2.25rem;
  padding: 0 var(--space-3);
  border-radius: var(--radius-md);
  color: var(--color-text-secondary);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  text-decoration: none;
  transition: background var(--dur-fast), color var(--dur-fast);
}
.ipr-nav__link .ipr-icon {
  width: 1.125rem;
  height: 1.125rem;
  color: var(--color-text-muted);
  transition: color var(--dur-fast);
}
.ipr-nav__link:hover { background: var(--color-surface-1); color: var(--color-text-primary); }
.ipr-nav__link:hover .ipr-icon { color: var(--color-text-secondary); }
/* O ITEM ATUAL: fundo liso um tom acima, texto branco e o icone no azul da
   marca. A luz que se apagava para a direita e o fio aceso da primeira versao
   sairam com o resto do brilho. */
.ipr-nav__link.is-active {
  background: var(--color-surface-3);
  color: var(--color-text-primary);
}
.ipr-nav__link.is-active .ipr-icon { color: var(--color-accent-300); }

/* --------------------------------------------------------- INDICADOR --- */
/* O cartao de numero, como o do painel do shadcn/ui: o rotulo em cima a
   esquerda, o icone pequeno e cinza a direita, e o numero, unico elemento
   grande. O halo azul da primeira versao saiu: o numero se basta. */
.ipr-stat {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.ipr-stat__topo  { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); }
.ipr-stat__label {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  line-height: var(--line-snug);
  color: var(--color-text-secondary);
}
.ipr-stat__icon { display: grid; color: var(--color-text-muted); }
.ipr-stat__icon .ipr-icon { width: 1rem; height: 1rem; }
.ipr-stat__hint  { font-size: var(--font-size-sm); color: var(--color-text-muted); }

/* O numero e o unico elemento grande do cartao, e usa tabular-nums: sem isso
   os digitos tem larguras diferentes e uma coluna de valores fica desalinhada
   a cada atualizacao, como se a tela estivesse tremendo. */
.ipr-stat__value {
  font-size: var(--font-size-2xl);
  font-weight: var(--font-weight-bold);
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--tracking-tight);
  line-height: var(--line-tight);
}

/* A variacao NUNCA depende so da cor: o macro sempre emite a seta junto do
   texto. A cor acelera; a seta e a palavra e que informam. */
.ipr-stat__delta {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  gap: var(--space-1);
  padding: 2px var(--space-2);
  border-radius: var(--radius-pill);
  background: var(--color-surface-2);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-muted);
}
.ipr-stat__delta .ipr-icon { width: 1em; height: 1em; }
.ipr-stat__delta--sobe  { color: var(--color-success-fg); background: var(--color-success-bg); }
.ipr-stat__delta--desce { color: var(--color-danger-fg); background: var(--color-danger-bg); }


/* -------------------------------------------------------------- SELO --- */
/* Estado de registro (pago, aberto, cancelado). Sempre com a palavra dentro:
   cor nunca e o unico portador da informacao.

   O selo de ESTADO leva um ponto da cor dele antes da palavra: numa coluna de
   cinquenta linhas, o olho acha o vermelho pelo ponto antes de ler. O neutro
   nao leva, porque ele e etiqueta (um convenio, um produto), e nao estado. */
.ipr-badge {
  --badge-bg: var(--color-surface-2);
  --badge-fg: var(--color-text-secondary);
  --badge-border: var(--color-border);

  display: inline-flex;
  align-items: center;
  gap: .375rem;
  padding: .125rem .5rem;
  border-radius: var(--radius-sm);
  background: var(--badge-bg);
  box-shadow: inset 0 0 0 1px var(--badge-border);
  color: var(--badge-fg);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-medium);
  line-height: 1.2;
  white-space: nowrap;
}
.ipr-badge:not(.ipr-badge--neutro)::before {
  content: "";
  flex: none;
  inline-size: 6px;
  block-size: 6px;
  border-radius: var(--radius-pill);
  background: currentColor;
}
.ipr-badge--ok      { --badge-bg: var(--color-success-bg); --badge-fg: var(--color-success-fg); --badge-border: var(--color-success-border); }
.ipr-badge--aberto  { --badge-bg: var(--color-warning-bg); --badge-fg: var(--color-warning-fg); --badge-border: var(--color-warning-border); }
.ipr-badge--erro    { --badge-bg: var(--color-danger-bg);  --badge-fg: var(--color-danger-fg);  --badge-border: var(--color-danger-border); }
.ipr-badge--info    { --badge-bg: var(--color-info-bg);    --badge-fg: var(--color-info-fg);    --badge-border: var(--color-info-border); }


/* --------------------------------------------------- CABECALHO DE PAGINA --- */
/* O titulo da pagina com o subtitulo a esquerda e o filtro a direita (o
   periodo, quase sempre). Estava escrito duas vezes, igual, no painel e nas
   comissoes, com nomes de pagina: a terceira tela de relatorio nasceria com a
   terceira copia. */
.ipr-cabecalho {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
}
.ipr-cabecalho__titulo {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
  font-size: var(--font-size-2xl);
  letter-spacing: var(--tracking-tight);
}
.ipr-cabecalho__sub {
  margin-block-start: var(--space-1);
  font-size: var(--font-size-md);
  color: var(--color-text-secondary);
}

/* ------------------------------------------------------------- PAINEL --- */
/* Cartao com cabecalho: titulo a esquerda, acao a direita. */
.ipr-panel { --card-padding: 0; display: flex; flex-direction: column; }
.ipr-panel__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* Quebra quando falta largura: o total ou a acao desce para baixo do
     titulo, em vez de empurrar a pagina para o lado (aconteceu nas comissoes,
     no celular, com o total do ano). */
  flex-wrap: wrap;
  gap: var(--space-3) var(--space-4);
  padding: var(--space-5) var(--space-6);
  border-bottom: 1px solid var(--color-border-subtle);
}
.ipr-panel__title {
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-semibold);
  letter-spacing: var(--tracking-snug);
}
.ipr-panel__sub   { margin-block-start: 2px; font-size: var(--font-size-sm); color: var(--color-text-muted); }
.ipr-panel__body  { padding: var(--space-6); }
/* --- De onde veio o dado -------------------------------------------------
   Nasceu no cabecalho da consulta e subiu para ca quando a campanha passou a
   precisar do mesmo marcador. E a regra do projeto: classe usada por mais de
   uma tela vira componente.

   Vem sempre com a COMPETENCIA junto quando o dado e mensal: margem e folha
   sao fotografias de um mes, e sem a data ao lado o numero parece de hoje. */
.ipr-fonte {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: .1875rem var(--space-3) .1875rem var(--space-2);
  border-radius: var(--radius-pill);
  background: var(--color-surface-2);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-muted);
  white-space: nowrap;
}
.ipr-fonte .ipr-icon { width: 1rem; height: 1rem; }
/* Tabela encosta na borda do painel: o padding viria das celulas. */
.ipr-panel__body--flush { padding: 0; }


/* ------------------------------------------------------------ GRAFICO --- */
/*
  O SVG vem do macro `bar_chart`. Aqui so a cor e a tipografia: a GEOMETRIA
  esta nos atributos do proprio SVG, porque altura de barra e dado, e dado nao
  entra por CSS.

  Barra em SVG, texto em HTML. TRES REGRAS SEGURAM ESTE COMPONENTE:
    1. a AREA tem altura fixa: sem ela a barra cresce com a largura do painel
       e tres meses viram um paredao;
    2. a coluna ESTICA ate essa altura (`align-items: stretch`), senao ela
       encolhe ate o conteudo e a barra perde a referencia;
    3. o SVG e ABSOLUTO dentro do trilho: em fluxo, a proporcao intrinseca
       dele (1 para 10) vira a altura, e o grafico vaza pela pagina. */
.ipr-grafico { margin: 0; }
.ipr-grafico__area {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(1.75rem, 1fr);
  gap: var(--space-2);
  block-size: 13rem;
  align-items: stretch;
}
/* NO CELULAR AS COLUNAS PODEM ENCOLHER ATE O ROTULO. O minimo de 1.75rem por
   coluna somava 424px num grafico de doze meses, mais que a tela inteira, e a
   pagina passava a rolar para o lado. */
@media (width < 40rem) {
  .ipr-grafico__area { grid-auto-columns: minmax(0, 1fr); gap: var(--space-1); }
}
.ipr-grafico__coluna {
  display: grid;
  grid-template-rows: 1.5rem minmax(0, 1fr) 1.25rem;
  gap: var(--space-2);
  block-size: 100%;
  min-block-size: 0;
  /* Ancora do valor, que sai do fluxo logo abaixo. */
  position: relative;
  /* AS LINHAS SAO DECLARADAS, e nao deduzidas pela ordem dos filhos.
     Com o valor fora do fluxo, sobraram dois filhos para tres linhas: a
     barra subiu para a faixa de cima (virou um risco fino) e o rotulo do mes
     foi parar no meio do grafico. */
  /* A COLUNA NAO PODE CRESCER PELO TEXTO. Item de grid nasce com
     `min-width: auto`, entao o valor em dinheiro ("R$ 32.100,00", 64px) fazia
     a coluna medir mais do que a trilha que ela tem (52px): as doze colunas
     somavam mais que a area, COMIAM O GAP entre as barras e a ultima
     escapava pela direita do painel. Medido na tela de Comissoes. */
  min-inline-size: 0;
}

/* O trilho e a RAIA da barra, e so tem a linha de base: sem ela uma barra
   baixa flutua.

   SEM LINHAS DE GRADE, de proposito. A barra ocupa a raia inteira de largura,
   entao a grade so aparecia no vao ACIMA de cada barra: um risco curto por
   cima de todas, que lia como uma "barra fantasma" desenhada errado. O valor
   exato existe no hover e no mes corrente, e e o que se le. */
.ipr-grafico__trilho {
  /* A FAIXA DO MEIO, declarada. Com o valor fora do fluxo sobraram dois
     filhos para tres linhas, e a barra subia para a faixa de cima: virava
     um risco fino, com o mes no meio do grafico. */
  grid-row: 2;
  position: relative;
  display: block;
  min-block-size: 0;
  border-radius: var(--radius-xs) var(--radius-xs) 0 0;
  box-shadow: inset 0 -1px 0 var(--color-chart-axis);
  overflow: hidden;
}
.ipr-grafico__barra {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  fill: var(--color-chart-bar);
  transition: fill var(--dur-fast), filter var(--dur-fast);
}
.ipr-grafico__coluna.is-atual .ipr-grafico__barra { fill: var(--color-chart-bar-atual); }
.ipr-grafico__coluna:hover .ipr-grafico__barra { filter: brightness(.94) saturate(1.2); }

.ipr-grafico__rotulo {
  grid-row: 3;
  font-size: var(--font-size-2xs);
  color: var(--color-text-muted);
  text-align: center;
  white-space: nowrap;
  align-self: center;
}
.ipr-grafico__coluna.is-atual .ipr-grafico__rotulo {
  color: var(--color-text-primary);
  font-weight: var(--font-weight-semibold);
}
/* O valor aparece no mes corrente e em quem recebe o mouse: doze valores em
   dinheiro ao mesmo tempo viram uma parede de numeros. Escondido por
   opacidade, nao removido: leitor de tela continua lendo todos. */
.ipr-grafico__valor {
  /*
    FORA DO FLUXO, e nao dentro da coluna.

    Ele e mais largo que a propria coluna e so aparece no mes corrente e no
    hover: no fluxo, um texto que fica invisivel 90% do tempo decidia a
    largura de todas as barras do grafico.

    Uma etiqueta com fundo proprio e sombra: quando dois valores aparecem ao
    mesmo tempo (o mes atual e o que recebeu o mouse), o de cima precisa ser
    legivel sobre o que estiver atras.
  */
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: 50%;
  translate: -50% 0;
  padding: 2px var(--space-2);
  border-radius: var(--radius-xs);
  background: var(--color-surface-opaco);
  box-shadow: var(--shadow-sm);
  font-size: var(--font-size-2xs);
  font-weight: var(--font-weight-semibold);
  font-variant-numeric: tabular-nums;
  color: var(--color-text-primary);
  text-align: center;
  white-space: nowrap;
  opacity: 0;
  transition: opacity var(--dur-fast);
  /* O rotulo nao rouba o mouse da coluna que o revela. */
  pointer-events: none;
}
.ipr-grafico__coluna.is-atual .ipr-grafico__valor { color: var(--color-accent-400); }
/* NAS PONTAS ELE ENCOSTA, em vez de sair do painel: centrado, o valor da
   primeira coluna escapava pela esquerda e o da ultima pela direita. */
.ipr-grafico__coluna:first-child .ipr-grafico__valor {
  inset-inline-start: 0;
  translate: 0;
}
.ipr-grafico__coluna:last-child .ipr-grafico__valor {
  inset-inline-start: auto;
  inset-inline-end: 0;
  translate: 0;
}
.ipr-grafico__coluna.is-atual .ipr-grafico__valor,
.ipr-grafico__coluna:hover .ipr-grafico__valor { opacity: 1; }

.ipr-grafico__legenda {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-block-start: var(--space-3);
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
}
.ipr-grafico__marca {
  inline-size: .625rem;
  block-size: .625rem;
  border-radius: 3px;
  background: var(--color-chart-bar-atual);
}

/* ---------------------------------------------------------------- TABELA --- */
.ipr-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--font-size-md);
}
/* 16px entre colunas, e nao 20: numa tabela de oito colunas, os quatro
   pixels a mais de cada lado somavam 64px, e era o que empurrava a ultima
   coluna (a de situacao, nas comissoes) para fora do cartao num notebook. */
.ipr-table th,
.ipr-table td {
  padding: .875rem var(--space-4);
  text-align: start;
  border-bottom: 1px solid var(--color-border-subtle);
  white-space: nowrap;
}
/* A primeira e a ultima coluna alinham com o titulo do painel acima: a
   tabela parece parte do cartao, e nao algo colado dentro dele. */
.ipr-table th:first-child,
.ipr-table td:first-child { padding-inline-start: var(--space-6); }
.ipr-table th:last-child,
.ipr-table td:last-child { padding-inline-end: var(--space-6); }
/* O CABECALHO E TEXTO DE APOIO, e nao faixa: frase em peso medio, cinza, e a
   linha de baixo separando do dado, como no shadcn/ui. A faixa cinza em caixa
   alta da primeira versao pesava mais que os proprios dados. Fica em 12px, e
   nao nos 14px do dado, para as tabelas continuarem cabendo em 1440px. */
.ipr-table th {
  padding-block: .625rem;
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-muted);
  border-bottom-color: var(--color-border);
}
.ipr-table tbody tr:last-child td { border-bottom: 0; }
.ipr-table tbody tr { transition: background var(--dur-fast); }
.ipr-table tbody tr:hover { background: var(--color-surface-2); }
/* Numero em coluna: alinhado a direita e com digito de largura fixa, senao a
   coluna de valores nao da para comparar batendo o olho.
   O `th, td { text-align: start }` acima tem especificidade maior (classe +
   elemento) que uma classe sozinha, entao o cabecalho da coluna de numero
   ficava a esquerda enquanto os valores iam para a direita. Repetir o
   elemento aqui empata a conta e alinha os dois. */
.ipr-table th.ipr-table__num,
.ipr-table td.ipr-table__num { text-align: end; }
.ipr-table__num { font-variant-numeric: tabular-nums; }

/* Cabecalho de duas linhas. "Saldo devedor aproximado" numa linha so estica a
   coluna e empurra o resto da tabela; quebrando, a palavra continua la e a
   coluna volta ao tamanho do numero.

   O `inline-block` e o que faz a segunda linha centralizar debaixo da
   primeira: sem ele, o <span> ocuparia a celula inteira e "aproximado"
   centralizaria em relacao a COLUNA, e nao ao texto de cima. */
.ipr-table__duplo { display: inline-block; text-align: center; }
.ipr-table__sub {
  display: block;
  font-size: var(--font-size-2xs);
  letter-spacing: 0;
  text-transform: none;
  opacity: .8;
}
/* `baseline`, e nao `top`: com `top`, o titulo de duas linhas empurrava a
   altura da faixa e sobrava um vao debaixo dos titulos de uma linha so, que
   e o que fazia o cabecalho parecer descolado da tabela. */
.ipr-table thead th { vertical-align: baseline; }
/* Entrelinha curta na segunda linha, pelo mesmo motivo. */
.ipr-table__sub { line-height: 1.15; }

/* A LINHA DE APOIO de uma celula: o dado em cima, o detalhe embaixo e menor.
   Toda celula e `nowrap`, entao o detalhe escrito na MESMA linha esticava a
   coluna ate a tabela passar do cartao: "Pensionista Instituidor: MARIA DA
   SILVA" corrido deixava a matricula com 284px. Em linha propria, cada
   pedaco continua inteiro e a coluna fica do tamanho do maior. */
.ipr-table__apoio {
  display: block;
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
}

/* Coluna que so segura um controle: ocupa o minimo e nao quebra. */
.ipr-table__aperta { inline-size: 1%; white-space: nowrap; }
/* A coluna que ABSORVE a sobra de largura. Sem uma assim, o navegador reparte
   o espaco entre todas e as colunas de numero ficam boiando longe do titulo. */
.ipr-table__largo { inline-size: 100%; }
/* No celular ela tambem quebra. E sempre texto (orgao, rotulo de uma
   composicao), e quebrar entre palavras nao atrapalha a leitura: sem isso, a
   composicao da proposta, so rotulo e valor, passava da tela. */
@media (width < 40rem) {
  .ipr-table th.ipr-table__largo,
  .ipr-table td.ipr-table__largo { white-space: normal; min-inline-size: 8rem; }
}
/* A COLUNA DE PROSA, que pode quebrar em varias linhas.

   Toda celula de tabela e `nowrap` de proposito: numero e nome de banco
   quebrados no meio sao ilegiveis. Mas o detalhe de um log e frase, e com
   `nowrap` ele nao cabe em largura nenhuma: a linha cresce ate estourar a
   caixa, e o que passa some pela direita com a coluna de acoes junto.

   O SELETOR PRECISA DO `td`/`th` JUNTO, como o de `ipr-table__num`: quem poe
   `nowrap` e `.ipr-table td`, que tem duas classes de especificidade. Escrita
   so como `.ipr-table__prosa`, a regra PERDE e nada quebra, sem erro nenhum
   para denunciar. Ja aconteceu aqui. */
.ipr-table__prosa { inline-size: 100%; }
.ipr-table th.ipr-table__prosa,
.ipr-table td.ipr-table__prosa { white-space: normal; min-inline-size: 16rem; }

/* --- A coluna de acoes, presa na direita -------------------------------
   TABELA LARGA ROLA DE LADO, e a primeira coisa que some pela direita e
   justamente a coluna de acoes. Presa, ela deixa de depender da largura:
   qualquer que seja o conteudo, o editar e o excluir estao onde se espera.

   O FUNDO PRECISA SER OPACO, senao a linha passa por baixo dela ao rolar. E
   precisa acompanhar o hover, senao a celula presa fica de outra cor quando
   o mouse entra na linha, e parece que ela nao e da linha.

   A DIVISA E SOMBRA POR DENTRO, e nao borda: com `border-collapse`, a borda
   pertence a grade da tabela e fica para tras quando a celula gruda. Medido:
   rolando, a coluna presa ficava sem divisa nenhuma. */
.ipr-table th.ipr-table__fixa,
.ipr-table td.ipr-table__fixa {
  position: sticky;
  inset-inline-end: 0;
  background: var(--color-surface-1);
  box-shadow: inset 1px 0 0 var(--color-border-subtle);
}
.ipr-table th.ipr-table__fixa { background: var(--color-surface-1); }
.ipr-table tbody tr:hover td.ipr-table__fixa { background: var(--color-surface-2); }
/* Menos ar dos lados que uma celula de texto: sao icones, e presa na direita
   a largura dela sai direto do que sobra para o resto da tabela. */
.ipr-table th.ipr-table__fixa,
.ipr-table td.ipr-table__fixa { padding-inline: var(--space-3); }
/* A DIVISA SO QUANDO HA CONTEUDO PASSANDO POR BAIXO. Com a tabela inteira a
   vista, a divisa fixa virava um traco vertical que nenhuma outra coluna
   tem. Onde o navegador liga animacao a rolagem, a divisa e uma sombra curta
   aparecem enquanto ha algo escondido a direita e somem no fim da rolagem.
   Sem esse recurso, ou com movimento reduzido, fica a divisa fixa. */
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: scroll()) {
    .ipr-table-wrap { scroll-timeline: --ipr-tabela-rolagem inline; }
    .ipr-table th.ipr-table__fixa,
    .ipr-table td.ipr-table__fixa {
      box-shadow: none;
      animation: ipr-fixa-divisa linear both;
      animation-timeline: --ipr-tabela-rolagem;
    }
    @keyframes ipr-fixa-divisa {
      from { box-shadow: inset 1px 0 0 var(--color-border), -.75rem 0 .75rem -.75rem var(--color-sombra-rolagem); }
      to { box-shadow: inset 1px 0 0 transparent, 0 0 0 0 transparent; }
    }
  }
}

/* --- A coluna do nome, que pode quebrar --------------------------------
   Nome de gente, de empresa ou de banco e comprido por natureza, e e a
   celula que cede espaco antes de a tabela passar do cartao: quando aperta,
   quebra em duas linhas, sempre entre palavras. Numero e data continuam
   inteiros. Numa tela larga nada quebra. */
.ipr-table td.ipr-table__nome { white-space: normal; }
.ipr-table td.ipr-table__nome .ipr-pessoa__texto { max-inline-size: 15rem; }
/* Mas com piso. No celular a tabela rola de lado de qualquer jeito, e sem
   minimo ela espremia o nome ate uma palavra por linha. A linha de baixo
   (CPF, e-mail, razao social) nao quebra: "141.586.203-" numa linha e "68"
   na outra nao se le. */
.ipr-table td.ipr-table__nome .ipr-pessoa { min-inline-size: 10rem; }
.ipr-table td.ipr-table__nome .ipr-pessoa__email { white-space: nowrap; }

/* --- Criterios rotulados dentro de uma celula --------------------------
   Rotulo a esquerda, valor a direita, uma linha por criterio. Com o rotulo na
   frente, o banco esta sempre na primeira linha, e comparar duas tabelas vira
   ler a mesma posicao duas vezes em vez de procurar.

   `white-space: normal` porque a celula de tabela e `nowrap`: uma lista de
   tres bancos numa linha so estica a coluna ate estourar a caixa. */
.ipr-criterios {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--space-1) var(--space-3);
  margin: 0;
  align-items: baseline;
}
.ipr-criterios dd { margin: 0; white-space: normal; }
/* A COLUNA PRECISA DE UM PISO, e o piso mora na CELULA e nao na lista.

   Valor que pode quebrar faz o min-content da coluna virar a maior PALAVRA,
   e o navegador entao espreme a coluna ate isso: medido em 119px, com "Eagle,
   Itau, Master" saindo uma palavra por linha. Com uma largura declarada, a
   coluna para de ser a que cede primeiro. */
.ipr-table th.ipr-table__criterios,
.ipr-table td.ipr-table__criterios {
  /* ABSORVE a sobra, como `ipr-table__largo` faz em outras telas. So UMA
     coluna pode pedir 100%: com o pedido na coluna de prazos, esta cedia tudo
     e caia para 119px. */
  inline-size: 100%;
  min-inline-size: 15rem;
  white-space: normal;
}


/* ---------------------------------------------------------- ATIVIDADE --- */
/* Lista vertical com um fio ligando os pontos. Serve a qualquer historico. */
.ipr-feed { display: flex; flex-direction: column; gap: var(--space-5); }
.ipr-feed__item {
  position: relative;
  display: flex;
  gap: var(--space-3);
  padding-inline-start: var(--space-1);
}
.ipr-feed__dot {
  flex-shrink: 0;
  width: 1.75rem;
  height: 1.75rem;
  display: grid;
  place-items: center;
  border-radius: var(--radius-pill);
  background: var(--color-accent-tint);
  box-shadow: inset 0 0 0 1px var(--color-accent-tint-strong);
  color: var(--color-accent-400);
}
/* O fio que liga um ponto ao proximo. O ultimo item nao tem proximo. */
.ipr-feed__item:not(:last-child) .ipr-feed__dot::after {
  content: "";
  position: absolute;
  inset-block-start: 1.75rem;
  inset-inline-start: calc(var(--space-1) + .875rem);
  width: 1px;
  height: calc(100% + var(--space-5) - 1.75rem);
  background: var(--color-border);
}
.ipr-feed__texto { font-size: var(--font-size-md); }
.ipr-feed__quando { font-size: var(--font-size-xs); color: var(--color-text-muted); }


/* ------------------------------------------------------------- SELECT --- */
/* Reaproveita .ipr-field__input inteiro; aqui so entra o que um <select> tem
   de proprio: a seta e o espaco para ela. A seta e background-image em SVG
   embutido, entao nao ha requisicao nem arquivo para manter. */
.ipr-select {
  appearance: none;
  padding-inline-end: 2.5rem;
  cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23647089' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right .75rem center;
  background-size: 1.1rem;
}

/* ------------------------------------------------------------- PESSOA --- */
/* Avatar + nome + e-mail numa celula de tabela. Serve a qualquer listagem de
   gente. */
.ipr-pessoa { display: flex; align-items: center; gap: var(--space-3); }
.ipr-pessoa__texto { display: flex; flex-direction: column; gap: 2px; line-height: var(--line-tight); min-inline-size: 0; }
.ipr-pessoa__nome { font-weight: var(--font-weight-semibold); color: var(--color-text-primary); }
.ipr-pessoa__email { font-size: var(--font-size-xs); color: var(--color-text-muted); }
/* A linha inteira e clicavel, mas continua parecendo texto: sublinhar cada
   nome transformaria a tabela num mar de azul. */
.ipr-pessoa--link { text-decoration: none; color: inherit; }
.ipr-pessoa--link:hover .ipr-pessoa__nome { color: var(--color-accent-400); }

/* --- Sugestoes de autocompletar ----------------------------------------
   Vive aqui, e nao no CSS de uma pagina, porque mais de um campo de telas
   diferentes usa a mesma lista.

   FLUTUA sobre o conteudo: aberta no fluxo, ela empurraria o resto do
   formulario para baixo a cada letra digitada, e o campo seguinte fugiria
   do dedo de quem ia clicar nele. O ancestral posicionado e o
   `.ipr-field__control`, que ja e relative. */
.ipr-sugestoes {
  position: absolute;
  inset-inline: 0;
  top: calc(100% + var(--space-1));
  z-index: var(--z-dropdown);
  margin: 0;
  padding: var(--space-1);
  list-style: none;
  background: var(--color-surface-opaco);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-xl);
  animation: ipr-periodo-in var(--dur-fast) var(--ease-out) both;
}
.ipr-sugestoes__item {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  cursor: pointer;
  line-height: var(--line-tight);
}
/* O mesmo destaque para o mouse e para o teclado: quem navega com as setas
   precisa ver exatamente o que quem passa o mouse ve. */
.ipr-sugestoes__item:hover,
.ipr-sugestoes__item.is-atual { background: var(--color-surface-2); }
.ipr-sugestoes__nome { font-weight: var(--font-weight-medium); }
.ipr-sugestoes__detalhe {
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
}

/* --- Caixa de MARCAR (`data-multi`) --------------------------------------
   A lista abre sem a pessoa digitar nada e fica aberta enquanto ela marca.
   Duas consequencias para o CSS:

   1. ALTURA COM TETO E ROLAGEM. Sao 191 orgaos e 1.217 cidades; sem teto, a
      caixa passaria da dobra e as ultimas opcoes ficariam fora da tela.
   2. a linha vira uma LINHA: caixinha, nome, e o detalhe empurrado para a
      direita. E o arranjo que deixa as caixinhas alinhadas numa coluna so. */
.ipr-sugestoes--marcar {
  max-block-size: 17rem;
  overflow-y: auto;
  /* Rolagem que para na caixa, e nao propaga para a pagina atras dela. */
  overscroll-behavior: contain;
}
.ipr-sugestoes--marcar .ipr-sugestoes__item {
  flex-direction: row;
  align-items: center;
  gap: var(--space-3);
}
.ipr-sugestoes--marcar .ipr-sugestoes__nome {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* O quadrado e o do componente de checkbox, reaproveitado. Aqui nao ha
   `<input>` (a linha e um `role="option"`, e input dentro de option e ARIA
   invalido), entao quem liga o visto e a linha. */
.ipr-sugestoes--marcar .ipr-checkbox__box { --check-size: 1.125rem; }
.ipr-sugestoes__marca {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex: 1 1 auto;
  min-width: 0;
  /* O <label> ocupa a linha inteira: clicar em qualquer ponto marca. */
  cursor: pointer;
}
/* O input real fica sobre a caixinha, invisivel: e ele que recebe o foco, e o
   anel de foco aparece no quadrado desenhado (regra do componente). */
.ipr-sugestoes__marca .ipr-checkbox__input { position: absolute; }
/* Marcado fica com fundo de acento fraco: varrendo a lista, o que ja esta
   escolhido se distingue sem depender so do visto de 6px. Sai do `:has()` do
   proprio checkbox, e nao de uma classe que o JavaScript precisaria manter em
   sincronia com o input. */
.ipr-sugestoes__item:has(.ipr-checkbox__input:checked) {
  background: var(--color-accent-tint);
}
/* PENDENTE DE CONFERIR NUM NAVEGADOR DE VERDADE.
   Estas duas regras estao escritas do jeito certo e funcionam em isolamento.
   Dentro desta lista, no Chrome headless, a caixinha NAO repintou por
   nenhuma das formas tentadas, enquanto o FUNDO DA LINHA, logo acima,
   repinta pelo mesmo `:has()`. Fica registrado para nao ser reescrito as
   cegas: pode ser artefato do modo headless. */
.ipr-sugestoes__item:has(.ipr-checkbox__input:checked) .ipr-checkbox__box {
  background: var(--color-accent-600);
  border-color: var(--color-accent-600);
}
.ipr-sugestoes__item:has(.ipr-checkbox__input:checked) .ipr-checkbox__box::after {
  opacity: 1;
  transform: rotate(45deg) translateY(-1px) scale(1);
}
.ipr-sugestoes__item:has(.ipr-checkbox__input:checked):hover {
  background: var(--color-accent-tint-strong);
}

/* --- Barra de filtros ---------------------------------------------------
   Vive aqui, e nao no CSS de uma pagina, porque mais de uma listagem usa a
   mesma barra. `auto-fit` com minimo: em tela larga fica tudo numa linha, em
   tela estreita quebra sozinho, sem media query. */
.ipr-filtros {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  align-items: end;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-6);
  border-bottom: 1px solid var(--color-border-subtle);
}
/* A busca merece o dobro do espaco dos selects. */
.ipr-filtros__busca { grid-column: span 2; }

@media (width < 40rem) {
  .ipr-filtros { padding-inline: var(--space-4); }
  .ipr-filtros__busca { grid-column: span 1; }
}

/* -------------------------------------------------------------- ACOES --- */
.ipr-acoes { display: flex; align-items: center; gap: var(--space-1); justify-content: flex-end; }
.ipr-acoes__form { margin: 0; display: contents; }
.ipr-acao {
  display: grid;
  place-items: center;
  width: 2rem;
  height: 2rem;
  padding: 0;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--color-text-muted);
  cursor: pointer;
  text-decoration: none;
  transition: background var(--dur-fast), color var(--dur-fast);
}
.ipr-acao .ipr-icon { width: 1.125rem; height: 1.125rem; }
.ipr-acao:hover { background: var(--color-surface-3); color: var(--color-text-primary); }
.ipr-acao--perigo:hover { background: var(--color-danger-bg); color: var(--color-danger); }

/* ------------------------------------------------------------- GAVETA --- */
/* `<details>` com titulo proprio. Veio da tela de consulta, onde abre os
   contratos liquidados e os outros descontos, e subiu para ca quando a tela
   de tabelas de comissao passou a guardar o log dentro de uma. */
.ipr-detalhes {
  border-top: 1px solid var(--color-border-subtle);
  padding-top: var(--space-4);
  margin-top: var(--space-4);
}
.ipr-detalhes__titulo {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  cursor: pointer;
  font-size: var(--font-size-md);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-secondary);
  list-style: none;
  border-radius: var(--radius-xs);
  transition: color var(--dur-fast);
}
.ipr-detalhes__titulo::-webkit-details-marker { display: none; }
/* A seta desenhada a mao, porque a do navegador nao acompanha a fonte nem a
   cor do sistema. Gira ao abrir, que e o unico sinal de estado. */
.ipr-detalhes__titulo::before {
  content: "";
  flex: none;
  inline-size: .4375rem;
  block-size: .4375rem;
  margin-inline: 2px 1px;
  border-right: 1.75px solid currentColor;
  border-bottom: 1.75px solid currentColor;
  transform: rotate(-45deg);
  transition: transform var(--dur-base) var(--ease-expo);
}
.ipr-detalhes[open] .ipr-detalhes__titulo::before { transform: rotate(45deg); }
.ipr-detalhes__titulo:hover { color: var(--color-accent-400); }
/* O QUE ABRE NAO PODE NASCER COLADO NO TITULO. Sem isto, os numeros da gaveta
   encostavam na linha que se clica para abrir, e os dois viravam um bloco so
   de texto. Vale para qualquer conteudo: tabela, lista ou totais. */
.ipr-detalhes__titulo + * { margin-block-start: var(--space-4); }
/* Quando a gaveta E o cartao, e nao um rodape dentro de um. Sem isto ela
   herdava a regua e a margem de cima, que existem para separa-la do conteudo
   acima quando ela vive DENTRO de um painel. */
.ipr-detalhes--cartao {
  border-top: 0;
  margin-top: 0;
  padding: var(--space-5) var(--card-padding, var(--space-6));
}
.ipr-detalhes--cartao .ipr-panel__body { padding-inline: 0; }

/* --------------------------------------------------- LISTA DE GAVETAS --- */
/*
  UMA GAVETA POR ITEM, no lugar de uma linha de tabela.

  Serve a lista cujo item tem MUITO mais dado do que cabe numa linha: o topo
  mostra o que se usa para escolher, e o resto abre quando se pede. Numa
  tabela, os mesmos dados viravam colunas que disputavam largura, e cada
  conserto encolhia uma coluna ate o proximo texto comprido estourar de novo.

  Sem `gap`: a divisao entre itens e a propria borda, como numa tabela.
*/
.ipr-gavetas { list-style: none; margin: 0; padding: 0; }
.ipr-gavetas > li + li { border-top: 1px solid var(--color-border-subtle); }

.ipr-gaveta__topo {
  display: grid;
  /* nome | banco | prazos | comissao. O nome e o banco absorvem a sobra,
     porque sao os dois de texto; prazos e comissao ficam do tamanho do que
     ha dentro. */
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) auto auto;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-4) var(--space-6);
  cursor: pointer;
  list-style: none;
  transition: background var(--dur-fast);
}
.ipr-gaveta__topo::-webkit-details-marker { display: none; }
.ipr-gaveta__topo:hover { background: var(--color-surface-2); }
.ipr-gaveta[open] .ipr-gaveta__topo { background: var(--color-surface-2); }
/* O foco precisa aparecer: o resumo e o unico alvo de teclado da linha. */
.ipr-gaveta__topo:focus-visible {
  outline: var(--ring-width) solid var(--color-focus);
  outline-offset: -2px;
}
/* O nome e uma coluna de duas linhas: o apelido e, abaixo, a observacao. */
.ipr-gaveta__nome { display: grid; gap: 2px; min-inline-size: 0; }
/* O APELIDO E O MAIOR TEXTO DA LINHA. E o nome que a casa deu a tabela, o que
   aparece no simulador e o que se procura na busca; do mesmo tamanho do
   resto, ele competia com a comissao e a linha ficava sem um ponto de
   partida para o olho. */
.ipr-gaveta__apelido {
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-semibold);
  letter-spacing: var(--tracking-snug);
  color: var(--color-text-primary);
}
/* O triangulo, a esquerda do apelido e DENTRO dele: como coluna propria, ele
   abriria uma quinta trilha de 12px que fica vazia no resto da grade. */
.ipr-gaveta__apelido::before {
  content: "";
  display: inline-block;
  width: 0; height: 0;
  margin-right: var(--space-2);
  vertical-align: middle;
  border-left: 5px solid var(--color-text-muted);
  border-block: 4px solid transparent;
  transition: transform var(--dur-base) var(--ease-expo);
}
.ipr-gaveta[open] .ipr-gaveta__apelido::before { transform: rotate(90deg); }
/* Alinhada com o TEXTO do apelido, e nao com o triangulo: o recuo e a largura
   do triangulo mais o espaco dele. */
.ipr-gaveta__nota {
  padding-inline-start: calc(5px + var(--space-2));
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
}
.ipr-gaveta__banco { color: var(--color-text-secondary); min-inline-size: 0; }
.ipr-gaveta__prazos { justify-self: end; }
/* Rotulo em cima, numero embaixo, alinhados a direita: sem cabecalho de
   coluna, o numero sozinho nao diz do que e. */
.ipr-gaveta__numero {
  display: grid;
  justify-items: end;
  gap: 2px;
  min-inline-size: 5rem;
  font-variant-numeric: tabular-nums;
}
.ipr-gaveta__numero strong { font-size: var(--font-size-lg); }

.ipr-gaveta__corpo {
  display: grid;
  gap: var(--space-4);
  padding: var(--space-2) var(--space-6) var(--space-6);
  /* Recuo igual ao do triangulo mais o espaco dele: o conteudo da gaveta
     alinha com o NOME do item, e nao com a borda do cartao. */
  padding-inline-start: calc(var(--space-6) + 5px + var(--space-2));
  background: var(--color-surface-2);
}
/* Os botoes numa linha que quebra: sao quatro, e num painel estreito eles
   nao cabem lado a lado. `display: contents` no formulario de cada acao faz
   o botao dele participar desta mesma linha. */
.ipr-gaveta__acoes { display: flex; flex-wrap: wrap; gap: var(--space-2); }

/* NUM PAINEL ESTREITO O RESUMO VIRA DUAS LINHAS.
   Quatro colunas em 400px dariam uma palavra por celula. Em duas linhas, o
   nome fica com a largura inteira e o resto se divide embaixo. */
@media (width < 48rem) {
  .ipr-gaveta__topo {
    grid-template-columns: minmax(0, 1fr) auto;
    gap: var(--space-2) var(--space-3);
    padding-inline: var(--space-4);
  }
  /* A colocacao e EXPLICITA, e nao a ordem do HTML: no fluxo automatico a
     comissao caia sozinha numa terceira linha, encostada a direita de uma
     coluna vazia. Ao lado do banco, le-se "de quem e" e "quanto paga" na
     mesma linha. */
  .ipr-gaveta__nome   { grid-column: 1 / -1; }
  .ipr-gaveta__banco  { grid-column: 1; grid-row: 2; }
  .ipr-gaveta__numero { grid-column: 2; grid-row: 2; }
  .ipr-gaveta__prazos { grid-column: 1 / -1; grid-row: 3; justify-self: start; }
  .ipr-gaveta__corpo { padding-inline: var(--space-4); }
}

/* ---------------------------------------------------------- PAGINACAO --- */
.ipr-paginacao {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
  padding: var(--space-4) var(--space-6);
  border-top: 1px solid var(--color-border-subtle);
}
.ipr-paginacao__item {
  min-width: 2rem;
  height: 2rem;
  display: grid;
  place-items: center;
  padding-inline: var(--space-2);
  border-radius: var(--radius-sm);
  color: var(--color-text-secondary);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  font-variant-numeric: tabular-nums;
  text-decoration: none;
  transition: background var(--dur-fast), color var(--dur-fast);
}
.ipr-paginacao__item:hover { background: var(--color-surface-2); color: var(--color-text-primary); }
.ipr-paginacao__item.is-atual {
  background: var(--color-accent-tint);
  box-shadow: inset 0 0 0 1px var(--color-accent-tint-strong);
  color: var(--color-accent-300);
  font-weight: var(--font-weight-semibold);
}

/* ------------------------------------------------ GRADE DE CAMPOS --- */
/*
  Campos lado a lado dentro de um grupo.

  O PROBLEMA que resolve: uma pilha vertical unica trata "Cidade" e "UF" como
  se tivessem a mesma importancia e a mesma largura. Duas colunas por padrao;
  `--largo` ocupa a linha toda. O `auto-fit` com minimo cuida do celular
  sozinho, sem media query.
*/
.ipr-campos {
  display: grid;
  gap: var(--space-4) var(--space-5);
  grid-template-columns: repeat(auto-fit, minmax(min(13rem, 100%), 1fr));
  align-items: start;
}
/* Campo que precisa da linha inteira: razao social, e-mail, qualquer um cujo
   conteudo seja longo o bastante para a metade da largura atrapalhar. */
.ipr-campo--largo { grid-column: 1 / -1; }
/* DUAS COLUNAS, e nao a linha toda.
   Campo largo demais para uma celula e curto demais para uma linha: nome,
   logradouro, orgao. Com `--largo` neles, o campo ANTERIOR ficava sozinho numa
   linha de quatro. `span 2` deixa eles dividirem a linha com os vizinhos e a
   grade fecha cheia. Numa grade que virou coluna unica, `span 2` se degrada
   para a largura toda sozinho. */
.ipr-campo--duplo { grid-column: span 2; }
/* Onde so cabe UMA coluna, `span 2` obrigava a grade a criar uma segunda,
   implicita e de largura `auto`, e os campos que caiam nela ficavam
   estreitos: data de nascimento aparecia "12/03" cortada. */
@media (width < 33rem) {
  .ipr-campo--duplo { grid-column: auto; }
}

/* -------------------------------------------------- GRUPO DE CAMPOS --- */
/* <fieldset> com <legend>: a associacao entre o titulo e os campos e nativa,
   entao o leitor de tela anuncia "Acesso, Perfil" em vez de so "Perfil". */
.ipr-grupo {
  border: 0;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  min-inline-size: 0;
}
.ipr-grupo + .ipr-grupo {
  padding-block-start: var(--space-6);
  border-top: 1px solid var(--color-border-subtle);
}
/* O titulo do grupo e um SUBTITULO de verdade (14px, semibold, escuro), e nao
   um rotulo miudo: e ele que divide o formulario em partes que se leem. */
.ipr-grupo__titulo {
  padding: 0;
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  line-height: var(--line-snug);
  color: var(--color-text-primary);
}
/* A EXPLICACAO DO GRUPO. Mesma escala da dica de campo, porque e a mesma
   coisa um degrau acima: `ipr-field__hint` explica um campo, esta explica o
   conjunto. Sem teto de largura: quem limita a medida e a propria coluna do
   formulario (`ipr-form-pagina`). */
.ipr-grupo__ajuda {
  font-size: var(--font-size-sm);
  line-height: var(--line-normal);
  color: var(--color-text-muted);
}
/* Colada no titulo: a ajuda pertence a ele, e com o `gap` cheio do grupo ela
   flutuava no meio do caminho entre o titulo e o primeiro campo.

   MAS A MARGEM NEGATIVA SO VALE A PARTIR DO SEGUNDO GRUPO, e isso nao e
   capricho. O <legend> nao e item de flex: o navegador o posiciona sobre a
   borda de cima do fieldset e reserva a altura dele, entao o `gap` NUNCA
   existiu entre o titulo e o proximo elemento. Nos grupos seguintes a margem
   negativa passa despercebida porque `.ipr-grupo + .ipr-grupo` reserva
   padding no topo, e sobra folga. No PRIMEIRO grupo nao ha padding nenhum, e
   a ajuda subia POR CIMA do proprio titulo. Medido no Chrome: 12px de
   sobreposicao exatos, na ficha de formalizacao. */
.ipr-grupo__titulo + .ipr-grupo__ajuda {
  margin-block-start: var(--space-1);
}
.ipr-grupo + .ipr-grupo .ipr-grupo__titulo + .ipr-grupo__ajuda {
  margin-block-start: calc(var(--space-4) * -1 + var(--space-1));
}
/* O que fica DEPOIS dos campos de um grupo: uma lista de leitura, um resumo
   do que ja esta gravado. Nao e campo, entao nao entra na grade. */
.ipr-grupo__extra {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* --------------------------------------------------- ESTADO VAZIO --- */
/* Uma tela sem dado ainda precisa dizer o que fazer. O desenho e o do
   `Empty` do shadcn/ui: o icone numa caixa cinza, o titulo e o proximo passo.
   Os aneis em volta do icone, da primeira versao, sairam com o resto do
   enfeite; sem o icone, o vazio seria uma frase solta, e frase solta parece
   erro. */
.ipr-empty {
  display: grid;
  justify-items: center;
  gap: var(--space-2);
  padding: var(--space-12) var(--space-6);
  text-align: center;
}
.ipr-empty__icon {
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  margin-block-end: var(--space-2);
  border-radius: var(--radius-lg);
  background: var(--color-surface-3);
  color: var(--color-text-secondary);
}
.ipr-empty__icon .ipr-icon { width: 1.25rem; height: 1.25rem; }
.ipr-empty__title { font-size: var(--font-size-lg); font-weight: var(--font-weight-semibold); letter-spacing: var(--tracking-snug); }
.ipr-empty__text  { color: var(--color-text-muted); font-size: var(--font-size-sm); max-width: 46ch; }

/* --- Etiquetas de selecao multipla -------------------------------------
   O campo continua sendo um texto com nomes separados por virgula; estas
   etiquetas sao a leitura desse texto. Ficam ABAIXO do campo, e nao dentro
   dele: dentro, cada etiqueta nova empurraria o cursor e o campo mudaria de
   altura enquanto a pessoa digita. */
.ipr-etiquetas {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  list-style: none;
  margin: var(--space-2) 0 0;
  padding: 0;
}
.ipr-etiqueta {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-1) var(--space-1) var(--space-1) var(--space-3);
  border-radius: var(--radius-pill);
  background: var(--color-accent-tint);
  box-shadow: inset 0 0 0 1px var(--color-accent-tint-strong);
  color: var(--color-text-primary);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  line-height: var(--line-tight);
}
.ipr-etiqueta__tirar {
  display: grid;
  place-items: center;
  width: 1.375rem;
  height: 1.375rem;
  padding: 0;
  border: 0;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--color-text-muted);
  font-size: var(--font-size-lg);
  line-height: 1;
  cursor: pointer;
  transition: background var(--dur-fast), color var(--dur-fast);
}
.ipr-etiqueta__tirar:hover { background: var(--color-danger-bg); color: var(--color-danger); }
/* As mesmas etiquetas, so para LER: numa tabela elas nao sao clicaveis nem
   removiveis, e o espacamento e menor porque a linha ja e apertada. */
.ipr-etiquetas--leitura { display: inline-flex; margin: 0; gap: var(--space-1); }
.ipr-etiquetas--leitura .ipr-etiqueta {
  padding: 1px var(--space-2);
  background: var(--color-surface-2);
  box-shadow: inset 0 0 0 1px var(--color-border);
  color: var(--color-text-secondary);
  font-size: var(--font-size-xs);
  font-variant-numeric: tabular-nums;
}

/* --- Conversa da proposta ----------------------------------------------
   A caixa e mais alta que os outros modais porque o que importa nela e ver
   varias mensagens de uma vez: uma conversa de tres linhas visiveis obriga a
   rolar para ler o que foi combinado ontem. */
.ipr-conversa__caixa {
  display: grid;
  grid-template-rows: auto 1fr auto auto;
  max-block-size: min(80vh, 40rem);
  inline-size: min(34rem, 92vw);
}
/* A linha do tempo rola sozinha; o cabecalho e o campo de escrever ficam
   parados, como em qualquer conversa. */
.ipr-conversa__linha {
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-6);
  background: var(--color-surface-2);
}
.ipr-conversa__vazio { padding: var(--space-6) 0; text-align: center; }

.ipr-balao { display: flex; gap: var(--space-3); align-items: flex-start; }
.ipr-balao__corpo {
  background: var(--color-surface-1);
  border: 1px solid var(--color-border-subtle);
  box-shadow: var(--shadow-xs);
  border-radius: var(--radius-lg);
  /* O canto reto aponta para o avatar: e o que faz o balao parecer dito por
     aquela pessoa, e nao um cartao solto. */
  border-start-start-radius: var(--radius-xs);
  padding: var(--space-3) var(--space-4);
  min-inline-size: 0;
}
.ipr-balao__topo {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  margin: 0 0 var(--space-1);
  font-size: var(--font-size-xs);
}
.ipr-balao__texto { margin: 0; overflow-wrap: anywhere; }
/* O proprio comentario vem do outro lado, como em toda conversa: quem le
   encontra o que escreveu sem precisar procurar o nome. */
.ipr-balao.is-meu { flex-direction: row-reverse; }
.ipr-balao.is-meu .ipr-balao__corpo {
  background: var(--color-accent-tint);
  border-color: var(--color-accent-tint-strong);
  border-start-start-radius: var(--radius-lg);
  border-start-end-radius: var(--radius-xs);
}
.ipr-balao.is-meu .ipr-balao__topo { flex-direction: row-reverse; }

.ipr-conversa__escrever {
  display: flex;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-6) var(--space-2);
  border-top: 1px solid var(--color-border-subtle);
}
.ipr-conversa__escrever .ipr-field__input { flex: 1; }

/* O balao na lista, com a contagem de comentarios em cima. */
.ipr-acao--balao { position: relative; }
.ipr-acao__conta {
  position: absolute;
  inset-block-start: -3px;
  inset-inline-end: -3px;
  min-inline-size: 1.0625rem;
  padding: 0 4px;
  border-radius: var(--radius-pill);
  background: var(--color-accent-600);
  box-shadow: 0 0 0 2px var(--color-surface-1);
  color: var(--color-text-on-accent);
  font-size: var(--font-size-2xs);
  font-weight: var(--font-weight-semibold);
  line-height: 1.0625rem;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

/* --- Alerta dentro de um painel ----------------------------------------
   Um bloco com icone para o que muda a decisao de quem esta lendo. TRES TONS,
   pela gravidade e nao pelo gosto:

     perigo (padrao)  o dado tem uma ressalva que pode levar a erro;
     aviso            algo que pede atencao, mas nao esta errado (um mes que
                      nao e o atual, uma fonte atrasada);
     info             so conta um estado ("voce esta copiando de tal tabela").

   Antes so existia o vermelho, e a competencia atrasada da folha aparecia
   pintada como erro numa tela que estava certa. Diferente do `.ipr-nota`, que
   e cinza e so explica. */
.ipr-alerta {
  --alerta-borda: var(--color-danger-border);
  --alerta-fundo: var(--color-danger-bg);
  --alerta-cor: var(--color-danger-fg);

  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  margin: 0;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--alerta-borda);
  border-radius: var(--radius-md);
  background: var(--alerta-fundo);
  color: var(--alerta-cor);
  font-size: var(--font-size-sm);
  line-height: var(--line-normal);
}
.ipr-alerta__icone { display: grid; flex: none; block-size: calc(1em * var(--line-normal)); place-items: center; }
.ipr-alerta__icone .ipr-icon { width: 1.125rem; height: 1.125rem; }
.ipr-alerta--aviso {
  --alerta-borda: var(--color-warning-border);
  --alerta-fundo: var(--color-warning-bg);
  --alerta-cor: var(--color-warning-fg);
}
/* Tudo certo: o fim de uma lista de pendencias ("esta tudo preenchido"). */
.ipr-alerta--ok {
  --alerta-borda: var(--color-success-border);
  --alerta-fundo: var(--color-success-bg);
  --alerta-cor: var(--color-success-fg);
}
/* O MESMO BLOCO, EM OUTRO TOM. A cor do texto aqui e a do corpo, e so o
   icone fica azul: informacao nao precisa gritar. */
.ipr-alerta--info {
  --alerta-borda: var(--color-info-border);
  --alerta-fundo: var(--color-info-bg);
  --alerta-cor: var(--color-text-primary);
}
.ipr-alerta--info .ipr-alerta__icone { color: var(--color-info); }
/* O conteudo do alerta quando ele tem mais de uma linha: um titulo, as
   etiquetas do que veio junto e a explicacao. Em coluna, e nao em paragrafo
   corrido, porque sao tres coisas de pesos diferentes. */
.ipr-origem { display: grid; gap: var(--space-2); min-inline-size: 0; }
.ipr-origem p { margin: 0; }
.ipr-origem__ajuda { font-size: var(--font-size-xs); color: var(--color-text-muted); }
/* A acao fica na PONTA DIREITA da caixa, e nao embaixo do texto: e uma saida
   ("comecar do zero"), e saida se procura no canto, longe do que se le. */
.ipr-alerta__acao { margin-inline-start: auto; flex: none; align-self: center; }

/* --- Copiar de uma tabela existente ------------------------------------
   Um cartao em linha: a explicacao a esquerda, a escolha e o botao a
   direita. E um FORMULARIO de verdade (GET), e por isso fica fora do cartao
   de cadastro: `<form>` dentro de `<form>` nao existe em HTML. */
.ipr-copiar {
  display: flex;
  align-items: end;
  flex-wrap: wrap;
  gap: var(--space-4);
  padding: var(--space-5) var(--space-6);
}
/* O texto ABSORVE a sobra, e o campo e o botao ficam do tamanho que
   precisam. */
.ipr-copiar__texto { flex: 1 1 16rem; min-inline-size: 0; }
.ipr-copiar__texto p { margin: 0; }
.ipr-copiar__titulo {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-weight: var(--font-weight-semibold);
}
.ipr-copiar__ajuda {
  margin-block-start: var(--space-1);
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}
/* Largura de leitura para o nome da tabela, e nao a do conteudo: com
   `auto`, o select mudava de tamanho conforme o apelido selecionado, e a
   linha inteira se remontava a cada troca. */
.ipr-copiar__campo { flex: 0 1 18rem; min-inline-size: 12rem; }

/* --- Origem e idade dos dados da consulta ------------------------------
   A data de quando o dado foi buscado e o botao de rebuscar ficam na mesma
   linha, em ponta e ponta: a informacao a esquerda, a acao a direita, que e
   a ordem em que se le e decide. */
.ipr-dados-fonte { display: grid; gap: var(--space-3); }
.ipr-dados-fonte__linha {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-3);
}
.ipr-dados-fonte__linha p { margin: 0; }
.ipr-dados-fonte__linha form { margin: 0; }
/* O rodape da conversa tem um aviso a esquerda e o fechar a direita: o
   `.ipr-modal__pe` padrao alinha tudo a direita, e o aviso ficaria colado no
   botao. */
.ipr-conversa__pe { justify-content: space-between; align-items: center; }
.ipr-conversa__pe p { margin: 0; }

/* --- A conversa nao pula ao abrir --------------------------------------
   O servidor manda `<dialog open>` para a caixa funcionar sem JavaScript.
   Ate o modulo rodar, o navegador desenha esse dialogo NO FLUXO da pagina:
   ele empurra o conteudo, e um instante depois o JS fecha e reabre como
   modal. O olho ve a caixa "vir de baixo" e a pagina se remontar.

   Aqui ela ja nasce flutuando no centro, aberta do jeito que for. Nao ha
   dois desenhos para trocar, entao nao ha pulo.

   `:modal` so casa quando o JavaScript abriu com showModal: e nesse caso
   que o navegador desenha o proprio fundo escuro. Sem ele, o `box-shadow`
   gigante faz o mesmo servico com uma linha. */
.ipr-conversa[open] {
  position: fixed;
  inset: 0;
  margin: auto;
  z-index: var(--z-modal);
  max-block-size: min(80vh, 40rem);
}
.ipr-conversa[open]:not(:modal) {
  box-shadow: 0 0 0 100vmax var(--color-overlay);
}

/* --- Qual consulta abrir -----------------------------------------------
   Usa a mesma caixa flutuante da conversa (`.ipr-conversa[open]`), porque as
   duas sao a mesma coisa: um dialogo que o servidor ja manda aberto para
   funcionar sem JavaScript. So o tamanho muda. */
.ipr-escolha[open] { max-block-size: none; inline-size: min(92vw, 34rem); }
/* Sao TRES saidas no rodape, e nao as duas de sempre: no celular elas nao
   cabem em linha, e sem a quebra a do meio some para fora da caixa. */
.ipr-escolha .ipr-modal__pe { flex-wrap: wrap; }
/* As duas saidas explicadas em uma linha cada. Sem marcador, porque o negrito
   do inicio de cada item ja e o que separa uma da outra. */
.ipr-lista-escolha {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-3);
  font-size: var(--font-size-md);
  color: var(--color-text-secondary);
}
.ipr-lista-escolha strong { color: var(--color-text-primary); }

/* --- Grafico de tendencia ----------------------------------------------
   Serie curta (tres meses) em barra vira um paredao: cada barra ocupa um
   terco da largura e a informacao continua sendo uma so, a direcao. Aqui o
   desenho e uma linha baixa, e o espaco sobra para o numero.

   Tres faixas empilhadas: valores em cima, desenho no meio, meses embaixo.
   As duas de texto sao HTML com colunas iguais, entao cada rotulo cai debaixo
   do seu ponto sem nenhuma conta de posicao. */
.ipr-tendencia { margin: 0; display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-1); }
.ipr-tendencia__linha { display: flex; }
.ipr-tendencia__linha > * {
  flex: 1;
  min-inline-size: 0;
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.ipr-tendencia__valor {
  font-size: var(--font-size-2xs);
  color: var(--color-text-muted);
  /* Valor em dinheiro nao quebra: "R$" numa linha e "1.442,06" na outra se
     le como dois numeros. */
  white-space: nowrap;
  transition: opacity var(--dur-fast);
}
/* COM CINCO PONTOS OU MAIS, so o mes atual fica escrito. Seis valores em
   dinheiro lado a lado nao cabem na coluna e viram uma parede de numeros; os
   outros aparecem ao passar o mouse no grafico, como no grafico de barras.
   Escondidos por opacidade, e nao removidos: o leitor de tela le todos. */
.ipr-tendencia__valores:has(> :nth-child(5)) > :not(.is-atual) { opacity: 0; }
.ipr-tendencia:hover .ipr-tendencia__valores > * { opacity: 1; }
.ipr-tendencia__valor.is-atual {
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-primary);
}
.ipr-tendencia__mes {
  font-size: var(--font-size-2xs);
  color: var(--color-text-muted);
}
.ipr-tendencia__mes.is-atual { color: var(--color-text-secondary); font-weight: var(--font-weight-medium); }
/* No celular, um mes sim e outro nao, contando do fim: seis rotulos de
   "03/2026" encostavam um no outro. O atual fica sempre, e `visibility`
   (e nao `display`) guarda o lugar de cada um debaixo do seu ponto. */
@media (width < 40rem) {
  .ipr-tendencia__mes:nth-last-child(even) { visibility: hidden; }
}

/* Altura minima, e nao fixa: sozinho o grafico tem um tamanho de bolso, e
   dentro de uma coluna com altura definida ele estica ate o fim dela. */
.ipr-tendencia__area { min-block-size: 4.5rem; }
.ipr-tendencia__desenho { inline-size: 100%; block-size: 100%; display: block; overflow: visible; }

/* `vector-effect: non-scaling-stroke` no HTML e o que salva os dois: a
   espessura passa a ser contada em pixels da tela, entao o estica-e-puxa do
   `preserveAspectRatio="none"` nao engorda a linha nem vira o ponto em
   elipse. */
.ipr-tendencia__traco {
  fill: none;
  stroke: var(--color-accent-400);
  stroke-width: 2.25;
  stroke-linejoin: round;
  stroke-linecap: round;
}
.ipr-tendencia__area-preenchida { fill: var(--color-accent-tint); stroke: none; }
/* Ponto = linha de comprimento zero com ponta redonda. Circulo de verdade em
   qualquer largura, porque a espessura nao escala. */
.ipr-tendencia__ponto {
  stroke: var(--color-accent-400);
  stroke-width: 6;
  stroke-linecap: round;
}
.ipr-tendencia__ponto.is-atual { stroke: var(--color-accent-500); stroke-width: 10; }

/* Campo compacto, para quando ele e um controle de apoio dentro de uma linha
   ja apertada (o seletor de situacao numa celula de tabela) e nao o campo
   principal de um formulario. Anda junto do `.ipr-btn--sm`, e por isso tem
   a altura dele. */
.ipr-field__input--sm {
  /* ALTURA tambem, e nao so a tipografia. `.ipr-field__input` fixa `height`,
     entao um modificador que mexesse so no padding deixaria o campo mais alto
     que o `.ipr-btn--sm` do lado. A altura sai pela variavel que o proprio
     componente consulta. */
  --field-height: var(--control-h-sm);
  /* `padding-inline`, e nao o atalho `padding`: o atalho zera tambem o
     `padding-inline-end`, que e onde o `.ipr-select` reserva o espaco da
     seta. */
  padding-inline: var(--space-3);
  border-radius: var(--radius-sm);
  font-size: var(--font-size-sm);
  inline-size: auto;
}
/* Compacto E com seta: menos folga que o select normal, mas ainda o
   suficiente para o texto nao passar por baixo dela. */
.ipr-select.ipr-field__input--sm { padding-inline-end: 2.25rem; }


/* ------------------------------------------------------------ AMBIENTE --- */
/*
  O FUNDO VIVO, EM TRES CAMADAS: duas luzes que respiram em direcoes opostas e
  uma malha de pontos que escorre na diagonal.

  Nasceu na tela de login e virou componente quando a landing precisou do
  mesmo fundo. Nao existe uma segunda copia: o que muda de uma tela para a
  outra sao as VARIAVEIS abaixo, e nao o codigo.

  As tres camadas usam o MESMO keyframe (`ipr-drift`, em base.css) e trocam
  so o destino e o periodo. O keyframe le --drift-x e --drift-y, entao um
  deslocamento escrito uma vez produz tres movimentos diferentes.

  Os periodos (--dur-ambient-1/2/3) sao PRIMOS ENTRE SI, e o porque esta em
  tokens.css: a combinacao das tres camadas so se repete depois de quase
  quatro horas.

  Todas animam SO transform. Nenhuma repinta: o desfoque e rasterizado uma vez
  e o compositor apenas desloca a textura pronta. A regra global de
  prefers-reduced-motion congela as tres.
*/
.ipr-ambiente {
  position: relative;
  isolation: isolate;
  /*
    `clip`, E NAO `hidden`, e a diferenca nao e cosmetica.

    Os dois recortam igual. Mas `overflow: hidden` cria um CONTAINER DE
    ROLAGEM (um elemento que poderia rolar, so que sem barra), e
    `position: sticky` gruda no container de rolagem mais proximo. Um filho
    grudento dentro de um `.ipr-ambiente` com `hidden` simplesmente nao gruda,
    e nao ha erro nenhum: o elemento so nao para onde deveria parar.

    `clip` recorta sem criar container de rolagem, entao o sticky volta a se
    ancorar na janela. A linha `hidden` fica antes como reserva para navegador
    que nao conheca `clip`, e a de baixo vence onde as duas valem.
  */
  overflow: hidden;
  overflow: clip;
}

/* Camada 1: luz quente, o azul da marca. */
.ipr-ambiente::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset-block-start: var(--luz-quente-y, 46%);
  inset-inline-start: var(--luz-quente-x, 44%);
  inline-size: var(--luz-quente-tam, min(48rem, 125vw));
  aspect-ratio: 1;
  border-radius: 50%;
  translate: -50% -50%;
  background: radial-gradient(circle, var(--color-aurora), transparent 62%);
  filter: blur(90px);
  opacity: var(--luz-quente-forca, .6);
  --drift-x: -5%;
  --drift-y: 4%;
  animation: ipr-drift var(--dur-ambient-1) var(--ease-in-out) infinite alternate;
}

/* Camada 2: luz fria, deslocada e indo para o outro lado. Duas luzes da mesma
   cor no mesmo sentido se somariam num borrao unico; opostas, elas se cruzam
   e o fundo ganha profundidade. */
.ipr-ambiente::after {
  content: "";
  position: absolute;
  z-index: -1;
  inset-block-start: var(--luz-fria-y, 62%);
  inset-inline-start: var(--luz-fria-x, 62%);
  inline-size: var(--luz-fria-tam, min(38rem, 105vw));
  aspect-ratio: 1;
  border-radius: 50%;
  translate: -50% -50%;
  background: radial-gradient(circle, var(--color-aurora-cool), transparent 65%);
  filter: blur(80px);
  --drift-x: 6%;
  --drift-y: -5%;
  animation: ipr-drift var(--dur-ambient-2) var(--ease-in-out) infinite alternate;
}

/*
  Camada 3: malha de pontos escorrendo na diagonal.

  E a unica camada com movimento que da para PERCEBER: as duas luzes sao
  lentas e difusas demais para o olho registrar. A malha da a sensacao de que
  a tela esta viva sem nunca disputar atencao com o conteudo.

  O deslocamento e EXATAMENTE um ladrilho (40px), com `linear` e sem
  `alternate`: ao completar o ciclo os pontos caem em cima de onde estavam, e
  a emenda e invisivel. Qualquer outro valor produziria um salto a cada volta.

  O elemento passa 5rem de cada borda para que o deslocamento nunca revele a
  quina, e a mascara apaga a malha nas pontas para ela nao virar papel de
  parede.
*/
.ipr-ambiente__malha {
  position: absolute;
  inset: -5rem;
  z-index: -1;
  pointer-events: none;
  background-image: radial-gradient(circle, var(--color-mesh-dot) 1.2px, transparent 1.2px);
  background-size: 40px 40px;
  -webkit-mask-image: var(--malha-foco, radial-gradient(ellipse 75% 65% at 50% 45%, #000 15%, transparent 72%));
          mask-image: var(--malha-foco, radial-gradient(ellipse 75% 65% at 50% 45%, #000 15%, transparent 72%));
  --drift-x: 40px;
  --drift-y: 40px;
  animation: ipr-drift var(--dur-ambient-3) linear infinite;
}

/* A TABELA ROLA DENTRO DO PROPRIO QUADRO.

   O `<div class="ipr-table-wrap">` existe em DEZ telas desde o comeco e nunca
   teve uma linha de CSS: o quadro nao continha nada, entao a tabela larga
   empurrava a PAGINA INTEIRA. No monitor isso nunca apareceu, porque sobra
   largura; numa tela estreita a pagina passava a rolar para o lado, e junto
   com ela a barra do topo e o cabecalho.

   `overflow-x: auto` sozinho ja transforma o quadro em area de rolagem: no
   monitor, onde a tabela cabe, nada muda.

   E A BORDA AVISA QUE HA MAIS. Uma sombra aparece na ponta de onde ainda ha
   coluna escondida, e some quando se chega ao fim, sem uma linha de
   JavaScript: dois fundos `local` (que rolam junto com a tabela e cobrem a
   sombra quando a ponta chega) por cima de dois fundos `scroll` (que ficam
   parados nas bordas). Antes a tabela larga era so cortada na borda do
   cartao, e parecia defeito: na tela de comissoes a coluna de situacao saia
   pela metade.

   `position: relative` E O QUE FAZ O RECORTE VALER PARA TUDO. Dentro da tabela
   ha elementos absolutos (o texto so para leitor de tela, a caixa de marcar
   invisivel), e elemento absoluto so e recortado por quem esta entre ele e o
   bloco de contencao dele. Sem ancora aqui, o bloco era o CARTAO, de fora do
   quadro: o recorte nao valia, e a pagina inteira passava a rolar para o
   lado no celular, em ate 750px. Medido em sete telas. */
.ipr-table-wrap {
  position: relative;
  overflow-x: auto;
  background:
    linear-gradient(to right, var(--color-surface-1) 30%, transparent) left center / 2.5rem 100% no-repeat local,
    linear-gradient(to left, var(--color-surface-1) 30%, transparent) right center / 2.5rem 100% no-repeat local,
    radial-gradient(farthest-side at 0 50%, var(--color-sombra-rolagem), transparent) left center / .875rem 100% no-repeat scroll,
    radial-gradient(farthest-side at 100% 50%, var(--color-sombra-rolagem), transparent) right center / .875rem 100% no-repeat scroll;
}

/* -------------------------------------------------- FOLHA DE MARGEM --- */
/*
  O QUADRO DE MARGENS DE UMA MATRICULA, e os numeros de apoio que ele usa.

  Estava em `pages/consultar.css` ate a apresentacao publica passar a mostrar
  ESTA tela. Duas telas usam, entao e componente: a regra da casa e que classe
  usada por mais de uma tela sobe para ca, e ha teste obrigando.

  O HTML correspondente e o macro `folha()`, em macros/ui.html: subir so o CSS
  deixaria a marcacao duplicada, que e o mesmo problema pela outra ponta.

  A LEITURA: cabecalho com a matricula titulando, os tres totais, faixas em
  lista com o livre em destaque e a barra do quanto ja foi usado, e a
  tendencia ao lado.
*/
.ipr-folha { display: grid; gap: var(--space-5); }
.ipr-folha + .ipr-folha { border-top: 1px solid var(--color-border-subtle); }

.ipr-folha__cabeca {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2) var(--space-4);
}
.ipr-folha__titulo {
  margin: 0;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--font-size-lg);
  letter-spacing: var(--tracking-snug);
}
/* Rotulo pequeno em cima do numero, e nao os dois do mesmo tamanho: base de
   calculo e o teto de onde as faixas saem, e nao um valor a comparar. */
.ipr-folha__base {
  margin: 0;
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  font-variant-numeric: tabular-nums;
}

/* Duas leituras da mesma folha lado a lado: quanto cabe hoje, e para onde
   isso vai. Num painel estreito elas empilham, e a tendencia vai para baixo,
   que e a ordem certa de ler. */
.ipr-folha__corpo {
  display: grid;
  gap: var(--space-8);
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
  /* `stretch`, e nao `start`: e o que permite a tendencia ter altura para se
     centrar em relacao a lista ao lado. */
  align-items: stretch;
}
/* EMPILHA JA NO NOTEBOOK. A conta e da coluna de CONTEUDO, e nao da janela:
   em 1024px a barra lateral leva 264px e sobram uns 650 para o painel, e os
   tres totais lado a lado precisam de quase 500 so na coluna da esquerda.
   Empilhando abaixo de 60rem, a folha passava 125px do cartao. Medido. */
@media (width < 75rem) {
  .ipr-folha__corpo { grid-template-columns: minmax(0, 1fr); gap: var(--space-6); }
}

.ipr-folha__esquerda { display: grid; gap: var(--space-5); align-content: start; min-inline-size: 0; }
/* O NOME E NEUTRO DE PROPOSITO. Comecou como `ipr-folha__totais`, dentro do
   quadro de margens, e a aba de simulacao precisou exatamente do mesmo
   desenho para parcela, troco e comissao. Sao tres numeros de fecho lado a
   lado: o que muda de tela para tela e o que eles dizem, e nao o bloco.

   TRES CAIXAS IGUAIS OCUPANDO A LARGURA INTEIRA, e nao tres caixas do
   tamanho do que ha dentro encostadas a esquerda. Assim a borda direita da
   ultima cai exatamente sobre a coluna LIVRE da lista abaixo.

   `repeat(3, 1fr)` e nao flex: com flex, a caixa do numero maior ficaria mais
   larga que as outras duas, e a simetria se perde de novo. */
.ipr-totais {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-3);
  align-items: stretch;
}
/* NAO LEVA `ipr-mini-grupo` junto: aquele e flex, esta depois no arquivo e,
   com a mesma especificidade, ganhava. CENTRADOS DENTRO DA CAIXA: o
   `ipr-mini` alinha a direita, que e o certo quando ele fecha um cabecalho,
   e errado aqui, onde tres caixas do mesmo tamanho ficam lado a lado. */
.ipr-totais .ipr-mini { text-align: center; }
/*
  NUM PAINEL ESTREITO AS TRES CAIXAS VIRAM TRES LINHAS.

  `repeat(3, 1fr)` nao encolhe abaixo do conteudo (item de grid nasce com
  `min-width: auto`), entao no celular as tres caixas somavam mais que a
  largura da tela e a ultima saia pela direita, cortada no meio do numero.

  Em linha, cada total vira rotulo a esquerda e valor a direita, que e como se
  le um resumo de dinheiro numa coluna so.
*/
@media (width < 48rem) {
  .ipr-totais { grid-template-columns: minmax(0, 1fr); gap: var(--space-2); }
  .ipr-totais .ipr-mini {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-3);
    text-align: start;
  }
}

/* --- Uma linha por faixa, em colunas -----------------------------------
   O NOME NAO E `faixa`: `ipr-faixa` ja e o par de campos minimo/maximo da
   campanha, aqui mesmo, e carrega em toda pagina. Os filhos daqui caiam nas
   tres colunas de la e a barra ficava espremida no meio.

   Colunas fixas para nome e numero: sem elas, cada linha comeca onde a
   anterior terminou e o olho nao tem por onde descer. */
.ipr-bandas {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-4);
}
/* AS COLUNAS SAO AS MESMAS NO CABECALHO E EM CADA LINHA, declaradas uma vez
   e herdadas pelos dois. Repetir a lista de trilhas nos dois lugares e o jeito
   classico de a tabela sair desalinhada na primeira coluna nova. */
.ipr-bandas__cabeca,
.ipr-banda {
  display: grid;
  grid-template-columns: minmax(6rem, 9rem) 7rem minmax(3rem, 1fr) 7rem;
  align-items: center;
  gap: var(--space-4);
  font-size: var(--font-size-md);
}
/* O cabecalho e so um guia, no tamanho do sobretitulo (regra la em cima):
   dois valores em dinheiro na mesma linha nao se distinguem sozinhos. */
.ipr-bandas__cabeca {
  margin: 0 0 calc(var(--space-2) * -1);
  font-size: var(--font-size-2xs);
}
.ipr-bandas__cabeca > :nth-child(2),
.ipr-bandas__cabeca > :last-child { text-align: end; }
/* Centrado sobre a barra: encostado a esquerda, "UTILIZADA" ficava colado no
   "TOTAL" da coluna anterior e os dois se liam como uma expressao so. */
.ipr-bandas__cabeca > :nth-child(3) { text-align: center; }

.ipr-banda__nome { color: var(--color-text-secondary); font-weight: var(--font-weight-medium); }
/* O TETO E CONTEXTO, e nao resposta: mesma coluna do livre em largura, para
   os dois alinharem, mas sem peso e sem cor. */
.ipr-banda__teto {
  color: var(--color-text-muted);
  font-variant-numeric: tabular-nums;
  text-align: end;
}
/* O LIVRE E A RESPOSTA DA PERGUNTA DO PAINEL, entao ele e o unico numero da
   linha com peso, e todos alinham pela direita para poderem ser comparados
   de cima a baixo sem ler os digitos. */
.ipr-banda__livre {
  color: var(--color-success);
  font-weight: var(--font-weight-semibold);
  font-variant-numeric: tabular-nums;
  text-align: end;
}
/* O trilho e CSS e o preenchimento e SVG: largura e dado. O arredondamento
   fica no trilho, senao o `rx` do retangulo seria esticado junto e viraria
   um arco. */
.ipr-banda__trilho {
  display: block;
  block-size: 8px;
  border-radius: var(--radius-pill);
  background: var(--color-surface-3);
  overflow: hidden;
}
.ipr-banda__uso { display: block; inline-size: 100%; block-size: 100%; }
.ipr-banda__uso rect { fill: var(--color-accent-400); }
.ipr-banda.is-estourada .ipr-banda__livre { color: var(--color-danger); }
.ipr-banda.is-estourada .ipr-banda__uso rect { fill: var(--color-danger); }

/* Sem largura para quatro colunas, a linha vira duas: nome e livre em cima,
   teto e barra embaixo. O cabecalho some, porque ele so faz sentido enquanto
   as colunas existem. */
@media (width < 48rem) {
  .ipr-bandas__cabeca { display: none; }
  .ipr-banda {
    grid-template-columns: 1fr auto;
    gap: var(--space-1) var(--space-3);
  }
  .ipr-banda__nome { order: 1; }
  .ipr-banda__livre { order: 2; }
  .ipr-banda__teto { order: 3; text-align: start; font-size: var(--font-size-2xs); }
  .ipr-banda__trilho { order: 4; }
}

/* A TENDENCIA OCUPA A COLUNA INTEIRA, com o desenho centrado no que sobra
   depois do titulo. Encostada no topo, ela terminava bem antes da ultima
   faixa e deixava um buraco embaixo, a direita. */
.ipr-folha__tendencia {
  display: grid;
  /* Coluna DECLARADA, com zero de minimo: a coluna implicita `auto` crescia
     ate a fileira de valores dos meses (que nao quebra) e a caixa passava da
     tela no celular. */
  grid-template-columns: minmax(0, 1fr);
  min-inline-size: 0;
  grid-template-rows: auto 1fr;
  gap: var(--space-3);
  block-size: 100%;
  padding: var(--space-4);
  border-radius: var(--radius-lg);
  background: var(--color-surface-2);
}
/* O DESENHO CRESCE ATE O FIM DA COLUNA, em vez de ficar centrado com sobra em
   cima e embaixo. Aqui quem manda na altura e a lista de faixas ao lado, que
   nao muda com a largura. */
.ipr-folha__tendencia .ipr-tendencia {
  block-size: 100%;
  grid-template-rows: auto 1fr auto;
}
/* Mesma tipografia do cabecalho das colunas do outro lado (o sobretitulo):
   as duas linhas estao na mesma altura, e com pesos diferentes uma parecia
   titulo e a outra legenda de rodape. */
.ipr-folha__legenda {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-1) var(--space-3);
}
/* A VARIACAO E O NUMERO QUE DECIDE A LIGACAO, entao ela vem escrita e nao
   deduzida de duas alturas de olho. Verde so quando SOBE: margem que abriu e
   oportunidade, margem que fechou e o mes passando. */
.ipr-folha__delta {
  font-weight: var(--font-weight-semibold);
  font-variant-numeric: tabular-nums;
  letter-spacing: normal;
  text-transform: none;
  color: var(--color-text-secondary);
}
.ipr-folha__delta.is-alta { color: var(--color-success); }

/* --- Indicadores no cabecalho ------------------------------------------
   Numero de apoio, ao lado do titulo. Nao viram cartao porque cartao pede
   uma faixa inteira de altura antes da lista, e a lista e o assunto da tela.

   O cabecalho quebra em duas partes no celular; sem `flex-wrap`, os numeros
   espremeriam o titulo ate ele virar uma coluna de letras. */
.ipr-dividas__head { flex-wrap: wrap; }
.ipr-mini-grupo {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
}
/* OS DOIS INDICADORES PRECISAM PARECER COISAS DIFERENTES.
   Um e contagem (numero seco, caixa neutra) e o outro e dinheiro (caixa
   tingida, com o valor destacado): a diferenca de peso diz o que e cada um
   antes da leitura. O rotulo e o sobretitulo da casa (regra la em cima). */
.ipr-mini {
  display: grid;
  gap: 2px;
  text-align: end;
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border-subtle);
  background: var(--color-surface-2);
}
.ipr-mini__valor {
  font-size: var(--font-size-xl);
  font-weight: var(--font-weight-bold);
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--tracking-tight);
  line-height: var(--line-tight);
  color: var(--color-text-primary);
}
/* Contagem: numero menor, sem enfeite. Nao e o que a pessoa procura. */
.ipr-mini--contagem .ipr-mini__valor { font-size: var(--font-size-lg); }
/* Dinheiro: e o numero da tela. Fundo tingido e cor de acento. */
.ipr-mini--dinheiro {
  background: var(--color-accent-tint);
  border-color: var(--color-accent-tint-strong);
}
.ipr-mini--dinheiro .ipr-mini__rotulo,
.ipr-mini--dinheiro .ipr-mini__valor { color: var(--color-accent-400); }

/* --------------------------------------------------------- PASSO NUMERADO --- */
/*
  O NUMERO DO PASSO, dentro do titulo do painel.

  Uma tela com tres paineis empilhados nao diz que eles sao uma SEQUENCIA: ela
  parece tres assuntos. O numero e a menor marca possivel de ordem, e por isso
  ele e `aria-hidden`: para quem le com o ouvido, a ordem ja esta na ordem dos
  titulos.
*/
.ipr-passo-num {
  display: inline-grid;
  place-items: center;
  inline-size: 1.625rem;
  block-size: 1.625rem;
  margin-inline-end: var(--space-3);
  border-radius: var(--radius-sm);
  background: var(--color-accent-600);
  color: var(--color-text-on-accent);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-bold);
  font-variant-numeric: tabular-nums;
  vertical-align: middle;
  /* O numero nasce do tamanho do titulo e ficaria maior que a pastilha. */
  line-height: 1;
}

/* ----------------------------------------------------------------- CONTA --- */
/*
  TRES CAIXAS QUE SAO UMA CONTA, com o mais e o igual escritos entre elas.

  Lado a lado sem sinal nenhum, os tres numeros pareciam tres indicadores
  independentes, e a pergunta "por que a margem da simulacao e maior que a
  margem livre?" nao tinha resposta na tela. Com os sinais, a soma se le.

  Os sinais sao `aria-hidden` e a caixa tem rotulo proprio: lidos em voz alta
  eles virariam "mais igual" no meio de tres valores em reais.
*/
.ipr-conta {
  display: flex;
  align-items: stretch;
  gap: var(--space-3);
  flex-wrap: wrap;
}
/* Cada caixa cresce igual, e pode encolher ate caber: sem o `min-inline-size`
   a caixa nao desce abaixo do proprio conteudo e a ultima sai pela direita,
   que e o mesmo defeito ja corrigido em `.ipr-totais`. */
.ipr-conta > .ipr-mini {
  flex: 1 1 10rem;
  min-inline-size: 0;
  text-align: center;
  align-content: center;
}
.ipr-conta__sinal {
  align-self: center;
  display: grid;
  place-items: center;
  inline-size: 1.75rem;
  block-size: 1.75rem;
  border-radius: var(--radius-pill);
  background: var(--color-surface-1);
  box-shadow: inset 0 0 0 1px var(--color-border);
  color: var(--color-text-muted);
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-semibold);
  line-height: 1;
}
/* Numa coluna estreita a conta vira pilha, e o sinal continua entre as
   caixas: em coluna ele e o que diz que a de baixo e a soma das de cima.
   A caixa encolhe para a altura do texto: na pilha, a altura igual das tres
   (que no monitor alinha a linha) virava tres quadros vazios. */
@media (width < 48rem) {
  .ipr-conta { flex-direction: column; gap: var(--space-2); }
  .ipr-conta > .ipr-mini {
    flex: none;
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-3);
    text-align: start;
  }
}

/* ------------------------------------------------------------- OPERACAO --- */
/*
  O TITULO DE UMA OPERACAO dentro de uma proposta de varias: o numero dela, a
  margem que ela usa e o resumo (tabela, prazo, parcela).

  Mora aqui, e nao no CSS da consulta, porque duas telas mostram a mesma
  coisa: a aba de simulacao e a pagina da proposta fechada.
*/
.ipr-operacao__titulo {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  flex-wrap: wrap;
  padding: var(--space-5) var(--space-6) 0;
  font-weight: var(--font-weight-semibold);
}

/* ---------------------------------------------------------------- OFERTA --- */
/*
  AS DUAS PERGUNTAS DE QUEM ESTA NA LIGACAO: quanto fica por mes e quanto o
  cliente recebe. Grandes, porque sao a operacao; sozinhas, porque qualquer
  numero ao lado delas (comissao, financiado) e lido como se tambem fosse do
  cliente.

  Usada na aba de simulacao, na pagina da proposta fechada e no PDF: por isso
  mora aqui, e nao no CSS de uma pagina.
*/
.ipr-oferta {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-4);
}
.ipr-oferta__item {
  position: relative;
  display: grid;
  gap: var(--space-1);
  padding: var(--space-5) var(--space-6);
  border-radius: var(--radius-lg);
  border: 1px solid var(--color-border-subtle);
  background: var(--color-surface-2);
  overflow: hidden;
}
/* O LIQUIDO E O NUMERO QUE O CLIENTE OUVE. A caixa dele leva o tom da marca,
   liso: e a unica coisa da tela que tem que ser achada sem procurar. */
.ipr-oferta__item--destaque {
  border-color: var(--color-accent-tint-strong);
  background: var(--color-accent-tint);
}
.ipr-oferta__valor {
  font-size: var(--font-size-2xl);
  font-weight: var(--font-weight-bold);
  letter-spacing: var(--tracking-tight);
  line-height: var(--line-tight);
  font-variant-numeric: tabular-nums;
  /* Numero em dinheiro nunca quebra no meio: "R$ 34.063," numa linha e "54"
     na outra se le como dois valores. */
  white-space: nowrap;
}
.ipr-oferta__item--destaque .ipr-oferta__rotulo,
.ipr-oferta__item--destaque .ipr-oferta__valor { color: var(--color-accent-400); }
.ipr-oferta__nota { font-size: var(--font-size-sm); color: var(--color-text-muted); }
/* ------------------------------------------------------- ACAO DE RODAPE --- */
/*
  O BOTAO QUE FECHA UM TRABALHO, com a frase que explica o que ele faz.

  Os dois sao um bloco so: empilhados sem nada entre eles, o texto encostava
  no botao e parecia legenda dele. Fica em components porque duas telas ja
  usam: "Fechar proposta" na simulacao e "Reabrir na consulta" no documento.

  `justify-items: start` porque botao de acao nao estica: dentro de um grid,
  item ocupa a trilha inteira por padrao, e o botao saia de ponta a ponta do
  painel com cara de barra.
*/
.ipr-acao-rodape {
  display: grid;
  justify-items: start;
  gap: var(--space-4);
}

/* O SELO DE "CABE NA FOLHA" vem logo abaixo, e nao colado: ele qualifica os
   dois numeros de cima, e encostado neles parecia legenda do segundo. */
.ipr-oferta + .ipr-nota--topo { margin-block-start: var(--space-4); }
@media (width < 48rem) {
  .ipr-oferta { grid-template-columns: minmax(0, 1fr); }
  .ipr-oferta__item { padding: var(--space-4) var(--space-5); }
}

/* ------------------------------------------------- A LISTA DO SELECT --- */
/*
  A LISTA DE OPCOES DE UM <select> NAO E DESENHADA PELA PAGINA: quem a desenha
  e o sistema operacional, e por isso ela aparece quadrada, com o azul do
  Windows, no meio de uma tela que nao tem nada quadrado nem daquele azul.
  Nenhum CSS de dentro da pagina alcancava aquilo, e e por isso que o campo
  parecia "do sistema" mesmo depois de estilizado por fora.

  `appearance: base-select` troca o desenho nativo por um que a pagina pinta,
  incluindo a lista. Fica DENTRO de `@supports` de proposito: onde o navegador
  nao souber, o campo continua sendo o mesmo <select> de sempre, com a lista
  do sistema. Nada quebra, nada some.

  A alternativa era escrever um seletor proprio em JavaScript, e ai vem tudo
  junto: setas, Home, End, digitar para procurar, foco, fechar ao clicar fora,
  e os papeis de acessibilidade. E o mesmo motivo pelo qual o pop-up daqui e
  `<dialog>` nativo: onde o navegador ja faz, refazer e assinar a manutencao
  de um controle que ele mantem de graca.

  VEM NO FIM DO ARQUIVO porque precisa ganhar das regras de `.ipr-select` e do
  `--sm` la de cima, que reservam espaco para a seta desenhada em background.
*/
@supports (appearance: base-select) {
  .ipr-select,
  .ipr-select::picker(select) { appearance: base-select; }

  .ipr-select {
    /* A seta de background sai: no desenho novo ela existe como elemento
       (`::picker-icon`), e as duas juntas dariam duas setas. */
    background-image: none;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    text-align: start;
  }
  .ipr-select.ipr-field__input--sm,
  .ipr-select { padding-inline-end: var(--space-3); }

  /*
    O TEXTO DA OPCAO ESCOLHIDA NAO PODE VAZAR DO CAMPO.

    Com `base-select` o campo vira caixa flex e o conteudo escolhido entra
    como um item dela. Item de flex nasce com `min-inline-size: auto`, ou
    seja, NAO ENCOLHE abaixo do proprio conteudo: um apelido de tabela
    comprido ("SIAPE Emprestimo / 1,95% / 12x a 96x") crescia para fora da
    borda e passava por cima do campo vizinho. Nao da erro, e so aparece com
    dado de verdade, que e como isto chegou a producao.

    A correcao e a mesma da coluna de grid no celular: deixar encolher
    (`min-inline-size: 0`) e cortar com reticencias. O texto inteiro continua
    na lista, que e onde ele se le.
  */
  /*
    DUAS REGRAS, E NAO UMA LISTA COM OS DOIS SELETORES.

    Seletor invalido INVALIDA A REGRA INTEIRA em CSS: escrito como
    `.ipr-select, .ipr-select::selectedcontent { ... }`, o navegador que nao
    conhece `::selectedcontent` descarta tambem a parte que valia para o
    campo. Foi exatamente o que aconteceu: o Chrome aplicava
    `appearance: base-select` e, ao mesmo tempo, `white-space: normal`, e o
    apelido de tabela comprido continuava quebrando em duas linhas dentro de
    uma caixa de 46px. Medido no navegador, depois de a correcao "nao pegar".

    Separadas, a primeira vale sempre e a segunda so onde o pseudo-elemento
    existir.
  */
  .ipr-select {
    min-inline-size: 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }
  .ipr-select::selectedcontent {
    min-inline-size: 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }
  /* A seta nunca cede espaco para o texto: sem isto ela e o item que encolhe,
     e o chevron sai achatado num campo estreito. */
  .ipr-select::picker-icon { flex: none; }

  /* A MESMA SETA DE SEMPRE. O desenho padrao do picker e um triangulo cheio,
     que nao existe em lugar nenhum do sistema: o mesmo chevron que o campo
     usava em background passa a ser o conteudo do icone. */
  .ipr-select::picker-icon {
    content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23647089' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
    inline-size: 1.1rem;
    block-size: 1.1rem;
    transition: rotate var(--dur-base) var(--ease-out);
  }
  /* Aberta, a seta aponta para cima: e o mesmo gesto do `<details>` do resto
     do sistema. */
  .ipr-select:open::picker-icon { rotate: 180deg; }

  .ipr-select::picker(select) {
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: var(--color-surface-opaco);
    box-shadow: var(--shadow-xl);
    padding: var(--space-1);
    /* Um respiro entre o campo e a lista, senao ela nasce colada na borda. */
    margin-block-start: var(--space-1);
    /* A lista nunca fica mais estreita que o campo que a abriu. */
    min-inline-size: anchor-size(self-inline);
  }
  /*
    So a ENTRADA e animada, e por `@starting-style`, que nao depende de
    nenhum seletor de estado. Escrita como `opacity: 0` na regra de base mais
    um `:open` para acender, um navegador que entendesse `base-select` mas nao
    o `:open` deixaria a lista invisivel, aberta, no meio da tela. Assim o
    pior caso e a lista aparecer sem transicao.
  */
  .ipr-select::picker(select) {
    transition: opacity var(--dur-fast) var(--ease-out),
                translate var(--dur-fast) var(--ease-out);
  }
  @starting-style {
    .ipr-select::picker(select) { opacity: 0; translate: 0 -.25rem; }
  }

  .ipr-select option {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-sm);
    font-size: var(--font-size-md);
    color: var(--color-text-primary);
    background: transparent;
    cursor: pointer;
  }
  /* O teclado percorre a lista com as setas, e o realce dele e o mesmo do
     mouse: dois destaques diferentes para a mesma coisa confundem. */
  .ipr-select option:hover,
  .ipr-select option:focus { background: var(--color-surface-2); outline: none; }
  .ipr-select option:checked {
    color: var(--color-accent-400);
    font-weight: var(--font-weight-semibold);
  }
  /* A marca da escolhida vai para o FIM da linha: no comeco, ela empurraria o
     texto de uma opcao e nao o das outras, e a lista sairia desalinhada. */
  .ipr-select option::checkmark {
    order: 1;
    margin-inline-start: auto;
    color: var(--color-accent-400);
  }
}


/* --- Arquivo enviado pelo usuario --------------------------------------
   A AREA DE SOLTAR E UM <label>: clicar nela abre o seletor sem uma linha de
   JavaScript, e arrastar e acrescimo do modulo. Sem script, continua sendo um
   campo de arquivo comum, com aparencia de area de soltar.

   NASCEU NA CONSULTA e subiu para ca quando a ficha de formalizacao passou a
   receber documento: sao as mesmas duas pecas (a area e a lista do que ja
   foi anexado) nas duas telas. */
.ipr-solta {
  display: grid;
  justify-items: center;
  gap: var(--space-1);
  padding: var(--space-6) var(--space-5);
  border: 1.5px dashed var(--color-border-strong);
  border-radius: var(--radius-lg);
  background: var(--color-surface-2);
  cursor: pointer;
  text-align: center;
  transition: border-color var(--dur-fast), background var(--dur-fast), transform var(--dur-base) var(--ease-expo);
}
.ipr-solta:hover,
.ipr-solta:focus-within,
.ipr-solta.is-sobre {
  border-color: var(--color-accent-500);
  background: var(--color-accent-tint);
}
/* Com o arquivo em cima, a area CRESCE um pouco: e o "pode soltar" que a
   pessoa procura antes de abrir a mao. */
.ipr-solta.is-sobre { transform: scale(1.01); }
.ipr-solta__icone {
  display: grid;
  place-items: center;
  inline-size: 2.5rem;
  block-size: 2.5rem;
  margin-block-end: var(--space-1);
  border-radius: var(--radius-md);
  background: var(--color-surface-1);
  box-shadow: var(--shadow-sm), inset 0 0 0 1px var(--color-border);
  color: var(--color-accent-400);
}
.ipr-solta__titulo {
  font-size: var(--font-size-md);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-primary);
}
.ipr-solta__sub { font-size: var(--font-size-xs); color: var(--color-text-muted); }

.ipr-anexos { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-2); }
.ipr-anexo {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-2) var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border);
  background: var(--color-surface-1);
  box-shadow: var(--shadow-xs);
  font-size: var(--font-size-sm);
}
.ipr-anexo__nome { flex: 1; min-width: 0; overflow-wrap: anywhere; }

.ipr-anexo__icone {
  display: grid;
  place-items: center;
  flex: none;
  inline-size: 2rem;
  block-size: 2rem;
  border-radius: var(--radius-sm);
  background: var(--color-accent-tint);
  color: var(--color-accent-400);
}
.ipr-anexo__icone .ipr-icon { width: 1.125rem; height: 1.125rem; }
.ipr-anexo__texto { flex: 1; min-width: 0; display: grid; gap: 2px; }
.ipr-anexo__sub {
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
  overflow-wrap: anywhere;
}
.ipr-anexo__tamanho {
  color: var(--color-text-muted);
  font-size: var(--font-size-xs);
  font-variant-numeric: tabular-nums;
}


/* ------------------------------------------------------------ CARREGADOR --- */
/*
  O icone da marca respirando, com uma orbita que gira em volta. Para espera
  de segundos, e nao de um clique: o botao tem o indicador dele, a navegacao
  tem a barra do topo, e a espera longa tem isto.

  A orbita e um arco com degrade conico: a cauda some, e o que o olho segue e
  a ponta acesa. Com movimento reduzido ela para, e a marca fica parada no
  centro, que continua dizendo "trabalhando" pelo texto ao lado.
*/
.ipr-carregador {
  --carregador-tam: 4.5rem;
  position: relative;
  display: grid;
  place-items: center;
  inline-size: var(--carregador-tam);
  block-size: var(--carregador-tam);
}
.ipr-carregador__marca {
  inline-size: 58%;
  block-size: auto;
  filter: drop-shadow(0 6px 14px var(--color-accent-tint-strong));
  animation: ipr-respirar 1.6s var(--ease-in-out) infinite alternate;
}
.ipr-carregador__orbita {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: conic-gradient(from 0deg, transparent 0deg, var(--color-accent-tint) 120deg, var(--color-accent-500) 330deg, transparent 360deg);
  /* Um anel, e nao um disco: a mascara apaga o meio e deixa 3px de borda. */
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 calc(100% - 3px));
          mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 calc(100% - 3px));
  animation: ipr-spin 1.1s linear infinite;
}
@keyframes ipr-respirar { from { transform: scale(.92); } to { transform: scale(1.04); } }


/* ------------------------------------------------ PROGRESSO DE NAVEGACAO --- */
/*
  A barra fina no topo da janela enquanto a proxima pagina carrega. O modulo
  `progresso` liga a classe no clique que vai mesmo navegar; quem a desliga e
  a chegada da pagina nova, que nasce sem ela.

  So `transform` e `opacity` animam: a barra roda no compositor e nao disputa
  quadro com a pagina que esta indo embora.
*/
.ipr-progresso {
  position: fixed;
  inset-block-start: 0;
  inset-inline: 0;
  z-index: var(--z-progresso);
  block-size: 3px;
  pointer-events: none;
  background: var(--gradient-hairline);
  background-color: var(--color-accent-500);
  box-shadow: 0 0 10px var(--color-accent-500), 0 0 2px var(--color-accent-400);
  transform: scaleX(0);
  transform-origin: left;
  opacity: 0;
  transition: opacity var(--dur-slow) var(--ease-out);
}
.ipr-progresso.is-ativo {
  opacity: 1;
  animation: ipr-progresso 9s var(--ease-expo) both;
}


/* ------------------------------------------------------------ ESQUELETO --- */
/*
  O LUGAR DO QUE AINDA ESTA CHEGANDO. Quando um pedaco da pagina e refeito
  sem recarregar (o simulador, por exemplo), ele fica com cara de "vindo", e
  nao de "parado": um brilho atravessa o bloco enquanto a resposta nao chega.

  Uso: `.ipr-esqueleto` num bloco qualquer, ou o estado `.is-atualizando`
  que o modulo `atualizar` liga no pedaco que esta sendo refeito.
*/
.ipr-esqueleto {
  border-radius: var(--radius-sm);
  background: linear-gradient(90deg, var(--color-esqueleto) 0%, var(--color-esqueleto-brilho) 50%, var(--color-esqueleto) 100%);
  background-size: 200% 100%;
  animation: ipr-shimmer 1.4s var(--ease-in-out) infinite;
  color: transparent;
}
