/* Nash — biblioteca de movimento dos botões.
   Tokens de tempo e curva, a placa de vidro como base, e um efeito por
   classe. Cada efeito responde a uma pergunta: o que este movimento diz a
   quem usa? A resposta abre o comentário de cada um; o que não responde,
   não entrou. Cores vêm de style-guide.css; a receita da placa é a do
   Figma (Design System › Vidro). Documentação: docs/motion.md.
   Nove efeitos precisam de motion.js: lampejo pelo lado de entrada, ocupado
   sem pulo (arco e aura), anel de concluído, cresce (altura por
   scrollHeight), digita (typewriter), abre e envia (a Barra de prompt),
   ancora (a barra desce ao rodapé) e conta (o número sobe).

   Revisão de 2026-09-04, oitava rodada: o convite ainda lia como poucos
   quadros mesmo depois do will-change. Medido de novo: a opacidade caía
   lisa (1 → 0,67 → 0,44 → 0,29…), mas a posição também mudava — 42px na
   horizontal, 23px na vertical — porque o convite era filho do campo
   (data-nash-viaja) e herdava o transform da viagem dele. Esmaecer E
   viajar ao mesmo tempo, em ~9 quadros reais de 140ms, é pouco quadro pra
   duas mudanças grandes juntas — lê como corte, sem ser jank de verdade.
   O convite virou irmão do campo, não filho: mesma área de grid, nunca
   recebe o transform. Agora só a opacidade muda; a posição fica parada.

   Revisão de 2026-09-04, sétima rodada: o dono disse que o texto do campo
   parecia perder quadros, e pediu a sequência da referência — o convite
   sai no meio do gesto e dá lugar ao cursor. Medido: a geometria do
   textarea é lisa (posição fracionária suave, sem salto), então não era
   quadro perdido. Era o texto sendo re-rasterizado a cada quadro enquanto
   viajava ~40px em posição fracionária sobre vidro borrado — cintilação de
   glifo, não jank. Duas respostas: will-change: transform nos slots que
   viajam (o texto vira textura e só é transladado), e o placeholder nativo
   virou .nash-prompt-convite, um texto secundário sobreposto que só
   esmaece em 140 ms — ele não viaja mais, sai antes de a viagem terminar.

   Revisão de 2026-09-04, sexta rodada: o dono achou o abre "ríspido", como
   se pulasse etapa no meio. Medido por CDP, quadro a quadro: não há jank
   de verdade (quadros regulares, nenhum gap grande). A causa é a curva —
   cubic-bezier(.16,1,.3,1) é uma "expo out": quase todo o movimento
   visível acontece nos primeiros ~35% da duração, e o resto é uma cauda
   quase parada. Somado aos ~20ms que o FLIP gasta medindo e forçando
   reflow antes do primeiro quadro em movimento, o efeito lido é
   "congela, salta, para" — não frame perdido, mas a curva errada pro
   tamanho do movimento. Entrou --nash-curva-espacial (cubic-bezier(.33,
   1,.68,1), "cubic out"), só nas propriedades que o abre já usa —
   altura da barra, transform dos slots que viajam, e a coluna/gap/padding
   da marca — pra espalhar o movimento por mais da duração. Quebra a regra
   de "uma curva só" de propósito, autorizado pelo dono mesmo pra decisões
   já fechadas; curva-saída segue em tudo que só troca de estado.

   Revisão de 2026-09-04, quinta rodada: o dono testou de novo e achou
   dois movimentos rápidos demais — o lampejo (o brilho que atravessa o
   vidro) e o abre (a barra virando cartão) — e o chip da marca "esquisito"
   ao abrir. A marca não era mesmo fluida: o grid da coluna do rótulo leva
   --nash-dur-abre pra crescer, mas o rótulo (nash-prompt-rotulo) esmaecia
   em --nash-dur-estado, mais curto — o texto chegava opaco antes de a
   coluna terminar de abrir espaço pra ele. Rótulo passou a usar
   --nash-dur-abre também, junto do grid e do FLIP do slot. Números:
   lampejo de 480ms pra 640ms, abre de 240ms pra 320ms, expande (o cresce
   do campo) de 220ms pra 300ms, todos na mesma curva de saída de sempre —
   não é um laço linear como os da rodada anterior, então a curva fica.

   Revisão de 2026-09-04, quarta rodada: o dono achou os laços rápidos
   demais — arco, digita e o degrau da fila. Ficam lineares, sem curva
   (pediu explicitamente pra não trocar por uma curva); só os números
   ficaram maiores: arco de 4,5s pra 5,5s, digita de 24ms pra 32ms por
   letra, passo de 70ms pra 90ms entre irmãos. O resto — tudo que já usa
   a curva de saída — não mudou.

   Revisão de 2026-09-04, terceira rodada: o dono testou a página e achou
   o Text Input (IA) "mal feito" — o campo não crescia (o cresce zerava a
   altura antes de medir e a transição partia da linha única, não da
   altura anterior), a borda "ficava só rodando" e o conjunto não compunha.
   A aura parou de girar: na referência a borda é um gradiente parado, roxo
   à esquerda e âmbar à direita, e o que vive é o halo, que respira. Entraram
   abre (a barra vira cartão de duas linhas e os controles viajam), envia,
   ancora, chega, some e conta — o vocabulário da Gen UI, documentado em
   docs/motion.md e montado em genui.css.

   Revisão de 2026-09-04, mesma tarde, segunda rodada: aura, cresce e
   digita entraram como opt-in, vindos de uma referência de Gen UI que o
   dono trouxe — a borda multi-cor sempre girando e o container que muda
   de tamanho quebram regras da régua atual (uma cor em movimento por
   tela; nada muda de tamanho), então viraram exceções nomeadas, não a
   regra nova. Nunca aura junto com arco na mesma tela.

   Revisão de 2026-09-04: o dono achou o conjunto "duro" — a mola no
   soltar e as escalas grandes liam como brinquedo, não instrumento. Toda
   mola saiu (nxx-motion: "a maioria da UI não quer bounce" — mola fica
   para arrastar, não para botão), amplitudes de escala e brilho caíram,
   e o lampejo e o giro do × encolheram para um traço, não um gesto. Uma
   curva só, a de saída, em tudo. */

:root {
  --nash-dur-pressao: 100ms; /* apertar: registrou */
  --nash-dur-micro: 140ms; /* hover entra e sai, giro do ícone */
  --nash-dur-solta: 160ms; /* soltar, mesma curva da chegada */
  --nash-dur-estado: 180ms; /* placa e stroke trocam de estado */
  --nash-dur-ponto: 160ms; /* o ponto acende */
  --nash-dur-brilho: 260ms; /* o halo floresce */
  --nash-dur-lampejo: 640ms; /* o traço de luz atravessa o vidro */
  --nash-dur-clarao: 300ms; /* o anel apaga depois do disparo */
  --nash-dur-concluido: 700ms; /* o anel acende, segura e apaga */
  --nash-arco-volta: 5.5s; /* o arco âmbar dá uma volta */
  --nash-aura-respira: 4s; /* o halo da aura respira um ciclo — parado, não gira */
  --nash-aura-volta: 6s; /* a linha da aura dá uma volta no outline */
  --nash-aura-a: var(--accent-design, #b36bff); /* a aura começa aqui, à esquerda */
  --nash-aura-b: var(--accent-image, #ffb454); /* e termina aqui, à direita */
  --nash-dur-expande: 300ms; /* o campo ganha altura pra multi-linha */
  --nash-dur-letra: 32ms; /* o typewriter revela um caractere */
  --nash-dur-abre: 320ms; /* a barra vira cartão; os controles viajam */
  --nash-dur-ancora: 560ms; /* a barra desce e ancora no rodapé */
  --nash-dur-chega: 520ms; /* um cartão gerado chega */
  --nash-dur-some: 160ms; /* o que sai, sai mais rápido do que chegou */
  --nash-passo: 90ms; /* o degrau entre irmãos que chegam em fila */
  --nash-curso: 24px; /* quanto a bolinha do Toggle viaja */
  --nash-curva-saida: cubic-bezier(0.16, 1, 0.3, 1);
  --nash-curva-espacial: cubic-bezier(0.33, 1, 0.68, 1); /* abre: deixa o movimento visível por mais tempo */
  --nash-placa: rgba(13, 15, 18, 0.32);
  --nash-placa-hover: rgba(31, 33, 40, 0.4);
  --nash-placa-pressed: rgba(8, 10, 13, 0.32);
}

/* ---------- base: o botão e a placa de vidro ---------- */

/* Reset do controle e a lista única de transições. Os efeitos só
   declaram estados; se cada um trouxesse a própria `transition`, a última
   classe apagaria as outras. Uma curva só — a de saída — chegando e
   voltando; nada balança. */
.nash-botao {
  appearance: none;
  border: 0;
  margin: 0;
  cursor: pointer;
  font: inherit;
  color: #fff;
  transition:
    transform var(--nash-dur-solta) var(--nash-curva-saida),
    background-color var(--nash-dur-estado) var(--nash-curva-saida),
    color var(--nash-dur-micro) var(--nash-curva-saida);
}

.nash-botao:active {
  transition-duration: var(--nash-dur-pressao);
  transition-timing-function: var(--nash-curva-saida);
}

.nash-botao:disabled {
  cursor: default;
  opacity: 0.35;
}

/* A placa: fill 32%, blur 24, e dois strokes de 1,5px por dentro —
   ::before branco (15 > 6 > 2 > 0), ::after no accent (45 > 18 > 6 > 0),
   apagado até um efeito pedir. */
.nash-placa {
  position: relative;
  isolation: isolate;
  background-color: var(--nash-placa);
  -webkit-backdrop-filter: blur(24px);
  backdrop-filter: blur(24px);
}

.nash-placa::before,
.nash-placa::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1.5px;
  pointer-events: none;
  -webkit-mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  mask-composite: exclude;
  transition: opacity var(--nash-dur-estado) var(--nash-curva-saida);
}

.nash-placa::before {
  background: linear-gradient(
    180deg,
    rgba(255, 255, 255, 0.15),
    rgba(255, 255, 255, 0.06) 40%,
    rgba(255, 255, 255, 0.02) 70%,
    rgba(255, 255, 255, 0)
  );
}

.nash-placa::after {
  opacity: 0;
  background: linear-gradient(
    180deg,
    color-mix(in srgb, var(--accent, #fff) 45%, transparent),
    color-mix(in srgb, var(--accent, #fff) 18%, transparent) 40%,
    color-mix(in srgb, var(--accent, #fff) 6%, transparent) 70%,
    transparent
  );
}

/* Sem placa em repouso: a aba dentro do trilho. A placa só aparece
   quando um estado a pede. */
.nash-placa--vazia {
  background-color: transparent;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

.nash-placa--vazia::before {
  opacity: 0;
}

/* ---------- pressão — "registrou" ----------
   Escala 0,98 em 100 ms; solta na mesma curva de saída em 160 ms — sem
   mola, sem balanço. Os filhos vão junto, que é o ponto. Sobrevive a
   todas as linhas da tabela de frequência: um controle que não muda ao
   apertar parece não ter registrado, e a pessoa aperta de novo. */
.nash-pressao:active {
  transform: scale(0.98);
}

/* ---------- subida — "dá pra apertar" ----------
   No hover a placa sobe para o cinza #1F2128 a 40% e o stroke branco
   acende; ao apertar, assenta no #080A0D a 32%. */
.nash-subida:hover {
  color: #fff;
  background-color: var(--nash-placa-hover);
  -webkit-backdrop-filter: blur(24px);
  backdrop-filter: blur(24px);
}

.nash-subida:hover::before {
  opacity: 1;
}

.nash-subida:active {
  background-color: var(--nash-placa-pressed);
}

/* ---------- lampejo — "é vidro" ----------
   Um traço de luz a 6% atravessa a placa quando o ponteiro entra, uma
   vez, pelo lado por onde ele entrou (motion.js grava --nash-lado: 1 ou
   -1). Não repete enquanto o ponteiro fica: hover acontece dezenas de
   vezes por dia, e uma luz em laço vira imposto. Mais fino e mais reto
   que um brilho de vidraça — lê como varredura, não como sheen. Precisa
   de um <i class="nash-luz"> dentro do botão. */
.nash-luz {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  overflow: hidden;
  pointer-events: none;
}

.nash-luz::before {
  content: '';
  position: absolute;
  top: -50%;
  bottom: -50%;
  left: 0;
  width: 42%;
  opacity: 0;
  background: linear-gradient(
    100deg,
    transparent,
    rgba(255, 255, 255, 0.06) 50%,
    transparent
  );
  transform: translateX(calc(-130% * var(--nash-lado, 1))) skewX(-8deg);
}

.nash-lampejo:hover .nash-luz::before {
  animation: nash-lampejo var(--nash-dur-lampejo) var(--nash-curva-saida)
    forwards;
}

@keyframes nash-lampejo {
  0% {
    opacity: 0;
    transform: translateX(calc(-130% * var(--nash-lado, 1))) skewX(-8deg);
  }

  20% {
    opacity: 1;
  }

  100% {
    opacity: 0;
    transform: translateX(calc(190% * var(--nash-lado, 1))) skewX(-8deg);
  }
}

/* ---------- acende — "este é o modo" ----------
   O ponto de 6px antes do rótulo: branco 30% em repouso, 55% no hover,
   accent com um halo baixo — 10px a 32% — quando selecionado. O stroke
   da placa troca do branco para o accent ao mesmo tempo. */
.nash-ponto {
  flex: none;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background-color: rgba(255, 255, 255, 0.3);
  box-shadow: 0 0 10px 0 transparent;
  transition:
    background-color var(--nash-dur-ponto) var(--nash-curva-saida),
    box-shadow var(--nash-dur-brilho) var(--nash-curva-saida);
}

.nash-acende:hover .nash-ponto {
  background-color: rgba(255, 255, 255, 0.55);
}

.nash-acende[aria-selected='true'],
.nash-acende[aria-pressed='true'] {
  color: #fff;
  background-color: var(--nash-placa);
  -webkit-backdrop-filter: blur(24px);
  backdrop-filter: blur(24px);
}

.nash-acende[aria-selected='true']::before,
.nash-acende[aria-pressed='true']::before {
  opacity: 0;
}

.nash-acende[aria-selected='true']::after,
.nash-acende[aria-pressed='true']::after {
  opacity: 1;
}

.nash-acende[aria-selected='true'] .nash-ponto,
.nash-acende[aria-pressed='true'] .nash-ponto {
  background-color: var(--accent);
  box-shadow: 0 0 10px 0
    color-mix(in srgb, var(--accent) 32%, transparent);
}

/* ---------- arco — "a ação principal, viva" ----------
   O stroke branco vira o arco âmbar e gira uma volta a cada 4,5 s; fora
   do arco o âmbar fica a 14% para a borda nunca sumir. Uma por tela: a
   ação principal usa o arco, nunca junto com a aura (abaixo — a outra
   exceção à regra de uma cor em movimento). nashMotion.arcoOcupado(el,
   true) acelera o giro 3x sem pular — "trabalhando" — e (el, false)
   devolve. */
@property --nash-angulo {
  syntax: '<angle>';
  inherits: false;
  initial-value: 0deg;
}

.nash-arco::before {
  opacity: 1;
  background: conic-gradient(
    from var(--nash-angulo),
    rgba(255, 180, 84, 0.14) 0deg,
    #ffb454 58deg,
    #ff6b2c 118deg,
    rgba(255, 107, 44, 0.14) 196deg,
    rgba(255, 180, 84, 0.14) 360deg
  );
  animation: nash-arco var(--nash-arco-volta) linear infinite;
}

@keyframes nash-arco {
  to {
    --nash-angulo: 360deg;
  }
}

/* ---------- aura — "esta superfície gera" (opt-in, cenário) ----------
   A borda de uma superfície que gera conteúdo — a Barra de prompt. Em
   repouso o stroke é o gradiente parado, --nash-aura-a à esquerda e
   --nash-aura-b à direita (design > imagem por padrão, os dois accents
   que geram), e o que vive é o halo, que respira. O stroke fica no
   ::after; o halo num <i class="nash-halo"> filho, mascarado pra só
   existir por fora do vidro, a --nash-halo-alcance do stroke.

   Revisão de 2026-09-04, nona rodada: uma linha corre o outline quando a
   superfície está atenta — no foco, e o tempo todo enquanto gera
   (data-estado="ocupado"). É um conic-gradient de arco fixo: a faixa
   colorida ocupa ~53% da volta (24deg a 190deg com as duas pontas
   esmaecendo) e o ângulo de partida gira em --nash-aura-volta. Fora
   desses dois estados a linha não corre — a borda parada de sempre. O
   que o dono chamou de "só rodando" na segunda rodada era o anel inteiro
   colorido girando sem estado que justificasse; aqui a corrida é a
   resposta a "estou ouvindo" e a "estou gerando".

   Sempre com nash-placa; nunca com nash-arco na mesma tela — arco e aura
   são as duas únicas exceções à regra de uma cor em movimento por tela.
   nashMotion.ocupado(el, true) acelera a respiração do halo 3× —
   "trabalhando" — e (el, false) devolve. */
.nash-aura::after {
  opacity: 1;
  background: linear-gradient(
    100deg,
    var(--nash-aura-a) 0%,
    var(--nash-aura-a) 22%,
    var(--nash-aura-b) 78%,
    var(--nash-aura-b) 100%
  );
}

@property --nash-aura-angulo {
  syntax: '<angle>';
  inherits: false;
  initial-value: 0deg;
}

.nash-aura:focus-within::after,
.nash-aura[data-estado='ocupado']::after {
  background: conic-gradient(
    from var(--nash-aura-angulo),
    transparent 0deg,
    var(--nash-aura-a) 24deg,
    var(--nash-aura-b) 156deg,
    transparent 190deg,
    transparent 360deg
  );
  animation: nash-aura-corre var(--nash-aura-volta) linear infinite;
}

@keyframes nash-aura-corre {
  to {
    --nash-aura-angulo: 360deg;
  }
}

.nash-halo {
  --nash-halo-alcance: 18px;
  position: absolute;
  inset: calc(-1 * var(--nash-halo-alcance));
  z-index: -1;
  padding: var(--nash-halo-alcance);
  border-radius: calc(var(--nash-raio, 32px) + var(--nash-halo-alcance));
  pointer-events: none;
  opacity: 0;
  filter: blur(10px);
  -webkit-mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  mask-composite: exclude;
  transition: opacity var(--nash-dur-brilho) var(--nash-curva-saida);
}

.nash-halo::before {
  content: '';
  position: absolute;
  inset: var(--nash-halo-alcance);
  border-radius: var(--nash-raio, 32px);
  padding: 6px;
  background: linear-gradient(
    100deg,
    var(--nash-aura-a) 0%,
    var(--nash-aura-a) 22%,
    var(--nash-aura-b) 78%,
    var(--nash-aura-b) 100%
  );
  -webkit-mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  mask-composite: exclude;
}

.nash-aura .nash-halo {
  animation: nash-respira var(--nash-aura-respira) ease-in-out infinite alternate;
}

/* Um laço simétrico pede curva simétrica: ease-in-out aqui, linear no
   arco. A curva de saída fica para o que chega e volta. */
@keyframes nash-respira {
  from {
    opacity: 0.38;
  }

  to {
    opacity: 0.8;
  }
}

/* ---------- clarão — "disparou" ----------
   Ao apertar, o anel âmbar sobe a 40% em 50 ms e apaga em 300 ms depois
   de soltar — um aviso, não um flash. Precisa de um <i class="nash-anel">
   dentro do botão; o mesmo anel serve ao concluído. */
.nash-anel {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1.5px;
  pointer-events: none;
  opacity: 0;
  background: conic-gradient(#ffb454, #ff6b2c, #ffb454);
  -webkit-mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  mask-composite: exclude;
  transition: opacity var(--nash-dur-clarao) var(--nash-curva-saida);
}

.nash-clarao:active .nash-anel {
  opacity: 0.4;
  transition-duration: 50ms;
}

/* ---------- concluído — "terminou" ----------
   nashMotion.concluido(el): o anel acende, segura e apaga, tudo em
   700 ms — só opacidade, sem escala. Uma vez por evento; nunca em laço. */
.nash-anel.nash-concluido {
  animation: nash-concluido var(--nash-dur-concluido) var(--nash-curva-saida)
    forwards;
}

@keyframes nash-concluido {
  0% {
    opacity: 0;
  }

  15% {
    opacity: 1;
  }

  70% {
    opacity: 1;
  }

  100% {
    opacity: 0;
  }
}

/* ---------- deslize — "mudou de estado" ----------
   A bolinha do Toggle viaja --nash-curso (24px; o Toggle miúdo da Barra de
   prompt põe 12px) em 180 ms; no On um halo baixo — 10px a 32% — floresce
   em 260 ms. A posição é o sinal; a cor reforça. */
.nash-bolinha {
  transition:
    transform var(--nash-dur-estado) var(--nash-curva-saida),
    box-shadow var(--nash-dur-brilho) var(--nash-curva-saida);
}

.nash-deslize[aria-checked='true'] .nash-bolinha,
.nash-deslize input:checked ~ .nash-bolinha {
  transform: translateX(var(--nash-curso));
  box-shadow: 0 0 10px 0 rgba(63, 140, 255, 0.32);
}

/* ---------- desperta — "pode escrever" ----------
   O Text Input em foco: o stroke sobe para o branco 45 > 18 > 6 > 0 (o
   ::after com --accent branco) e os ícones vão a 100%. */
.nash-desperta {
  --accent: #fff;
}

.nash-desperta .nash-icone {
  opacity: 0.6;
  transition: opacity var(--nash-dur-estado) var(--nash-curva-saida);
}

.nash-desperta:focus-within::after {
  opacity: 1;
}

.nash-desperta:focus-within .nash-icone {
  opacity: 1;
}

/* ---------- cresce — "aceita mais" (opt-in) ----------
   O campo de texto ganha altura quando o conteúdo passa de 1 linha —
   nashMotion.cresce(el) mede scrollHeight a cada input e anima a
   propriedade height, partindo da altura que estava na tela (a primeira
   versão zerava antes de medir e a transição partia da linha única — o
   campo encolhia e crescia a cada tecla). Única peça da biblioteca que muda de tamanho: o
   texto realmente ocupa mais espaço, não dá pra fingir com transform sem
   distorcer as letras. Por isso é opt-in, não um efeito de botão comum. */
.nash-cresce {
  resize: none;
  overflow: hidden;
  transition: height var(--nash-dur-expande) var(--nash-curva-saida);
}

/* ---------- digita — "está chegando" (opt-in) ----------
   nashMotion.digita(el, texto): revela o texto letra a letra. Num
   input/textarea escreve em .value e dispara 'input' — o cursor é o
   nativo do campo, e o cresce ao lado cresce junto. Em qualquer outro
   elemento, escreve em textContent e cria o próprio nash-cursor (não dá
   pra fixar um <span> no HTML porque textContent apaga filhos a cada
   passo). Pra demonstração e onboarding, nunca pra texto que a pessoa
   mesma digitou. */
.nash-cursor {
  display: inline-block;
  width: 1px;
  margin-left: 1px;
  background: currentColor;
  animation: nash-pisca 1s steps(2, start) infinite;
}

@keyframes nash-pisca {
  to {
    opacity: 0;
  }
}

/* ---------- abre — "cabe mais" ----------
   A Barra de prompt sai da pill de uma linha pro cartão de duas: o campo
   toma a primeira linha inteira e os controles descem pra segunda, viajando
   (FLIP: nashMotion.abre mede antes e depois, inverte com transform e
   solta), enquanto a barra ganha altura — a mesma exceção do cresce, pelo
   mesmo motivo: é a caixa do texto que cresce. O chip da marca ganha o
   rótulo "Prompts" abrindo a coluna do rótulo de 0fr pra 1fr. Abre no foco
   por ponteiro ou quando há texto; fecha ao perder o foco vazio ou ao
   enviar. Vindo do teclado, 0 ms — quem chega pelo Tab já está à frente. */
.nash-prompt {
  transition:
    height var(--nash-dur-abre) var(--nash-curva-espacial),
    transform var(--nash-dur-ancora) var(--nash-curva-saida);
}

/* will-change promove o slot a camada própria: o texto dentro dele é
   rasterizado uma vez e depois só transladado pelo compositor. Sem isso o
   browser redesenha os glifos a cada quadro em posição fracionária, e traço
   fino sobre vidro borrado cintila — lê como quadro perdido, mesmo com a
   geometria perfeitamente lisa (medido: 7-9 ms por quadro, sem gap). */
.nash-prompt [data-nash-viaja] {
  will-change: transform;
  transition: transform var(--nash-dur-abre) var(--nash-curva-espacial);
}

/* ---------- convite — "pode perguntar" ----------
   O texto secundário do campo em repouso. Ao abrir, esmaece em 140 ms —
   sai no meio do gesto de 320 ms — e deixa o cursor do campo sozinho
   dizendo "pode digitar". Volta quando a barra fecha vazia. Não é o
   ::placeholder nativo de propósito: aquele vive dentro do textarea, que
   viaja no abre (data-nash-viaja); o convite é irmão do campo, não filho —
   ocupa a mesma área de grid mas nunca recebe o transform da viagem. Só a
   opacidade dele muda, nunca a posição: viajar e esmaecer ao mesmo tempo,
   em poucos quadros, lia como perda de quadro mesmo sem jank de verdade. */
.nash-prompt-convite {
  transition: opacity 140ms var(--nash-curva-saida);
}

.nash-prompt--aberta .nash-prompt-convite,
.nash-prompt--com-texto .nash-prompt-convite {
  opacity: 0;
}

.nash-prompt-marca {
  transition:
    grid-template-columns var(--nash-dur-abre) var(--nash-curva-espacial),
    gap var(--nash-dur-abre) var(--nash-curva-espacial),
    padding var(--nash-dur-abre) var(--nash-curva-espacial),
    transform var(--nash-dur-solta) var(--nash-curva-saida),
    background-color var(--nash-dur-estado) var(--nash-curva-saida);
}

.nash-prompt-rotulo {
  opacity: 0;
  transition: opacity var(--nash-dur-abre) var(--nash-curva-espacial);
}

.nash-prompt--aberta .nash-prompt-rotulo {
  opacity: 1;
}

/* data-seco: o quadro em que a barra troca de estado sem animar (foco
   vindo do teclado). motion.js põe, força o reflow e tira. */
.nash-prompt[data-seco],
.nash-prompt[data-seco] * {
  transition: none !important;
}

/* ---------- envia — "foi" ----------
   nashMotion.envia(el): o anel do botão de enviar acende (o concluído), o
   texto esmaece em 180 ms, o campo esvazia e a barra fecha (abre, false)
   com a aura ocupada — respirando 3× — até quem consome chamar
   nashMotion.ocupado(el, false). Dispara o evento 'nash-envia' com o texto
   no detail; é aí que a Gen UI começa. */
.nash-prompt-campo textarea {
  transition:
    height var(--nash-dur-expande) var(--nash-curva-saida),
    opacity var(--nash-dur-estado) var(--nash-curva-saida);
}

.nash-prompt[data-estado='ocupado'] .nash-prompt-envia .nash-botao {
  pointer-events: none;
}

/* ---------- ancora — "agora é o console" ----------
   nashMotion.ancora(palco, estado): troca data-estado do Palco e a barra
   viaja do centro pro rodapé (FLIP, transform, 560 ms — a distância é
   grande, o tempo segue a distância). O trilho de sugestões aparece acima
   dela com o chega. Uma vez por geração; de volta ao centro só no limpar. */

/* ---------- chega — "a IA gerou isto, agora" ----------
   Um cartão gerado entra: opacidade 0 > 1, 12px de baixo pra cima e escala
   0,97 > 1, em 520 ms; irmãos entram em fila, --nash-ordem × --nash-passo
   (70 ms) depois de --nash-atraso (o consumidor ajusta pra sobrepor com o
   ancora). Por dentro, o cartão se desenha depois que chegou: barras sobem
   (scaleY da base), a rosca varre (--nash-varre no mask), a linha se
   revela (clip-path) e as bolhas brotam de 0,5 — nunca de zero: nada no
   mundo nasce do nada. Uma vez por evento, nunca em laço. */
.nash-chega {
  animation: nash-chega var(--nash-dur-chega) var(--nash-curva-saida) both;
  animation-delay: calc(var(--nash-atraso, 0ms) + var(--nash-ordem, 0) * var(--nash-passo));
}

@keyframes nash-chega {
  from {
    opacity: 0;
    transform: translateY(12px) scale(0.97);
  }
}

.nash-chega .nash-sobe,
.nash-chega .nash-varre,
.nash-chega .nash-revela,
.nash-chega .nash-brota,
.nash-chega .nash-entra {
  animation-duration: var(--nash-dur-chega);
  animation-timing-function: var(--nash-curva-saida);
  animation-fill-mode: both;
  animation-delay: calc(
    var(--nash-atraso, 0ms) + var(--nash-ordem, 0) * var(--nash-passo) + 160ms +
      var(--nash-i, 0) * var(--nash-passo) / 2
  );
}

.nash-chega .nash-sobe {
  transform-origin: bottom;
  animation-name: nash-sobe;
}

@keyframes nash-sobe {
  from {
    transform: scaleY(0);
  }
}

@property --nash-varre {
  syntax: '<angle>';
  inherits: false;
  initial-value: 360deg;
}

.nash-chega .nash-varre {
  animation-name: nash-varre;
}

@keyframes nash-varre {
  from {
    --nash-varre: 0deg;
  }

  to {
    --nash-varre: 360deg;
  }
}

.nash-chega .nash-revela {
  animation-name: nash-revela;
}

@keyframes nash-revela {
  from {
    clip-path: inset(0 100% 0 0);
  }

  to {
    clip-path: inset(0 0 0 0);
  }
}

.nash-chega .nash-brota {
  animation-name: nash-brota;
}

@keyframes nash-brota {
  from {
    opacity: 0;
    transform: scale(0.5);
  }
}

.nash-chega .nash-entra {
  animation-name: nash-entra;
}

@keyframes nash-entra {
  from {
    opacity: 0;
    transform: translateX(-6px);
  }
}

/* ---------- some — "deu lugar" ----------
   O que sai só apaga: opacidade a 0 em 160 ms, mais rápido do que chegou.
   Quem consome troca o conteúdo quando a transição termina. */
.nash-some {
  opacity: 0;
  transition: opacity var(--nash-dur-some) var(--nash-curva-saida);
}

/* ---------- conta — "a IA calculou" ----------
   nashMotion.conta(el, alvo, ms): o número sobe de 0 até o alvo em 520 ms
   pela curva de saída, com font-variant-numeric: tabular-nums pra não
   mexer no layout. Com movimento reduzido chega inteiro. */
.nash-conta {
  font-variant-numeric: tabular-nums;
}

/* ---------- giro — "vai fechar" ----------
   ---------- realce — "esse ícone é a ação" ----------
   No Icon Button de fechar o × inclina 15° no hover — um nudge, não um
   giro inteiro; nos outros o ícone cresce 5%. Um ou outro, nunca os
   dois. */
.nash-giro .nash-icone,
.nash-realce .nash-icone {
  transition: transform var(--nash-dur-micro) var(--nash-curva-saida);
}

.nash-giro:hover .nash-icone {
  transform: rotate(15deg);
}

.nash-realce:hover .nash-icone {
  transform: scale(1.05);
}

/* ---------- foco — "o teclado está aqui" ----------
   Anel no accent, sem animação: quem chega pelo teclado já está à frente
   da tela, e animar a resposta a deixa atrás. */
.nash-botao:focus-visible {
  outline: 2px solid var(--accent, #4dc9ff);
  outline-offset: 2px;
  transition: none;
}

/* ---------- reduzido — "mesmo estado, menos movimento" ----------
   Com prefers-reduced-motion, ou com a classe .nash-reduzido num
   ancestral: cor e opacidade ainda mudam, em 100 ms; sem escala, sem
   lampejo; o arco para no quadro do Figma. Duração zero seria um corte,
   e corte também incomoda. */
@media (prefers-reduced-motion: reduce) {
  .nash-botao,
  .nash-botao:active,
  .nash-placa::before,
  .nash-placa::after,
  .nash-ponto,
  .nash-anel,
  .nash-bolinha,
  .nash-desperta .nash-icone,
  .nash-giro .nash-icone,
  .nash-realce .nash-icone,
  .nash-cresce,
  .nash-halo,
  .nash-prompt,
  .nash-prompt [data-nash-viaja],
  .nash-prompt-marca,
  .nash-prompt-rotulo,
  .nash-prompt-convite,
  .nash-prompt-campo textarea,
  .nash-some {
    transition-duration: 100ms;
    transition-timing-function: var(--nash-curva-saida);
  }

  .nash-pressao:active,
  .nash-giro:hover .nash-icone,
  .nash-realce:hover .nash-icone {
    transform: none;
  }

  .nash-lampejo:hover .nash-luz::before,
  .nash-anel.nash-concluido,
  .nash-cursor,
  .nash-chega .nash-sobe,
  .nash-chega .nash-varre,
  .nash-chega .nash-revela,
  .nash-chega .nash-brota,
  .nash-chega .nash-entra {
    animation: none;
  }

  .nash-arco::before {
    animation-play-state: paused;
  }

  .nash-aura .nash-halo {
    animation: none;
    opacity: 0.6;
  }

  .nash-aura:focus-within::after,
  .nash-aura[data-estado='ocupado']::after {
    animation-play-state: paused;
  }

  .nash-chega {
    animation-name: nash-chega-reduzido;
    animation-duration: 100ms;
  }
}

/* O chega reduzido só muda opacidade, pro estado final: nada se desloca,
   e a informação — "isto acabou de chegar" — continua dita. */
@keyframes nash-chega-reduzido {
  from {
    opacity: 0;
  }
}

.nash-reduzido .nash-botao,
.nash-reduzido .nash-botao:active,
.nash-reduzido .nash-placa::before,
.nash-reduzido .nash-placa::after,
.nash-reduzido .nash-ponto,
.nash-reduzido .nash-anel,
.nash-reduzido .nash-bolinha,
.nash-reduzido .nash-desperta .nash-icone,
.nash-reduzido .nash-giro .nash-icone,
.nash-reduzido .nash-realce .nash-icone,
.nash-reduzido .nash-cresce,
.nash-reduzido .nash-halo,
.nash-reduzido .nash-prompt,
.nash-reduzido .nash-prompt [data-nash-viaja],
.nash-reduzido .nash-prompt-marca,
.nash-reduzido .nash-prompt-rotulo,
.nash-reduzido .nash-prompt-convite,
.nash-reduzido .nash-prompt-campo textarea,
.nash-reduzido .nash-some {
  transition-duration: 100ms;
  transition-timing-function: var(--nash-curva-saida);
}

.nash-reduzido .nash-pressao:active,
.nash-reduzido .nash-giro:hover .nash-icone,
.nash-reduzido .nash-realce:hover .nash-icone {
  transform: none;
}

.nash-reduzido .nash-lampejo:hover .nash-luz::before,
.nash-reduzido .nash-anel.nash-concluido,
.nash-reduzido .nash-cursor,
.nash-reduzido .nash-chega .nash-sobe,
.nash-reduzido .nash-chega .nash-varre,
.nash-reduzido .nash-chega .nash-revela,
.nash-reduzido .nash-chega .nash-brota,
.nash-reduzido .nash-chega .nash-entra {
  animation: none;
}

.nash-reduzido .nash-arco::before {
  animation-play-state: paused;
}

.nash-reduzido .nash-aura .nash-halo {
  animation: none;
  opacity: 0.6;
}

.nash-reduzido .nash-aura:focus-within::after,
.nash-reduzido .nash-aura[data-estado='ocupado']::after {
  animation-play-state: paused;
}

.nash-reduzido .nash-chega {
  animation-name: nash-chega-reduzido;
  animation-duration: 100ms;
}

/* ===== acréscimos do site (fora do artefato) =====
   Duas peças sem equivalente em src/renderer/motion.css, mantidas do porte
   de 2026-09-08 porque outras páginas do site dependem delas — não fazem
   parte dos "componentes" revertidos acima. */

/* ---------- revela — "este bloco chegou à tela" (novo no site) ----------
   Uma revelação por scroll: opacidade e 24px de subida, na curva espacial,
   em --nash-dur-revela, com --nash-ordem para irmãos em fila. Nada além de
   transform e opacity. nash-motion.js põe .is-visivel quando o bloco cruza
   18% da tela, uma vez só — o que já chegou não vai embora ao rolar de
   volta, porque um bloco que some e volta cobra atenção sem dizer nada. */
.nash-revela {
  transition:
    opacity var(--nash-dur-revela) var(--nash-curva-espacial),
    transform var(--nash-dur-revela) var(--nash-curva-espacial);
  transition-delay: calc(var(--nash-ordem, 0) * var(--nash-passo));
}

/* Só nasce escondido onde o JS vai revelar (html.js entra no <head>);
   sem JS a página inteira já está lá. */
html.js .nash-revela {
  opacity: 0;
  transform: translateY(24px);
}

html.js .nash-revela.is-visivel {
  opacity: 1;
  transform: none;
}

/* ---------- cursor — "o ponteiro é parte da cena" (novo no site) ----------
   Um anel de 28px e um ponto de 4px seguem o ponteiro; sobre algo clicável
   o anel cresce, sobre texto vira uma barra, ao apertar encolhe. Só em
   ponteiros finos com hover — no toque não existe —, e nunca quando o
   sistema pede contraste ou cores forçadas: aí o ponteiro do sistema é a
   acomodação de quem o configurou (nash-motion.js). nash-motion.js move os
   dois por transform; o anel é uma caixa fixa de 28px e quem cresce é o
   traço (<i>) por transform, e a barra (<b>) troca por opacidade — nada de
   width, height ou margin em movimento. */
.nash-cursor-anel,
.nash-cursor-ponto {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 9999;
  pointer-events: none;
  border-radius: 50%;
  mix-blend-mode: difference;
  opacity: 0;
  will-change: transform;
}

.nash-cursor-anel {
  width: 28px;
  height: 28px;
  margin: -14px 0 0 -14px;
  transition:
    opacity var(--nash-dur-estado) var(--nash-curva-saida),
    scale var(--nash-dur-pressao) var(--nash-curva-saida);
}

.nash-cursor-anel > i {
  position: absolute;
  inset: -14px;
  border: 1px solid #fff;
  border-radius: 50%;
  transform: scale(0.5);
  transition:
    transform var(--nash-dur-estado) var(--nash-curva-saida),
    opacity var(--nash-dur-estado) var(--nash-curva-saida),
    background-color var(--nash-dur-estado) var(--nash-curva-saida);
}

.nash-cursor-anel > b {
  position: absolute;
  inset: 0 auto;
  left: 13px;
  width: 2px;
  border-radius: 1px;
  background: #fff;
  opacity: 0;
  transition: opacity var(--nash-dur-estado) var(--nash-curva-saida);
}

.nash-cursor-ponto {
  width: 4px;
  height: 4px;
  margin: -2px 0 0 -2px;
  background: #fff;
  transition: opacity var(--nash-dur-micro) var(--nash-curva-saida);
}

html.tem-cursor .nash-cursor-anel,
html.tem-cursor .nash-cursor-ponto {
  opacity: 1;
}

/* Sobre algo clicável o anel cresce e o ponto fica: é ele que marca o
   hotspot, justamente onde a precisão importa. */
html.tem-cursor.cursor-sobre .nash-cursor-anel > i {
  transform: none;
  background-color: rgba(255, 255, 255, 0.12);
}

html.tem-cursor.cursor-texto .nash-cursor-anel > i {
  opacity: 0;
}

html.tem-cursor.cursor-texto .nash-cursor-anel > b {
  opacity: 1;
}

html.tem-cursor.cursor-texto .nash-cursor-ponto {
  opacity: 0;
}

/* Pressão — "registrou": scale é independente de transform, então compõe
   com o translate que o JS grava a cada quadro. */
html.tem-cursor.cursor-pressiona .nash-cursor-anel {
  scale: 0.85;
}

/* cursor: none chega aos descendentes só por herança; o que declara cursor
   próprio (.copiavel, .nash-botao, :disabled) ganharia dois ponteiros. */
@media (hover: hover) and (pointer: fine) {
  html.tem-cursor,
  html.tem-cursor *,
  html.tem-cursor .nash-botao:disabled {
    cursor: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  html.js .nash-revela,
  .nash-cursor-anel,
  .nash-cursor-anel > i,
  .nash-cursor-anel > b,
  .nash-cursor-ponto {
    transition-duration: 100ms;
    transition-delay: 0ms;
    transition-timing-function: var(--nash-curva-saida);
  }

  html.js .nash-revela {
    transform: none;
  }
}
