/**
 * design-system.css — FinançasPro Design Tokens v2.0
 * Fonte única de verdade para tokens visuais.
 * Todos os módulos CSS dependem exclusivamente deste arquivo.
 */

/* ============================================================
   DESIGN SYSTEM - FinançasPro
   ============================================================ */

/* Lucide Icons SVG Styling */
i[data-lucide] {
  display: inline-block;
  vertical-align: middle;
  width: 1em;
  height: 1em;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  fill: none;
}

/* Ícones em elementos com tamanho específico */
.saldo-emoji i[data-lucide],
.nav-emoji i[data-lucide],
.card-label i[data-lucide],
.auth-logo i[data-lucide],
.sidebar-logo i[data-lucide] {
  width: 1.25em;
  height: 1.25em;
}

/* Ícones em botões */
button i[data-lucide] {
  pointer-events: none;
}

/* Ícones em headings */
.secao-titulo i[data-lucide] {
  margin-right: 0.5em;
}

/* Ícones em labels de formulário */
label i[data-lucide] {
  margin-right: 0.5em;
}

/* Rotação de chevron-down em toggles expandidos */
.toggle-arrow.expanded i[data-lucide="chevron-down"],
.extras-arrow.expanded i[data-lucide="chevron-down"] {
  transform: rotate(180deg);
  transition: transform 0.3s ease;
}

.toggle-arrow i[data-lucide="chevron-down"],
.extras-arrow i[data-lucide="chevron-down"] {
  transition: transform 0.3s ease;
}

/* Contraste para ícones em fundos coloridos */
.card.receita i[data-lucide],
.card.despesa i[data-lucide],
.kpi-card.receita i[data-lucide],
.kpi-card.despesa i[data-lucide] {
  color: white;
}

.tipo-btn i[data-lucide] {
  color: inherit;
}

/* Tamanhos responsivos para ícones */
@media (max-width: 768px) {
  .saldo-emoji i[data-lucide],
  .nav-emoji i[data-lucide],
  .card-label i[data-lucide] {
    width: 1.1em;
    height: 1.1em;
  }
  
  .sidebar-logo i[data-lucide] {
    width: 1em;
    height: 1em;
  }
}

@media (max-width: 480px) {
  .saldo-emoji i[data-lucide],
  .nav-emoji i[data-lucide],
  .card-label i[data-lucide] {
    width: 1em;
    height: 1em;
  }
}

/* Tamanhos mínimos para telas de alta densidade */
i[data-lucide] {
  min-width: 16px;
  min-height: 16px;
}

@media (min-resolution: 2dppx) {
  i[data-lucide] {
    min-width: 20px;
    min-height: 20px;
  }
}

/* Animações de feedback para ícones */
@keyframes checkmark {
  0% { transform: scale(0); opacity: 0; }
  50% { transform: scale(1.2); }
  100% { transform: scale(1); opacity: 1; }
}

.sucesso i[data-lucide="check"] {
  animation: checkmark 0.3s ease;
}

/* Feedback visual em hover/focus de botões */
button:hover i[data-lucide],
button:focus i[data-lucide] {
  opacity: 0.8;
  transform: scale(1.1);
  transition: transform 0.2s ease, opacity 0.2s ease;
}

button i[data-lucide] {
  transition: transform 0.2s ease, opacity 0.2s ease;
}

:root {

  /* ── Paleta primária (verde FinançasPro) ────────────────────────────
     O verde foi redesenhado a partir da promessa da marca, não de uma
     referência de mercado. O tom antigo (#12694e) era da família de uma
     cooperativa de crédito: o oposto do posicionamento, que é justamente
     não parecer mais uma instituição financeira.
     500 = Verde Marca · 400 = Verde Vivo (acento) · 700 = Verde Profundo
     (fundo do ícone e das superfícies escuras).
     Todos os pares em uso passam AA — ver scripts/check-contrast.cjs. */
  --color-primary-50:  #edf6f2;
  --color-primary-100: #d3e9df;
  --color-primary-200: #a9d4c1;
  --color-primary-300: #74b99c;
  --color-primary-400: #2fa37b;  /* Verde Vivo — acento */
  --color-primary-500: #12694e;  /* Verde Marca — principal */
  --color-primary-600: #0f5741;
  --color-primary-700: #0b3d2e;  /* Verde Profundo — ícone e fundo escuro */
  --color-primary-800: #082c21;
  --color-primary-900: #051a14;

  /* ── Semântica ───────────────────────────────────────────── */
  /* Dessaturadas de propósito: dinheiro não é semáforo. O vermelho puro
     transforma todo mês normal em emergência, e num app cuja voz é calma isso
     contradiz o produto. Os tons -light servem ao tema escuro. */
  --color-success:       #2f9c6d;
  --color-success-light: #4fc79a;
  --color-success-dark:  #16613f;
  --color-success-bg:    rgba(47, 156, 109, 0.08);

  --color-danger:       #c9573a;
  --color-danger-light: #f08a6e;
  --color-danger-dark:  #8f3a26;
  --color-danger-bg:    rgba(201, 87, 58, 0.08);

  --color-warning:       #c98a1e;
  --color-warning-light: #e9b44c;
  --color-warning-dark:  #7d4f05;
  --color-warning-bg:    rgba(201, 138, 30, 0.08);

  --color-info:       #3c86a8;
  --color-info-light: #6fb2d2;
  --color-info-dark:  #235871;
  --color-info-bg:    rgba(60, 134, 168, 0.08);

  /* ── Semântica acessível (texto e botões) ────────────────────
     Os tons vivos acima (--color-success, --color-warning, ...) existem para
     PREENCHIMENTO: barra de progresso, ponto de legenda, fundo de toast. Eles
     reprovam no contraste WCAG AA quando usados como cor de texto ou sob texto
     branco — o warning chega a 2,15:1, contra o mínimo de 4,5:1.

     Use SEMPRE os tokens -on-light abaixo para texto e botões no tema claro.
     O tema escuro remapeia estes mesmos nomes para os tons -light, que passam
     sobre os fundos escuros (ver themes/dark-mode.css).

     Todos os valores são verificados por scripts/check-contrast.cjs no CI.
     ───────────────────────────────────────────────────────────── */
  --color-success-on-light: #1c7a4f;  /* 5,32:1 sobre branco · 5,06:1 sobre a página */
  --color-warning-on-light: #9a6206;  /* 5,09:1 sobre branco · 4,85:1 sobre a página */
  --color-danger-on-light:  #b4472e;  /* 5,41:1 sobre branco · 5,15:1 sobre a página */
  --color-info-on-light:    #2c6e8f;  /* 5,62:1 sobre branco · 5,35:1 sobre a página */

  /* Alias que alterna com o tema — é este que o CSS de componente deve usar. */
  --color-success-text: var(--color-success-on-light);
  --color-warning-text: var(--color-warning-on-light);
  --color-danger-text:  var(--color-danger-on-light);
  --color-info-text:    var(--color-info-on-light);

  /* A cor da MARCA usada como texto também precisa alternar. Faltava este
     alias, e por isso 135 regras escreviam `color: var(--color-primary-600)`
     — um verde escuro, correto sobre branco e ilegível sobre o card escuro:
     1,93:1 no valor de entradas do extrato. O axe não reprovou; quem encontrou
     foi uma varredura que compõe o fundo real de cada elemento (e2e/marca). */
  --color-primary-text: var(--color-primary-600);

  /* Superfícies que continuam CLARAS nos dois temas (chip de categoria, selo
     de contagem). Como o fundo não vira escuro, o texto também não pode virar
     claro — estes dois tokens ficam fixos de propósito. */
  --color-sobre-tinta-clara: var(--color-primary-700);
  --color-apoio-sobre-tinta-clara: #55665c;

  /* ── Neutros ─────────────────────────────────────────────────
     Uma família só, levemente quente. Os neutros anteriores eram o slate do
     Tailwind, que é azulado, e conviviam na mesma tela com texto de tom verde
     quente. A briga não é consciente, mas é o que fazia a interface parecer
     montada com peças de dois sistemas. */
  --color-white:     #ffffff;
  --color-gray-50:   #fbfcfb;
  --color-gray-100:  #f3f5f4;
  --color-gray-200:  #e5e9e7;
  --color-gray-300:  #cdd4d0;
  --color-gray-400:  #98a39d;
  --color-gray-500:  #6e7a74;
  --color-gray-600:  #55605a;
  --color-gray-700:  #3c4541;
  --color-gray-800:  #242a27;
  --color-gray-900:  #161a18;
  --color-black:     #000000;

  /* ── Backgrounds ─────────────────────────────────────────── */
  --color-bg-page:      #f7faf8;
  --color-bg-card:      #ffffff;
  --color-bg-primary:   rgba(18, 105, 78, 0.08);
  --color-bg-dark-page: #101613;
  --color-bg-dark-card: #19211d;
  --color-bg-dark-elevated: #212b26;

  /* ── Texto ───────────────────────────────────────────────── */
  --color-text-primary:   #121915;
  --color-text-secondary: #3f4f47;
  /* Escurecido de #5f7266 em 22/08/2026. O valor antigo passava sobre branco
     (5,1:1) e sobre o fundo da pagina (4,8:1) -- que era o que o
     check-contrast.cjs media -- mas falhava sobre as SUPERFICIES TINGIDAS onde o
     texto secundario tambem aparece: chips como .ext-tx-meta-tag
     (background: --color-bg-primary) e legendas sobre cards com tinta verde.
     Ali o axe media 4,21:1 e 4,25:1, abaixo do minimo AA de 4,5. Quem mede a
     pilha real de transparencias e o axe, no e2e/accessibility.spec.cjs; o
     check-contrast.cjs ganhou os pares tingidos para pelo menos parar de
     ignora-los em silencio. */
  --color-text-muted:     #55665c;  /* AA: 6,1:1 s/ branco · 5,4:1 s/ tinta · 5,8:1 s/ página */
  --color-text-inverse:   #ffffff;

  /* ── Borda ───────────────────────────────────────────────── */
  --color-border:       #dde5e1;
  --color-border-light: #eaf0ed;
  --color-border-focus: #12694e;
  /* Borda para impressão: no papel não há tema, e a borda esverdeada do app
     sai como um cinza sujo. Um neutro puro imprime previsível em qualquer
     impressora. Usado só dentro de @media print. */
  --color-border-print: #cccccc;

  /* ── Gradientes ──────────────────────────────────────────── */
  /* ── Gradientes: um só, e ele não mora aqui ───────────────────
     O produto tinha 103 gradientes. Isso não é ênfase, é textura — e é o
     traço estético que envelhece mais rápido, o que contradiz uma marca que
     promete permanência. Sobrou UM, escrito à mão na superfície do saldo
     (features/superficie.css), mais o brilho do esqueleto de carregamento, onde
     o gradiente É a animação.
     Os tokens abaixo viraram cor chapada porque componentes antigos ainda os
     citam pelo nome; nenhum deles produz gradiente. */
  --gradient-primary:     var(--color-primary-500);
  --gradient-primary-rev: var(--color-primary-500);
  --gradient-danger:      var(--color-danger-on-light);
  --gradient-warning:     var(--color-warning-on-light);
  --gradient-page:        var(--color-bg-page);

  /* ── Opacidades de overlay ───────────────────────────────── */
  --color-overlay-xs: rgba(18, 105, 78, 0.04);
  --color-overlay-sm: rgba(18, 105, 78, 0.08);
  --color-overlay-md: rgba(18, 105, 78, 0.15);
  --color-overlay-lg: rgba(18, 105, 78, 0.25);

  /* ── Espaçamento (base 4px / escala 2x) ─────────────────── */
  --space-0:  0px;
  --space-1:  4px;
  --space-2:  8px;
  --space-3:  12px;
  --space-4:  16px;
  --space-5:  20px;
  --space-6:  24px;
  --space-8:  32px;
  --space-10: 40px;
  --space-12: 48px;
  --space-16: 64px;

  /* ── Tipografia ──────────────────────────────────────────── */
  --font-family-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --font-family-mono: 'JetBrains Mono', 'Fira Code', monospace;

  /* ── Escala tipográfica ───────────────────────────────────────
     Nove degraus existiam desde sempre, mas o CSS usava trinta tamanhos
     literais além deles — 13,5px, 12,5px, 15px, 17px, 22px, 26px e mais rem
     soltos. Não é excesso de zelo tipográfico: é o que faz a interface parecer
     montada por várias mãos, e é também o motivo de a hierarquia ser resolvida
     no peso (600/700 em toda parte) em vez de no tamanho.

     Os três degraus de display abaixo cobrem o que a escala não alcançava: os
     números grandes de saldo e os ícones vazios, que antes usavam 44, 48 e
     64px avulsos. */
  --font-size-2xs: 10px;
  --font-size-xs:  12px;
  --font-size-sm:  14px;
  --font-size-base: 16px;
  --font-size-lg:  18px;
  --font-size-xl:  20px;
  --font-size-2xl: 24px;
  --font-size-3xl: 30px;
  --font-size-4xl: 36px;
  --font-size-display:   44px;
  --font-size-display-2: 56px;

  --font-weight-normal:   400;
  --font-weight-medium:   500;
  --font-weight-semibold: 600;
  --font-weight-bold:     700;
  --font-weight-extrabold: 800;

  --line-height-tight:   1.25;
  --line-height-normal:  1.5;
  --line-height-relaxed: 1.75;

  --letter-spacing-tight:  -0.5px;
  --letter-spacing-normal: 0;
  --letter-spacing-wide:   0.5px;
  --letter-spacing-wider:  0.8px;
  --letter-spacing-widest: 1px;

  /* ── Raio: três valores, e só ─────────────────────────────────
     A escala tinha sete degraus e o CSS usava doze valores literais — dois
     jeitos diferentes de dizer "totalmente redondo" (99px e 999px) e um 30px
     solitário. Ninguém nota conscientemente, mas é assim que uma interface
     perde a sensação de ter sido feita pela mesma mão.
       controle   — botão, campo, chip retangular, barra
       superfície — cartão, modal, folha
       pill       — chip redondo, avatar, indicador
     Os nomes antigos continuam como apelidos para não quebrar componente
     nenhum, mas todos caem num destes três. */
  --radius-controle:   8px;
  --radius-superficie: 16px;
  --radius-pill:       9999px;

  --radius-none: 0px;
  --radius-sm:   var(--radius-controle);
  --radius-md:   var(--radius-controle);
  --radius-lg:   var(--radius-superficie);
  --radius-xl:   var(--radius-superficie);
  --radius-2xl:  var(--radius-superficie);
  --radius-full: var(--radius-pill);

  /* ── Sombras ─────────────────────────────────────────────── */
  /* ── Elevação: três níveis, e só ──────────────────────────────
     Antes havia duas famílias concorrentes (--shadow-* e --shadow-*-premium)
     somando mais de dez sombras para o mesmo trabalho, e ninguém sabia qual
     usar num componente novo. Agora a pergunta tem resposta objetiva:
       nível 0 — está na página. Sem sombra: a borda define a superfície.
       nível 1 — flutua sobre o conteúdo (botão, menu, chip, cartão em hover).
       nível 2 — cobre o conteúdo (modal, gaveta, folha).
     Os nomes antigos continuam logo abaixo como apelidos, todos apontando
     para estes três, para não sobrar nenhuma definição órfã. */
  --elevacao-0: none;
  --elevacao-1: 0 1px 2px rgba(18, 25, 21, 0.05), 0 2px 8px rgba(18, 25, 21, 0.07);
  --elevacao-2: 0 2px 8px rgba(18, 25, 21, 0.08), 0 12px 32px rgba(18, 25, 21, 0.14);

  --shadow-xs: var(--elevacao-1);
  --shadow-sm: var(--elevacao-1);
  --shadow-md: var(--elevacao-1);
  --shadow-lg: var(--elevacao-2);
  --shadow-xl: var(--elevacao-2);
  /* Tint de marca: mesma geometria da escala, com a cor da marca. Existe só
     para o botão primário e o destrutivo, onde a sombra colorida separa o
     controle do fundo. Nunca em cartão. */
  --shadow-primary-sm: 0 1px 2px rgba(18, 105, 78, 0.10), 0 2px 8px rgba(18, 105, 78, 0.16);
  --shadow-primary:    var(--shadow-primary-sm);
  --shadow-primary-lg: 0 2px 8px rgba(18, 105, 78, 0.14), 0 12px 32px rgba(18, 105, 78, 0.22);
  --shadow-danger:     0 1px 2px rgba(201, 87, 58, 0.10), 0 2px 8px rgba(201, 87, 58, 0.18);
  --shadow-inset:      inset 0 2px 4px rgba(0, 0, 0, 0.06);

  /* ── Transições ──────────────────────────────────────────── */
  --transition-fast:   150ms ease;
  --transition-normal: 250ms ease;
  --transition-slow:   350ms ease;
  --transition-bounce: 250ms cubic-bezier(0.34, 1.56, 0.64, 1);
  --transition-smooth: 350ms cubic-bezier(0.4, 0, 0.2, 1);

  /* ── Z-Index (escala contínua) ───────────────────────────── */
  --z-base:           0;
  --z-raised:         10;
  --z-dropdown:       100;
  --z-nav:            150;
  --z-sticky:         200;
  --z-fixed:          300;
  --z-modal-backdrop: 400;
  --z-modal:          500;
  --z-popover:        600;
  --z-tooltip:        700;
  --z-toast:          800;
  --z-overlay:        900;
  --z-top:            1000;

  /* ── Glass / Surface tokens ─────────────────────────────── */
  --glass-light:      rgba(255, 255, 255, 0.82);
  --glass-medium:     rgba(255, 255, 255, 0.65);
  --glass-border:     rgba(255, 255, 255, 0.40);
  --glass-shadow:     0 8px 32px rgba(18, 25, 21, 0.08), inset 0 1px 0 rgba(255,255,255,0.6);

  /* ── Gradientes ──────────────────────────────────────────── */
  --gradient-green-hero:  var(--color-primary-600);
  --gradient-green-card:  var(--color-primary-50);
  --gradient-red-card:    var(--color-danger-bg);
  --gradient-surface:     var(--color-bg-card);

  /* ── Elevações semânticas ────────────────────────────────── */
  --elevation-0: none;
  --elevation-1: 0 1px 3px rgba(0,0,0,0.06), 0 1px 2px rgba(0,0,0,0.04);
  --elevation-2: 0 4px 12px rgba(0,0,0,0.07), 0 2px 4px rgba(0,0,0,0.04);
  --elevation-3: 0 10px 28px rgba(0,0,0,0.09), 0 4px 10px rgba(0,0,0,0.05);
  --elevation-4: 0 20px 48px rgba(0,0,0,0.12), 0 8px 16px rgba(0,0,0,0.06);

  /* ── Fase 4: Tipografia display ─────────────────────────── */
  --font-family-display: 'Plus Jakarta Sans', 'Inter', -apple-system, sans-serif;

  /* ── Curvas de aceleração ───────────────────────────────── */
  --ease-spring:      cubic-bezier(0.37, 0, 0.63, 1);
  --ease-overshoot:   cubic-bezier(0.34, 1.56, 0.64, 1);
  --ease-decelerate:  cubic-bezier(0.0, 0.0, 0.2, 1);
  --ease-accelerate:  cubic-bezier(0.4, 0.0, 1, 1);
  --ease-emphasized:  cubic-bezier(0.2, 0.0, 0.0, 1.0);
  --ease-expressive:  cubic-bezier(0.34, 1.40, 0.64, 1);

  /* ── Fase 4: Durações semânticas ────────────────────────── */
  --dur-instant:   80ms;
  --dur-fast:     150ms;
  --dur-moderate: 250ms;
  --dur-slow:     400ms;
  --dur-enter:    360ms;
  --dur-exit:     200ms;

  /* ── Apelidos da escala de elevação ──────────────────────────
     Estes nomes vieram da fase "premium" e descreviam aparência, não função —
     por isso duplicavam a escala acima. Ficam como apelidos até o último
     componente trocar de nome; nenhum define sombra própria. */
  --shadow-green-glow:   var(--elevacao-1);
  --shadow-superficie: var(--elevacao-0);
  --shadow-card-hover:   var(--elevacao-1);
  --shadow-float:        var(--elevacao-2);
  --shadow-btn-primary:  var(--elevacao-1);
  --shadow-btn-hover:    var(--elevacao-1);

  /* ── Aliases de compatibilidade (style.css legacy) ───────── */
  --primary:        var(--color-primary-500);
  --primary-dark:   var(--color-primary-600);
  --primary-light:  #2fa37b;
  --primary-bg:     var(--color-bg-primary);
  --success:        var(--color-success);
  --danger:         var(--color-danger);
  --warning:        var(--color-warning);
  --bg:             var(--color-bg-page);
  --bg-card:        var(--color-bg-card);
  --card-bg:        var(--color-bg-card);
  --border:         var(--color-border);
  --text:           var(--color-text-primary);
  --text-light:     var(--color-text-secondary);
  --text-muted:     var(--color-text-muted);
  --text-primary:   var(--color-text-primary);
  --text-secondary: var(--color-text-secondary);
  --radius:         var(--radius-lg);
}

/* ============================================================
   RESET MÍNIMO
   ============================================================ */

*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

/* ============================================================
   BOTÕES (Componente Base)
   ============================================================ */

/* --- Base --- */
.fp-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  font-family: var(--font-family-sans);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  line-height: var(--line-height-tight);
  text-decoration: none;
  border: none;
  border-radius: var(--radius-lg);
  cursor: pointer;
  transition: all var(--transition-fast);
  white-space: nowrap;
}

.fp-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* --- Variantes --- */

/* Primary */
.fp-btn--primary {
  background: var(--color-primary-500);
  color: var(--color-text-inverse);
  box-shadow: var(--shadow-primary);
}

.fp-btn--primary:hover:not(:disabled) {
  background: var(--color-primary-600);
  transform: translateY(-1px);
  box-shadow: 0 12px 32px rgba(18, 105, 78, 0.35);
}

.fp-btn--primary:active:not(:disabled) {
  transform: translateY(0);
}

/* Secondary */
.fp-btn--secondary {
  background: var(--color-gray-100);
  color: var(--color-gray-700);
}

.fp-btn--secondary:hover:not(:disabled) {
  background: var(--color-gray-200);
}

/* Outline */
.fp-btn--outline {
  background: transparent;
  color: var(--color-primary-text);
  border: 2px solid var(--color-primary-500);
}

.fp-btn--outline:hover:not(:disabled) {
  background: var(--color-primary-50);
}

/* Ghost */
.fp-btn--ghost {
  background: transparent;
  color: var(--color-gray-600);
}

.fp-btn--ghost:hover:not(:disabled) {
  background: var(--color-gray-100);
  color: var(--color-gray-900);
}

/* Danger */
.fp-btn--danger {
  background: var(--color-danger-on-light);
  color: var(--color-text-inverse);
}

.fp-btn--danger:hover:not(:disabled) {
  background: var(--color-danger-dark);
}

/* --- Tamanhos --- */
.fp-btn--sm {
  padding: var(--space-2) var(--space-3);
  font-size: var(--font-size-xs);
}

.fp-btn--lg {
  padding: var(--space-4) var(--space-6);
  font-size: var(--font-size-base);
}

/* --- Icon Button --- */
.fp-btn--icon {
  padding: var(--space-2);
  border-radius: var(--radius-md);
}

/* ============================================================
   CARDS (Componente Base)
   ============================================================ */

.fp-card {
  background: var(--color-bg-card);
  border-radius: var(--radius-xl);
  padding: var(--space-4);
  box-shadow: var(--shadow-sm);
  border: 1px solid var(--color-border-light);
}

.fp-card--hover:hover {
  box-shadow: var(--shadow-md);
  transform: translateY(-2px);
  transition: all var(--transition-fast);
}

.fp-card--padded-sm { padding: var(--space-3); }
.fp-card--padded-lg { padding: var(--space-6); }

/* ============================================================
   FORMULÁRIOS (Componentes Base)
   ============================================================ */

.fp-input {
  width: 100%;
  padding: var(--space-3) var(--space-4);
  font-family: var(--font-family-sans);
  font-size: var(--font-size-base);
  line-height: var(--line-height-normal);
  color: var(--color-text-primary);
  background: var(--color-bg-card);
  border: 2px solid var(--color-gray-200);
  border-radius: var(--radius-lg);
  transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}

.fp-input:focus {
  outline: none;
  border-color: var(--color-primary-500);
  box-shadow: 0 0 0 3px rgba(18, 105, 78, 0.1);
}

.fp-input::placeholder {
  color: var(--color-text-muted);
}

.fp-input:disabled {
  background: var(--color-gray-100);
  cursor: not-allowed;
}

.fp-label {
  display: block;
  margin-bottom: var(--space-2);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-secondary);
}

.fp-form-group {
  margin-bottom: var(--space-4);
}

.fp-form-group:last-child {
  margin-bottom: 0;
}

/* ============================================================
   TIPOGRAFIA UTILITÁRIA
   ============================================================ */

.fp-text-xs { font-size: var(--font-size-xs); }
.fp-text-sm { font-size: var(--font-size-sm); }
.fp-text-base { font-size: var(--font-size-base); }
.fp-text-lg { font-size: var(--font-size-lg); }
.fp-text-xl { font-size: var(--font-size-xl); }
.fp-text-2xl { font-size: var(--font-size-2xl); }
.fp-text-3xl { font-size: var(--font-size-3xl); }

.fp-font-normal { font-weight: var(--font-weight-normal); }
.fp-font-medium { font-weight: var(--font-weight-medium); }
.fp-font-semibold { font-weight: var(--font-weight-semibold); }
.fp-font-bold { font-weight: var(--font-weight-bold); }

.fp-text-primary { color: var(--color-text-primary); }
.fp-text-secondary { color: var(--color-text-secondary); }
.fp-text-muted { color: var(--color-text-muted); }
/* Utilitários de TEXTO usam os aliases acessíveis, nunca os tons vivos. */
.fp-text-success { color: var(--color-success-text); }
.fp-text-danger { color: var(--color-danger-text); }
.fp-text-warning { color: var(--color-warning-text); }
.fp-text-info { color: var(--color-info-text); }

/* ============================================================
   ESPAÇAMENTO UTILITÁRIO
   ============================================================ */

/* Padding */
.fp-p-0 { padding: var(--space-0); }
.fp-p-1 { padding: var(--space-1); }
.fp-p-2 { padding: var(--space-2); }
.fp-p-3 { padding: var(--space-3); }
.fp-p-4 { padding: var(--space-4); }
.fp-p-6 { padding: var(--space-6); }
.fp-p-8 { padding: var(--space-8); }

/* Margin */
.fp-m-0 { margin: var(--space-0); }
.fp-m-1 { margin: var(--space-1); }
.fp-m-2 { margin: var(--space-2); }
.fp-m-3 { margin: var(--space-3); }
.fp-m-4 { margin: var(--space-4); }
.fp-m-6 { margin: var(--space-6); }

/* ============================================================
   LAYOUT UTILITÁRIO
   ============================================================ */

.fp-flex { display: flex; }
.fp-flex-col { flex-direction: column; }
.fp-items-center { align-items: center; }
.fp-justify-center { justify-content: center; }
.fp-justify-between { justify-content: space-between; }
.fp-gap-2 { gap: var(--space-2); }
.fp-gap-4 { gap: var(--space-4); }

.fp-grid { display: grid; }
.fp-grid-cols-2 { grid-template-columns: repeat(2, 1fr); }
.fp-grid-cols-3 { grid-template-columns: repeat(3, 1fr); }
.fp-gap-4 { gap: var(--space-4); }

/* ============================================================
   DARK MODE — Tokens remapeados
   ============================================================ */

[data-theme="dark"] {
  /* Backgrounds */
  --color-bg-page:      var(--color-bg-dark-page);
  --color-bg-card:      var(--color-bg-dark-card);
  --color-bg-primary:   rgba(47, 163, 123, 0.14);

  /* Aliases legacy */
  --bg:     var(--color-bg-dark-page);
  --bg-card: var(--color-bg-dark-card);

  /* Texto */
  --color-primary-text:    var(--color-primary-300);

  /* Tintas claras viram tintas escuras: são superfície, não cor de marca. */
  --color-primary-50:  #16221d;
  --color-primary-100: #1e2f28;
  --color-primary-200: #2a4238;

  --color-text-primary:   #edf3f0;
  --color-text-secondary: #a6b5ad;
  --color-text-muted:     #96a79e;  /* AA: 6,5:1 sobre card escuro */
  --text:        #edf3f0;
  --text-light:  #a6b5ad;
  --text-muted:  #96a79e;

  /* Borda */
  --color-border:       #2c3833;
  --color-border-light: #212b26;
  --border: #2c3833;

  /* Neutros remapeados */
  --color-gray-100: #2c3833;
  --color-gray-200: #3c4541;

  /* Elevação no escuro: mesma geometria da escala clara, com mais opacidade
     porque sombra sobre fundo escuro precisa disso para existir. O que NÃO
     pode é redefinir --shadow-sm/md/lg com valores próprios: isso ressuscita
     a segunda família de sombras que a escala veio eliminar. */
  --elevacao-1: 0 1px 2px rgba(0, 0, 0, 0.28), 0 2px 8px rgba(0, 0, 0, 0.32);
  --elevacao-2: 0 2px 8px rgba(0, 0, 0, 0.34), 0 12px 32px rgba(0, 0, 0, 0.44);
}

[data-theme="dark"] .fp-card {
  border-color: var(--color-border);
  background: var(--color-bg-card);
}

[data-theme="dark"] .fp-input {
  background: var(--color-bg-dark-elevated);
  border-color: var(--color-border);
  color: var(--color-text-primary);
}

[data-theme="dark"] .fp-btn--secondary {
  background: var(--color-gray-700);
  color: var(--color-text-primary);
}

[data-theme="dark"] .fp-btn--ghost:hover {
  background: var(--color-gray-700);
}

/* ══════════════════════════════════════════════════════════════
   NÚMEROS TABULARES — em toda superfície monetária
   ══════════════════════════════════════════════════════════════
   Num app de finanças toda coluna de valores precisa de tabular-nums, senão
   os dígitos têm larguras diferentes, as vírgulas não alinham entre linhas e
   o extrato fica visualmente torto — mais difícil de comparar sem que o leitor
   saiba por quê. Estava aplicado só no painel (5 usos em dashboard.css);
   extrato, metas, orçamento e faturas ficavam de fora.

   A primeira versão desta regra cobria -valor, -saldo, -total e -montante, e
   a sonda de auditoria mostrou que isso deixava de fora metade do vocabulário
   real do projeto: kpi-value, orc-kpi-card-value, cp-kpi-val, sub-kpi-val e
   ext-grupo-subtotal continuavam com dígitos de largura variável. O erro foi
   escrever o seletor a partir do que eu imaginava que as classes se chamavam,
   em vez de ler a árvore renderizada.

   Agora a lista cobre val/value/total/kpi/preco além das anteriores — e há um
   teste e2e que varre o DOM real procurando texto no formato R$ 0,00 sem
   tabular-nums. É o teste, não o seletor, que garante a cobertura: nome de
   classe novo continua entrando sem avisar, mas passa a reprovar no CI.
   ══════════════════════════════════════════════════════════════ */
[class*="valor"],
[class*="valores"],
[class*="value"],
[class*="-val"],
[class*="saldo"],
[class*="total"],
[class*="montante"],
[class*="kpi"],
[class*="preco"],
[class$="-num"],
.num-financeiro,
.moeda,
td[data-numero],
time,
/* Dois casos onde o valor mora num elemento sem classe própria: o chip de
   lançamento rápido e o resumo do patrimônio. Ficam nomeados aqui em vez de
   ganharem classe nova, para o seletor continuar sendo a única fonte. */
.quick-chip strong,
.pat-hero-breakdown span {
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
}

/* Campo de digitação é a exceção: ali o alinhamento tabular atrapalha a
   leitura enquanto o usuário digita, porque o cursor "pula". */
input[class*="valor"],
input[class*="saldo"] {
  font-variant-numeric: normal;
  font-feature-settings: normal;
}

/* ══════════════════════════════════════════════════════════════
   BOTÃO HERDA A TIPOGRAFIA DO APP
   ══════════════════════════════════════════════════════════════
   Um <button> sem font-size cai no padrão do navegador — 13,333px, que não
   existe em escala nenhuma. Uma sonda no DOM renderizado encontrou nove deles
   (cp-cal-nav, perfil-card-*, periodo-nav, perfil-action-btn e os SVG dentro
   deles). Nenhum quebrava a tela, porque quase todos só contêm ícone; mas o
   dia em que alguém puser texto ali, ele nasce fora da escala.
   ══════════════════════════════════════════════════════════════ */
button, input, select, textarea {
  font-family: inherit;
  font-size: inherit;
  line-height: inherit;
}
