/* ═══════════════════════════════════════════════════════════════
   Contas em Dia — application styles
   All color flows from tokens.css. No literal hex below this line.
   ═══════════════════════════════════════════════════════════════ */

/* ═══════════════════════════════════════════════════════════════
   RESET
   Substitui o reset do Pico v2, removido na Fase 0. Cobre só o que
   o Pico cobria e o app usa — não é um reset genérico de biblioteca.
   ═══════════════════════════════════════════════════════════════ */
*, *::before, *::after { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-weight: var(--weight-body);
  font-size: var(--text-base);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  margin: 0;
  line-height: 1.2;
  text-wrap: balance;
}
p { margin: 0 0 var(--space-3); }
ul, ol { margin: 0; padding: 0; }

a { color: var(--primary); text-decoration: none; }
a:hover { text-decoration: underline; }

/* Controles herdam a fonte — o navegador não faz isso sozinho */
input, select, textarea, button {
  font-family: inherit;
  font-size: inherit;
  color: inherit;
  margin: 0;
}
button { background: none; border: none; padding: 0; cursor: pointer; }
select { cursor: pointer; }

table { border-collapse: collapse; width: 100%; }
th { text-align: left; font-weight: var(--weight-body-strong); }

summary { cursor: pointer; list-style: none; }
summary::-webkit-details-marker { display: none; }

code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.92em; }
hr { border: none; border-top: 1px solid var(--border); margin: var(--space-4) 0; }

/* Foco: um único tratamento no app inteiro. Nunca outline:none sem
   substituto — ver design_directions_ii.md §4. */
:focus-visible {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--focus-ring);
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* ═══════════════════════════════════════════════════════════════
   ESCALA DE CONTROLES
   Toda altura de controle sai daqui. Se um controle não usa uma
   destas classes, ele está errado.
   ═══════════════════════════════════════════════════════════════ */
.ctl-sm, .ctl-md, .ctl-lg {
  display: inline-flex;
  align-items: center;
  border-radius: var(--radius-control);
  border: 1px solid transparent;
  white-space: nowrap;
  transition: background var(--transition), border-color var(--transition), color var(--transition);
}
.ctl-sm { height: var(--control-sm); padding: 0 var(--control-sm-px); font-size: var(--control-sm-fs); }
.ctl-md { height: var(--control-md); padding: 0 var(--control-md-px); font-size: var(--control-md-fs); }
.ctl-lg { height: var(--control-lg); padding: 0 var(--control-lg-px); font-size: var(--control-lg-fs); }

/* IBM Plex Sans is tabular by default; assert it anyway so a
   feature-stripped webfont build can't misalign amount columns. */
.num-col, .acc-bal, .rta-amount, .assign-input, .account-balance,
.avail-badge, .report-table td, .chip-amount {
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
}

/* ═══════════════════════════════════════════════════════════════
   COMPONENT LIBRARY
   ═══════════════════════════════════════════════════════════════ */

/* ─── Chips: three semantic states ──────────────────────────────
   Chip color signals the nature of the fact.
   Chip text says what to do.
   ──────────────────────────────────────────────────────────────*/
.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: 2px var(--space-2);
  border-radius: var(--radius-control);
  border: 1px solid transparent;
  font-size: var(--text-sm);
  font-weight: var(--weight-body-strong);
  line-height: 1.4;
  white-space: nowrap;
}

.chip-warn {
  background: var(--chip-warn-bg);
  border-color: var(--chip-warn-border);
  color: var(--chip-warn-text);
}
.chip-ok {
  background: var(--chip-ok-bg);
  border-color: var(--chip-ok-border);
  color: var(--chip-ok-text);
}
.chip-danger {
  background: var(--chip-danger-bg);
  border-color: var(--chip-danger-border);
  color: var(--chip-danger-text);
}
.chip-neutral {
  background: var(--chip-neutral-bg);
  border-color: var(--chip-neutral-border);
  color: var(--chip-neutral-text);
}
/* Preenchido, mesmo par usado em categoria estourada — mais forte que
   .chip-warn (contornado/suave), mesma cor-base. Selo "Atenção" da base
   de conhecimento (ver help/_macros.html::note()). */
.chip-attention {
  background: var(--attention-fill);
  border-color: var(--attention-edge);
  color: var(--attention-fill-text);
}

.chip-sm { padding: 0 var(--space-1); font-size: var(--text-xs); }

/* Chip numérico em coluna: largura fixa, número à direita.
   Algarismo tabular iguala DÍGITOS, não contagem de caracteres —
   "R$ 0,00" e "R$ 1.800,00" continuariam de larguras diferentes.
   Ver design_directions_ii.md §12.3.1. */
.chip-num {
  min-width: 11ch;
  justify-content: flex-end;
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
}

/* ─── Meters ────────────────────────────────────────────────────
   Attention fill is bordered — the border carries UI contrast so
   the sun-yellow fill never has to.
   ──────────────────────────────────────────────────────────────*/
.meter {
  display: block;
  width: 100%;
  height: 6px;
  background: var(--track);
  border-radius: var(--radius-meter);
  overflow: hidden;
}
.meter-fill {
  display: block;
  height: 100%;
  border-radius: var(--radius-meter);
  background: var(--primary);
  transition: width 0.2s ease;
}
.meter-fill.is-ok { background: var(--primary); }

/* Subfinanciado: preenchimento contornado sobre trilho neutro. Sobra
   trilho cinza à direita — é essa sobra que diz "falta atribuir". */
.meter-fill.is-attention {
  background: var(--attention-fill);
  border: 1px solid var(--attention-edge);
}

/* Gasto além: a barra inteira fica no matiz de atenção e não sobra
   trilho. Mesma lógica dos chips — contornado é "dá para fazer mais",
   preenchido é "precisa arrumar". Vermelho segue reservado ao
   irreversível (PRJ-DEC-006).
   O traço extra sinaliza que passou do limite, para a gravidade não
   depender só de cor. */
.meter.is-over {
  background: var(--chip-warn-bg);
  border: 1px solid var(--attention-edge);
}
.meter.is-over .meter-fill {
  background: repeating-linear-gradient(
    135deg,
    var(--attention-fill) 0 4px,
    var(--attention-edge) 4px 6px
  );
  border: none;
}

/* ─── Cards ─────────────────────────────────────────────────── */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: var(--space-4);
}
.card-dashed {
  background: var(--surface);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-card);
  padding: var(--space-4);
}
.card-inset {
  background: var(--surface-sunk);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: var(--space-3);
}

/* ─── Form controls ─────────────────────────────────────────── */
.input,
.select {
  width: 100%;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-control);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--control-md-fs);
  height: var(--control-md);
  padding: 0 var(--control-md-px);
  margin: 0;
  transition: border-color var(--transition), box-shadow var(--transition);
}
.input:focus,
.select:focus {
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--focus-ring);
  outline: none;
}
.input-sm,
.select-sm {
  height: var(--control-sm);
  padding: 0 var(--control-sm-px);
  font-size: var(--control-sm-fs);
}
.input-num { text-align: right; font-variant-numeric: tabular-nums; }
.input-auto { width: auto; }

/* Todo select carrega a seta. Sem exceção — o estilo nativo some em
   fundo claro e o usuário deixa de saber que o campo expande.
   Ver design_directions_ii.md §4. */
.select,
select.input {
  appearance: none;
  -webkit-appearance: none;
  background-image: var(--chevron);
  background-repeat: no-repeat;
  background-position: right var(--control-md-px) center;
  padding-right: calc(var(--control-md-px) * 2 + var(--icon-sm));
}
.select-sm {
  background-position: right var(--control-sm-px) center;
  padding-right: calc(var(--control-sm-px) * 2 + var(--icon-sm));
}
.select:disabled { opacity: 0.55; cursor: not-allowed; }

.field {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  font-size: var(--text-xs);
  color: var(--muted);
}
.field > input, .field > select { color: var(--ink); }

/* Combobox — casca visual. O comportamento (busca, teclado) entra
   na Fase 3, junto da edição inline. */
.combobox { position: relative; display: block; }
.combobox-list {
  position: absolute;
  z-index: 40;
  top: calc(100% + 2px);
  left: 0; right: 0;
  max-height: 240px;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-control);
  box-shadow: 0 6px 20px rgba(0,0,0,0.13);
  padding: var(--space-1);
}
.combobox-option {
  display: flex;
  align-items: center;
  height: var(--control-sm);
  padding: 0 var(--control-sm-px);
  border-radius: var(--radius-control);
  font-size: var(--control-sm-fs);
  cursor: pointer;
}
.combobox-option {
  padding-left: calc(var(--control-sm-px) + var(--space-3));  /* indentação sob a seção */
}
.combobox-option:hover,
.combobox-option.is-active { background: var(--row-hover); }
.combobox-option.is-active { outline: 2px solid var(--primary); outline-offset: -2px; }

/* Seção: cabeçalho, não opção. Não é selecionável. */
.combobox-group {
  padding: var(--space-2) var(--control-sm-px) var(--space-1);
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
  cursor: default;
}
.combobox-group + .combobox-option { margin-top: 0; }

.combobox-empty { padding: var(--space-2) var(--control-sm-px); }
.combobox-create {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
  font-size: var(--control-sm-fs);
}
.combobox-create .select { flex: 1 1 8rem; }

/* Entrada é a exceção num app onde quase tudo é saída, então é ela que
   ganha cor. Teal, não vermelho na saída: gasto é o caso normal, e
   vermelho segue reservado ao irreversível (PRJ-DEC-006). */
.tx-f-amount.is-inflow {
  border-color: var(--chip-ok-border);
  background: var(--chip-ok-bg);
  color: var(--chip-ok-text);
}
.tx-f-amount.is-inflow::placeholder { color: var(--chip-ok-text); opacity: 0.7; }

/* ─── Buttons ───────────────────────────────────────────────── */
.btn-primary {
  background: var(--primary);
  color: var(--primary-on);
  border: 1px solid transparent;
  height: var(--control-md);
  padding: 0 var(--control-md-px);
  border-radius: var(--radius-control);
  cursor: pointer;
  font-family: var(--font-body);
  font-weight: var(--weight-body-strong);
  font-size: var(--control-md-fs);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background var(--transition);
}
.btn-primary:hover { background: var(--primary-hover); color: var(--primary-on); }

.btn-ghost {
  background: transparent;
  border: 1px solid var(--border-strong);
  color: var(--muted);
  height: var(--control-md);
  padding: 0 var(--control-md-px);
  border-radius: var(--radius-control);
  cursor: pointer;
  font-family: var(--font-body);
  font-size: var(--control-md-fs);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: border-color var(--transition), color var(--transition);
}
.btn-ghost:hover { border-color: var(--primary); color: var(--ink); }

/* Irreversible actions — the only everyday home for ledger-red */
.btn-danger {
  background: transparent;
  border: 1px solid transparent;
  color: var(--text-danger);
  cursor: pointer;
  font-size: var(--control-sm-fs);
  height: var(--control-sm);
  padding: 0 var(--control-sm-px);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-control);
  transition: background var(--transition);
}
.btn-danger:hover { background: var(--chip-danger-bg); }

.btn-sm {
  height: var(--control-sm);
  padding: 0 var(--control-sm-px);
  font-size: var(--control-sm-fs);
}
.btn-lg {
  height: var(--control-lg);
  padding: 0 var(--control-lg-px);
  font-size: var(--control-lg-fs);
}
.btn-block { width: 100%; }
.btn-primary:disabled,
.btn-ghost:disabled { opacity: 0.55; cursor: not-allowed; }

/* ─── Sobreposições ─────────────────────────────────────────────
   Popover: escolha curta ancorada a um campo (calendário, categoria).
   Menu: ações sobre um objeto.
   Modal fica reservado a destrutivo — ver §8 do estudo II.
   ──────────────────────────────────────────────────────────────*/
.popover, .menu {
  position: absolute;
  z-index: 40;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-card);
  box-shadow: 0 6px 20px rgba(0,0,0,0.13);
}
.popover { padding: var(--space-3); min-width: 240px; }
.menu { padding: var(--space-1); min-width: 180px; }
.menu-item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  height: var(--control-sm);
  padding: 0 var(--control-sm-px);
  border-radius: var(--radius-control);
  font-size: var(--control-sm-fs);
  color: var(--ink);
  text-align: left;
  text-decoration: none;
  cursor: pointer;
}
.menu-item:hover { background: var(--row-hover); text-decoration: none; }
.menu-item.is-danger { color: var(--text-danger); }
.menu-item.is-danger:hover { background: var(--chip-danger-bg); }
.menu-sep { height: 1px; background: var(--border); margin: var(--space-1) 0; }

/* ─── Estado vazio ──────────────────────────────────────────────
   Uma frase e uma ação. Sem ilustração — §10 do estudo II.
   ──────────────────────────────────────────────────────────────*/
.empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-7) var(--space-4);
  text-align: center;
  color: var(--muted);
}
.empty-text { font-size: var(--text-md); max-width: 44ch; margin: 0; }

/* ─── Ícones ────────────────────────────────────────────────── */
.icon {
  width: var(--icon-sm);
  height: var(--icon-sm);
  flex-shrink: 0;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.icon-lg { width: var(--icon-lg); height: var(--icon-lg); }

/* ═══════════════════════════════════════════════════════════════
   LAYOUT
   ═══════════════════════════════════════════════════════════════ */
.layout { display: flex; min-height: 100vh; }

/* ─── LEFT SIDEBAR ──────────────────────────────────────────── */
.sidebar {
  width: var(--sidebar-w);
  flex-shrink: 0;
  background: var(--surface);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  position: fixed;
  top: 0; left: 0;
  height: 100vh;
  overflow: hidden;
  z-index: 20;
}

/* Alça de redimensionamento — faixa fina na borda direita da barra.
   Fica plana até o hover/arraste para não competir visualmente com o
   conteúdo; a área de toque é maior que a linha visível. */
.sidebar-resizer {
  position: fixed;
  top: 0;
  left: var(--sidebar-w);
  transform: translateX(-3px);
  width: 6px;
  height: 100vh;
  cursor: col-resize;
  z-index: 21;
  background: transparent;
  touch-action: none;
}
.sidebar-resizer:hover,
.sidebar-resizer.is-dragging {
  background: var(--border-strong);
}
@media (max-width: 720px) {
  .sidebar-resizer { display: none; }
}
body.is-resizing-sidebar {
  cursor: col-resize;
  user-select: none;
}

/* ─── Barra mobile + colapso da barra lateral (achado da revisão manual:
   a barra ficava fixa em 220px sem nenhum jeito de recolher, sobrando
   ~155px de conteúdo numa tela de 375px) ───────────────────────────── */
.mobile-topbar { display: none; }
.sidebar-backdrop { display: none; }

@media (max-width: 720px) {
  .mobile-topbar {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    position: fixed;
    top: 0; left: 0; right: 0;
    height: 48px;
    padding: 0 var(--space-3);
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    z-index: 30;
  }
  .mobile-menu-icon,
  .mobile-menu-icon::before,
  .mobile-menu-icon::after {
    display: block;
    width: 18px;
    height: 2px;
    background: var(--ink);
    border-radius: 1px;
  }
  .mobile-menu-icon { position: relative; }
  .mobile-menu-icon::before,
  .mobile-menu-icon::after {
    content: '';
    position: absolute;
    left: 0;
  }
  .mobile-menu-icon::before { top: -6px; }
  .mobile-menu-icon::after { top: 6px; }

  /* Fora da tela até abrir — sidebar vira um menu por cima do
     conteúdo (não empurra mais nada), então --sidebar-w deixa de
     valer como largura real de layout aqui. */
  .sidebar {
    width: 260px;
    transform: translateX(-100%);
    transition: transform 0.2s ease;
    z-index: 40;
  }
  .sidebar.is-open { transform: translateX(0); }

  .sidebar-backdrop {
    display: block;
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.4);
    z-index: 35;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s ease;
  }
  .sidebar-backdrop.is-open {
    opacity: 1;
    pointer-events: auto;
  }
}

@media (max-width: 720px) and (prefers-reduced-motion: reduce) {
  .sidebar,
  .sidebar-backdrop { transition: none; }
}

.sidebar-top { flex-shrink: 0; padding: 1rem 0.85rem 0; }

.sidebar-brand {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: 1.25rem;
}
/* Selo com fundo — sem logo definitivo ainda, mas a marca precisa de
   peso próprio, não só de uma cor de texto igual a qualquer outro
   elemento da tela. Fica pronto pra virar container de <img> depois. */
.brand-mark {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: var(--radius-control);
  background: var(--primary);
  color: var(--primary-on);
  font-size: 1rem;
  line-height: 1;
  flex-shrink: 0;
}
.brand-name { font-size: 1rem; font-weight: var(--weight-body-strong); letter-spacing: 0.02em; color: var(--ink); }

/* Nav — estado de repouso ganha superfície própria (tom de --bg contra
   o --surface da barra lateral); sem isso os links eram texto solto,
   indistinguíveis do fundo até o hover. Ícone precede o rótulo, como
   nos apps de referência citados pelo operador. */
.sidebar-nav { display: flex; flex-direction: column; gap: 3px; margin-bottom: var(--space-4); }
.nav-link {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: 0.5rem 0.65rem;
  border-radius: var(--radius-control);
  background: var(--bg);
  border: 1px solid var(--border);
  color: var(--muted);
  text-decoration: none;
  font-size: 0.88rem;
  font-weight: 500;
  transition: background var(--transition), color var(--transition), border-color var(--transition);
}
.nav-link .icon { color: var(--muted); transition: color var(--transition); }
.nav-link:hover { background: var(--row-hover); color: var(--ink); border-color: var(--border-strong); }
.nav-link:hover .icon { color: var(--ink); }
.nav-link.active {
  background: var(--chip-ok-bg);
  border-color: var(--chip-ok-border);
  color: var(--chip-ok-text);
  font-weight: var(--weight-body-strong);
}
.nav-link.active .icon { color: var(--chip-ok-text); }

/* Divisor entre a navegação do app e a lista de contas — pedido
   explícito do operador: as duas listas pareciam uma coisa só. */
.sidebar-divider {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: 0 0.85rem var(--space-1);
  margin-top: var(--space-1);
}
.sidebar-divider span {
  font-size: 0.66rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--muted);
  white-space: nowrap;
}
.sidebar-divider::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--border);
}

/* Account list */
.sidebar-accounts {
  flex: 1;
  overflow-y: auto;
  padding: 0 var(--space-2);
  scrollbar-width: thin;
  scrollbar-color: var(--border-strong) transparent;
}

.acc-group { margin-bottom: var(--space-1); }

.acc-group-header {
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--muted);
  padding: 0.6rem 0.5rem 0.2rem;
}

.sidebar-account {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.35rem 0.55rem;
  border-radius: var(--radius-control);
  text-decoration: none;
  color: var(--ink);
  font-size: 0.84rem;
  transition: background var(--transition);
  gap: var(--space-2);
}
.sidebar-account:hover { background: var(--row-hover); }
.sidebar-account.active { background: var(--chip-ok-bg); color: var(--chip-ok-text); }

/* Ícone de tipo — segmenta corrente/poupança/dinheiro/cartão/
   acompanhamento visualmente, sem precisar de mais um nível de
   cabeçalho para cada tipo. Cor neutra: o ícone identifica, não
   compete com o saldo (que é o dado que importa na linha). */
.acc-type-icon { color: var(--muted); flex-shrink: 0; }
.sidebar-account.active .acc-type-icon { color: var(--chip-ok-text); }

.acc-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.acc-bal { flex-shrink: 0; font-size: 0.82rem; color: var(--muted); }

/* Entra como último item da lista de contas — pertence a ela
   visualmente — mas o traço tracejado e o peso mais leve marcam que é
   uma ação, não mais uma conta existente. */
.sidebar-account-add {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: 0.4rem 0.55rem;
  margin-top: 2px;
  border-radius: var(--radius-control);
  border: 1px dashed var(--border-strong);
  color: var(--muted);
  text-decoration: none;
  font-size: 0.82rem;
  transition: background var(--transition), color var(--transition), border-color var(--transition);
}
.sidebar-account-add:hover { background: var(--row-hover); color: var(--primary); border-color: var(--primary); }
.sidebar-account-add-icon {
  display: flex; align-items: center; justify-content: center;
  width: 16px; height: 16px; flex-shrink: 0;
  font-size: 0.9rem; line-height: 1;
}

/* Sidebar footer */
.sidebar-footer {
  flex-shrink: 0;
  padding: var(--space-3) 0.85rem;
  border-top: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.sidebar-add-account {
  font-size: 0.78rem;
  color: var(--muted);
  text-decoration: none;
  transition: color var(--transition);
}
.sidebar-add-account:hover { color: var(--primary); }
.currency-select {
  width: 100%;
  font-size: var(--control-sm-fs);
  height: var(--control-sm);
  padding: 0 var(--control-sm-px);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-control);
  color: var(--muted);
}
.lang-switch a { color: var(--muted); text-decoration: none; }
.lang-switch a:hover { color: var(--primary); }

/* ─── MAIN CONTENT ──────────────────────────────────────────── */
.main-content {
  margin-left: var(--sidebar-w);
  flex: 1;
  min-height: 100vh;
  overflow: hidden;
}
@media (max-width: 720px) {
  /* A barra virou um menu por cima do conteúdo (.sidebar acima), não
     empurra mais nada — e o espaço em cima é da barra mobile fixa. */
  .main-content { margin-left: 0; padding-top: 48px; }
}

.page-content { padding: var(--space-6) 2.5rem; }
@media (max-width: 720px) {
  .page-content { padding: var(--space-4) 1.25rem; }
}

/* ─── BUDGET 2-COLUMN LAYOUT ────────────────────────────────── */
.budget-layout { display: flex; min-height: 100vh; }

.budget-center {
  flex: 1;
  min-width: 0;
  padding: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
}

.budget-right {
  width: 268px;
  flex-shrink: 0;
  background: var(--surface);
  border-left: 1px solid var(--border);
  padding: 1.25rem;
  height: 100vh;
  overflow-y: auto;
  position: sticky;
  top: 0;
}

/* ─── BUDGET HEADER (month nav + RTA) ──────────────────────── */
.budget-header {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-3) var(--space-6);
  padding: 1.25rem 1.75rem var(--space-3);
  border-bottom: 1px solid var(--border);
  background: var(--bg);
  flex-shrink: 0;
}
/* Nem sempre é a largura da tela que aperta aqui — a barra lateral
   fixa de 220px + o painel direito de 268px (.budget-right) já comem
   quase 500px antes de sobrar qualquer coisa pro .budget-center, então
   isto quebrava (texto cortado, anel sobreposto) em tablets também, não
   só em celular. flex-wrap acima resolve pelos dois motivos de uma vez
   — reage à largura real do container, não a um breakpoint fixo. */
.month-nav, .rta-block { flex-shrink: 0; }

.month-nav {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-shrink: 0;
}
.month-label {
  font-size: 1rem;
  font-weight: var(--weight-body-strong);
  min-width: 130px;
  text-align: center;
}
.btn-nav {
  background: var(--surface);
  border: 1px solid var(--border-strong);
  color: var(--muted);
  width: var(--control-sm); height: var(--control-sm);
  border-radius: var(--radius-control);
  cursor: pointer;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: var(--control-sm-fs);
  transition: background var(--transition), color var(--transition);
}
.btn-nav:hover { background: var(--row-hover); color: var(--ink); }

/* RTA block — "ready to assign" is the headline number */
.rta-block { display: flex; align-items: center; gap: var(--space-3); }
.rta-text { display: flex; flex-direction: column; gap: 0.1rem; }
.rta-label {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--muted);
}
.rta-amount {
  font-size: 1.9rem;
  color: var(--primary);
  line-height: 1.1;
}
.rta-sublabel { font-size: 0.73rem; color: var(--muted); }

/* Overassigned is attention, not failure — yellow, never red. */
/* RTA negativo — vermelho desde PRJ-DEC-008: o dinheiro atribuído não
   existe (plano matematicamente inválido), categoria diferente de
   categoria estourada (que continua em amarelo preenchido — dinheiro
   que existe em outro lugar, só precisa realocar). Preenchido, não só
   texto recolorido: é o estado mais grave que o bloco pode mostrar. */
.rta-block.rta-negative {
  background: var(--chip-danger-bg);
  border: 1px solid var(--chip-danger-border);
  border-radius: var(--radius-card);
  padding: var(--space-2) var(--space-3);
  margin: calc(var(--space-2) * -1) calc(var(--space-3) * -1);
}
.rta-block.rta-negative .rta-amount { color: var(--chip-danger-text); }
.rta-block.rta-negative .rta-sublabel { color: var(--chip-danger-text); }

/* ─── Anel do Pronto pra Atribuir ───────────────────────────────
   Fecha conforme o dinheiro recebe função — não é decorativo, é a
   mesma informação do número ao lado, só que de relance. Três
   estados (routes/budget.py::_rta_ring): positive (verde, ainda tem
   pra atribuir), zero (neutro, anel aberto — tudo atribuído), over
   (vermelho desde PRJ-DEC-008 — ver nota acima). */
.rta-ring { width: 44px; height: 44px; flex-shrink: 0; }
.rta-ring-track {
  fill: none;
  stroke: var(--track);
  stroke-width: 6;
}
.rta-ring-fill {
  fill: none;
  stroke-width: 6;
  stroke-linecap: round;
  transition: stroke-dashoffset 0.3s ease, stroke 0.2s ease;
}
.rta-ring-positive .rta-ring-fill { stroke: var(--primary); }
.rta-ring-zero .rta-ring-fill { stroke: var(--chip-neutral-border); }
.rta-ring-over .rta-ring-fill { stroke: var(--chip-danger-border); }

/* ─── FILTER BAR ────────────────────────────────────────────── */
.budget-filters {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.6rem 1.75rem;
  border-bottom: 1px solid var(--border);
  background: var(--bg);
  flex-shrink: 0;
  gap: var(--space-2);
}

.filter-tabs { display: flex; gap: 4px; }
.filter-tab {
  background: transparent;
  border: 1px solid transparent;
  color: var(--muted);
  height: var(--control-sm);
  padding: 0 var(--control-sm-px);
  border-radius: var(--radius-control);
  font-family: var(--font-body);
  font-size: var(--control-sm-fs);
  display: inline-flex;
  align-items: center;
  cursor: pointer;
  transition: background var(--transition), border-color var(--transition), color var(--transition);
}
.filter-tab:hover { border-color: var(--border-strong); color: var(--ink); }
.filter-tab.active {
  background: var(--chip-ok-bg);
  border-color: var(--chip-ok-border);
  color: var(--chip-ok-text);
}

/* ─── BUDGET TABLE ──────────────────────────────────────────── */
.budget-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);   /* 12px — densidade escolhida na opção B */
}

.th-with-tip { display: inline-flex; align-items: center; gap: var(--space-1); }

.budget-table thead th {
  text-align: left;
  height: var(--row-h);
  padding: 0 var(--space-3) 0 1.75rem;
  border-bottom: 1px solid var(--border);
  color: var(--muted);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  background: var(--bg);
  position: sticky;
  top: 0;
  z-index: 1;
}
.budget-table thead th.num-col,
.budget-table thead th.avail-th { text-align: right; }

/* Group rows */
.group-row { cursor: default; }
.group-row td {
  height: calc(var(--row-h) + var(--space-2));
  padding: var(--space-3) var(--space-3) var(--space-1) 1.75rem;
  font-weight: 700;
  font-size: var(--text-xs);
  color: var(--ink);
  border-bottom: 1px solid var(--border);
  background: var(--bg);
}
.group-row .num-col { text-align: right; padding-right: var(--space-4); }

.group-name-cell { vertical-align: middle; white-space: nowrap; }
.group-name-cell > * { vertical-align: middle; }
.group-toggle {
  font-size: 0.65rem;
  color: var(--muted);
  cursor: pointer;
  user-select: none;
  width: 12px;
  display: inline-block;
  margin-right: var(--space-1);
  transition: transform 0.15s;
}

/* Category rows */
.category-row td {
  height: var(--row-h);        /* 28px */
  padding: 0 var(--space-3);
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
  background: var(--surface);
}
.category-row:hover td { background: var(--row-hover); }
/* Overspent reads as attention, not punishment. */
.category-row.overspent td { background: var(--chip-warn-bg); }

/* NÃO usar display:flex num <td>. Isso tira a célula do contexto de
   formatação de tabela: ela deixa de participar do dimensionamento de
   coluna e a própria borda inferior passa a ser desenhada num
   comprimento diferente do resto da linha — a "barra solta" sob cada
   categoria. O alinhamento vertical resolve-se com vertical-align, e o
   conteúdo interno com inline-block. */
.cat-name-cell {
  padding-left: 1.75rem !important;
  vertical-align: middle;
  white-space: nowrap;
}
.cat-name-cell > * { vertical-align: middle; }
.cat-indent { display: inline-block; width: 12px; }
.cat-label {
  display: inline-block;
  max-width: 22ch;
  cursor: pointer;
  color: var(--ink);
  transition: color var(--transition);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cat-label:hover { color: var(--primary); }
.cat-empty {
  padding: 0.4rem 0.75rem 0.4rem 3rem !important;
  color: var(--muted);
  font-style: italic;
  font-size: 0.8rem;
}

/* Assign input */
.assign-cell { text-align: right; padding: 0.2rem 0 !important; }
.assign-form { display: flex; justify-content: flex-end; margin: 0; padding-right: var(--space-2); }
.assign-input {
  width: 92px;
  text-align: right;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius-control);
  padding: 0 var(--control-sm-px);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--control-sm-fs);
  margin: 0; height: var(--control-sm);
  transition: background var(--transition), border-color var(--transition);
}
.assign-input:hover { border-color: var(--border-strong); background: var(--surface); }
.assign-input:focus {
  background: var(--surface);
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--focus-ring);
  outline: none;
}
/* No painel de detalhe (não na linha densa da tabela) é a única forma
   de editar no celular — precisa parecer obviamente editável mesmo
   sem foco, não um texto estático até passar o mouse (que no celular
   nunca acontece). */
#panel-assign-row .assign-input {
  width: 110px;
  border-color: var(--border-strong);
  background: var(--surface);
}

/* Number columns */
.num-col { text-align: right; width: 11ch; padding-right: var(--space-4) !important; }
.avail-col { text-align: right; width: 14ch; padding-right: 1.25rem !important; }
.avail-th { width: 14ch; padding-right: 1.25rem !important; }

/* A negative balance is a fact, not an alarm — plain ink. */
.negative { color: var(--ink); }
.positive { color: var(--text-ok); }

/* Available badges — the chip system applied to funding state */
.avail-badge {
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
  min-width: 11ch;              /* largura fixa: ver .chip-num */
  padding: 2px var(--space-2);
  border-radius: var(--radius-control);
  border: 1px solid transparent;
  font-size: var(--text-sm);
  font-weight: var(--weight-body-strong);
  white-space: nowrap;
}
.avail-badge.funded {
  background: var(--chip-ok-bg);
  border-color: var(--chip-ok-border);
  color: var(--chip-ok-text);
}
/* Subfinanciado e gasto-além são estados diferentes e precisam de pesos
   diferentes. Ambos ficam no matiz de atenção — vermelho continua
   reservado ao irreversível (PRJ-DEC-006) — mas o CONTORNADO diz "dá
   para fazer mais" e o PREENCHIDO diz "precisa arrumar". A forma
   carrega a gravidade; o matiz carrega "isto pede atenção". */
.avail-badge.partial {
  background: var(--surface);
  border-color: var(--chip-warn-border);
  color: var(--chip-warn-text);
}
.avail-badge.overspent {
  background: var(--chip-warn-bg);
  border-color: var(--chip-warn-border);
  color: var(--chip-warn-text);
}
.avail-badge.zero {
  background: var(--chip-neutral-bg);
  border-color: var(--chip-neutral-border);
  color: var(--chip-neutral-text);
}

/* ─── RIGHT PANEL ───────────────────────────────────────────── */
.panel-header { margin-bottom: var(--space-4); }
.panel-back {
  font-size: 0.75rem;
  color: var(--primary);
  cursor: pointer;
  display: block;
  margin-bottom: 0.3rem;
  transition: color var(--transition);
}
.panel-back:hover { color: var(--primary-hover); }
.panel-title { font-size: 0.95rem; font-weight: 700; color: var(--ink); }

.summary-section { display: flex; flex-direction: column; gap: 0; }
.summary-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: var(--space-2) 0;
  font-size: 0.82rem;
  border-bottom: 1px solid var(--border);
  color: var(--muted);
  gap: var(--space-2);
}
.summary-row span:first-child { flex: 1; }
.summary-row span:last-child {
  font-variant-numeric: tabular-nums;
  font-weight: var(--weight-body-strong);
  color: var(--ink);
  flex-shrink: 0;
}
.summary-total {
  border-top: 1px solid var(--border-strong);
  border-bottom: none;
  padding-top: 0.6rem;
  margin-top: 0.2rem;
  font-weight: 700;
}
.summary-total span { color: var(--ink) !important; }

.panel-divider { border: none; border-top: 1px solid var(--border); margin: var(--space-4) 0; }
.panel-section-label {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--muted);
  font-weight: 700;
  margin-bottom: 0.6rem;
}
.panel-hint { font-size: 0.77rem; color: var(--muted); font-style: italic; line-height: 1.5; }
/* An inline link inside hint text can't rely on color alone against the
   muted/italic paragraph around it — the global `a` rule only underlines
   on hover, which isn't enough affordance here (confirmed: a tester missed
   the import-instead link in onboarding entirely until they hovered). */
.panel-hint a { text-decoration: underline; font-weight: 600; }

/* Auto-assign buttons */
.auto-assign-options { display: flex; flex-direction: column; gap: 0.4rem; }
.auto-assign-btn {
  background: var(--surface-sunk);
  border: 1px solid var(--border);
  border-radius: var(--radius-control);
  color: var(--muted);
  min-height: var(--control-md);
  padding: 0 var(--control-md-px);
  font-family: var(--font-body);
  font-size: var(--control-md-fs);
  cursor: not-allowed;
  text-align: left;
  opacity: 0.6;
}

/* Goal form */
.goal-form { display: flex; flex-direction: column; gap: var(--space-2); }
.panel-label {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  font-size: 0.78rem;
  color: var(--muted);
}
.panel-select,
.panel-input {
  width: 100%;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-control);
  color: var(--ink);
  font-family: var(--font-body);
  height: var(--control-md);
  padding: 0 var(--control-md-px);
  font-size: var(--control-md-fs);
}
.panel-select:focus,
.panel-input:focus {
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--focus-ring);
  outline: none;
}

/* Category items — "de que essa categoria é feita" */
.item-list {
  list-style: none;
  margin: 0 0 var(--space-3);
  padding: 0;
  display: flex;
  flex-direction: column;
}
.item-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: 0.4rem 0;
  border-bottom: 1px solid var(--border);
  font-size: 0.82rem;
}
.item-name { flex: 1; min-width: 0; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cadence-chip { flex-shrink: 0; }
.item-amount {
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
  min-width: 7ch;
  text-align: right;
}
.item-delete-btn {
  flex-shrink: 0;
  background: none;
  border: none;
  color: var(--muted);
  font-size: 1rem;
  line-height: 1;
  width: var(--control-sm);
  height: var(--control-sm);
  border-radius: var(--radius-control);
  cursor: pointer;
  transition: background var(--transition), color var(--transition);
}
.item-delete-btn:hover { background: var(--row-hover); color: var(--brand-red); }

.item-suggestion {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
  padding: var(--space-2) 0.6rem;
  margin-bottom: var(--space-3);
  background: var(--surface-sunk);
  border-radius: var(--radius-control);
  font-size: 0.8rem;
  color: var(--muted);
}
.item-suggestion strong {
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  margin-right: auto;
}

.item-add-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-top: var(--space-2);
  padding-top: var(--space-2);
}

/* ─── Ajuda em contexto: (i) com balão ──────────────────────────
   Botão pequeno que revela uma explicação curta — self-service pros
   principais recursos, sem sair da tela. Hover/foco no desktop; toque
   alterna via .is-open (ver app.js), porque :hover não existe em touch. */
.info-tip {
  position: relative;
  display: inline-flex;
  cursor: help;
}
.info-tip-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 1px solid var(--border-strong);
  color: var(--muted);
  font-size: 10px;
  font-style: italic;
  font-family: Georgia, 'Times New Roman', serif;
  line-height: 1;
  user-select: none;
}
.info-tip:hover .info-tip-icon,
.info-tip:focus-within .info-tip-icon,
.info-tip.is-open .info-tip-icon {
  border-color: var(--primary);
  color: var(--primary);
}
.info-tip-bubble {
  position: absolute;
  z-index: 30;
  top: calc(100% + 6px);
  left: 50%;
  transform: translateX(-50%) translateY(-4px);
  width: 220px;
  padding: var(--space-2) var(--space-3);
  background: var(--ink);
  color: var(--surface);
  border-radius: var(--radius-control);
  font-size: 0.72rem;
  font-weight: 400;
  text-transform: none;
  letter-spacing: normal;
  line-height: 1.5;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.18);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity var(--transition), transform var(--transition), visibility var(--transition);
}
.info-tip:hover .info-tip-bubble,
.info-tip:focus-within .info-tip-bubble,
.info-tip.is-open .info-tip-bubble {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: translateX(-50%) translateY(0);
}
@media (prefers-reduced-motion: reduce) {
  .info-tip-bubble { transition: none; }
}

/* Perto da borda direita (painel de 268px, cabeçalho "Disponível") um
   balão centralizado estoura a borda — ancora pela direita ali. */
.budget-right .info-tip-bubble,
.avail-th .info-tip-bubble {
  left: auto;
  right: -8px;
  transform: translateY(-4px);
  width: 200px;
}
.budget-right .info-tip:hover .info-tip-bubble,
.budget-right .info-tip:focus-within .info-tip-bubble,
.budget-right .info-tip.is-open .info-tip-bubble,
.avail-th .info-tip:hover .info-tip-bubble,
.avail-th .info-tip:focus-within .info-tip-bubble,
.avail-th .info-tip.is-open .info-tip-bubble {
  transform: translateY(0);
}

/* ─── Modo "explicar esta tela" ─────────────────────────────── */
/* Contorno sempre visível (não só no hover) enquanto o modo está ativo —
   precisa funcionar igual em toque, que não tem hover. */
body.help-mode-active [data-help-topic] {
  outline: 1px dashed var(--primary);
  outline-offset: 2px;
  border-radius: 3px;
  cursor: help;
}
#help-mode-toggle.is-active { color: var(--primary); }

/* Painel de ajuda recém-aberto: pulso breve pra guiar o olho até o
   parágrafo certo, não só o topo do artigo. */
.help-highlight { animation: help-highlight-pulse 1.6s ease-out; }
@keyframes help-highlight-pulse {
  0%   { background: var(--chip-ok-bg); }
  100% { background: transparent; }
}

.help-panel-full-link {
  display: block;
  font-size: 0.75rem;
  color: var(--muted);
  text-decoration: none;
  margin-bottom: var(--space-3);
}
.help-panel-full-link:hover { color: var(--ink); }

/* ─── Transactions ──────────────────────────────────────────── */
.tx-table { width: 100%; border-collapse: collapse; font-size: 0.875rem; }
.tx-table th {
  text-align: left;
  padding: 0.5rem 0.75rem;
  border-bottom: 2px solid var(--border);
  color: var(--muted);
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.07em;
}
.tx-table td { padding: 0.45rem 0.75rem; border-bottom: 1px solid var(--border); vertical-align: middle; }
.tx-table tr:hover td { background: var(--row-hover); }

.cleared-dot {
  display: inline-block;
  width: 9px; height: 9px;
  border-radius: 50%;
  background: var(--track);
  border: 2px solid var(--border-strong);
  cursor: pointer;
  transition: background var(--transition), border-color var(--transition);
}
.cleared-dot.cleared { background: var(--primary); border-color: var(--primary); }
.cleared-dot.reconciled { background: var(--chip-ok-text); border-color: var(--chip-ok-text); }

/* ─── Lançamento inline ──────────────────────────────────────────
   Linha editável no topo da grade. Substitui o formulário de tela
   cheia — ver design_directions_ii.md §7.
   ──────────────────────────────────────────────────────────────*/
.tx-toolbar { display: flex; gap: var(--space-2); margin-bottom: var(--space-2); }

.tx-edit > .tx-edit-cell {
  padding: var(--space-2) var(--space-3);
  background: var(--chip-ok-bg);
  border-bottom: 1px solid var(--chip-ok-border);
}
.tx-edit-form {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
  margin: 0;
}
/* Larguras proporcionais às colunas da grade, para a linha em edição
   não parecer um formulário estranho colado na tabela. */
.tx-f-account  { width: 9rem; flex: none; }
.tx-f-date     { width: 9.5rem; flex: none; }
.tx-f-payee    { flex: 1 1 11rem; min-width: 9rem; }
.tx-f-category { flex: 1 1 13rem; min-width: 10rem; }
.tx-f-memo     { flex: 1 1 9rem; min-width: 7rem; }
.tx-f-amount   { width: 8rem; flex: none; }
.tx-f-inst     { width: 4.5rem; flex: none; }

/* Campo com lista de sugestões também declara que expande. */
.has-chevron {
  background-image: var(--chevron);
  background-repeat: no-repeat;
  background-position: right var(--control-sm-px) center;
  padding-right: calc(var(--control-sm-px) * 2 + var(--icon-sm));
}

.tx-edit-actions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
  width: 100%;
  padding-top: var(--space-2);
  border-top: 1px solid var(--chip-ok-border);
}
.tx-installments {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--text-xs);
  color: var(--muted);
  cursor: pointer;
  white-space: nowrap;
}
.tx-edit-hint {
  font-size: var(--text-xs);
  color: var(--muted);
  flex: 1 1 14rem;
  min-width: 0;
}
#tx-cancel { margin-left: auto; }

/* ─── Accounts ──────────────────────────────────────────────── */
.account-list { display: grid; gap: 0.6rem; }
.account-card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.9rem 1.25rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  transition: border-color var(--transition);
}
.account-card:hover { border-color: var(--primary); }
.account-name-row { display: flex; align-items: center; gap: var(--space-2); }
.account-name-row .icon-lg { color: var(--muted); flex-shrink: 0; }
.account-name { font-weight: var(--weight-body-strong); color: var(--ink); }
.account-meta { margin-top: 0.2rem; }
.account-type-badge {
  font-size: 0.66rem;
  padding: 0.12rem 0.4rem;
  border-radius: var(--radius-control);
  background: var(--chip-neutral-bg);
  border: 1px solid var(--chip-neutral-border);
  color: var(--chip-neutral-text);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.account-actions { display: flex; align-items: center; gap: var(--space-3); }
.account-balance { font-size: var(--text-md); font-weight: 700; }
.account-balance.negative { color: var(--ink); }
.account-balance.positive { color: var(--text-ok); }

.pix-keys { border-top: 1px dashed var(--border-strong); }

/* ─── Configurações ─────────────────────────────────────────── */
.settings-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
  gap: var(--space-4);
  max-width: 64rem;
}
/* minmax(20rem,1fr) = 320px mínimos por coluna — em telas abaixo de
   ~720px isso força 2 colunas de 320px a estourarem a viewport (achado
   da revisão manual do onboarding: rolagem horizontal severa em
   Configurações a 375px). Uma coluna só resolve. */
@media (max-width: 720px) {
  .settings-grid { grid-template-columns: 1fr; }
}
.stack { display: flex; flex-direction: column; gap: var(--space-3); margin: 0; }
.stack .field { gap: var(--space-1); }

.theme-choice { display: flex; gap: var(--space-2); flex-wrap: wrap; }
.theme-option {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  min-height: var(--control-md);
  padding: 0.35rem var(--control-md-px);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-control);
  font-size: var(--control-md-fs);
  cursor: pointer;
  transition: border-color var(--transition), background var(--transition);
}
.theme-option.is-active {
  border-color: var(--chip-ok-border);
  background: var(--chip-ok-bg);
  color: var(--chip-ok-text);
}
.theme-option input { accent-color: var(--primary); }

.switch {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-base);
  cursor: pointer;
}
.switch input { accent-color: var(--primary); width: 16px; height: 16px; }

/* ─── Modal ─────────────────────────────────────────────────────
   Último recurso, reservado a confirmação irreversível — §8 do estudo
   II. É o único do app.
   ──────────────────────────────────────────────────────────────*/
.modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-4);
  background: rgba(0, 0, 0, 0.45);
}
.modal-backdrop[hidden] { display: none; }
.modal {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: var(--space-5);
  max-width: 26rem;
  width: 100%;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.25);
}
.modal-title { font-size: var(--text-md); margin-bottom: var(--space-2); }
.modal-body { font-size: var(--text-base); color: var(--muted); margin-bottom: var(--space-4); }
.modal-actions { display: flex; gap: var(--space-2); justify-content: flex-end; align-items: center; }

/* ─── Aviso rápido (modo "explicar esta tela") ─────────────────
   Clicar num ponto sem artigo associado, no modo ajuda, ficava
   silencioso — achado do operador ("ainda não faz nada"). Em vez de
   fingir cobertura que a base de conhecimento ainda não tem (ver
   BKLG-002, deliberadamente adiado), isto só torna a ausência honesta
   em vez de parecer quebrado. */
.help-toast {
  position: fixed;
  left: 50%;
  bottom: var(--space-6);
  transform: translateX(-50%) translateY(8px);
  z-index: 95;
  background: var(--ink);
  color: var(--surface);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-control);
  font-size: 0.8rem;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--transition), transform var(--transition);
}
.help-toast.is-visible { opacity: 1; transform: translateX(-50%) translateY(0); }
@media (prefers-reduced-motion: reduce) {
  .help-toast { transition: none; }
}

/* ─── Forms ─────────────────────────────────────────────────── */
.form-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(175px, 1fr));
  gap: var(--space-4);
  margin-bottom: var(--space-4);
}
.form-row label { display: flex; flex-direction: column; gap: 0.3rem; font-size: 0.82rem; color: var(--muted); }
.form-row input,
.form-row select {
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-control);
  color: var(--ink);
  font-family: var(--font-body);
  height: var(--control-md);
  padding: 0 var(--control-md-px);
  font-size: var(--control-md-fs);
}
.form-row input:focus,
.form-row select:focus {
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--focus-ring);
  outline: none;
}

/* ─── Import ────────────────────────────────────────────────── */
.import-zone {
  border: 2px dashed var(--border-strong);
  border-radius: var(--radius-card);
  padding: var(--space-6) 1.25rem;
  text-align: center;
  color: var(--muted);
  transition: border-color 0.2s;
}
.import-zone:hover { border-color: var(--primary); }
.import-zone input[type="file"] { color: var(--muted); font-size: 0.85rem; }

/* ─── Banners ───────────────────────────────────────────────── */
.success-banner {
  background: var(--chip-ok-bg);
  border: 1px solid var(--chip-ok-border);
  border-radius: var(--radius-card);
  padding: var(--space-4) 1.25rem;
  color: var(--chip-ok-text);
  margin-bottom: var(--space-4);
}
.warn-banner {
  background: var(--chip-warn-bg);
  border: 1px solid var(--chip-warn-border);
  border-radius: var(--radius-card);
  padding: var(--space-4) 1.25rem;
  color: var(--chip-warn-text);
  margin-bottom: var(--space-4);
}

/* ─── Reports ───────────────────────────────────────────────── */
.report-table { width: 100%; border-collapse: collapse; font-size: 0.875rem; }
.report-table th {
  text-align: left;
  padding: 0.45rem 0.75rem;
  border-bottom: 2px solid var(--border);
  color: var(--muted);
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.07em;
}
.report-table td { padding: var(--space-2) 0.75rem; border-bottom: 1px solid var(--border); }
.report-table tr:hover td { background: var(--row-hover); }
.report-table td.num { text-align: right; }

/* ─── Empty states ──────────────────────────────────────────── */
.empty-cell { text-align: center; padding: 2.5rem; color: var(--muted); }

/* ─── Chaves Pix ────────────────────────────────────────────── */
.pix-keys {
  grid-column: 1 / -1;
  width: 100%;
  margin-top: var(--space-2);
  padding-top: var(--space-2);
  border-top: 1px dashed var(--border-strong);
}
.pix-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) 0;
  font-size: var(--text-sm);
}
.pix-row code { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.pix-form {
  display: flex;
  gap: var(--space-2);
  align-items: center;
  margin-top: var(--space-2);
  flex-wrap: wrap;
}
.pix-form .input { flex: 1; min-width: 180px; }
.badge-fixed { min-width: 3.4rem; justify-content: center; }

.add-category-row td { padding: var(--space-2) 0.75rem; }
.category-add-form {
  display: flex;
  gap: var(--space-2);
  align-items: center;
  margin-top: var(--space-2);
  flex-wrap: wrap;
}
.category-add-form .input,
.category-add-form .select { flex: 1; min-width: 140px; }

/* <summary> com cara de link discreto */
.summary-link {
  display: inline-flex;
  align-items: center;
  height: var(--control-sm);
  font-size: var(--text-xs);
  color: var(--muted);
  cursor: pointer;
}
.summary-link:hover { color: var(--primary); }

/* <summary> com cara de botão */
.summary-btn { display: inline-flex; margin-bottom: var(--space-3); }

.form-hint {
  font-size: var(--text-xs);
  color: var(--muted);
  margin: var(--space-2) 0 var(--space-3);
}

/* Explicação de campo, separada visualmente do resto do formulário por
   uma borda fina — não é aviso (sem cor de alerta), só precisa ficar
   claramente destacada do texto ao redor. Reaproveitável pelo texto
   contextual dinâmico também (ver static/js/app.js). */
.field-hint-box {
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: var(--space-3) 1rem;
  color: var(--muted);
  font-size: var(--text-xs);
  margin: var(--space-2) 0 var(--space-3);
}

/* ─── Utility ───────────────────────────────────────────────── */
.text-muted { color: var(--muted); }
.text-xs { font-size: var(--text-xs); }
.text-sm { font-size: var(--text-sm); }
.m-0 { margin: 0; }
.flex-wrap { flex-wrap: wrap; }
.grow { flex: 1; min-width: 0; }
.w-full { width: 100%; }
.th-center { text-align: center; }
.td-nowrap { white-space: nowrap; }
.ml-1 { margin-left: var(--space-1); }
.hint-list {
  margin-top: var(--space-2);
  padding-left: var(--space-4);
  font-size: var(--text-xs);
  color: var(--muted);
  list-style: disc;
}
.text-ok { color: var(--text-ok); }
.text-danger { color: var(--text-danger); }
.page-title { font-size: 1.25rem; margin: 0 0 1.25rem; color: var(--ink); }
.section-label {
  font-size: 0.68rem;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.09em;
  font-weight: 700;
  margin-bottom: var(--space-2);
}
.flex { display: flex; }
.gap-1 { gap: var(--space-2); }
.gap-2 { gap: var(--space-4); }
.items-center { align-items: center; }
.justify-between { justify-content: space-between; }
.justify-end { justify-content: flex-end; }
.mt-1 { margin-top: var(--space-2); }
.mt-2 { margin-top: var(--space-4); }
.mt-3 { margin-top: var(--space-5); }
.mb-1 { margin-bottom: var(--space-2); }
.mb-2 { margin-bottom: var(--space-4); }
.mb-3 { margin-bottom: var(--space-5); }

/* ═══════════════════════════════════════════════════════════════
   ANÁLISE FINANCEIRA — design_directions_ii.md §12
   ═══════════════════════════════════════════════════════════════ */
.analysis-tabs { margin-bottom: var(--space-5); }
.analysis-content { max-width: 900px; }

.analysis-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}

.btn-disabled { opacity: 0.35; pointer-events: none; }

/* Trilha de navegação */
.analysis-breadcrumb {
  font-size: 0.78rem;
  color: var(--muted);
  margin-bottom: var(--space-3);
  display: flex;
  align-items: center;
  gap: var(--space-1);
  flex-wrap: wrap;
}
.breadcrumb-link {
  color: var(--primary);
  text-decoration: none;
  cursor: pointer;
}
.breadcrumb-link:hover { text-decoration: underline; }
.breadcrumb-sep { color: var(--border-strong); }
.breadcrumb-current { color: var(--ink); font-weight: var(--weight-body-strong); }

.empty-state {
  padding: var(--space-7) var(--space-4);
  text-align: center;
  color: var(--muted);
  font-size: 0.85rem;
}

/* ─── Rosca + lista ranqueada (§12.2) ──────────────────────────── */
.analysis-donut-layout {
  display: flex;
  align-items: center;
  gap: var(--space-7);
  flex-wrap: wrap;
}

.donut-wrap { position: relative; flex-shrink: 0; width: 200px; height: 200px; }
.donut-svg { width: 100%; height: 100%; }
.donut-seg {
  cursor: pointer;
  transition: opacity var(--transition);
}
.donut-seg:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
.donut-seg.is-dimmed { opacity: 0.35; }

.donut-center {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  pointer-events: none;
  padding: 0 1.5rem;
}
.donut-center-value {
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.donut-center-label { font-size: 0.68rem; color: var(--muted); text-transform: uppercase; letter-spacing: 0.06em; }

.rank-list { list-style: none; margin: 0; padding: 0; flex: 1; min-width: 240px; }
.rank-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: 0.45rem 0.3rem;
  border-radius: var(--radius-control);
  cursor: pointer;
  transition: background var(--transition), opacity var(--transition);
}
.rank-row:hover, .rank-row.is-active { background: var(--row-hover); }
.rank-row.is-dimmed { opacity: 0.45; }
.rank-row:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }

.rank-swatch { width: 10px; height: 10px; border-radius: 2px; flex-shrink: 0; }
.rank-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 0.85rem; color: var(--ink); }
.rank-pct { flex-shrink: 0; font-size: 0.78rem; color: var(--muted); font-variant-numeric: tabular-nums; min-width: 4ch; text-align: right; }
.rank-value { flex-shrink: 0; font-size: 0.85rem; font-weight: var(--weight-body-strong); color: var(--ink); font-variant-numeric: tabular-nums; min-width: 9ch; text-align: right; }
.rank-bar { flex-shrink: 0; width: 60px; height: 4px; border-radius: 2px; background: var(--surface-sunk); overflow: hidden; }
.rank-bar-fill { display: block; height: 100%; border-radius: 2px; }

.analysis-footer { margin-top: var(--space-4); }

/* ─── Linha (tendência) e área (patrimônio) — §12.4 ────────────── */
.line-chart-wrap { position: relative; width: 100%; }
.line-chart-svg { width: 100%; height: auto; display: block; overflow: visible; }

.line-chart-path {
  stroke: var(--chart-1);
  stroke-width: 2px;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.area-chart-fill { fill: var(--chart-1); opacity: 0.12; stroke: none; }
.chart-zero-line {
  stroke: var(--chart-axis);
  stroke-width: 1px;
  stroke-dasharray: 3 3;
}
.line-chart-dot {
  fill: var(--chart-1);
  opacity: 0;
  transition: opacity var(--transition);
}
.line-chart-dot.is-active { opacity: 1; }
.line-chart-hit { fill: transparent; cursor: crosshair; }

.chart-tooltip {
  position: absolute;
  z-index: 10;
  transform: translate(-50%, calc(-100% - 10px));
  background: var(--ink);
  color: var(--surface);
  font-size: 0.72rem;
  padding: 0.35rem 0.6rem;
  border-radius: var(--radius-control);
  white-space: nowrap;
  pointer-events: none;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.18);
}

/* ─── Entradas × Saídas: barra divergente na célula (§12.4) ────── */
.net-bar {
  display: inline-block;
  width: 60px;
  height: 6px;
  background: var(--surface-sunk);
  border-radius: 2px;
  position: relative;
  margin-right: var(--space-2);
  vertical-align: middle;
}
.net-bar-fill {
  position: absolute;
  top: 0;
  height: 100%;
  border-radius: 2px;
}
.net-bar-fill.is-positive { left: 50%; background: var(--chip-ok-text); }
.net-bar-fill.is-negative { right: 50%; background: var(--chip-warn-text); }

@media (max-width: 720px) {
  .analysis-donut-layout { flex-direction: column; align-items: stretch; }
  .rank-list { min-width: 0; }
}

/* ═══════════════════════════════════════════════════════════════
   TOUR GUIADO EM CONTEXTO — substitui o antigo assistente de
   configuração em páginas separadas (ver services/tour.py). NÃO é o
   modal do app (.modal-backdrop acima) — fica abaixo dele no z-index
   de propósito, pra uma confirmação de verdade sempre vencer se
   alguma precisar interromper um tour em andamento.
   ═══════════════════════════════════════════════════════════════ */
.tour-backdrop {
  position: fixed;
  z-index: 90;
  top: 50%; left: 50%; width: 0; height: 0;
  border-radius: 6px;
  pointer-events: none;
  transition: top var(--transition), left var(--transition),
              width var(--transition), height var(--transition);
  /* Truque de um elemento só: este &lt;div&gt; é posicionado via JS
     (static/js/app.js) bem em cima do retângulo do elemento apontado
     (ou fica 0×0 no centro da tela, pra um passo sem âncora); o
     box-shadow com espalhamento gigante escurece todo o resto da tela
     ao redor dele, o que desenha o "recorte" iluminado sem precisar de
     um segundo elemento nem de CSS mask. */
}
.tour-backdrop.is-active {
  box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.45);
}
@media (prefers-reduced-motion: reduce) {
  .tour-backdrop { transition: none; }
}

.tour-bubble {
  position: fixed;
  z-index: 91;
  max-width: 320px;
  background: var(--primary);
  color: var(--primary-on);
  border-radius: var(--radius-card);
  padding: var(--space-4);
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.3);
  /* Posição real (top/left) é calculada em JS a partir de data-anchor —
     este valor inicial só evita um salto visível no primeiro paint. */
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
.tour-hide {
  position: absolute;
  top: var(--space-2);
  right: var(--space-2);
  background: none;
  border: none;
  color: var(--primary-on);
  opacity: 0.75;
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  padding: var(--space-1);
}
.tour-hide:hover { opacity: 1; }
.tour-step-counter {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  opacity: 0.8;
  margin-bottom: var(--space-1);
}
.tour-title { font-size: var(--text-base); margin: 0 0 var(--space-2); padding-right: var(--space-5); }
.tour-body { font-size: 0.85rem; line-height: 1.55; margin: 0 0 var(--space-3); opacity: 0.95; }
.tour-actions { display: flex; flex-direction: column; gap: var(--space-2); }
.tour-field {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  font-size: 0.8rem;
}
.tour-nav { display: flex; justify-content: flex-end; gap: var(--space-2); }
/* Botões dentro do balão herdam a cor do tema, não a paleta própria de
   .btn-primary/.btn-ghost (que assumem fundo claro) — sobrescritos aqui
   só dentro de .tour-bubble. */
.tour-bubble .btn-primary { background: var(--primary-on); color: var(--primary); }
.tour-bubble .btn-primary:hover { background: var(--primary-on); opacity: 0.9; }
.tour-bubble .btn-ghost { border-color: var(--primary-on); color: var(--primary-on); }
.tour-bubble .select { background: var(--primary-on); color: var(--ink); }

/* ═══════════════════════════════════════════════════════════════
   RENDA COMPROMETIDA COM PARCELAMENTOS
   ═══════════════════════════════════════════════════════════════ */
.installments-summary {
  display: flex;
  gap: var(--space-6);
  flex-wrap: wrap;
  margin-bottom: var(--space-5);
}
.installments-stat-value {
  font-size: 1.3rem;
  font-weight: 700;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.installments-stat-value.is-attention { color: var(--chip-warn-text); }
.installments-stat-label {
  font-size: 0.72rem;
  color: var(--muted);
  display: flex;
  align-items: center;
  gap: var(--space-1);
  margin-top: 0.15rem;
}

.installments-bars {
  display: flex;
  align-items: flex-end;
  gap: var(--space-2);
  height: 160px;
  padding: 0 var(--space-2);
  border-bottom: 1px solid var(--border);
  margin-bottom: var(--space-2);
}
.installments-bar-col {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  height: 100%;
  min-width: 0;
}
.installments-bar {
  width: 60%;
  min-height: 2px;
  background: var(--chart-1);
  border-radius: 2px 2px 0 0;
}
.installments-bar-label {
  font-size: 0.62rem;
  color: var(--muted);
  margin-top: 0.3rem;
  text-transform: uppercase;
  white-space: nowrap;
}

/* ─── Base de conhecimento (help) ────────────────────────────── */
.help-index-intro {
  color: var(--muted);
  margin: -0.75rem 0 var(--space-5);
  max-width: 42rem;
}

.help-article-list {
  display: grid;
  gap: var(--space-3);
}

.help-article-card {
  display: block;
  text-decoration: none;
  color: inherit;
  transition: border-color var(--transition), background var(--transition);
}
.help-article-card:hover,
.help-article-card:focus-visible {
  border-color: var(--border-strong);
  background: var(--row-hover);
}
.help-article-card h3 {
  margin: 0 0 var(--space-1);
  font-size: var(--text-md);
  font-weight: var(--weight-body-strong);
  color: var(--ink);
}
.help-article-card p {
  margin: 0;
  color: var(--muted);
  font-size: var(--text-base);
}

.help-back {
  display: inline-block;
  color: var(--muted);
  text-decoration: none;
  font-size: var(--text-sm);
  margin-bottom: var(--space-3);
}
.help-back:hover { color: var(--ink); }

/* Coluna de leitura: mais estreita que o resto do app de propósito —
   texto corrido em largura de página inteira é difícil de ler. */
.help-article {
  max-width: 42rem;
}
.help-article h3 {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  margin: var(--space-6) 0 var(--space-3);
}
.help-article p {
  line-height: 1.6;
  margin: 0 0 var(--space-4);
}
.help-lede {
  font-size: var(--text-md);
  line-height: 1.6;
  color: var(--ink);
}

.help-priorities {
  list-style: none;
  counter-reset: help-priority;
  margin: 0 0 var(--space-4);
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.help-priorities li {
  counter-increment: help-priority;
  position: relative;
  padding: var(--space-3) var(--space-4) var(--space-3) 2.75rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  line-height: 1.6;
}
.help-priorities li::before {
  content: counter(help-priority);
  position: absolute;
  left: var(--space-3);
  top: var(--space-3);
  width: 1.375rem;
  height: 1.375rem;
  border-radius: 50%;
  background: var(--surface-sunk);
  border: 1px solid var(--border-strong);
  color: var(--muted);
  font-size: var(--text-xs);
  font-weight: var(--weight-body-strong);
  display: flex;
  align-items: center;
  justify-content: center;
}
.help-priorities strong {
  display: block;
  color: var(--ink);
  margin-bottom: 0.2rem;
}

/* Imagem no tamanho real, nunca esticada — um recorte pequeno (ex.: o
   bloco "Pronto para atribuir") não deve inflar até a largura da coluna
   de leitura, senão pixeliza. max-width (não width) deixa a imagem no
   seu tamanho nativo e só encolhe se não couber; a largura exata de
   cada shot vem de static/img/help/_shots.json via routes/help.py, que
   vira o style="max-width:Npx" inline no <img> (ver help/metodo.html). */
.help-figure {
  margin: var(--space-5) 0;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.help-figure img {
  max-width: 100%;
  height: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  display: block;
  background: var(--surface-sunk);
}
.help-figure figcaption {
  margin-top: var(--space-2);
  font-size: var(--text-sm);
  color: var(--muted);
  line-height: 1.5;
  align-self: stretch;
}

/* Selo de aviso (help/_macros.html::note()) — 4 níveis validados em
   protótipo: Importante (chip-ok) < Aviso (chip-warn) < Atenção
   (chip-attention) < Cuidado (chip-danger, mesma cor que ação
   irreversível/RTA negativo em PRJ-DEC-008). A cor mora na pill, não
   no fundo do bloco — o contêiner é neutro nos 4 casos. */
.help-callout {
  display: flex;
  gap: var(--space-3);
  align-items: flex-start;
  background: var(--surface-sunk);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: var(--space-3) var(--space-4);
  line-height: 1.6;
  margin: var(--space-4) 0;
}
.help-callout .chip {
  flex-shrink: 0;
  margin-top: 0.15rem;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}

.help-section-title {
  margin: var(--space-6) 0 var(--space-3);
}
.help-section-title:first-child { margin-top: 0; }

/* ═══════════════════════════════════════════════════════════════
   RESPONSIVO: TELAS DE CELULAR (≤720px) E TABLET
   Achado do operador: usando o app de verdade num celular, o layout
   "quebra completamente" — a barra lateral/topbar cobria quase toda a
   tela estreita (resolvido antes, ver @media em cima) mas o conteúdo
   em si (grade do orçamento com painel fixo de 268px, linha de
   lançamento com vários campos lado a lado) nunca tinha tratamento
   mobile — só reflui por acidente via flex-wrap, sem garantia de não
   estourar a largura da página. Tablet (721–1024px) herda o layout
   de desktop por padrão (a barra lateral cabe de sobra ali) — não
   precisa de um terceiro modo, só de verificação visual (feito via
   screenshot em 3 larguras antes deste commit).
   ═══════════════════════════════════════════════════════════════ */

/* Rede de segurança genérica pra qualquer tabela larga: nunca deixa o
   conteúdo dela forçar scroll horizontal da PÁGINA — o scroll fica
   contido na própria tabela. Não muda nada em telas onde já cabe. */
.table-scroll { width: 100%; overflow-x: auto; }

/* ─── Barra de navegação inferior (celular) ────────────────────── */
.mobile-bottom-nav { display: none; }

@media (max-width: 720px) {
  .mobile-bottom-nav {
    display: flex;
    position: fixed;
    bottom: 0; left: 0; right: 0;
    z-index: 30;
    background: var(--surface);
    border-top: 1px solid var(--border);
    /* padding-bottom extra pro "home indicator" do iOS / gesture bar
       do Android não ficar por cima dos itens. */
    padding-bottom: env(safe-area-inset-bottom, 0);
  }
  .bottom-nav-item {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    padding: 0.4rem 0 0.35rem;
    min-height: 56px;
    background: none;
    border: none;
    color: var(--muted);
    font-family: var(--font-body);
    font-size: 0.68rem;
    text-decoration: none;
    cursor: pointer;
  }
  .bottom-nav-item.active { color: var(--primary); }
  .bottom-nav-icon { width: var(--icon-sm); height: var(--icon-sm); }
  /* Reaproveita o ícone de hambúrguer que já existia na topbar — some
     de lá (ver base.html) e passa a viver só aqui, na aba "Mais". */
  .bottom-nav-item .mobile-menu-icon,
  .bottom-nav-item .mobile-menu-icon::before,
  .bottom-nav-item .mobile-menu-icon::after { background: currentColor; }

  /* Conteúdo não pode ficar embaixo da barra fixa. */
  .main-content { padding-bottom: calc(56px + env(safe-area-inset-bottom, 0)); }
}

/* ─── Orçamento: painel de categoria vira uma folha no celular ────
   Primeira tentativa (empilhar .budget-right abaixo de .budget-center)
   deixava o painel fora da tela até rolar além da lista inteira de
   categorias — achado tocando o app de verdade, não só lendo o CSS.
   Agora é uma folha fixa que sobe de baixo, com fundo escurecido;
   .budget-right-close/backdrop (marcação em budget/index.html) só
   existem visualmente aqui dentro. O JS (app.js) só alterna .is-open
   em qualquer htmx:afterSwap de #right-panel-content — não importa
   qual elemento disparou a troca (categoria, "← Resumo", formulário de
   meta…), então nenhum gatilho precisa saber que está num celular. */
@media (max-width: 720px) {
  .budget-right-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.4);
    z-index: 39;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s ease;
  }
  .budget-right-backdrop.is-open { opacity: 1; pointer-events: auto; }

  .budget-right {
    position: fixed;
    /* top:auto é necessário — sem isto, o top:0 da regra de desktop
       (.budget-right{position:sticky;top:0}) vaza pra cá. Com top E
       bottom fixados, a folha fica presa no TOPO da tela (over-
       constrained: a regra inicial do CSS ignora bottom quando height
       também é limitada), e translateY(105%) nunca a tira da tela de
       verdade — achado ao vivo (BUG-mobile-002), não visível só lendo
       o CSS. */
    top: auto;
    left: 0; right: 0; bottom: 0;
    width: auto;
    max-height: 80vh;
    height: auto;
    border-left: none;
    border-top: 1px solid var(--border);
    border-radius: var(--radius-card) var(--radius-card) 0 0;
    box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.18);
    padding-top: 2.75rem;
    transform: translateY(105%);
    transition: transform 0.25s ease;
    z-index: 40;
  }
  .budget-right.is-open { transform: translateY(0); }

  .budget-right-close {
    position: absolute;
    top: var(--space-2); right: var(--space-2);
    width: 32px; height: 32px;
    display: flex; align-items: center; justify-content: center;
    background: var(--surface-sunk);
    border: none;
    border-radius: 50%;
    font-size: 1.3rem;
    line-height: 1;
    color: var(--muted);
    cursor: pointer;
  }
}
@media (min-width: 721px) {
  .budget-right-backdrop, .budget-right-close { display: none; }
}
@media (max-width: 720px) and (prefers-reduced-motion: reduce) {
  .budget-right, .budget-right-backdrop { transition: none; }
}

/* ─── Lançamento inline: largura mínima de cada campo somada passa
   de 60rem — em vez de depender só do flex-wrap (que empilha os
   campos de qualquer jeito), cada um ocupa a largura toda abaixo de
   720px, lado a lado só onde cabe de verdade (conta+data). ────── */
@media (max-width: 720px) {
  .tx-f-payee, .tx-f-category, .tx-f-memo, .tx-f-amount {
    flex: 1 1 100%;
    min-width: 0;
    width: auto;
  }
}

/* ─── Grade do orçamento: lista compacta, não tabela rolável ──────
   Rolar de lado era só um band-aid (achado do operador: "é sinal de
   que o design não foi feito pra celular"). A tabela real tem 4
   colunas (Categoria/Atribuído/Atividade/Disponível) — no celular só
   Categoria e Disponível ficam na linha (as duas que importam numa
   leitura rápida); Atribuído e Atividade saem da linha e viram parte
   do painel de detalhe, que agora tem um campo "Atribuído" editável
   (#panel-assign-row em partials/category_panel.html) — tocar a linha
   abre o painel, e é lá que se edita no celular, não mais na célula
   embutida (ver routes/budget.py::assign(), que mantém os dois em
   sincronia via OOB não importa qual deles originou a edição).
   Esconder por posição de coluna (não display:flex no <td> — quebra o
   contexto de formatação de tabela, ver comentário em cima de
   .cat-name-cell) é intencional: a ordem das 4 colunas é definida só
   neste template, estável o bastante pra não precisar de uma classe
   nova em cada <td>. ───────────────────────────────────────────── */
@media (max-width: 720px) {
  .budget-table thead { display: none; }
  .budget-table tbody tr > :nth-child(2),
  .budget-table tbody tr > :nth-child(3) {
    display: none;
  }
  .cat-label { max-width: none; }
  .cat-name-cell, .avail-col { padding-top: var(--space-2) !important; padding-bottom: var(--space-2) !important; }
  .category-row td, .group-row td { height: auto; }
}

/* ─── Transações: cartão de 2-3 linhas no celular, mesma ideia ─────
   A tabela continua sendo uma tabela de verdade (table-layout intacto,
   nunca display:flex num <td> enquanto ele participa de layout de
   tabela — mesmo aviso de cima) — só a <tr> de cada transação vira um
   container flex com wrap, e cada célula (ainda display:block)
   reordenada por "order" forma: Beneficiário+Valor na 1ª linha (o
   flex:1 do beneficiário já consome o espaço que sobra, então
   Conta/Data/Categoria naturalmente quebram pra 2ª linha sem precisar
   de truque de flex-basis:100% — só Memo e a linha de ações usam isso,
   porque aquelas sim precisam de linha própria garantida mesmo
   cabendo espaço sobrando na de cima). .tx-edit (a linha de
   lançamento, uma única <td colspan>) não tem a classe .tx-row, fica
   de fora disto inteiro — já tem tratamento próprio (ver .tx-f-*). */
@media (max-width: 720px) {
  .tx-table thead { display: none; }
  .tx-table tbody tr.tx-row {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    column-gap: var(--space-2);
    padding: var(--space-2) 0;
  }
  .tx-table tbody tr.tx-row td {
    display: block;
    border-bottom: none;
    padding: 0.1rem 0;
  }
  .tx-payee-cell {
    order: 1;
    flex: 1 1 auto;
    min-width: 0;
    font-weight: var(--weight-body-strong);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .tx-amount-cell { order: 2; flex: 0 0 auto; }
  .tx-account-cell, .tx-date-cell { order: 3; flex: 0 0 auto; font-size: var(--text-xs); }
  .tx-category-cell {
    order: 4;
    flex: 1 1 auto;
    min-width: 0;
    font-size: var(--text-xs);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  /* Separador só aparece quando a célula anterior existe de verdade —
     a coluna Conta some inteira quando filtrado a uma só conta (ver
     transactions/index.html), então isto não pode ser texto fixo no
     template. */
  .tx-account-cell + .tx-date-cell::before,
  .tx-date-cell + .tx-category-cell::before { content: ' · '; }

  /* Sempre força quebra de linha — mesmo vazia — pra ações (conciliado
     + excluir) sempre caírem juntas na própria linha final, não juntas
     com Conta/Data/Categoria quando o memo não existe pra empurrá-las.
     Uma quebra em branco de ~0.1rem de altura é um troco aceitável por
     não ter que inventar um <td> só pra isso. */
  .tx-memo-cell { order: 5; flex-basis: 100%; font-size: var(--text-xs); }

  .tx-cleared-cell, .tx-delete-cell {
    order: 6;
    flex: 0 0 auto;
    text-align: left;   /* sobrepõe .th-center — não há mais coluna de
                            desktop pra centralizar contra */
  }
  .tx-cleared-cell { margin-left: auto; }

  /* Alvos de toque maiores — 9px de bolinha (mais 2px de borda) nunca
     foi um alvo de dedo viável; a tabela densa de desktop usa mouse. */
  .tx-cleared-cell .cleared-dot { width: 16px; height: 16px; border-width: 3px; }
  .tx-cleared-cell, .tx-delete-cell { padding: var(--space-1) !important; }
}
