/* Ábaco, aplicação: navegação, listas, formulários.
   O básico (cores, tipografia, tela de entrada) está em abaco.css. */

body.app { background: var(--ground); }

.grade { max-width: 1160px; margin: 0 auto; padding: 0 1.25rem; }

/* O topo horizontal antigo (.topo, .menu, .sair) foi removido.
   A navegação vive agora no menu lateral em layout.css. */


/* ---------- cabeçalho de página ---------- */

/* O cabeçalho é compacto em TODA tela, sem exceção (pedido dele,
   13/09/2026: "aplique o cabeçalho de páginas mais compactos para todas as
   telas do sistema, sem exceção... as coisas precisam ser padronizadas").
   Nasceu como uma variante `.compacto` só para Hoje e Importar, e ele
   cortou essa ideia pela raiz, com razão: duas telas com um cabeçalho e
   quarenta com outro é justamente a falta de padrão que ele reclama.

   A conta: o cabeçalho antigo custava 79px de altura antes de qualquer
   conteúdo - título de 2.1rem em cima, subtítulo embaixo, 1.8rem de
   respiro. Agora os dois ficam na mesma linha, menores: ~33px. São 46px
   devolvidos em cada uma das 42 telas. */
.pagina-topo {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: .5rem 1.2rem;
  margin-bottom: .9rem;
  flex-wrap: wrap;
}

/* O primeiro filho é sempre o bloco de identidade da tela (título +
   subtítulo); o segundo, quando existe, é ação ou filtro e continua
   empurrado para a direita pelo `space-between`.

   `flex: 1 1 16rem` não é detalhe: sem uma base pequena, o bloco de
   identidade pede a largura do título MAIS o subtítulo inteiro numa linha
   só, e o irmão (botões, abas, filtro) não cabe e **desce para outra
   linha** - foi o que aconteceu em Veículos, cujo subtítulo é longo:
   o cabeçalho foi de 79px para 141px, o dobro do que devia. Com base
   pequena, o bloco de identidade cede espaço e quebra dentro de si mesmo,
   e o irmão fica onde sempre esteve, à direita. Medido tela a tela. */
.pagina-topo > div:first-child {
  display: flex;
  align-items: baseline;
  gap: .6rem;
  flex-wrap: wrap;
  flex: 1 1 16rem;
  min-width: 0;
}

h1.titulo {
  font-family: var(--f-display);
  font-weight: 700;
  font-size: 1.4rem;
  letter-spacing: -.02em;
  margin: 0;
  color: var(--ink);
}

.subtitulo {
  color: var(--ink-soft);
  font-size: .95rem;
  margin: .3rem 0 0;
  line-height: 1.45;
}

/* Dentro do cabeçalho o subtítulo vira a continuação da mesma linha do
   título, sem margem própria. Fora dele (`.subtitulo` solto em quatro
   telas) o respiro original continua valendo. */
.pagina-topo .subtitulo { font-size: .85rem; margin: 0; line-height: 1.4; }

/* ---------- tabela moderna ---------- */

.tabela-caixa {
  background: var(--carta-fundo);
  border: var(--carta-borda);
  border-radius: var(--carta-raio);
  box-shadow: var(--carta-sombra);
  overflow-x: auto;
  min-width: 0;              /* respeitar flex container pai */
}

table.lista { border-collapse: collapse; width: 100%; font-size: .88rem; }

table.lista thead th {
  font-family: var(--f-body);
  font-size: .72rem;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--ink-soft);
  background: var(--surface-alt);
  text-align: left;
  padding: .65rem .85rem;
  border-bottom: 1px solid var(--rule);
  white-space: nowrap;
  font-weight: 600;
}

table.lista td {
  padding: var(--linha-respiro);
  border-bottom: 1px solid var(--rule-soft);
  vertical-align: middle;
}

table.lista tbody tr:last-child td { border-bottom: 0; }
/* Zebra striping sutil estilo TradeMap */
table.lista tbody tr:nth-child(even) td { background: var(--surface-alt); }
table.lista tbody tr:hover td { background: color-mix(in oklab, var(--surface-alt) 40%, var(--surface)); }

table.lista thead th.valor,
table.lista th.valor,
td.valor, th.valor {
  text-align: right;
  font-family: var(--f-mono);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

td.data {
  font-family: var(--f-mono);
  font-size: .84rem;
  color: var(--ink-soft);
  white-space: nowrap;
}

.negativo { color: var(--good); font-weight: 600; }

.desc-principal { display: block; font-weight: 500; color: var(--ink); }
.desc-extra { font-size: .8rem; color: var(--ink-faint); margin-top: 1px; }

/* ---------- pílulas arredondadas (pills) ---------- */

.pilula {
  display: inline-flex;
  align-items: center;
  font-family: var(--f-body);
  font-size: .72rem;
  font-weight: 600;
  letter-spacing: .02em;
  padding: .2em .65em;
  border-radius: 99px;
  white-space: nowrap;
  background: var(--surface-alt);
  color: var(--ink-soft);
}
.pilula.cat { background: var(--accent-soft); color: var(--accent-forte); }
.pilula.parcela { background: var(--warm-soft); color: var(--warm); }
.pilula.andamento { background: var(--warm-soft); color: var(--warm); }
.pilula.pendente { background: var(--bad-soft); color: var(--bad); }
.pilula.ok { background: var(--good-soft); color: var(--good); }
/* "info": azul informativo, sem ligacao com o significado de nenhum token
   semantico (nao e bom nem ruim, so um dado a mais - FGTS, "na fatura",
   beneficiario do IR). Cinco lugares copiavam esta mesma cor solta num
   `style=""` cada um; achado na revisao de codigo de 10/09/2026. */
.pilula.info { background: rgba(2, 132, 199, .15); color: #0284c7; }
.pilula.info.contorno { background: rgba(2, 132, 199, .12); border: 1px solid rgba(2, 132, 199, .3); }
.pilula.ok.contorno { background: rgba(22, 163, 74, .12); color: #16a34a; border: 1px solid rgba(22, 163, 74, .3); }
.pilula.foto {
  background: var(--surface);
  color: var(--ink-soft);
  border: 1px solid var(--rule);
  text-decoration: none;
}
/* Tag solta (11/09/2026): mesmo roxo de `.borda-roxa` nos cartões de KPI,
   pra ficar reconhecível como "dimensão extra, fora da árvore de categoria"
   em qualquer tela onde aparecer. É link (filtra por ela ao clicar). */
.pilula.tag { background: rgba(124, 58, 237, .13); color: #7c3aed; text-decoration: none; }
.pilula.tag:hover { background: rgba(124, 58, 237, .22); }

/* Avatar de banco/corretora em Contas e Cartões: sem logo de verdade (ver
   `services/instituicoes.py`), só a letra sobre a cor oficial da marca - o
   suficiente pra reconhecer "de relance" numa lista comprida. */
.avatar-instituicao {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.6rem;
  height: 1.6rem;
  border-radius: 50%;
  font-family: var(--f-body);
  font-size: .74rem;
  font-weight: 700;
  color: #fff;
  text-shadow: 0 1px 1px rgb(0 0 0 / 0.25);
  flex-shrink: 0;
}
.pilula.foto:hover { color: var(--accent); border-color: var(--accent); }

/* ---------- painéis de resumo ---------- */

.cartoes-grade { display: grid; gap: 1.25rem; margin-bottom: 2rem; }
/* Só existia UM `@media (min-width: 640px) .cartoes-grade` de verdade: as
   duas regras de breakpoint fixo (repeat(2,1fr) e repeat(4,1fr), removidas
   aqui) ficavam sempre atrás desta no arquivo, então nunca venciam a
   cascata em nenhuma largura - código morto, mesma família de defeito que
   o `table.lista` e o tema claro duplicados (docs/PROMPT-UI.md, regra 4).
   220px também era estreito demais para valor monetário: "R$ 245.678,90"
   quebra bem no espaço depois do "R$", e o R$ some sozinho em cima do
   número (achado dele em Patrimônio → Investimentos e Dívidas →
   Financiamento, 13/09/2026, mesmo `cartao_kpi` nas duas telas). 240px cabe
   a maior string real do sistema nessa fonte; `white-space: nowrap` em
   `.cartao-kpi .painel-numero` abaixo é a segunda trava contra a mesma
   família. */
@media (min-width: 640px) { .cartoes-grade { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); } }

.painel {
  background: var(--carta-fundo);
  border: var(--carta-borda);
  border-radius: var(--carta-raio);
  box-shadow: var(--carta-sombra);
  padding: var(--painel-respiro);
  transition: transform var(--transicao), box-shadow var(--transicao);
}

.painel:hover {
  box-shadow: var(--carta-sombra-alta);
  transform: var(--carta-levanta);
}

.painel-rotulo {
  font-family: var(--f-body);
  font-size: .8rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--ink-soft);
  margin: 0 0 .5rem;
}

.painel-numero {
  font-family: var(--f-mono);
  font-size: var(--painel-numero-tamanho);
  font-weight: 800;
  letter-spacing: -.03em;
  font-variant-numeric: tabular-nums;
  display: block;
  line-height: 1.15;
  color: var(--ink);
}

.painel-nota { font-size: .84rem; color: var(--ink-faint); margin: .4rem 0 0; }

/* ---------- cartões de KPI padronizados (estilo veículos) ---------- */
.cartao-kpi {
  padding: 1.2rem;
  border-left: 4px solid var(--accent);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  border-radius: var(--raio);
  text-decoration: none;
  color: inherit;
}
.cartao-kpi.borda-acento   { border-left-color: var(--accent); }
.cartao-kpi.borda-azul     { border-left-color: #0284c7; }
.cartao-kpi.borda-verde    { border-left-color: #16a34a; }
.cartao-kpi.borda-laranja  { border-left-color: #d97706; }
.cartao-kpi.borda-roxa     { border-left-color: #7c3aed; }
.cartao-kpi.borda-vermelha { border-left-color: var(--bad); }

/* Mesma paleta de 5 cores acima (é o que já distingue os cartões de KPI),
   reaproveitada para distinguir tipo de custo dentro de uma lista ou barra
   - primeiro uso em Veículos > Composição dos Gastos, que pintava tudo com
   --accent (achado dele, 13/09/2026: "está tudo verde, colocar uma cor por
   tipo de custo"). Ordem cíclica: quem usa escolhe a cor por
   `loop.index0 % 6`, nunca por nome de categoria - a lista de tipos varia
   por usuário e por tela. */
.custo-cor-0 { background: var(--accent); }
.custo-cor-1 { background: #0284c7; }
.custo-cor-2 { background: #16a34a; }
.custo-cor-3 { background: #d97706; }
.custo-cor-4 { background: #7c3aed; }
.custo-cor-5 { background: var(--bad); }

.cartao-kpi .painel-rotulo {
  font-size: .75rem;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--ink-soft);
  font-weight: 600;
  margin: 0 0 .4rem;
}
.cartao-kpi .painel-numero {
  font-family: var(--f-mono);
  font-size: 1.8rem;
  font-weight: 700;
  color: var(--ink);
  line-height: 1.15;
  /* "R$ 1.234,56" tem espaço dentro - sem isto a coluna estreita quebra
     bem ali, e o R$ fica sozinho acima do número. */
  white-space: nowrap;
}
.cartao-kpi .painel-nota {
  font-size: .8rem;
  color: var(--ink-faint);
  margin: .4rem 0 0;
}

/* O quadradinho colorido que identifica a categoria numa lista. Estava
   escrito à mão, inline, em analise.html ("Detalhe por categoria"); virou
   classe quando Tendências passou a precisar do mesmo (13/09/2026, achado
   dele: "gráficos todos verdes da mesma cor"). A cor vem sempre do dado
   (`categoria.cor`), por isso continua no `style=` de quem usa. */
.ponto-categoria {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 2px;
  margin-right: .4rem;
  flex-shrink: 0;
}

/* ---------- barra de proporção ---------- */

.trilho {
  height: 8px;
  background: var(--surface-alt);
  border-radius: 99px;
  overflow: hidden;
  margin-top: .6rem;
}
.trilho span {
  display: block;
  height: 100%;
  background: linear-gradient(90deg, var(--accent), var(--accent-forte));
  border-radius: inherit;
}
.trilho span.alerta { background: var(--warm); }
.trilho span.estouro { background: var(--bad); }
.trilho span.confortavel { background: var(--good); }
.trilho span.razoavel { background: var(--accent); }
.trilho span.apertada { background: var(--warm); }
.trilho span.critica { background: var(--bad); }

.numero-grande {
  font-family: var(--f-display);
  font-size: 2.8rem;
  font-weight: 700;
  line-height: 1;
  color: var(--ink);
}

/* ---------- formulário ---------- */

.form-caixa {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--raio);
  padding: 1.4rem;
  max-width: 620px;
  width: 100%;
  box-sizing: border-box;
}

.linha-campos { display: grid; gap: 1rem; min-width: 0; }
/* 560px deixava "Como pagou" e "Cartao" um debaixo do outro no celular, e o
   formulario da tela Hoje - o mais usado que existe aqui - passava de duas
   telas de altura antes do botao Lancar. Os dois cabem lado a lado desde
   360px: sao um <select> curto cada. Medido em 24/09/2026 num iPhone de
   390px, a rolagem ate o botao caiu pela metade. */
@media (min-width: 360px) { .linha-campos.duas { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }
.linha-campos { gap: .7rem 1rem; }

.campo { min-width: 0; }

.campo input,
.campo select,
.campo textarea {
  width: 100%;
  max-width: 100%;
  box-sizing: border-box;
}

.campo select,
.campo textarea {
  font-family: var(--f-body);
  font-size: 1rem;
  padding: .62rem .75rem;
  border: 1px solid var(--rule);
  border-radius: var(--raio);
  background: var(--surface);
  color: var(--ink);
}
.campo select:focus, .campo textarea:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--surface);
  /* O mesmo anel do input, senao cada campo do formulario responde de um
     jeito ao foco. */
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--accent) 22%, transparent);
}

.campo .ajuda { font-size: .78rem; color: var(--ink-faint); }

input.dinheiro {
  font-family: var(--f-mono);
  font-size: 1.15rem;
  font-variant-numeric: tabular-nums;
}

.com-cifrao {
  display: flex;
  align-items: center;
  gap: .5rem;
  border: 1px solid var(--rule);
  border-radius: var(--raio);
  background: var(--surface);
  padding: 0 .8rem;
  width: 100%;
  max-width: 100%;
  box-sizing: border-box;
  transition: border-color var(--transicao), box-shadow var(--transicao), background var(--transicao);
}

.com-cifrao:hover {
  border-color: var(--ink-faint);
}

.com-cifrao:focus-within {
  border-color: var(--accent);
  background: var(--surface);
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--accent) 22%, transparent);
}

.com-cifrao span {
  font-family: var(--f-mono);
  font-size: .88rem;
  font-weight: 600;
  color: var(--ink-soft);
  flex-shrink: 0;
  user-select: none;
}

.com-cifrao input {
  flex: 1;
  border: 0 !important;
  background: transparent !important;
  padding: .62rem 0 !important;
  box-shadow: none !important;
  outline: none !important;
  color: var(--ink);
  min-width: 0;
}

.acoes-form { display: flex; gap: .9rem; align-items: center; margin-top: .4rem; }
.acoes-form .botao { width: auto; padding-left: 1.6rem; padding-right: 1.6rem; }

.link-discreto {
  font-family: var(--f-mono);
  font-size: .74rem;
  color: var(--ink-faint);
  text-decoration: none;
}
.link-discreto:hover { color: var(--ink); }

/* ---------- filtros ---------- */

/* O filtro e ferramenta, nao conteudo, e por isso encolheu.
 *
 * Ele: *"de forma geral, creio que os filtros sejam muito grandes e ocupem
 * muito espaco na tela que deveriam ser ocupados por coisas mais relevantes"*.
 *
 * Tinha razao: cada campo era um bloco com rotulo em cima, dentro de um cartao
 * com sombra, e em Lancamentos os seis campos comiam quase meia tela antes do
 * primeiro lancamento aparecer. Agora e uma faixa discreta - sem sombra, sem
 * cartao, com o rotulo miudo por cima do campo e os campos mais baixos. O que
 * ganha espaco e a lista, que e o que ele veio ver. */
/* Barra de filtros, compacta pelo mesmo motivo do cabeçalho (pedido dele,
   13/09/2026: "os filtros podem ser mais compactos também, economiza
   espaço assim"). Antes custava ~77px de altura: rótulo em cima, campo
   embaixo, respiro de sobra em cima e embaixo. Agora ~55px, sem trocar o
   desenho - o rótulo continua sendo a micro-caixa-alta que identifica cada
   filtro, só que o conjunto inteiro é mais apertado. */
.filtros {
  display: flex;
  gap: .35rem .5rem;
  flex-wrap: wrap;
  align-items: flex-end;
  margin-bottom: .7rem;
  padding: .4rem .6rem;
  background: var(--surface-alt);
  border: 1px solid var(--rule-soft);
  border-radius: var(--raio);
}
.filtros .campo { margin-bottom: 0; min-width: 0; gap: 0; }
.filtros .campo label {
  font-size: .62rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--ink-faint);
  margin-bottom: .1rem;
  display: block;
}
.filtros select, .filtros input {
  min-width: 112px;
  background: var(--surface-alt);
  border: 1px solid var(--rule);
  border-radius: var(--raio-sm);
  padding: .3rem .6rem;
  font-size: .82rem;
  font-weight: 500;
  color: var(--ink);
  transition: all var(--transicao);
}
.filtros select:hover, .filtros input:hover {
  border-color: var(--accent);
}
.filtros select:focus, .filtros input:focus {
  background: var(--surface);
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--accent) 18%, transparent);
}

/* ---------- barra de métricas estilo fintech/TradeMap ---------- */

.faixa-metricas {
  display: inline-flex;
  align-items: center;
  gap: 1.4rem;
  padding: .6rem 1.2rem;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--raio);
  margin-bottom: 1.1rem;
  box-shadow: var(--sombra);
  flex-wrap: wrap;
}

.metrica-item {
  display: flex;
  flex-direction: column;
  gap: .15rem;
}

.metrica-label {
  font-size: .68rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--ink-soft);
}

.metrica-dado {
  font-family: var(--f-mono);
  font-size: .98rem;
  font-weight: 600;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.metrica-dado.valor-destaque { color: var(--accent); }
.metrica-dado.valor-alerta { color: var(--bad); }

.metrica-divisor {
  width: 1px;
  height: 26px;
  background: var(--rule-soft);
}

/* ---------- vazio ---------- */

.vazio { text-align: center; padding: 3rem 1rem; color: var(--ink-faint); }
.vazio p { margin: 0 0 .5rem; }

/* ---------- paginação ---------- */

.paginas {
  display: flex;
  gap: .5rem;
  align-items: center;
  justify-content: center;
  margin-top: 1.2rem;
  font-family: var(--f-mono);
  font-size: .76rem;
}
.paginas a, .paginas span {
  padding: .35rem .7rem;
  border: 1px solid var(--rule);
  border-radius: var(--raio);
  text-decoration: none;
  color: var(--ink-soft);
}
.paginas a:hover { border-color: var(--accent); color: var(--accent); }
.paginas .atual { background: var(--accent-soft); color: var(--accent); border-color: var(--accent-soft); }

/* A barra do celular e o breakpoint mobile estão em layout.css (900px).
   O bloco antigo que ficava aqui (720px) foi removido para evitar conflito. */


/* ---------- polimento: profundidade e resposta ao ponteiro ----------

   Os cartoes tinham borda mas nenhuma sombra, entao a tela era plana e nada
   respondia ao passar o mouse. Aqui entram tres coisas, todas discretas:
   uma sombra base que separa o cartao do fundo, um leve levantar no hover, e
   destaque na linha da tabela sob o ponteiro.

   Nada disso e enfeite: e o que diz "isto aqui e clicavel" e "voce esta nesta
   linha", que e metade da sensacao de fluidez. */

.painel,
.tabela-caixa,
.form-caixa {
  box-shadow: var(--sombra);
  transition: box-shadow var(--transicao), transform var(--transicao),
              border-color var(--transicao);
}

/* So o painel levanta. Tabela e formulario ficam parados de proposito: sao
   areas de leitura e digitacao, e levantar ao passar o mouse distrai. */
.painel:hover {
  box-shadow: var(--sombra-alta);
  transform: translateY(-1px);
  border-color: color-mix(in oklab, var(--accent) 30%, var(--rule));
}

table.lista tbody tr {
  transition: background var(--transicao);
}

table.lista tbody tr:hover {
  background: color-mix(in oklab, var(--ink) 3%, transparent);
}

/* A pilula de categoria e clicavel em varias telas; vale responder. */
.pilula {
  transition: background var(--transicao), color var(--transicao),
              border-color var(--transicao);
}

/* O item ativo do menu ja tinha marca na lateral (border-left). O que
   faltava era a troca ser suave, em vez de piscar de um item para outro. */
.lateral nav a {
  transition: background var(--transicao), color var(--transicao),
              border-left-color var(--transicao);
}

@media (prefers-reduced-motion: reduce) {
  .painel:hover { transform: none; }
}

/* As acoes da lista de lancamentos viraram icones na primeira coluna; as
   regras estao mais abaixo, em `.col-acoes`. O que fica aqui e so o "apagar"
   em texto, ainda usado nas telas de cadastro. */

.acoes-linha {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: .8rem;
  white-space: nowrap;
}

.acoes-linha form { display: inline; }

.link-discreto.apagar {
  /* Reset do botao: em <button>, sem isto o navegador desenha a caixa cinza. */
  appearance: none;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  font-family: var(--f-mono);
  font-size: .74rem;
  text-decoration: none;
}

.link-discreto.apagar:hover { color: var(--bad); }

/* ---------- lancamento previsto ----------

   Na planilha era a linha pintada de vermelho: a compra que ele tem quase
   certeza de que vai fazer, e que o SUM da fatura ja incluia.

   Aqui usa a cor de alerta, nao a de erro: previsto nao e problema, e so
   ainda-nao-aconteceu. Vermelho de erro nesta lista gritaria a toa. */

tr.e-previsto td { color: var(--warm); }
tr.e-previsto .desc-principal { font-style: italic; }
tr.e-previsto td a { color: var(--warm); }

.pilula.previsto {
  background: var(--warm-soft);
  color: var(--warm);
}

.linha-check {
  display: flex;
  align-items: flex-start;
  gap: .55rem;
  cursor: pointer;
  margin-bottom: 1rem;
  font-size: .9rem;
}

.linha-check input { width: auto; margin: .25rem 0 0; flex: 0 0 auto; }
.linha-check .desc-extra { display: block; }

/* ---------- acoes da linha: icones a esquerda ----------

   Estavam como texto cinza no meio da linha, e o "apagar" era um <button>
   sem reset, entao aparecia com a caixa cinza padrao do navegador. Ficava
   feio e quase invisivel.

   Agora sao dois icones na primeira coluna, discretos em repouso e com cor
   no hover. A esquerda porque e onde o olho comeca a linha, e porque a
   coluna fica estreita e nao empurra o valor. */

.col-acoes { width: 1%; white-space: nowrap; padding-right: .2rem; }

.acoes { display: flex; align-items: center; gap: .1rem; }
.acoes form { display: flex; margin: 0; }

.acao {
  /* Reset do botao: sem isto o navegador desenha a caixa cinza. */
  appearance: none;
  background: none;
  border: 0;
  padding: .44rem;
  min-height: 36px;
  min-width: 36px;
  margin: 0;
  border-radius: var(--raio);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--ink-faint);
  cursor: pointer;
  text-decoration: none;
  transition: background var(--transicao), color var(--transicao);
}

.acao svg {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.acao:hover { background: var(--accent-soft); color: var(--accent); }
.acao.apagar:hover { background: var(--bad-soft); color: var(--bad); }

.acao:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

body.reordenando {
  user-select: none !important;
  -webkit-user-select: none !important;
  cursor: grabbing !important;
}

.acao.arrastar {
  cursor: grab;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}
.acao.arrastar:active {
  cursor: grabbing;
}
.acao.arrastar svg {
  fill: currentColor;
  stroke: none;
  pointer-events: none;
}
tr.arrastando {
  opacity: 0.38;
  background: var(--surface-alt) !important;
}
tr.reordenado-sucesso {
  animation: piscarSucesso 0.7s ease;
}
@keyframes piscarSucesso {
  0% { background-color: color-mix(in oklab, var(--good) 25%, transparent); }
  100% { background-color: transparent; }
}

tr.alvo-antes > td {
  border-top: 2px solid var(--accent) !important;
}
tr.alvo-depois > td {
  border-bottom: 2px solid var(--accent) !important;
}
.toast-reordenar {
  position: fixed;
  bottom: 24px;
  right: 24px;
  background: var(--ink, #1a1a1a);
  color: var(--surface, #ffffff);
  padding: 8px 16px;
  border-radius: 8px;
  font-size: 0.82rem;
  font-weight: 500;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.2);
  z-index: 9999;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 0.2s ease, transform 0.2s ease;
  pointer-events: none;
}
.toast-reordenar.visivel {
  opacity: 1;
  transform: translateY(0);
}

/* No celular o hover nao existe, entao o icone precisa ser visivel parado. */
@media (hover: none) {
  .acao { color: var(--ink-soft); }
}

/* ---------- animações de entrada ----------

   Os componentes aparecem com um deslocamento sutil de baixo para cima. É o
   detalhe que separa "funciona" de "tem acabamento". O delay escalonado faz
   os cartões de resumo surgirem um depois do outro, em vez de todos ao mesmo
   tempo. */

@keyframes surgir {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: translateY(0); }
}

.bloco, .painel, .cartao, .tabela-caixa, .form-caixa {
  animation: surgir 0.35s cubic-bezier(0.2, 0.7, 0.3, 1) both;
}

/* Quando o conteúdo é trocado via filtro dinâmico (AJAX), os elementos
   recriados dentro de #resultado nascem com a animação "surgir" (opacity 0→1).
   Isso causava uma "piscada" visível a cada digitação na busca. Desligar
   a animação durante a troca elimina o piscar sem remover o efeito na
   carga inicial da página. */
#resultado.troca-dinamica .tabela-caixa,
#resultado.troca-dinamica .painel,
#resultado.troca-dinamica .vazio {
  animation: none;
}

/* Transição suave de opacidade durante troca dinâmica */
#resultado {
  transition: opacity 80ms ease-out;
}

.cartoes-grade > :nth-child(2) { animation-delay: 60ms; }
.cartoes-grade > :nth-child(3) { animation-delay: 120ms; }
.cartoes-grade > :nth-child(4) { animation-delay: 180ms; }
.cartoes-grade > :nth-child(5) { animation-delay: 240ms; }

@media (prefers-reduced-motion: reduce) {
  .bloco, .painel, .cartao, .tabela-caixa, .form-caixa { animation: none; }
}

/* ---------- skeleton loading ----------

   Placeholder brilhante para conteúdo que ainda está carregando.
   Substitui o "nada" por uma indicação visual de que algo está a caminho. */

.esqueleto {
  background: linear-gradient(
    90deg,
    var(--surface-alt) 25%,
    color-mix(in oklab, var(--surface-alt) 60%, var(--surface)) 50%,
    var(--surface-alt) 75%
  );
  background-size: 200% 100%;
  animation: brilho 1.5s ease-in-out infinite;
  border-radius: var(--raio);
  min-height: 1em;
}

@keyframes brilho {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

@media (prefers-reduced-motion: reduce) {
  .esqueleto { animation: none; opacity: .6; }
}

/* ---------- modal de confirmação ----------

   Substitui o window.confirm() nativo. O <dialog> é criado por modal.js e
   estilizado aqui para respeitar o tema. */

dialog.modal {
  border: 1px solid var(--rule);
  border-radius: var(--raio-grande);
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--sombra-alta);
  max-width: 420px;
  width: calc(100% - 2rem);
  padding: var(--space-xl);
}

dialog.modal::backdrop {
  background: oklch(0 0 0 / 0.45);
}

.modal-titulo {
  font-family: var(--f-display);
  font-size: 1.2rem;
  font-weight: 600;
  margin: 0 0 var(--space-sm);
}

.modal-corpo {
  font-size: .92rem;
  color: var(--ink-soft);
  margin-bottom: var(--space-xl);
  line-height: 1.5;
}

.modal-acoes {
  display: flex;
  gap: var(--space-md);
  justify-content: flex-end;
}

.modal-acoes .botao {
  width: auto;
  padding: .55rem 1.2rem;
  font-size: .9rem;
}

.modal-acoes .botao.vazado {
  background: none;
  border: 1px solid var(--rule);
  color: var(--ink-soft);
}

.modal-acoes .botao.vazado:hover {
  border-color: var(--ink-faint);
  color: var(--ink);
}

/* ---------- botões de perigo ----------

   Antes viviam em <style> inline em lancamento_editar.html e excluir.html.
   Centralizados aqui para que qualquer tela use sem copiar. */

.botao.perigo {
  background: var(--bad);
  color: var(--sobre-accent);
}

.botao.perigo:hover {
  background: oklch(from var(--bad) calc(l - .05) c h);
}

.botao.vazado-perigo {
  background: none;
  border: 1px solid var(--bad);
  color: var(--bad);
}

.botao.vazado-perigo:hover {
  background: var(--bad-soft);
}

/* ---------- .secundario e .fantasma ----------

   Duas variantes usadas em varios templates (importar.html, veiculo_
   manutencoes.html, imposto_renda.html) sem nunca terem sido definidas -
   caiam no `.botao` puro (fundo verde solido, width:100%), e um botao
   "secundario" ou um link de "limpar filtro" virava um segundo botao
   primario do tamanho da tela. Achado em 10/09/2026 conferindo por
   screenshot, nao so por leitura de HTML. */

.botao.secundario {
  background: none;
  border: 1px solid var(--rule);
  color: var(--ink-soft);
  box-shadow: none;
}

.botao.secundario:hover {
  border-color: var(--ink-faint);
  color: var(--ink);
}

.botao.fantasma {
  width: auto;
  background: none;
  border: 0;
  box-shadow: none;
  color: var(--accent);
  padding: .35rem .5rem;
  font-size: .85rem;
  font-weight: 500;
  text-decoration: underline;
}

.botao.fantasma:hover {
  color: var(--accent-forte);
}

/* Dentro de .filtros os botoes/links de acao (ex: "Limpar filtro") ficam ao
   lado dos campos, nao esticados a largura toda - o base `.botao` e
   width:100% de proposito para forms empilhados, o que nao serve aqui. */
.filtros .botao {
  width: auto;
}

/* ---------- gráficos ----------

   Antes espalhados em <style> inline em analise.html e melhorar.html. */

.grafico-caixa {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--raio);
  padding: 1rem 1.2rem;
  margin-bottom: 1rem;
}

.grafico-titulo {
  font-family: var(--f-display);
  font-size: 1.05rem;
  font-weight: 600;
  margin: 0 0 .7rem;
}

.dois-graficos {
  display: grid;
  gap: 1rem;
}

@media (min-width: 640px) {
  .dois-graficos { grid-template-columns: 1fr 1fr; }
}

/* ---------- acordeão de cadastro ----------

   O <details class="caixa-nova"> estava em <style> inline em
   cartoes.html, orcamento.html e recorrentes.html. */

.caixa-nova {
  margin-top: 1.5rem;
}

.caixa-nova > summary {
  font-family: var(--f-mono);
  font-size: .72rem;
  text-transform: uppercase;
  letter-spacing: .09em;
  color: var(--accent);
  cursor: pointer;
  padding: .5rem 0;
  list-style: none;
  font-weight: 600;
}

.caixa-nova > summary::-webkit-details-marker { display: none; }
.caixa-nova > summary::before { content: "+ "; }
.caixa-nova[open] > summary::before { content: "− "; }

/* ---------- status dot ---------- */

.status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  display: inline-block;
  vertical-align: middle;
  margin-right: var(--space-xs);
}

.status-dot.ativo {
  background: var(--good);
  animation: pulso-dot 2s ease-in-out infinite;
}

.status-dot.pendente { background: var(--warm); }
.status-dot.erro { background: var(--bad); }

@keyframes pulso-dot {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in oklab, var(--good) 40%, transparent); }
  50%      { box-shadow: 0 0 0 6px color-mix(in oklab, var(--good) 0%, transparent); }
}

@media (prefers-reduced-motion: reduce) {
  .status-dot.ativo { animation: none; }
}

/* ---------- alertas de linha ----------

   Antes em <style> inline em fatura.html. */

.alerta-linha {
  padding: .35rem .6rem;
  font-size: .78rem;
  border-radius: var(--raio-sm);
  margin-top: .2rem;
}

.alerta-linha.possivel_duplicata {
  background: var(--warm-soft);
  color: var(--warm);
}

.alerta-linha.fora_da_janela {
  background: var(--bad-soft);
  color: var(--bad);
}

.alerta-linha.parcela_solta {
  color: var(--bad);
  font-weight: 500;
}

.alerta-linha.previsto {
  color: var(--ink-faint);
}

/* ---------- utilitários e seções ---------- */

[x-cloak] { display: none !important; }

.secao-titulo {
  font-family: var(--f-display);
  font-size: 1.15rem;
  font-weight: 600;
  margin: 0 0 .2rem;
}

.secao-nota {
  font-size: .9rem;
  color: var(--ink-soft);
  margin: 0 0 .9rem;
  max-width: 62ch;
}

.grafico-nota {
  font-size: .82rem;
  color: var(--ink-faint);
  margin: 0 0 .6rem;
}

.grafico { width: 100%; }

/* ---------- conferência de fatura ---------- */

.conferencia-topo { margin: 1.8rem 0 .7rem; }
.conferencia-titulo {
  font-family: var(--f-display);
  font-size: 1.1rem;
  margin: 0 0 .35rem;
}
.conferencia-nota {
  margin: 0;
  font-size: .82rem;
  color: var(--ink-soft);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .35rem;
}

/* ---------- edição e exclusão de cadastros ---------- */

.confirmar-exclusao {
  max-width: 560px;
  border-top: 3px solid var(--bad);
}

.consequencias {
  margin: .6rem 0 1rem;
  padding-left: 1.1rem;
}

.consequencias li {
  margin-bottom: .35rem;
  font-size: .88rem;
  color: var(--ink-soft);
}

.editar-grade {
  display: grid;
  gap: 1.1rem;
  align-items: start;
}

@container (min-width: 58rem) {
  .editar-grade {
    grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr);
  }
}

.apagar-lancamento {
  border-top: 3px solid var(--bad);
}

/* ---------- estados inativos e despesas recorrentes ---------- */

.painel.inativo { opacity: .62; }
tr.inativa td { opacity: .5; }

.paineis-dois {
  display: grid;
  gap: .9rem;
  margin-bottom: 1.2rem;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  max-width: 860px;
}

.form-caixa .so-credito { display: none; }
.form-caixa:has(#r-meio option[value="credito"]:checked) .so-credito { display: grid; }

.pilula.cartao {
  background: var(--accent-soft);
  color: var(--accent-forte);
}

.atalhos-lancar {
  display: flex;
  gap: .6rem;
  margin-bottom: 1rem;
  flex-wrap: wrap;
}

/* ---------- sub-abas de navegacao e filtros discretos ---------- */

.sub-abas {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  background: var(--surface-alt);
  padding: .25rem;
  border-radius: var(--raio);
  border: 1px solid var(--rule);
  margin-bottom: 1.25rem;
  flex-wrap: wrap;
}

.sub-aba {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  padding: .32rem .75rem;
  font-family: var(--f-body);
  font-size: .82rem;
  font-weight: 500;
  border-radius: calc(var(--raio) - 2px);
  text-decoration: none;
  color: var(--ink-soft);
  background: transparent;
  border: 1px solid transparent;
  white-space: nowrap;
  width: auto;
  box-sizing: border-box;
  cursor: pointer;
  transition: all var(--transicao);
}

.sub-aba:hover {
  color: var(--ink);
  background: color-mix(in oklab, var(--ink) 5%, transparent);
}

.sub-aba.ativa {
  color: var(--ink);
  background: var(--surface);
  border-color: var(--rule);
  box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.06);
  font-weight: 600;
}

.sub-aba-contador {
  font-family: var(--f-mono);
  font-size: .75rem;
  opacity: .75;
}

.botao-acao {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  padding: .35rem .75rem;
  font-family: var(--f-body);
  font-size: .82rem;
  font-weight: 500;
  border-radius: var(--raio);
  text-decoration: none;
  color: var(--ink-soft);
  background: var(--surface-alt);
  border: 1px solid var(--rule);
  white-space: nowrap;
  width: auto;
  box-sizing: border-box;
  cursor: pointer;
  transition: all var(--transicao);
}

.botao-acao:hover {
  color: var(--ink);
  border-color: var(--accent);
}

.botao-acao.destaque {
  background: var(--accent);
  color: var(--sobre-accent);
  border-color: var(--accent);
  font-weight: 600;
}

/* ============================================================
   No celular, tabela nao e tabela: e uma pilha de cartoes
   ============================================================

   Medido em 24/09/2026 num iPhone de 390px: a tabela de lancamentos
   ocupava 910px. A pagina nao rolava de lado - a caixa e que rolava -
   entao o que sobrava na tela era a coluna de acoes, a data e meia
   descricao. **O valor, que e a unica coisa que ele abre a tela para
   ver, ficava fora.** Quatro telas estavam assim.

   A saida e parar de tratar a tabela como tabela abaixo de 720px: cada
   `<tr>` vira um cartao, e cada `<td>` vira uma linha "rotulo | valor"
   dentro dele. O rotulo sai do `data-rotulo` da celula, que repete o
   `<th>` da coluna - sem ele a celula aparece so com o conteudo, que
   ainda e melhor do que cortada.

   A tabela continua sendo `<table>` no HTML, com `<thead>` e escopo de
   coluna: quem usa leitor de tela continua ouvindo a estrutura, e o
   `role="table"` dos elementos nao muda. So a pintura muda. */
@media (max-width: 720px) {
  .tabela-caixa { overflow-x: visible; background: none; border: 0; box-shadow: none; }

  table.lista { display: block; font-size: .95rem; }
  table.lista thead { display: none; }
  table.lista tbody { display: flex; flex-direction: column; gap: .7rem; }

  /* Flex com `order` para ler na ordem que a pessoa pensa: o que foi,
     quanto custou, e so depois quando/onde/como. A coluna de acoes e a
     primeira no HTML (e o certo para teclado: o comando vem antes do
     item) e a ultima na pintura. Nada disso muda a ordem do foco. */
  table.lista tbody tr {
    display: flex;
    flex-direction: column;
    background: var(--carta-fundo);
    border: var(--carta-borda);
    border-radius: var(--carta-raio);
    padding: .85rem 1rem;
    box-shadow: var(--carta-sombra);
  }

  table.lista td { order: 3; }
  table.lista td.celula-titulo { order: 1; }
  /* `.valor` sem rotulo e o dinheiro do cartao - o numero pelo qual a
     linha existe. Com rotulo e so mais um dado alinhado a direita
     (contagem de lancamentos, quantidade), e ai nao vira manchete. */
  table.lista td.valor:not([data-rotulo]) { order: 2; }
  table.lista td.col-acoes { order: 9; }

  /* A zebra e o hover eram pistas de "qual linha estou lendo" numa
     grade. Em cartao separado a pista e a borda, e a zebra vira
     sujeira: dois tons de fundo alternados sem motivo. */
  table.lista tbody tr:nth-child(even) td,
  table.lista tbody tr:hover td { background: none; }

  table.lista td {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    padding: .3rem 0;
    border-bottom: 0;
    text-align: right;
  }

  table.lista td[data-rotulo]::before {
    content: attr(data-rotulo);
    flex: 0 0 auto;
    text-align: left;
    font-size: .72rem;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--ink-faint);
    font-weight: 600;
    font-family: var(--f-body);
  }

  /* Celula vazia so faria o cartao crescer com uma linha em branco. */
  table.lista td:empty { display: none; }

  /* Pilula e feita para nao quebrar: "Estorno e cashback > Cashback" numa
     linha so mede 386px numa caixa de 357px, e sai pela direita levando a
     tabela junto. Num cartao ela pode quebrar - o nome inteiro importa
     mais que o formato de pastilha. Medido em 24/09/2026 (regra 4b do
     conferir_visual). */
  table.lista td .pilula {
    white-space: normal;
    text-align: right;
    max-width: 100%;
  }
  table.lista td.valor { white-space: nowrap; }

  /* O dinheiro e o motivo de abrir a tela: vem grande, separado por um
     fio do resto do cartao. */
  table.lista td.valor:not([data-rotulo]) {
    font-size: 1.25rem;
    font-weight: 600;
    padding-top: .55rem;
    margin-top: .35rem;
    border-top: 1px solid var(--rule-soft);
  }

  /* Acoes: eram a primeira coluna, e no celular empurravam o conteudo
     para fora antes de qualquer coisa ser lida. Vao para o rodape do
     cartao, espalhadas, com alvo de dedo de 44px - o minimo que Apple e
     Google pedem, e que os 14px do icone nao davam. */
  table.lista td.col-acoes {
    justify-content: flex-start;
    padding-top: .6rem;
    margin-top: .4rem;
    border-top: 1px solid var(--rule-soft);
  }
  table.lista td.col-acoes::before { display: none; }
  table.lista td.col-acoes .acoes { gap: .35rem; }
  table.lista td.col-acoes .acao {
    min-width: 44px;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }

  /* Arrastar para reordenar e gesto de mouse: no celular o toque longo
     ja e "selecionar texto", e o alvo de 14px nao tem chance. Some. */
  table.lista td.col-acoes .acao.arrastar { display: none; }

  /* A descricao e o titulo do cartao, nao um campo com rotulo. */
  table.lista td.celula-titulo {
    display: block;
    text-align: left;
    font-size: 1.05rem;
    font-weight: 600;
    padding-bottom: .45rem;
  }
  table.lista td.celula-titulo::before { display: none; }
}
