/* Grupo Dls/ - formulário de contato
   Rótulo acima do campo, ajuda abaixo do rótulo, erro abaixo do campo.
   Nunca placeholder no lugar de rótulo. */

.form {
  display: grid;
  gap: var(--sp-5);
}

/* `align-items: start` para os dois campos da linha não esticarem um
   pelo outro quando só um deles ganha mensagem de erro. */
.form__row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-5);
  align-items: start;
}

.field {
  display: grid;
  gap: var(--sp-2);
}

/* Marcador de obrigatório. Amarelo porque é a cor de sinal do sistema, e
   `aria-hidden` seria errado aqui: quem usa leitor de tela também
   precisa saber quais campos são obrigatórios - e o `required` do HTML
   já diz isso pela via correta. */
.field__req {
  color: var(--c-yellow);
}

.form__nota {
  font-size: var(--fs-small);
  color: rgba(255, 255, 255, 0.62);
}

/* `:not(.tag)` porque a pílula de frente também é um `label`, e não é um
   rótulo de campo: ela é o próprio controle. Sem a exceção ela herdaria
   caixa alta, corpo de rótulo e cinza - e viraria um rótulo com borda. */
.field label:not(.tag) {
  font-size: var(--fs-label);
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.72);
}

.field input,
.field select,
.field textarea {
  width: 100%;
  padding: 0.95em 1.1em;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.24);
  border-radius: var(--r-input);
  color: var(--c-white);
  font-size: var(--fs-body);
  transition:
    border-color var(--dur-micro) var(--ease-out),
    background-color var(--dur-micro) var(--ease-out);
}

.field textarea {
  min-height: 118px;
  resize: vertical;
}

/* Placeholder com contraste real. Cinza fraco sobre fundo escuro é
   a falha de acessibilidade mais comum em formulário bonito. */
.field ::placeholder {
  color: rgba(255, 255, 255, 0.46);
}

.field input:hover,
.field select:hover,
.field textarea:hover {
  border-color: rgba(255, 255, 255, 0.42);
}

.field input:focus-visible,
.field select:focus-visible,
.field textarea:focus-visible {
  outline: 2px solid var(--c-yellow);
  outline-offset: 2px;
  background: rgba(255, 255, 255, 0.08);
}

.field select {
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, rgba(255, 255, 255, 0.7) 50%),
    linear-gradient(135deg, rgba(255, 255, 255, 0.7) 50%, transparent 50%);
  background-position:
    calc(100% - 22px) calc(50% + 2px),
    calc(100% - 16px) calc(50% + 2px);
  background-size: 6px 6px;
  background-repeat: no-repeat;
  padding-right: 3rem;
}

.field select option {
  background: #111;
  color: var(--c-white);
}

/* ---------- seleção de frentes por tags ----------
   Mesma pílula do resto do sistema. Por baixo há um checkbox de
   verdade: é ele que guarda o estado, entra no FormData e responde ao
   teclado. A pílula é só a roupa - `appearance: none` esticado sobre a
   caixa inteira mantém o alvo de toque do tamanho do que se vê.

   Fieldset em bloco e não em grid: o `legend` não é item de grid em
   todos os navegadores, e num fieldset em grid ele sai do espaçamento
   e cria um degrau que só aparece em um deles. */
.field--tags {
  display: block;
  margin: 0;
  padding: 0;
  border: 0;
}

.field--tags legend {
  padding: 0;
  font-size: var(--fs-label);
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.72);
}

.tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  margin-top: var(--sp-4);
}

.tag {
  position: relative;
  display: inline-flex;
  align-items: center;
  padding: 0.72em 1.3em;
  border: 1px solid rgba(255, 255, 255, 0.24);
  border-radius: var(--r-pill);
  font-size: var(--fs-small);
  line-height: 1;
  cursor: pointer;
  transition:
    background-color var(--dur-base) var(--ease-out),
    border-color var(--dur-base) var(--ease-out),
    color var(--dur-base) var(--ease-out);
}

.tag input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  appearance: none;
  border-radius: inherit;
  opacity: 0;
  cursor: pointer;
}

.tag:hover {
  border-color: rgba(255, 255, 255, 0.5);
}

.tag:has(input:checked) {
  background: var(--c-white);
  border-color: var(--c-white);
  color: var(--c-black);
}

.tag:has(input:focus-visible) {
  outline: 2px solid var(--c-yellow);
  outline-offset: 2px;
}

.field__help {
  font-size: var(--fs-small);
  color: rgba(255, 255, 255, 0.62);
}

/* O espaço da mensagem fica reservado desde sempre. Com `min-height: 0`
   a dica de campo obrigatório NASCIA dentro do fluxo e empurrava tudo
   o que vem embaixo: errar o e-mail fazia o telefone, a seleção de
   frentes e o botão pularem de lugar - e o pulo acontece justamente
   enquanto a pessoa ainda está lendo o erro.

   `1lh` é a altura de uma linha desta fonte neste corpo: reserva o
   necessário e nada além. */
.field__error {
  font-size: var(--fs-small);
  color: #ff9d9d;
  min-height: 1lh;
}

.field.has-error input,
.field.has-error select,
.field.has-error textarea {
  border-color: #ff9d9d;
}

/* Armadilha de robô. Fora da tela, fora da ordem de tabulação,
   fora do leitor de tela. Sem CAPTCHA: CAPTCHA é atrito e derruba
   conversão. */
.form__trap {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.form__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-5);
}

.form .btn {
  --btn-bg: var(--c-yellow);
  --btn-fg: var(--c-black);
  border-color: var(--c-yellow);
}

.form .btn:hover {
  --btn-bg: var(--c-white);
  --btn-fg: var(--c-black);
  border-color: var(--c-white);
}

.form .btn[disabled] {
  opacity: 0.55;
  cursor: progress;
}

/* Estados. O formulário nunca fica mudo: enviando, enviado e falhou
   têm mensagem própria, com o texto exato do copy. */
.form__status {
  font-size: var(--fs-small);
  line-height: 1.5;
}

.form__status:empty {
  display: none;
}

.form__status[data-state="sending"] {
  color: rgba(255, 255, 255, 0.7);
}

.form__status[data-state="ok"] {
  color: var(--c-lime);
}

.form__status[data-state="error"] {
  color: #ff9d9d;
}

/* Esqueleto de envio: a forma do que vem, não um giro genérico. */
.form.is-sending .field input,
.form.is-sending .field select,
.form.is-sending .field textarea {
  opacity: 0.55;
}

@media (max-width: 620px) {
  .form__row {
    grid-template-columns: 1fr;
  }
}

/* ============================================================
   toast
   O aviso flutuante de confirmação. Ver `components/toast.js`
   para a divisão: erro fica na tira, confirmação sobe aqui.

   POR QUE ELE MORA NESTA FOLHA, e não numa própria. Ele é
   carregado exatamente onde há formulário - as quatro páginas
   que trazem `form.css` são as quatro que enviam alguma coisa -,
   e uma folha nova custaria um `<link>` em cada uma delas para
   entregar quarenta linhas. No dia em que algo fora de
   formulário precisar de um aviso, ele sobe para `layout.css`
   com a marcação intacta.
   ============================================================ */

/* A região viva. Nasce vazia no boot e nunca recebe estilo de caixa:
   ela é só o lugar onde o aviso aparece, e `pointer-events: none`
   garante que um retângulo invisível no canto da tela não roube
   clique de nada que esteja embaixo. */
.toast-area {
  position: fixed;
  z-index: var(--z-toast);
  right: var(--sp-5);
  bottom: max(var(--sp-5), env(safe-area-inset-bottom));
  left: auto;
  display: grid;
  justify-items: end;
  pointer-events: none;
}

/* Superfície escura fixa, e não os tokens da página. O aviso flutua
   sobre chão claro (a /contato) e sobre chão escuro (a home), e uma
   caixa que troca de cor junto com a página some numa das duas. Preto
   com texto branco mede 21:1 em qualquer fundo. */
.toast {
  pointer-events: auto;
  display: flex;
  align-items: flex-start;
  gap: var(--sp-4);
  max-width: min(28rem, calc(100vw - var(--sp-5) * 2));
  padding: var(--sp-5);
  border-radius: 12px;
  border-left: 3px solid var(--c-lime);
  background: var(--c-black);
  color: var(--c-white);
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.32);
  animation: toast-entra var(--dur-base) var(--ease-out) both;
}

.toast__texto {
  font-size: var(--fs-small);
  line-height: 1.5;
}

.toast__fechar {
  flex: none;
  width: 28px;
  height: 28px;
  margin: -2px -4px 0 0;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--c-gray-on-dark);
  cursor: pointer;
  touch-action: manipulation;
}

.toast__fechar svg {
  width: 15px;
  height: 15px;
  pointer-events: none;
}

.toast__fechar:hover {
  color: var(--c-white);
}

.toast :focus-visible {
  outline: 2px solid var(--c-white);
  outline-offset: 2px;
  box-shadow: none;
}

@keyframes toast-entra {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}

@keyframes toast-sai {
  from { opacity: 1; transform: none; }
  to   { opacity: 0; transform: translateY(8px); }
}

.toast.is-saindo {
  animation: toast-sai var(--dur-micro) var(--ease-out) both;
}

/* Sem movimento: o aviso aparece e some, sem deslizar. O script
   também para de esperar `animationend` neste caso - sem animação, o
   evento não chega, e o aviso ficaria preso. */
@media (prefers-reduced-motion: reduce) {
  .toast,
  .toast.is-saindo {
    animation: none;
  }
}

/* No celular ele ocupa a largura, encostado nas duas margens: uma
   caixa de 28rem alinhada à direita numa tela de 375 deixa uma faixa
   morta à esquerda e empurra o texto para uma coluna estreita. */
@media (max-width: 620px) {
  .toast-area {
    right: var(--sp-4);
    left: var(--sp-4);
    bottom: max(var(--sp-4), env(safe-area-inset-bottom));
    justify-items: stretch;
  }

  .toast {
    max-width: none;
  }
}
