/* Botão, campo, seleção e menu suspenso. As primitivas que as telas compõem. */

/* why: o botão Win32 é chanfrado para fora em repouso e para dentro ao ser pressionado — a borda
   inteira troca de lado, e é essa inversão que dá o clique. Sem `:active` ele vira uma caixa
   cinza que não responde. */
.button {
  min-height: var(--chrome-height);
  padding: var(--space-tight) var(--space-loose);
  border: 1px solid;
  border-color: var(--bevel-light) var(--bevel-shadow-deep) var(--bevel-shadow-deep)
    var(--bevel-light);
  background: var(--chrome);
  color: var(--text);
  font: inherit;
  cursor: pointer;
}

.button:hover:not(:disabled) {
  background: var(--surface-band);
}

.button:active:not(:disabled) {
  border-color: var(--bevel-shadow-deep) var(--bevel-light) var(--bevel-light)
    var(--bevel-shadow-deep);
  /* why: o deslocamento de 1px é o que faz o rótulo afundar junto com a borda. Sem ele o texto
     fica parado numa caixa que se moveu, e o clique parece falha de pintura. */
  padding: calc(var(--space-tight) + 1px) var(--space-loose) calc(var(--space-tight) - 1px);
}

.button:disabled {
  color: var(--text-disabled);
  cursor: default;
}

.button--default {
  border-color: var(--accent);
  font-weight: 600;
}

/* why: destrutivo não ganha fundo vermelho. `ui-ux.md` proíbe carregar significado só na cor, e o
   Win32 nunca teve botão colorido — o que separa excluir de salvar é a palavra, a posição e a
   confirmação que a T9.4 exige antes de apagar. A borda só marca o par. */
.button--destructive {
  border-color: var(--status-overdue);
}

.button--flat {
  border-color: transparent;
  background: none;
}

.button--flat:hover:not(:disabled) {
  border-color: var(--border);
  background: var(--surface-band);
}

/* O campo é S-1: um poço cortado na superfície que o contém, e a recessão anda para o mesmo lado
   nos dois temas porque uma depressão perde luz em qualquer escala. */
.field {
  display: flex;
  flex-direction: column;
  gap: var(--space-tight);
  margin-bottom: var(--space-snug);
}

/* why: rótulo acima do controle, e nunca `placeholder` no lugar dele — o placeholder desaparece
   no instante em que a pessoa digita, que é exatamente quando ela precisa dele. */
.field__label {
  font-weight: 600;
}

.field__label--required::after {
  content: ' *';
  color: var(--status-overdue);
}

/* why: texto de ajuda é permanente, não tooltip. Se o campo precisa de explicação para ser
   preenchido certo, a explicação faz parte do campo. O erro ocupa esta mesma linha, então a
   altura da fileira não pula quando a validação falha. */
.field__help {
  min-height: 1.2em;
  color: var(--text-muted);
  font-size: var(--font-size-small);
}

.field__help--invalid {
  color: var(--status-overdue);
  font-weight: 600;
}

.input,
.select,
.textarea {
  min-height: var(--chrome-height);
  padding: var(--space-tight) var(--space-snug);
  border: 1px solid;
  border-color: var(--bevel-shadow-deep) var(--bevel-light) var(--bevel-light)
    var(--bevel-shadow-deep);
  background: var(--surface);
  color: var(--text);
  font: inherit;
}

.input:disabled,
.select:disabled,
.textarea:disabled {
  background: var(--chrome);
  color: var(--text-disabled);
}

.input.invalid,
.select.invalid,
.textarea.invalid {
  border-color: var(--status-overdue);
}

/* why: a largura do campo ensina o que se espera antes da primeira tecla. Um CEP com a largura da
   linha promete um texto longo que ele vai recusar. */
.input--narrow {
  max-width: 12ch;
}

.input--medium {
  max-width: 24ch;
}

.textarea {
  min-height: calc(var(--chrome-height) * 3);
  resize: vertical;
}

.checkbox {
  display: flex;
  align-items: center;
  gap: var(--space-snug);
  cursor: pointer;
}

/* O farol de situação: uma bolinha cheia seguida do nome do estado.

   why: o nome ao lado, e não a bolinha sozinha. Três matizes numa coluna estreita exigem que quem
   lê já conheça a convenção, e quem abre o programa pela primeira vez não conhece — foi o que
   derrubou a primeira versão, que usava três formas diferentes. Com a leitura fora da cor, a matiz
   fica livre para ser viva, e o nome usa a cor de texto da célula, que é a que a paleta garante
   legível contra a faixa alternada e contra a seleção.
   why: as três matizes são exceção documentada à regra de derivar tudo dos tokens de tema. Estado
   precisa de significado fixo, e um tema não pode repintá-lo. */
.status-light {
  display: inline-flex;
  align-items: center;
  gap: var(--space-snug);
}

/* why: um círculo em SVG e não o caractere `●`. A fonte que o sistema resolve não precisa ter o
   glifo, e quando não tem vira um retângulo vazio — foi o que o head desktop viu sob Wine.
   Geometria não depende de fonte instalada. */
.status-light__dot {
  width: 8px;
  height: 8px;
  flex-shrink: 0;
}

.status-light__dot--settled {
  color: var(--status-settled);
}

.status-light__dot--open {
  color: var(--status-open);
}

.status-light__dot--overdue {
  color: var(--status-overdue);
}

/* O menu suspenso serve a barra de menu, o `Ações` da toolbar e o menu por linha da grade. Um só
   desenho, porque os três são a mesma coisa e o operador não deveria aprender três. */
.menu {
  position: absolute;
  z-index: 20;
  min-width: 180px;
  padding: var(--space-hairline);
  border: 1px solid;
  border-color: var(--bevel-light) var(--bevel-shadow-deep) var(--bevel-shadow-deep)
    var(--bevel-light);
  background: var(--surface);
  /* why: a única sombra da skin, e ela é dura de propósito. O Win32 projetava um retângulo cinza
     deslocado, sem desfoque; uma sombra suave aqui seria a estética errada por vinte anos. */
  box-shadow: 2px 2px 0 rgb(0 0 0 / 25%);
}

/* O véu que fecha o menu no clique fora, invisível e do tamanho da janela.

   why: **HTML, e não uma função nova no `shortcuts.js`.** O backlog previa o contrário — o módulo
   já tem ouvinte no documento, então a captura sairia barata —, mas a regra que admite JavaScript
   neste head é a fronteira e não o preço: só entra ali o que o C# não alcança, e um elemento que
   recebe clique é justamente o que ele alcança. De brinde, o véu morre junto com o menu, sem
   registro para desfazer nem ouvinte sobrevivendo a um componente descartado.
   why: um degrau abaixo do `.menu` no `z-index`, para ficar sob o menu e sobre o resto. Igualar os
   dois deixaria a ordem por conta do documento, e o menu por linha nasce antes do véu. */
.menu-veil {
  position: fixed;
  inset: 0;
  z-index: 19;
}

.menu__item {
  display: flex;
  align-items: center;
  gap: var(--space-snug);
  width: 100%;
  padding: var(--space-tight) var(--space-loose);
  border: none;
  background: none;
  color: var(--text);
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.menu__item:hover:not(:disabled),
.menu__item:focus-visible {
  background: var(--selection);
}

.menu__item:disabled {
  color: var(--text-disabled);
  cursor: default;
}

/* why: a marca do item escolhido é o `✓` do Win32, num vão reservado. Reservar largura é o que
   impede a lista inteira de deslizar 14px quando o operador troca de tema. */
.menu__item::before {
  content: '';
  width: 14px;
  flex-shrink: 0;
}

.menu__item--checked::before {
  content: '✓';
}

.menu__separator {
  height: 1px;
  margin: var(--space-hairline) 0;
  background: var(--bevel-shadow);
  border-bottom: 1px solid var(--bevel-light);
}

/* O diálogo modal, que a edição, o filtro e o assistente de importação compartilham.

   why: um `<div>` sobre um véu, e não o `<dialog>` nativo. `showModal()` só existe em JavaScript, e
   uma chamada de interop por diálogo aberto pagaria um salto de thread para conseguir o que o
   posicionamento já dá. O que o nativo entregaria de graça — foco preso, `Esc`, inerte atrás — os
   componentes de diálogo assumem explicitamente. */
.dialog-overlay {
  position: fixed;
  inset: 0;
  z-index: 30;
  display: grid;
  place-items: center;
  padding: var(--space-loose);
  /* why: `rgba(0,0,0,0.6)` acumula com a superfície escura e produz a região morta que
     `ui-ux.md` chama de buraco negro. O véu cinza funciona nos dois temas porque quem muda é a
     superfície de baixo, não ele. */
  background: rgb(128 128 128 / 40%);
}

.dialog {
  max-width: min(560px, 100%);
  max-height: 90dvh;
  overflow: auto;
  padding: 0;
  border: 1px solid;
  border-color: var(--bevel-light) var(--bevel-shadow-deep) var(--bevel-shadow-deep)
    var(--bevel-light);
  background: var(--surface);
  color: var(--text);
}

.dialog__title {
  padding: var(--space-tight) var(--space-snug);
  background: var(--accent);
  color: var(--accent-contrast);
  font-weight: 600;
}

.dialog__body {
  padding: var(--space-loose);
}

.dialog__footer {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-snug);
  padding: var(--space-snug) var(--space-loose) var(--space-loose);
}

/* A lista de rótulo e valor que os diálogos de leitura usam.

   why: grade de duas colunas, e não `<dl>` no fluxo padrão, onde o `<dd>` nasce indentado abaixo do
   `<dt>` e o par se lê como dois parágrafos soltos. A coluna do rótulo é `auto` para acompanhar a
   palavra mais longa sem número mágico.
   why: nasceu com escopo de tela na T8 e subiu para cá na T9, quando ganhou o segundo diálogo de
   leitura. Detalhe de usuário e detalhe de título mostram a mesma anatomia. */
.detail-list {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-tight) var(--space-loose);
  margin: 0 0 var(--space-snug);
}

.detail-list dt {
  color: var(--text-muted);
}

.detail-list dd {
  margin: 0;
  font-weight: 600;
}
