:root{
--font-sans:'Space Grotesk',system-ui,sans-serif;
--font-mono:'JetBrains Mono',ui-monospace,monospace;

/* escala tipografica — nenhum outro valor de font-size e legal */
--fs-tiny:10px;--fs-xs:11px;--fs-sm:12px;--fs-base:13px;--fs-md:15px;
--fs-lg:18px;--fs-xl:22px;--fs-2xl:28px;--fs-hero:44px;

/* espacamento */
--sp-1:2px;--sp-2:4px;--sp-3:6px;--sp-4:8px;--sp-5:10px;--sp-6:12px;
--sp-7:14px;--sp-8:16px;--sp-9:20px;--sp-10:24px;
--sp-12:32px;--sp-14:40px;--sp-16:48px;

--r-sm:4px;--r1:6px;--r2:10px;--r3:14px;--r-pill:999px;

/* superficies — tema claro.
   Ordem semantica preservada do sistema legado (219 call sites vivos):
   bg3 = superficie elevada (card/modal/login), bg0 = fundo de pagina,
   bg1 = preenchimento sutil, bg2 = preenchimento forte (chip, th, input).
   NAO reordenar: o doc de design usa bg1 como superficie, esta base nao. */
--bg0:#FAF8F3;--bg1:#F4F1E8;--bg2:#E9E4D6;--bg3:#FFFFFF;
--line:#DCD6C7;--line2:#EDE9DE;

/* texto — tres niveis */
--tx0:#0E1330;--tx1:#4A4F66;--tx2:#60657A;--tx-inv:#F2EEE3;

/* marca */
--pri:#0E1330;--pri-fg:#F2EEE3;--pri-hover:#1B2246;
--accent:var(--tx0);

/* sidebar — SEGUE O TEMA (01/08/2026; antes era navy nos dois).
   No claro e um painel bone um degrau abaixo do canvas, com tinta navy.
   A regra anterior ("sidebar navy sempre, logo sempre bone") amarrava uma
   constante na outra: so era segura enquanto o fundo nao mudasse, e ninguem
   percebia quando mudava — o logo ficou invisivel duas vezes por isso. O
   contraste agora e expresso em var() sobre --sb-bg/--sb-tx0 (bloco de
   aliases abaixo), entao nao depende de ninguem lembrar. */
--sb-bg:#F4F1E8;--sb-tx0:#0E1330;
--sb-tx1:#4A4F66;--sb-tx2:#5E637A;
--sb-fill:#0E1330;--sb-line:#DCD6C7;

/* semantica financeira */
/* T2 (01/08/2026): #1C7A54 dava 4.17:1 sobre --bg2 (#E9E4D6) — o fundo de th,
   chip e linha de tabela, que e onde .tm.pos mais aparece. Escurecido. */
--green:#196B4A;--green-l:#E3F1E9;--green-b:#A8D6BF;
--red:#A82A20;--red-l:#FBE9E6;--red-b:#E8B3AC;
--amber:#8A5B08;--amber-l:#FBF0DC;--amber-b:#E2C48A;
/* --gold vive no selo PRO, em 10px: #8F6E1C reprovava nesse tamanho. */
--gold:#6F5410;--sage:#5E8674;--purple:#5B4B9B;--teal:#1F6F79;
--yellow:var(--gold);

--sh1:0 1px 2px rgba(14,19,48,.06);
--sh2:0 4px 14px rgba(14,19,48,.09);
--sh3:0 18px 48px rgba(14,19,48,.16);
--focus:#0E1330;--focus-inv:#F2EEE3;
}

/* Escuro: GRAFITE, nao navy (01/08/2026 — decisao final depois de quatro
   tentativas de salvar o navy escuro).
   Por que trocou: navy escuro e um azul dessaturado por definicao, e todo
   ajuste caia num dos dois lados — clarear deixava leitoso, saturar deixava
   berrante. Grafite e neutro de proposito: nao compete com cor nenhuma, entao
   verde/vermelho/ambar ficam em saturacao cheia sem brigar com o fundo, e e
   isso que tira o aspecto desbotado. O navy continua sendo a marca
   (--color-navy, tema claro, login, lockups); so deixou de ser a tinta do
   escuro.
   Duas regras que sobreviveram das tentativas anteriores:
   1. --bg2 e a superficie critica — fundo de th/chip/input E das linhas de
      tabela, onde badge e numero pousam. Ao mexer nela, reconferir --tx2 e os
      tres badges sobre ela.
   2. Tint (-l) fica em .11. Clarear o texto semantico sem escurecer o tint
      sobe o fundo junto e o badge perde contraste: foi assim que .bdg.vencido
      caiu para 2.7:1. */
[data-theme="dark"]{
/* grafite levemente quente, para conversar com o bone da marca */
--bg0:#1A1B1D;--bg1:#222325;--bg2:#2B2D30;--bg3:#232426;
--line:#3D3F43;--line2:#2F3134;
--tx0:#F6F3EA;--tx1:#CFCBC2;--tx2:#A3A099;--tx-inv:#1A1B1D;
--pri:#F6F3EA;--pri-fg:#1A1B1D;--pri-hover:#FFFFFF;
/* a sidebar sobe um degrau acima do canvas, nunca desce — senao vira um
   buraco na lateral da tela */
--sb-bg:#202123;--sb-tx0:#F6F3EA;
--sb-tx1:rgba(246,243,234,.82);--sb-tx2:rgba(246,243,234,.70);
--sb-fill:#F6F3EA;--sb-line:rgba(246,243,234,.14);
/* saturacao cheia: o fundo neutro aguenta */
--green:#3FD494;--green-l:rgba(63,212,148,.11);--green-b:rgba(63,212,148,.44);
--red:#FF8B7C;--red-l:rgba(255,139,124,.11);--red-b:rgba(255,139,124,.44);
--amber:#F2B33F;--amber-l:rgba(242,179,63,.11);--amber-b:rgba(242,179,63,.42);
--gold:#DFBA63;--sage:#7FC5A4;--purple:#AE9BF5;--teal:#55C6D6;
--sh1:0 1px 2px rgba(0,0,0,.34);
--sh2:0 4px 14px rgba(0,0,0,.42);
--sh3:0 18px 48px rgba(0,0,0,.52);
--focus:#F6F3EA;--focus-inv:#1A1B1D;
}

/* A densidade real deste app NAO passa por token: sao as regras
   body[data-density="compact"|"dense"] mais abaixo neste arquivo, que ajustam
   th/td/.bgh/.tm/.bdg/.tw-h/.sc diretamente. Os valores validos continuam sendo
   normal|compact|dense (CHECK de profiles.density, migration 004). */

/* ==== COMPATIBILIDADE — nomes que o app ja consome ====================
   Regra: nome com uso > 0 nunca desaparece. O valor pode mudar a vontade,
   o NOME nao — sem o alias a var() cai pra unset e a propriedade (borda,
   sombra, cor) some sem erro no console. */
:root{
--tx:var(--tx0);--tx3:var(--tx2);--tx-sub:var(--tx2);

--br:var(--line);--brd:var(--line);--bd:var(--line);--bbg:var(--bg2);--ibg:var(--bg2);
--hv:rgba(14,19,48,.05);--ov:rgba(14,19,48,.45);--scr:var(--bg2);

--grn:var(--green);--greenL:var(--green-l);
--org:var(--amber);--orange:var(--amber);--orangeL:var(--amber-l);
--warn:var(--amber);--redL:var(--red-l);
--blue:var(--pri);--blueL:rgba(14,19,48,.08);--priL:var(--blueL);
--yellow:var(--gold);--yellowL:rgba(111,84,16,.10);
--coral:#B4543F;

--r-full:50%;
--sh:var(--sh1);--sh-dp:var(--sh2);--sh-toast:var(--sh2);
--sh-toggle:var(--sh1);--sh-modal:var(--sh3);

/* --t continua existindo (nome com uso nunca some), mas NAO deve mais ser usado
   como `transition:var(--t-ui)`. Aquilo expande para `transition:.18s cubic-bezier(...)`
   e, sem nome de propriedade, o CSS assume `all`: o browser passa a vigiar toda
   propriedade animavel do elemento. Em .card, que aparece as dezenas numa tela,
   isso custa em dois momentos — qualquer mudanca de estilo vira 180ms de
   animacao (a tela parece esmaecer e reassentar), e o hover de box-shadow entra
   na mesma transicao `all` enquanto se rola a pagina, competindo com o scroll.
   --t-ui nomeia so o que de fato muda em hover/foco. Mesma duracao, mesma
   curva, mesmo efeito visual — sem o `all`. */
--t:.18s cubic-bezier(.25,.1,.25,1);
--t-ui:background-color .18s cubic-bezier(.25,.1,.25,1),border-color .18s cubic-bezier(.25,.1,.25,1),color .18s cubic-bezier(.25,.1,.25,1),box-shadow .18s cubic-bezier(.25,.1,.25,1),transform .18s cubic-bezier(.25,.1,.25,1),opacity .18s cubic-bezier(.25,.1,.25,1);

--ff-display:var(--font-sans);--ff-body:var(--font-sans);
--fs-body:var(--fs-base);--fs-label:var(--fs-sm);--fs-section:var(--fs-md);
--fs-caption:var(--fs-xs);--fs-micro:var(--fs-tiny);
--fw-regular:400;--fw-medium:500;--fw-semibold:600;--fw-bold:700;--fw-black:800;

--sp-11:26px;--sp-13:36px;--sp-15:44px;

--sb-tx:var(--sb-tx0);--sb-br:var(--sb-line);
--sb-on:var(--sb-fill);--sb-ni:var(--sb-tx1);
--sb-ni-hv:var(--sb-tx0);
/* Pilula do item ativo: fundo --sb-fill, tinta --sb-ni-on. Era var(--sb-tx0),
   que funcionava enquanto --sb-fill era um veu translucido; com --sb-fill
   solido isso da navy sobre navy no claro. Apontando para --sb-bg, a tinta e
   sempre o oposto do preenchimento, nos dois temas. */
--sb-ni-on:var(--sb-bg);
/* hover: veu de tinta no claro, veu de luz no escuro. E o unico --sb-* que
   precisa de valor literal por tema, porque nao deriva de nenhum token. */
--sb-hv:rgba(14,19,48,.055);--navyM:var(--pri-hover);
/* Logo da sidebar: contrasta com o painel por construcao, em vez de depender
   de alguem lembrar que "ali o logo e sempre bone". */
--sb-logo-shield:var(--sb-tx0);--sb-logo-stroke:var(--sb-bg);
--sb-logo-inner:var(--sb-tx0);--sb-logo-v:var(--sb-bg);

--color-primary:var(--pri);--color-navy:#0E1330;--color-bone:#F2EEE3;
--color-bg:var(--bg0);--color-surface:var(--bg1);--color-border:var(--line);
--color-text:var(--tx0);--color-text-muted:var(--tx2);
--color-success:var(--green);--color-danger:var(--red);--color-warning:var(--amber);
}

[data-theme="dark"]{
--hv:rgba(255,255,255,.07);--ov:rgba(0,0,0,.62);
--blueL:rgba(246,243,234,.12);--yellowL:rgba(223,186,99,.16);
/* contraparte do --sb-hv claro: sobre painel grafite o veu volta a ser luz */
--sb-hv:rgba(246,243,234,.09);
}
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}

/* .kbd — tecla de atalho. Unica peca do doc de design que nao tinha
   equivalente no vocabulario existente (11 copias inline em router.js). */
.kbd{display:inline-block;min-width:22px;padding:3px var(--sp-4);background:var(--bg2);color:var(--tx0);border:1px solid var(--br);border-bottom-width:2px;border-radius:var(--r-sm);font-family:var(--font-mono);font-size:var(--fs-caption);font-weight:var(--fw-medium);text-align:center;line-height:1.4}


/* P4: Skeleton loading animation */
@keyframes shimmer{0%{background-position:-200px 0}100%{background-position:200px 0}}
.skeleton{background:linear-gradient(90deg,var(--bg1) 25%,var(--bg2) 50%,var(--bg1) 75%);background-size:400px 100%;animation:shimmer 1.5s infinite;border-radius:var(--r2);height:20px;margin:4px 0}
/* P4: Screen reader only text */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}
/* Lucide Icons */
.lc{width:18px;height:18px;stroke-width:1.75;flex-shrink:0}
.ni .lc{width:18px;height:18px;stroke-width:1.75}
.btn .lc,.bgh .lc{width:14px;height:14px;stroke-width:2}
.bi .lc{width:18px;height:18px;stroke-width:1.75}
.lc-lg{width:24px;height:24px;stroke-width:1.5}
.lc-sm{width:14px;height:14px;stroke-width:2}
.search-wrap{position:relative}.search-wrap .lc-search{position:absolute;left:10px;top:50%;transform:translateY(-50%);width:14px;height:14px;color:var(--tx1);pointer-events:none}.search-wrap .fi{padding-left:32px}
body{font-family:var(--ff-body);background:var(--bg0);color:var(--tx0);line-height:1.47;-webkit-font-smoothing:antialiased;overflow:hidden;height:100vh}
::selection{background:var(--blue);color:var(--pri-fg)}
.app{display:flex;height:100vh}

/* Sidebar */
.sb{width:250px;min-width:250px;background:var(--sb-bg);border-right:1px solid var(--sb-br);display:flex;flex-direction:column;z-index:100;transition:background .2s,width .22s ease,min-width .22s ease}
.app.sbc .sb{width:0;min-width:0;padding:0;border-right:0;overflow:hidden}
.sb-h{padding:20px 16px 8px;display:flex;align-items:center;gap:10px;cursor:pointer}
.sb-logo{width:36px;height:36px;border-radius:var(--r1);display:flex;align-items:center;justify-content:center}
.sb-nm{font-family:var(--ff-display);font-size:var(--fs-section);font-weight:var(--fw-bold);line-height:1.2;color:var(--sb-tx);letter-spacing:.3px}.sb-sub{font-size:var(--fs-caption);color:var(--sb-tx2)}
.sb-nav{padding:8px;flex:1;overflow-y:auto}.sb-nav::-webkit-scrollbar{width:4px}.sb-nav::-webkit-scrollbar-thumb{background:var(--scr);border-radius:2px}
.sb-sec{margin-bottom:16px}.sb-st{font-size:var(--fs-micro);font-weight:var(--fw-bold);color:var(--sb-tx2);text-transform:uppercase;letter-spacing:.22em;padding:0 var(--sp-4);margin-bottom:var(--sp-3);font-family:var(--font-mono)}
.label-mono{font-family:var(--font-mono);font-size:var(--fs-label);text-transform:uppercase;letter-spacing:.22em;font-weight:var(--fw-medium);color:var(--tx1)}
.ni{display:flex;align-items:center;gap:var(--sp-4);padding:7px var(--sp-5);border-radius:var(--r1);cursor:pointer;color:var(--sb-ni);font-size:var(--fs-body);font-weight:var(--fw-medium);transition:background .15s,color .15s,padding-left .15s;border:none;background:none;width:100%;text-align:left;font-family:inherit;text-decoration:none;box-sizing:border-box}
.ni:hover{background:var(--sb-hv);color:var(--sb-ni-hv)}.ni:hover:not(.on){padding-left:14px}.ni.on{background:var(--sb-on);color:var(--sb-ni-on)}.ni .ic{font-size:16px;width:22px;text-align:center}
/* T11: item de modulo fora do plano — visivel, discreto, ainda clicavel. */
/* M2: esmaece o rotulo e o icone, NAO o selo — senao o proprio aviso de "fora
   do plano" some junto com o item que ele explica. Por isso a opacidade vai nos
   filhos, e nao no .ni inteiro. */
.ni.ni-off{color:var(--sb-tx2)}
.ni.ni-off .lc{opacity:.5}
.ni.ni-off:hover{color:var(--sb-tx1)}
/* O selo carrega o aviso, então ele é o único pedaço do item fora do plano que
   NÃO esmaece. opacity:1 aqui não basta sozinho: opacity num ancestral cria
   contexto de composição e o filho não escapa dele, e um style inline com
   opacity vence esta regra de qualquer forma. Por isso o layout do selo mora
   aqui e o JS não escreve style nele. */
.ni-selo{pointer-events:none;opacity:1;margin-left:auto}
.sb-ft{padding:8px;border-top:1px solid var(--sb-br)}
/* Selo de regime (ONDA 1 — as 2 lentes): diz em qual regime a página lê os números.
   Caixa = só pago, pela data de pagamento. Competência = por vencimento, todos os status.
   Sem isso o mesmo lançamento aparece em meses diferentes no DRE e no Mapa do Caixa e
   parece erro — era o que fazia até a IA chamar atraso de pagamento de "anomalia". */
/* Sem opacity: ela compunha --tx2 com o canvas e derrubava este selo para
   3.59:1 em 11px. O selo diz em qual regime a página lê os números, que é
   informação e não enfeite — se precisar ser mais discreto, isso é trabalho de
   token de cor. Terceira ocorrência do mesmo padrão (ver .sb-ver e
   .sb-sig-fam, corrigidos na mesma passada). */
.regime-selo{font-size:11px;font-weight:600;color:var(--tx2);border:1px solid var(--tx2);border-radius:999px;padding:3px 11px;margin:0 0 12px;display:inline-block}
/* Assinatura de família (padrão de marca Viktus): versão + "Um produto Viktus".
   O wordmark passou a seguir .logo-light/.logo-dark de fato em 01/08/2026 (eram
   duas <img>, uma por tema). Antes este comentário dizia que ele seguia, mas a
   marcação tinha uma <img> só, fixa na versão bone — o que não aparecia porque
   a sidebar era navy nos dois temas e bone contrastava sempre. */
.sb-sig{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:6px 10px 2px;margin-top:4px;border-top:1px solid var(--sb-br)}
/* Sem opacity aqui. Ela multiplicava sobre --sb-tx2 e derrubava texto de 10px
   para 3.6:1 — rebaixar rótulo é trabalho de token de cor, que o contraste
   acompanha, e não de opacidade, que ninguém remede depois. */
.sb-ver{font-size:10px;color:var(--sb-tx2);font-family:var(--font-mono,'JetBrains Mono',monospace)}
.sb-sig-fam{display:flex;align-items:center;gap:6px;font-size:11px;font-weight:500;color:var(--sb-tx2)}
.sb-sig-fam img{height:14px;width:auto}.sy{display:flex;align-items:center;gap:8px;padding:6px 10px;border-radius:var(--r1);font-size:12px;color:var(--sb-tx2);cursor:pointer}.sy:hover{background:var(--sb-hv)}
.sd{width:8px;height:8px;border-radius:50%;background:var(--sb-tx2)}.sd.ok{background:var(--green)}.sd.er{background:var(--red)}.sd.ig{background:var(--orange);animation:pu 1s infinite}@keyframes pu{0%,100%{opacity:1}50%{opacity:.4}}

/* Main */
.main{flex:1;display:flex;flex-direction:column;overflow:hidden}
.top{height:56px;min-height:56px;border-bottom:1px solid var(--br);display:flex;align-items:center;justify-content:space-between;padding:0 20px}
.top-l{display:flex;align-items:center;gap:var(--sp-6)}.top-t{font-family:var(--ff-display);font-size:20px;font-weight:700}
.top-r{display:flex;align-items:center;gap:6px}
.ms{display:flex;align-items:center;background:var(--bg1);border-radius:var(--r1);padding:2px}
.ms button{border:none;background:none;padding:8px 12px;border-radius:6px;cursor:pointer;color:var(--tx1);font-size:16px;font-family:inherit;min-width:36px;min-height:36px;display:inline-flex;align-items:center;justify-content:center}.ms button:hover{color:var(--tx0);background:var(--hv)}
.ms .cur{font-size:13px;font-weight:600;color:var(--tx0);padding:4px 8px;min-width:100px;text-align:center}
.ys select{background:var(--bg1);border:1px solid var(--br);border-radius:6px;padding:4px 8px;font-size:13px;font-weight:600;color:var(--tx0);font-family:inherit;outline:none}
.bi{width:32px;height:32px;border-radius:var(--r1);border:none;background:none;color:var(--tx1);cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:17px;transition:var(--t-ui)}.bi:hover{background:var(--hv);color:var(--tx0)}
::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--br);border-radius:3px}::-webkit-scrollbar-thumb:hover{background:var(--tx2)}
.ct{flex:1;overflow-y:auto;padding:var(--sp-10)}

/* Components */
.cg{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:var(--sp-6);margin-bottom:var(--sp-10)}
.card{background:var(--bg3);border:1px solid var(--br);border-radius:var(--r3);padding:var(--sp-8);transition:var(--t-ui);box-shadow:var(--sh)}.card:hover{box-shadow:0 4px 12px rgba(15,23,42,.10),0 1px 4px rgba(15,23,42,.06)}
.card-ic{width:36px;height:36px;border-radius:var(--r2);display:flex;align-items:center;justify-content:center;font-size:22px;line-height:1;margin-bottom:8px}
.card-lb{font-size:var(--fs-label);font-weight:var(--fw-medium);color:var(--tx1);margin-bottom:var(--sp-2)}
.card-v{font-family:'JetBrains Mono',monospace;font-size:28px;font-weight:var(--fw-semibold);line-height:1.1;font-variant-numeric:tabular-nums}.card-v.pos{color:var(--green)}.card-v.neg{color:var(--red)}
/* M1: valor monetario e SEMPRE mono — o hero saia em proporcional e as casas
   nao alinhavam com os outros tres cards. */
.card-ic .lc{width:18px;height:18px;stroke-width:1.75}
.card-v-hero{font-family:'JetBrains Mono',monospace;font-size:32px;font-weight:700;line-height:1.1;font-variant-numeric:tabular-nums}
.sr{display:flex;gap:10px;margin-bottom:18px;flex-wrap:wrap}.sc{flex:1;min-width:160px;background:var(--bg3);border:1px solid var(--br);border-radius:var(--r2);padding:12px 16px;text-align:center}.sc .lb{font-size:11px;color:var(--tx1);font-weight:500}.sc .vl{font-family:'JetBrains Mono',monospace;font-size:18px;font-weight:600;margin-top:3px;font-variant-numeric:tabular-nums}
.tw{background:var(--bg3);border:1px solid var(--br);border-radius:var(--r2);overflow:hidden;margin-bottom:20px}
.tw-h{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid var(--br);flex-wrap:wrap;gap:8px}.tw-h h3{font-size:14px;font-weight:600}
table{width:100%;border-collapse:collapse}
th{font-family:var(--ff-body);font-size:10px;text-transform:uppercase;letter-spacing:.5px;font-weight:700;color:var(--tx1);text-align:left;padding:var(--sp-4) var(--sp-6);border-bottom:1px solid var(--br);background:var(--bg1);cursor:pointer;user-select:none;white-space:nowrap}th:hover{color:var(--tx0)}
td{padding:var(--sp-4) var(--sp-6);font-size:var(--fs-body);border-bottom:1px solid var(--br)}
tr[style*="cursor"]:hover td{background:rgba(14,19,48,.06)}
td[onclick]:hover{background:var(--bg2)!important;opacity:.85}
.cat-search-wrap{position:relative;display:inline-block;min-width:160px}
.ai-report{font-size:14px;line-height:1.7;color:var(--tx0)}.ai-report h2.ai-section{margin:24px 0 12px;padding:10px 14px;background:var(--bg2);border-radius:var(--r1);font-size:16px;border-left:4px solid var(--pri)}.ai-report h3{margin:16px 0 8px;font-size:14px;color:var(--tx0)}.ai-report ul{margin:8px 0;padding-left:20px}.ai-report li{margin:4px 0}.ai-report table.ai-table{width:100%;border-collapse:collapse;margin:12px 0;font-size:13px}.ai-report table.ai-table th{background:var(--bg2);padding:8px 10px;text-align:left;font-weight:600;border-bottom:2px solid var(--br)}.ai-report table.ai-table td{padding:6px 10px;border-bottom:1px solid var(--br);font-variant-numeric:tabular-nums}.ai-report table.ai-table tr:hover{background:var(--bg2)}.ai-report strong{color:var(--tx0)}.spinner-lg{width:40px;height:40px;border:4px solid var(--br);border-top:4px solid var(--pri);border-radius:50%;animation:spin 1s linear infinite;margin:0 auto}.spinner-sm{display:inline-block;width:14px;height:14px;border:2px solid rgba(255,255,255,.3);border-top:2px solid #fff;border-radius:50%;animation:spin 1s linear infinite;vertical-align:middle;margin-right:6px}@keyframes spin{to{transform:rotate(360deg)}}
.cat-search-btn{width:100%;padding:4px 24px 4px 8px;font-size:11px;border:1px solid var(--br);border-radius:var(--r1);background:var(--bg1);color:var(--tx);cursor:pointer;text-align:left;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;appearance:none;-webkit-appearance:none}
.cat-search-btn::after{content:'▾';position:absolute;right:8px;top:50%;transform:translateY(-50%);font-size:11px;pointer-events:none;color:var(--tx1)}
.cat-search-dd{position:absolute;top:100%;left:0;right:0;background:var(--bg1);border:1px solid var(--br);border-radius:var(--r1);box-shadow:0 4px 16px rgba(0,0,0,.18);z-index:999;display:none;min-width:220px}
.cat-search-dd.open{display:block}
.cat-search-dd input{width:100%;padding:6px 8px;font-size:12px;border:none;border-bottom:1px solid var(--br);outline:none;background:var(--bg1);color:var(--tx);box-sizing:border-box}
.cat-search-dd ul{list-style:none;margin:0;padding:0;max-height:200px;overflow-y:auto}
.cat-search-dd li{padding:5px 10px;font-size:12px;cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--tx)}
.cat-search-dd li:hover,.cat-search-dd li.hl{background:var(--pri);color:var(--pri-fg)}
.cat-search-dd li.optgrp{font-size:11px;font-weight:700;color:var(--tx1);padding:6px 10px 3px;cursor:default;text-transform:uppercase;background:var(--bg2)}
.xTab{background:var(--bg2);color:var(--tx1);border:1px solid var(--br);font-size:12px;padding:6px 12px;cursor:pointer;border-radius:var(--r1);transition:all .15s}
.xTab.on{background:var(--pri);color:var(--pri-fg);border-color:var(--pri)}
.al-badge{background:var(--red);color:#fff;font-size:11px;font-weight:700;padding:1px 6px;border-radius:10px;margin-left:6px;min-width:16px;text-align:center;display:inline-block}
.proj-alert{background:var(--redL);border:1px solid var(--red);border-radius:var(--r1);padding:10px 14px;margin-top:8px;font-size:12px;color:var(--red);display:flex;align-items:center;gap:8px}
tr:last-child td{border-bottom:none}tr:hover{background:var(--hv)}
/* T8: coluna de valor sempre a direita, cabecalho junto, digitos de mesma largura. */
td.tm,th.tm,.tm{font-family:'JetBrains Mono',monospace;font-size:12px;font-weight:500;font-variant-numeric:tabular-nums;text-align:right}.tm.pos{color:var(--green)}.tm.neg{color:var(--red)}
/* Design system utilities: compact value display (val-mono) and hero KPI cards (kpi-val) */
.val-mono{font-family:var(--font-mono);font-variant-numeric:tabular-nums;font-weight:700}
.kpi-val{font-family:'JetBrains Mono',monospace;font-variant-numeric:tabular-nums;font-weight:700;font-size:22px;margin:6px 0;line-height:1.1}
/* P4: KPI card unified family — card-v-compact (22px), card-v-hero modifiers, semantic highlights */
.card-v-hero.pos{color:var(--green)}.card-v-hero.neg{color:var(--red)}
.card-v.warn{color:var(--orange)}.card-v-compact.warn{color:var(--orange)}
.card-v-compact{font-family:'JetBrains Mono',monospace;font-size:22px;font-weight:700;line-height:1.1;font-variant-numeric:tabular-nums;margin:6px 0}.card-v-compact.pos{color:var(--green)}.card-v-compact.neg{color:var(--red)}
.card-sub{font-size:11px;color:var(--tx2);margin-top:4px;line-height:1.35}
.card-hl-pos{border-color:var(--green)!important;box-shadow:0 2px 12px rgba(52,199,89,.15)!important}
.card-hl-neg{border-color:var(--red)!important;box-shadow:0 2px 12px rgba(255,59,48,.15)!important}
.vl.pos{color:var(--green)}.vl.neg{color:var(--red)}
/* T1 — .mut = SAIDA/despesa. Saida nao e erro: fica neutra. O vermelho passa a
   significar so tres coisas: saldo negativo, vencido/atraso e acao destrutiva.
   .neg continua existindo e continua vermelho, mas so para valor realmente negativo. */
.card-v.mut,.card-v-hero.mut,.vl.mut,.tm.mut{color:var(--tx1)}
.bdg{display:inline-flex;align-items:center;padding:var(--sp-1) var(--sp-4);border-radius:6px;font-size:10px;letter-spacing:.3px;text-transform:uppercase;font-weight:var(--fw-medium)}
.bdg.pago{background:var(--greenL);color:var(--green)}/* P5: pendente e o estado PADRAO de toda conta — neutro. Ambar so no degrau
   de urgencia (vence em ate 3 dias), para que ambar volte a significar algo. */
.bdg.pendente{background:var(--bg2);color:var(--tx1)}
.bdg.vencendo{background:var(--orangeL);color:var(--orange)}.bdg.vencido{background:var(--redL);color:var(--red)}.bdg.quitado{background:var(--greenL);color:var(--green)}.bdg.atraso{background:var(--orangeL);color:var(--orange)}
/* Menu flutuante (T6) — uma peca, dois usos: menu de conta e "Exportar".
   Ancorado ao gatilho, fecha em clique fora e Esc. */
.mnu{position:fixed;z-index:900;min-width:210px;padding:var(--sp-2);background:var(--bg3);border:1px solid var(--br);border-radius:var(--r2);box-shadow:var(--sh-dp);animation:mnuIn .12s ease}
@keyframes mnuIn{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}
.mnu-hd{padding:var(--sp-5) var(--sp-6) var(--sp-4);border-bottom:1px solid var(--br);margin-bottom:var(--sp-2);display:flex;flex-direction:column;gap:2px}
.mnu-hd b{font-size:var(--fs-body);font-weight:var(--fw-semibold);color:var(--tx0)}
.mnu-hd span{font-size:var(--fs-caption);color:var(--tx2);overflow:hidden;text-overflow:ellipsis}
.mnu-i{display:flex;align-items:center;gap:var(--sp-5);width:100%;padding:var(--sp-5) var(--sp-6);border:none;border-radius:var(--r1);background:none;font-family:inherit;font-size:var(--fs-body);color:var(--tx0);cursor:pointer;text-align:left;min-height:38px}
.mnu-i:hover{background:var(--bg1)}
.mnu-i:focus-visible{outline:2px solid var(--pri);outline-offset:-2px}
.mnu-i .lc{width:15px;height:15px;color:var(--tx2);flex-shrink:0}
.mnu-i--danger{color:var(--red)}
.mnu-i--danger:hover{background:var(--redL)}
.mnu-i--danger .lc{color:var(--red)}
.mnu-sep{height:1px;background:var(--br);margin:var(--sp-2) 0}
.bdg.ok{background:var(--greenL);color:var(--green)}.bdg.warn{background:var(--orangeL);color:var(--orange)}.bdg.bad{background:var(--redL);color:var(--red)}.bdg.mute{background:var(--bg2);color:var(--tx2)}.bdg.info{background:var(--blueL);color:var(--blue)}.bdg.gold{background:var(--yellowL);color:var(--gold);border:1px solid var(--gold)}
.btn{display:inline-flex;align-items:center;gap:5px;padding:7px var(--sp-7);border-radius:var(--r2);font-size:var(--fs-body);font-weight:var(--fw-medium);cursor:pointer;transition:var(--t-ui);border:none;font-family:inherit;min-height:44px}a.btn{text-decoration:none}
.btn-p{background:var(--pri);color:var(--pri-fg);font-weight:600}.btn-p:hover{filter:brightness(1.1)}.btn-p:active{filter:brightness(.92);transform:scale(.98)}
.btn-s{background:var(--bg1);color:var(--tx0);border:1.5px solid var(--br)}.btn-s:hover{background:var(--bg2)}.btn-s:active{background:var(--bg2);transform:scale(.98)}
.btn-d{background:var(--redL);color:var(--red)}.btn-d:hover{background:var(--red);color:#fff}
.btn-d-strong{background:var(--red);color:#fff;font-weight:600}.btn-d-strong:hover{filter:brightness(1.1)}.btn-d-strong:active{filter:brightness(.92);transform:scale(.98)}
.btn-g{background:var(--green);color:#fff;font-weight:600}.btn-g:hover{filter:brightness(1.1)}.btn-g:active{filter:brightness(.92);transform:scale(.98)}
.btn-rm{background:none;border:none;cursor:pointer;color:var(--red)}
.seg-btn{border:none;background:transparent;color:var(--tx2);padding:7px 12px;font-size:12px;font-weight:600;cursor:pointer;transition:background .15s,color .15s}.seg-btn.on{background:var(--pri);color:var(--pri-fg)}
.emoji-pick-btn{font-size:20px;padding:4px;border:none;background:none;cursor:pointer;border-radius:4px;transition:background .1s}.emoji-pick-btn:hover{background:var(--bg2)}
.btn-sm{padding:var(--sp-2) var(--sp-5);font-size:var(--fs-label)}
.bgh{background:none;border:none;color:var(--blue);padding:6px 10px;font-size:13px;cursor:pointer;font-family:inherit;border-radius:6px;min-width:36px;min-height:36px;display:inline-flex;align-items:center;justify-content:center}.bgh:hover{background:var(--blueL)}
.ibtn{background:none;border:none;color:inherit;padding:4px;cursor:pointer;border-radius:4px;display:inline-flex;align-items:center;justify-content:center;line-height:1;font-size:inherit}.ibtn:hover{background:var(--hv)}
@media(max-width:768px){.ibtn{min-width:40px;min-height:40px}}
.fc{padding:var(--sp-2) var(--sp-5);border-radius:var(--r-pill);border:1px solid var(--br);background:none;font-size:var(--fs-label);font-weight:var(--fw-medium);color:var(--tx1);cursor:pointer;transition:var(--t-ui);font-family:inherit}.fc:hover{background:var(--hv)}.fc.on{background:var(--pri);color:var(--pri-fg);border-color:var(--pri)}
.tabs{display:flex;border-bottom:1px solid var(--br);margin-bottom:18px}
.tab{padding:var(--sp-4) var(--sp-9);border:none;background:none;font-size:var(--fs-body);font-weight:var(--fw-medium);color:var(--tx1);cursor:pointer;position:relative;font-family:inherit}.tab:hover{color:var(--tx0)}.tab.on{color:var(--pri)}.tab.on::after{content:'';position:absolute;bottom:-1px;left:0;right:0;height:2px;background:var(--pri);border-radius:1px 1px 0 0}
.mo{position:fixed;inset:0;background:var(--ov);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);z-index:1000;display:flex;align-items:center;justify-content:center;opacity:0;pointer-events:none;transition:opacity .2s}
.mo.on{opacity:1;pointer-events:all}
.mo-bx{background:var(--bg3);border-radius:var(--r3);width:500px;max-width:90vw;max-height:85vh;overflow-y:auto;box-shadow:0 24px 64px rgba(0,0,0,.25);transform:scale(.96) translateY(10px);transition:transform .25s cubic-bezier(.25,.1,.25,1)}
.mo.on .mo-bx{transform:scale(1) translateY(0)}
.mo-hd{display:flex;align-items:center;justify-content:space-between;padding:var(--sp-9) var(--sp-11) 0}.mo-hd h2{font-family:var(--ff-display);font-size:20px;font-weight:var(--fw-bold)}
.mo-x{width:36px;height:36px;border-radius:var(--r-full);background:var(--bg2);border:none;cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--tx1);font-size:16px}.mo-x:hover{background:var(--hv)}
.mo-bd{padding:var(--sp-9) var(--sp-11)}.mo-ft{padding:var(--sp-6) var(--sp-11);border-top:1px solid var(--br);display:flex;justify-content:flex-end;gap:8px}
.fg{margin-bottom:var(--sp-6)}.fl{display:block;font-family:var(--ff-body);font-size:11px;text-transform:uppercase;letter-spacing:.4px;font-weight:var(--fw-semibold);color:var(--tx1);margin-bottom:var(--sp-2)}
.fi,.fs{width:100%;padding:9px var(--sp-6);background:var(--ibg);border:1px solid var(--br);border-radius:var(--r1);font-size:var(--fs-body);font-family:inherit;color:var(--tx0);outline:none;transition:border-color .2s,box-shadow .2s}.fi:focus,.fs:focus{border-color:var(--pri);box-shadow:0 0 0 3px rgba(14,19,48,.18)}.fi.valid{border-color:var(--green)}.fi.invalid,.fs.invalid{border-color:var(--red);box-shadow:0 0 0 3px rgba(176,0,32,.18);animation:fieldShake .3s ease}
/* Focus visible for keyboard navigation */
:focus-visible{outline:2px solid transparent;outline-offset:2px;box-shadow:0 0 0 2px var(--bg0),0 0 0 4px rgba(14,19,48,.45)}
[data-theme="dark"] :focus-visible{box-shadow:0 0 0 2px var(--bg0),0 0 0 4px rgba(246,243,234,.45)}
button:focus:not(:focus-visible),input:focus:not(:focus-visible),select:focus:not(:focus-visible),a:focus:not(:focus-visible){outline:none}
.fr{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.ck{display:flex;align-items:center;gap:8px;font-size:13px;cursor:pointer}.ck input[type=checkbox]{width:16px;height:16px;accent-color:var(--blue)}
.rp{background:var(--bg1);border-radius:var(--r1);padding:10px 14px;margin-top:8px}
.tg-r{display:flex;align-items:center;justify-content:space-between;padding:8px 0}
.tg{width:42px;height:24px;background:var(--bg2);border-radius:12px;border:none;cursor:pointer;position:relative;transition:var(--t-ui)}.tg.on{background:var(--green)}.tg::after{content:'';width:20px;height:20px;background:#fff;border-radius:var(--r-full);position:absolute;top:2px;left:2px;transition:var(--t-ui);box-shadow:var(--sh-toggle)}.tg.on::after{left:20px}
/* B2: estado vazio no lugar do canvas, ocupando o mesmo espaco para o painel
   nao encolher quando nao ha dado. */
.chart-em{display:flex;align-items:center;justify-content:center;min-height:200px;padding:20px}
.em{text-align:center;padding:40px 20px;color:var(--tx2)}.em .ei{font-size:40px;margin-bottom:8px}.em .ei .lc{width:40px;height:40px;stroke-width:1.25;color:var(--tx2)}
.al-i{display:flex;align-items:center;gap:10px;padding:8px 14px;border-bottom:1px solid var(--br)}.al-i:last-child{border-bottom:none}.al-i:hover{background:var(--hv)}
.al-d{width:8px;height:8px;border-radius:50%}.al-d.red{background:var(--red)}.al-d.org{background:var(--orange)}.al-d.grn{background:var(--green)}
.al-nf{flex:1}.al-nf .at{font-size:13px;font-weight:500}.al-nf .ad{font-size:11px;color:var(--tx2)}
.al-v{font-family:'JetBrains Mono',monospace;font-size:13px;font-weight:600}
/* A troca de tela nao anima. Cada navegacao rodava fadeSlideIn (opacity 0→1 e
   translateY 8px→0) sobre o container inteiro da pagina, o que compoe a tela
   toda por 220ms: a leitura fica esperando o conteudo assentar, e em tela com
   tabela longa o custo de composicao aparece como travada. Conteudo que ja
   esta pronto deve aparecer pronto — a animacao so tem valor quando cobre uma
   espera real, e aqui nao ha espera: trocar de mes e trocar de menu nao fazem
   nenhuma chamada de rede (medido: 0 requisicoes em ambos).
   A keyframe fica declarada porque tem uso fora daqui. */
@keyframes fadeSlideIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}
.pg{display:none}.pg.on{display:block}
.chg{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:20px}.chc{background:var(--bg3);border:1px solid var(--br);border-radius:var(--r2);padding:16px}.chc.fw{grid-column:1/-1}
.dash-grid{display:grid;grid-template-columns:1fr 1fr;gap:14px}
.dash-col-left,.dash-col-right{display:flex;flex-direction:column;gap:0}
.dash-ind{display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:8px}
/* P1: sem painel em volta, o tile passa a ser a superficie de card. E a grade
   usa auto-fit com um minimo maior, para nao sobrar fileira orfa de tres. */
.dash-ind-lg{grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:10px}
.cht{font-size:14px;font-weight:600;margin-bottom:12px;display:flex;align-items:center;justify-content:space-between}.cht .tg2{font-size:11px;background:var(--bbg);color:var(--tx1);padding:2px 8px;border-radius:8px}
.chb{position:relative;height:200px}
@media(min-width:1600px){.dash-grid{grid-template-columns:1fr 1.2fr}.dash-ind{grid-template-columns:repeat(4,1fr)}.cg{grid-template-columns:repeat(4,1fr)}}
@media(max-width:1024px){.chg{grid-template-columns:1fr}.dash-grid{grid-template-columns:1fr}}
@media(max-width:768px){.sb{position:fixed;left:-250px;top:0;bottom:0;z-index:200;box-shadow:0 0 30px rgba(0,0,0,.4)}.sb.open{left:0}.mbo{position:fixed;inset:0;background:rgba(0,0,0,.4);z-index:199;display:none}.mbo.on{display:block}.fr{grid-template-columns:1fr}.bmm{display:flex!important}}
@media(max-width:480px){.cg{grid-template-columns:1fr}.ct{padding:14px}}
.bmm{display:flex!important}
/* Pulso do Ano — tooltip fixo no body */
.bal-fixed-tip{position:fixed;transform:translate(-50%,-100%);background:var(--bg3);border:1px solid var(--br);border-radius:6px;padding:4px 9px;font-size:11px;font-weight:700;font-family:var(--font-mono);white-space:nowrap;box-shadow:var(--sh);z-index:9999;opacity:0;pointer-events:none;transition:opacity .1s}
.grid2{display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));gap:14px}
.grid4{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:14px}
.sw-item{display:flex;align-items:center;gap:8px;padding:6px 10px;background:var(--bg1);border-radius:var(--r1);margin-bottom:4px;font-size:13px}
.sw-item:hover{background:var(--bg2)}.sw-item .sw-del{margin-left:auto;cursor:pointer;opacity:.4;font-size:11px}.sw-item .sw-del:hover{opacity:1;color:var(--red)}
.prog-bar{height:8px;background:var(--bg2);border-radius:4px;overflow:hidden;margin-top:4px}.prog-fill{height:100%;border-radius:4px;transition:width .3s}
.score-card{text-align:center;padding:16px}.score-num{font-size:48px;font-weight:700;font-family:'JetBrains Mono',monospace}.score-label{font-size:12px;color:var(--tx2);margin-top:4px}
.ind-row{display:flex;justify-content:space-between;padding:8px 0;border-bottom:1px solid var(--br);font-size:13px}.ind-row:last-child{border:0}.ind-val{font-weight:600;font-family:'JetBrains Mono',monospace}
/* Login Screen */
/* Theme-adaptive logos */
/* Guarda da troca de tema: enquanto a classe está no <html>, nada anima.
   Sem ela, mutar os tokens sob uma transition ativa (a .sb tem
   transition:background .2s) prende a transition em "running" e o paint fica
   congelado no tema anterior. Aplicada por setTheme() em shared/router.js. */
.theme-switching *,.theme-switching *::before,.theme-switching *::after{transition:none!important}
.logo-light{display:block}.logo-dark{display:none}
[data-theme="dark"] .logo-light{display:none}
[data-theme="dark"] .logo-dark{display:block}
/* ═══ T4 — Login em painel dividido (01/08/2026) ═══
   O login e SEMPRE claro nos dois temas: os tokens sao redefinidos aqui dentro,
   entao nada nesta arvore le [data-theme]. */
.login-wrap{
  --bg0:#FAF8F3;--bg1:#F4F1E8;--bg2:#E9E4D6;--bg3:#FFFFFF;
  --tx0:#0E1330;--tx1:#4A4F66;--tx2:#60657A;
  --br:#DCD6C7;--ibg:#F4F1E8;
  --pri:#0E1330;--pri-fg:#F2EEE3;--blue:#0E1330;--blueL:rgba(14,19,48,.08);
  position:fixed;inset:0;z-index:9999;display:flex;background:var(--bg3);color:var(--tx0)
}
.login-wrap.hidden{display:none}

/* Painel esquerdo — marca */
.login-brand{position:relative;flex:0 0 42%;min-width:240px;background:#0E1330;color:#F2EEE3;
  display:flex;flex-direction:column;justify-content:space-between;padding:38px 34px;overflow:hidden}
/* P4: ancorado no canto INFERIOR DIREITO, tocando duas bordas e com a ponta
   fora da area. Centralizado no topo e cortado dos dois lados, o olho lia como
   acidente de layout; corte assimetrico por um lado so le como intencao.
   Opacidade .14 — a .09 sobre navy ficava no limiar de sujeira no monitor. */
.login-brand-bleed{position:absolute;right:-16%;bottom:-34%;width:78%;max-width:none;height:auto;opacity:.14;pointer-events:none}
.login-lockup{display:flex;align-items:center;gap:11px;position:relative}
.login-lockup img{height:26px;width:auto}
.login-lockup b{display:block;font-family:var(--font-sans);font-size:19px;font-weight:600;line-height:1.05;letter-spacing:-.01em}
.login-lockup span{display:block;font-family:var(--font-mono);font-size:7.5px;font-weight:500;
  letter-spacing:.28em;text-transform:uppercase;opacity:.5;margin-top:3px}
.login-tagline{position:relative;font-size:15px;line-height:1.5;max-width:26ch;opacity:.82}

/* Painel direito — formulario */
.login-panel{flex:1;display:flex;align-items:center;justify-content:center;padding:40px 28px;background:var(--bg3);overflow-y:auto}
.login-box{width:100%;max-width:360px;background:none;border:0;border-radius:0;padding:0;box-shadow:none}
.login-title{font-family:var(--ff-display);font-size:26px;font-weight:var(--fw-semibold);letter-spacing:-.02em;margin-bottom:var(--sp-2)}
.login-sub{font-size:var(--fs-body);color:var(--tx1);margin-bottom:var(--sp-10)}
.login-fg{margin-bottom:14px}
.login-fg label{display:block;font-size:var(--fs-label);font-weight:600;color:var(--tx1);margin-bottom:5px}
.login-fg input{width:100%}
.login-btn{width:100%;justify-content:center;margin-top:var(--sp-4)}
.login-wait{margin-top:10px;font-size:11px;line-height:1.45;color:var(--tx2)}
.login-err{color:var(--red);font-size:var(--fs-label);margin-top:10px;min-height:16px}
.login-toggle{margin-top:14px;font-size:var(--fs-body);color:var(--tx1)}
.login-toggle a{color:var(--tx0);cursor:pointer;font-weight:600;text-decoration:underline;text-underline-offset:3px}
.login-toggle a:hover{opacity:.7}

/* Abaixo de 720px a marca vira faixa no topo, sem tagline */
@media(max-width:720px){
  .login-wrap{flex-direction:column}
  .login-brand{flex:0 0 96px;min-width:0;height:96px;padding:0 20px;justify-content:center}
  .login-brand-bleed{width:150px;right:-28px;bottom:-46px}
  .login-tagline{display:none}
  .login-panel{padding:26px 20px;align-items:flex-start}
}
.logout-btn{display:flex;align-items:center;gap:8px;padding:7px 10px;border-radius:var(--r1);cursor:pointer;color:var(--red);font-size:13px;font-weight:500;transition:var(--t-ui);border:none;background:none;width:100%;text-align:left;font-family:inherit;margin-top:4px}
.logout-btn:hover{background:var(--redL)}
.login-loading{display:inline-block;width:16px;height:16px;border:2px solid rgba(255,255,255,.3);border-top-color:#fff;border-radius:50%;animation:spin .6s linear infinite;margin-right:6px;vertical-align:middle}
@keyframes spin{to{transform:rotate(360deg)}}
/* Spin inline (botões loading) */
.spin-inline{display:inline-block;animation:spin 1s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}
/* Toast */
.toast-wrap{position:fixed;bottom:20px;right:20px;z-index:9999;display:flex;flex-direction:column;gap:8px;pointer-events:none}
.toast{padding:var(--sp-5) var(--sp-9);border-radius:var(--sp-5);border-left:4px solid rgba(255,255,255,.35);font-size:var(--fs-body);font-weight:var(--fw-medium);color:#fff;box-shadow:var(--sh-toast);animation:toastIn .3s ease,toastOut .3s ease 2.7s;pointer-events:auto;max-width:340px}
.toast.ok{background:var(--green)}.toast.err{background:var(--red)}.toast.warn{background:var(--orange)}.toast.info{background:var(--blue);color:var(--pri-fg)}
@keyframes toastIn{from{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}
@keyframes toastOut{from{opacity:1}to{opacity:0;transform:translateY(-10px)}}
/* Loading overlay */
.loading-ov{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,.15);z-index:9998;display:flex;align-items:center;justify-content:center}
.loading-sp{width:36px;height:36px;border:3px solid rgba(14,19,48,.12);border-top-color:var(--pri);border-radius:50%;animation:spin .7s linear infinite}
/* Mobile responsive tables */
@media(max-width:768px){
  table{font-size:11px}
  .tw{overflow-x:auto;-webkit-overflow-scrolling:touch}
  th,td{padding:6px 4px!important}
  .grid2{grid-template-columns:1fr!important}
  .grid4{grid-template-columns:1fr 1fr!important}
  .sc{min-width:auto!important;padding:10px!important}
  .sr{flex-wrap:wrap}
  .chg{grid-template-columns:1fr!important}
  .chc.fw{grid-column:auto!important}
  .top-r{gap:4px}
  .top-t{font-size:14px}
  .mo-bx{width:95%!important;max-width:95%!important;max-height:90vh}
  .fr{flex-direction:column}
}
/* Help tooltip */
/* .help-btn herda tudo de .bi (32px, sem borda, hover em --hv). O que sobra
   aqui e so o repouso mais discreto: --tx2 em vez de --tx1, porque a ajuda e
   secundaria em relacao a tema/alertas/perfil, que sao acao. No hover ele
   assume a cor primaria, e ai fica claro que e clicavel.
   O que existia antes — circulo de 36px com borda 1.5px em var(--pri) e um "?"
   de texto em peso 700 — lia como botao de acao primaria e era o unico glifo
   nao-lucide da topbar. */
.help-btn{color:var(--tx2)}
.help-btn:hover,.help-btn[aria-expanded="true"]{color:var(--pri);background:var(--hv)}
.help-wrap{position:relative;display:flex;align-items:center}
.top-l{position:relative}
/* Ancorado a direita: o wrapper agora vive no fim do .top-r, entao left:0
   jogaria os 420px do balao para fora da viewport. */
.help-tip{display:none;position:absolute;top:100%;right:0;margin-top:8px;background:var(--bg3);border:1px solid var(--br);border-radius:var(--r2);padding:14px 16px;font-size:12px;line-height:1.6;color:var(--tx1);box-shadow:0 8px 24px rgba(0,0,0,.12);z-index:100;width:max-content;max-width:min(420px,calc(100vw - 32px));min-width:280px}
.help-tip.on{display:block}
.help-tip h4{font-size:13px;font-weight:700;color:var(--pri);margin-bottom:6px}
.help-tip p{margin:4px 0;font-size:11.5px}
.help-tip .ht-label{font-weight:600;color:var(--tx0)}
/* Ponte para o manual completo. As duas ajudas eram ilhas: o balao da tela nao
   levava a Central de Ajuda e a Central nao sabia de onde o usuario veio. */
.help-tip .ht-more{display:block;margin-top:10px;padding-top:10px;border-top:1px solid var(--br);font-size:11.5px;font-weight:600;color:var(--pri);background:none;border-left:0;border-right:0;border-bottom:0;width:100%;text-align:left;cursor:pointer;font-family:inherit}
.help-tip .ht-more:hover{text-decoration:underline}
/* No telefone o balão ancora na VIEWPORT, não no botão.
   Com `right:0` relativo ao .help-wrap ele nasce alinhado ao botão — e o botão não fica na
   borda da tela, tem sino e perfil à direita dele. Medido em 390px: o balão ia de -60px a
   298px, ou seja, 60px de conteúdo fora da tela pela esquerda, com o texto decapitado.
   E o ui-check não acusa: fora da viewport pela esquerda não expande o documento, então não
   há overflow horizontal para medir. Só apareceu no PNG. */
@media(max-width:600px){
  .help-tip{position:fixed;top:60px;left:12px;right:12px;width:auto;max-width:none;min-width:0}
}
.ind-card:hover{border-color:var(--pri)!important;box-shadow:0 2px 8px rgba(14,19,48,.10)}
.ind-tip{position:fixed;left:50%;top:50%;transform:translate(-50%,-50%);min-width:280px;max-width:380px;background:var(--bg3);border:1px solid var(--pri);border-radius:var(--r2);padding:16px 18px;box-shadow:0 12px 40px rgba(0,0,0,.2);z-index:200}
.ind-tip-ov{position:fixed;inset:0;background:rgba(0,0,0,.15);z-index:199}
/* Plan badge */
.plan-badge{font-size:11px;font-weight:700;padding:2px 8px;border-radius:6px;margin-left:6px}
.plan-badge.starter{background:var(--orangeL);color:var(--orange)}
.plan-badge.pro{background:var(--blueL);color:var(--blue)}
.plan-badge.cortesia{background:var(--greenL);color:var(--green)}
/* ═══ Date Picker ═══ */
.dp-overlay{display:none;position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,.3);z-index:1000;justify-content:center;align-items:center}
.dp-overlay.open{display:flex}
/* --r3, nao --r-pill: r-pill virou 999px (pilula de verdade, correto pro .fc),
   e num painel de 640px isso vira um comprimido gigante. */
.dp-container{background:var(--bg1);border-radius:var(--r3);box-shadow:var(--sh-dp);padding:0;overflow:hidden;max-width:640px;width:95%}
.dp-top{display:flex;gap:0}
.dp-calendars{flex:1;display:flex;padding:14px 16px;gap:20px}
.dp-shortcuts{width:170px;background:var(--bg2);padding:8px 6px;display:flex;flex-direction:column;gap:2px;border-left:1px solid var(--br)}
.dp-sc-section{font-size:9px;font-weight:700;color:var(--tx1);text-transform:uppercase;letter-spacing:.6px;padding:3px 8px 1px;margin-top:2px}
.dp-sc-section:first-child{margin-top:0}
.dp-sc-row{display:flex;flex-wrap:wrap;gap:2px;padding:0 2px}
.dp-shortcut{padding:3px 7px;font-size:10px;border-radius:5px;cursor:pointer;border:1px solid transparent;background:var(--bg1);text-align:center;color:var(--tx);transition:var(--t-ui);font-family:inherit;white-space:nowrap;line-height:1.4}
.dp-shortcut:hover{border-color:var(--pri);color:var(--pri);background:var(--priL)}
.dp-shortcut.active{background:var(--pri);color:var(--pri-fg);border-color:var(--pri)}
.dp-shortcut.full{width:100%;text-align:left;padding:4px 8px}
.dp-cal{flex:1;min-width:0}
.dp-cal-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:6px}
.dp-cal-title{font-size:12px;font-weight:600;color:var(--tx)}
.dp-cal-nav{width:24px;height:24px;border:1px solid var(--br);border-radius:5px;background:var(--bg1);cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:11px;color:var(--tx1);transition:var(--t-ui)}
.dp-cal-nav:hover{background:var(--bg2);color:var(--tx)}
.dp-weekdays{display:grid;grid-template-columns:repeat(7,1fr);gap:0;margin-bottom:2px}
.dp-weekday{font-size:9px;font-weight:600;color:var(--tx1);text-align:center;padding:2px 0;text-transform:uppercase}
.dp-days{display:grid;grid-template-columns:repeat(7,1fr);gap:1px}
.dp-day{width:30px;height:28px;display:flex;align-items:center;justify-content:center;font-size:11px;border-radius:6px;cursor:pointer;transition:var(--t-ui);color:var(--tx);border:none;background:none;font-family:inherit;margin:0 auto}
.dp-day:hover{background:var(--priL);color:var(--pri)}
.dp-day.other{color:var(--tx2);opacity:.4}
.dp-day.today{font-weight:700;box-shadow:inset 0 0 0 1.5px var(--pri)}
.dp-day.selected{background:var(--pri);color:var(--pri-fg);font-weight:600}
.dp-day.in-range{background:var(--priL);color:var(--pri);border-radius:0}
.dp-day.range-start{background:var(--pri);color:var(--pri-fg);font-weight:600;border-radius:6px 0 0 6px}
.dp-day.range-end{background:var(--pri);color:var(--pri-fg);font-weight:600;border-radius:0 6px 6px 0}
.dp-day.range-start.range-end{border-radius:6px}
.dp-inputs{display:flex;gap:12px;padding:10px 16px;background:var(--bg2)}
.dp-input-group{flex:1}
.dp-input-label{font-size:9px;font-weight:600;color:var(--tx1);margin-bottom:2px;text-transform:uppercase;letter-spacing:.4px}
.dp-input{width:100%;padding:5px 8px;font-size:12px;border:1px solid var(--br);border-radius:6px;background:var(--bg1);color:var(--tx);font-family:inherit;text-align:center}
.dp-input:focus{outline:none;border-color:var(--pri);box-shadow:0 0 0 2px rgba(14,19,48,.12)}
.dp-footer{display:flex;justify-content:flex-end;gap:8px;padding:10px 16px;border-top:1px solid var(--br)}
.dp-btn{padding:6px 16px;font-size:12px;font-weight:600;border-radius:6px;cursor:pointer;border:none;transition:var(--t-ui);font-family:inherit}
.dp-btn-cancel{background:var(--bg2);color:var(--tx1)}
.dp-btn-cancel:hover{background:#ddd}
.dp-btn-apply{background:var(--pri);color:var(--pri-fg)}
.dp-btn-apply:hover{filter:brightness(1.1)}
.dp-month-grid{display:none;grid-template-columns:repeat(3,1fr);gap:6px;padding:14px 16px;flex:1}
.dp-month-grid.open{display:grid}
.dp-month-item{padding:8px 6px;text-align:center;font-size:11px;border-radius:6px;cursor:pointer;border:none;background:none;color:var(--tx);transition:var(--t-ui);font-family:inherit}
.dp-month-item:hover{background:var(--priL);color:var(--pri)}
.dp-month-item.current{font-weight:700;box-shadow:inset 0 0 0 1.5px var(--pri)}
.dp-month-item.selected{background:var(--pri);color:var(--pri-fg)}
.ms .cur{cursor:pointer;padding:4px 12px;border-radius:var(--r1);transition:var(--t-ui)}
.ms .cur:hover{background:var(--priL);color:var(--pri)}
@media(prefers-reduced-motion:reduce){*,*::before,*::after{animation-duration:0.01ms!important;animation-iteration-count:1!important;transition-duration:0.01ms!important}}

/* ═══════════════════════════════════════════════════════════════
   MOBILE UI — bottom nav + cards + full-screen modals + FAB
   Aplicado em telas <=768px. Desktop continua intacto.
   ═══════════════════════════════════════════════════════════════ */
.bnav{display:none}
.mob-sheet-only{display:none}

@media(max-width:768px){
  /* Sidebar desaparece em mobile — bottom nav substitui */
  .sb,.mbo{display:none!important}
  .top-l .bmm{display:none!important}

  /* Impede overflow horizontal — empurraria bottom nav pra fora da viewport */
  html,body{overflow-x:hidden;max-width:100vw}
  .main{margin-left:0!important;padding-bottom:calc(72px + env(safe-area-inset-bottom))!important;max-width:100vw;overflow-x:hidden}
  .ct{padding:14px 14px 24px;max-width:100vw;overflow-x:hidden}

  /* Top header compacto */
  .top{padding:0 12px;gap:8px;height:52px;min-height:52px;padding-top:env(safe-area-inset-top)}
  .top-l{gap:8px;flex:0 1 auto;min-width:0}
  /* min-width:0: item flex não encolhe abaixo do conteúdo sem isto, e "Mapa do Caixa" passava
     por baixo do seletor de mês (medido em 19/09 a 375px). */
  .top-t{font-size:17px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
  .top-r{gap:4px;flex:1;min-width:0;justify-content:flex-end}
  .top-r .ms{flex:0 1 auto}
  .top-r .ms .cur{font-size:12px;min-width:auto;padding:4px 6px}
  .top-r .ms button{min-width:30px;min-height:30px;padding:4px 8px}
  .top-r .ys,.top-r #periodBadge{display:none}
  /* Os seletores [onclick*=] que escondiam botões aqui morreram na migração para data-act
     (06/08); o botão de tema fica, porque desde a v4.72 é o ÚNICO caminho para trocar o tema.
     Mês + 4 ícones não cabem em 375px com título longo, e o seletor de mês escorregava por
     baixo do título (medido em 19/09): o mês passa a encolher com reticências. */
  .top-r .ms{min-width:0;flex-shrink:0}
  .top-r .ms .cur{white-space:nowrap;min-width:0}
  /* Quem cede é o título (o mês abreviado + setas sempre cabem): "Contas a Receber" vira
     "Contas a Re…" a 375px. O que sai do topo no celular é decisão de design, listada no hub. */
  .top-l{flex:1 1 auto}
  .top-r{flex:0 0 auto}

  /* Bottom navigation */
  .bnav{
    display:flex;position:fixed;bottom:0;left:0;right:0;
    height:64px;padding-bottom:env(safe-area-inset-bottom);
    background:var(--bg3);border-top:1px solid var(--br);
    box-shadow:0 -4px 16px rgba(0,0,0,.06);z-index:100
  }
  .bnav-item{
    flex:1 1 0;min-width:0;display:flex;flex-direction:column;align-items:center;justify-content:center;
    gap:2px;padding:6px 2px;border:none;background:none;cursor:pointer;
    color:var(--tx2);font-size:10px;font-weight:500;font-family:inherit;
    -webkit-tap-highlight-color:transparent;transition:color .15s
  }
  .bnav-item .lc{width:22px;height:22px;stroke-width:1.75}
  .bnav-item.on{color:var(--pri)}
  .bnav-item.on .lc{stroke-width:2.25}
  .bnav-item:active{opacity:.6}
  .bnav-item.bnav-fab{padding:6px 2px}
  .bnav-fab-circle{
    width:42px;height:42px;border-radius:50%;background:var(--pri);
    display:flex;align-items:center;justify-content:center;color:var(--pri-fg);
    box-shadow:0 4px 10px rgba(14,19,48,.30);margin-bottom:2px
  }
  .bnav-fab-circle .lc{width:22px;height:22px;stroke:var(--pri-fg);stroke-width:2.5}
  .bnav-item.bnav-fab{color:var(--pri);font-weight:600}
  .bnav-item.bnav-fab:active .bnav-fab-circle{transform:scale(.92);filter:brightness(.9)}

  /* Modais → full-screen */
  .mo .mo-bx{
    width:100vw!important;max-width:none!important;
    height:100dvh!important;max-height:none!important;
    border-radius:0!important;display:flex;flex-direction:column;
    margin:0!important
  }
  .mo .mo-hd{padding:14px 16px;padding-top:calc(14px + env(safe-area-inset-top))}
  .mo .mo-bd{flex:1;padding:16px;padding-bottom:24px;overflow-y:auto;-webkit-overflow-scrolling:touch}
  .mo .mo-ft{padding:12px 16px calc(12px + env(safe-area-inset-bottom));border-top:1px solid var(--br);position:sticky;bottom:0;background:var(--bg3)}
  .mo .fr{grid-template-columns:1fr!important;gap:0}

  /* Bottom-sheet (Menu/Novo): vira sheet do rodapé, não full-screen */
  .mob-sheet-only{display:flex!important}
  .mob-sheet .mo-bx{
    height:auto!important;max-height:80dvh!important;
    margin-top:auto!important;border-radius:16px 16px 0 0!important
  }
  .mob-action{
    width:100%;display:flex;align-items:center;gap:14px;
    padding:14px 16px;border:0;background:none;cursor:pointer;
    color:var(--tx0);font-size:15px;font-family:inherit;text-align:left;
    border-bottom:1px solid var(--br);min-height:52px
  }
  .mob-action:last-child{border-bottom:0}
  .mob-action:active{background:var(--bg2)}
  .mob-action .lc{width:22px;height:22px;color:var(--tx1);flex-shrink:0}

  /* Tables → cards verticais */
  .tw{border-radius:0;border-left:0;border-right:0;margin-left:-14px;margin-right:-14px}
  .tw-h{flex-direction:column;align-items:stretch;gap:6px;padding:12px 14px}
  table thead{display:none}
  table tbody tr{display:block;padding:12px 14px;border-bottom:1px solid var(--br)}
  table tbody tr td{display:flex;justify-content:space-between;align-items:center;padding:3px 0;border:0;font-size:13px;text-align:right;white-space:normal}
  table tbody tr td:first-child{font-weight:600;font-size:14px;color:var(--tx0);justify-content:flex-start;text-align:left;margin-bottom:4px;padding-bottom:6px;border-bottom:1px dashed var(--br)}
  table tbody tr td .bdg{font-size:10px;padding:2px 8px}
  table tbody tr td.tm{font-family:'JetBrains Mono',monospace;font-weight:600}
  /* Rótulo por célula no cartão: td com data-lb mostra o nome da coluna à esquerda do valor
     (o thead sumiu). Opt-in por tabela; Patrimônio é a primeira, as outras entram na revisão mobile. */
  /* Toggle de 42×24 fica com área de toque de 62×44 sem mudar o desenho: o ::after é o
     botão deslizante, o ::before vira só zona clicável ao redor. Medido em 19/09: 13 toggles
     de Configurações abaixo de 40px no celular. */
  .tg::before{content:'';position:absolute;inset:-10px}
  table tbody tr td[data-lb]::before{content:attr(data-lb);color:var(--tx1);font-weight:400;font-size:11px;text-transform:uppercase;letter-spacing:.3px;margin-right:12px;text-align:left}

  /* Resumo / KPIs em uma coluna */
  .sr{flex-direction:column;gap:8px}
  .sc{min-width:0;width:100%;text-align:left;padding:12px 14px}
  .sc .lb{font-size:11px}
  .sc .vl{font-size:20px;text-align:left}
  .dash-ind,.cg,.chg,.grid2,.grid4{grid-template-columns:1fr!important;gap:10px}

  /* Filter chips: scroll horizontal */
  .tabs,.tw-h>div:has(.fc){overflow-x:auto;flex-wrap:nowrap;-webkit-overflow-scrolling:touch;padding-bottom:4px}
  .tab,.fc{white-space:nowrap;flex-shrink:0}

  /* Forms: input bigger, font 16 evita zoom no iOS */
  .fg{margin-bottom:14px}
  .fi,.fs{padding:11px 12px;font-size:16px;min-height:44px}
  textarea.fi{min-height:80px}

  /* Login responsivo: o layout mobile agora vive no @media(max-width:720px)
     junto do bloco T4. A regra antiga forcava height:100dvh no .login-box, o
     que dentro do painel dividido empurrava o formulario para fora da tela. */

  /* T12: alvo de toque — chip de filtro, aba, fechar-modal e ajuda ficavam
     entre 26px e 36px no telefone, abaixo do piso de 44px do guia. */
  .fc{min-height:44px;padding:0 var(--sp-7);display:inline-flex;align-items:center}
  .tab{min-height:44px;display:inline-flex;align-items:center}
  .mo-x{min-width:44px;min-height:44px}
  .help-btn{min-width:44px;min-height:44px}
  /* Touch targets ≥44px */
  .btn{min-height:44px;font-size:14px}
  .btn-s,.btn-p{padding:11px 16px}
  .bi{min-width:36px;min-height:36px}
  .bgh{min-width:36px;min-height:36px}

  /* Charts ocupam largura total */
  canvas{max-width:100%;height:auto!important}

  /* Page padding */
  .pg{padding:14px}

  /* Toast: above bottom nav */
  .toast-wrap{bottom:calc(72px + env(safe-area-inset-bottom));right:12px;left:12px;align-items:stretch}
}

@media(max-width:480px){
  .top-t{font-size:16px}
  .top{height:48px;min-height:48px}
  .bnav{height:60px}
}

/* ═══ FASE 1: tap states + tokens mobile (resolve botões transparentes) ═══ */
@media(max-width:768px){
  /* Suprime tap highlight nativo iOS em todo elemento clicável */
  body{-webkit-tap-highlight-color:transparent;touch-action:manipulation}

  /* Buttons icon-only (.bi, .bgh): hover-only fill some em mobile.
     Forçar fundo + borda visível e estado :active claro. */
  .bi{background:var(--bg1);border:1px solid var(--br)}
  .bi:active{background:var(--bg2);transform:scale(.95)}
  .bgh{background:var(--bg1);border:1px solid var(--br);border-radius:var(--r1);padding:6px 10px}
  .bgh:active{background:var(--bg2);transform:scale(.95)}

  /* Botões textuais: estado :active explícito (mobile não dispara :hover) */
  .btn{transition:transform .12s ease,background .15s ease,filter .15s}
  .btn-s:active{background:var(--bg2);transform:scale(.97)}
  .btn-p:active{filter:brightness(.85);transform:scale(.97)}

  /* Filter chips e tabs: estado pressed visível */
  .fc:active{background:var(--bg2);transform:scale(.96)}
  .tab:active{opacity:.7}

  /* Cards/superfícies clicáveis: feedback no tap */
  .card[onclick],.sc[onclick],tr[onclick],td[onclick]{transition:background .15s,transform .12s}
  .card[onclick]:active,.sc[onclick]:active{background:var(--bg2);transform:scale(.99)}

  /* Bottom nav: scale em vez de só opacity */
  .bnav-item:active{background:var(--bg2);transform:scale(.94);opacity:1}

  /* Mob action (sheets): active mais visível */
  .mob-action:active{background:var(--bg2);transform:scale(.98)}

  /* Hierarquia de cards: borda mais visível no dark, sombra leve no light */
  .card,.tw,.sc{box-shadow:0 1px 2px rgba(0,0,0,.04),0 4px 10px rgba(0,0,0,.05)}
}

/* T2 (01/08/2026) — bloco removido. Ele forcava #1E2228 em .card/.tw/.sc/
   .login-box/.mo-bx e #141720 nos campos, criando uma SEGUNDA familia de
   superficie no dark que nao pertencia a escala de tokens: era o que fazia os
   KPIs sairem quase-pretos enquanto .chc (que nunca foi sobrescrito) renderizava
   o --bg3 correto. O comentario original justificava o patch com "bg3 atual =
   bg1 (#2A2D33)", condicao que deixou de existir quando o dark foi repintado.
   Superficie no dark agora vem do token, igual ao light. */

/* Modal header sticky em mobile (não perde X ao rolar form longo) */
@media(max-width:768px){
  .mo .mo-hd{position:sticky;top:0;background:var(--bg3);z-index:2;border-bottom:1px solid var(--br)}
  [data-theme="dark"] .mo .mo-hd{background:#2D3038}
}

/* ═══ Listagem densa de Contas a Pagar/Receber em mobile ═══
   Mostra só descrição + valor (linha 1) e data + status (linha 2).
   Categoria, checkbox e ações ficam ocultos — tap abre o modal de edição
   (já é onclick="editCI(...)" nas tds de descrição/data). */
@media(max-width:768px){
  #pg-pagar table tbody tr,
  #pg-receber table tbody tr{
    display:grid;grid-template-columns:1fr auto;column-gap:12px;row-gap:2px;
    padding:12px 14px;align-items:center
  }
  #pg-pagar table tbody tr td,
  #pg-receber table tbody tr td{
    display:initial;padding:0;border:0;font-size:13px;text-align:left;
    white-space:normal;justify-content:flex-start
  }
  /* col 1=checkbox, col 4=categoria, col 7=ações: ocultas em mobile */
  /* A col 7 (ações) NAO e mais ocultada: sem ela nao havia como dar baixa numa
     conta pelo telefone, que e justamente o teste do T12. */
  #pg-pagar table tbody tr td:nth-child(1),
  #pg-pagar table tbody tr td:nth-child(4),
  #pg-receber table tbody tr td:nth-child(1),
  #pg-receber table tbody tr td:nth-child(4){display:none}
  /* col 3=descrição: linha 1, esquerda, bold */
  #pg-pagar table tbody tr td:nth-child(3),
  #pg-receber table tbody tr td:nth-child(3){
    grid-column:1;grid-row:1;font-weight:600;font-size:14px;color:var(--tx0);
    overflow:hidden;text-overflow:ellipsis;border:0;margin:0;padding:0;
    cursor:pointer
  }
  /* col 5=valor: linha 1, direita, mono */
  #pg-pagar table tbody tr td:nth-child(5),
  #pg-receber table tbody tr td:nth-child(5){
    grid-column:2;grid-row:1;font-weight:700;font-size:14px;
    font-family:'JetBrains Mono',monospace;text-align:right;justify-self:end
  }
  /* col 2=vencimento: linha 2, esquerda, meta */
  #pg-pagar table tbody tr td:nth-child(2),
  #pg-receber table tbody tr td:nth-child(2){
    grid-column:1;grid-row:2;font-size:11px;color:var(--tx2);cursor:pointer
  }
  /* col 6=status badge: linha 3, esquerda (T12) */
  #pg-pagar table tbody tr td:nth-child(6),
  #pg-receber table tbody tr td:nth-child(6){
    grid-column:1;grid-row:3;justify-self:start;margin-top:6px
  }
  /* col 7=ações: linha 3, direita, alvo de 44px (T12) */
  #pg-pagar table tbody tr td:nth-child(7),
  #pg-receber table tbody tr td:nth-child(7){
    grid-column:2;grid-row:3;justify-self:end;margin-top:6px;
    display:flex;gap:4px;align-items:center
  }
  #pg-pagar table tbody tr td:nth-child(7) button,
  #pg-receber table tbody tr td:nth-child(7) button{
    min-width:44px;min-height:44px;display:inline-flex;
    align-items:center;justify-content:center
  }
  /* T12: filtros viram faixa horizontal rolavel; a busca ocupa a largura toda
     acima dela, em vez de as duas coisas disputarem a mesma linha. */
  #pg-pagar .ct-flt,#pg-receber .ct-flt{flex-wrap:nowrap;overflow-x:auto;
    -webkit-overflow-scrolling:touch;scrollbar-width:none;padding-bottom:4px}
  #pg-pagar .ct-flt::-webkit-scrollbar,#pg-receber .ct-flt::-webkit-scrollbar{display:none}
  #pg-pagar .ct-flt .fc,#pg-receber .ct-flt .fc{flex:0 0 auto}
  #pg-pagar .search-wrap,#pg-receber .search-wrap{width:100%;margin-bottom:8px}
  #pg-pagar table tbody tr td:nth-child(6) .bdg,
  #pg-receber table tbody tr td:nth-child(6) .bdg{
    font-size:10px;padding:2px 7px;font-weight:600
  }
  /* P3: a barra inferior tem 64px + safe-area e ficava por cima das acoes do
     ultimo cartao. Reserva a altura dela + 16px no fim da lista. */
  #pg-pagar .ct-card,#pg-receber .ct-card{padding-bottom:calc(64px + env(safe-area-inset-bottom) + 16px)}

  /* P3: no telefone os tres ficam so como icone — texto ao lado de icone criava
     tres pesos no mesmo grupo. O rotulo continua no aria-label e no title. */
  #pg-pagar table tbody tr td:nth-child(7) .bgh-tx,
  #pg-receber table tbody tr td:nth-child(7) .bgh-tx{display:none}

  /* tap state na linha inteira */
  #pg-pagar table tbody tr:active,
  #pg-receber table tbody tr:active{background:var(--bg2)}
}

/* ═══ Skip link (acessibilidade) ═══ */
.skip-link{position:absolute;left:-9999px;top:0;background:var(--color-navy);color:var(--color-bone);padding:8px 14px;border-radius:var(--r1);z-index:10000;font-size:13px}
.skip-link:focus{left:8px;top:8px}

/* ═══ Forced colors (Windows High Contrast) ═══ */
@media(forced-colors:active){
  .btn,.btn-p,.btn-s,.btn-d,.fi,.fs{border:1px solid CanvasText}
  .btn-p{background:Highlight;color:HighlightText}
  .bdg{border:1px solid CanvasText}
  :focus-visible{outline:3px solid Highlight;outline-offset:2px}
}

/* === migrado do inline === */
@keyframes fieldShake{0%,100%{transform:translateX(0)}25%{transform:translateX(-4px)}75%{transform:translateX(4px)}}
/* Help accordion */
.help-group{margin-bottom:14px}
.help-group-title{font-size:13px;font-weight:700;color:var(--tx2);text-transform:uppercase;letter-spacing:.5px;padding:6px 0;border-bottom:1px solid var(--br);margin-bottom:6px}
.help-item{border:1px solid var(--br);border-radius:var(--r1);margin-bottom:6px;overflow:hidden}
.help-item-header{display:flex;align-items:center;gap:10px;padding:12px 14px;cursor:pointer;background:var(--bg2);font-weight:600;font-size:14px;user-select:none;transition:background .15s}
.help-item-header:hover{background:var(--bg1)}
.help-item-header .chevron{transition:transform .2s;font-size:10px;color:var(--tx2)}
.help-item-header.open .chevron{transform:rotate(90deg)}
.help-item-body{display:none;padding:14px;font-size:13px;line-height:1.6;color:var(--tx1)}
.help-item-body.open{display:block}
.help-item-body h4{font-size:13px;font-weight:700;margin:10px 0 4px;color:var(--tx1)}
.help-item-body ul{margin:4px 0 10px 18px;padding:0}
.help-item-body li{margin-bottom:3px}
/* Vídeo sugerido: é roteiro de conteúdo a gravar, não link quebrado. O rótulo
   virou pastilha para deixar isso explícito — o itálico solto lia como legenda
   de um player que não carregou. */
.help-video{font-size:11.5px;color:var(--tx1);margin-top:10px;padding:8px 10px;background:var(--bg2);border-radius:var(--r1);display:flex;flex-wrap:wrap;align-items:center;gap:8px;border-left:2px solid var(--br)}
.help-video-tag{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.4px;color:var(--tx2);white-space:nowrap}
/* Busca do manual. Com 20 tópicos, rolar até achar deixou de ser viável. */
.help-search{display:flex;align-items:center;gap:10px;margin-bottom:14px}
.help-search .fi{flex:1;min-width:0}
.help-count{font-size:11.5px;color:var(--tx2);white-space:nowrap;flex-shrink:0}
@media(max-width:600px){.help-search{flex-wrap:wrap}.help-count{width:100%}}
/* Densidade de layout */
body[data-density="compact"] th{padding:4px 10px;font-size:9px}
body[data-density="compact"] td{padding:3px 10px;font-size:12px;line-height:1.3}
body[data-density="compact"] .bgh{min-height:22px;font-size:11px;padding:1px 6px}
body[data-density="compact"] .tm{font-size:11px}
body[data-density="compact"] .bdg{font-size:9px;padding:0 4px}
body[data-density="compact"] .tw-h{padding:8px 12px}
body[data-density="dense"] th{padding:2px 8px;font-size:9px;text-transform:uppercase;letter-spacing:.3px;font-weight:700}
body[data-density="dense"] td{padding:2px 8px;font-size:11px;line-height:1.1}
body[data-density="dense"] .bgh{min-height:18px;font-size:10px;padding:1px 5px}
body[data-density="dense"] .tm{font-size:10px}
body[data-density="dense"] .bdg{font-size:9px;padding:0 3px;line-height:13px}
body[data-density="dense"] .tw-h{padding:6px 12px}
body[data-density="dense"] .cg{gap:8px}
body[data-density="dense"] .sc{padding:8px 12px}
/* Zebra / grupos especiais */
tbody tr:nth-child(even){background:var(--bg2)}
tbody#pgB tr:nth-child(even),tbody#rcB tr:nth-child(even){background:transparent}
tbody#pgB tr.zE,tbody#rcB tr.zE{background:var(--bg2)}
/* Sticky sticky/tabela ct-card */
.ct-card .tw-h{position:sticky;top:0;z-index:12;background:var(--bg3)}
.ct-card .ct-flt{position:sticky;z-index:11;background:var(--bg3)}
.ct-tbl thead th{position:sticky;background:var(--bg3);z-index:10;box-shadow:0 1px 0 var(--br)}
/* Checkbox row */
tr:has(>td>input[type=checkbox]){cursor:pointer}
tr:has(>td>input[type=checkbox]):hover{background:var(--blueL)}
td:has(>input[type=checkbox]){padding:8px 10px}
td>input[type=checkbox],th>input[type=checkbox]{width:18px;height:18px;accent-color:var(--blue);cursor:pointer}
th:has(>input[type=checkbox]){cursor:pointer;padding:8px 10px}

/* ══════════════════════════════════════════════════════════════════════
   PADROES DE ESTRUTURA (01/08/2026)
   Tres arranjos que o produto ja usa e que nao tinham classe: arvore
   hierarquica (Plano de Contas), mestre-detalhe (Clientes) e ciclo de status
   com acao em lote (Boletos). Vieram do projeto de design como
   vocabulary/patterns.css; aqui entram como bloco no fim do arquivo, porque
   este repo nao tem @import nem build — arquivo novo custaria uma tag com ?v=
   no index.html e uma entrada no shell do sw.js, que tem teste conferindo.
   Se a tela precisa de um arranjo novo, ele entra aqui, nao como style inline.
   ══════════════════════════════════════════════════════════════════════ */

/* ==== ARVORE (.arv) — Plano de Contas ================================
   Hierarquia rasa (3 niveis) com codigo contabil. O recuo vai em data-nivel e
   NAO em margin no filho: o recuo tem de valer na linha inteira, senao o hover
   e a faixa de selecao cortam antes do texto. */
.arv{width:100%;border-collapse:collapse}
.arv th{font-size:var(--fs-micro);font-weight:var(--fw-bold);text-transform:uppercase;letter-spacing:.14em;color:var(--tx2);background:var(--bg2);text-align:left;padding:9px 14px;white-space:nowrap}
.arv td{padding:0;border-bottom:1px solid var(--line2)}
/* Fora do zebra global — a regra e `tbody tr:nth-child(even)` mais acima neste
   arquivo, e a linha seguinte a ela (tbody#pgB/tbody#rcB) ja e o precedente de
   opt-out. Numa lista, listra par/impar ajuda a seguir a linha; numa arvore ela
   ocupa o unico canal que ja carrega significado, que e o fundo dizendo se a
   linha e grupo ou folha. Um sinal por canal.
   O :nth-child(2n) no seletor nao e enfeite: (0,2,2) contra (0,1,2) do zebra.
   Sem ele a regra empata em especificidade e o resultado passa a depender da
   ordem. */
.arv tbody tr:nth-child(2n){background:none}
/* 5 trilhas para 5 filhos: twisty, codigo, nome, valor, acoes. Contar filho a
   filho — uma trilha a menos joga o ultimo numa linha implicita, e o sintoma
   (linha com o dobro da altura) nao aponta para a contagem. */
.arv-l{display:grid;grid-template-columns:22px 92px 1fr auto auto;align-items:center;gap:10px;padding:9px 14px;font-size:13px;cursor:default;transition:background var(--t-fast,.12s)}
.arv-l:hover{background:var(--hv)}
.arv-l[data-nivel="2"]{padding-left:38px}
.arv-l[data-nivel="3"]{padding-left:62px}
/* Grupo (nivel 1 e 2) e estrutura, nao lancamento: fica em display, sem tinta
   semantica. Folha (nivel 3) e onde o dinheiro entra. */
.arv-l.grupo{font-weight:var(--fw-semibold);background:var(--bg1)}
.arv-l.grupo[data-nivel="2"]{background:none}
.arv-tw{background:none;border:none;color:var(--tx2);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;padding:0;border-radius:var(--r1)}
.arv-tw:hover{background:var(--bg2);color:var(--tx0)}
.arv-tw .lc{width:14px;height:14px;transition:transform var(--t-fast,.12s)}
.arv-tw[aria-expanded="false"] .lc{transform:rotate(-90deg)}
/* Folha nao tem twisty, mas o espaco dela fica: sem isso o codigo de cada folha
   desalinha do codigo do grupo acima. */
.arv-tw.vazio{visibility:hidden;pointer-events:none}
.arv-cod{font-family:var(--font-mono);font-size:11px;color:var(--tx2);letter-spacing:.02em}
.arv-nm{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.arv-nm .arv-tag{font-size:10px;font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.12em;color:var(--tx2);margin-left:8px}
.arv-vl{font-family:var(--font-mono);font-size:12px;color:var(--tx1);justify-self:end;white-space:nowrap}
.arv-ac{display:flex;gap:2px;justify-self:end}

/* ==== MESTRE-DETALHE (.md) — Clientes ================================
   Lista a esquerda, ficha a direita. A lista rola sozinha e o detalhe rola com a
   pagina: a lista e um indice, nao conteudo — quem esta lendo a ficha nao deve
   perder a lista de vista. */
.md{display:grid;grid-template-columns:308px 1fr;gap:14px;align-items:start}
.md-l{background:var(--bg3);border:1px solid var(--line);border-radius:var(--r2);overflow:hidden;position:sticky;top:0;max-height:calc(100vh - 120px);display:flex;flex-direction:column}
.md-l-h{padding:10px;border-bottom:1px solid var(--line2);display:flex;flex-direction:column;gap:8px}
.md-l-b{overflow-y:auto;flex:1}
.md-i{display:flex;flex-direction:column;gap:2px;width:100%;text-align:left;background:none;border:none;border-bottom:1px solid var(--line2);padding:10px 12px;cursor:pointer;font-family:inherit;color:var(--tx0);border-left:3px solid transparent;transition:background var(--t-fast,.12s)}
.md-i:hover{background:var(--hv)}
.md-i.on{background:var(--bg1);border-left-color:var(--pri)}
.md-i-nm{font-size:13px;font-weight:var(--fw-medium);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.md-i-mt{font-size:11px;color:var(--tx2);display:flex;align-items:center;gap:6px}
.md-d{background:var(--bg3);border:1px solid var(--line);border-radius:var(--r2);min-width:0}
.md-d-h{padding:16px 18px;border-bottom:1px solid var(--line2);display:flex;align-items:flex-start;justify-content:space-between;gap:12px;flex-wrap:wrap}
.md-d-t{font-family:var(--ff-display);font-size:18px;font-weight:var(--fw-bold);line-height:1.25}
.md-d-s{font-size:12px;color:var(--tx2);margin-top:3px;font-family:var(--font-mono)}
.md-d-b{padding:16px 18px}
/* Par rotulo/valor da ficha. Rotulo em micro caixa-alta, valor em corpo: a ficha
   e leitura, nao formulario — nao usar .fl/.fi para exibir valor salvo, porque
   campo de formulario convida a editar o que nao e editavel. */
.md-kv{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:14px 18px}
.md-k{font-size:var(--fs-micro);font-weight:var(--fw-bold);text-transform:uppercase;letter-spacing:.14em;color:var(--tx2);margin-bottom:3px}
.md-v{font-size:13px;color:var(--tx0)}
.md-v.mono{font-family:var(--font-mono);font-size:12px}
.md-v.vazio{color:var(--tx2)}

/* ==== CICLO DE STATUS (.cic) — Boletos ===============================
   O .bdg diz o estado atual; o .cic diz o caminho. Boleto nao e pago/nao-pago:
   ele percorre emissao > registro > pagamento > baixa, e o usuario precisa saber
   em que etapa a fila esta parada. */
.cic{display:flex;align-items:stretch;gap:0;flex-wrap:wrap;background:var(--bg3);border:1px solid var(--line);border-radius:var(--r2);overflow:hidden;margin-bottom:14px}
.cic-e{flex:1;min-width:132px;padding:12px 14px;border-right:1px solid var(--line2);display:flex;flex-direction:column;gap:3px}
.cic-e:last-child{border-right:none}
.cic-k{font-size:var(--fs-micro);font-weight:var(--fw-bold);text-transform:uppercase;letter-spacing:.14em;color:var(--tx2);display:flex;align-items:center;gap:6px}
.cic-k .lc{width:13px;height:13px}
.cic-n{font-family:var(--font-mono);font-size:19px;font-weight:var(--fw-semibold);color:var(--tx0)}
.cic-v{font-family:var(--font-mono);font-size:11px;color:var(--tx2)}
/* Etapa travada: onde a fila para. Recebe a tinta de atencao, e so ela — se toda
   etapa ganhar cor, nenhuma chama. */
.cic-e.trava{background:var(--amber-l);box-shadow:inset 3px 0 0 var(--amber)}
.cic-e.trava .cic-n{color:var(--amber)}
.cic-e.fim .cic-n{color:var(--green)}

/* ==== ACAO EM LOTE (.selb) ===========================================
   Aparece quando ha selecao. Ancorada no topo da tabela (nao flutuante no
   rodape): a acao pertence a lista, e a lista rola. */
.selb{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:9px 14px;background:var(--bg1);border-bottom:1px solid var(--line2)}
.selb-n{font-size:12px;font-weight:var(--fw-semibold);color:var(--tx0)}
.selb-n b{font-family:var(--font-mono)}
.selb-a{display:flex;gap:6px;flex-wrap:wrap;margin-left:auto}

@media(max-width:900px){
  .md{grid-template-columns:1fr}
  .md-l{position:static;max-height:none}
  /* No telefone a lista e a tela; a ficha vira a tela seguinte. Quem monta a
     tela decide qual dos dois esta visivel — o CSS so para de empilhar. */
  /* .arv-cod sai do fluxo aqui, sobram 4 filhos — 4 trilhas. */
  .arv-l{grid-template-columns:22px 1fr auto auto;gap:8px}
  .arv-cod{display:none}
  .arv-l[data-nivel="2"]{padding-left:26px}
  .arv-l[data-nivel="3"]{padding-left:42px}
}

/* ── Hover que era `onmouseover="this.style…"` (Fase 3 da CSP, 06/08/2026) ──────
   Três handlers de hover viravam seis handlers inline em JS só para mexer em
   estilo. Estado visual de ponteiro é trabalho de CSS: aqui não há função a
   chamar, nada a migrar para `data-act`, e o resultado é menos código do que
   antes. A cor variável do card de sugestão entra por custom property no
   próprio elemento (`--hov`), que é como CSS recebe um valor dinâmico sem que
   JS precise escrever estilo. */
.hov-lift{transition:transform .15s,box-shadow .15s}
.hov-lift:hover{transform:translateY(-2px);box-shadow:0 4px 16px rgba(0,0,0,.12)}
.hov-sug:hover{border-color:var(--hov,var(--pri));transform:translateY(-1px)}
.hov-row:hover{background:var(--bg2)}

/* ── Área de arrastar arquivo (Fase 3 da CSP, 06/08/2026) ─────────────────────
   Os seis handlers de drag existiam para escrever `this.style.borderColor` na
   entrada e apagar na saída. A cor do realce entra por `--dz` no elemento, e o
   estado é uma CLASSE — não estilo escrito por JS. Sobra ao JS só o que CSS não
   faz: marcar o estado e receber o arquivo. */
.dz{border:2px dashed var(--br);transition:border-color .15s}
.dz.dz-on{border-color:var(--dz,var(--pri))}
