/* =============================================================
   SOPPHUS — sistema de design "Uma resposta por tela"
   MOBILE-FIRST: o padrão é o celular; min-width faz crescer.

   Regra de ouro: se um valor não está no bloco de tokens, ele
   não existe. 4 tamanhos de fonte (28/18/16/13), 2 pesos (400/600),
   escala de espaço 4/8/12/16/24/32, raio 14/18/999.
   Sombra é sinal reservado: só barra de resposta e modal/toast.
============================================================= */
:root {
  color-scheme: light;

  /* ---- CORES — A IDENTIDADE PRÓPRIA DO SOPPHUS ----
     Origem: docs/marca/identidade-visual-sopphus.png (arte oficial).
     Vinho #3A1A25 · rosa #F7ADB7 e #E58FA8 · dourado #D4AF37 · off-white #FFF1F4.

     Até 05-08-26 o app vestia a paleta da vitrine da Chocolateria Sophia
     (marrom #3D2817 + dourado #C5953D) — herança do ERP de origem. Era emprestada:
     o SOPPHUS é produto próprio e tem arte própria. Decisão do usuário em 05-08-26:
     usar as cores da logo, SEM forçar o marrom. O marrom saiu inteiro.

     A regra de rigor da paleta antiga CONTINUA valendo, e é o que impede o rosa de
     virar enfeite ilegível: cor que precisa ser LIDA tem contraste medido; cor de
     marca fica como SUPERFÍCIE. Todos os números abaixo são medidos, não estimados. */
  --vinho:        #3A1A25;   /* a cor da marca que também é o preto do app */
  --vinho-2:      #2A1219;
  --rosa:         #E58FA8;   /* MARCA — superfície, botão primário, ativo */
  --rosa-claro:   #F7ADB7;   /* MARCA — realce claro */
  --rosa-fundo:   #FBE9EE;   /* tint: quadradinho de ícone (1,17:1 vs cartão) */
  --rosa-texto:   #A8305F;   /* o rosa quando precisa ser LIDO (6,46:1) */
  --dourado:      #D4AF37;   /* MARCA — superfície e detalhe, nunca texto (2,10:1) */
  --dourado-fundo:#F8F0DA;   /* tint (1,14:1 vs cartão) */
  --dourado-texto:#8A631D;   /* o dourado quando precisa ser LIDO (5,41:1) */
  --offwhite:     #FFF1F4;

  --primary:       var(--rosa);
  --primary-light: var(--rosa-claro);
  --secondary:     var(--vinho);
  --accent:        var(--dourado);
  --accent-light:  var(--dourado-fundo);

  /* Fundo "papel rosado": #FDF6F8 tem croma OKLab 0,008 — o rosado da marca se
     percebe como temperatura, não como cor chapada (o #FFF1F4 puro da arte, croma
     0,016, vira rosa-chiclete numa tela inteira de celular). O branco fica onde o
     olho lê: cartão, topo, barra e campos. */
  /* ---- QUATRO NÍVEIS DE SUPERFÍCIE (05-08-26) ----
     A interface estava chapada: fundo #FDF6F8 e cartão #FFFFFF davam 1,065 de
     separação — o cartão praticamente desaparecia no fundo, e como TODO cartão
     tinha o mesmo tratamento, nada indicava o que era mais importante.

     Agora há uma escada, e ela é o que cria hierarquia sem cor nova:
       --bg           página, o nível mais fundo
       --superficie   agrupamento (métricas, atalhos) — junta o que é do mesmo assunto
       --card         conteúdo
       --card + borda-forte + sombra elevada = o que MERECE atenção

     Os valores mantêm o matiz rosado da marca, e ainda assim separam MAIS que
     o cinza neutro sugerido: 1,145 de fundo para cartão contra 1,081 do
     #F5F6F8. Croma OKLab 0,007 — é temperatura, não cor. */
  --bg:            #F4EEF0;    /* L* 95,4 · --text 13,54:1 */
  --superficie:    #FAF5F7;    /* L* 97,5 · agrupamento */
  --card:          #FFFFFF;
  /* A borda voltou a ter presença (1,32 contra 1,16). Na revisão anterior ela
     foi enfraquecida porque TODO cartão tinha borda E sombra — redundância.
     Com os níveis de superfície o papel dela mudou: agora ela é o que define o
     cartão, e a sombra fica só para o que se destaca. */
  --border:        #E8DDE2;    /* 1,32:1 vs cartão */
  --card-border:   #E8DDE2;
  --border-forte:  #DCCBD3;    /* 1,55:1 — cartão importante */
  /* recesso DENTRO do cartão (campo, trilho, :active, DRE destaque) */
  --superficie-2:  #F9F0F3;    /* 1,12:1 vs cartão */
  /* fundo de alerta: vermelho a 8% sobre o cartão. O --danger escrito nele
     ainda dá 5,75:1, então a tarja NÃO custa legibilidade. */
  --fundo-perigo:  #F9EEED;

  /* ---- TRÊS NÍVEIS DE TEXTO ----
     A hierarquia passa a ser feita por CONTRASTE, e não por peso. Antes quase
     tudo que precisava se destacar virava 600; agora o texto secundário desce
     de tom em vez de o principal engordar. Isso é o que deixa a página leve
     sem perder a leitura.
       --text        títulos, valores, o que se lê primeiro
       --text-light  rótulos, apoio, metadados — o corpo secundário
       --text-suave  SÓ elemento gráfico (chevron, ícone decorativo, trilho),
                     onde o mínimo é 3:1 — nunca texto corrido */
  --text:          #3A1A25;    /* 15,51:1 no cartão */
  --text-light:    #6B5560;    /*  6,79:1 — subiu de #7A5F6A (5,72) porque
                                  agora ele carrega texto que era 600 preto */
  --text-suave:    #8A7480;    /*  4,29:1 — abaixo de 4,5 DE PROPÓSITO: não é
                                  para texto, é para traço e ícone (mín. 3) */

  /* Cor da ÁREA ativa: o roteador escreve data-area no <html> e o shell.css troca
     este token — título do topo, ícone, foco e campo em foco falam a cor da aba.
     Padrão (cadastros, telas avulsas): o rosa lido da marca. */
  --cor-area:      var(--rosa-texto);
  /* tint da área, para o quadradinho do ícone acompanhar a aba */
  --cor-area-fundo: var(--rosa-fundo);

  /* superfície escura — usada em faixa e realce; a sidebar clara não a usa mais */
  --sidebar:       var(--card);
  --sidebar-hover: var(--superficie-2);
  --sidebar-text:  var(--text);
  /* Texto que vai SOBRE superfície escura (faixa do admin, --gradient).
     Existe com nome próprio porque --sidebar-text mudou de sentido quando a
     sidebar virou clara: quem escrevia sobre o escuro precisava de um token que
     não acompanhasse essa virada. É o off-white da marca — 14,13:1 sobre o vinho
     e 10,04:1 sobre a ponta clara do gradiente. É o MESMO nos dois temas. */
  --texto-sobre-escuro: #FFF1F4;
  /* 88% e não os 72% de antes: sobre o trecho MAIS CLARO do gradiente da tela de
     entrada (#A8305F) o texto a 72% caía para 3,80:1 e reprovava. O mínimo
     medido para passar ali é 83%; 88% dá ~4,9:1 e deixa margem. Sobre a faixa do
     admin, que é mais escura, isso só melhora. */
  --apoio-sobre-escuro: rgba(255, 241, 244, 0.88);
  /* semânticos: só em selo e alerta, nunca em área grande.
     Medidos sobre o fundo rosado: 6,69 · 6,43 · 6,14:1 */
  --success:    #166534;
  --warning:    #854D0E;
  --danger:     #B3261E;
  --info:       var(--rosa-texto);
  --gradient:   linear-gradient(135deg, #3A1A25 0%, #5A2A38 100%);
  /* paleta de dados (gráficos, nesta ordem) — o rosa e o dourado da marca
     entram na frente; azul e verde ficam para separar sob daltonismo */
  --dado-1: #E58FA8;
  --dado-2: #D4AF37;
  --dado-3: #2a78d6;
  --dado-4: #1baf7a;
  --dado-5: #9B59B6;
  --dado-1-texto: #A8305F;   /* o --dado-1 legível em 13px */

  /* ---- CORES POR ÁREA — reconhecimento, NUNCA único sinal ----
     As duas primeiras SÃO as cores da marca levadas a texto; as duas últimas
     existem para garantir separação sob daltonismo (rosa e dourado sozinhos
     colapsam em protanopia). Contrastes medidos sobre #FFFFFF:
       Início     #A8305F  6,46:1   ← o rosa da marca; a "casa" veste a marca
       Precificar #8A631D  5,41:1   ← o dourado da marca
       Financeiro #046049  7,57:1   ← o verde do dinheiro
       Relatórios #1E40AF  8,72:1
     Separação ΔE OKLab entre TODOS os pares: mínima 19,6 (o piso do sistema é 8).
     Distância do vermelho de erro --danger: mínima 8,3 (Início) — passa, e é o
     motivo de erro nunca ser dito só por cor: sempre ícone + palavra junto. */
  --aba-inicio:      #A8305F;
  --aba-precificar:  #8A631D;
  --aba-financeiro:  #046049;
  --aba-relatorios:  #1E40AF;
  /* A QUINTA, para Cadastros virar destino de barra (05-08-26). Escolhida por
     busca sobre 12 candidatos, com simulação de protanopia, deuteranopia e
     tritanopia: #0E7490 dá 5,36:1 no branco e separação mínima 10,3 contra as
     outras quatro E contra o vermelho de erro — folgado, e maior do que a que as
     quatro já têm entre si (2,7, entre financeiro e relatórios sob tritanopia).
     Roxos e violetas foram todos reprovados: colapsam no azul de Relatórios. */
  --aba-cadastros:   #0E7490;
  /* O ativo não muda de matiz: só ganha peso e barrinha. Trocar a cor ao ativar
     faria a barra "piscar" de cor a cada navegação. */
  --aba-inicio-ativa: var(--aba-inicio);
  /* tint de cada área — fundo do quadradinho do ícone. Contraste do ÍCONE
     dentro do próprio tint: 5,53 · 4,76 · 6,41 · 7,06:1 (mínimo de traço é 3). */
  --aba-inicio-fundo:      #FBE9EE;
  --aba-precificar-fundo:  #F8F0DA;
  --aba-financeiro-fundo:  #DFF0EA;
  --aba-relatorios-fundo:  #E2E7F6;
  --aba-cadastros-fundo:   #DCEDF2;
  /* Versões claras das mesmas famílias, para quando a área aparece sobre
     superfície ESCURA (tema escuro e faixas em vinho). Medidas sobre #33161F: */
  --aba-inicio-clara:      #F7ADB7;   /* rosa claro     ·  9,11:1 */
  --aba-precificar-clara:  #D4AF37;   /* dourado        ·  7,83:1 */
  --aba-financeiro-clara:  #6EE7B7;   /* verde claro    · 10,80:1 */
  --aba-relatorios-clara:  #93C5FD;   /* azul claro     ·  9,13:1 */
  --aba-cadastros-clara:   #7DD3E8;   /* petróleo claro ·  9,4:1 */

  /* ---- TIPOGRAFIA ----
     Pilha "arredondada" honesta: iOS/macOS-Safari → SF Pro Rounded (de fato);
     Android → Roboto (neutra-macia); Win11 → Segoe UI Variable Text (o teto
     do Windows, humanista); Win10 → Segoe UI. `ui-rounded` sem aspas é
     custom-ident válido: navegador que não conhece só pula a entrada.
     PESO 500 É VETADO: a Segoe estática do Win10 não o tem e o casamento
     CSS desce a 400, apagando a hierarquia — 600 fica. */
  --fonte: ui-rounded, 'SF Pro Rounded', 'SF Compact Rounded',
           'Segoe UI Variable Text', 'Segoe UI', Roboto, Ubuntu,
           system-ui, -apple-system, sans-serif;
  /* ---- FONTE DOS VALORES (05-08-26, escolha do usuário: estilo fintech) ----
     Os números de dinheiro passam a usar a MONO do sistema, como Stripe faz nos
     painéis. Ganhos concretos, não só estética: dígito de largura fixa nunca
     "dança" quando o valor muda, e o desenho reto separa o número do texto
     arredondado em volta.

     Pilha só com fontes JÁ INSTALADAS — o projeto não carrega fonte externa, e
     não vai passar a carregar por isto. `ui-monospace` pega a mono nativa do
     sistema onde existir; as demais são os nomes reais em cada plataforma.

     Como mono tem métrica própria, ela vem com dois ajustes obrigatórios:
     `font-variant-numeric` deixa de importar (mono já é tabular por definição)
     e o tracking encolhe um pouco, porque mono nasce mais espaçada. */
  --fonte-numero: ui-monospace, 'SF Mono', SFMono-Regular, Menlo,
                  'Cascadia Mono', 'Segoe UI Mono', Consolas,
                  'Roboto Mono', 'Ubuntu Mono', monospace;
  --track-numero: -0.02em;   /* compensa o avanço natural da mono */

  --tam-resposta: 28px;   /* A Resposta e valor-herói */
  --tam-titulo:   18px;   /* título de área, pergunta de seção */
  --tam-corpo:    16px;   /* corpo, botão, item de lista, CAMPO (regra iOS) */
  --tam-apoio:    13px;   /* rótulo, legenda, data, derivação da conta */
  --peso-normal: 400;
  --peso-forte:  600;
  /* entrelinha: apoio 13px fecha em 20px, título 18px fecha em 24px;
     corpo mantém 1,5 (24px) e herói 1,2 (bloco único) */
  --ent-apoio:  1.538;    /* 13px × 1,538 ≈ 20px */
  --ent-titulo: 1.334;    /* 18px × 1,334 ≈ 24px */
  /* tracking: positivo leve no apoio, 0 no corpo/título, herói destensionado */
  --track-apoio: 0.01em;
  --track-heroi: -0.015em;  /* era −0,02em */

  /* ---- ESPAÇAMENTO (escala fechada) ---- */
  --esp-1: 4px;  --esp-2: 8px;  --esp-3: 12px;
  --esp-4: 16px; --esp-5: 24px; --esp-6: 32px;

  /* ---- FORMA ----
     Raio subiu de 14 para 18px em 05-08-26: com cartão de 120px+ o canto de 14
     lê como "caixa de formulário"; 18 lê como cartão. O quadradinho do ícone
     ganhou raio próprio (12px) — ele é pequeno, e 18 nele viraria bolha. */
  --raio:        18px;   /* cartão, seção, modal */
  --raio-medio:  14px;   /* campo, botão, item de lista */
  --raio-pequeno:12px;   /* quadradinho de ícone, selo quadrado */
  --raio-folha:  22px;   /* modal */
  --raio-pilula: 999px;  /* pílula, selo, segmentado */
  --fio:       1px solid var(--border);
  --fio-total: 2px solid var(--text);   /* SÓ na linha de total */
  /* compat: shell.js usa var(--radius) em estilo inline — manter o alias */
  --radius: var(--raio);

  /* ---- SOMBRA ----
     Tingida com o VINHO da marca (rgba(58,26,37,…)), nunca preto puro: sombra
     cinza sobre fundo rosado suja; tingida, assenta.

     Mudança de 05-08-26: o cartão em repouso passou a ter uma sombra mínima.
     Antes a regra era "sombra só no que flutua" e o relevo vinha só da borda —
     correto, e era parte do ar chapado que o usuário apontou. A hierarquia
     continua intacta porque as três faixas estão bem separadas: cartão 0.04,
     flutuante 0.10, modal 0.16. */
  --sombra-cartao:   0 1px 2px rgba(58, 26, 37, 0.04), 0 6px 20px rgba(58, 26, 37, 0.04);
  --sombra-elevada:  0 2px 4px rgba(58, 26, 37, 0.05), 0 12px 28px rgba(58, 26, 37, 0.07);
  --sombra-resposta: 0 -6px 24px rgba(58, 26, 37, 0.08);  /* barra de resposta */
  --sombra-modal:    0 8px 40px rgba(58, 26, 37, 0.16);   /* modal e toast */

  /* ---- QUEM SEPARA: sombra ou borda? Um dos dois, nunca os dois ----
     Revisão de 05-08-26. Cada cartão tinha borda de 1,31:1 E sombra ao mesmo
     tempo — a mesma separação desenhada duas vezes, e boa parte do peso que a
     interface carregava. Agora é um por tema, que é o que Linear e Stripe fazem:
       claro   → a SOMBRA dá a elevação; a borda fica ultrassutil (1,16) só para
                 segurar a forma em tela sem suporte a sombra colorida
       escuro  → sombra não existe sobre fundo escuro; quem separa é a BORDA
     `--fio-cartao` é o que os componentes usam; `--fio` continua para divisores
     internos (linha entre registros, topo de seção), que são outra coisa. */
  --fio-cartao: 1px solid var(--border);

  /* ---- ALTURAS ---- */
  --alvo-toque:      44px;
  --altura-controle: 52px;
  --topo-h: 56px;
  /* 64px, e este número NÃO é escolhido: é a altura que a barra realmente tem.
     Ficou em 62 por muito tempo enquanto o conteúdo do item media 63px (pílula
     de 28 + gap 3 + rótulo 16 + 16 de padding) mais 1px de borda = 64.
     Os 2px de diferença apareciam como uma FRESTA no rodapé, por onde o
     conteúdo rolando ficava visível — foi o que o usuário viu e reportou duas
     vezes. Quem usa este token para reservar espaço confia que ele é a altura
     real; se o conteúdo do item mudar, este valor tem de mudar junto. */
  --nav-h:  64px;
  /* barra de resposta do Precificar (frase + conta fechada) */
  --barra-h: 76px;
  --barra-colapsada: 48px;

  /* ---- MOVIMENTO ----
     Revisado em 05-08-26 contra as regras de animação de Emil Kowalski
     (github.com/emilkowalski/skills). As durações já passavam; as CURVAS não.

     `ease-out` nativo do CSS é fraco — ele desacelera pouco no fim, e é
     justamente o fim que o olho acompanha. Curvas próprias abaixo, cada uma
     com um trabalho:

     NUNCA `ease-in` em UI: começar devagar faz a interface parecer que
     demorou a responder, mesmo com a mesma duração total. */
  --dur-curta: 160ms;   /* press de botão, hover (faixa 100–160) */
  --dur-media: 200ms;   /* dropdown, popover (faixa 150–250) */
  --dur-longa: 260ms;   /* modal, folha (faixa 200–500, mas o teto de UI é 300) */

  --curva:       cubic-bezier(0.23, 1, 0.32, 1);        /* entrada e feedback */
  --curva-cor:   cubic-bezier(0.25, 0.46, 0.45, 0.94);  /* hover e mudança de cor */
  --curva-morph: cubic-bezier(0.77, 0, 0.175, 1);       /* movimento na tela */
}

/* =============================================================
   TEMA ESCURO — onde a marca finalmente respira

   A arte oficial do SOPPHUS é escura: fundo vinho com rosa e dourado. No claro
   as cores da marca precisam ser escurecidas para poderem ser lidas; aqui elas
   entram PURAS e passam com folga — rosa #E58FA8 = 6,92:1 e dourado #D4AF37 =
   7,83:1 sobre o cartão. Não é o tema claro invertido: é a identidade original.

   UM BLOCO SÓ, ativado por [data-tema="escuro"]. Quem resolve a preferência do
   sistema é o JS no boot (matchMedia), num script inline antes da primeira
   pintura — assim o CSS não precisa repetir 40 tokens dentro de um @media, e
   não existe o risco clássico de os dois blocos saírem de sincronia. Sem JS o
   app não tem tela nenhuma (tudo é renderizado por ele), então cair no tema
   claro nesse caso não é perda.

   Todos os contrastes abaixo medidos sobre o cartão #33161F. */
:root[data-tema="escuro"] {
  color-scheme: dark;

  /* ---- ESCALA DE SUPERFÍCIES, revista em 05-08-26 ----
     A escala antiga tinha croma OKLab 0,035 a 0,057: vinho chapado, que num
     app inteiro lê como pesado e um pouco datado. A nova fica em 0,019 a 0,023
     — 45% menos saturada, mesmo matiz. A identidade não muda; o que sai é o
     excesso de tinta.

     Os degraus também encolheram (1,08 · 1,09 · 1,13 contra 1,10 · 1,11 · 1,20):
     superfícies vizinhas quase se tocando é o que dá o ar de profundidade
     contínua em vez de camadas empilhadas. */
  /* Mesma escada de quatro níveis do tema claro, na direção oposta: aqui
     "mais importante" é mais CLARO, porque a luz é que destaca no escuro. */
  --bg:            #160E13;   /* página, o mais fundo */
  --superficie:    #1C1218;   /* agrupamento */
  --card:          #241A20;   /* conteúdo */
  --superficie-2:  #2C2128;   /* recesso dentro do cartão */
  --border:        #3D2F36;   /* 1,32:1 sobre o cartão */
  --card-border:   #3D2F36;
  --border-forte:  #514049;   /* cartão importante */
  --fundo-perigo:  #33191C;   /* tarja de alerta, vermelho sobre o cartão */
  --text:          #FFF1F4;   /* o off-white da marca · 15,39:1 */
  --text-light:    #C4B2B9;   /*  8,38:1 */
  --text-suave:    #9C8A92;   /*  5,20:1 — traço e ícone */

  /* As cores da marca, PURAS (é o ganho do tema escuro) */
  --rosa-texto:    #F7ADB7;   /*  9,11:1 — no escuro o rosa lido é o CLARO */
  --dourado-texto: #D4AF37;   /*  7,83:1 — o dourado da arte, sem escurecer */
  --rosa-fundo:    #4A2531;   /* tint do quadradinho · rosa nele 5,3:1 */
  --dourado-fundo: #44291F;

  --cor-area:       var(--rosa-texto);
  --cor-area-fundo: var(--rosa-fundo);

  --sidebar:       var(--card);
  --sidebar-hover: var(--superficie-2);
  --sidebar-text:  var(--text);

  /* Semânticos: os escuros do tema claro dão 2,7–3,3:1 aqui e reprovam.
     Cada um sobe para a versão clara da mesma família. */
  --success:  #4ADE80;   /*  9,45:1 */
  --warning:  #FCD34D;   /* 11,42:1 */
  --danger:   #FCA5A5;   /*  8,68:1 */
  --info:     var(--rosa-texto);
  --gradient: linear-gradient(135deg, #241017 0%, #43202C 100%);

  /* Áreas: as mesmas quatro famílias, na versão clara já medida */
  --aba-inicio:      var(--aba-inicio-clara);       /*  9,11:1 */
  --aba-precificar:  var(--aba-precificar-clara);   /*  7,83:1 */
  --aba-financeiro:  var(--aba-financeiro-clara);   /* 10,80:1 */
  --aba-relatorios:  var(--aba-relatorios-clara);   /*  9,13:1 */
  --aba-cadastros:   var(--aba-cadastros-clara);    /*   9,4:1 */
  --aba-inicio-ativa: var(--aba-inicio);
  /* tints: o próprio cartão puxado na direção da cor da área */
  --aba-inicio-fundo:      #4A2531;
  --aba-precificar-fundo:  #44291F;
  --aba-financeiro-fundo:  #1E3830;
  --aba-relatorios-fundo:  #26304A;
  --aba-cadastros-fundo:   #1E3540;

  /* Dados: no escuro o azul e o verde escuros somem — sobem para as versões claras */
  --dado-1: #F7ADB7;
  --dado-2: #D4AF37;
  --dado-3: #7DB3F0;
  --dado-4: #6EE7B7;
  --dado-5: #C89BE0;
  --dado-1-texto: var(--dado-1);

  /* No escuro o cartão NÃO tem sombra. Sombra é sombra de luz — sobre fundo
     escuro ela não separa nada, só suja a borda do elemento com uma mancha.
     Aqui quem separa é a borda (1,24:1), e o cartão fica limpo.
     A sombra volta a existir só no que FLUTUA de verdade: modal e toast, onde
     ela não separa do fundo, mas diz "isto está por cima de tudo". */
  --sombra-cartao:   none;
  --sombra-elevada:  none;
  --sombra-resposta: 0 -8px 28px rgba(0, 0, 0, 0.35);
  --sombra-modal:    0 12px 48px rgba(0, 0, 0, 0.55);
}

/* A troca de tema não anima: 40 tokens de cor em transição ao mesmo tempo
   custam um repaint da árvore inteira e "borram" a tela no celular. O corte
   seco é mais rápido de ler e mais honesto. */

* { box-sizing: border-box; margin: 0; padding: 0; }

/* =============================================================
   LINGUAGEM DE ÍCONE — traço fino, uniforme, sem fundo (05-08-26)

   O app tinha traços de 1,8 · 1,9 · 2 · 2,2 espalhados pelo markup, herdados
   de momentos diferentes. Traço grosso é o que dava aos ícones o ar pesado e
   genérico; e traço IRREGULAR entre ícones vizinhos é pior ainda, porque um
   parece mais importante que o outro sem motivo.

   Um valor só, num lugar só: 1,5. O seletor pega `stroke="currentColor"`, que
   é a assinatura dos ícones de INTERFACE — os traços dos gráficos usam
   `style="stroke:…"` com a cor do dado e ficam de fora, como devem.

   Isto sobrescreve o atributo do markup, então nenhum SVG precisou ser
   reescrito. Ícone que precise de traço próprio declara por classe depois. */
svg[stroke="currentColor"] {
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

html, body {
  font-family: var(--fonte);
  background: var(--bg);
  color: var(--text);
  font-size: var(--tam-corpo);
  line-height: 1.5;
  -webkit-text-size-adjust: 100%;
}

button, input, select { font-family: inherit; }

/* Todo número em tabular — o layout não dança quando o valor muda */
input[type="number"] { font-variant-numeric: tabular-nums; }

/* Foco sempre visível — este é o ÚNICO anel de foco do sistema.
   Na cor da área (pior caso #2166B8 = 5,74:1 sobre branco; mínimo 3:1).
   Dentro da sidebar escura o shell.css troca para --sidebar-text. */
:focus-visible {
  outline: 2px solid var(--cor-area);
  outline-offset: 2px;
}

/* ---------- Movimento: respeito obrigatório ---------- */
/* MAIS SUAVE, NÃO DESLIGADO — revisto em 05-08-26.

   Antes isto era `transition: none; animation: none` em tudo. É o reflexo
   comum e está errado: quem pediu menos movimento não pediu menos INFORMAÇÃO.
   O incômodo vem de coisa que se DESLOCA na tela (deslizar, escalar), não de
   cor e opacidade — e sem o fade, elementos passam a piscar na tela sem que se
   entenda de onde vieram, o que é pior para quem tem sensibilidade vestibular.

   Regra aplicada: manter opacidade e cor, remover deslocamento. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    /* a lista SUBSTITUI o que cada componente declarou: sai transform, ficam
       as propriedades que não movem nada de lugar */
    transition-property: opacity, color, background-color, border-color,
                         box-shadow, fill, stroke !important;
    animation: none !important;
  }
  /* As entradas que eram keyframes com deslocamento viram fade puro: o
     elemento ainda "chega", só não vem deslizando. */
  .modal, .seletor-lista, .painel-avisos, .toast, .responde {
    animation: surge-sem-mover var(--dur-curta) var(--curva) !important;
  }
  @keyframes surge-sem-mover { from { opacity: 0; } to { opacity: 1; } }
  /* o brilho do esqueleto é movimento contínuo: some de vez */
  .skeleton { animation: none !important; background: var(--superficie-2); }
}

/* =============================================================
   Cabeçalho (página de precificar avulsa)
============================================================= */
.topo {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--card);
  border-bottom: var(--fio);
  padding: var(--esp-3) var(--esp-4);
}
.topo-linha {
  display: flex;
  align-items: center;
  gap: var(--esp-3);
  justify-content: space-between;
}
/* O tracking largo sobrevive SÓ na marca */
.marca {
  font-size: var(--tam-corpo);
  font-weight: var(--peso-forte);
  letter-spacing: 0.14em;
}
.marca .beta {
  font-size: var(--tam-apoio);
  font-weight: var(--peso-normal);
  letter-spacing: 0;
  color: var(--text-light);
  border: var(--fio);
  border-radius: var(--raio-pilula);
  padding: 0 var(--esp-2);
  margin-left: var(--esp-2);
  vertical-align: 2px;
}
.topo .subtitulo {
  color: var(--text-light);
  font-size: var(--tam-apoio);
  margin-top: 2px;
}

/* =============================================================
   Layout
============================================================= */
.conteudo {
  padding: var(--esp-4) var(--esp-4) calc(var(--barra-h) + var(--esp-4));
  max-width: 1400px;
  margin: 0 auto;
}

/* =============================================================
   A ASSINATURA — frase-resposta e conta fechada
   Todo número importante vive DENTRO de uma frase; o valor 28px
   fica embutido nela. Nunca rótulo em caixa alta sobre número solto.
============================================================= */
.resposta-frase {
  font-size: var(--tam-corpo);
  font-weight: var(--peso-normal);
  line-height: 1.5;
}
/* Número secundário dentro da frase: forte, sem virar herói.
   PROPORCIONAL e não tabular — mudança de 05-08-26. Tabular existe para números
   ALINHAREM EM COLUNA; dentro de uma frase não há coluna nenhuma, e o efeito
   colateral é ruim: medido nesta fonte, o dígito "1" ocupa 15,5px em tabular
   contra 11,3px em proporcional. São 4,2px de vazio em volta de cada "1", que
   em "R$ 1.430,00" viram buracos irregulares no meio do valor.
   (Esta regra tem especificidade 0,1,1 e vencia a de .valor-resposta, 0,1,0 —
   por isso o herói continuava tabular mesmo depois de trocado lá embaixo.) */
.resposta-frase strong,
.resposta-frase b {
  font-weight: var(--peso-forte);
  font-variant-numeric: proportional-nums;
  white-space: nowrap;
}
/* O valor-herói embutido na frase.
   Tracking ZERO: o --track-heroi (−0,015em) existia para compensar o excesso de
   espaço que o tabular abria. Sem tabular, ele só aperta — e apertar dígito
   grande é a outra metade do desconforto. */
.valor-resposta {
  font-family: var(--fonte-numero);
  letter-spacing: var(--track-numero);
  font-size: var(--tam-resposta);
  font-weight: var(--peso-forte);
  line-height: 1.2;
  font-variant-numeric: proportional-nums;
  white-space: nowrap;
}
/* prejuízo: a PALAVRA e o número em --danger — nunca cor sozinha */
.resposta-frase .negativo { color: var(--danger); }
/* lucro: espelho do .negativo — a PALAVRA e o número em --success
   (7,13:1 sobre o branco do cartão, 6,68:1 sobre o creme) */
.resposta-frase .positivo { color: var(--success); }

/* A linha da conta fechada: "custo R$ 4,20 + margem 60% = R$ 10,50" */
.conta-fechada {
  font-family: var(--fonte-numero);
  letter-spacing: var(--track-numero);
  font-size: var(--tam-apoio);
  color: var(--text-light);
  font-variant-numeric: proportional-nums;
  margin-top: var(--esp-1);
}

/* =============================================================
   CARTÃO — a forma base. Tocável tem chevron + :active; leitura não.
============================================================= */
/* Padding de 24px (era 16): o pedido de "deixar a tipografia respirar" se
   resolve aqui, não com mais espaço ENTRE os cartões. Cartão apertado com muito
   ar em volta lê como bloco denso flutuando; o inverso lê como conteúdo. */
.cartao,
.cartao-resposta {
  display: block;
  width: 100%;
  background: var(--card);
  border: var(--fio-cartao);
  border-radius: var(--raio);
  box-shadow: var(--sombra-cartao);
  padding: var(--esp-5);
  color: inherit;
  font: inherit;
  text-align: left;
  text-decoration: none;
  transition: box-shadow var(--dur-curta) var(--curva),
              border-color var(--dur-curta) var(--curva-cor),
              background var(--dur-curta) var(--curva-cor);
}
a.cartao, button.cartao { cursor: pointer; -webkit-tap-highlight-color: transparent; }
/* No hover, o cartão SOBE (sombra) em vez de acender a borda de rosa. Borda
   colorida em hover é ruído: a elevação já diz que o elemento respondeu. */
a.cartao:active, button.cartao:active { background: var(--superficie-2); }

/* =============================================================
   CARTÃO IMPORTANTE — o primeiro lugar da hierarquia

   Um só por tela. Borda mais forte (1,55 contra 1,32) e sombra elevada: é o
   que a pessoa deve ver ANTES de qualquer outra coisa. Se dois cartões
   levarem esta classe, nenhum é importante.
============================================================= */
.cartao.destaque {
  border-color: var(--border-forte);
  box-shadow: var(--sombra-elevada);
}
/* Prejuízo ganha tarja: o cartão inteiro no vermelho a 8%. Isso NÃO substitui
   a palavra — a frase continua dizendo "Faltou", e o valor continua em
   --danger. A tarja é o terceiro sinal, para quem varre a tela sem ler. */
.cartao.perigo {
  background: var(--fundo-perigo);
  border-color: color-mix(in srgb, var(--danger) 22%, var(--border));
}

/* Cartão do Mês (Início): a resposta + por quê, tocável inteiro */
.cartao-mes {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--esp-2);
  padding-right: var(--esp-6);   /* respiro para o chevron */
  /* 24 e não 32: o usuário apontou que sobrava espaço SEM contraste, o que
     paradoxalmente fazia a tela parecer cheia. Com os níveis de superfície
     separando as seções, o vão pode encolher. */
  margin-bottom: var(--esp-5);
}
/* O `::after` com "›" foi REMOVIDO em 05-08-26: o markup já traz um
   `<span class="chevron">`, então a tela mostrava DOIS chevrons — um no canto
   e outro solto embaixo. Ficou o do markup, que é o que leva `aria-hidden`. */
.cartao-mes .chevron {
  position: absolute;
  top: var(--esp-5);
  right: var(--esp-5);
}
/* extrato full-bleed dentro do cartão: sem borda própria, cola nas bordas.
   Os cantos de BAIXO acompanham a curva do cartão: sem isto, o full-bleed
   pintaria por cima da curva e cortaria os dois cantos.
   O margin negativo TEM de casar com o padding do cartão — que subiu de 16 para
   24px na revisão de 05-08-26; sem atualizar aqui, a coluna descolaria 8px de
   cada lado e o full-bleed viraria uma faixa torta. */
.cartao .coluna-dinheiro {
  border: 0;
  border-top: var(--fio);
  border-radius: 0 0 calc(var(--raio) - 1px) calc(var(--raio) - 1px);
  margin: 0 calc(-1 * var(--esp-5)) calc(-1 * var(--esp-5));
}
.cartao-mes .coluna-dinheiro { margin-right: calc(-1 * var(--esp-6)); }

/* O ícone alinha com a PRIMEIRA LINHA da frase, não com o bloco todo: com o
   valor em 28px, centralizar no bloco jogaria o ícone para o meio do número. */
.mes-linha {
  display: flex;
  align-items: flex-start;
  gap: var(--esp-3);
}
.mes-icone {
  flex-shrink: 0;
  width: 22px;
  height: 22px;
  margin-top: 3px;              /* desce até o centro óptico da primeira linha */
  color: var(--danger);
}
/* A linha do POR QUÊ. Fica em apoio: ela explica, não compete com o valor. */
.mes-detalhe {
  font-size: var(--tam-apoio);
  line-height: var(--ent-apoio);
  letter-spacing: var(--track-apoio);
  color: var(--text-light);
}
.mes-detalhe strong {
  font-weight: var(--peso-forte);
  color: var(--text);
}

/* =============================================================
   COLUNA DO DINHEIRO — linhas de registro (mata o stat tile solto)
============================================================= */
.coluna-dinheiro {
  background: var(--card);
  border: var(--fio-cartao);
  border-radius: var(--raio);
  box-shadow: var(--sombra-cartao);
  overflow: hidden;             /* linhas full-bleed dentro do cartão */
}
/* dentro de um cartão ela é full-bleed e não pode ter sombra própria */
.cartao .coluna-dinheiro { box-shadow: none; }
.registro {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--esp-3);
  align-items: baseline;
  padding: var(--esp-4) var(--esp-5);
}
.registro + .registro { border-top: var(--fio); }
.registro-rotulo {
  font-size: var(--tam-apoio);
  font-weight: var(--peso-normal);
  color: var(--text-light);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.registro-valor {
  font-family: var(--fonte-numero);
  letter-spacing: var(--track-numero);
  font-size: var(--tam-corpo);
  font-weight: var(--peso-normal);
  color: var(--text);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  transition: opacity var(--dur-curta) var(--curva);
}
/* Entrada/saída no extrato: verde/vermelho SEMPRE acompanhados do sinal
   aritmético no próprio valor ("+ R$ 320,00" / "− R$ 80,00") — o sinal vem
   do markup; a cor sozinha nunca carrega o sentido. */
.registro-valor.entrada { color: var(--success); }
.registro-valor.saida   { color: var(--danger); }

/* Linha de total: fio de 2px é TERMINAL — nada abaixo dele no cartão */
.registro.total { border-top: var(--fio-total); }
.registro.total .registro-valor {
  font-size: var(--tam-resposta);
  line-height: 1.2;
  letter-spacing: 0;
}

/* =============================================================
   CARTÃO TRAVADO — estado vazio que age
   rótulo 13 cinza + traço 28 + frase de destrave + chevron
============================================================= */
.cartao-travado {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--esp-1) var(--esp-3);
  min-height: 56px;
  margin-bottom: var(--esp-3);
}
a.cartao-travado, button.cartao-travado { cursor: pointer; }
a.cartao-travado:active, button.cartao-travado:active { background: var(--superficie-2); }
.travado-rotulo {
  grid-column: 1;
  font-size: var(--tam-apoio);
  color: var(--text-light);
}
/* o traço (—) no tamanho da resposta, apagado: aqui MORARIA um número */
.travado-valor {
  font-family: var(--fonte-numero);
  letter-spacing: var(--track-numero);
  grid-column: 1;
  font-size: var(--tam-resposta);
  font-weight: var(--peso-forte);
  line-height: 1.2;
  color: var(--text-light);
  font-variant-numeric: proportional-nums;
}
.travado-destrave {
  grid-column: 1;
  font-size: var(--tam-apoio);
  color: var(--text);
}
.cartao-travado .chevron { grid-column: 2; grid-row: 1 / span 3; }

/* Chevron — o sinal de "posso tocar" (cartão de leitura NUNCA o tem).
   Usa --text-suave (4,29:1), abaixo dos 4,5 de texto, e isso é DELIBERADO e
   verificado: os 7 chevrons da tela são todos `aria-hidden="true"`, nenhum é
   lido por leitor de tela, e o nome acessível do cartão vem do próprio conteúdo
   ("Sobrou R$ 1.430,00 em agosto"). Ele é afordância visual, não informação —
   o critério que vale é o de elemento gráfico, 3:1, com folga.
   Se um dia o chevron deixar de ser aria-hidden, ele volta para --text-light. */
.chevron {
  flex-shrink: 0;
  color: var(--text-suave);
  font-size: var(--tam-titulo);
  line-height: 1;
}

/* Travado → respondido: patch de DOM dirigido anima com esta classe */
.responde { animation: responde var(--dur-media) var(--curva); }
@keyframes responde {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: none; }
}
/* Valor atualizando (barra viva, linha de registro): só opacity */
.valor-troca { animation: valor-troca var(--dur-media) var(--curva); }
@keyframes valor-troca { from { opacity: 0; } to { opacity: 1; } }

/* O seletor de produto abre a tela de precificar: é o PRIMEIRO PASSO da tarefa
   e, desde 05-08-26, também o que mais se destaca nela. Sem escolher o produto
   não há ficha, não há preço, não há nada — mas ele era um campo como outro
   qualquer e sumia na página: recesso claro sobre fundo claro.

   O destaque NÃO vem de cor de marca nem de borda grossa. Vem de dois níveis
   que o sistema já usa para dizer "isto merece atenção":
   1. o passo ganha SUPERFÍCIE PRÓPRIA, com --border-forte e sombra elevada —
      o mesmo tratamento do `.cartao.destaque` do Início;
   2. o valor escolhido sobe para 18px. Hierarquia por TAMANHO, que é o mesmo
      recurso que resolveu a meta que estava sumindo, e não por mais uma cor.

   O campo lá dentro INVERTE para a cor do cartão, e isso não é decisão nova:
   é a regra que já existe para campo dentro de modal e de seção
   (`.modal .input, .secao-corpo .input`). Sobre superfície que já é clara o
   recesso desapareceria — --superficie e --superficie-2 diferem em 1,01.

   O FOCO continua distinguível do repouso: ele troca a borda para a cor da
   área e acrescenta o halo de 3px, que o repouso não tem. Só a inversão
   recesso→superfície é que deixa de valer aqui, exatamente como no modal. */
.campo-produto {
  margin-bottom: var(--esp-5);
  padding: var(--esp-4);
  background: var(--superficie);
  border: 1px solid var(--border-forte);
  border-radius: var(--raio);
  box-shadow: var(--sombra-elevada);
}
.campo-produto .rotulo {
  display: block;
  font-size: var(--tam-corpo);
  color: var(--text);
  margin-bottom: var(--esp-2);
}
.campo-produto .seletor-botao {
  background-color: var(--card);
  border-color: var(--border);
}
.campo-produto .seletor-valor { font-size: var(--tam-titulo); }

/* =============================================================
   SELETOR (combobox próprio) — js/seletor.js

   Substituiu o <select> nativo porque o popup dele é desenhado pelo SISTEMA
   OPERACIONAL: escapava dos limites do <iframe> da tela de precificar e saía
   branco no tema escuro. Aqui a lista é DOM comum — fica contida e usa os
   tokens como qualquer outro componente.
============================================================= */
.seletor { position: relative; }

.seletor-botao {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--esp-3);
  width: 100%;
  text-align: left;
  cursor: pointer;
  /* herda .input: altura, raio, fundo de recesso, foco na cor da área */
}
.seletor-valor {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.seletor-seta {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  color: var(--text-suave);
  stroke-width: 1.5;
  transition: transform var(--dur-curta) var(--curva);
}
.seletor-botao[aria-expanded="true"] .seletor-seta { transform: rotate(180deg); }

.seletor-lista {
  transform-origin: top center;
  position: absolute;
  top: calc(100% + var(--esp-1));
  left: 0;
  right: 0;
  z-index: 45;          /* acima do conteúdo, abaixo de modal (50) e toast (60) */
  max-height: 260px;
  overflow-y: auto;
  list-style: none;
  padding: var(--esp-1);
  background: var(--card);
  border: var(--fio-cartao);
  border-radius: var(--raio-medio);
  box-shadow: var(--sombra-modal);
  animation: seletor-abre var(--dur-curta) var(--curva);
}
.seletor-lista[hidden] { display: none; }
/* Escala a partir do GATILHO, não do centro: o popover "cresce" de onde foi
   tocado. Escalar do meio faz o elemento parecer que veio de outro lugar.
   (Modal é a exceção da regra e continua centrado.) */
@keyframes seletor-abre {
  from { opacity: 0; transform: translateY(-4px) scale(0.97); }
  to   { opacity: 1; transform: none; }
}

.seletor-opcao {
  padding: var(--esp-3) var(--esp-3);
  border-radius: var(--raio-pequeno);
  font-size: var(--tam-corpo);
  color: var(--text);
  cursor: pointer;
  min-height: var(--alvo-toque);
  display: flex;
  align-items: center;
}
/* DOIS estados diferentes, de propósito:
   `data-ativo`  = onde o teclado está agora (o cursor da lista)
   `aria-selected` = o que está de fato escolhido
   Confundir os dois é o erro clássico: a pessoa navega com as setas e perde de
   vista qual era a opção original. */
.seletor-opcao[data-ativo="sim"] { background: var(--superficie-2); }
.seletor-opcao[aria-selected="true"] {
  color: var(--cor-area);
  font-weight: var(--peso-forte);
}

/* =============================================================
   Seção (Precificar) — independentes, todas nascem abertas
============================================================= */
.secao {
  background: var(--card);
  border: var(--fio-cartao);
  border-radius: var(--raio);
  box-shadow: var(--sombra-cartao);
  margin-bottom: var(--esp-3);
  overflow: hidden;
}
.secao-cab {
  display: flex;
  align-items: center;
  gap: var(--esp-2);
  width: 100%;
  padding: var(--esp-4) var(--esp-5);
  background: none;
  border: 0;
  cursor: pointer;
  text-align: left;
  min-height: var(--alvo-toque);
}
.secao-cab h2 {
  font-size: var(--tam-corpo);
  font-weight: var(--peso-forte);
  color: var(--text);
  flex: 1;
}
/* contagem/resumo do cabeçalho: "3 ingredientes" · "Margem 30% · Imposto 3,64%" */
.secao-cab .secao-resumo,
.secao-cab .contador {
  font-size: var(--tam-apoio);
  color: var(--text-light);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* INDICADOR DE EXPANSÃO — secundário por definição.
   Ele diz que a seção abre; não é o assunto do cabeçalho. Três ajustes,
   feitos em 05-08-26, e a ordem de importância é essa:

   1. TRAÇO, antes do tamanho. O ícone tinha 14px com stroke-width 2,2 — num
      ícone pequeno isso dá uma razão traço/área altíssima, e é o que fazia ele
      pesar mais que o título ao lado. Em 1,6 ele fica fino como o texto.
      O `stroke-width` vem cravado no atributo do SVG; sobrescrever pelo CSS
      mantém o markup de todas as telas intacto.
   2. TAMANHO. Sobe para 16px — o ícone fica maior E mais leve que antes,
      porque o que pesava era o traço, não a área.
   3. CONTRASTE. --text-suave (4,29:1 no claro), o nível reservado a elemento
      gráfico. O título ao lado está em 15,51 — a diferença de 3,6× é o que
      manda o olho para o conteúdo primeiro.

   O alinhamento é ÓPTICO, não geométrico: ver .secao-cab .seta abaixo. */
.secao-cab .seta {
  /* caixa fixa: o ícone gira dentro dela sem empurrar o texto ao lado */
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  color: var(--text-suave);
  /* herda o 1,5 global; declarado aqui só para deixar explícito que este ícone
     não é exceção — ele segue a mesma linguagem do resto */
  stroke-width: 1.5;
  /* O chevron "v" tem a massa concentrada na metade de BAIXO do seu quadro
     (o bico desce até 15 de 24). Centrado no quadro ele parece cair; 1px para
     cima devolve o centro óptico ao meio da linha do título.
     Feito com MARGIN e não com transform: o transform é de quem gira o ícone no
     estado fechado, e as duas regras se sobrescreveriam. */
  margin-top: -1px;
  transition: transform var(--dur-curta) var(--curva);
}

/* -------------------------------------------------------------
   Seção com IDENTIDADE de categoria (Insumos x Produtos x Produção).

   As cores NÃO são novas: são as MESMAS que já servem de cor de área,
   com contraste medido — o dourado da marca levado a texto (#8A631D,
   5,41:1), o rosa da marca levado a texto (#A8305F, 6,46:1) e o azul
   (#1E40AF, 8,72:1), que entra justamente porque rosa e dourado
   sozinhos colapsam sob protanopia.

   A cor nunca é o único sinal: o nome está escrito no cabeçalho e o
   ícone tem desenho próprio. Quem não distingue as cores continua
   lendo a tela inteira.
------------------------------------------------------------- */
.secao[data-cat] { border-left: 3px solid var(--cor-cat, var(--border)); }
.secao[data-cat="insumos"]  { --cor-cat: var(--dourado-texto); }
.secao[data-cat="produtos"] { --cor-cat: var(--rosa-texto); }
.secao[data-cat="producao"] { --cor-cat: var(--aba-relatorios); }   /* azul 8,72:1 */
.secao[data-cat] .icone-cat { color: var(--cor-cat); flex-shrink: 0; }
.secao[data-cat] .contador  { color: var(--cor-cat); font-weight: var(--peso-forte); }

/* O botão de adicionar herda a cor da própria seção — o "+ insumo"
   fica âmbar dentro de Insumos e vinho dentro de Produtos, então o
   destino do clique é reconhecível antes de ler. */
.secao[data-cat] .btn.fantasma {
  color: var(--cor-cat);
  border-color: var(--cor-cat);
}
.btn .icone { flex-shrink: 0; }
.btn.fantasma.largo { display: flex; align-items: center; justify-content: center; gap: var(--esp-2); }
.secao[data-aberta="nao"] .seta { transform: rotate(-90deg); }
.secao[data-aberta="nao"] .secao-corpo { display: none; }
.secao-corpo { padding: var(--esp-5); padding-top: 0; }
.secao-corpo > :first-child { margin-top: var(--esp-1); }

/* =============================================================
   Itens da receita — linha: nome + input + subtotal + lixeira 44px
============================================================= */
.lista { display: flex; flex-direction: column; gap: var(--esp-3); }
/* `flex-shrink: 0` é OBRIGATÓRIO aqui, não é ajuste fino.
   Em flex column o padrão é `flex-shrink: 1`: assim que a lista ganhou
   `max-height` (a rolável de 3 itens), o flexbox começou a ESPREMER os itens
   para caber na altura — cada um encolheu para a altura do nome e o preço
   vazou para fora do próprio card. Com shrink 0 o item mantém a altura e a
   lista rola, que é o comportamento pretendido. */
.lista > * { flex-shrink: 0; }

/* =============================================================
   LISTA ROLÁVEL — mostra 3, rola o resto (05-08-26)

   A tela de Cadastros abria com as seções FECHADAS para não despejar 15 itens.
   O efeito colateral era pior que o problema: a tela abria vazia, com dois
   cabeçalhos e nada mais.

   Aqui as seções abrem, mas a lista mostra três itens e rola por dentro. A
   seção passa a ter altura previsível, a tela tem conteúdo desde o primeiro
   quadro, e o resto do acervo está a um gesto — ou a uma busca, logo acima.

   `--altura-item` é MEDIDO, não estimado: é a altura real de uma linha de
   insumo (nome + subtítulo + 32 de padding). Se a linha ganhar conteúdo, este
   número muda junto, senão o corte cai no meio do quarto item.
============================================================= */
.lista.rolavel {
  --itens-visiveis: 3;
  /* 110px: a altura REAL de uma linha de insumo (nome + preço + "por kg",
     empilhados no celular) com os 32px de padding.
     Duas medições erradas antes desta, e a segunda ensina mais que a primeira:
       · 92px, estimado — a lista mostrou 4 itens em vez de 3;
       · 56px, "medido" — mas medido com os itens JÁ ESPREMIDOS pelo bug do
         flex-shrink. Era a altura do defeito, não a do item.
     Medir depois de consertar, e não antes, é o que fecha a conta. */
  --altura-item: 110px;
  max-height: calc(var(--itens-visiveis) * var(--altura-item)
                   + (var(--itens-visiveis) - 1) * var(--esp-3));
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  /* o corte no topo/base fica óbvio: a lista some por trás de um degradê em vez
     de terminar numa linha reta, que pareceria fim de conteúdo */
  mask-image: linear-gradient(to bottom, transparent 0, #000 10px,
                              #000 calc(100% - 14px), transparent 100%);
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 10px,
                              #000 calc(100% - 14px), transparent 100%);
  /* respiro para a barra de rolagem não encostar no conteúdo */
  padding-right: var(--esp-1);
  scrollbar-width: thin;
  scrollbar-color: var(--border) transparent;
}
/* Filtro ativo com poucos resultados: a lista encolhe para caber neles em vez
   de segurar a altura de 3 e deixar um vão embaixo do único achado. */
.lista.rolavel.sem-limite {
  max-height: none;
  overflow-y: visible;
  mask-image: none;
  -webkit-mask-image: none;
}
/* rolagem por teclado precisa de foco visível — a lista é focável (tabindex) */
.lista.rolavel:focus-visible { outline: 2px solid var(--cor-area); outline-offset: 2px; }
.lista.rolavel::-webkit-scrollbar { width: 4px; }
.lista.rolavel::-webkit-scrollbar-thumb {
  background: var(--border);
  border-radius: var(--raio-pilula);
}
.lista.rolavel::-webkit-scrollbar-track { background: transparent; }

/* Quantos itens ficaram de fora. A barra de rolagem no celular só aparece
   DURANTE o gesto, então sem esta linha a pessoa vê três insumos e conclui
   que tem três. */
.lista-resto {
  font-size: var(--tam-apoio);
  color: var(--text-light);
  text-align: center;
  margin-top: var(--esp-3);
  letter-spacing: var(--track-apoio);
}

/* O atributo `hidden` do HTML vale `display: none`, mas isso vem do
   user-agent e QUALQUER `display` declarado aqui o sobrescreve — inclusive o
   `grid` logo abaixo. Sem esta linha, a busca marcava os itens como hidden e
   eles continuavam ocupando espaço na lista: filtrar por "choco" deixava a
   lista com 964px de altura em vez de 124. Bug pego medindo a altura real,
   não a contagem de `.hidden`, que dava certo e escondia o problema. */
.item[hidden] { display: none; }

.item {
  border: var(--fio);
  border-radius: var(--raio-medio);
  padding: var(--esp-4);
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--esp-2) var(--esp-3);
  align-items: center;
  min-height: 56px;
}
.item-nome {
  grid-column: 1 / -1;
  font-weight: var(--peso-normal);
  display: flex;
  align-items: baseline;
  gap: var(--esp-2);
  flex-wrap: wrap;
  min-width: 0;
}
.item-nome .unidade {
  font-size: var(--tam-apoio);
  color: var(--text-light);
  font-weight: var(--peso-normal);
}
.item-qtd { display: flex; align-items: center; gap: var(--esp-2); }
.item-qtd label { font-size: var(--tam-apoio); color: var(--text-light); }
.item-qtd input { width: 112px; }
.item-sub {
  font-family: var(--fonte-numero);
  letter-spacing: var(--track-numero);
  text-align: right;
  font-weight: var(--peso-normal);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.item-sub .custo-unit {
  display: block;
  font-size: var(--tam-apoio);
  font-weight: var(--peso-normal);
  color: var(--text-light);
}
.item-remover {
  grid-column: 2;
  justify-self: end;
  background: none;
  border: var(--fio);
  border-radius: var(--raio-medio);
  color: var(--text-light);
  width: var(--alvo-toque);
  height: var(--alvo-toque);
  cursor: pointer;
  display: grid;
  place-items: center;
}

/* =============================================================
   Campos — 52px, fonte 16 (iOS), rótulo 13 a 4px, UM por linha
============================================================= */
/* CAMPO DISCRETO — revisão de 05-08-26.
   Antes o campo era branco com borda de 1,31:1 sobre um cartão também branco:
   a borda era a única coisa que o desenhava, e por isso precisava ser forte.
   Uma caixa contornada em cada linha do formulário é o que mais pesa numa tela
   de cadastro.

   Agora o campo é um RECESSO: fundo levemente rebaixado (1,12:1) e borda
   transparente. Ele se integra à superfície em vez de se recortar dela — e no
   foco ganha borda e halo, que é quando o contorno realmente informa algo. */
.input, select.input {
  width: 100%;
  min-height: var(--altura-controle);
  font-size: var(--tam-corpo);
  padding: var(--esp-3) var(--esp-4);
  border: 1px solid transparent;
  border-radius: var(--raio-medio);
  /* background-COLOR e não o shorthand: o select põe a própria seta em
     background-image, e o shorthand a apagaria. */
  background-color: var(--superficie-2);
  color: var(--text);
  transition: border-color var(--dur-curta) var(--curva-cor),
              background var(--dur-curta) var(--curva-cor),
              box-shadow var(--dur-curta) var(--curva);
}
.input::placeholder { color: var(--text-light); opacity: 1; }

/* SELECT — seta própria, no lugar da nativa.
   A seta que o navegador desenha ignora o padding do campo e encosta na borda:
   com o raio de 14px do campo, ela fica espremida contra a curva. Além disso
   ela muda de desenho e de tamanho em cada navegador, o que é exatamente o que
   um design system não pode ter.

   `appearance: none` desliga a nativa; a nossa entra como background e respeita
   os mesmos 16px de respiro lateral dos outros campos. É o MESMO chevron da
   seção dobrável, com o mesmo traço de 1,6 — desenho consistente. */
select.input {
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  padding-right: 44px;   /* 16 de respiro + 16 da seta + 12 de folga */
  background-repeat: no-repeat;
  background-position: right var(--esp-4) center;
  background-size: 16px 16px;
  /* Data URI por tema: a cor tem de vir cravada no SVG (background-image não
     herda currentColor). É --text-suave em cada tema. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238A7480' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
}
:root[data-tema="escuro"] select.input {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239C8A92' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
}
/* IE/Edge legado desenhava uma segunda seta */
select.input::-ms-expand { display: none; }

/* ATENÇÃO nos estados abaixo: todos usam `background-color`, nunca o shorthand
   `background`. O shorthand reseta background-image junto — e apagaria a seta
   do select em todo hover e todo foco. */
/* No foco o campo SOBE para a cor do cartão e ganha o contorno na cor da área:
   a inversão (recesso → superfície) é sinal mais forte que engrossar a borda. */
.input:focus {
  background-color: var(--card);
  border-color: var(--cor-area);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--cor-area) 14%, transparent);
}
/* Dentro de superfície que já é recesso (modal, seção), o campo inverte:
   fica no branco do cartão para não sumir no fundo igual ao dele. */
.modal .input, .secao-corpo .input { background-color: var(--card); border-color: var(--border); }
.modal .input:focus, .secao-corpo .input:focus { border-color: var(--cor-area); }

.campo { display: flex; flex-direction: column; gap: var(--esp-2); }
/* Rótulo em 400: era 400 e continua. O que mudou foi a COR — --text-light subiu
   para 6,79:1, então ele lê melhor sem precisar de peso. */
.campo label {
  font-size: var(--tam-apoio);
  font-weight: var(--peso-normal);
  color: var(--text-light);
}
.campo-ajuda { font-size: var(--tam-apoio); color: var(--text-light); }
/* A mensagem de erro do campo. Substituiu o balão nativo do navegador em
   05-08-26 — ele ignorava a tipografia e as cores do sistema, mudava de texto
   entre navegadores e sumia sozinho. Aqui ela fica: nasce embaixo do campo
   errado e só sai quando a pessoa corrige. */
.campo-erro {
  font-size: var(--tam-apoio);
  color: var(--danger);
  display: flex;
  align-items: flex-start;
  gap: var(--esp-1);
}
/* O "!" antes da mensagem é o segundo sinal — cor sozinha nunca carrega o
   sentido, e aqui vale mais ainda porque vermelho é a cor mais confundida. */
.campo-erro::before {
  content: "!";
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: 15px;
  height: 15px;
  margin-top: 2px;
  border-radius: 50%;
  background: var(--danger);
  color: var(--card);
  font-size: 11px;
  font-weight: var(--peso-forte);
  line-height: 1;
}
/* O campo em erro também muda de borda: quem não lê a mensagem enxerga onde é. */
.campo.com-erro .input {
  border-color: var(--danger);
}
.campo.com-erro .input:focus {
  border-color: var(--danger);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--danger) 16%, transparent);
}
/* dentro de .campo-com-icone o ícone acompanha o estado de erro */
.campo.com-erro .campo-icone { color: var(--danger); }

/* um campo por linha no celular — fim da grade 2×3 de porcentagens */
.grade-campos {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--esp-3);
}

/* =============================================================
   Botões — 3 variantes. UM primário por tela, no terço inferior.
============================================================= */
/* O PRIMÁRIO É ROSA EM TODA TELA — mudança de 05-08-26.

   Antes o botão vestia a cor da ÁREA e o rótulo era branco. Isso morreu por dois
   motivos. O primeiro é medido: com o rosa da marca no lugar do marrom, branco
   sobre #E58FA8 dá 2,38:1 e reprova sem apelação. O segundo é de identidade —
   o CTA é o lugar mais visto do app, e é onde a marca deve estar, não a aba.

   Rosa #E58FA8 com rótulo no vinho #3A1A25 = 6,52:1. É literalmente o botão
   "Entrar" da arte oficial. As duas cores são fixas nos dois temas (no escuro o
   par dá 7,60:1 contra o fundo), então o contraste não depende do tema.
   A cor da área continua viva onde ela informa: título, ícone, foco, barrinha. */
.btn {
  min-height: var(--altura-controle);
  padding: var(--esp-3) var(--esp-4);
  border-radius: var(--raio-medio);
  border: 1px solid var(--rosa);
  background: var(--rosa);
  color: var(--vinho);
  font-size: var(--tam-corpo);
  font-weight: var(--peso-forte);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--esp-2);
  transition: transform var(--dur-curta) var(--curva),
              box-shadow var(--dur-curta) var(--curva);
  -webkit-tap-highlight-color: transparent;
}
/* O primário é o único elemento com sombra COLORIDA: o rosa da própria marca
   projetado embaixo. É o que o faz "subir" da página sem precisar de gradiente
   nem de borda grossa. */
.btn:not(.fantasma):not(.perigo) { box-shadow: 0 2px 10px rgba(229, 143, 168, 0.35); }
.btn:active { transform: scale(0.97); }
.btn:disabled { opacity: 0.45; cursor: not-allowed; transform: none; box-shadow: none; }
.btn.fantasma {
  background: var(--card);
  color: var(--text);
  border-color: var(--border);
  box-shadow: none;
}
.btn.perigo {
  min-height: var(--alvo-toque);
  background: transparent;
  color: var(--danger);
  border-color: var(--border);
  box-shadow: none;
}
.btn.largo { width: 100%; }
.btn.sm { min-height: var(--alvo-toque); padding: var(--esp-2) var(--esp-3); }

/* =============================================================
   Estado vazio (convite para agir) e skeleton
============================================================= */
.vazio {
  text-align: center;
  color: var(--text-light);
  font-size: var(--tam-apoio);
  line-height: 1.5;
  padding: var(--esp-5) var(--esp-3);
  border: 1px dashed var(--border);
  border-radius: var(--raio);
}
.skeleton {
  height: 56px;
  border-radius: var(--raio);
  /* hex órfãos #EFEFEF/#F7F7F7 saíram: o brilho agora vem dos tokens */
  background: linear-gradient(90deg, var(--superficie-2) 25%, var(--card) 50%, var(--superficie-2) 75%);
  background-size: 200% 100%;
  animation: brilho 1.2s infinite;
}
@keyframes brilho { from { background-position: 200% 0; } to { background-position: -200% 0; } }

/* =============================================================
   BARRA DE RESPOSTA VIVA — só no Precificar, fixa acima do rodapé.
   A única sombra "para cima" do sistema.
============================================================= */
.resultado {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 30;
  min-height: var(--barra-h);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--esp-1);
  background: var(--card);
  border-top: var(--fio);
  box-shadow: var(--sombra-resposta);
  padding: var(--esp-3) var(--esp-4) calc(var(--esp-3) + env(safe-area-inset-bottom));
}
.resultado .valor-resposta { transition: opacity var(--dur-media) var(--curva); }
.resultado .conta-fechada { margin-top: 0; }

/* Colapso com teclado aberto (JS põe .colapsada na barra) */
.resultado.colapsada {
  min-height: var(--barra-colapsada);
  padding-top: var(--esp-1);
  padding-bottom: calc(var(--esp-1) + env(safe-area-inset-bottom));
}
.resultado.colapsada .conta-fechada,
.resultado.colapsada .aviso { display: none; }
.resultado.colapsada .resposta-frase {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.resultado.colapsada .valor-resposta { font-size: var(--tam-corpo); }

.aviso {
  font-size: var(--tam-apoio);
  color: var(--warning);
}

/* Ações da ficha (Salvar preço + Precificar outro) — terço inferior,
   logo acima da barra de resposta */
/* =============================================================
   REGRA DO SISTEMA: BOTÃO NÃO ENCOSTA EM NADA — 05-08-26

   Preferência declarada do usuário ("não gosto de botões colados assim,
   evite"), e ela tem fundamento: botão é o único elemento da tela que a pessoa
   MIRA. Colado num vizinho, dois problemas somam — o alvo fica ambíguo para o
   olho e o toque errado fica fácil para o polegar.

   O piso do sistema passa a ser 24px em volta de qualquer botão de largura
   cheia. Onde ele separa dois BLOCOS diferentes (ação e conteúdo), 32px.
   Botão dentro de barra de ação (modal) segue no gap próprio — ali eles são
   um par, e afastá-los quebraria o par.
============================================================= */
.acoes-ficha {
  display: flex;
  flex-direction: column;
  gap: var(--esp-5);            /* 24: era 16, e 16 ainda lia como bloco único */
  margin-top: var(--esp-6);     /* 32: separa a ação do conteúdo acima */
}

/* Boas-vindas (estado vazio que convida) */
.vazio-convite h2 {
  font-size: var(--tam-titulo);
  font-weight: var(--peso-forte);
  line-height: var(--ent-titulo);   /* 18px fecha em 24px */
  letter-spacing: 0;                /* era −0,01em: tira o aperto do título */
}

/* -------------------------------------------------------------
   Botão que fica SOLTO no corpo da tela, sem card em volta —
   como o "Cadastrar seu primeiro insumo" do início. Sem isto ele
   nasce encostado no bloco de cima (folga medida: 0px), porque
   .btn não carrega margem nenhuma, e com razão: dentro de modal e
   de barra de ação a margem atrapalharia. O respiro é do CONTEXTO,
   não do botão.
------------------------------------------------------------- */
/* (o respiro de .acao-solta vive junto das outras regras de botão, mais
   abaixo — ver "BOTÃO NÃO ENCOSTA EM NADA") */

/* =============================================================
   Faixa de alertas — o que precisa de atenção hoje.

   Fica no topo do Início. Cada linha é um link para onde a coisa
   se resolve: aviso que não leva à ação é só má notícia.

   URGENTE x ATENÇÃO nunca se distinguem só pela cor — mudam de
   ÍCONE (círculo com "!" x triângulo) e o texto sempre escreve o
   prazo ("venceu ontem", "vence em 3 dias"). Cor é o terceiro
   sinal, não o primeiro.
============================================================= */
.bloco-alertas {
  display: flex;
  flex-direction: column;
  gap: var(--esp-2);
  margin-bottom: var(--esp-4);
}
.alerta {
  display: flex;
  align-items: flex-start;
  gap: var(--esp-3);
  padding: var(--esp-4);
  background: var(--card);
  border: var(--fio-cartao);
  border-left: 3px solid var(--cor-alerta, var(--text-light));
  border-radius: var(--raio-medio);
  box-shadow: var(--sombra-cartao);
  color: var(--text);
  text-decoration: none;
  min-height: var(--alvo-toque);
  transition: box-shadow var(--dur-curta) var(--curva);
}
/* O alerta virou CONTAINER (link + botão de dispensar) em 05-08-26 — antes era
   o próprio <a>. Um botão dentro de um link é markup inválido e o toque fica
   ambíguo; separando, cada alvo faz uma coisa só. */
.alerta { padding: 0; align-items: stretch; }
.alerta-link {
  display: flex;
  align-items: flex-start;
  gap: var(--esp-3);
  flex: 1;
  min-width: 0;
  padding: var(--esp-4);
  color: inherit;
  text-decoration: none;
}
.alerta-dispensar {
  flex-shrink: 0;
  width: var(--alvo-toque);
  display: grid;
  place-items: center;
  background: none;
  border: 0;
  border-left: var(--fio);
  color: var(--text-suave);
  cursor: pointer;
  border-radius: 0 var(--raio-medio) var(--raio-medio) 0;
}
.alerta-dispensar svg { width: 16px; height: 16px; stroke-width: 1.5; }

.alerta[data-nivel="urgente"] { --cor-alerta: var(--danger); }
.alerta[data-nivel="atencao"] { --cor-alerta: var(--warning); }
.alerta-icone { color: var(--cor-alerta); flex-shrink: 0; margin-top: 1px; }
.alerta-texto { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.alerta-texto strong {
  font-size: var(--tam-corpo);
  font-weight: var(--peso-forte);
  line-height: 1.35;
}
.alerta-detalhe {
  font-size: var(--tam-apoio);
  color: var(--text-light);
  line-height: var(--ent-apoio);
}
.alerta .chevron { color: var(--text-light); align-self: center; flex-shrink: 0; }
.alerta-resto {
  font-size: var(--tam-apoio);
  color: var(--text-light);
  padding-left: var(--esp-4);
}

/* -------------------------------------------------------------
   Selo de validade do lote. Mesma regra: a palavra carrega o
   sentido ("venceu há 2 dias"), a cor só reforça.
------------------------------------------------------------- */
.selo-lote {
  display: inline-block;
  font-size: var(--tam-apoio);
  font-weight: var(--peso-normal);
  line-height: var(--ent-apoio);
  padding: 2px var(--esp-2);
  border-radius: var(--raio-pilula);
  background: var(--superficie-2);
  color: var(--text-light);
}
.selo-lote.urgente { color: var(--danger); }
.selo-lote.atencao { color: var(--warning); }
.selo-lote.neutro  { color: var(--text-light); }

/* =============================================================
   Modal — CENTRADO na tela, em qualquer largura.

   Era uma "folha" ancorada embaixo (place-items: end center) e só
   centralizava a partir de 768px. No celular ela subia colada à
   base: ocupava do meio da tela para baixo, cobria a navegação e
   ainda transbordava 12px além da viewport por causa do padding
   inferior — medido, não suposto. Como o modal é a tela inteira do
   momento em que aparece, ancorar embaixo não trazia vantagem
   nenhuma e custava a leitura.

   Agora: centrado sempre, com respiro lateral garantido pelo
   padding do fundo, e raio nos quatro cantos.
============================================================= */
.modal-fundo {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.4);
  z-index: 50;
  display: grid;
  place-items: center;
  /* O respiro lateral vive AQUI, no fundo, e não como margem do modal:
     assim ele vale também quando o conteúdo é alto e o modal encosta
     no limite da altura. safe-area cobre o notch em telas com recorte. */
  padding: var(--esp-4) max(var(--esp-4), env(safe-area-inset-left))
           var(--esp-4) max(var(--esp-4), env(safe-area-inset-right));
}
.modal-fundo[hidden] { display: none; }
.modal {
  background: var(--card);
  border-radius: var(--raio-folha);
  box-shadow: var(--sombra-modal);
  width: 100%;
  max-width: 520px;
  padding: var(--esp-5) var(--esp-4);
  /* 100% da altura do fundo já descontado o padding dele — o modal nunca
     ultrapassa a tela, e o conteúdo rola por dentro. */
  max-height: 100%;
  overflow-y: auto;
  animation: folha var(--dur-media) var(--curva);
}
@keyframes folha {
  from { opacity: 0; transform: translateY(12px) scale(0.98); }
  to   { opacity: 1; transform: none; }
}
.modal h3 {
  font-size: var(--tam-titulo);
  font-weight: var(--peso-forte);
  line-height: var(--ent-titulo);
  letter-spacing: 0;
  margin-bottom: var(--esp-1);
}
.modal .ajuda {
  font-size: var(--tam-apoio);
  color: var(--text-light);
  margin-bottom: var(--esp-4);
}
.modal .campos {
  display: flex;
  flex-direction: column;
  gap: var(--esp-3);
  margin-bottom: var(--esp-5);   /* 24px entre campos e ações */
}
.modal .acoes { display: flex; gap: var(--esp-3); }
.modal .acoes .btn { flex: 1; }

/* =============================================================
   Toast — consequência, nunca "Criado." seco. Acima da nav.
============================================================= */
#toasts {
  position: fixed;
  left: var(--esp-3); right: var(--esp-3);
  bottom: calc(var(--nav-h) + var(--esp-3) + env(safe-area-inset-bottom));
  z-index: 60;
  display: flex;
  flex-direction: column;
  gap: var(--esp-2);
  pointer-events: none;
}
.toast {
  background: var(--card);
  border: var(--fio-cartao);
  border-left: 4px solid var(--text-light);
  border-radius: var(--raio);
  box-shadow: var(--sombra-modal);
  padding: var(--esp-4) var(--esp-5);
  font-size: var(--tam-corpo);
  line-height: 1.5;
  pointer-events: auto;
  /* TRANSITION, não keyframes — regra dura para toast (05-08-26).
     Keyframes REINICIAM do zero quando interrompidos, e toast é justamente o
     componente que aparece em sequência: o segundo entrando enquanto o
     primeiro ainda sai fazia os dois pularem. Transição retarget suave.
     O JS adiciona `.vem` no quadro seguinte à inserção — ver toast() no
     shell.js. */
  opacity: 0;
  transform: translateY(8px);
  transition: opacity var(--dur-curta) var(--curva),
              transform var(--dur-curta) var(--curva);
}
.toast.vem { opacity: 1; transform: none; }
.toast.sai { opacity: 0; transform: translateY(4px); }
.toast.ok { border-left-color: var(--success); }
.toast.erro { border-left-color: var(--danger); }
/* Toast com ação ("Desfazer"): texto + botão na mesma linha */
.toast.com-acao {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--esp-3);
}
.toast-acao {
  flex-shrink: 0;
  background: none;
  border: 0;
  color: var(--text);
  font-size: var(--tam-corpo);
  font-weight: var(--peso-forte);
  text-decoration: underline;
  cursor: pointer;
  padding: var(--esp-2);
  margin: calc(-1 * var(--esp-2));
  min-height: var(--alvo-toque);
}
@keyframes entra {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: none; }
}

.sr {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* =============================================================
   Apoio 13px — entrelinha fecha em 20px e tracking levemente
   positivo (--track-apoio). Texto corrido de apoio deste arquivo;
   rótulos de navegação e pílulas ficam de fora de propósito.
============================================================= */
.topo .subtitulo, .conta-fechada, .registro-rotulo, .travado-rotulo,
.travado-destrave, .item-nome .unidade, .item-qtd label, .item-sub .custo-unit,
.campo label, .campo-ajuda, .campo-erro, .vazio, .aviso, .modal .ajuda,
.secao-cab .secao-resumo, .secao-cab .contador {
  line-height: var(--ent-apoio);
  letter-spacing: var(--track-apoio);
}

/* =============================================================
   QUADRADINHO DE ÍCONE — o elemento-assinatura do sistema

   Um ícone de traço solto sobre o cartão branco é o que fazia a tela
   parecer um formulário. Dentro de um quadrado tintado com a cor da
   própria área, ele vira âncora visual: o olho acha o bloco antes de
   ler o rótulo, e a cor repete a da aba (memória cromática).

   O tint é claro de propósito (1,14–1,24:1 contra o cartão): ele
   precisa ser visto como superfície, não competir com o número. O
   contraste que importa é o do ÍCONE dentro dele — 4,76 a 7,06:1,
   bem acima do mínimo de 3:1 exigido para elemento gráfico.
============================================================= */
/* SEM FUNDO — 05-08-26, pedido do usuário: o quadradinho tintado atrás de cada
   ícone dava um ar genérico de template. O ícone agora é só o traço.

   O que substitui o quadradinho como âncora visual: o ícone cresce (20 → 26px)
   e o traço afina (1,9 → 1,5). Ícone grande e fino ocupa a mesma área óptica
   que um pequeno dentro de caixa, sem o peso do bloco de cor. A cor da área
   continua ali — mudou de SUPERFÍCIE para TRAÇO.

   A classe segue chamada `.icone-caixa` porque é o que o markup de todas as
   telas usa; renomear seria mexer em 30 chamadas para ganhar nada. */
.icone-caixa {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  color: var(--cor-area);
}
.icone-caixa svg {
  width: 26px;
  height: 26px;
  stroke-width: 1.5;
}
.icone-caixa.sm svg { width: 20px; height: 20px; }

/* A caixa herda a cor da área em que está; estes modificadores deixam
   fixar uma área específica (grade de módulos, cartões de resumo). */
.icone-caixa[data-cor="inicio"]     { --cor-area: var(--aba-inicio);     --cor-area-fundo: var(--aba-inicio-fundo); }
.icone-caixa[data-cor="precificar"] { --cor-area: var(--aba-precificar); --cor-area-fundo: var(--aba-precificar-fundo); }
.icone-caixa[data-cor="financeiro"] { --cor-area: var(--aba-financeiro); --cor-area-fundo: var(--aba-financeiro-fundo); }
.icone-caixa[data-cor="relatorios"] { --cor-area: var(--aba-relatorios); --cor-area-fundo: var(--aba-relatorios-fundo); }
.icone-caixa[data-cor="cadastros"]  { --cor-area: var(--aba-cadastros);  --cor-area-fundo: var(--aba-cadastros-fundo); }

/* =============================================================
   TENDÊNCIA — o selo de variação (▲ +12%)

   A cor NUNCA carrega o sentido sozinha: o selo traz a seta (▲/▼) E o
   sinal aritmético no número. Quem não distingue verde de vermelho lê
   a direção na seta.

   E há uma regra de negócio embutida: em despesa, subir é RUIM. Por
   isso o tom é `bom`/`ruim`, não `sobe`/`desce` — quem monta a tela
   decide o significado, o componente só pinta.
============================================================= */
.tendencia {
  font-family: var(--fonte-numero);
  letter-spacing: var(--track-numero);
  display: inline-flex;
  align-items: center;
  gap: 3px;
  flex-shrink: 0;
  font-size: var(--tam-apoio);
  font-weight: var(--peso-normal);
  line-height: 1;
  font-variant-numeric: tabular-nums;
  padding: 4px var(--esp-2);
  border-radius: var(--raio-pilula);
  background: var(--superficie-2);
  color: var(--text-light);
  white-space: nowrap;
}
.tendencia svg { width: 12px; height: 12px; }
.tendencia.bom  { background: color-mix(in srgb, var(--success) 12%, var(--card)); color: var(--success); }
.tendencia.ruim { background: color-mix(in srgb, var(--danger) 12%, var(--card));  color: var(--danger); }

/* =============================================================
   SEGMENTADO — período (Hoje · Semana · Mês)

   Substitui a fileira de pílulas soltas do .filtro-periodo. A diferença
   não é enfeite: pílulas soltas não dizem que as opções são EXCLUSIVAS
   entre si. Um trilho único com o selecionado deslizando dentro diz.
============================================================= */
.segmentado {
  display: inline-flex;
  gap: 2px;
  padding: 3px;
  background: var(--superficie-2);
  border-radius: var(--raio-pilula);
  max-width: 100%;
  overflow-x: auto;
  scrollbar-width: none;
}
.segmentado::-webkit-scrollbar { display: none; }
.segmentado button {
  flex-shrink: 0;
  min-height: 34px;
  padding: 0 var(--esp-3);
  border: 0;
  border-radius: var(--raio-pilula);
  background: none;
  color: var(--text-light);
  font-size: var(--tam-apoio);
  font-weight: var(--peso-normal);
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--dur-curta) var(--curva-cor),
              color var(--dur-curta) var(--curva-cor);
}
/* selecionado: superfície própria + peso + cor da área. Três sinais. */
.segmentado button[aria-pressed="true"] {
  background: var(--card);
  color: var(--cor-area);
  font-weight: var(--peso-forte);
  box-shadow: var(--sombra-cartao);
}

/* =============================================================
   BARRA DE AÇÃO — o "adicionar" fica ACIMA da lista, nunca abaixo

   Mudança de 05-08-26. O botão era o último elemento da seção: com a
   lista cheia, a ação mais frequente da tela ficava a uma rolagem
   inteira de distância. Em cima, ela está sempre a um toque.

   A busca vem junto e logo abaixo do botão, porque a ordem de uso é
   essa: quem chega ou adiciona algo novo, ou procura algo que já existe.
============================================================= */
.barra-acao {
  display: flex;
  flex-direction: column;
  gap: var(--esp-3);
  margin-bottom: var(--esp-4);
}
.barra-acao .busca { margin-bottom: 0; }

/* Botão de ação no topo da ÁREA (não de uma seção) — o "Lançar" do
   financeiro. Ele separa DOIS blocos (o cartão-resposta acima, as seções
   abaixo), então leva o respiro maior dos dois lados. */
.btn.acao-topo {
  width: 100%;
  margin-top: var(--esp-5);
  margin-bottom: var(--esp-6);
}

/* Botão largo SOLTO no corpo da tela (o "Cadastrar seu primeiro insumo", o
   "Registrar produção"). Fora de um container de ações, ele é um bloco por si
   e leva 32px dos dois lados.

   Cheguei a escrever aqui uma "rede de segurança" com `.btn.largo + *` e
   `:not()` de seletor complexo — descartada: pegaria elementos dentro de modal
   e de barra de ação, onde os botões são um PAR e afastá-los quebra o par.
   Regra ampla demais em CSS conserta uma tela e estraga três. */
.btn.acao-solta { margin: var(--esp-6) 0; }

/* Em tela larga o botão não precisa esticar: ele e a busca dividem a linha,
   com a busca ficando com a folga (é ela que cresce bem). */
@media (min-width: 620px) {
  .barra-acao {
    flex-direction: row-reverse;   /* busca à esquerda, ação à direita */
    align-items: center;
  }
  .barra-acao .btn.largo { width: auto; flex-shrink: 0; }
  .barra-acao .busca { flex: 1; }
  .btn.acao-topo { width: auto; }
}

/* =============================================================
   BUSCA — campo com lupa embutida (o topo do print)

   Só aparece onde há o que filtrar de verdade: a partir de 6 itens
   (MINIMO_PARA_BUSCAR no shell.js). Busca sobre lista de 3 é ruído
   que rouba a primeira dobra.
============================================================= */
.busca {
  position: relative;
  margin-bottom: var(--esp-4);
}
.busca .input {
  padding-left: 44px;
  border-radius: var(--raio-pilula);
  background: var(--card);
}
.busca .lupa {
  position: absolute;
  left: var(--esp-4);
  top: 50%;
  transform: translateY(-50%);
  width: 18px;
  height: 18px;
  color: var(--text-suave);
  pointer-events: none;
}

/* =============================================================
   >= 768px — duas colunas; a barra vira painel lateral em repouso
   (sem sombra: sombra é só do que flutua)
============================================================= */
@media (min-width: 768px) {
  :root { --barra-h: 0px; }

  .conteudo {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 320px;
    align-items: start;
    gap: var(--esp-5);
    padding: var(--esp-5) var(--esp-5) var(--esp-6);
  }
  .coluna-principal { min-width: 0; }

  /* painel lateral em repouso: borda dá o relevo, sem sombra */
  .resultado {
    position: sticky;
    top: 84px;
    bottom: auto;
    min-height: 0;
    justify-content: flex-start;
    gap: var(--esp-2);
    border: var(--fio);
    border-radius: var(--raio);
    box-shadow: none;
    padding: var(--esp-4);
  }

  /* campos podem dividir a linha com folga de tela */
  .grade-campos { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  /* Item deixa de ser card e vira linha */
  .item {
    grid-template-columns: minmax(0, 1fr) 170px 130px var(--alvo-toque);
    gap: var(--esp-3);
  }
  .item-nome { grid-column: auto; }
  .item-remover { grid-column: auto; }

  #toasts { left: auto; width: 360px; }

  /* O modal não aparece aqui de propósito: centrado e com raio nos quatro
     cantos agora é o padrão em QUALQUER largura, não um ganho de tela grande.
     Repetir as regras aqui só criaria dois lugares para manter. */
}

/* =============================================================
   >= 1100px — mais respiro
============================================================= */
@media (min-width: 1100px) {
  .conteudo { grid-template-columns: minmax(0, 1fr) 380px; gap: var(--esp-6); }
  .topo { padding: var(--esp-3) var(--esp-5); }
}

/* =============================================================
   HOVER SÓ ONDE HÁ PONTEIRO DE VERDADE — 05-08-26

   Em aparelho de toque o navegador dispara :hover no toque e DEIXA O ESTADO
   GRUDADO até a pessoa tocar em outro lugar. Num app mobile-first isso não é
   detalhe estético: o cartão fica aceso depois que o dedo saiu, e o botão
   parece continuar pressionado.

   `@media (hover: hover) and (pointer: fine)` só casa em quem tem mouse ou
   trackpad. Todas as regras de :hover do sistema vivem AQUI dentro — e por
   estarem no fim do arquivo, mantêm a precedência que tinham antes.

   `:active` e `:focus-visible` ficam de fora deste bloco de propósito: são os
   estados que o toque e o teclado realmente usam.
============================================================= */
@media (hover: hover) and (pointer: fine) {

  /* ---- de sopphus.css ---- */
  a.cartao:hover, button.cartao:hover { box-shadow: var(--sombra-elevada); }
  :root[data-tema="escuro"] a.cartao:hover,
  :root[data-tema="escuro"] button.cartao:hover { background: var(--superficie-2); }
  .seletor-opcao:hover { background: var(--superficie-2); }
  .item-remover:hover { color: var(--danger); border-color: var(--danger); }
  .input:hover:not(:focus) { background-color: var(--card); border-color: var(--border); }
  .btn:not(.fantasma):not(.perigo):hover { box-shadow: 0 4px 16px rgba(229, 143, 168, 0.45); }
  .btn.fantasma:hover { border-color: var(--cor-area); color: var(--cor-area); }
  .alerta:hover { box-shadow: var(--sombra-elevada); }
  .alerta-dispensar:hover { color: var(--danger); background: var(--superficie-2); }

  /* ---- de shell.css ---- */
  .painel-avisos-limpar:hover { text-decoration: underline; }
  .painel-avisos .alerta:hover { background: var(--superficie-2); box-shadow: none; }
  .btn-topo:hover { border-color: var(--rosa); color: var(--rosa-texto); }
  a.card-resumo:hover { box-shadow: var(--sombra-elevada); border-color: var(--rosa); }
  .card-modulo:hover { border-color: var(--rosa); box-shadow: var(--sombra-elevada); }
  .card-modulo[aria-disabled="true"]:hover { border-color: var(--border); box-shadow: none; }
  .campo-com-icone .senha-revelar:hover { color: var(--cor-area); }
  .link-esqueci:hover { text-decoration: underline; }
  .btn-conta:hover { border-color: var(--rosa); color: var(--rosa-texto); }

  /* A sidebar só existe a partir de 768px — o hover dela precisa continuar
     dentro dessa condição, senão a regra passa a valer numa largura onde o
     elemento está `display: none` (inofensivo hoje, pegadinha amanhã). */
  @media (min-width: 768px) {
    .nav-lateral .nav-item:hover { color: var(--text); background: var(--superficie-2); }
  }
}

/* ---- :active e :focus FICAM FORA da guarda ----
   Estes são os estados que o TOQUE e o TECLADO usam. Ao mover os :hover para a
   media query, três regras vieram junto por estarem no mesmo seletor
   (`.item-remover:hover, .item-remover:active`) — e isso teria matado o
   feedback de toque justamente no aparelho que só tem toque. Reescritas aqui. */
.item-remover:active { color: var(--danger); border-color: var(--danger); }
.btn.fantasma:active { border-color: var(--cor-area); color: var(--cor-area); }
.btn-conta:active { border-color: var(--rosa); color: var(--rosa-texto); }
