/* e-PGM · camada de movimento.
 *
 * Carregada depois de vidro.css. Acrescenta transições curtas às mudanças de
 * estado que já existem (tela nova, dossiê, janelas, seções recolhíveis,
 * gravação confirmada, carregamento). Não altera regras, dados nem o leiaute
 * final das telas; o único desenho estático novo é a seta das seções
 * recolhíveis, no lugar do triângulo nativo. Remover o <link> deste arquivo e
 * o <script> de movimento.js devolve o comportamento anterior sem nenhum
 * outro efeito.
 *
 * Princípios:
 *   - curto e com propósito: 140 a 320 ms, saída com mola e sem ricochete;
 *   - nunca adia o momento em que o conteúdo pode ser usado: tudo entra já no
 *     DOM e clicável, e o fechamento continua instantâneo;
 *   - só opacidade e deslocamento, que a placa de vídeo compõe sem refazer o
 *     leiaute. Sombra não é animada em listas densas;
 *   - com "reduzir movimento" ativo no sistema operacional, nada é animado:
 *     todas as animações ficam dentro de (prefers-reduced-motion: no-preference). */

/* ---------- tokens ---------- */

:root {
  --mov-curva: cubic-bezier(.2, .8, .2, 1);
  --mov-rapido: 140ms;
  --mov-curto: 200ms;
  --mov-medio: 260ms;
  --mov-longo: 320ms;
  --mov-osso: rgba(15, 23, 42, .075);
  --mov-osso-luz: rgba(15, 23, 42, .025);
  --mov-verde: #34c759;
}
html[data-tema="escuro"] {
  --mov-osso: rgba(255, 255, 255, .07);
  --mov-osso-luz: rgba(255, 255, 255, .14);
  --mov-verde: #30d158;
}

/* ---------- elementos estáticos usados pelo movimento.js ----------
 * Valem também com "reduzir movimento": não animam nada por si. */

/* Seta de abertura das seções recolhíveis. O script só marca o sumário que
 * exibia o triângulo nativo e não usava ::before; a seta nova ocupa o mesmo
 * lugar e gira em vez de trocar de desenho. */
summary[data-mov-seta] { list-style: none; }
summary[data-mov-seta]::-webkit-details-marker { display: none; }
summary[data-mov-seta]::before {
  content: ""; display: inline-block; box-sizing: border-box; flex: none;
  width: .47em; height: .47em; margin: 0 .56em 0 .1em; vertical-align: .12em;
  border: solid currentColor; border-width: 0 .15em .15em 0; border-radius: 0 0 1.5px 0;
  rotate: -45deg;
}
details[open] > summary[data-mov-seta]::before { rotate: 45deg; vertical-align: .2em; }

/* Contagem dos indicadores: o número real continua no documento (leitores de
 * tela, cópia, testes e o próprio sistema leem sempre o valor exato); durante
 * meio segundo o que se vê é a camada sobreposta, que não ocupa espaço. */
.mov-contando { position: relative; -webkit-text-fill-color: transparent; }
.mov-contando::after {
  content: attr(data-mov-contagem);
  content: attr(data-mov-contagem) / "";
  position: absolute; inset: 0; white-space: nowrap; text-align: inherit;
  -webkit-text-fill-color: currentColor; pointer-events: none;
}

/* Âncora para o selo de gravação, só em botões sem posicionamento próprio. */
.mov-salvo-ancora { position: relative; }

@media (prefers-reduced-motion: no-preference) {

  /* ---------- entrada de tela e chegada de conteúdo ----------
   * Classes alternadas (-a/-b) com o mesmo desenho: trocar de uma para a
   * outra reinicia a animação sem forçar leiaute. O script retira a classe
   * ao terminar. */

  .mov-entrada-a { animation: mov-entrar-a var(--mov-curto) var(--mov-curva); }
  .mov-entrada-b { animation: mov-entrar-b var(--mov-curto) var(--mov-curva); }
  #lateralCorpo.mov-entrada-a { animation: mov-subir-a var(--mov-longo) var(--mov-curva); }
  #lateralCorpo.mov-entrada-b { animation: mov-subir-b var(--mov-longo) var(--mov-curva); }
  .mov-chegada-a { animation: mov-chegar-a var(--mov-curto) var(--mov-curva); }
  .mov-chegada-b { animation: mov-chegar-b var(--mov-curto) var(--mov-curva); }

  @keyframes mov-entrar-a { from { opacity: 0; translate: 0 6px; } }
  @keyframes mov-entrar-b { from { opacity: 0; translate: 0 6px; } }
  @keyframes mov-subir-a { from { opacity: 0; translate: 0 12px; } }
  @keyframes mov-subir-b { from { opacity: 0; translate: 0 12px; } }
  @keyframes mov-chegar-a { from { opacity: 0; translate: 0 4px; } }
  @keyframes mov-chegar-b { from { opacity: 0; translate: 0 4px; } }

  /* ---------- dossiê em tela inteira ----------
   * O painel surge por cima da tela (a barra de cima vem junto); o corpo sobe
   * pelo movimento.js. Fechar continua instantâneo. */

  #painelLateral:not(.oculto) { animation: mov-aparecer var(--mov-curto) var(--mov-curva); }

  @keyframes mov-aparecer { from { opacity: 0; } }

  /* ---------- janelas ---------- */

  .modal-seguro:not(.oculto) { animation: mov-aparecer var(--mov-curto) var(--mov-curva); }
  .modal-seguro:not(.oculto) > .cartao-modal { animation: mov-janela var(--mov-medio) var(--mov-curva); }
  dialog[open] { animation: mov-janela var(--mov-medio) var(--mov-curva); }
  dialog[open]::backdrop { animation: mov-aparecer var(--mov-curto) var(--mov-curva); }

  @keyframes mov-janela { from { opacity: 0; scale: .97; translate: 0 6px; } }

  /* Menu do usuário e cartão de operação: descem alguns pixels ao surgir. */
  .menu-usuario[open] > .menu-usuario-painel {
    transform-origin: top right;
    animation: mov-descer-menu var(--mov-curto) var(--mov-curva);
  }
  .operacao-global:not(.oculto) { animation: mov-descer var(--mov-medio) var(--mov-curva); }

  @keyframes mov-descer-menu { from { opacity: 0; scale: .98; translate: 0 -4px; } }
  @keyframes mov-descer { from { opacity: 0; translate: 0 -8px; } }

  /* ---------- seções recolhíveis ----------
   * Altura animada só quando a pessoa clica no sumário (o script marca a
   * seção por um instante com data-mov-animar). Aberturas feitas pelo sistema
   * (seção lembrada, "Ir para", campo inválido) seguem instantâneas, para
   * não deslocar a página depois de pronta nem atrapalhar a rolagem. */

  @supports (interpolate-size: allow-keywords) and selector(::details-content) {
    :is(#conteudo, #lateralCorpo) details { interpolate-size: allow-keywords; }
    /* Fechada, a área de conteúdo já mede zero; declarar o zero dá o ponto de
     * partida da transição. Sem efeito visual fora dela. */
    :is(#conteudo, #lateralCorpo) details:not([open])::details-content { block-size: 0; }
    :is(#conteudo, #lateralCorpo) details[data-mov-animar]::details-content {
      overflow-y: clip;
      transition: block-size var(--mov-medio) var(--mov-curva),
        content-visibility var(--mov-medio) allow-discrete;
    }
    /* Altura em pixels prende a margem inferior do último bloco, que na
     * altura automática escaparia para o respiro da seção: um décimo de pixel
     * de respiro faz a medida automática já incluí-la (movimento.js só marca
     * "contida" a seção cujo respiro ou borda inferior guardaria essa margem). */
    :is(#conteudo, #lateralCorpo) details[data-mov-animar="contida"]::details-content {
      padding-block-end: .1px;
    }
    /* Seção sem respiro: a margem do último bloco escaparia para fora dela
     * no fim; a área que cresce já a leva desde o início (valor medido pelo
     * movimento.js no clique). */
    :is(#conteudo, #lateralCorpo) details[data-mov-animar="livre"]::details-content {
      margin-block-end: var(--mov-margem-final, 0px);
    }
    /* Ao fechar, a margem do primeiro bloco fica dentro da área que encolhe
     * (senão sumia de uma vez no último quadro). O acréscimo que isso causa,
     * medido pelo movimento.js no clique, é anulado por margem negativa que
     * volta a zero no mesmo ritmo da altura. */
    :is(#conteudo, #lateralCorpo) details[data-mov-animar="fechando"]::details-content {
      padding-block-start: .1px;
      margin-block-start: calc(-1 * var(--mov-compensar, 0px));
      animation: mov-compensar var(--mov-medio) var(--mov-curva) forwards;
    }
    @keyframes mov-compensar { to { margin-block-start: 0; } }
  }
  :is(#conteudo, #lateralCorpo) details[data-mov-animar] > summary[data-mov-seta]::before {
    transition: rotate var(--mov-medio) var(--mov-curva), vertical-align var(--mov-medio) var(--mov-curva);
  }

  /* ---------- botões, abas e controles ----------
   * Especificidade mínima (só a etiqueta): onde as outras camadas já declaram
   * transições próprias, elas prevalecem. Aqui só se preenche o que mudava de
   * estado sem transição. A etiqueta fica na ponta do seletor de propósito:
   * assim o navegador só confere botões, links e sumários, não a página toda. */

  :where(#conteudo, #lateralCorpo, .cartao-modal, dialog, .lateral-topo) button,
  :where(#conteudo, #lateralCorpo, .cartao-modal, dialog, .lateral-topo) a,
  :where(#conteudo, #lateralCorpo, .cartao-modal, dialog, .lateral-topo) summary {
    transition-property: color, background-color, border-color, box-shadow, opacity, transform;
    transition-duration: var(--mov-rapido);
    transition-timing-function: var(--mov-curva);
  }
  /* Mesmos tempos da camada vidro, com a pressão incluída. */
  .abas button {
    transition: background-color .18s ease, color .18s ease, box-shadow .18s ease,
      transform .1s var(--mov-curva);
  }
  .grupo-secundario button {
    transition: color .15s ease, box-shadow .2s ease, background-color .15s ease,
      transform .1s var(--mov-curva);
  }
  .usuario-topo button {
    transition: background-color .15s ease, color .15s ease, transform .1s var(--mov-curva);
  }
  .abas button:active, .grupo-secundario button:active, .usuario-topo button:active,
  .lateral-topo button:active:not(:disabled), .sub-abas button:active:not(:disabled),
  .busca-topo button:active, .ui-indice-dossie a:active { transform: scale(.98); }
  .busca-topo button { transition: background-color .15s ease, transform .1s var(--mov-curva); }

  /* Cartões clicáveis: sobem 1 px ao passar o mouse e cedem ao toque. */
  .painel-indicadores .indicador-link {
    transition: transform .2s var(--mov-curva), border-color .2s ease, box-shadow .2s ease,
      background-color .2s ease;
  }
  .painel-indicadores .indicador-link:active { transform: scale(.985); }
  .fluxo-dlc-card { transition: transform .2s var(--mov-curva), border-color .2s ease; }

  /* Opções em cartão (acesso da publicação): escolha com transição. */
  .opcoes-acesso-publicacao > label {
    transition: border-color .2s ease, background-color .2s ease, box-shadow .2s ease,
      transform .12s var(--mov-curva);
  }
  .opcoes-acesso-publicacao > label:active { transform: scale(.99); }

  /* Anel de foco do teclado: chega de fora para dentro em vez de acender.
   * Regras com :focus-visible só são conferidas no elemento em foco. */
  :where(#conteudo, #lateralCorpo, .cartao-modal, dialog, .navegacao-sistema, .topo, .lateral-topo)
    :where(button, a, summary, [role="tab"], [tabindex]:not([tabindex="-1"])):focus-visible {
    animation: mov-foco .18s var(--mov-curva);
  }
  @keyframes mov-foco { from { outline-color: transparent; outline-offset: 6px; } }

  /* ---------- gravação confirmada ----------
   * Selo com visto no canto do botão que disparou a gravação, por menos de um
   * segundo. O texto e o estado do botão não mudam. */

  button:is(.mov-salvo-a, .mov-salvo-b)::after {
    content: "✓";
    content: "✓" / "";
    position: absolute; z-index: 2; top: -7px; right: -7px;
    display: grid; place-items: center; width: 18px; height: 18px; border-radius: 50%;
    background: var(--mov-verde); color: #fff; -webkit-text-fill-color: #fff;
    font: 700 11px/1 var(--fonte-interface, system-ui, sans-serif);
    letter-spacing: 0; text-indent: 0; text-transform: none; pointer-events: none;
    animation: mov-selo-a .95s var(--mov-curva) both;
  }
  button.mov-salvo-b::after { animation-name: mov-selo-b; }

  @keyframes mov-selo-a {
    0% { opacity: 0; scale: .55; box-shadow: 0 0 0 2px var(--papel), 0 0 0 2px rgba(52, 199, 89, .5); }
    22% { opacity: 1; scale: 1; }
    60% { box-shadow: 0 0 0 2px var(--papel), 0 0 0 9px rgba(52, 199, 89, 0); }
    78% { opacity: 1; scale: 1; }
    100% { opacity: 0; scale: .9; box-shadow: 0 0 0 2px var(--papel), 0 0 0 9px rgba(52, 199, 89, 0); }
  }
  @keyframes mov-selo-b {
    0% { opacity: 0; scale: .55; box-shadow: 0 0 0 2px var(--papel), 0 0 0 2px rgba(52, 199, 89, .5); }
    22% { opacity: 1; scale: 1; }
    60% { box-shadow: 0 0 0 2px var(--papel), 0 0 0 9px rgba(52, 199, 89, 0); }
    78% { opacity: 1; scale: 1; }
    100% { opacity: 0; scale: .9; box-shadow: 0 0 0 2px var(--papel), 0 0 0 9px rgba(52, 199, 89, 0); }
  }

  /* ---------- carregamento ----------
   * Esqueleto com brilho no lugar do "Carregando…" solto. O texto continua
   * visível como legenda (e para leitores de tela). Só aparece se a espera
   * passar de 140 ms: carregamento rápido não pisca. Substitui o giro da
   * camada vidro. */

  .carregando {
    display: flex; flex-direction: column; gap: 12px;
    padding: 16px 0 18px; text-align: left;
    color: var(--tinta-terciaria); font-size: 12.5px; line-height: 1.4;
    animation: mov-aparecer var(--mov-medio) var(--mov-curva) 140ms backwards;
  }
  .carregando[hidden] { display: none; }
  .carregando::before {
    content: ""; display: block; flex: none;
    width: auto; height: 67px; margin: 0; border: 0; border-radius: 0; vertical-align: baseline;
    background: linear-gradient(100deg, var(--mov-osso) 38%, var(--mov-osso-luz) 50%, var(--mov-osso) 62%) 0 0 / 250% 100%;
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Crect width='36%25' height='12' rx='6'/%3E%3Crect y='24' width='100%25' height='9' rx='4.5'/%3E%3Crect y='41' width='90%25' height='9' rx='4.5'/%3E%3Crect y='58' width='64%25' height='9' rx='4.5'/%3E%3C/svg%3E") 0 0 / 100% 100% no-repeat;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Crect width='36%25' height='12' rx='6'/%3E%3Crect y='24' width='100%25' height='9' rx='4.5'/%3E%3Crect y='41' width='90%25' height='9' rx='4.5'/%3E%3Crect y='58' width='64%25' height='9' rx='4.5'/%3E%3C/svg%3E") 0 0 / 100% 100% no-repeat;
    animation: mov-brilho 1.6s linear infinite;
  }
  /* Tela inteira ou dossiê inteiro: título, cartão e linhas. */
  :is(#conteudo, #lateralCorpo) > .carregando:only-child { padding: 4px 0 18px; }
  :is(#conteudo, #lateralCorpo) > .carregando:only-child::before {
    height: 236px;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Crect y='2' width='26%25' height='22' rx='7'/%3E%3Crect y='36' width='42%25' height='11' rx='5.5'/%3E%3Crect y='70' width='100%25' height='104' rx='16'/%3E%3Crect y='190' width='100%25' height='10' rx='5'/%3E%3Crect y='208' width='86%25' height='10' rx='5'/%3E%3Crect y='226' width='58%25' height='10' rx='5'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Crect y='2' width='26%25' height='22' rx='7'/%3E%3Crect y='36' width='42%25' height='11' rx='5.5'/%3E%3Crect y='70' width='100%25' height='104' rx='16'/%3E%3Crect y='190' width='100%25' height='10' rx='5'/%3E%3Crect y='208' width='86%25' height='10' rx='5'/%3E%3Crect y='226' width='58%25' height='10' rx='5'/%3E%3C/svg%3E");
  }

  @keyframes mov-brilho { from { background-position: 100% 0; } to { background-position: 0 0; } }

  /* ---------- rolagem ----------
   * Suave só no salto pelo índice do dossiê; o script liga e desliga a
   * classe, para não suavizar a restauração de posição feita após as ações. */

  #lateralCorpo.mov-rolagem-suave { scroll-behavior: smooth; }
}
