/* Movimento do Trecurii (Design Motion Principles: lente Emil + Jakub; produtividade, abaixo de 300 ms).
   Regras: só transform/opacity/filter; entrada mais marcada que saída; curvas customizadas, sem "ease" puro;
   sem animação em ação de teclado nem na troca frequente de página (só entrada curta); tudo respeita prefers-reduced-motion. */
:root{--ease-in:cubic-bezier(.5,0,.75,0);--d-enter:180ms;--d-exit:120ms}

/* ---------- barra de progresso global (aparece após 150 ms de espera por dados) ---------- */
.loadbar{position:fixed;top:0;left:var(--side-w);right:0;height:3px;z-index:var(--z-toast);overflow:hidden;opacity:0;pointer-events:none;transition:opacity var(--d-exit) var(--ease-in)}
.loadbar.on{opacity:1;transition-duration:var(--d-enter)}
.loadbar::before{content:"";position:absolute;inset:0;width:40%;background:var(--green);border-radius:0 3px 3px 0;transform:translateX(-100%)}
.loadbar.on::before{animation:load 1.1s var(--ease) infinite;will-change:transform}   /* sem animação infinita quando escondida */
@keyframes load{to{transform:translateX(260%)}}

/* ---------- skeleton: bloco calmo com brilho que passa (transform), alinhado ao layout real ---------- */
.sk{display:block;position:relative;overflow:hidden;background:var(--line);border-radius:6px;max-width:100%}
.sk::after{content:"";position:absolute;inset:0;transform:translateX(-100%);background:linear-gradient(90deg,transparent,color-mix(in srgb,var(--ink) 9%,transparent),transparent);animation:shimmer 1.4s var(--ease) infinite}
@keyframes shimmer{to{transform:translateX(100%)}}
[data-skeleton] .card,[data-skeleton] .metric{pointer-events:none}
.metric strong.sk-b{padding:7.65px 0}   /* mesma altura do número real (49,3 px); padding em vez de margem evita colapso */
.sk-xs,.sk-sm{display:none}
@container page (max-width:520px){.sk-xs,.sk-sm{display:block}.metric strong.sk-b{padding:0}}
@container page (min-width:700px) and (max-width:800px){.sk-sm{display:block}}

/* ---------- entrada de tela e atualização suave ---------- */
.page-in{animation:enter var(--d-enter) var(--ease) both}
@keyframes enter{from{opacity:0;transform:translateY(8px)}}
/* Um único momento orquestrado, só no Início e só sem skeleton: 3 grupos (hero, indicadores, listas) em sequência curta (40 ms). O texto estático não anima. */
.seq{animation:enter 220ms var(--ease) both;animation-delay:calc(var(--i,0) * 40ms)}
/* Depois do skeleton (ou numa atualização) o layout já está na tela: só os dados fazem fade, sem deslocamento. */
.from-skeleton .data-in{animation:fade-in 150ms var(--ease) both}
.from-skeleton .seq,.soft .seq,.soft .progress span{animation:none}
.content{transition:opacity var(--d-exit) var(--ease)}
.content.refreshing{opacity:.55}

/* ---------- modal: entra com opacidade + deslocamento + blur leve; sai mais curto e sutil ---------- */
dialog.modal[open]{animation:modal-in var(--d-enter) var(--ease)}
dialog.modal.leaving{animation:modal-out var(--d-exit) var(--ease-in) forwards;pointer-events:none}
dialog[open]::backdrop{animation:fade-in var(--d-enter) var(--ease)}
dialog.leaving::backdrop{animation:fade-out var(--d-exit) var(--ease-in) forwards}
@keyframes modal-in{from{opacity:0;transform:translateY(8px) scale(.98);filter:blur(3px)}}
@keyframes modal-out{to{opacity:0;transform:translateY(-4px) scale(.99)}}
@keyframes fade-in{from{opacity:0}}
@keyframes fade-out{to{opacity:0}}
.swap-in{animation:fade-in var(--d-enter) var(--ease)}

/* ---------- avisos, itens que entram e saem ---------- */
.toast{animation:toast-in var(--d-enter) var(--ease)}
.toast.leaving{animation:toast-out var(--d-exit) var(--ease-in) forwards}
@keyframes toast-in{from{opacity:0;transform:translateY(8px)}}
@keyframes toast-out{to{opacity:0;transform:translateY(4px)}}
.leaving:not(dialog):not(.toast){animation:item-out var(--d-exit) var(--ease-in) forwards;pointer-events:none}
@keyframes item-out{to{opacity:0;transform:translateX(-8px)}}
.check.enter,.comment.enter{animation:item-in var(--d-enter) var(--ease)}
@keyframes item-in{from{opacity:0;transform:translateY(6px)}}
.ticket.landed{animation:land 220ms var(--ease)}
@keyframes land{from{opacity:.4;transform:scale(.97)}}

/* ---------- feedback de ação ---------- */
.row[aria-busy=true]{opacity:.55;transition:opacity 120ms var(--ease)}
.btn:active:not(:disabled){transform:scale(.97)}
.done-box.on svg{animation:pop 140ms var(--ease)}
@keyframes pop{from{opacity:0;transform:scale(.6)}}
#theme svg.swap{animation:icon-swap var(--d-enter) var(--ease)}
@keyframes icon-swap{from{opacity:0;transform:scale(.8) rotate(-20deg);filter:blur(2px)}}
/* Botão aguardando resposta: anel girando, para o clique nunca parecer ignorado. */
.btn[aria-busy=true]::before{content:"";width:11px;height:11px;border:2px solid currentColor;border-right-color:transparent;border-radius:50%;animation:spin .7s linear infinite;flex:none}
@keyframes spin{to{transform:rotate(360deg)}}

/* ---------- progresso: barra cresce por transform, não por largura ---------- */
.progress span{width:100%;transform:scaleX(var(--p,0));transform-origin:left;animation:grow 480ms var(--ease) both}
@keyframes grow{from{transform:scaleX(0)}}
.stage{animation:fade-in var(--d-enter) var(--ease) both}

@media (max-width:900px){.loadbar{left:0}}
@media (prefers-reduced-motion:reduce){
  .sk::after{animation:none;transform:none;background:none}
  .loadbar::before{animation:none;transform:none;width:100%;opacity:.7}
  .btn[aria-busy=true]::before{animation:none}
}

/* Troca de tema "líquida" (theme-liquid.js): o tema novo é revelado por uma máscara; nada de cross-fade nem de transições de cor durante a troca. */
html[data-liquid]::view-transition-old(root),html[data-liquid]::view-transition-new(root){animation:none;mix-blend-mode:normal}
html[data-liquid]::view-transition-old(root){z-index:1}
html[data-liquid]::view-transition-new(root){z-index:2}
html[data-liquid] *,html[data-liquid] *::before,html[data-liquid] *::after{transition:none!important}
