:root {
  --ground: #f4f6fa;
  --surface: #ffffff;
  --surface-2: #edf1f7;
  --border: #dde2ea;
  --ink: #14181f;
  --ink-soft: #565f70;
  --ink-mute: #8891a1;
  --accent: #2a78d6;
  --accent-ink: #ffffff;
  --accent-soft: #e5eefb;
  --accent-line: #b7d3f6;
  --good: #0ca30c;
  --good-soft: #e2f5e2;
  --warn: #b8790a;
  --warn-soft: #fdefd6;
  --critical: #d03b3b;
  --critical-soft: #fbe4e4;
  --grid: #e4e7ee;
  --shadow: 0 1px 2px rgba(20,24,31,0.04), 0 8px 24px -12px rgba(20,24,31,0.12);
  /* Sidebar de navegação: mesma paleta escura nos dois temas do app, tipo
     admin do WordPress — é a "casca" do painel, não muda com o conteúdo. */
  --nav-bg: #1c2130;
  --nav-bg-raised: #262c40;
  --nav-ink: #aab0c4;
  --nav-ink-active: #ffffff;
  --nav-border: rgba(255,255,255,0.07);
  --nav-accent: #4c8fef;
  color-scheme: light;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --ground: #14161b;
    --surface: #1b1e25;
    --surface-2: #23262e;
    --border: #333947;
    --ink: #f1f2f5;
    --ink-soft: #b7bcc8;
    --ink-mute: #7d8494;
    --accent: #3987e5;
    --accent-ink: #06121f;
    --accent-soft: #1c3252;
    --accent-line: #2d4d80;
    --good: #23c123;
    --good-soft: #123a17;
    --warn: #e2a53a;
    --warn-soft: #3a2c10;
    --critical: #e66767;
    --critical-soft: #3a1c1c;
    --grid: #2b2f38;
    --shadow: 0 1px 2px rgba(0,0,0,0.3), 0 8px 24px -12px rgba(0,0,0,0.5);
    color-scheme: dark;
  }
}
:root[data-theme="dark"] {
  --ground: #14161b;
  --surface: #1b1e25;
  --surface-2: #23262e;
  --border: #333947;
  --ink: #f1f2f5;
  --ink-soft: #b7bcc8;
  --ink-mute: #7d8494;
  --accent: #3987e5;
  --accent-ink: #06121f;
  --accent-soft: #1c3252;
  --accent-line: #2d4d80;
  --good: #23c123;
  --good-soft: #123a17;
  --warn: #e2a53a;
  --warn-soft: #3a2c10;
  --critical: #e66767;
  --critical-soft: #3a1c1c;
  --grid: #2b2f38;
  --shadow: 0 1px 2px rgba(0,0,0,0.3), 0 8px 24px -12px rgba(0,0,0,0.5);
  color-scheme: dark;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  background: var(--ground);
  color: var(--ink);
  font-family: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
  -webkit-font-smoothing: antialiased;
  line-height: 1.5;
}
.wrap {
  /* 1180px deixava a tabela de revisão do extrato (8 colunas, cada combo
     de Tipo/Bloco/Categoria/Item com no mínimo 108px) mais larga que a
     coluna de conteúdo disponível — sobrava só ~912px depois da sidebar,
     por isso a rolagem interna cortava a coluna "Item". 1440px cobre
     qualquer tela de notebook/desktop comum (a partir de 13") sem precisar
     dessa rolagem no caso comum; ela continua existindo como rede de
     segurança pra telas menores.  */
  max-width: 1440px;
  margin: 0 auto;
  padding: 28px 20px 64px;
  display: flex;
  flex-direction: column;
  gap: 22px;
}
h1, h2, h3 { font-family: "Manrope", system-ui, sans-serif; text-wrap: balance; margin: 0; }
.num { font-family: "IBM Plex Mono", ui-monospace, monospace; }
.tabular { font-variant-numeric: tabular-nums; }

header.top {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 16px;
  flex-wrap: wrap;
  border-bottom: 1px solid var(--border);
  padding-bottom: 18px;
}
header.top .eyebrow {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 6px;
}
header.top h1 { font-size: 26px; font-weight: 800; color: var(--ink); }
.brand { display: flex; align-items: center; gap: 12px; }
/* Só o símbolo (sem o texto "NEXO" da arte original) — o texto embutido na
   logo é branco vazado sobre fundo preto sólido, então some ao recortar o
   fundo pra transparente; o nome continua legível vindo do <h1> normal,
   que já muda de cor sozinho no tema escuro. */
.brand-mark { height: 34px; width: auto; flex: none; }

/* O cabeçalho grande (marca + título) só aparece na Visão geral — nas
   outras abas ele só repetia sem acrescentar nada, roubando espaço vertical
   (ver switchView em app.js). "Sair" vive fixo no rodapé do menu lateral
   (.nav-account), assim continua alcançável em qualquer aba; o seletor
   Ano/Mês (.master-period) mudou de lugar pro topo da própria aba Planilha,
   que é a única que o usa. */
.master-period { display: flex; gap: 12px; flex-wrap: wrap; }
.master-period select { min-width: 152px; }

/* source / file loader panel */
.source-panel {
  background: var(--surface);
  border: 1px dashed var(--border);
  border-radius: 12px;
  padding: 18px 20px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  box-shadow: var(--shadow);
}
.source-panel.dragover { border-color: var(--accent); background: var(--accent-soft); }
.source-panel .info { display: flex; flex-direction: column; gap: 3px; }
.source-panel .info .title { font-weight: 600; font-size: 14px; }
.source-panel .info .detail { font-size: 12.5px; color: var(--ink-mute); }
.source-panel .info .detail a { color: var(--accent); font-weight: 600; text-decoration: none; }
.source-panel .info .detail a:hover { text-decoration: underline; }
.btn {
  font: inherit;
  font-family: "IBM Plex Sans", sans-serif;
  font-weight: 600;
  font-size: 13.5px;
  color: var(--accent-ink);
  background: var(--accent);
  border: none;
  border-radius: 8px;
  padding: 10px 16px;
  cursor: pointer;
}
.btn:hover { filter: brightness(1.06); }
.btn.secondary {
  background: var(--surface-2);
  color: var(--ink);
  border: 1px solid var(--border);
}
.btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.status-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--ink-mute); flex: none; }
.status-dot.ready { background: var(--good); }
.status-dot.error { background: var(--critical); }
.empty-state { font-size: 13px; color: var(--ink-mute); }

/* Card mostrado nas abas Overview/Consultas/Metas antes de qualquer
   planilha ser carregada — mesmo texto/estilo do .card comum, só com o
   botão alinhado ao início em vez de esticado. */
.empty-state-card { align-items: flex-start; }
.empty-state-card .sub { margin-top: 0; }

/* KPI row */
.kpis { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; }
.kpi {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 16px 18px;
  box-shadow: var(--shadow);
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.kpi .label { font-size: 12.5px; color: var(--ink-mute); font-weight: 500; }
.kpi .value { font-size: 22px; font-weight: 600; color: var(--ink); }
.kpi.balanco .value.pos { color: var(--good); }
.kpi.balanco .value.neg { color: var(--critical); }
/* Comparação com o mês anterior embutida no próprio KPI, além da frase que
   já existe no card de insights logo abaixo (Fase 6 do roadmap de UX). */
.kpi-delta { font-size: 11.5px; font-weight: 600; }
.kpi-delta.pos { color: var(--good); }
.kpi-delta.neg { color: var(--critical); }

/* Contexto de período — antes não havia nada indicando "isto é o mês tal"
   (Fase 6 do roadmap de UX), e não dava pra navegar pra outro mês
   (retomado depois que a revisão externa de UX apontou isso logo na
   primeira rodada — item que tinha ficado só parcialmente feito). Existe
   em mais de uma página agora (Visão geral e Análises) — mesmo estado,
   mesmo componente, ids com prefixos diferentes (ov.../an...). */
.period-context { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-mute); margin: 0; }
.period-nav { position: relative; display: flex; align-items: center; gap: 10px; }
.period-nav-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; padding: 0;
  border: 1px solid var(--border); border-radius: 7px;
  background: var(--surface); color: var(--ink-soft);
  cursor: pointer; transition: background 0.12s, color 0.12s, border-color 0.12s;
}
.period-nav-btn svg { width: 15px; height: 15px; }
.period-nav-btn:hover:not(:disabled) {
  background: var(--accent-soft); color: var(--accent); border-color: var(--accent-line);
}
.period-nav-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.period-nav-btn:disabled { opacity: 0.35; cursor: default; }

/* O rótulo do período virou um botão (clicar abre o seletor direto de
   Ano/Mês) — clicar nas setinhas várias vezes pra voltar, digamos, a um
   mês de 2025 era lento demais (pedido do usuário depois de usar o
   seletor). Reseta a aparência nativa de <button> pra continuar parecendo
   o texto que já era. */
.period-context-btn {
  font: inherit; border: none; background: none; padding: 2px 4px; margin: 0 -4px;
  border-radius: 6px; cursor: pointer; transition: background 0.12s, color 0.12s;
}
.period-context-btn:hover { background: var(--surface-2); color: var(--ink-soft); }
.period-context-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

.period-picker {
  position: absolute; top: calc(100% + 8px); left: 0; z-index: 20;
  display: flex; gap: 12px; align-items: flex-end;
  background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
  padding: 14px; box-shadow: var(--shadow);
}
.period-picker .field { display: flex; flex-direction: column; gap: 4px; }
.period-picker label { font-size: 11px; color: var(--ink-mute); font-weight: 600; text-transform: uppercase; letter-spacing: 0.03em; }
.period-picker select {
  font: inherit; font-size: 13px; padding: 6px 8px; border-radius: 7px;
  border: 1px solid var(--border); background: var(--surface); color: var(--ink);
}
.period-picker-hoje {
  align-self: flex-end; font-size: 12px; font-weight: 600; color: var(--accent);
  background: none; border: none; cursor: pointer; padding: 6px 2px; white-space: nowrap;
}
.period-picker-hoje:hover { text-decoration: underline; }

/* Nota discreta indicando que parte de um total ainda não é dado
   realizado, e sim uma projeção pelo ritmo médio — usada no KPI, na
   Composição e no rodapé do Explorador. */
.estimate-note, .kpi-estimate-note {
  font-size: 11.5px;
  color: var(--ink-mute);
  font-style: italic;
}
.kpi-estimate-note { margin-top: -2px; }
.estimate-note { padding: 0 6px 4px; }

.grid { display: grid; grid-template-columns: 1.55fr 1fr; gap: 16px; align-items: stretch; }
.grid.grid-even { grid-template-columns: 1.2fr 1fr; }
@media (max-width: 880px) {
  /* .grid.grid-even precisa ser repetido aqui (não só ".grid") porque duas
     classes têm mais especificidade que uma — a regra de cima nunca seria
     sobrescrita só com ".grid", e os dois cards ficariam lado a lado,
     espremidos, até em telas de celular. */
  .grid, .grid.grid-even { grid-template-columns: 1fr; }
  .kpis { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 480px) {
  .kpis { grid-template-columns: 1fr; }
}

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 20px 22px 22px;
  box-shadow: var(--shadow);
  display: flex;
  flex-direction: column;
  gap: 14px;
  /* Um .card é item de flex (dentro de #dashboard ou de .grid/.metas-grid).
     Sem isso, o tamanho mínimo automático de flex/grid item respeita o
     conteúdo interno mais largo (ex.: a tabela do Comparativo, com
     min-width próprio) e o card recusa encolher — empurra a página inteira
     pra um scroll horizontal, mesmo o conteúdo tendo seu próprio
     overflow-x:auto. */
  min-width: 0;
}
/* Mesma lógica pros filhos diretos do .card: eles são flex items do card
   (flex-direction: column, então a largura é o eixo cruzado) e herdam o
   mesmo problema de min-width:auto sempre que carregam algo largo dentro
   (tabela do Comparativo, grade do Mapa de calor). */
.card > * { min-width: 0; }
.card h2 { font-size: 15.5px; font-weight: 700; }
.card .sub { font-size: 12.5px; color: var(--ink-mute); margin-top: -8px; }

/* Metas: grade própria (não mais espremida ao lado do Explorador) — até 3
   cards por linha, a 4ª meta (e as seguintes) quebram para a linha de
   baixo. align-items:stretch (padrão do grid) já iguala a altura dos
   cards dentro de uma mesma linha, sem precisar de flex/JS extra. */
.metas-grid { display: grid; grid-template-columns: repeat(3, minmax(0,1fr)); gap: 16px; }
.metas-grid > .card { justify-content: space-between; }
@media (max-width: 980px) { .metas-grid { grid-template-columns: repeat(2, minmax(0,1fr)); } }
@media (max-width: 640px) { .metas-grid { grid-template-columns: 1fr; } }

.filters { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.field { display: flex; flex-direction: column; gap: 4px; }
.field label { font-size: 11.5px; color: var(--ink-mute); font-weight: 600; letter-spacing: 0.02em; }
select {
  font: inherit;
  font-family: "IBM Plex Sans", sans-serif;
  font-size: 13.5px;
  color: var(--ink);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 7px;
  padding: 8px 30px 8px 11px;
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6'><path d='M0 0L5 6L10 0Z' fill='%23565f70'/></svg>");
  background-repeat: no-repeat;
  background-position: right 11px center;
  cursor: pointer;
  min-width: 170px;
}
select:focus-visible, button:focus-visible, .bar-hit:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Consulta por período: De/Até como calendário nativo de mês/ano (input
   type="month") — mesmo visual dos <select>, e o navegador já trava a
   escolha ao intervalo coberto pela planilha via min/max (ver
   buildQueryDateInputs em app.js). */
input[type="month"] {
  font: inherit;
  font-family: "IBM Plex Mono", monospace;
  font-size: 13px;
  color: var(--ink);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 7px;
  padding: 7px 11px;
  min-width: 150px;
}
input[type="month"]:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
input[type="month"]::-webkit-calendar-picker-indicator { cursor: pointer; opacity: 0.65; }
input[type="month"]::-webkit-calendar-picker-indicator:hover { opacity: 1; }

.chart-wrap { position: relative; min-height: 80px; }
svg.chart { width: 100%; height: auto; display: block; overflow: visible; }
.grid-line { stroke: var(--grid); stroke-width: 1; }
.axis-label { fill: var(--ink-mute); font-size: 10.5px; font-family: "IBM Plex Mono", monospace; }
.cat-label { fill: var(--ink-mute); font-size: 10.5px; font-family: "IBM Plex Sans", sans-serif; }
.bar { fill: var(--accent); transition: fill 0.12s ease, opacity .12s ease; }
.bar.hover { fill: var(--accent); filter: brightness(1.12); }
/* Mês ainda não realizado: mostra a estimativa (ritmo médio) em vez do
   valor (zerado) da planilha, com uma textura tracejada pra deixar claro
   que não é dado lançado. */
.bar.estimate { fill-opacity: 0.35; stroke: var(--accent); stroke-width: 1; stroke-dasharray: 3 2; }
.bar.estimate.hover { fill-opacity: 0.5; }
/* Explorador de despesas: mês com valor negativo (ex.: Balanço no vermelho)
   vira uma barra vermelha em vez da cor padrão — mais fácil de notar de
   relance. Só no Explorador (1 categoria por vez); no Comparativo entre
   anos a cor já identifica o ano, então não faria sentido sobrescrever. */
.bar.neg { fill: var(--critical); }
.bar.neg.hover { fill: var(--critical); filter: brightness(1.12); }
.bar.neg.estimate { stroke: var(--critical); }
.bar-hit { fill: transparent; cursor: pointer; }
.chart-foot {
  display: flex;
  justify-content: space-between;
  font-size: 12.5px;
  color: var(--ink-soft);
  padding-top: 2px;
  border-top: 1px solid var(--border);
}
.chart-foot b { color: var(--ink); font-weight: 600; }

/* Consulta por período: mesmo par De/Até, qualquer categoria e qualquer
   ano — 2 blocos de resultado lado a lado, ficha visual próxima ao KPI mas
   um tom mais discreta (fundo surface-2) por estar dentro de um .card. */
.query-result { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; }
.query-tile {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.query-label { font-size: 12.5px; color: var(--ink-mute); font-weight: 500; }
.query-value { font-size: 22px; font-weight: 600; color: var(--ink); }
@media (max-width: 640px) { .query-result { grid-template-columns: 1fr; } }

.tooltip {
  position: absolute;
  pointer-events: none;
  background: var(--ink);
  color: var(--ground);
  font-size: 12px;
  padding: 6px 10px;
  border-radius: 6px;
  transform: translate(-50%, -100%);
  white-space: nowrap;
  opacity: 0;
  transition: opacity 0.1s ease;
  z-index: 5;
  box-shadow: var(--shadow);
}
.tooltip .t-val { font-family: "IBM Plex Mono", monospace; font-weight: 600; font-size: 13px; }
.tooltip .t-lab { color: var(--ink-mute); font-size: 11px; }
.tooltip.show { opacity: 1; }
/* Usado quando não há espaço acima do ponto (ex.: primeira linha do mapa de
   calor) — a legenda aparece abaixo em vez de cortar no topo do card. */
.tooltip.tooltip-below { transform: translate(-50%, 8px); }

.progress-track {
  height: 22px;
  border-radius: 6px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  overflow: hidden;
  position: relative;
}
.progress-fill { height: 100%; background: var(--accent); border-radius: 6px 0 0 6px; }
.progress-nums { display: flex; justify-content: space-between; font-size: 12.5px; color: var(--ink-soft); }
.progress-nums b { color: var(--ink); font-weight: 600; }
/* Total histórico (sem o corte de "Início") — só referência, por isso mais
   discreto que a linha principal de Acumulado/Meta. */
.progress-nums.historico { font-size: 11.5px; color: var(--ink-mute); font-style: italic; margin-top: -6px; }
.progress-nums.historico b { color: var(--ink-soft); font-weight: 600; font-style: normal; }
.progress-pct { font-family: "IBM Plex Mono", monospace; font-size: 26px; font-weight: 600; color: var(--accent); }

.comp-track { height: 26px; border-radius: 6px; overflow: hidden; display: flex; border: 1px solid var(--border); }
.comp-seg-wrap { height: 100%; display: flex; }
.comp-seg { height: 100%; }
/* Parte estimada (ritmo médio) de uma fatia — mesma cor da categoria, só
   com uma textura por cima pra não parecer dado já realizado. */
.comp-seg.is-estimate {
  opacity: 0.45;
  background-image: repeating-linear-gradient(135deg, rgba(255,255,255,.5) 0 4px, transparent 4px 8px);
}
.comp-legend { display: flex; flex-direction: column; gap: 2px; font-size: 12.5px; }
.comp-group { border-radius: 6px; }
.comp-legend-row {
  all: unset;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  gap: 7px;
  width: 100%;
  padding: 6px 6px;
  border-radius: 6px;
  cursor: pointer;
  color: var(--ink-soft);
  font-family: "IBM Plex Sans", sans-serif;
  font-size: 12.5px;
}
.comp-legend-row:hover:not(:disabled) { background: var(--surface-2); }
.comp-legend-row:disabled { cursor: default; }
.comp-legend-row:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.comp-legend-row .swatch { width: 9px; height: 9px; border-radius: 2px; flex: none; }
.comp-legend-row .lab { flex: 1; text-align: left; }
.comp-legend-row b { color: var(--ink); font-weight: 600; font-family: "IBM Plex Mono", monospace; }
.comp-legend-row .caret { color: var(--ink-mute); font-size: 10px; width: 12px; text-align: center; flex: none; }
.comp-sub-list { display: flex; flex-direction: column; gap: 6px; padding: 6px 6px 12px 27px; }
.comp-sub-row { display: grid; grid-template-columns: 1fr 64px auto; align-items: center; gap: 8px; font-size: 11.5px; color: var(--ink-mute); }
.comp-sub-row .lab { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.comp-sub-row .bar-wrap { display: block; background: var(--surface-2); border-radius: 3px; height: 8px; overflow: hidden; }
.comp-sub-row .bar { display: block; height: 100%; background: var(--accent-line); border-radius: 3px; }
.comp-sub-row .val { color: var(--ink-soft); font-weight: 600; text-align: right; }

.alerts { display: flex; flex-direction: column; gap: 8px; }
.alert-row { display: flex; align-items: center; gap: 10px; padding: 9px 11px; border-radius: 8px; background: var(--surface-2); font-size: 13px; }
.pill { flex: none; font-size: 11px; font-weight: 700; letter-spacing: 0.02em; padding: 3px 9px; border-radius: 999px; }
.pill.ok { background: var(--good-soft); color: var(--good); }
.pill.warn { background: var(--warn-soft); color: var(--warn); }
.pill.info { background: var(--surface-2); color: var(--ink-mute); }
.alert-row .txt { color: var(--ink-soft); }

.note-box {
  font-size: 12.5px;
  color: var(--ink-soft);
  background: var(--surface-2);
  border-radius: 8px;
  padding: 10px 12px;
}

/* "Para onde direcionar a sobra" */
.sobra-value { font-family: "IBM Plex Mono", monospace; font-size: 28px; font-weight: 600; color: var(--accent); }
.sobra-breakdown {
  display: flex; justify-content: space-between; flex-wrap: wrap; gap: 6px 14px;
  font-size: 12.5px; color: var(--ink-soft);
  padding-bottom: 12px; margin-top: -4px;
  border-bottom: 1px solid var(--border);
}
.sobra-breakdown b { color: var(--ink); font-weight: 600; }
.sobra-tips p { font-size: 12.5px; color: var(--ink-soft); margin: 0 0 8px; }
.sobra-tips ol { margin: 0; padding-left: 20px; display: flex; flex-direction: column; gap: 8px; }
.sobra-tips li { font-size: 12.5px; color: var(--ink-soft); line-height: 1.45; }
.sobra-tips li b { color: var(--ink); font-weight: 600; }

/* Boas práticas gerais fica recolhido por padrão — é o bloco mais comprido
   do card "Planejamento do mês" e o mesmo texto genérico pra qualquer
   pessoa, então não precisa ocupar espaço permanente (Fase 5 do roadmap
   de UX: reduzir card denso demais / aninhado demais). <details> nativo,
   sem JS. */
.sobra-tips-details summary {
  cursor: pointer;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--accent);
  list-style: none;
  padding: 2px 0;
}
.sobra-tips-details summary::-webkit-details-marker { display: none; }
.sobra-tips-details summary::before { content: '▸ '; }
.sobra-tips-details[open] summary::before { content: '▾ '; }
.sobra-tips-details .sobra-tips { margin-top: 10px; }

/* Perfil de investidor — layout em pilha (rótulo em cima, barra embaixo)
   em vez da grade de .invest-row, porque os rótulos aqui são frases
   descritivas mais longas do que um nome de categoria de investimento e
   não cabem numa coluna de largura fixa sem cortar. */
.perfil-field { padding-top: 2px; }
.perfil-field select { width: 100%; }
.perfil-alloc { display: flex; flex-direction: column; gap: 12px; }
.perfil-desc { font-size: 12.5px; color: var(--ink-soft); margin: 0; line-height: 1.45; }
.perfil-row { display: flex; flex-direction: column; gap: 5px; }
.perfil-row-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 10px;
  font-size: 12.5px;
}
.perfil-row-label { color: var(--ink-soft); }
.perfil-row-nums { display: flex; gap: 10px; align-items: baseline; white-space: nowrap; flex-shrink: 0; }
.perfil-row-value { color: var(--ink); font-weight: 600; }
.perfil-row-pct { color: var(--ink-mute); min-width: 34px; text-align: right; }
.perfil-bar-wrap { background: var(--surface-2); border-radius: 4px; height: 8px; overflow: hidden; }
.perfil-bar { height: 100%; background: var(--accent); border-radius: 4px; }

/* Investimentos por categoria */
.invest-list { display: flex; flex-direction: column; gap: 8px; }
.invest-row {
  display: grid;
  grid-template-columns: 150px 1fr 84px 52px;
  align-items: center;
  gap: 10px;
  font-size: 12.5px;
}
.invest-label { color: var(--ink-soft); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.invest-bar-wrap { background: var(--surface-2); border-radius: 4px; height: 16px; overflow: hidden; }
.invest-bar { height: 100%; background: var(--accent); border-radius: 4px; }
.invest-bar.has-estimate {
  background-image: repeating-linear-gradient(135deg, rgba(255,255,255,.5) 0 4px, transparent 4px 8px);
  opacity: 0.7;
}
.invest-value { text-align: right; color: var(--ink); font-weight: 600; }
.invest-pct { text-align: right; color: var(--ink-mute); }
@media (max-width: 640px) {
  .invest-row { grid-template-columns: 90px 1fr 70px; }
  .invest-pct { display: none; }
}

/* ranking de gastos — hierarquia visual clara em 3 níveis:
   categoria maior (título + traço colorido) > régua vertical que "contém"
   > subcategoria (rótulo em caixa alta, tipo etiqueta) > item (linha com barra) */
.rank-list { display: flex; flex-direction: column; }
.rank-group { margin-top: 14px; }
.rank-group:first-child { margin-top: 0; }
.rank-group-header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 10px;
  font-weight: 700;
  font-size: 14.5px;
  color: var(--ink);
  background: var(--surface-2);
  border-left: 4px solid var(--accent);
  border-radius: 4px;
  padding: 8px 12px;
}
.rank-group-header .g-value { font-weight: 600; font-size: 12px; color: var(--ink-soft); flex: none; }
/* Detalhe progressivo: bloco fechado por padrão (só o total), clique
   revela as categorias; categoria fechada por padrão, clique revela os
   itens. .rank-caret é a mesma seta ▸/▾ do <details> de boas práticas. */
.rank-group-header, .rank-sub-header { cursor: pointer; }
.rank-group-header:hover, .rank-sub-header:hover { filter: brightness(0.98); }
.rank-caret { flex: none; color: var(--ink-mute); font-size: 11px; width: 12px; }
.rank-group-header .rank-caret::before { content: '▾'; }
.rank-group.collapsed .rank-group-header .rank-caret::before { content: '▸'; }
.rank-group.collapsed .rank-group-body { display: none; }
.rank-group-body {
  margin-left: 8px;
  padding-left: 14px;
  border-left: 2px solid var(--border);
}
.rank-sub:first-child .rank-sub-header { margin-top: 2px; }
.rank-sub-header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 10px;
  font-size: 13px;
  font-weight: 700;
  color: var(--ink);
  padding: 0 0 5px;
  margin-top: 12px;
  border-bottom: 1px solid var(--border);
}
.rank-sub-header .rank-caret::before { content: '▾'; }
.rank-sub.collapsed .rank-sub-header .rank-caret::before { content: '▸'; }
.rank-sub.collapsed .rank-sub-body { display: none; }
.rank-sub-header .num { font-weight: 600; font-size: 11.5px; color: var(--ink-mute); }
.rank-row {
  display: grid;
  grid-template-columns: 160px 1fr 90px 48px;
  align-items: center;
  gap: 10px;
  font-size: 13.5px;
  padding: 3px 0;
}
.rank-row.indented .rank-label { padding-left: 10px; }
.rank-label { color: var(--ink-soft); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rank-bar-wrap { background: var(--surface-2); border-radius: 4px; height: 16px; overflow: hidden; }
.rank-bar { height: 100%; background: var(--accent); border-radius: 4px; }
.rank-bar.other { background: var(--ink-mute); }
.rank-value { text-align: right; color: var(--ink); font-weight: 600; }
.rank-pct { text-align: right; color: var(--ink-mute); }
@media (max-width: 640px) {
  /* Nomes de itens (ex.: "DARF Unificado", "IPVA e Licenciamento") não cabem
     numa coluna estreita de 90px sem cortar com reticências — em vez de
     encolher a coluna, o rótulo passa pra sua própria linha (largura total,
     quebrando texto normalmente) e a barra + valor ficam juntos embaixo. */
  .rank-row {
    grid-template-columns: 1fr 70px;
    grid-template-areas: "label label" "bar value";
    row-gap: 4px;
  }
  .rank-row .rank-label {
    grid-area: label;
    overflow: visible;
    text-overflow: clip;
    white-space: normal;
  }
  .rank-row .rank-bar-wrap { grid-area: bar; }
  .rank-row .rank-value { grid-area: value; }
  .rank-group-body { margin-left: 4px; padding-left: 8px; }
  .rank-pct { display: none; }
}

/* Comparativo entre anos */
.compare-controls { display: flex; gap: 20px; flex-wrap: wrap; align-items: flex-end; }
.year-chips { display: flex; gap: 8px; flex-wrap: wrap; }
.year-chip {
  font: inherit;
  font-family: "IBM Plex Sans", sans-serif;
  font-size: 12.5px;
  font-weight: 600;
  padding: 7px 13px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--surface-2);
  color: var(--ink-soft);
  cursor: pointer;
}
.year-chip:hover { border-color: var(--accent-line); }
.year-chip.selected { background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent); }
.year-chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.compare-legend { display: flex; flex-wrap: wrap; gap: 14px; font-size: 12.5px; color: var(--ink-soft); padding-top: 2px; }
.compare-legend-item { display: flex; align-items: center; gap: 6px; }
.compare-legend-item .swatch { width: 9px; height: 9px; border-radius: 2px; flex: none; }
.compare-legend-item b { color: var(--ink); font-family: "IBM Plex Mono", monospace; font-weight: 600; }

.compare-table-wrap { overflow-x: auto; }
.compare-table { border-collapse: collapse; width: 100%; font-size: 13.5px; min-width: 460px; }
.compare-table th, .compare-table td { padding: 8px 12px; text-align: right; border-bottom: 1px solid var(--border); white-space: nowrap; }
.compare-table th:first-child, .compare-table td:first-child { text-align: left; white-space: normal; }
.compare-table thead th { color: var(--ink-mute); font-weight: 600; font-size: 11px; text-transform: uppercase; letter-spacing: 0.02em; }
.compare-table .metric-label { color: var(--ink-soft); font-weight: 600; }
.compare-table td { color: var(--ink); }
.compare-table td .cell-val { font-family: "IBM Plex Mono", monospace; font-weight: 600; }
.compare-table .delta { display: block; font-size: 11px; margin-top: 2px; font-weight: 600; }
.compare-table .delta.pos { color: var(--good); }
.compare-table .delta.neg { color: var(--critical); }
.compare-table .delta.neutral { color: var(--ink-mute); }

/* linha do tempo */
.tl-line.past { stroke: var(--accent); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.tl-line.future { stroke: var(--accent); stroke-width: 2; stroke-dasharray: 5 4; opacity: 0.5; stroke-linejoin: round; stroke-linecap: round; }
.tl-today-line { stroke: var(--ink-mute); stroke-width: 1; stroke-dasharray: 3 3; }
.tl-crosshair { stroke: var(--ink-mute); stroke-width: 1; }
.tl-dot { fill: var(--accent); stroke: var(--surface); stroke-width: 2; }
.tl-hit { cursor: crosshair; }

/* mapa de calor */
.heatmap-wrap { position: relative; overflow-x: auto; }
.heatmap-grid { display: grid; gap: 3px; min-width: 560px; }
.heat-head { font-size: 11px; color: var(--ink-mute); text-align: center; padding: 4px 0; font-weight: 600; }
.heat-year { text-align: right; padding-right: 8px; }
.heat-cell { height: 30px; border-radius: 4px; cursor: pointer; }
.heat-cell:focus-visible { outline: 2px solid var(--ink); outline-offset: 1px; }

footer {
  font-size: 12px;
  color: var(--ink-mute);
  border-top: 1px solid var(--border);
  padding-top: 16px;
  display: flex;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}

/* Navegação principal (Overview / Lançamentos) — sidebar escura fixa no
   desktop (visual de painel admin), vira uma faixa horizontal de abas no
   mobile. A cor da sidebar não muda com o tema claro/escuro do resto do
   painel — é a "casca" do app, sempre a mesma. */
.app-shell { display: flex; align-items: flex-start; gap: 20px; }
.app-nav {
  flex: none;
  width: 208px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  position: sticky;
  top: 20px;
  background: var(--nav-bg);
  border: 1px solid var(--nav-border);
  border-radius: 14px;
  padding: 10px;
  box-shadow: var(--shadow);
}
.nav-item {
  font: inherit;
  font-family: "IBM Plex Sans", sans-serif;
  font-size: 13.5px;
  font-weight: 600;
  text-align: left;
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--nav-ink);
  background: none;
  border: 0;
  border-left: 3px solid transparent;
  border-radius: 7px;
  padding: 10px 12px 10px 11px;
  cursor: pointer;
}
.nav-item .nav-ico { flex: none; width: 16px; height: 16px; opacity: 0.85; }
.nav-item:hover { background: var(--nav-bg-raised); color: var(--nav-ink-active); }
.nav-item.active {
  background: var(--nav-bg-raised);
  color: var(--nav-ink-active);
  border-left-color: var(--nav-accent);
}
.nav-item.active .nav-ico { opacity: 1; }
.nav-item:focus-visible { outline: 2px solid var(--nav-accent); outline-offset: 2px; }

/* "Configurações" agrupa Planilha / Importar extrato / Categorias / Buscar
   num submenu recolhível — telas que se abre pra ajustar ou alimentar
   dado, não pra acompanhar o dia a dia (Fase 8 do roadmap de UX). */
.nav-caret { margin-left: auto; flex: none; width: 14px; height: 14px; opacity: 0.7; transition: transform 0.15s; }
.nav-group-toggle[aria-expanded="true"] .nav-caret { transform: rotate(180deg); }
.nav-subgroup {
  display: none;
  flex-direction: column;
  gap: 2px;
  margin: 2px 0 4px 12px;
  padding-left: 8px;
  border-left: 2px solid var(--nav-border);
}
.nav-subgroup.open { display: flex; }
.nav-item.nav-sub { font-size: 12.5px; padding: 8px 11px; }
.nav-item.nav-sub .nav-ico { width: 14px; height: 14px; }
/* Rodapé fixo do menu — "Logado como X · Sair" fica sempre alcançável
   nele, em qualquer aba, agora que o cabeçalho grande só aparece na
   Visão geral (ver header.top acima). */
.nav-account {
  margin-top: 6px; padding: 10px 11px 2px; border-top: 1px solid var(--nav-border);
  display: flex; flex-direction: column; gap: 8px;
}
/* Menu de conta de verdade no rodapé do menu — avatar com inicial + e-mail
   numa linha, "Sair" como ação própria embaixo — em vez do texto corrido
   "Logado como X · Sair" de antes (Fase 6 do roadmap de UX). */
.account-chip { display: flex; align-items: center; gap: 8px; min-width: 0; }
.account-avatar {
  flex: none; width: 22px; height: 22px; border-radius: 50%;
  background: var(--nav-bg-raised); color: var(--nav-ink-active);
  display: flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 700;
}
.account-name {
  font-size: 11.5px; color: var(--nav-ink); opacity: 0.85;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}
.account-logout {
  align-self: flex-start; font-size: 11.5px; font-weight: 600;
  color: var(--nav-ink); opacity: 0.7; text-decoration: none;
  padding-left: 30px;
}
.account-logout:hover { opacity: 1; text-decoration: underline; }
.app-content { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 22px; }
.view { display: flex; flex-direction: column; gap: 22px; }

@media (max-width: 880px) {
  .app-shell { flex-direction: column; }
  .app-nav {
    width: 100%;
    flex-direction: row;
    flex-wrap: wrap;
    position: static;
    gap: 4px;
  }
  .nav-item { flex: 1 1 auto; justify-content: center; border-left: 0; border-bottom: 3px solid transparent; }
  .nav-item.active { border-bottom-color: var(--nav-accent); }
  .nav-group-toggle { justify-content: flex-start; }
  .nav-subgroup {
    flex-basis: 100%; flex-direction: row; flex-wrap: wrap; justify-content: center;
    margin: 0; padding-left: 0; border-left: 0;
  }
  .nav-item.nav-sub { flex: 1 1 auto; }
  .nav-account { flex-basis: 100%; align-items: center; border-top: 0; margin-top: 0; }
  .account-chip { justify-content: center; }
  .account-logout { align-self: center; padding-left: 0; }
}

.hidden { display: none !important; }

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; }
}

/* Lançamentos — form de criação/edição direto no banco (API), independente
   de ter planilha carregada — por isso o card fica fora de #dashboard. */
input[type="text"], input[type="number"], input[type="date"], input[type="password"] {
  font: inherit;
  font-family: "IBM Plex Sans", sans-serif;
  font-size: 13.5px;
  color: var(--ink);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 7px;
  padding: 7px 11px;
}
input[type="number"] { font-family: "IBM Plex Mono", monospace; }
input[type="text"]:focus-visible, input[type="number"]:focus-visible,
input[type="date"]:focus-visible, input[type="password"]:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px;
}

.lanc-form { display: flex; flex-wrap: wrap; gap: 12px 14px; align-items: flex-end; }
.lanc-form .field { flex: 1 1 130px; }
.lanc-form .field-obs, .lanc-field-obs { flex: 2 1 220px; }
.lanc-form input, .lanc-form select { width: 100%; }
.lanc-form-actions { display: flex; gap: 8px; flex: 1 1 100%; }

.lanc-list { display: flex; flex-direction: column; gap: 8px; max-height: 320px; overflow-y: auto; }
.lanc-item {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: 8px;
  padding: 9px 12px; font-size: 13px;
}
.lanc-item-main { display: flex; flex-direction: column; gap: 2px; flex: 1 1 200px; min-width: 0; }
.lanc-item-title { color: var(--ink); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lanc-item-sub { color: var(--ink-mute); font-size: 11.5px; }
.lanc-item-valor { font-family: "IBM Plex Mono", monospace; font-weight: 600; color: var(--ink); white-space: nowrap; }
.lanc-item-valor.receita { color: var(--good); }
.lanc-item-valor.despesa { color: var(--critical); }
.lanc-item-actions { display: flex; gap: 6px; flex: none; }
.lanc-item-actions button {
  font: inherit; font-family: "IBM Plex Sans", sans-serif; font-size: 12px; font-weight: 600;
  background: none; border: 1px solid var(--border); border-radius: 6px; padding: 4px 9px;
  color: var(--ink-soft); cursor: pointer;
}
.lanc-item-actions button:hover { background: var(--surface); color: var(--ink); }
.lanc-item-actions button.danger:hover { color: var(--critical); border-color: var(--critical); }

.lanc-msg { font-size: 12.5px; padding: 8px 12px; border-radius: 8px; }
.lanc-msg.ok { background: var(--good-soft); color: var(--good); }
.lanc-msg.error { background: var(--critical-soft); color: var(--critical); }

@media (max-width: 640px) {
  .lanc-form .field { flex-basis: 100%; }
}

/* Importar extrato — tela de revisão antes de gravar no banco. Cada linha
   é uma transação lida do arquivo (OFX por enquanto); os campos ficam
   editáveis porque a sugestão automática de categoria é um palpite, não
   uma certeza — nada é gravado sem passar por aqui. */
.extrato-resumo {
  display: flex; gap: 18px; flex-wrap: wrap; align-items: baseline;
  font-size: 12.5px; color: var(--ink-soft);
}
.extrato-resumo b { font-size: 15px; color: var(--ink); font-family: "IBM Plex Mono", monospace; }
.review-table-wrap { overflow-x: auto; border: 1px solid var(--border); border-radius: 10px; }
.review-table { border-collapse: collapse; width: 100%; font-size: 13.5px; min-width: 800px; }
.review-table th, .review-table td { padding: 7px 8px; border-bottom: 1px solid var(--border); vertical-align: middle; }
.review-table tbody tr:last-child td { border-bottom: 0; }
.review-table thead th {
  color: var(--ink-mute); font-weight: 600; font-size: 10.5px; text-transform: uppercase;
  letter-spacing: 0.03em; text-align: left; white-space: nowrap; background: var(--surface-2);
}
.review-table td.col-data { white-space: nowrap; font-family: "IBM Plex Mono", monospace; color: var(--ink-soft); }
.review-table td.col-desc { max-width: 220px; color: var(--ink-soft); font-size: 12px; }
.review-table td.col-valor { font-family: "IBM Plex Mono", monospace; white-space: nowrap; text-align: right; font-weight: 600; }
.review-table td.col-valor.receita { color: var(--good); }
.review-table td.col-valor.despesa { color: var(--critical); }
.review-table select, .review-table input[type="text"] {
  font: inherit; font-family: "IBM Plex Sans", sans-serif; font-size: 12px;
  padding: 5px 7px; width: 100%; min-width: 108px;
  color: var(--ink); background: var(--surface); border: 1px solid var(--border); border-radius: 6px;
}
.review-table input[type="checkbox"] { width: 16px; height: 16px; accent-color: var(--accent); cursor: pointer; }
.review-table tr.excluida { opacity: 0.4; }
.review-table tr.excluida select, .review-table tr.excluida input[type="text"] { pointer-events: none; }
.review-badge {
  display: inline-block; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.02em;
  padding: 2px 6px; border-radius: 999px; margin-left: 6px; vertical-align: middle;
}
.review-badge.sugerido { background: var(--accent-soft); color: var(--accent); }
