
:root{
  --paper:#F5F1E7;
  --panel:#FFFFFF;
  --ink:#22262B;
  /* cor de texto PADRÃO do tema: nunca é personalizada (--ink é, em Aparência → Texto). O texto do menu cai aqui quando não há cor própria de menu — assim mudar o Texto do sistema não muda o menu. */
  --ink-base:#22262B;
  --ink-soft:#5B6068;
  --line:#DED5C0;
  /* Contorno das caixas (.panel/.login-card) — mais escuro/saturado que --line (usado em
     inputs/divisórias, onde um traço sutil é o efeito certo). --line contra --panel branco tinha
     contraste ~1.5:1, quase invisível; pedido do usuário: separar melhor a caixa do fundo da
     página nos dois temas. */
  --panel-border:#C7B89A;
  /* Cores extraídas de pixel real do logo (Logotipos/Code_Generated_Image (1).png, versão fundo
     claro) — pedido do usuário: "basear cores padrão pelos logos". --teal é o mesmo verde-azulado
     do texto "CONTROL"; --blue é o azul do anel externo do ícone; --navy é o azul-marinho de fundo
     do cartão do logo (usado no tema escuro e no rodapé do site).
     Apesar do nome, --teal/--teal-dark/--teal-rgb são o token de "cor de destaque ATUAL" — aplicarTema()
     sobrescreve os três em runtime pra qualquer ACCENT_PRESETS escolhido (o nome ficou de quando só
     existia uma cor). O valor literal abaixo é só o flash antes da hidratação (ver comentário perto de
     TEMA_CACHE_KEY) — decisão 2026-09-05: preset padrão virou 'azul', então o flash usa os mesmos
     valores do preset azul (idênticos a --blue/--blue-dark, coincidência esperada — os dois vêm do
     mesmo azul do anel do logo). */
  --teal:#165DD3;
  --teal-dark:#1148A8;
  --teal-rgb:22,93,211;
  /* Texto teal sobre fundo com tinta translúcida (badges "Aberto"/"Pago") — precisa ser mais escuro
     que --teal no tema claro (texto escuro em fundo claro) mas mais claro que --teal no tema escuro
     (senão fica 3.1:1 de contraste, abaixo do mínimo de 4.5:1 — medido de verdade). Por isso não dá
     pra só usar --teal-dark ou --teal direto nos dois temas; token dedicado, redefinido no bloco
     [data-theme="dark"] abaixo. */
  --badge-teal-text:var(--teal-dark);
  --blue:#165DD3;
  --blue-dark:#1148A8;
  --blue-rgb:22,93,211;
  --navy:#0F172A;
  --amber:#B8863B;
  --amber-rgb:184,134,59;
  --red:#AE4438;
  --red-rgb:174,68,56;
  --stamp:#B0453A;
  --input-bg:#FFFDF8;
  --surface-alt:#F3EFE3;
  --surface-subtle:#FBFAF5;
  --hover-tint:#FAF7EF;
  --badge-neutral-bg:#EAE6DA;
  --text-faint:#C9C2B1;
  --amber-tint-bg:#FBF6EA;
  --red-tint-bg:#FBF2F0;
  --nav-bg:#FBF9F3;
  --dropdown-bg:#FFFFFF;
  /* Redesign (item 8) — tokens de sombra/raio pro visual "nota" inspirado no Google Keep. Cards
     passam a se apoiar mais em sombra suave do que em borda dura; --radius-card sobe de 12px pra
     16px em painéis/cartões. Sombra escura demais no tema escuro só cria uma mancha invisível
     contra um fundo já escuro — por isso o valor é redefinido em :root[data-theme="dark"] abaixo,
     mais forte, em vez de reusar o mesmo rgba. */
  --radius-card:16px;
  --shadow-card:0 1px 2px rgba(34,38,43,.06),0 1px 1px rgba(34,38,43,.04);
  --shadow-card-hover:0 10px 24px -8px rgba(34,38,43,.16);
}
:root[data-theme="dark"]{
  /* Fundo do tema escuro passou a ser o azul-marinho de verdade do logo (Code_Generated_Image (2).png,
     versão fundo escuro) em vez de um cinza neutro genérico — mesmo pedido de basear as cores no logo. */
  --paper:#0F172A;
  --panel:#1A2540;
  --ink:#EDEAE2;
  --ink-base:#EDEAE2;
  --ink-soft:#A8A296;
  --line:#2C3A5C;
  --panel-border:#48598A;
  /* --teal/--teal-dark/--teal-rgb (nome legado — é o token de "cor de destaque ATUAL", ver comentário
     equivalente no :root claro acima) só valem como flash antes de aplicarTema() hidratar de verdade;
     desde 2026-09-05 usam os valores do preset 'azul' (o novo padrão), com --teal-dark recalculado —
     ver comentário em ACCENT_PRESETS.azul sobre por que não dá pra usar o mesmo valor de
     escuro.main/escuro.dark que o preset "deveria" ter e ainda passar em contraste. */
  --teal:#3B82F6;
  --teal-dark:#4C8DF5;
  --teal-rgb:59,130,246;
  /* Pro azul, quem é mais CLARO (e por isso dá mais contraste no fundo tingido do badge) é
     --teal-dark, não --teal (o oposto do teal original, onde --teal era o mais claro dos dois) —
     ainda assim só chega a 3.88:1 contra esse fundo específico, abaixo dos 4.5:1 que o teal batia
     (4.91:1); é a melhor opção disponível entre os dois tokens sem trocar a cor de destaque em si,
     residual conhecido, não perseguido mais a fundo aqui. */
  --badge-teal-text:var(--teal-dark);
  --blue:#3B82F6;
  --blue-dark:#1C6AE2;
  --blue-rgb:59,130,246;
  --navy:#0F172A;
  /* --red do tema claro (#AE4438) reaproveitado sem ajuste aqui até agora — contraste medido contra
     --panel ficava em 2.66:1 e contra as caixas de aviso vermelhas (--red-tint-bg) em 2.48:1, bem
     abaixo do mínimo de 4.5:1 (texto normal). Usado em avisos importantes (Zona de Risco, restaurar
     backup, erros de formulário), não só decoração — precisa ser legível de verdade. Versão mais
     clara/salmão só pro tema escuro, testada e chegando a 5-6.4:1 em todos os fundos onde é usado. */
  --red:#E08072;
  --red-rgb:224,128,114;
  --stamp:#C96A5C;
  --input-bg:#1D2A4A;
  --surface-alt:#1D2A4A;
  --surface-subtle:#17223D;
  --hover-tint:#1D2A4A;
  --badge-neutral-bg:#293659;
  --text-faint:#5C6A8C;
  --amber-tint-bg:#3A331F;
  --red-tint-bg:#3A2624;
  --nav-bg:#111D38;
  --dropdown-bg:#1A2540;
  --shadow-card:0 1px 2px rgba(0,0,0,.4);
  --shadow-card-hover:0 10px 24px -8px rgba(0,0,0,.55);
}
*{box-sizing:border-box;}
body{margin:0;background:var(--paper);color:var(--ink);font-family:'Inter',sans-serif;-webkit-font-smoothing:antialiased;}
h1,h2,h3{font-family:'Fraunces',serif;font-weight:600;margin:0 0 4px;}
.mono{font-family:'JetBrains Mono',monospace;}
input,select,button,textarea{font-family:inherit;font-size:14px;}
input,select,textarea{padding:9px 11px;border:1px solid var(--line);border-radius:6px;background:var(--input-bg);color:var(--ink);width:100%;}
/* Item 12.250 — container dos Secure Fields do Mercado Pago (iframe): mesma aparência dos <input> acima. */
.secure-field-container{height:38px;padding:0 11px;border:1px solid var(--line);border-radius:6px;background:var(--input-bg);width:100%;box-sizing:border-box;overflow:hidden;}
/* Pedido do usuário, corrigindo o item 12.233/12.234: "o que falei que os campos de texto estão
   pequenos é na LARGURA... volta o tamanho da caixa de texto anterior" — o aumento de fonte/padding
   por tela foi remendo errado (o problema nunca foi o tamanho do TEXTO); revertido pro tamanho
   único de sempre. O problema de fato era a LARGURA do formulário de Dados Fiscais, resolvido
   alargando .login-card (que o contém) por tela — ver a regra logo abaixo dele neste arquivo. */
/* Campo travado (ex.: OS já faturada/paga) — antes disso um campo "disabled" ficava quase idêntico a
   um campo normal neste tema (só o texto ficava um pouco mais claro, fácil de não perceber). Regra
   global: qualquer input/select/textarea desabilitado no sistema inteiro fica visivelmente diferente
   — fundo hachurado, borda tracejada, cursor de bloqueado. */
input:disabled,select:disabled,textarea:disabled{
  background-image:repeating-linear-gradient(135deg, rgba(127,127,127,.14) 0 6px, transparent 6px 12px);
  border-style:dashed;
  color:var(--muted-ink,var(--ink));
  opacity:.7;
  cursor:not-allowed;
}
input:focus,select:focus,textarea:focus{outline:2px solid var(--teal);outline-offset:1px;}
input[type=checkbox],input[type=radio]{accent-color:var(--teal);}
/* Pedido do usuário: botão de "mostrar senha" (olho) em todo campo de senha do sistema — envolve só
   o <input>, o <label> continua fora do wrap. */
.pwd-wrap{position:relative;}
.pwd-wrap input{padding-right:34px;}
.pwd-toggle-btn{position:absolute;right:4px;top:50%;transform:translateY(-50%);background:none;border:none;cursor:pointer;padding:6px;color:var(--ink-soft);display:inline-flex;align-items:center;justify-content:center;}
.pwd-toggle-btn:hover{color:var(--ink);}
label{display:block;font-size:12px;color:var(--ink-soft);margin-bottom:4px;font-weight:600;letter-spacing:.02em;text-transform:uppercase;}
.field{margin-bottom:12px;}
button{cursor:pointer;border:none;border-radius:8px;padding:10px 16px;font-weight:600;font-size:13.5px;transition:transform .08s ease,box-shadow .12s ease;}
button:active{transform:scale(.97);}
.btn-primary{background:var(--teal);color:#fff;}
.btn-primary:hover{background:var(--teal-dark);}
.btn-secondary{background:transparent;color:var(--teal);border:1px solid var(--teal);}
.btn-danger{background:transparent;color:var(--red);border:1px solid var(--red);}
.btn-amber{background:var(--amber);color:#fff;}
.btn-ghost{background:transparent;color:var(--ink-soft);}
.btn-sm{padding:6px 10px;font-size:12.5px;border-radius:6px;}
/* Botão "← Voltar" (Clientes) — pílula com um círculo-ícone dentro, reaproveitando o mesmo motivo
   visual arredondado do mockup (chips, busca, FAB) em vez de um link de texto solto. */
.btn-voltar{display:inline-flex;align-items:center;gap:7px;background:var(--surface-alt);border-radius:20px;padding:5px 14px 5px 5px;color:var(--ink-soft);font-weight:600;font-size:12.5px;margin-bottom:10px;transition:background-color .12s ease,color .12s ease;}
.btn-voltar:hover{background:rgba(var(--teal-rgb),.14);color:var(--teal-dark);}
/* Fundo em teal translúcido (não --panel) — em tema escuro --panel/--surface-alt ficam quase idênticos
   e o círculo do ícone sumia contra a pílula; teal também casa com o resto dos "chips" do redesign. */
.btn-voltar-icon{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;border-radius:50%;background:rgba(var(--teal-rgb),.18);color:var(--teal-dark);font-size:12px;flex-shrink:0;}
a{color:var(--teal-dark);}

/* LOGIN */
/* display:none por padrão (não :flex) — o boot (INIT, fim do arquivo) tenta restaurar a sessão
   (local via window.storage, API via refresh token) antes de decidir se mostra login; sem isso, a
   tela de login sempre "piscava" por uma fração de segundo em todo carregamento de página, mesmo
   quando ia restaurar a sessão com sucesso logo em seguida (achado real reportado pelo usuário). Só
   aparece de verdade quando o boot conclui que não há nenhuma sessão pra restaurar, ou explicitamente
   no logout. */
#loginScreen{min-height:100vh;display:none;align-items:center;justify-content:center;padding:20px;}
#resetSenhaScreen{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:20px;}
#trocaSenhaObrigatoriaScreen{min-height:100vh;display:none;align-items:center;justify-content:center;padding:20px;}
.login-card{background:var(--panel);border:1px solid var(--panel-border);border-radius:14px;padding:40px 34px;width:100%;max-width:380px;box-shadow:0 18px 40px -20px rgba(34,38,43,.25);}
/* Item 12.237 (pedido do usuário): a largura alargada por tela (520px tablet/620px desktop) do
   item 12.235 era só pra caber o formulário de Dados Fiscais (vários campos em grid2) que ficava
   DENTRO deste card. Esse formulário se mudou pro pop-up próprio (.bloqueio-form-box, fora do
   .login-card) — sem ele aqui dentro, o card volta a ser só e-mail/senha, então volta à largura
   original de sempre (380px, igual no celular/tablet/desktop). */
.login-card h1{font-size:30px;letter-spacing:-.01em;}
.login-mark{width:44px;height:44px;border-radius:10px;background:var(--teal);color:#fff;display:flex;align-items:center;justify-content:center;font-family:'Fraunces',serif;font-weight:700;font-size:20px;margin-bottom:16px;}
.login-sub{color:var(--ink-soft);font-size:13px;margin-bottom:22px;}
.error-msg{color:var(--red);font-size:13px;margin-top:8px;min-height:16px;}

/* APP SHELL */
#app{display:none;}
header.topbar{background:#22262B;color:#F5F1E7;padding:14px 22px;display:flex;align-items:center;justify-content:space-between;position:sticky;top:0;z-index:40;}
.brand{display:flex;align-items:center;gap:10px;}
.brand .mark{width:32px;height:32px;border-radius:8px;background:var(--amber);color:#fff;display:flex;align-items:center;justify-content:center;font-family:'Fraunces',serif;font-weight:700;}
.brand-name{font-family:'Fraunces',serif;font-size:19px;font-weight:600;letter-spacing:-.01em;line-height:1.15;}
.brand-tagline{font-size:11px;color:#B9B2A2;letter-spacing:.02em;line-height:1.2;}
.user-chip{font-size:12.5px;color:#D7D1C4;display:flex;align-items:center;gap:10px;min-width:0;}
/* Tablet (681–960px): o cabeçalho tinha ~930px de conteúdo e estourava a largura (a página inteira rolava de lado). Compacta sem esconder
   nada essencial: sem o slogan, busca e seletor de filial mais estreitos e só o avatar do usuário (o nome fica no título do avatar). */
@media(min-width:681px) and (max-width:960px){
  header.topbar{padding:12px 14px;}
  .brand-tagline{display:none;}
  #topbarRight{gap:8px !important;}
  #buscaCodigoGlobalModulo{width:90px !important;}
  #buscaCodigoGlobal{width:110px !important;}
  #filialAtivaSelect{max-width:100px !important;}
  #userNameChip{display:none;}
  .brand-name{white-space:nowrap;}
}
@media(min-width:681px) and (max-width:760px){
  #buscaCodigoGlobalModulo{display:none !important;} /* tablet estreito: a busca fica só com o campo de texto */
}
/* Achado real (responsividade): mesmo problema do #filialAtivaSelect (ver renderFilialSwitcher() em
   auth.js) — um nome de usuário comprido, sem limite nenhum, contribuía pro topbar estourar a
   largura da tela. Trunca com reticências em vez de crescer sem limite (não resolve sozinho o
   estouro em telas ~681-1024px quando #topbarRight tem MUITOS itens — ver docs/SISTEMA.md, item 2). */
#userNameChip{max-width:130px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
/* Central de Ajuda (topbar) — substitui os botões separados de Manual/Suporte/link externo por um
   único ícone com menu; ver toggleAjudaMenu()/renderAjudaMenu(). */
#ajudaMenuDropdown{display:none;position:absolute;top:calc(100% + 6px);right:0;width:210px;background:var(--dropdown-bg);border:1px solid var(--line);border-radius:8px;box-shadow:0 12px 30px -12px rgba(0,0,0,.25);z-index:60;padding:4px;}
.ajuda-menu-item{display:flex;align-items:center;gap:8px;width:100%;padding:9px 10px;font-size:13px;text-align:left;background:none;border:none;border-radius:6px;color:var(--ink);text-decoration:none;cursor:pointer;box-sizing:border-box;}
.ajuda-menu-item:hover{background:var(--line);}
/* Mockup "JLOControl Redesign Keep" — círculo com as iniciais do usuário no topbar, ao lado do nome. */
.user-avatar{width:26px;height:26px;border-radius:50%;background:var(--teal);color:#fff;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:11px;flex-shrink:0;}
#sidebarCollapseBtn{background:none;border:1px solid rgba(255,255,255,.3);color:#fff;padding:7px 10px;border-radius:6px;flex-shrink:0;line-height:1;}

.app-body{display:flex;align-items:flex-start;}
.sidebar{width:240px;flex-shrink:0;background:var(--nav-bg);border-right:1px solid var(--line);min-height:calc(100vh - 57px);position:sticky;top:57px;overflow-y:auto;overflow-x:hidden;padding:14px 10px;box-sizing:border-box;transition:width .15s ease,padding .15s ease;}
.sidebar.collapsed{width:0;min-width:0;padding:0;border-right:none;overflow:hidden;}
/* Item 8 — menu lateral com "auto esconder" (preferência do usuário, Aparência). Diferente do
   .collapsed puro (width:0 — nada pra passar o mouse em cima, então nunca reapareceria), o modo auto
   esconder deixa uma tira fina de 6px sempre visível na borda esquerda — é nela que o :hover funciona.
   Ao passar o mouse, vira position:fixed flutuando POR CIMA do conteúdo (não empurra .main pro lado,
   senão a página inteira "pula" toda vez que o mouse entra/sai do menu). Só faz sentido com mouse de
   verdade — não entra em telas de toque (tablet já tem seu próprio modo rail fixo, @media 681-1024px
   acima). */
@media(min-width:1025px){
  .sidebar.auto-hide.collapsed{width:6px;min-width:6px;padding:0;overflow:hidden;background:var(--teal);opacity:.4;cursor:pointer;transition:opacity .15s ease;}
  .sidebar.auto-hide.collapsed:hover{opacity:1;}
  .sidebar.auto-hide.collapsed:hover{
    position:fixed;top:57px;left:0;bottom:0;width:240px;min-width:240px;padding:14px 10px;
    background:var(--nav-bg);border-right:1px solid var(--line);overflow-y:auto;overflow-x:hidden;
    box-shadow:12px 0 28px -12px rgba(0,0,0,.35);z-index:55;
  }
}
.sidebar-group{display:flex;align-items:center;justify-content:space-between;gap:6px;width:100%;text-align:left;background:none;border:none;border-radius:22px;padding:11px 14px;color:var(--nav-text, var(--ink-soft));font-weight:600;font-size:13.5px;margin-bottom:2px;white-space:nowrap;transition:background-color .12s ease;}
.sidebar-group:hover{background:var(--hover-tint);}
.sidebar-group.active{color:#fff;background:var(--teal);}
.sidebar-caret{font-size:10px;opacity:.55;flex-shrink:0;}
.sidebar-children{display:flex;flex-direction:column;padding-left:10px;margin:2px 0 10px;border-left:2px solid var(--line);}
.sidebar-child{display:block;width:100%;text-align:left;background:none;border:none;border-radius:18px;padding:9px 14px;color:var(--ink-soft);font-weight:600;font-size:12.5px;margin:1px 0;white-space:nowrap;transition:background-color .12s ease;}
.sidebar-child:hover{background:var(--hover-tint);}
.sidebar-child.active{background:var(--teal);color:#fff;}
.sidebar-subchildren{display:flex;flex-direction:column;padding-left:14px;margin:0 0 4px;border-left:2px solid var(--line);}
.sidebar-subchild{display:block;width:100%;text-align:left;background:none;border:none;border-radius:16px;padding:7px 12px;color:var(--ink-soft);font-weight:600;font-size:11.5px;margin:1px 0;white-space:nowrap;transition:background-color .12s ease;}
.sidebar-icon{margin-right:9px;}
.sidebar-subchild:hover{background:var(--hover-tint);}
.sidebar-subchild.active{background:var(--teal);color:#fff;}
.menu-order-row{display:flex;align-items:center;gap:8px;padding:6px 4px;border-radius:6px;}
.menu-order-row:hover{background:var(--hover-tint);}
.menu-order-row.dragging{opacity:.4;}
.drag-handle{cursor:grab;color:var(--ink-soft);font-size:15px;user-select:none;flex-shrink:0;}
tr.dragging, .cliente-card.dragging{opacity:.4;}
.order-controls{display:inline-flex;align-items:center;gap:7px;}
.order-controls .drag-handle{font-size:17px;}
.order-arrows{display:flex;flex-direction:column;border:1px solid var(--line);border-radius:5px;overflow:hidden;flex-shrink:0;}
.order-arrow-btn{display:flex;align-items:center;justify-content:center;width:22px;height:15px;padding:0;border:none;border-radius:0;background:var(--surface-alt);color:var(--ink-soft);font-size:9px;line-height:1;}
.order-arrow-btn:first-child{border-bottom:1px solid var(--line);}
.order-arrow-btn:hover:not(:disabled){background:var(--hover-tint);color:var(--ink);}
.order-arrow-btn:disabled{opacity:.35;cursor:default;}
.order-pos-input{width:44px;padding:4px 2px;text-align:center;font-size:12px;flex-shrink:0;}

main{flex:1;min-width:0;padding:24px 22px 60px;}
.view{display:none;}
.view.active{display:block;}
.panel{background:var(--panel);border:1px solid var(--panel-border);border-radius:var(--radius-card);padding:22px;margin-bottom:20px;box-shadow:var(--shadow-card);}
.panel-head{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:10px;margin-bottom:16px;}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:12px;}
.grid3{display:grid;grid-template-columns:1fr 1fr 1fr;gap:12px;}
.grid4{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;}
/* Item 12.238 (pedido do usuário) — Dados Fiscais: "Número" e "UF" são bem mais curtos que os
   campos ao lado (Endereço/Complemento/Bairro/Cidade), mas .grid3 dá a mesma largura pra todos —
   Número ficava enorme e UF sozinho numa linha só pra ele. 2 colunas largas + 1 estreita no meio,
   sem mexer em .grid3 (usado em várias outras telas). Coluna estreita ainda mais reduzida e
   centralizada (pedido do usuário) — o campo estreito fica entre os dois largos, não mais na
   ponta; texto do input também centralizado (Número/UF são curtos, ficam melhor assim). */
.grid-doc-3{display:grid;grid-template-columns:4fr 1fr 4fr;gap:12px;}
.grid-doc-3 .field.campo-estreito input{text-align:center;}
@media(max-width:720px){.grid2,.grid3,.grid4,.grid-doc-3{grid-template-columns:1fr;}}
/* .grid4 é reaberto para 2 colunas dentro do breakpoint mobile (max-width:680px) mais abaixo neste
   arquivo — depende da ordem das regras (a de 680 vem depois e vence por cascata). Se mover blocos de
   CSS, mantenha a regra de 680 depois desta. */

table{width:100%;border-collapse:collapse;font-size:13.5px;}
/* Tabelas com muitas colunas (OS, contas, permissões etc.) podem ficar mais largas que o espaço
   disponível entre o breakpoint mobile (680px, onde viram cards) e telas grandes. Sem isso, o excesso
   simplesmente some (body tem overflow-x:hidden) em vez de poder ser rolado. */
[id$="TabelaWrap"], [id^="cfTabelaWrap"], #fechamentoListaWrap, #fechamentosListaWrap,
#caixaFechamentoWrap, #caixaAnterioresListaWrap{overflow-x:auto;-webkit-overflow-scrolling:touch;}
th{text-align:left;font-size:11px;text-transform:uppercase;letter-spacing:.04em;color:var(--ink-soft);border-bottom:2px solid var(--line);padding:8px 8px;}
td{padding:10px 8px;border-bottom:1px solid var(--line);vertical-align:middle;}
tr:hover td{background:var(--hover-tint);}
/* Item 8 — linha-cartão híbrida: cada linha de .responsive-table (o padrão já usado por quase toda
   lista do sistema — 51 telas) vira um "cartão" arredondado com sombra suave, mas o conteúdo continua
   alinhado em colunas — ainda lê como tabela, só não parece mais uma grade crua. Aplica em toda tela
   que já usa essa classe, sem precisar mexer na marcação de cada uma — só CSS compartilhado.
   border-collapse:separate (não :collapse) porque box-shadow/border-radius em <tr> não funciona
   direito com bordas colapsadas entre células. Só a partir de 681px — abaixo disso .responsive-table
   já vira uma pilha de cards via display:block (regra própria, mais antiga, ver @media max-width:680px
   abaixo); as duas regras não podem se sobrepor, senão o :first-child/:last-child arredonda cantos
   errados de um <td> que virou bloco cheio-de-largura em vez de célula. */
@media(min-width:681px){
  table.responsive-table{border-collapse:separate;border-spacing:0 8px;}
  table.responsive-table tbody tr{background:var(--panel);box-shadow:var(--shadow-card);transition:box-shadow .12s ease;}
  table.responsive-table tbody tr:hover{box-shadow:var(--shadow-card-hover);}
  table.responsive-table tbody td{border-bottom:none;padding:11px 10px;}
  table.responsive-table tbody td:first-child{border-top-left-radius:12px;border-bottom-left-radius:12px;padding-left:14px;}
  table.responsive-table tbody td:last-child{border-top-right-radius:12px;border-bottom-right-radius:12px;padding-right:14px;}
  /* Densidade compacta (Aparência → "Listas mais compactas") — preferência global, não por tela, pra
     não precisar de um controle repetido em cada uma das ~30 telas de lista. */
  body.densidade-compacta table.responsive-table{border-spacing:0 4px;}
  body.densidade-compacta table.responsive-table tbody td{padding:6px 10px;font-size:12.5px;}
}
/* Ações da linha (.row-actions, já usado em boa parte das listas) só ficam escondidas até o hover A
   PARTIR do desktop de verdade (>1024px, onde existe mouse) — abaixo disso (tablet, toque como
   entrada principal) ficam sempre visíveis, senão nunca apareceriam pra quem não tem hover. */
@media(min-width:1025px){
  table.responsive-table .row-actions{opacity:0;transition:opacity .12s ease;}
  table.responsive-table tbody tr:hover .row-actions,
  table.responsive-table tbody tr:focus-within .row-actions{opacity:1;}
}

.badge{display:inline-flex;align-items:center;gap:5px;padding:3px 9px;border-radius:20px;font-size:11px;font-weight:700;letter-spacing:.02em;}
.badge-aberto{background:rgba(var(--teal-rgb),.13);color:var(--badge-teal-text);}
/* Chip clicável pra seleção múltipla (ex: Tipos de Serviço aplicáveis a um Checklist) — visual de
   "tag" que liga/desliga ao clicar, em vez de uma lista crua de checkboxes pequenas. */
.chip-toggle{display:inline-flex;align-items:center;gap:6px;padding:6px 14px;border-radius:20px;font-size:13px;font-weight:600;border:1px solid var(--line);background:var(--panel);color:var(--ink-soft);cursor:pointer;user-select:none;transition:background-color .12s ease,border-color .12s ease,color .12s ease;}
.chip-toggle:hover{border-color:var(--teal);}
.chip-toggle input{position:absolute;opacity:0;width:0;height:0;pointer-events:none;}
.chip-toggle.selecionado{background:rgba(var(--teal-rgb),.14);border-color:var(--teal);color:var(--teal-dark);}
.chip-toggle-wrap{display:flex;flex-wrap:wrap;gap:8px;}
.chip-toggle-acoes{display:flex;align-items:center;gap:10px;margin-bottom:10px;flex-wrap:wrap;}
.chip-toggle-acoes button{background:none;border:none;padding:0;color:var(--teal-dark);font-size:12.5px;font-weight:600;cursor:pointer;text-decoration:underline;}
.chip-toggle-contador{font-size:12.5px;color:var(--ink-soft);}
.stamp{display:inline-block;border:2px solid var(--stamp);color:var(--stamp);font-family:'Fraunces',serif;font-weight:700;font-size:10.5px;letter-spacing:.08em;padding:2px 8px;border-radius:4px;transform:rotate(-4deg);text-transform:uppercase;}
.os-status-pill{width:auto;padding:6px 14px;border-radius:20px;font-size:12.5px;font-weight:700;border:1px solid var(--line);background:var(--badge-neutral-bg);color:var(--ink-soft);cursor:pointer;}
.color-swatch-btn{width:30px;height:30px;border-radius:50%;cursor:pointer;padding:0;flex-shrink:0;}

.toolbar{display:flex;gap:10px;flex-wrap:wrap;align-items:flex-end;margin-bottom:14px;}
.toolbar .field{margin-bottom:0;min-width:150px;}
.empty-state{text-align:center;padding:40px 20px;color:var(--ink-soft);}
.empty-state h3{color:var(--ink);}
.hidden{display:none !important;}
.divider{height:1px;background:var(--line);margin:18px 0;}
.small{font-size:12px;color:var(--ink-soft);}
/* Pedido do usuário: "os logos do mercado pago estão ficando muito pequenos... diferenciar os
   tamanhos de tela". Selo de "pagamento protegido" (login bloqueado, Configurações → Assinatura,
   pop-up de assinatura vencida) — mesmos 3 breakpoints do resto do arquivo. */
.selo-mp-logo{height:24px;width:auto;display:block;}
@media(min-width:681px) and (max-width:1024px){.selo-mp-logo{height:36px;}}
@media(min-width:1025px){.selo-mp-logo{height:46px;}}
.horas-normal{font-size:15px;font-weight:700;}
.right{text-align:right;}
/* Antes era background:#22262B fixo (o valor exato de --ink no tema claro) — bar sempre "invertida"
   pra escuro, o que passava despercebido no tema escuro (perto de --panel) mas ficava um bloco preto
   destoante no tema claro, junto do --amber do valor. Trocado pros tokens de tema pra acompanhar o
   resto do painel nos dois temas. */
.total-strip{display:flex;justify-content:space-between;align-items:center;background:var(--surface-alt);color:var(--ink);border:1px solid var(--line);padding:14px 18px;border-radius:10px;margin-top:14px;}
.total-strip .val{font-family:'JetBrains Mono',monospace;font-size:22px;font-weight:700;color:var(--amber);}
.chk-row{display:flex;align-items:center;gap:10px;padding:8px 6px;border-bottom:1px solid var(--line);}
.chk-row input[type=checkbox]{width:auto;}
.search-select{position:relative;}
.search-select input{cursor:text;}
.search-select-list{position:absolute;top:calc(100% + 4px);left:0;right:0;background:var(--dropdown-bg);border:1px solid var(--line);border-radius:8px;max-height:220px;overflow-y:auto;z-index:60;box-shadow:0 12px 30px -12px rgba(0,0,0,.25);display:none;}
.search-select-list.open{display:block;}
.search-select-list div{padding:9px 12px;font-size:13.5px;cursor:pointer;}
.search-select-list div:hover, .search-select-list div.active{background:var(--surface-alt);}
.search-select-list .none{color:var(--ink-soft);cursor:default;}
#buscaCodigoGlobalResultados{min-width:360px;max-width:min(560px,92vw);max-height:360px;}
/* Menu único "Recibo ▾" — substitui a fileira de até 4 botões (Baixar PDF/Imprimir/WhatsApp/E-mail)
   por um só botão com menu suspenso, pedido do usuário: "criar um único botão unificando estas
   ações" (evita a fileira de botões estourar a largura da tela/célula da tabela no celular). */
.recibo-menu-lista{min-width:200px;background:var(--dropdown-bg);border:1px solid var(--line);border-radius:8px;box-shadow:0 12px 30px -12px rgba(0,0,0,.25);overflow:hidden;}
/* Achado real: quando a lista/card tem poucas linhas (ex.: só 1 orçamento), o container que envolve
   a tabela/cards (`[id$="TabelaWrap"]`, ver overflow-x:auto acima) fica mais baixo que o menu
   suspenso do Recibo — e por causa de uma peculiaridade do CSS (overflow-x:auto força overflow-y a
   computar como "auto" também, mesmo sem ser escrito), esse container passa a CORTAR o menu, que
   antes era `position:absolute` (contido nele). Corrigido: o menu passa a ser criado dinamicamente e
   anexado direto no `<body>` como `position:fixed`, com a posição calculada em JS a partir do botão
   que o abriu (mesmo padrão já usado por `.cal-criar-menu`, que tem exatamente esse mesmo problema
   resolvido) — assim ele nunca fica preso dentro do overflow de nenhum ancestral. */
.recibo-menu-lista.recibo-menu-flutuante{position:fixed;z-index:999;}
.recibo-menu-lista button{display:block;width:100%;text-align:left;padding:10px 14px;background:none;border:none;border-radius:0;color:var(--ink);font:inherit;font-size:13.5px;font-weight:500;cursor:pointer;white-space:nowrap;}
.recibo-menu-lista button:hover{background:var(--hover-tint);}
.recibo-menu-lista button[disabled]{opacity:.5;cursor:default;}
.recibo-menu-lista button[disabled]:hover{background:none;}
#buscaCodigoGlobalResultados > div{padding:9px 12px;border-bottom:1px solid var(--line);display:flex;align-items:baseline;gap:10px;color:var(--ink);}
#buscaCodigoGlobalResultados > div:last-child{border-bottom:none;}
#buscaCodigoGlobalResultados .busca-item-modulo{flex:0 0 108px;max-width:108px;font-weight:700;font-size:11px;text-transform:uppercase;letter-spacing:.02em;color:var(--amber, #a06b1f);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding:0;border:none;}
#buscaCodigoGlobalResultados .busca-item-info{flex:1;min-width:0;font-size:13px;color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding:0;border:none;}
#buscaCodigoGlobalResultados .busca-item-info .busca-item-codigo{font-weight:600;color:var(--ink);}
#buscaCodigoGlobalResultados .busca-item-mais{color:var(--ink-soft);font-style:italic;cursor:default;font-size:12px;text-align:center;padding:8px 12px;display:block;}
.visita-box{background:var(--amber-tint-bg);border:1px dashed var(--amber);border-radius:8px;padding:12px 14px;margin-top:4px;}
.checklist-box{border:1px solid var(--line);border-radius:8px;padding:12px 14px;margin-top:4px;background:var(--surface-subtle);}
.form-section{border:1px solid var(--line);border-radius:10px;padding:18px 20px;margin-bottom:16px;background:var(--surface-subtle);}
.form-section:last-child{margin-bottom:0;}
.form-section-title{font-family:'Fraunces',serif;font-weight:600;font-size:15px;color:var(--ink);margin:0 0 16px;padding-bottom:10px;border-bottom:1px solid var(--line);}
.form-section .field:last-child{margin-bottom:0;}
/* Mockup "JLOControl Redesign Keep" — formulário em "cartões de nota" (usado por enquanto só no
   piloto de Clientes, ver renderClientes()). Cor no topo por categoria, igual ao .caixa-card do
   Dashboard já faz com os pins. */
.form-note-card{background:var(--panel);border-radius:16px;box-shadow:var(--shadow-card);padding:20px 22px;margin-bottom:16px;position:relative;overflow:hidden;}
.form-note-accent{position:absolute;top:0;left:0;right:0;height:4px;}
/* Campo "fluido": sem borda visível até o hover/foco — só uma linha embaixo, que só aparece de
   verdade no foco. O rótulo (label, já maiúsculo/cinza por padrão) continua dando o contorno do campo
   mesmo sem borda, então a legibilidade não depende só da borda. outline:none no foco é proposital
   (mesma decisão de design do mockup) — a cor de fundo + a linha embaixo já são o indicador de foco. */
.fluid-field input, .fluid-field select, .fluid-field textarea{border:none;border-bottom:1.5px solid transparent;background:transparent;border-radius:0;padding:6px 4px;transition:background-color .12s ease,border-color .12s ease;font-family:inherit;resize:vertical;}
.fluid-field input:hover, .fluid-field select:hover, .fluid-field textarea:hover{background:var(--hover-tint);border-radius:6px 6px 0 0;}
.fluid-field input:focus, .fluid-field select:focus, .fluid-field textarea:focus{background:var(--hover-tint);border-bottom-color:var(--teal);border-radius:6px 6px 0 0;outline:none;}
/* Endereço de Cliente preenchido via busca de CEP (buscarCepClienteEndereco()) — campo travado,
   fundo diferenciado avisa que veio automático; apagar o CEP destrava. */
.fluid-field input:disabled{background:var(--surface-alt);color:var(--ink-soft);cursor:not-allowed;}
/* Ações flutuantes do formulário de Clientes (mockup) — só existem enquanto a tela de Clientes está
   com permissão de gerenciar (podeGerenciar). padding-bottom no wrapper do formulário (76px, ver
   renderClientes()) evita que cubram o fim do próprio formulário.
   Pedido do usuário: separados só por margin-right:auto ainda liam como um bloco só (mesma pílula
   preta contínua por trás dos dois); ancorados em cantos opostos (left/right:24px) separou de
   verdade mas espalhou demais — pedido seguinte foi "separados, porém centralizados". Resolvido com
   um wrapper (.form-floating-actions) centralizado na tela (mesmo left:50%/transform de antes),
   mas SEM fundo próprio — só os 2 filhos (.form-floating-cancel e o botão principal) têm pílula/
   fundo individual, com gap real entre eles. Continuam 2 formas visuais distintas, só que como um
   par centralizado em vez de espalhado nos cantos. */
.form-floating-actions{position:fixed;left:50%;bottom:24px;transform:translateX(-50%);display:flex;align-items:center;gap:14px;z-index:40;}
/* padding vertical 0 de propósito — o Cancelar (sem btn-sm, mesma altura do botão principal) já traz
   seu próprio padding vertical; somar padding vertical AQUI também deixaria a pílula mais alta que o
   botão ao lado (os dois padding-top/bottom se empilhando). Só o padding horizontal fica aqui, pra
   dar a "moldura" da pílula sem mexer na altura. */
.form-floating-cancel{background:#22262B;border-radius:30px;padding:0 18px 0 22px;display:flex;align-items:center;gap:12px;box-shadow:0 14px 32px -10px rgba(0,0,0,.4);}
/* Pedido do usuário: "Salvar Alterações"/"Cadastrar Cliente" mais arredondado, igual ao Cancelar (a
   pílula .form-floating-cancel já usa 30px) — o botão em si só tinha o border-radius:8px genérico
   de <button>, bem menos arredondado que a pílula ao lado dele. */
.form-floating-save{box-shadow:0 14px 32px -10px rgba(0,0,0,.4);border-radius:30px;}
@media(max-width:680px){
  .form-floating-actions{left:12px;right:12px;transform:none;bottom:76px;justify-content:center;}
  .form-floating-cancel{padding:0 14px;}
}
.checklist-item-row{display:flex;align-items:center;gap:10px;padding:7px 2px;border-bottom:1px dashed var(--line);}
.checklist-item-row:last-child{border-bottom:none;}
.checklist-item-row input[type=checkbox]{width:auto;flex-shrink:0;}
.checklist-item-row .item-texto{flex:1;font-size:13.5px;}
.checklist-item-row input[type=text]{flex:1;max-width:220px;}
.pw-field{position:relative;}
.pw-field input{padding-right:60px;}
.pw-toggle{position:absolute;right:4px;top:4px;bottom:4px;background:transparent;border:none;color:var(--teal-dark);font-size:11px;font-weight:700;padding:0 8px;cursor:pointer;}
.os-badge-concluida{background:rgba(var(--teal-rgb),.13);color:var(--teal-dark);}
.os-badge-aberta{background:rgba(var(--amber-rgb),.15);color:var(--amber);}
.os-inner-tabs, .est-inner-tabs, .emp-inner-tabs, .cli-inner-tabs{display:flex;gap:4px;margin:4px 0 18px;border-bottom:1px solid var(--line);flex-wrap:wrap;}
.os-inner-tabs button, .est-inner-tabs button, .emp-inner-tabs button, .cli-inner-tabs button{background:none;border:none;padding:9px 16px;font-size:12.5px;font-weight:600;color:var(--ink-soft);border-bottom:2px solid transparent;}
.os-inner-tabs button.active, .est-inner-tabs button.active, .emp-inner-tabs button.active, .cli-inner-tabs button.active{color:var(--teal-dark);border-bottom-color:var(--teal);}
.stock-low{color:var(--red);font-weight:700;}
/* Item 17 — Permissões reescrita como cards (mesmo padrão visual de .cadastro-card usado no resto do
   sistema) em vez de uma <table> — a tabela original ficava sem tema/quebrada no celular e no tablet
   (thead escondido abaixo de 680px levava junto os botões "✓ tudo/✗ nada", e não existia wrapper de
   scroll horizontal entre 681-1024px). Como cada permissão tem 3 papéis (não é "1 registro, N campos"
   como o resto das telas), não dá pra reaproveitar literalmente .cadastro-card/grid-template-columns
   — em vez disso, cada permissão vira um cartão com um toggle rotulado por papel dentro, que já
   reflui sozinho em qualquer largura sem precisar de breakpoint dedicado. */
.perm-roles-bar{display:flex;flex-wrap:wrap;gap:18px;margin:14px 0;padding:12px 14px;background:var(--surface-alt);border-radius:12px;}
.perm-roles-bar-item{display:flex;align-items:center;gap:8px;font-size:12.5px;color:var(--ink-soft);}
.perm-roles-bar-item strong{color:var(--ink);}
.perm-group{margin-top:24px;}
.perm-group-head{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:8px;padding:0 2px;margin-bottom:10px;border-bottom:1px solid var(--line);padding-bottom:8px;}
.perm-group-title{font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:var(--ink-soft);font-weight:700;}
.perm-group-bulk{display:flex;flex-wrap:wrap;gap:14px;}
.perm-group-bulk-item{display:flex;align-items:center;gap:1px;font-size:11px;color:var(--ink-soft);white-space:nowrap;}
.perm-group-bulk-item button{padding:2px 6px;}
.perm-card{background:var(--panel);border:1px solid var(--line);border-radius:14px;box-shadow:var(--shadow-card);padding:12px 16px;margin-bottom:8px;display:flex;align-items:center;justify-content:space-between;gap:16px;flex-wrap:wrap;}
.perm-card-label{flex:1 1 260px;font-size:13px;font-weight:600;color:var(--ink);}
.perm-card-roles{display:flex;gap:20px;flex-wrap:wrap;}
.perm-role-toggle{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--ink-soft);cursor:pointer;white-space:nowrap;}
.perm-role-toggle input{width:auto;margin:0;}
@media(max-width:680px){
  .perm-card{flex-direction:column;align-items:stretch;justify-content:flex-start;}
  /* flex-basis:260px em .perm-card-label é pensado pro eixo principal HORIZONTAL (desktop, linha) —
     com .perm-card virando coluna aqui, o eixo principal passa a ser vertical, e aquele 260px vira
     ALTURA mínima do rótulo (achado real testando no celular: cartão de ~350px de altura por causa
     disso). Precisa de flex-basis:auto aqui pra voltar a ser só a altura do texto. */
  .perm-card-label{flex:0 0 auto;}
  .perm-card-roles{gap:10px;justify-content:space-between;}
}
.badge-pago{background:rgba(var(--teal-rgb),.13);color:var(--badge-teal-text);}
.badge-vencido{background:rgba(var(--red-rgb),.13);color:var(--red);}
.badge-parcial{background:rgba(var(--amber-rgb),.15);color:var(--amber);}
.badge-cancelado{background:var(--badge-neutral-bg);color:var(--ink-soft);}
/* Pedido do usuário: deixar o calendário com um estilo mais parecido com o do Google Calendar —
   linhas de grade mais finas/discretas (uma só, sem dupla borda entre células), cabeçalho de dias da
   semana mais espaçado, o dia de hoje marcado com um círculo preenchido em volta só do número (não a
   célula inteira tingida, que brigava visualmente com os cal-item coloridos), e os eventos como
   "chips" com uma bolinha colorida na frente (em vez de só um fundo translúcido). */
/* Item 12 — cabeçalho: navegação (Hoje/‹/›/título) à esquerda, seletor de visualização (Dia/Semana/
   Mês/Ano, "igual ao Google") à direita — mesmo chip-toggle usado no resto do rollout. */
.fin-cal-toolbar{display:flex;align-items:center;justify-content:space-between;gap:14px;flex-wrap:wrap;margin-top:4px;}
.fin-cal-nav{display:flex;align-items:center;gap:6px;flex-wrap:wrap;}
.fin-cal-view-switch{display:flex;align-items:center;gap:4px;background:var(--surface-alt);border-radius:20px;padding:3px;}
.fin-cal-view-switch span{cursor:pointer;padding:6px 14px;border-radius:18px;font-size:12px;font-weight:700;color:var(--ink-soft);}
.fin-cal-view-switch span.ativo{background:var(--panel);box-shadow:0 1px 2px rgba(0,0,0,.08);color:var(--ink);}
.fin-cal{width:100%;border-collapse:collapse;table-layout:fixed;}
.fin-cal th{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.02em;color:var(--ink-soft);padding:10px 2px;text-align:center;border-bottom:1px solid var(--line);}
/* Item 12 — pedido do usuário: "não deixar os quadrados das datas com tamanhos diferentes". Altura
   FIXA (não mais min/max-height com rolagem interna) — o que não couber vira "+N mais"
   (calCelulaConteudoHTML/calAbrirDiaPopup), então o conteúdo nunca mais faz a célula crescer. */
.fin-cal td{border:1px solid var(--line);border-top:none;border-left:none;vertical-align:top;height:130px;overflow:hidden;padding:6px 5px;font-size:11px;cursor:pointer;transition:background .12s;}
.fin-cal td:first-child{border-left:1px solid var(--line);}
.fin-cal thead+tbody tr:first-child td{border-top:1px solid var(--line);}
.fin-cal td:hover{background:var(--hover-tint);}
.fin-cal td.other-month{background:var(--surface-subtle);color:var(--text-faint);cursor:default;}
.fin-cal td.other-month:hover{background:var(--surface-subtle);}
/* Item 12 — "centralizar datas": o número do dia fica centralizado na largura da célula (antes
   ficava encostado à esquerda). */
.fin-cal .day-num-wrap{display:flex;justify-content:center;margin-bottom:4px;}
.fin-cal .day-num{font-weight:500;font-size:12px;width:22px;height:22px;display:flex;align-items:center;justify-content:center;border-radius:50%;cursor:pointer;}
.fin-cal .day-num:hover{background:var(--blue);color:#fff;}
.cal-th-dia-clic{cursor:pointer;}
.cal-th-dia-clic:hover{color:var(--blue);}
.fin-cal td.today .day-num{background:var(--blue);color:#fff;font-weight:700;}
.fin-cal .cal-item{font-size:10px;line-height:1.5;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding:2px 6px;border-radius:4px;margin-bottom:2px;cursor:pointer;display:flex;align-items:center;gap:4px;}
.fin-cal .cal-item::before{content:'';width:6px;height:6px;min-width:6px;border-radius:50%;}
.fin-cal .cal-item:hover{filter:brightness(.94);}
.fin-cal .cal-item-pagar{background:rgba(var(--red-rgb),.12);color:var(--red);}
.fin-cal .cal-item-pagar::before{background:var(--red);}
.fin-cal .cal-item-receber{background:rgba(var(--teal-rgb),.12);color:var(--teal-dark);}
.fin-cal .cal-item-receber::before{background:var(--teal-dark);}
.fin-cal .cal-mais{font-size:10px;color:var(--ink-soft);cursor:pointer;padding:2px 6px;font-weight:600;}
.fin-cal .cal-mais:hover{text-decoration:underline;}
/* Semana — mesma tabela do Mês, só uma linha, célula bem mais alta (mais espaço por dia). */
.fin-cal.semana td{height:280px;}
/* Item 12 — 3 níveis de tamanho: desktop (padrão acima), tablet e celular, cada um menor que o
   anterior — "não deixar os quadrados com tamanhos diferentes" dentro do MESMO nível, mas os 3
   níveis em si têm tamanhos diferentes de propósito (maior no desktop, menor no celular). */
@media(max-width:1024px) and (min-width:681px){
  .fin-cal td{height:100px;font-size:10px;}
  .fin-cal.semana td{height:220px;}
  .fin-cal .day-num{font-size:11px;width:20px;height:20px;}
  .fin-cal .cal-item{font-size:9.5px;}
}
@media(max-width:680px){
  .fin-cal td{height:64px;font-size:9.5px;padding:4px 3px;}
  .fin-cal.semana td{height:160px;}
  .fin-cal .day-num{font-size:10px;width:18px;height:18px;}
  .fin-cal .cal-item{font-size:8.5px;padding:1px 4px;}
  .fin-cal .cal-item::before{width:5px;height:5px;min-width:5px;}
}
/* Menu flutuante "Nova conta" ao clicar um espaço vazio do calendário (mesmo padrão de popup já
   usado no Recibo ▾) — 2 opções, some ao escolher uma ou ao clicar fora. */
.cal-criar-menu{position:fixed;background:var(--panel);border:1px solid var(--panel-border);border-radius:8px;box-shadow:0 8px 24px -8px rgba(0,0,0,.3);padding:6px;min-width:180px;z-index:999;}
.cal-criar-menu-item{padding:8px 10px;border-radius:6px;cursor:pointer;font-size:13px;white-space:nowrap;}
.cal-criar-menu-item:hover{background:var(--hover-tint);}
/* Visão Dia — lista vertical, sem grade. */
.cal-dia-view{display:flex;flex-direction:column;gap:8px;}
.cal-dia-item{display:flex;justify-content:space-between;align-items:center;gap:14px;padding:12px 14px;border-radius:10px;cursor:pointer;transition:filter .12s;}
.cal-dia-item:hover{filter:brightness(.97);}
.cal-dia-item-pagar{background:rgba(var(--red-rgb),.08);}
.cal-dia-item-receber{background:rgba(var(--teal-rgb),.08);}
/* Visão Ano — 12 meses em miniatura. */
.cal-ano-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;}
@media(max-width:1024px){ .cal-ano-grid{grid-template-columns:repeat(3,1fr);} }
@media(max-width:680px){ .cal-ano-grid{grid-template-columns:repeat(2,1fr);gap:10px;} }
.cal-ano-mes{border:1px solid var(--line);border-radius:10px;padding:10px;}
.cal-ano-mes-titulo{font-weight:700;font-size:12px;margin-bottom:6px;text-align:center;cursor:pointer;text-transform:uppercase;letter-spacing:.03em;}
.cal-ano-mes-titulo:hover{color:var(--blue);}
.cal-ano-mini{width:100%;border-collapse:collapse;}
.cal-ano-mini th{font-size:8px;color:var(--ink-soft);font-weight:600;padding:1px;}
.cal-ano-mini td{width:14.28%;text-align:center;font-size:9px;padding:2px 0;cursor:pointer;border-radius:4px;}
.cal-ano-mini td:hover{background:var(--hover-tint);}
.cal-ano-mini td.other-month{color:var(--text-faint);cursor:default;}
.cal-ano-mini td.other-month:hover{background:none;}
.cal-ano-mini td.today{background:var(--blue);color:#fff;font-weight:700;}
.cal-ano-mini .dots{display:flex;justify-content:center;gap:2px;margin-top:1px;}
.cal-ano-mini .dot{width:4px;height:4px;border-radius:50%;}
.cal-ano-mini .dot-pagar{background:var(--red);}
.cal-ano-mini .dot-receber{background:var(--teal-dark);}
/* Popup "+N mais" — lista completa do dia, centralizado, fecha ao clicar fora (mesmo padrão de
   overlay do confirmOverlay, mas conteúdo variável em vez do modal fixo de confirmação). */
.cal-dia-popup-overlay{position:fixed;inset:0;background:rgba(0,0,0,.4);z-index:1000;display:flex;align-items:center;justify-content:center;padding:20px;}
.cal-dia-popup{background:var(--panel);border-radius:12px;max-width:480px;width:100%;max-height:80vh;overflow-y:auto;padding:18px;box-shadow:0 20px 50px -12px rgba(0,0,0,.4);}
.cal-dia-popup-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px;}
/* Pedido do usuário: os itens do popup de "+N mais" deviam reagir de forma mais dinâmica ao passar
   o mouse e ao clicar — antes só tinham o `filter:brightness(.94)` genérico herdado de `.cal-item`
   (pensado pra célula minúscula do grid do mês, sem espaço pra mais nada); aqui dentro do popup
   sobra espaço de sobra pra um feedback bem mais perceptível. */
.cal-dia-popup .cal-item{font-size:12.5px;padding:8px 10px;margin-bottom:6px;transition:transform .12s ease,box-shadow .12s ease,filter .12s ease;}
.cal-dia-popup .cal-item::before{width:8px;height:8px;min-width:8px;}
.cal-dia-popup .cal-item:hover{filter:brightness(.9);transform:translateX(3px) scale(1.015);box-shadow:0 3px 10px -4px rgba(0,0,0,.3);}
.cal-dia-popup .cal-item:active{filter:brightness(.82);transform:translateX(3px) scale(.97);box-shadow:none;transition-duration:.05s;}
/* Item 21 — título do calendário clicável (mês/ano abrem seletor rápido, mesma ideia do Google). */
.cal-titulo-clic{cursor:pointer;border-radius:6px;padding:2px 6px;margin:0 -6px;}
.cal-titulo-clic:hover{background:var(--hover-tint);color:var(--blue);}
.cal-seletor-popup{max-width:340px;}
.cal-seletor-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;}
.cal-seletor-grid-ano{grid-template-columns:repeat(4,1fr);}
.cal-seletor-item{padding:10px 6px;border:1px solid var(--line);border-radius:8px;background:var(--panel);color:var(--ink);font-size:13px;font-weight:600;cursor:pointer;text-align:center;}
.cal-seletor-item:hover{border-color:var(--blue);color:var(--blue);}
.cal-seletor-item.ativo{background:var(--blue);border-color:var(--blue);color:#fff;}
.caixa-dash{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin-bottom:18px;}
@media(max-width:1000px){ .caixa-dash{grid-template-columns:repeat(2,1fr);} }
.caixa-card{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:14px 16px;box-shadow:var(--shadow-card);position:relative;}
/* Item 8 — Dashboard "mural": cards podem ser fixados (📌, inspirado nas notas fixadas do Keep) pra
   sempre aparecer primeiro, numa seção separada. Botão fica sempre no canto do card, mais visível só
   se já fixado ou no hover — event.stopPropagation() no onclick evita disparar o drill-down do card
   (toggleDashboardFiltro) ao clicar só no pino. */
.dash-pin-btn{position:absolute;top:8px;right:8px;background:none;border:none;font-size:13px;line-height:1;padding:3px;opacity:.3;border-radius:50%;}
.dash-pin-btn:hover{opacity:1;background:var(--hover-tint);}
.dash-pin-btn.pinned{opacity:1;}
.dash-section-label{font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:var(--ink-soft);font-weight:700;margin:4px 0 10px;}
/* Mockup "JLOControl Redesign Keep" — bolinha de status colorida ao lado do nome, nas linhas-cartão de
   lista (ex. Clientes). */
.status-dot{display:inline-block;width:7px;height:7px;border-radius:50%;margin-right:7px;vertical-align:middle;flex-shrink:0;}
/* Mockup "JLOControl Redesign Keep" — visualização "Confortável" da lista de Clientes: linhas-cartão
   em vez de tabela, ações (Ligar/WhatsApp/Editar) só aparecem no hover no desktop; no mobile ficam
   sempre visíveis numa fileira no rodapé do card, já que não existe hover no toque. */
/* Generalizado (usuário pediu pra levar o padrão visual de Clientes pras outras telas de cadastro):
   .cadastro-card/.cadastro-cards-head são a versão reaproveitável de tudo MENOS
   grid-template-columns — cada tela tem um número de colunas diferente (ex.: Fornecedores não tem
   "Cidade"), então isso fica numa classe MODIFICADORA à parte por tela (ex.: .fornecedor-card),
   combinada junto (`class="cadastro-card fornecedor-card"`) — inline style colidiria com o
   style="cursor:pointer" que linhaClicavelAttrs() já injeta no mesmo elemento. .cliente-card/
   .cliente-cards-head continuam com seu próprio grid-template-columns dedicado (não mudou), só
   passaram a compartilhar o resto das regras com .cadastro-card via selector list. */
.cliente-cards-head, .cadastro-cards-head{display:grid;gap:14px;padding:0 16px;margin-bottom:8px;font-size:10.5px;text-transform:uppercase;letter-spacing:.05em;color:var(--ink-soft);font-weight:700;}
.cliente-cards-head{grid-template-columns:16px 2.3fr 1.4fr 1.1fr 1fr 130px;}
.cliente-card, .cadastro-card{background:var(--panel);border:1px solid var(--line);border-radius:14px;box-shadow:var(--shadow-card);display:grid;align-items:center;gap:14px;padding:14px 16px;margin-bottom:10px;transition:box-shadow .15s ease,transform .1s ease;}
.cliente-card{grid-template-columns:16px 2.3fr 1.4fr 1.1fr 1fr 130px;}
/* Fornecedores (item 9 — mesmo padrão de Clientes): 5 colunas, não 6 — sem "Cidade" (Fornecedor não
   tem esse campo separado do endereço livre). */
.fornecedor-cards-head, .fornecedor-card{grid-template-columns:16px 2.5fr 1.8fr 1fr 150px;}
/* 12.320 — Contratos: bolinha, contrato+cliente, valor+vencimento, status+inadimplente, ações. */
.contrato-cards-head, .contrato-card{grid-template-columns:16px 2.4fr 1.5fr 1.6fr 110px;}
/* Funcionários (item 9): 6 colunas — Cargo e Filial em colunas separadas (equivalente a "contato"
   de Cliente/Fornecedor, mas são 2 pedaços de info distintos aqui). Ações mais largas — até 5 ícones
   (Ligar/WhatsApp/Editar/Criar Usuário/Inativar), mas .row-actions já quebra linha sozinho. */
.funcionario-cards-head, .funcionario-card{grid-template-columns:16px 2fr 1.3fr 1.3fr 0.9fr 190px;}
/* Contas Bancárias (item 9): dot, Nome(+badge Padrão), Banco/Agência-Conta, Saldo, Status, ações —
   mesmas 6 colunas de Cliente. */
.conta-bancaria-cards-head, .conta-bancaria-card{grid-template-columns:16px 2fr 1.6fr 1.1fr 1fr 130px;}
/* Caixas — cadastro (item 9): só 5 colunas — dot, Nome, Filial, Status, ações (tela mais simples do
   rollout, sem coluna extra de "contato"/saldo). */
.caixa-cadastro-cards-head, .caixa-cadastro-card{grid-template-columns:16px 2fr 1.4fr 1fr 110px;}
/* Maquininhas (item 9): dot, Nome, Filial/Terminal (2 linhas numa coluna só), Status, ações. */
.maquininha-cards-head, .maquininha-card{grid-template-columns:16px 2fr 1.8fr 1fr 130px;}
/* Tipos de Serviço (item 9): dot, Nome, Cobrança+Valor(+badge Visita opcional, 2 linhas), Status, ações. */
.servico-cards-head, .servico-card{grid-template-columns:16px 2fr 1.8fr 1fr 140px;}
/* Checklist (item 9): sem bolinha de status (entidade não tem ativo/inativo) — só Nome, Resumo, ações. */
.checklist-cards-head, .checklist-card{grid-template-columns:2fr 3fr 110px;}
/* Campos da OS (item 9): mesmo caso de Checklist — sem status, 3 colunas. */
.oscampo-cards-head, .oscampo-card{grid-template-columns:2fr 3fr 110px;}
/* Status da OS (item 9): o "dot" é a própria cor do status, não ativo/inativo. */
.osstatus-cards-head, .osstatus-card{grid-template-columns:16px 3fr 110px;}
/* Categorias de Caixa (item 9): sem dot (sem cor/status) — Nome + ações. */
.caixacategoria-cards-head, .caixacategoria-card{grid-template-columns:3fr 110px;}
/* Formas de Pagamento (item 9): Nome + resumo de maquininhas vinculadas + ações. */
.caixaforma-cards-head, .caixaforma-card{grid-template-columns:2fr 1.6fr 110px;}
/* Categorias Financeiras (item 9): Nome + Tipo + ações. */
.fincategoria-cards-head, .fincategoria-card{grid-template-columns:2fr 1.3fr 110px;}
/* Centro de Custo (item 9): sem dot — Nome + ações. */
.centrocusto-cards-head, .centrocusto-card{grid-template-columns:3fr 110px;}
/* Usuários (item 9, última tela do rollout): dot, Nome, Usuário/Papel/Sessão, Status(+badge
   tentativas), ações — mesmas 6 colunas de Cliente. */
.usuario-cards-head, .usuario-card{grid-template-columns:16px 2fr 1.8fr 1.3fr 150px;}
/* Regras de Cobrança por E-mail (itens 7/8, leva seguinte): Nome + Quando/Assunto + Status + ações
   — lista pequena, sem reordenação manual nem paginação (a tela nunca teve isso, não é o pedido). */
.regracobranca-cards-head, .regracobranca-card{grid-template-columns:1.6fr 2fr 110px 110px;}
/* Filiais (itens 7/8, leva seguinte): dot, Nome+código, Telefone, Sede/Status, ações. */
.filial-cards-head, .filial-card{grid-template-columns:16px 2fr 1.4fr 1.2fr 150px;}
/* Registros Simples (itens 7/8, leva seguinte): Cliente+Data, Serviço, Valor, Situação/OS, ações. */
.registro-cards-head, .registro-card{grid-template-columns:2fr 1.8fr 1fr 1.2fr 150px;}
/* Contas a Pagar/Receber (itens 7/8, leva seguinte): Entidade+Descrição, Categoria, Vencimento/
   Valor, Situação, ações — compartilhado entre as 2 telas (mesma função renderContaFin). */
.contafin-cards-head, .contafin-card{grid-template-columns:2.2fr 1.4fr 1.3fr 1.3fr 150px;}
/* Orçamento e Pedidos de Compra (itens 7/8, leva seguinte) — mesmo formato nas duas telas:
   Nº/Cliente/Vendedor, Itens, Valor(/Validade), Status, ações. */
.orcamento-cards-head, .orcamento-card, .pedidocompra-cards-head, .pedidocompra-card{grid-template-columns:2fr 1.8fr 1.2fr 1.2fr 220px;}
/* Todas as Vendas (itens 7/8, leva seguinte) — tela só de leitura (sem ações por linha, por isso
   sem coluna de ações): Venda, Cliente/Vendedor, Itens, Valor, Status. */
.venda-cards-head, .venda-card{grid-template-columns:2fr 1.6fr 1.8fr 1fr 130px;}
/* Estoque — Catálogo (itens 7/8, leva seguinte): dot, Item(código/marca/grupo), Disponível, Preços,
   ações. Era a única tela do rollout sem ícone nenhum antes desta leva (texto puro). Item 41 — 1ª
   coluna alargada de 16px pra 34px: passou a caber também o checkbox de seleção múltipla (entrada em
   lote) ao lado do dot, que com 16px ficava sobrepondo os dois. */
.estoque-cards-head, .estoque-card{grid-template-columns:34px 2fr 1fr 1.3fr 150px;}
/* Estoque — Movimentações (itens 7/8, leva seguinte): só leitura, sem ações — Produto/Data, Tipo,
   Qtd., Usuário, Observação. */
.estoquehist-cards-head, .estoquehist-card{grid-template-columns:1.8fr 1.3fr 90px 1.2fr 2fr;}
/* Ordens de Serviço (itens 7/8, leva seguinte) — a tela mais complexa do sistema (colunas
   dinâmicas de Campos da OS): dot, Nº+Cliente+campos personalizados resumidos, Datas, Valor,
   Status/Prioridade/Checklist (badges empilhados), ações (até 5 ícones, por isso mais largo). */
.os-cards-head, .os-card{grid-template-columns:16px 2.2fr 1.3fr 1.1fr 1.8fr 230px;}
/* Caixa — Movimentações do caixa (itens 7/8, leva seguinte, última tela): Valor, Descrição/
   Categoria, Data/Forma de pagamento, ações. */
.mov-cards-head, .mov-card{grid-template-columns:1fr 2.2fr 1.6fr 180px;}
.cliente-card:hover, .cadastro-card:hover{box-shadow:var(--shadow-card-hover);transform:translateY(-1px);}
.cliente-card .row-actions, .cadastro-card .row-actions{opacity:0;justify-content:flex-end;transition:opacity .12s ease;}
.cliente-card:hover .row-actions, .cadastro-card:hover .row-actions{opacity:1;}
@media(max-width:820px){
  .cliente-cards-head, .cadastro-cards-head{display:none;}
  .cliente-card, .cadastro-card{grid-template-columns:1fr !important;}
  .cliente-card .row-actions, .cadastro-card .row-actions{opacity:1;border-top:1px dashed var(--line);padding-top:10px;margin-top:8px;}
}
/* Pedido do usuário: Ligar/WhatsApp maiores no celular, com rótulo de texto (mesmo espírito do
   mockup mobile — botões flex:1 com "📞 Ligar"/"💬 WhatsApp" em vez de ícone sozinho pequeno). Só no
   celular de verdade (680px) — no tablet (entre 680 e 820px) os cards já viram 1 coluna, mas o
   toque ainda tem espaço de sobra pra ícone pequeno, então mantém compacto até 680px. */
.contato-btn-label{display:none;}
@media(max-width:680px){
  .cliente-card .contato-btn, .cadastro-card .contato-btn{flex:1;display:inline-flex;align-items:center;justify-content:center;gap:6px;padding:10px 8px;font-size:13px;}
  .cliente-card .contato-btn span:first-child, .cadastro-card .contato-btn span:first-child{font-size:16px;}
  .cliente-card .contato-btn-label, .cadastro-card .contato-btn-label{display:inline;}
}
.caixa-card .card-label{font-size:11px;text-transform:uppercase;color:var(--ink-soft);font-weight:700;letter-spacing:.03em;}
.caixa-card .card-icon{font-size:14px;margin-right:6px;letter-spacing:0;text-transform:none;}
.caixa-card .card-val{font-family:'JetBrains Mono',monospace;font-size:20px;font-weight:700;margin-top:4px;}
.clickable-card{cursor:pointer;transition:border-color .1s ease,transform .08s ease,box-shadow .12s ease;}
.clickable-card:hover{border-color:var(--teal);box-shadow:var(--shadow-card-hover);transform:translateY(-2px);}
.clickable-card:active{transform:scale(.98);}
/* Pedido do usuário: arrastar os cards do Dashboard pra reordenar, com um "balanço" (jiggle, igual ao
   modo de editar da tela inicial do iOS) enquanto "Personalizar Dashboard" está aberto — sinaliza que
   os cards viraram arrastáveis sem precisar de texto explicando. Pares e ímpares balançam em direções
   opostas e com atraso diferente, pra não ficar tudo balançando em uníssono feito soldado. */
@keyframes dashCardWiggle{ 0%,100%{transform:rotate(-.6deg);} 50%{transform:rotate(.6deg);} }
.dash-editing .caixa-card{cursor:grab;animation:dashCardWiggle .26s ease-in-out infinite;touch-action:none;}
.dash-editing .caixa-card:nth-child(even){animation-direction:alternate-reverse;animation-delay:.09s;}
.dash-editing .caixa-card:active{cursor:grabbing;}
.dash-editing .caixa-card.dragging{opacity:.35;animation:none;}
.dash-editing .caixa-card:hover{transform:none;box-shadow:var(--shadow-card);border-color:var(--line);}
/* Alvo do arrasto por toque (celular) — dá o mesmo feedback visual que o navegador já dá de graça no
   drag-and-drop de mouse (o cursor muda perto do alvo), já que toque não tem esse indicador nativo. */
.dash-editing .caixa-card.touch-drop-target{border-color:var(--teal);box-shadow:0 0 0 2px var(--teal);animation:none;}
tr.clickable-row{cursor:pointer;}
tr.clickable-row:hover td{background:var(--hover-tint);}
tr.linha-destacada td, .linha-destacada.mov-list-item{animation:destaquePulse 2.2s ease;}
@keyframes destaquePulse{ 0%{background:rgba(var(--teal-rgb),.35);} 100%{background:transparent;} }
.row-actions{display:flex;gap:6px;flex-wrap:wrap;align-items:center;}
.mov-entrada{color:var(--teal-dark);font-weight:700;}
.mov-saida{color:var(--red);font-weight:700;}
.mov-list-item{display:flex;justify-content:space-between;align-items:center;gap:10px;padding:9px 4px;border-bottom:1px dashed var(--line);font-size:13.5px;}
.mov-list-item:last-child{border-bottom:none;}
.fecha-caixa-table{width:100%;border-collapse:collapse;margin-top:10px;}
.fecha-caixa-table th{text-align:left;font-size:11px;text-transform:uppercase;color:var(--ink-soft);padding:6px 8px;border-bottom:2px solid var(--line);}
.fecha-caixa-table td{padding:8px;border-bottom:1px solid var(--line);}
.fecha-caixa-table input{max-width:130px;}
@media(max-width:680px){ .caixa-dash{grid-template-columns:repeat(2,1fr);} }
.download-fallback{background:rgba(var(--teal-rgb),.08);border:1px solid var(--teal);border-radius:8px;padding:12px 16px;margin-top:12px;font-size:13px;}
.download-fallback a{font-weight:700;}
#confirmOverlay, #reciboPromptOverlay, #scannerOverlay, #suporteContatoOverlay, #avisoNaoSalvoOverlay, #clienteContatosOverlay, #assinaturaModalOverlay, #dadosFiscaisOverlay, #legalReaceiteOverlay, #excedenteLicencasOverlay, #excedenteFiliaisOverlay, #estoqueLoteOverlay, #bloqueioComparacaoPlanosOverlay{position:fixed;inset:0;background:rgba(34,38,43,.55);z-index:200;display:none;align-items:center;justify-content:center;padding:20px;}
#confirmOverlay.open, #reciboPromptOverlay.open, #scannerOverlay.open, #suporteContatoOverlay.open, #avisoNaoSalvoOverlay.open, #clienteContatosOverlay.open, #assinaturaModalOverlay.open, #dadosFiscaisOverlay.open, #legalReaceiteOverlay.open, #excedenteLicencasOverlay.open, #excedenteFiliaisOverlay.open, #estoqueLoteOverlay.open, #bloqueioComparacaoPlanosOverlay.open{display:flex;}
/* Item 39 — gate de re-aceite de Termos/Privacidade precisa ficar acima de qualquer outro overlay
   (inclusive #dadosFiscaisOverlay, que na prática nunca dispara junto porque verificarReaceiteLegal()
   bloqueia _ativarModoApiComum() antes de verificarPopUpDadosFiscais() rodar — z-index extra é só
   uma garantia a mais, não a única linha de defesa). Sem botão de fechar, de propósito: é a única
   diferença estrutural em relação ao padrão de overlay acima (ver <div id="legalReaceiteOverlay">). */
#legalReaceiteOverlay{z-index:400;}
/* 12.307 — pop-up de usuários acima do limite do plano: também sem botão de fechar (só some ao desativar o excesso). Abaixo do reaceite legal. */
#excedenteLicencasOverlay{z-index:390;}
/* 12.315 — filiais acima do limite do plano: também sem botão de fechar; abaixo do reaceite legal e do pop-up de usuários. */
#excedenteFiliaisOverlay{z-index:385;}
/* Item 8 v2 — tour guiado por spotlight. "Modo assistente concentrado" (pedido do usuário): durante
   o tour a pessoa não pode navegar livremente pelo sistema — só usar os controles do próprio tour ou
   clicar no elemento em destaque. Por isso o spotlight não é mais 1 div com box-shadow (que só é
   visual, clique atravessa) — são 4 painéis reais (#tourPainelTopo/Baixo/Esquerda/Direita) cobrindo
   o viewport inteiro MENOS o retângulo do elemento em destaque, cada um com pointer-events:auto (
   bloqueiam clique de verdade). O retângulo do meio fica livre, sem painel nenhum por cima — clique
   passa direto pro elemento real (é assim que os passos 'configurar' continuam funcionando). Sem
   elemento (passo de boas-vindas/introdução), o painel de cima cobre a tela inteira sozinho.
   #tourAnelBorda é só um contorno fino, puramente visual (pointer-events:none), pra continuar
   parecendo um destaque de verdade e não só 4 retângulos escuros. */
.tour-painel{position:fixed;display:none;background:rgba(20,22,26,.62);pointer-events:auto;z-index:199;}
#tourAnelBorda{position:fixed;display:none;border-radius:8px;border:2px solid var(--teal);pointer-events:none;z-index:199;box-shadow:0 0 0 3px rgba(10,149,123,.25);transition:top .2s ease,left .2s ease,width .2s ease,height .2s ease;}
#tourBalao{z-index:199;transition:top .2s ease,left .2s ease;}
.confirm-box{background:var(--panel);border-radius:12px;padding:24px;max-width:420px;width:100%;box-shadow:0 25px 60px -20px rgba(0,0,0,.5);}
.confirm-box h3{margin-bottom:10px;}
/* Assinatura em pop-up: cabeçalho fixo com o X, seções sem a moldura de painel, linha "caixa + botão" alinhada. */
#assinaturaModalOverlay{z-index:199;}
.as-modal-head{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:14px;}
.as-modal .as-sec{margin:0 0 18px;}
.as-modal .as-sec h2{font-size:17px;margin:0 0 8px;}
.as-linha-troca{display:flex;align-items:flex-end;gap:12px;flex-wrap:wrap;}
.as-linha-troca .field{flex:1 1 240px;margin:0;}
.as-linha-troca .field select{height:46px;}
.as-linha-troca .btn-secondary,.as-linha-troca .btn-primary{height:46px;white-space:nowrap;}
.as-acoes{display:flex;gap:10px;flex-wrap:wrap;margin-top:12px;}
.as-cancelar-wrap{border:1px solid var(--line);}
/* Modal de Dados Fiscais é longo (rola): a barra de botões fica SEMPRE visível no rodapé do modal — antes o "Salvar" ficava escondido abaixo da dobra e parecia que não havia botão. */
#dadosFiscaisOverlay .confirm-box .actions{position:sticky;bottom:-24px;background:var(--panel);padding:14px 0 24px;margin:8px 0 -24px;border-top:1px solid var(--line);z-index:1;}
.confirm-box p{font-size:14px;color:var(--ink-soft);line-height:1.5;margin:0 0 20px;}
.confirm-box .actions{display:flex;gap:10px;justify-content:flex-end;}
/* Item 12.237 (pedido do usuário) — "Pagar agora"/"Trocar plano ou forma de pagamento" na tela de
   LOGIN bloqueado passam a abrir como um pop-up por cima de tudo (antes cresciam inline dentro do
   próprio .login-card, empurrando a tela pra baixo). Criado dinamicamente por
   abrirModalBloqueioPagamento() (modoApi.js) — z-index abaixo de #bloqueioComparacaoPlanosOverlay
   (200) de propósito: o botão "Dúvidas sobre os planos" dentro deste modal abre aquele overlay por
   cima. No celular mantém o tamanho/formato atual dos campos (pedido do usuário: "no celular pode
   deixar do tamanho atual") — só tablet/desktop ganham mais largura/altura, pra caber sem rolar. */
.bloqueio-pagamento-modal-overlay{position:fixed;inset:0;background:rgba(34,38,43,.6);z-index:190;display:flex;align-items:center;justify-content:center;padding:20px;}
.bloqueio-form-box{position:relative;max-height:90vh;overflow-y:auto;padding-top:36px;}
/* Pedido do usuário: o pop-up ficou pequeno demais no tablet/desktop, mostrando barra de rolagem
   à toa — aumentado pra caber o conteúdo sem rolar nessas telas; overflow-y:auto continua ligado
   (regra acima), então a barra volta a aparecer sozinha se a janela for menor que isso. */
@media(min-width:681px) and (max-width:1024px){.bloqueio-form-box{max-width:720px;max-height:94vh;}}
@media(min-width:1025px){.bloqueio-form-box{max-width:900px;max-height:92vh;}}
.modal-close-btn{position:absolute;top:10px;right:10px;width:32px;height:32px;padding:0;border:none;background:transparent;color:var(--ink-soft);font-size:24px;line-height:1;cursor:pointer;border-radius:8px;display:flex;align-items:center;justify-content:center;box-sizing:border-box;}
.modal-close-btn:hover{background:var(--line);color:var(--ink);}
/* Confirmação ao clicar no X ou no Cancelar do modal acima — mesmo padrão visual de
   #avisoNaoSalvoOverlay (2 das 3 opções: aqui não existe "Salvar" parcial, é um formulário de
   pagamento, não um cadastro). Acima do modal (190), abaixo do resto dos overlays padrão (200) —
   nenhum dos dois precisa coexistir com aquele grupo. */
#bloqueioFecharModalConfirmOverlay{position:fixed;inset:0;background:rgba(34,38,43,.55);z-index:195;display:none;align-items:center;justify-content:center;padding:20px;}
#bloqueioFecharModalConfirmOverlay.open{display:flex;}
.closure-card{border:1px solid var(--line);border-radius:10px;padding:14px 16px;margin-bottom:12px;}
.closure-card .head{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:8px;}
.link-icon{font-size:12px;text-decoration:none;border:1px solid var(--line);padding:2px 8px;border-radius:20px;color:var(--teal-dark);}
.th-sort{cursor:pointer;user-select:none;white-space:nowrap;}
.th-sort:hover{color:var(--teal-dark);}
.th-sort .sort-arrow{font-size:9px;margin-left:3px;opacity:.7;}
/* bottom:96px (não 20px) — abre espaço pro botão flutuante de atalhos (#fabBtn, item 8), que fica
   fixo em bottom:24px/right:24px com 56px de diâmetro; sem isso o toast aparece por cima do FAB. */
.toast{position:fixed;bottom:96px;right:20px;background:#22262B;color:#fff;padding:12px 18px;border-radius:8px;font-size:13px;z-index:100;box-shadow:0 10px 30px -10px rgba(0,0,0,.4);max-width:320px;}
body{overflow-x:hidden;}
.toast.err{background:var(--red);}
.fab-btn{position:fixed;right:24px;bottom:24px;width:56px;height:56px;border-radius:50%;background:var(--teal);color:#fff;font-size:26px;line-height:1;display:flex;align-items:center;justify-content:center;box-shadow:0 10px 24px -6px rgba(var(--teal-rgb),.55);z-index:90;transition:transform .15s ease,box-shadow .15s ease;padding:0;}
.fab-btn:hover{box-shadow:0 14px 30px -6px rgba(var(--teal-rgb),.65);}
.fab-btn.open{transform:rotate(45deg);}
.fab-menu{position:fixed;right:24px;bottom:90px;z-index:90;display:flex;flex-direction:column;align-items:flex-end;gap:8px;pointer-events:none;}
.fab-menu.open{pointer-events:auto;}
.fab-menu-item{display:flex;align-items:center;gap:10px;background:var(--panel);color:var(--ink);border:1px solid var(--panel-border);border-radius:24px;padding:9px 16px 9px 14px;font-size:13px;font-weight:600;box-shadow:var(--shadow-card-hover);opacity:0;transform:translateY(6px);transition:opacity .12s ease,transform .12s ease;white-space:nowrap;}
.fab-menu.open .fab-menu-item{opacity:1;transform:translateY(0);}
.fab-menu-item .ico{font-size:15px;}
/* Item 26 — avisos persistentes no canto (trial acabando / pagamento com erro). Canto oposto ao FAB
   (esquerda) de propósito, pra nunca sobrepor um botão que fica clicável o tempo todo. */
#avisosSistemaWrap{position:fixed;left:16px;bottom:24px;z-index:89;display:flex;flex-direction:column;gap:8px;max-width:320px;}
.aviso-sistema{display:flex;align-items:flex-start;gap:8px;background:var(--panel);border:1px solid var(--amber,#b8860b);border-left:4px solid var(--amber,#b8860b);border-radius:10px;padding:10px 12px;box-shadow:var(--shadow-card-hover);font-size:12.5px;color:var(--ink);}
.aviso-sistema.aviso-erro{border-color:var(--red,#c0392b);border-left-color:var(--red,#c0392b);}
.aviso-sistema .aviso-sistema-fechar{background:none;border:none;color:var(--ink-soft);cursor:pointer;font-size:15px;line-height:1;padding:0 0 0 6px;flex-shrink:0;}
.aviso-sistema a{font-weight:700;}
.aviso-sistema-nao-mostrar{text-transform:none;letter-spacing:0;display:flex;align-items:center;gap:6px;margin-top:6px;font-size:11.5px;font-weight:400;color:var(--ink-soft);cursor:pointer;}
.aviso-sistema-nao-mostrar input{width:auto;margin:0;}
@media(max-width:680px){
  #avisosSistemaWrap{left:12px;right:12px;bottom:72px;max-width:none;}
}
.mobile-bottom-nav{display:none;}
@media(max-width:680px){
  /* bottom:72px (não 16px) — abre espaço pra barra de navegação inferior (~60px de altura), que só
     existe nesta faixa de largura. */
  .fab-btn{right:16px;bottom:72px;width:52px;height:52px;font-size:24px;}
  .fab-menu{right:16px;bottom:134px;}
  .toast{bottom:134px;}
  /* overflow-x:auto (não flex distribuído) — com TODOS os grupos (não só 4), a barra dificilmente
     cabe na largura da tela; rola na horizontal em vez de espremer os itens. scrollbar-width:none/
     ::-webkit-scrollbar escondem a barra de rolagem só visualmente, o gesto de arrastar continua
     funcionando normal (mesmo truque já usado em filas de chips/abas horizontais comuns em apps). */
  .mobile-bottom-nav{
    display:flex;position:fixed;left:0;right:0;bottom:0;z-index:45;
    background:var(--nav-bg);border-top:1px solid var(--line);
    padding:6px 2px calc(6px + env(safe-area-inset-bottom,0px));
    overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none;
  }
  .mobile-bottom-nav::-webkit-scrollbar{display:none;}
  .mobile-nav-item{flex:0 0 auto;min-width:62px;display:flex;flex-direction:column;align-items:center;gap:2px;background:none;border:none;color:var(--ink-soft);font-size:9.5px;font-weight:600;padding:6px 8px;border-radius:10px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
  .mobile-nav-item .ico{font-size:18px;line-height:1;}
  .mobile-nav-item.active{color:var(--teal-dark);}
  /* Balão flutuante com os subitens de um grupo tocado na barra inferior — fica ANCORADO por cima da
     barra (não é a gaveta lateral inteira, que continua só pelo "Mais"). bottom calc() soma a altura
     aproximada da barra (~60px) + respiro, pra flutuar logo acima dela sem depender de medir a barra
     via JS a cada abertura. */
  .mobile-nav-flyout{
    display:none;position:fixed;left:12px;right:12px;
    bottom:calc(60px + env(safe-area-inset-bottom,0px) + 10px);
    z-index:46;background:var(--panel);border:1px solid var(--panel-border);border-radius:16px;
    box-shadow:var(--shadow-card-hover);padding:8px;max-height:55vh;overflow-y:auto;
  }
  .mobile-nav-flyout.open{display:block;}
}
/* Itens/título dos balões flutuantes de navegação — compartilhado pelo balão do celular
   (.mobile-nav-flyout, acima) e pelo balão do rail no tablet (.sidebar-rail-flyout, abaixo). Sem
   media query própria: só existe dentro de um balão, que já controla quando aparece. */
.nav-flyout-title{font-size:11px;text-transform:uppercase;letter-spacing:.04em;color:var(--nav-text, var(--ink-soft));font-weight:700;padding:8px 10px 6px;}
.nav-flyout-item{display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%;text-align:left;background:none;border:none;border-radius:12px;padding:12px 10px;color:var(--nav-text, var(--ink-base));font-weight:600;font-size:14px;}
.nav-flyout-item.active{background:rgba(var(--teal-rgb),.14);color:var(--teal-dark);}
/* Item com submenu que também navega por conta própria — rótulo (toca = navega) e seta (toca =
   expande) são 2 áreas de toque separadas dentro do mesmo "item" visual. */
.nav-flyout-item-wrap{padding:0;}
.nav-flyout-item-label{flex:1;text-align:left;background:none;border:none;padding:12px 6px 12px 10px;color:inherit;font:inherit;font-weight:inherit;}
/* Item 18 — pedido do usuário: seta pouco visível (10px, opacidade .6) e descentralizada dentro da
   área de toque (um <button> sem centralização explícita depende do alinhamento inline padrão do
   navegador, que varia). display:flex + align/justify:center garante ela sempre no meio do botão,
   independente de fonte/renderização; tamanho/opacidade maiores pra ficar visível de verdade como
   um alvo de toque, não só decoração discreta. */
.nav-flyout-item-caret{background:none;border:none;padding:0;width:40px;height:40px;color:inherit;flex-shrink:0;display:flex;align-items:center;justify-content:center;}
.nav-flyout-item .caret{font-size:16px;opacity:.85;flex-shrink:0;line-height:1;}
/* Item 5 — submenu de 2º nível expande DENTRO do próprio balão (efeito sanfona), mesmo padrão que o
   menu lateral cheio já usa (grupo → item → subitem) em vez de trocar o conteúdo do balão inteiro. */
.nav-flyout-subitems{display:flex;flex-direction:column;padding-left:14px;margin:0 0 4px;border-left:2px solid var(--line);}
.nav-flyout-subitem{display:block;width:100%;text-align:left;background:none;border:none;border-radius:10px;padding:9px 10px;color:var(--nav-text, var(--ink-soft));font-weight:600;font-size:12.5px;}
.nav-flyout-subitem.active{background:rgba(var(--teal-rgb),.14);color:var(--teal-dark);}
/* Item 4 — balão do rail no tablet: mesma ideia do balão do celular, mas ancorado do LADO do ícone
   clicado (não em cima de uma barra inferior — no tablet o menu continua na lateral). Posição
   (top/left) calculada em JS a partir do ícone clicado, ver renderNavFlyout(). */
@media(min-width:681px) and (max-width:1024px){
  .sidebar-rail-flyout{
    display:none;position:fixed;z-index:56;width:220px;
    background:var(--panel);border:1px solid var(--panel-border);border-radius:16px;
    box-shadow:var(--shadow-card-hover);padding:8px;max-height:70vh;overflow-y:auto;
  }
  .sidebar-rail-flyout.open{display:block;}
}

/* Busca global (#buscaCodigoGlobalHolder) — chegou a ser centralizada no topbar via position:absolute;
   left:50% (estilo inline antigo), sem levar em conta a largura real de .brand/#topbarRight; em telas
   de laptop comuns (1280×720 até ~1500px, dependendo do nome da filial/tenant) esse bloco centralizado
   ficava largo o bastante pra sobrepor o seletor de filial e o resto do topbarRight — reportado pelo
   usuário. Corrigido de vez: a busca SEMPRE participa do fluxo normal de flex do #topbarRight (que já
   é display:flex), nunca mais flutua por cima dos irmãos, só divide o espaço com eles.
   position:relative (não static) continua sendo necessário como ancestral posicionado do dropdown de
   resultados (#buscaCodigoGlobalResultados, position:absolute;left:0;right:0) — ver estilo inline no
   HTML. #topbarRight tem flex-wrap:wrap (também inline) pra quebrar numa 2ª linha em vez de espremer
   ou sobrepor quando o conteúdo não cabe numa única linha. */
/* 12.323 — desktop: o campo de busca cresce com a tela (antes 180px fixos), de ~200px até ~380px. */
#buscaCodigoGlobal{width:clamp(200px,22vw,380px);}
#buscaMobileBtn{display:none;}
@media(max-width:1100px){
  #buscaCodigoGlobalModulo{width:110px!important;}
  #buscaCodigoGlobal{width:120px!important;}
}
/* Item 8 — sidebar em modo "rail" no tablet (só ícone, sem rótulo), entre o desktop (sidebar
   completa) e o celular (gaveta em tela cheia, ver @media 680px abaixo). Reaproveita a MESMA
   sidebar/mecanismo de navegação de sempre — só a aparência muda. `.sidebar-drilled` (grupo aberto
   com submenu, ver buildNav()) força a largura cheia de volta, senão o rótulo dos itens do submenu
   fica ilegível espremido em 72px. */
@media(min-width:681px) and (max-width:1024px){
  .sidebar:not(.sidebar-drilled){width:72px;padding:14px 8px;}
  .sidebar:not(.sidebar-drilled) .sidebar-group{justify-content:center;padding:12px 0;border-radius:14px;}
  .sidebar:not(.sidebar-drilled) .sidebar-label-text,
  .sidebar:not(.sidebar-drilled) .sidebar-caret{display:none;}
  .sidebar:not(.sidebar-drilled) .sidebar-icon{margin-right:0;font-size:17px;}
}
/* responsive tables -> cards */
@media(max-width:680px){
  .responsive-table thead{display:none;}
  .responsive-table, .responsive-table tbody, .responsive-table tr, .responsive-table td{display:block;width:100%;}
  .responsive-table tr{border:1px solid var(--panel-border);border-radius:14px;margin-bottom:10px;padding:6px 10px;background:var(--panel);box-shadow:var(--shadow-card);}
  .responsive-table td{border-bottom:1px dashed var(--line);display:flex;justify-content:space-between;gap:10px;padding:8px 2px;}
  .responsive-table td:last-child{border-bottom:none;}
  .responsive-table td::before{content:attr(data-label);font-weight:700;color:var(--ink-soft);font-size:11px;text-transform:uppercase;letter-spacing:.03em;}
  .responsive-table .btn-sm{padding:10px 14px;font-size:13px;}
  /* Mockup "JLOControl Redesign Keep": no card do celular, os botões de ação (.row-actions — já usado
     em ~metade das listas do sistema, não só Clientes) viram uma fileira de ícones sempre visível no
     rodapé do card, em vez de mais uma linha "rótulo: valor" empilhada — genérico, funciona em
     qualquer tela que já usa essa classe, sem precisar identificar qual coluna é "o nome" de cada
     tabela (isso variaria demais entre as ~51 telas pra generalizar com segurança). */
  .responsive-table td:has(.row-actions){flex-direction:column;align-items:stretch;gap:8px;border-top:1px dashed var(--line);border-bottom:none;padding-top:10px;margin-top:2px;}
  .responsive-table td:has(.row-actions)::before{display:none;}
  .responsive-table .row-actions{width:100%;justify-content:flex-start;}
  header.topbar{padding:10px 10px;gap:6px;}
  .brand{gap:7px;min-width:0;}
  .brand .mark{width:28px;height:28px;font-size:13px;flex-shrink:0;}
  .brand-name{font-size:16px;}
  .brand-tagline{display:none;}
  #topbarRight{gap:6px !important;}
  #filialAtivaSelect{max-width:90px !important;}
  .user-chip{display:none;}
  #buscaCodigoGlobalHolder{display:none!important;} /* tem style inline display:flex; sem !important
    aqui a busca continuaria ocupando espaço no celular, empurrando o menu */
  /* 12.323 — celular: botão 🔎 no cabeçalho abre a busca numa barra de largura total logo abaixo dele */
  #buscaMobileBtn{display:inline-flex;align-items:center;justify-content:center;height:34px;}
  #buscaCodigoGlobalHolder.busca-aberta{display:flex!important;position:fixed!important;left:0;right:0;z-index:60;padding:8px 10px;background:#22262B;box-shadow:0 8px 20px -10px rgba(0,0,0,.5);gap:6px;}
  #buscaCodigoGlobalHolder.busca-aberta #buscaCodigoGlobal{flex:1;min-width:0;width:auto!important;}
  #buscaCodigoGlobalHolder.busca-aberta #buscaCodigoGlobalModulo{display:block!important;width:38%!important;max-width:150px;}
  #buscaCodigoGlobalHolder.busca-aberta #buscaCodigoGlobalResultados{left:0;right:0;min-width:0;max-width:none;}
  #logoutBtn{padding:6px 9px;font-size:11.5px;}
  #sidebarCollapseBtn{display:none;}
  main{padding:16px 12px 76px;} /* 76px (não 50px) — abre espaço pra barra de navegação inferior (item 8) */
  .app-body{display:block;}
  .sidebar{display:none;position:fixed;top:53px;left:0;right:0;bottom:0;background:var(--nav-bg);z-index:50;overflow-y:auto;padding:10px 16px;width:auto !important;min-height:0;border-right:none;}
  .sidebar.open{display:block;}
  .sidebar-group{padding:14px 6px;}
  .panel{padding:16px;}
  .grid4{grid-template-columns:1fr 1fr;}
  /* alvos de toque maiores nos controles de ordem manual (⠿ ▲▼ + posição) — 22×15px é pequeno
     demais pra tocar com o dedo com precisão */
  .order-controls{gap:10px;}
  .drag-handle{font-size:22px;padding:6px;}
  .order-controls .drag-handle{font-size:24px;}
  .order-arrow-btn{width:34px;height:26px;font-size:12px;}
  .order-pos-input{width:52px;padding:8px 4px;font-size:14px;}
}
@media(max-width:400px){
  .brand-text{display:none;}
}

/* 12.322 — selos "Contrato ativo" / "Inadimplente" do cliente (clienteSelos.js) */
.cliente-selos-slot:empty{display:none;}
.cliente-selos-abaixo{display:block;margin-top:6px;}
.cliente-selos{display:inline-flex;flex-wrap:wrap;gap:6px;align-items:flex-start;}
.cliente-selo-item{display:inline-flex;flex-direction:column;gap:4px;}
.cliente-selo{border:0;font:inherit;font-size:11px;cursor:pointer;}
.cliente-selo-detalhe{white-space:pre-line;font-size:12px;color:var(--ink);background:var(--paper,#fff);border:1px solid var(--line,#ddd);border-radius:8px;padding:6px 8px;max-width:360px;}
