/* ============================================================
   LETHAL · Movimento
   ------------------------------------------------------------
   ESTE ARQUIVO E O DONO UNICO DO MOVIMENTO DO SITE: toda entrada e
   TODO hover moram aqui, e nenhum outro CSS escreve `:hover`.

   POR QUE JUNTO, e nao cada hover ao lado do seu componente: porque
   movimento so vira sistema quando da para LER O SISTEMA INTEIRO DE
   UMA VEZ. Espalhado, cada componente ganha o seu jeitinho, e em tres
   meses o site tem seis vocabularios de hover e nenhum dono. Aqui a
   pergunta "como este site responde ao mouse?" tem um arquivo por
   resposta. Cada componente ficou com um comentario apontando para ca.

   NENHUM VALOR NASCE AQUI. Duracao, atraso, curva, escala e veu sao
   tokens do tokens.css (FUNDACAO.md 4.1).

   ------------------------------------------------------------
   O VOCABULARIO, e sao quatro palavras. Nao existe uma quinta.
   ------------------------------------------------------------
   1. ACENDE     texto de apoio vira texto forte. Link de menu, rodape,
                 idioma, voltar, terciario, link editorial.
   2. QUADRO     o conteudo cresce DENTRO do proprio quadro, ocupando o
                 espaco negativo. O quadro nao cresce e nao empurra
                 nada. Foto de peca, foto da pagina e o mark.
   3. PREENCHE   uma varredura de claro atravessa ou sobe e completa o
                 elemento, em vez de a cor trocar de uma vez. Botao,
                 filtro, chip de tamanho.
   4. ENTRA      opacidade mais um deslocamento curto para cima, em
                 cascata, quando o bloco chega na tela.

   E A ESPERA NAO E A QUINTA. A secao 6 deste arquivo desenha o botao
   que esta trabalhando, e ela reusa a TERCEIRA palavra em regime
   continuo: a mesma varredura, no mesmo sentido, que so nao chega ao
   fim. Se ela tivesse virado gesto proprio, o vocabulario passaria a
   ter cinco palavras para quatro ideias.

   O SENTIDO DA VARREDURA E O DA FORMA:
     largo (botao, filtro, chip)  → da ESQUERDA para a DIREITA, que e o
                                    sentido da leitura
     alto  (quadro 4:5, foto)     → de BAIXO para CIMA

   ------------------------------------------------------------
   AS TRES TRAVAS
   ------------------------------------------------------------
   1. TODO hover vive dentro de `@media (hover: hover)`. No celular e
      no tablet o iOS gruda o estado de hover ate a pessoa tocar em
      outro lugar, e o botao fica aceso sozinho, sem ninguem ali.
      Feedback de toque e `:active`, e ele esta no fim deste arquivo.
   2. A cascata so ESCONDE dentro de `prefers-reduced-motion:
      no-preference`. Quem pede menos movimento nao recebe conteudo
      invisivel esperando um script: recebe a pagina pronta.
   3. Nada de biblioteca. A CSP e `script-src 'self'` (FUNDACAO.md 5):
      nao entra GSAP, nao entra AOS, nao entra CDN nenhum. CSS mais um
      IntersectionObserver de 60 linhas fazem tudo o que esta aqui.
   ============================================================ */


/* ============================================================
   1. ACENDE
   O gesto mais barato do sistema, e o mais usado: o que estava em tom
   de apoio vai para o tom forte. Sem caixa, sem fundo, sem sublinhado
   novo. A duracao e `--transicao`, que e a de troca de cor.
   ============================================================ */
@media (hover: hover) {
  /* `.nav a` saiu daqui em 5/ago: o menu de texto do topo deixou de existir
     (ver a nota no base.css). O rodape assumiu a navegacao e ja estava nesta
     lista, entao o acender continua igual onde ele passou a morar. */
  .rodape__links a:hover,
  .voltar:hover,
  .btn--terciario:hover,
  .sacola:hover,
  /* Os dois icones do topo acendem pelo `color`, e nao por uma regra
     propria: o desenho e `background: currentColor` (ver .icone no
     componentes.css), entao ele segue a cor do botao ou do link que o
     carrega, sem uma segunda linha aqui para cada icone novo. */
  .conta:hover,
  .busca-abrir:hover,
  .guardar:hover,
  /* ⚠️ `a.` E OBRIGATORIO AQUI. O mesmo nome de classe serve as duas
     gavetas, e na da SACOLA ele e um <span>: sem o `a.`, o nome da peca
     acenderia numa lista onde ele nao leva a lugar nenhum, que e acender
     prometendo clique. Na dos guardados ele e link e e o caminho
     primario da linha. */
  a.gaveta__nome:hover,
  .busca__link:hover .busca__nome,
  .fechar:hover,
  .tirar:hover,
  .bloco__botao:hover .bloco__editar,
  .quantidade__btn:not(:disabled):hover,
  .idioma__op:not([aria-current="true"]):hover,
  .idioma-porta:hover,
  .idioma-linha:not([aria-current="true"]):hover,
  .pais-linha:not([aria-current="true"]):hover { color: var(--paper); }
  /* A sigla acende junto com a linha, senao ela fica para tras no meio do
     movimento e a linha parece acender pela metade. O DDI do painel de paises
     e a mesma peca com outro nome, e acende pelo mesmo motivo. */
  .idioma-linha:hover .idioma-linha__sigla { color: var(--paper); }
  .pais-linha:hover .pais-linha__ddi { color: var(--paper); }
  /* O chevron cai dois pixels: e o mesmo gesto do painel, que desce. */
  .idioma-porta:hover .idioma-porta__chevron { transform: translateY(0) rotate(45deg); }

  /* Terciario nunca desenha caixa, nem no hover. So muda de cor. */
  .btn--terciario:hover { background: transparent; }

  /* Link editorial: quem acende e a LINHA de baixo, que ja existe em
     tom de apoio. O texto ja esta no tom forte. */
  .link-seta:hover { border-color: var(--paper); }
  .faixa--claro .link-seta:hover { border-bottom-color: var(--ink); }

  /* A seta do cartao e o unico sinal de "isto e clicavel" que ele tem,
     entao ela acende junto com o resto do cartao. */
  .card__link:hover .card__seta { border-color: var(--paper); }

  /* A linha de pedido dentro da conta segue a mesma regra do cartao: quem
     acende e a seta, que e o unico sinal de que a linha inteira e um link. A
     porta do painel e a mesma linha, entao e a mesma regra. */
  .conta-pedido__link:hover .conta-pedido__seta,
  .conta-porta__link:hover .conta-porta__seta { border-color: var(--paper); }

  /* O caminho de volta ACENDE, que e a primeira palavra do vocabulario: ele ja
     vive em tom de apoio, entao subir para o tom cheio e o gesto inteiro. A
     seta acompanha sozinha, porque ela e desenhada com `currentColor`. */
  .conta-voltar:hover { color: var(--paper); }

  /* ---- O guardar PREENCHE, e nao e uma quinta palavra ----
     O vocabulario tem quatro (acende, quadro, preenche, entra) e este
     botao usa duas delas ao mesmo tempo, que e o que a peca pede: a cor
     sobe (acende, na lista la em cima) e o desenho se preenche.

     O preenchimento aqui e literal, e nao metafora: a mascara troca do
     marcador vazado para o marcador cheio, que e EXATAMENTE o desenho
     em que o clique vai parar. E a mesma promessa que o chip de tamanho
     ja fazia, escrita no componentes.css: "o preenchimento e uma previa
     exata do que o clique faz, ele para no mesmo desenho do :checked".

     ⚠️ SO NO QUE NAO ESTA GUARDADO. O que ja esta guardado nao preenche
     porque ja esta preenchido, e prometer de novo o que ja aconteceu e
     o defeito que a mesma regra do chip evita.

     ⚠️ E SO NO QUE GUARDA. O `[data-guardar]` no seletor nao e enfeite:
     a porta do cabecalho usa a mesma classe `.guardar` e NAO guarda nada,
     e um marcador que se preenche quando o dedo passa por cima dela
     prometeria salvar alguma coisa que aquele clique nao salva. Preencher
     e a previa do clique, entao so preenche quem vai ficar preenchido. */
  .guardar[data-guardar]:not([aria-pressed="true"]):hover .icone--guardar {
    -webkit-mask-image: url("/assets/icones/marcador-cheio.svg?v=20260806c");
            mask-image: url("/assets/icones/marcador-cheio.svg?v=20260806c");
  }
  /* Na pagina da peca ele tem caixa, e caixa acende pela borda, igual ao
     .btn--secundario de onde a borda veio. */
  .guardar--caixa:hover { border-color: var(--paper); }
}


/* ============================================================
   2. QUADRO · o conteudo cresce dentro do proprio quadro
   ------------------------------------------------------------
   Quem cresce e o que esta DENTRO, nunca a caixa. O quadro fica do
   mesmo tamanho, o layout nao se mexe um pixel, e nada empurra nada
   (FUNDACAO.md 10: nada de layout pulando). E por isso que o efeito e
   `transform`, que nao participa do layout, e nunca `width` ou `zoom`.

   Os quadros de foto ja tem `overflow: hidden`, entao a imagem cresce
   e o excedente e cortado pela propria moldura.

   O mark nao tem moldura para cortar: o "espaco negativo" dele e a
   folga que ja existe ao redor da letra no cabecalho e no rodape.
   Como transform nao empurra nada, 6% cabem sem encostar em ninguem.
   ============================================================ */
@media (hover: hover) {
  .card__quadro img,
  .peca__foto img {
    transition: transform var(--preenche-dur) var(--mov-curva);
  }
  .card__link:hover .card__quadro img,
  .peca__foto:hover img { transform: scale(var(--zoom-quadro)); }

  .marca__mark,
  .rodape__marca img { transition: transform var(--transicao); }
  .marca:hover .marca__mark,
  .rodape__marca:hover img { transform: scale(var(--zoom-mark)); }
}


/* ============================================================
   3. PREENCHE · a varredura de claro
   ------------------------------------------------------------
   O elemento nao troca de cor de uma vez: ele PREENCHE, como se
   estivesse carregando. Num site preto e branco o unico "mais claro"
   que existe e o papel, entao o preenchimento e ele, e nunca uma cor
   nova (nao existe cor terciaria neste sistema).

   COMO E FEITO, e por que assim: uma camada `::before` de tamanho
   inteiro com `transform: scaleX(0)` e origem na esquerda. Escala e
   opacidade sao as duas unicas coisas que o navegador anima sem
   recalcular layout; animar `width` ou `background-size` cobraria um
   recalculo por quadro em cada botao da tela.

   `inset: 0` cobre a CAIXA DE RECHEIO, e nao a borda: a borda do botao
   de contorno continua sendo dela, e acende por conta propria.
   ============================================================ */

/* ---- 3a. O grupo que INVERTE o rotulo ----
   Botao secundario, filtro nao marcado e chip de tamanho nao marcado.
   Os tres terminam a varredura preenchidos de papel, e papel com
   rotulo de papel em cima nao se le.

   A INVERSAO E FEITA COM `mix-blend-mode: difference`, e a escolha tem
   motivo. A alternativa obvia e trocar a cor do rotulo por transicao,
   e ela tem um defeito que so aparece no meio do caminho: a varredura
   leva 320ms atravessando, e a cor troca de uma vez em algum instante
   dela. No instante errado o rotulo fica escuro sobre a metade que
   ainda nao foi preenchida, ou seja, ilegivel por uma fracao de
   segundo, e sempre no meio de um botao que a pessoa esta prestes a
   clicar.

   Com `difference`, cada pixel se resolve sozinho: onde a varredura ja
   passou o rotulo e escuro, onde ainda nao passou ele e claro. Nao
   existe instante errado porque nao existe instante nenhum: e uma
   consequencia da posicao, nao do tempo. Papel (#f2f1ed) menos papel
   da preto puro, entao o rotulo preenchido fica em 18:1 contra o
   fundo, bem acima do piso de 4,5:1 (FUNDACAO.md 4.2).

   O `isolation: isolate` e obrigatorio: sem ele a mistura vazaria para
   o fundo da secao inteira. Com ele, ela para na borda do botao.

   `@supports` porque o dia em que o navegador nao souber misturar, o
   certo e nao preencher: fica o hover de acender a borda, que e o que
   o site fazia antes e continua legivel. Preencher sem inverter seria
   entregar um botao branco com rotulo branco. */
@supports (mix-blend-mode: difference) {
  @media (hover: hover) {
    .btn--secundario,
    .filtro[aria-pressed="false"],
    .tamanho input:not(:disabled):not(:checked) + span,
    .opcao input:not(:disabled):not(:checked) + .opcao__caixa {
      position: relative;
      isolation: isolate;
    }
    .btn--secundario::before,
    .filtro[aria-pressed="false"]::before,
    .tamanho input:not(:disabled):not(:checked) + span::before,
    .opcao input:not(:disabled):not(:checked) + .opcao__caixa::before {
      content: "";
      position: absolute;
      inset: 0;
      background: var(--paper);
      /* Acima do rotulo, de proposito: e do rotulo que ela precisa
         para inverter. Sem `mix-blend-mode` ela o cobriria, e e
         exatamente por isso que este bloco inteiro vive dentro do
         @supports. */
      mix-blend-mode: difference;
      pointer-events: none;
      transform: scaleX(0);
      transform-origin: left center;
      transition: transform var(--preenche-dur) var(--mov-curva);
    }
    /* Mesma trava do 3b: botao travado casa com `:hover` no navegador, e
       preencher um travado seria prometer um clique que nao existe. */
    .btn--secundario:not(:disabled):not([aria-disabled="true"]):hover::before,
    .filtro[aria-pressed="false"]:not(:disabled):hover::before,
    .tamanho input:not(:disabled):not(:checked):hover + span::before,
    .opcao input:not(:disabled):not(:checked):hover + .opcao__caixa::before {
      transform: scaleX(1);
    }
  }
}

/* A borda acende junto, e ela acende SEMPRE, com ou sem mistura. E ela
   que segura o hover inteiro no navegador que caiu fora do @supports.

   O `:not(:disabled)` tambem vale aqui, e por um motivo de ordem: o
   `.btn:disabled` do componentes.css apaga a borda do botao travado, e
   este arquivo carrega DEPOIS dele com a mesma especificidade. Sem a
   trava, o hover devolveria a borda que o travado tinha acabado de
   perder, e um botao que nao da para clicar acenderia. */
@media (hover: hover) {
  .btn--secundario:not(:disabled):not([aria-disabled="true"]):hover { border-color: var(--paper); }
  .filtro[aria-pressed="false"]:not(:disabled):hover { color: var(--paper); border-color: var(--paper); }
  .tamanho input:not(:disabled):not(:checked):hover + span { border-color: var(--paper); }
  .opcao input:not(:disabled):not(:checked):hover + .opcao__caixa { border-color: var(--paper); }
}

/* O campo tem hover, e ele e o mais discreto do sistema: a borda sobe do
   fio para o papel. Nao e PREENCHE, e nao pode ser: preencher um campo de
   claro apagaria o que a pessoa escreveu. Um campo com erro nao responde ao
   mouse, porque a borda dele ja esta no papel inteiro dizendo outra coisa. */
@media (hover: hover) {
  .campo__caixa:not(:disabled):not([aria-invalid="true"]):hover { border-color: var(--paper-apoio); }
}

/* ---- 3b. O primario, que ja e claro ----
   Ele nao inverte nada: o rotulo dele ja e escuro. A varredura leva o
   papel ao unico degrau acima que existe, e passa POR TRAS do rotulo
   (`z-index: -1`), que e o inverso da camada de cima do grupo 3a.
   O `isolation` aqui serve para o -1 nao cair atras da propria secao.

   ⚠️ O `:not(:disabled)` NAO E DECORACAO, e ele foi medido. O botao de
   pedir nasce TRAVADO ate a pessoa escolher o tamanho, e com o mouse em
   cima dele o navegador respondeu `matches(':hover') === true`. Ou seja,
   um botao travado casa com `:hover` e, sem esta trava, a varredura
   passaria por tras do rotulo e o travado acenderia como se desse para
   clicar. Aqui ele nao acendeu, mas isso e comportamento de um navegador
   num dia, e nao contrato: `aria-disabled` (que nao e atributo nativo)
   acenderia com certeza. Travado e travado, e nao promete o que nao da. */
@media (hover: hover) {
  .btn--primario { position: relative; isolation: isolate; }
  .btn--primario::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background: var(--paper-vivo);
    transform: scaleX(0);
    transform-origin: left center;
    transition: transform var(--preenche-dur) var(--mov-curva);
  }
  .btn--primario:not(:disabled):not([aria-disabled="true"]):hover::before { transform: scaleX(1); }
}

/* ---- 3c. O que e ALTO preenche de BAIXO para CIMA ----
   O quadro 4:5 do cartao e a foto da pagina da peca. Aqui a varredura
   nao pode fechar em papel: embaixo dela tem uma FOTO, e preencher a
   foto de branco seria apagar a peca que a pessoa veio ver. Entao o
   que sobe e um VEU, que e o mesmo gesto na intensidade que a
   superficie aguenta.

   Ele sobe junto com a imagem crescendo (grupo 2): sao os dois lados
   do mesmo hover, e por isso dividem a mesma duracao. */
@media (hover: hover) {
  .card__quadro::after,
  .peca__foto::after,
  .som__porta::after {
    content: "";
    position: absolute;
    inset: 0;
    background: var(--veu-sobe);
    pointer-events: none;
    transform: scaleY(0);
    transform-origin: bottom center;
    transition: transform var(--preenche-dur) var(--mov-curva);
  }
  .card__link:hover .card__quadro::after,
  .peca__foto:hover::after,
  .som__porta:hover::after { transform: scaleY(1); }

  /* A porta da playlist responde como um quadro de peca, e nao como um
     botao: o veu sobe e o "L" cresce DENTRO do campo. E a mesma resposta do
     cartao, e e o que faz a playlist pertencer ao site em vez de parecer um
     tocador colado nele. O rotulo e o triangulo ficam ACIMA do veu porque
     tem `position: relative` na paginas.css. */
  .som__porta .som__mark { transition: transform var(--preenche-dur) var(--mov-curva); }
  .som__porta:hover .som__mark { transform: scale(var(--zoom-quadro)); }
  .som__porta { transition: border-color var(--transicao); }
  .som__porta:hover { border-color: var(--fio-vivo); }
}


/* ============================================================
   4. ENTRA · a cascata hierarquica
   ------------------------------------------------------------
   Quando um bloco chega na tela, os elementos dele aparecem em
   cascata, NA ORDEM DA LEITURA e nunca todos de uma vez:

       rotulo  →  titulo  →  corpo  →  botao ou link

   A cascata e DO BLOCO, nao da pagina: cada secao anima quando chega,
   e uma secao nunca espera a outra. Quem marca o bloco e
   `data-cascata`; quem marca cada degrau e `data-entra`; quem conta a
   ordem e o `movimento.js`, escrevendo `data-passo` em cada degrau.

   REGRA DE MARCACAO: um elemento e bloco OU degrau, nunca os dois. E
   o que deixa blocos aninhados (a grade de pecas dentro da secao)
   funcionarem sem uma cascata mexer na outra.

   O MOVIMENTO E SO OPACIDADE MAIS UM DESLOCAMENTO CURTO PARA CIMA.
   Nada de escala na entrada, nada de deslizar de lado, nada de quicar:
   o design system pede "confianca silenciosa", e coisa que salta na
   tela e o contrario disso.

   ANIMA UMA VEZ. Quem ja apareceu nao volta a animar quando a pessoa
   rola para cima: o `movimento.js` para de observar o bloco assim que
   ele entra. Pagina que reanima ao rolar de volta cansa em trinta
   segundos.

   ------------------------------------------------------------
   POR QUE ISTO VIVE DENTRO DE `no-preference`
   ------------------------------------------------------------
   Esta e a unica regra do site que ESCONDE conteudo, e conteudo
   escondido depende de um script para voltar. Entao ela so existe
   quando a pessoa aceita movimento. Duas consequencias, e as duas sao
   de proposito:

     - com `prefers-reduced-motion: reduce`, nada e escondido em
       momento nenhum, e a pagina nasce inteira na tela;
     - no navegador que nao conhece a media query, idem.

   A terceira rede esta no JavaScript: a classe `.mov` do <html>, que
   e quem liga estas regras, so e escrita se o IntersectionObserver
   existir. Sem script, sem `.mov`, e o site inteiro aparece normal.
   ============================================================ */
@media (prefers-reduced-motion: no-preference) {
  .mov [data-entra] {
    opacity: 0;
    transform: translateY(var(--mov-desloca));
    transition: opacity   var(--mov-dur) var(--mov-curva),
                transform var(--mov-dur) var(--mov-curva);
  }
  .mov [data-entra].entrou { opacity: 1; transform: none; }

  /* O atraso de cada degrau. E `transition-delay` e NAO uma variavel
     de atraso: variavel de CSS e herdada, e um degrau que fosse pai de
     outro passaria o proprio atraso para o filho sem ninguem pedir.
     `transition-delay` nao herda, entao cada degrau responde so pelo
     que esta escrito nele.

     O teto e 6. Um bloco de doze degraus com atraso crescente
     terminaria quase um segundo depois de comecar, e o ultimo item
     pareceria travado. Do sexto em diante todos entram juntos. */
  .mov [data-passo="1"] { transition-delay: calc(var(--mov-passo) * 1); }
  .mov [data-passo="2"] { transition-delay: calc(var(--mov-passo) * 2); }
  .mov [data-passo="3"] { transition-delay: calc(var(--mov-passo) * 3); }
  .mov [data-passo="4"] { transition-delay: calc(var(--mov-passo) * 4); }
  .mov [data-passo="5"] { transition-delay: calc(var(--mov-passo) * 5); }
  .mov [data-passo="6"] { transition-delay: calc(var(--mov-passo) * 6); }
}

/* A QUARTA REDE, e ela é de papel.
   Impressão não rola a página: o navegador manda o documento inteiro para a
   folha, e o que nunca entrou na tela nunca recebeu `entrou`. Sem esta regra,
   quem mandasse imprimir a página de uma peça sem ter rolado até o fim
   receberia meia folha em branco, e o defeito seria invisível na tela.
   Foi visto acontecendo: numa aba em segundo plano o navegador suspende o
   IntersectionObserver, e o conteúdo fica esperando. Na tela isso se conserta
   sozinho quando a pessoa volta para a aba; no papel, não existe voltar. */
@media print {
  .mov [data-entra] { opacity: 1 !important; transform: none !important; }
}


/* ============================================================
   4b. A CAMADA TAMBEM ENTRA, E CADA UMA PELO SEU EIXO
   ------------------------------------------------------------
   ⚠️ ISTO VOLTA UMA DECISAO ESCRITA AQUI MESMO, e o motivo mudou.

   O comentario que estava neste lugar dizia que a gaveta NAO deslizava da
   direita de proposito, porque deslizar seria "uma QUINTA palavra num
   vocabulario que tem quatro e nao pode ter cinco". Bruno pediu o deslize
   em 5/ago, e ao escrever a reversao apareceu que a regra dos quatro nunca
   esteve em jogo: o `docs/DESIGN.md 6.2` ja mandava, com estas palavras,
   que O SENTIDO DO MOVIMENTO E O DA FORMA — "largo atravessa da esquerda
   para a direita, alto sobe de baixo para cima".

   Entao nao nasce palavra nova aqui. E o ENTRA de sempre (opacidade mais
   deslocamento) OBEDECENDO A FORMA, e o que decide o eixo e a BORDA EM QUE
   A CAMADA MORA:

     .gaveta   encosta na direita  →  entra pela direita   (eixo X)
     .busca    encosta no topo     →  desce do topo        (eixo Y)
     .camada   e centrada          →  nao vem de borda nenhuma, entao
                                      continua com o deslocamento curto

   ⚠️ O DESLOCAMENTO DAS DUAS ANCORADAS E 100%, E NAO OS 14px DO RESTO. Um
   painel que mora fora da tela precisa ser visto VINDO DE FORA: 14px nao
   lem como "veio da lateral", lem como "tremeu". Os 14px continuam certos
   para bloco de conteudo, que nao vem de lugar nenhum, so aparece.

   ⚠️ E ELAS NAO LEVAM `opacity` JUNTO. O deslize ja conta a historia
   inteira de onde a camada veio, e somar fade a um painel opaco de tela
   cheia da o efeito de vidro sujo no meio do caminho. Quem faz o fundo
   escurecer suave e o veu, que tem a sua propria animacao. Fade fica para
   quem aparece NO LUGAR, que e a `.camada`.

   E animacao e nao transicao porque o <dialog> nasce na hora em que abre:
   nao existe estado anterior para transicionar a partir dele.

   ⚠️ SO A ENTRADA E ANIMADA. Fechar continua instantaneo, porque
   `dialog.close()` tira o elemento na hora e segurar isso pede intervir no
   JavaScript dos dois arquivos (o `Esc` fecha sem passar pela funcao
   `fechar`). Se um dia a saida entrar, ela entra pelo MESMO eixo de cada
   uma, e nunca por outro: camada que entra pela direita e sai por cima
   parece duas camadas diferentes.
   ============================================================ */
/* ------------------------------------------------------------
   ENTRA E SAI PELO MESMO CAMINHO
   ------------------------------------------------------------
   ⚠️ ERAM `@keyframes` E VIRARAM TRANSICAO em 5/ago, e a troca tem um
   motivo unico: keyframe so sabe ENTRAR. A camada deslizava suave para
   dentro e sumia num piscar, porque `dialog.close()` tira o elemento na
   hora, e isso e a lacuna que o Bruno pediu para fechar.

   O que fecha a lacuna sao tres peças de CSS que so funcionam juntas:

     `@starting-style`     de onde a camada vem. Sem ele nao ha estado
                           anterior no primeiro quadro, e ENTRAR nao anima
     `display allow-discrete`  segura o `display: none` ate o fim da saida.
                           Sem ele o elemento some no primeiro quadro e a
                           saida nao acontece
     `overlay allow-discrete`  segura a camada no TOP LAYER durante a saida.
                           Sem ele ela cai para tras do resto da pagina no
                           meio da animacao, que e pior do que nao animar

   ⚠️ O EIXO DA SAIDA E O MESMO DA ENTRADA, SEMPRE, e sai de graca aqui:
   ela volta para o estado de onde veio. Camada que entra pela direita e sai
   por cima parece duas camadas diferentes.

   ⚠️ TUDO ISTO VIVE DENTRO DE `no-preference`, INCLUSIVE O ESTADO FECHADO.
   Se o `transform` do fechado vazasse para fora deste bloco, quem pede menos
   movimento receberia a camada parada FORA DA TELA, sem transicao nenhuma
   para traze-la: a gaveta abriria invisivel. Quem pede menos movimento
   recebe a camada aparecendo e sumindo, que e o certo.

   ⚠️ SE O NAVEGADOR FOR VELHO, NADA QUEBRA: sem `@starting-style` e sem
   `allow-discrete` a camada aparece e some sem animacao, que e exatamente
   como ela se comportava antes deste bloco existir.
   ------------------------------------------------------------ */
@media (prefers-reduced-motion: no-preference) {
  .gaveta, .busca, .camada, .painel-idioma {
    transition: transform var(--mov-dur) var(--mov-curva),
                opacity   var(--mov-dur) var(--mov-curva),
                display   var(--mov-dur) allow-discrete,
                overlay   var(--mov-dur) allow-discrete;
  }

  /* O ESTADO FECHADO, que e de onde ela entra e para onde ela sai. */
  .gaveta { transform: translateX(100%); }
  .busca  { transform: translateY(-100%); }
  /* A camada das politicas e CENTRADA: ela nao mora em borda nenhuma, entao
     nao desliza de lugar nenhum. Deslocamento curto mais fade, que e o ENTRA
     do resto do site. */
  .camada { transform: translateY(var(--mov-desloca)); opacity: 0; }

  /* ------------------------------------------------------------
     O PAINEL DE IDIOMA (6/ago). Pedido do Bruno: "surge de cima para
     baixo, e quando se recolhe tambem, suave".

     ⚠️ ELE DESCE, MAS NAO DESCE DE FORA DA TELA, e a diferenca decide o
     numero. A regra escrita acima separa os dois casos: camada que mora
     FORA da tela precisa ser vista VINDO DE FORA, e para essa 14px "lem
     como tremeu"; bloco que ja esta DENTRO so aparece, e 14px e o certo.

     Este e o segundo caso, e por um motivo de ancoragem: ele nao encosta
     em borda nenhuma, ele nasce colado embaixo da porta que o abriu (as
     duas medidas vem do `getBoundingClientRect` da porta, no
     `js/idioma-painel.js`). Um `translateY(-100%)` como o da busca o
     faria vir de cima do cabecalho, atravessando a marca, e leria como
     uma segunda camada de tela cheia em vez de um menu preso a um botao.

     Entao o gesto e o deslocamento curto da casa, so que NEGATIVO: ele
     comeca 14px acima do lugar e desce ate ele. Descer 14px sob a porta e
     literalmente "de cima para baixo", na escala de um menu.

     O `transform-origin` fica no canto de cima e da direita porque e de
     la que ele sai: e o mesmo canto onde a porta esta, e onde o
     `margin` do `componentes.css` prende o painel.

     ⚠️ O FADE ENTRA AQUI, e nas camadas deslizantes nao. A regra acima
     recusa fade em painel opaco de tela cheia (vira vidro sujo no meio do
     caminho); aqui o painel e pequeno e o deslocamento e curto, entao sem
     fade ele PULA em vez de aparecer. E a mesma escolha da `.camada`.
     ------------------------------------------------------------ */
  .painel-idioma {
    transform: translateY(calc(var(--mov-desloca) * -1));
    opacity: 0;
    transform-origin: top right;
  }

  .gaveta[open], .busca[open] { transform: none; }
  .camada[open], .painel-idioma[open] { transform: none; opacity: 1; }

  @starting-style {
    .gaveta[open] { transform: translateX(100%); }
    .busca[open]  { transform: translateY(-100%); }
    .camada[open] { transform: translateY(var(--mov-desloca)); opacity: 0; }
    .painel-idioma[open] {
      transform: translateY(calc(var(--mov-desloca) * -1));
      opacity: 0;
    }
  }

  /* O VEU acompanha, senao o fundo clareia de uma vez enquanto a folha
     ainda esta saindo, e a folha parece descolada da propria sombra. */
  dialog::backdrop {
    opacity: 0;
    transition: opacity var(--mov-dur) var(--mov-curva),
                display var(--mov-dur) allow-discrete,
                overlay var(--mov-dur) allow-discrete;
  }
  dialog[open]::backdrop { opacity: 1; }
  @starting-style { dialog[open]::backdrop { opacity: 0; } }
}

/* O ARRASTO PARA FECHAR, e so no celular (docs/FLUXO.md 6).
   Quem move a folha e a mao, entao enquanto o dedo esta nela nao existe
   transicao nenhuma: transicao no meio de um arrasto e o elemento
   chegando atrasado onde o dedo ja esta. A transicao existe so para a
   VOLTA, quando a pessoa arrasta pouco e solta.
   O deslocamento entra como variavel (`--arrasto`) e nao como `transform`
   escrito no elemento: assim o transform continua sendo desta folha de
   estilo, e o JavaScript so informa um numero.

   ⚠️ ELE USA `translate`, A PROPRIEDADE, E NAO `transform`, e a troca foi
   obrigatoria em 5/ago. O arrasto escrevia `transform: translateY(...)` e
   passou a brigar com a entrada e a saida da camada, que tambem sao
   `transform`: a ultima regra ganhava, e no celular a gaveta perdia a
   animacao inteira, ou o arrasto parava de responder ao dedo.

   `translate` e `transform` sao propriedades SEPARADAS e o navegador as
   COMPOE (translate primeiro, transform depois). Cada uma fica com um dono:
   `transform` e da animacao de entrar e sair, `translate` e da mao. Duas
   coisas diferentes nunca mais disputam a mesma linha. */
@media (max-width: 700px) {
  .gaveta[open] {
    translate: 0 var(--arrasto, 0px);
    transition: translate var(--transicao),
                /* ⚠️ AS QUATRO DE CIMA SE REPETEM AQUI DE PROPOSITO.
                   `transition` e atalho: declarar so `translate` apagaria a
                   transicao de entrada e saida desta folha no celular, e a
                   gaveta voltaria a sumir num piscar justamente no aparelho
                   em que ela ocupa a tela inteira. */
                transform var(--mov-dur) var(--mov-curva),
                opacity   var(--mov-dur) var(--mov-curva),
                display   var(--mov-dur) allow-discrete,
                overlay   var(--mov-dur) allow-discrete;
  }
  /* Enquanto o dedo esta na folha, nada de transicao NO ARRASTO. A entrada e
     a saida continuam com a delas: sem esta separacao, soltar o dedo no meio
     de um fechamento congelaria a camada na tela. */
  .gaveta[data-arrastando="sim"] { transition: none; }
}

/* ============================================================
   5. TOQUE
   ------------------------------------------------------------
   O que o dedo recebe. Fica fora de `@media (hover: hover)` porque e
   justamente para quem nao tem mouse, e o efeito e o mesmo dos dois
   lados: o botao afunda 1px enquanto o dedo esta nele.
   ============================================================ */
.btn:active { transform: translateY(1px); }
.btn:disabled:active,
.btn[aria-disabled="true"]:active { transform: none; }


/* ============================================================
   6. ESPERA · a varredura que nao completa
   ------------------------------------------------------------
   NAO E UMA QUINTA PALAVRA, e isso importa. O vocabulario continua
   sendo quatro. Esta secao e a TERCEIRA (preenche) em regime
   continuo: a mesma varredura de claro, no mesmo sentido de leitura
   (esquerda para a direita, porque o botao e largo), com a unica
   diferenca de que ela nao chega ao fim e recomeca.

   O hover diz "isto responde". A varredura em laco diz "isto esta
   respondendo, ainda". Mesmo gesto, tempo diferente, e por isso
   ninguem precisa aprender um sinal novo para entender.

   POR QUE NAO UM DISCO GIRANDO. Disco e vocabulario de aplicativo:
   nao tem raio zero, nao tem lado, nao tem sentido de leitura, e
   caberia igual em qualquer site do mundo, que e a definicao do que o
   `docs/DESIGN.md` chama de template. Uma barra reta que atravessa e
   o gesto que este site ja faz em toda parte.

   ⚠️ A TARJA DE CORPO INTEIRO FOI CONSTRUIDA E RECUSADA, E O REGISTRO
   FICA PARA NINGUEM REFAZE-LA. A primeira versao desta secao tinha a
   faixa crescendo ate a altura do botao, com `mix-blend-mode:
   difference` invertendo o rotulo por onde passasse. No papel era a
   melhor ideia das duas: reusava a mecanica ja provada do 3a, e a
   tarja e um ativo que o `MARCA.md` 12 manda ficar. Na tela, um terco
   do botao em preto solido indo e voltando a cada 1,15s le como
   defeito de renderizacao, e nao como trabalho. Um estado de espera
   nao pode ser a coisa mais barulhenta da pagina: ele acompanha, nao
   anuncia. Comparacao lado a lado em `site/_medir-espera.html` 3.

   O que sobrou e mais simples e mais barato: 2px na base, sem mistura
   de camada, sem `@supports`, sem uma regra por variante. Nada aqui
   depende de recurso que um navegador possa nao ter.

   ⚠️ O `::before` E O MESMO DA VARREDURA DE HOVER, E ISSO E SEGURO.
   Todas as regras que acendem aquele `::before` carregam
   `:not(:disabled)`, e o botao ocupado E `disabled`: no instante em
   que a espera comeca, a camada de hover ja esta desligada e parada em
   `scaleX(0)`. Uma camada so, dois trabalhos que nunca acontecem
   juntos. Reusar foi escolha e nao economia: um `::after` teria
   colidido com a seta do `.btn--bloco`.
   ============================================================ */
.btn[aria-busy="true"] { position: relative; overflow: hidden; }
.btn[aria-busy="true"]::before {
  content: "";
  position: absolute;
  /* ⚠️ `z-index: auto` DESFAZ O `-1` DO PRIMARIO. No hover aquela camada
     passa POR TRAS do rotulo de proposito (3b); aqui ela nao passa por
     tras de nada, e herdar o -1 a esconderia atras do proprio fundo. */
  z-index: auto;
  left: 0; right: 0; bottom: 0; top: auto;
  height: 2px;
  /* ⚠️ `currentColor` E O QUE FAZ UMA DECLARACAO SERVIR AS TRES VARIANTES.
     O primario tem `color: --ink` e a faixa sai escura sobre o papel; o
     secundario tem `color: --paper` e ela sai clara sobre o preto; o
     terciario segue o tom de apoio dele. Nenhuma regra por variante, e
     nenhuma chance de alguem criar a quarta e esquecer desta linha. E o
     mesmo raciocinio do `.icone`, que ja e `background: currentColor`.

     O GRADIENTE E O QUE TORNA A CONTA INDEPENDENTE DA LARGURA: o claro
     ocupa a faixa do meio e o resto e transparente, entao em -100% ela
     esta inteira fora pela esquerda e em +100% inteira fora pela
     direita. Botao de 120px e botao de 600px levam o mesmo tempo e
     percorrem o mesmo caminho, sem uma linha de matematica por tamanho. */
  background: linear-gradient(90deg,
                transparent 0,
                transparent calc(50% - var(--espera-faixa) / 2),
                currentColor calc(50% - var(--espera-faixa) / 2),
                currentColor calc(50% + var(--espera-faixa) / 2),
                transparent calc(50% + var(--espera-faixa) / 2),
                transparent 100%);
  pointer-events: none;
  /* O repouso e o MEIO, e nao a saida pela esquerda. O motivo esta em 6a. */
  transform: none;
  /* A transicao do hover nao manda mais nesta camada: quem manda e a
     animacao. Sem isto, a troca de estado herdaria os 320ms do preenche. */
  transition: none;
  animation: lethal-varredura var(--espera-dur) var(--espera-curva) infinite;
}

@keyframes lethal-varredura {
  from { transform: translateX(-100%); }
  to   { transform: translateX(100%); }
}

/* ---- 6a. QUEM PEDE MENOS MOVIMENTO CONTINUA SABENDO QUE ESTA ESPERANDO ----
   ⚠️ ESTA E A PARTE QUE NAO PODE SER ESQUECIDA, e ela e o motivo de o
   `transform` de repouso la em cima ser `none` e nao `translateX(-100%)`.

   O `tokens.css` termina com `* { animation: none !important }` dentro de
   `prefers-reduced-motion: reduce`, e esse `!important` alcanca esta secao
   tambem, como tem que alcancar. So que uma faixa parada no lugar onde a
   animacao a deixaria some da tela, e ai o estado inteiro vira aquilo que
   esta secao existe para acabar: um botao sem resposta, agora tambem sem
   faixa. Feedback que depende de animacao nao e feedback, e um enfeite que
   some justamente para quem mais precisa de clareza.

   Entao aqui o repouso e informativo: a faixa ocupa a base INTEIRA, parada.
   Ela nao percorre, nao pulsa e nao pisca, e continua dizendo com desenho o
   que o rotulo trocado ja diz com palavra. So o movimento sai. */
@media (prefers-reduced-motion: reduce) {
  .btn[aria-busy="true"]::before {
    background: currentColor;
    transform: none;
  }
}
