/* ════════════════════════════════════════════════════════════════════════════
   public/mobile/10-casca.css — PEÇA 10: A CASCA
   Carregada depois de styles.css e de contratos.css, e depois de 00-base.css
   (de quem consome os tokens --m-*). Mesma origem de autor: em empate de
   especificidade vence quem vem depois — é por isso que estas regras desfazem
   as de styles.css sem um único !important.

   COBRE (e é a ÚNICA peça que declara estes seletores, por contrato):
     header.top · .brand · .spacer · .search · .search kbd · .search input
     .who · .icon-btn · .menu-wrap · .menu · .menu button · .menu .sep
     nav.tabs · nav.tabs button · nav.tabs button > span · .tab-badge
     #tabsMais / .tabs-mais · main · .khead

   NÃO COBRE (donos vizinhos):
     .drawer/.scrim/.dhead/.dbody/.icon-close/.contact-row .......... peça 20
     .tablewrap/table/thead th/tbody/tr/td/.pager/td[data-lab] ...... peça 30
     .chat-* (incl. a ALTURA do .chat-wrap) ......................... peça 40
     #view-* (Agora, Pipeline, Vendas, Contratos, formulários) ...... peça 50
     tokens --m-*, piso de 16px dos campos, .toast-wrap, primitivos
     de toque (.chip-btn, .newlead-btn, .toggle), html/body ......... peça 00

   Uma única declaração vive FORA da @media: `#tabsMais{display:none}`.
   É a 4ª exceção nominal da arquitetura, aberta pelo FURO [20]: mobile.js
   acrescenta o botão "Mais" ao DOM sem condição de largura (de propósito —
   gatear em matchMedia quebraria ao girar o aparelho), então sem esta linha
   um 11º botão "☰ Mais" apareceria na barra de abas do DESKTOP todos os dias.

   ─── REGRA NORMATIVA DE CAMADA VERTICAL (FURO [15]) ─────────────────────────
   No celular a barra de abas é `position:fixed;bottom:0` e é OPACA, e ocupa
   sempre os últimos  calc(var(--m-nav-h) + var(--m-safe-b))  pixels da tela.
   NENHUM outro elemento `position:fixed` de NENHUMA peça pode ocupar essa
   faixa: quem precisa de rodapé ancora em
       bottom: calc(var(--m-nav-h) + var(--m-safe-b) + N)
   Vale em particular para o FAB "➕ Nova venda" da peça 50 (#view-nfse #vNova)
   e para qualquer coisa que a peça 00 queira pôr no pé (o .toast-wrap já foi
   para o topo justamente por isso). A peça 50 DEPENDE deste parágrafo.
   ════════════════════════════════════════════════════════════════════════════ */


/* ╔══════════════════════════════════════════════════════════════════════════╗
   ║ ÚNICA REGRA FORA DA MEDIA QUERY — exceção autorizada pelo FURO [20]      ║
   ╚══════════════════════════════════════════════════════════════════════════╝
   LOAD-BEARING para o desktop: mobile.js:72-81 faz
     mais.id = "tabsMais"; tabs.appendChild(mais)
   sem guarda de largura. Sem esta linha o botão "☰ Mais" herda
   `nav.tabs button` (styles.css:60) e vira uma 11ª aba no desktop.
   Tem de vir ANTES da regra `#tabsMais{display:flex}` de dentro da @media:
   as duas têm especificidade (1,0,0) e quem decide é a ordem no arquivo. */
#tabsMais{display:none}


/* ⚠️ A CONDICAO DA CAMADA MOBILE, identica nos 6 arquivos:
     largura ate 780px  OU  (altura ate 520px E ponteiro grosso)
   O segundo ramo existe porque celular DEITADO nao cabe no primeiro: um iPhone 12/13/14
   em paisagem mede 844px de largura (Pro Max, 926) e caia FORA da camada — recebia o
   layout de desktop numa tela de 375px de altura, com estouro horizontal de 45px
   (medido). `max-height:520px` pega paisagem de celular (375-428px de altura) e nao
   pega iPad deitado (768). `pointer:coarse` garante que nenhuma janela de desktop
   encolhida na vertical entre aqui. */
@media (max-width:780px), (max-height:520px) and (pointer:coarse){

/* ┌──────────────────────────────────────────────────────────────────────────┐
   │ 1 · CABEÇALHO — de 461px de linha para 375                              │
   └──────────────────────────────────────────────────────────────────────────┘
   Medição de partida (EVIDENCIA §1): header.top é flex de linha única, sem
   wrap e sem overflow; a soma das partes dá 461px de documento num viewport
   de 375. #themeBtn nasce em x=377 e o ⋮ em x=423 — os dois FORA da tela. */

  /* PRÉ-REQUISITO LOAD-BEARING DE TODA A PEÇA.
     DESFAZ styles.css:52 (backdrop-filter:saturate(160%) blur(10px)).
     backdrop-filter com valor != none cria BLOCO CONTENTOR para descendentes
     position:fixed — e nav.tabs é filha DIRETA de header.top (index.html:47
     dentro do <header class="top"> da 42). Sem este `none`, o
     `position:fixed;bottom:0` da barra resolveria contra a caixa de 60px do
     cabeçalho e a barra nasceria colada embaixo do header, NO TOPO da tela.
     Verificado: header.top não tem transform, filter, perspective, will-change
     nem contain, e .app (styles.css:51) é só flex — este é o único contentor
     acidental do caminho.
     O `background` opaco vem OBRIGATORIAMENTE junto: o valor de styles.css:52
     é color-mix(... 88%, transparent) e, sem o blur, a página apareceria
     atrás do cabeçalho durante a rolagem. */
  header.top{
    backdrop-filter:none;
    -webkit-backdrop-filter:none;
    background:var(--surface);
    gap:8px;                       /* DESFAZ styles.css:52 (gap:14px) — 4 vãos × 6px poupados */
    /* DESFAZ styles.css:52 (padding:11px 20px). Em longhand porque a faixa
       lateral do notch entra aqui: com viewport-fit=cover ligado, em PAISAGEM num
       iPhone com notch env(safe-area-inset-left/right) chega a ~47px, e o conteúdo
       do cabeçalho nasceria debaixo do recorte e dos cantos arredondados. */
    /* o padding-top carrega a faixa do topo: no modo APP (manifest.json,
       display:standalone) nao ha barra do navegador e o cabecalho nasceria debaixo do
       relogio e do notch. Em aba normal o env vale 0 e nada muda. */
    padding-top:calc(8px + env(safe-area-inset-top, 0px));
    padding-bottom:8px;
    padding-left:calc(12px + env(safe-area-inset-left, 0px));
    padding-right:calc(12px + env(safe-area-inset-right, 0px));
  }
  /* Conta da linha de 375px, com o cabeçalho enxugado:
       375 − 24 (padding) = 351 úteis
       − 32 (4 gaps de 8) − 30 (.brand só com o logo) − 38 (.who: .av 34 + pad 4)
       − 44 (#themeBtn) − 44 (⋮) = 163px para a BUSCA.
     Contra os ~52px medidos hoje (EVIDENCIA §1 / DOSSIE "busca com ~52px
     úteis"). Descontando os 34px de padding da lupa e os 12 da direita, sobram
     ~115px de texto digitável — a busca global volta a ser usável, e ela é o
     caminho curto pra achar um lead entre 2.564 (o campo próprio da aba Leads
     está declarado fora de escopo no contrato). */

  /* O TEXTO da marca sai; o losango fica.
     DESFAZ styles.css:55 (.brand small{display:block}) por ancestral.
     Por que tirar o bloco inteiro e não só o <small>: com o texto
     "CRM · Leads" a .brand mede ~105px (DOSSIE mediu 123px com o <small>), e
     aí a busca ficaria com 88px — 42px de texto, ou seja o MESMO defeito com
     outro número. O logo ◆ (styles.css:54, 30×30) mantém a identidade, e a
     barra inferior passa a dizer em que aba a pessoa está.
     #brandSub ("2.564 contatos", escrito por app.js:455) continua sendo
     atualizado; só não é pintado no celular. */
  .brand{flex:0 0 auto;min-width:0}
  .brand > div:not(.logo){display:none}

  /* DESFAZ styles.css:63 (.spacer{flex:1}) — um flex:1 de basis 0 que no
     celular só serve pra consumir o déficit de largura. */
  .spacer{display:none}

  /* DESFAZ styles.css:64 (min-width:200px;max-width:340px) e styles.css:309
     (.search{min-width:120px}). A busca passa a ser o item elástico da linha:
     é ela que fica com o que sobrar, em vez de a nav.tabs ficar com zero. */
  .search{min-width:0;max-width:none;flex:1 1 auto}

  /* atalho de teclado físico: não existe no celular, e styles.css:68 o põe
     ABSOLUTO em right:9px, por cima do texto digitado num campo estreito. */
  .search kbd{display:none}

  /* DESFAZ styles.css:66 (padding:9px 12px 9px 34px;font-size:13px).
     LONGHANDS, nunca o shorthand `padding` — FURO [3]: a lupa é
     `.search svg{position:absolute;left:11px}` (styles.css:65), não ocupa
     espaço no fluxo, e os 34px de padding-left são o que reserva o lugar
     dela. Um `padding:11px 12px` colocaria o ícone por cima do placeholder.
     O padding-left é REPETIDO aqui de propósito: é a única declaração de
     padding que este campo recebe na camada mobile (a peça 00 tirou
     `.search input` do bloco coletivo de 16px por causa deste furo).
     font-size:16px é o limiar EXATO abaixo do qual o Safari do iPhone dá
     zoom ao focar e não desfaz no blur. */
  .search input{
    font-size:16px;
    min-height:var(--m-tap);
    padding-top:11px;
    padding-bottom:11px;
    padding-left:34px;
    padding-right:12px;
  }

  /* o nome já é escondido por styles.css:309 (.who span{display:none}); fica
     só o avatar de 34px (styles.css:132), que é o sinal de qual conta está
     logada num aparelho compartilhado. O padding-left:4px de styles.css:71
     vira 0: 4px na linha mais disputada do app. */
  .who{padding-left:0;flex:0 0 auto}

  /* DESFAZ styles.css:69 (width:38px;height:38px) — #themeBtn e #moreBtn
     chegam aos 44px do HIG (EVIDENCIA §7 mediu 38×32 e 38×38).
     `flex:0 0 var(--m-tap)` é load-bearing: com `width` sozinho os dois ainda
     têm flex-shrink:1 e encolhem quando a linha aperta — foi assim que o
     #themeBtn foi medido com 32px de largura útil. */
  .icon-btn{
    flex:0 0 var(--m-tap);
    width:var(--m-tap);
    height:var(--m-tap);
    -webkit-tap-highlight-color:transparent;
  }
  .menu-wrap{flex:0 0 auto}


/* ┌──────────────────────────────────────────────────────────────────────────┐
   │ 2 · MENU ⋮ (#moreMenu) — onde ele cai no celular, e os alvos de 44px    │
   └──────────────────────────────────────────────────────────────────────────┘
   Confirmado antes de escrever: o menu NÃO sai da tela. Ele é
   `position:absolute;right:0` (styles.css:73) dentro de `.menu-wrap`
   (position:relative, styles.css:72), que é o ÚLTIMO item da linha — borda
   direita em 375−12 = 363. Com os 240px de min-width ele ocuparia 123→363.
   O que estava errado era outra coisa: os 7 itens têm ~37px de altura
   (styles.css:75, padding:9px 11px + 13px de fonte) e são justamente
   "Novo lead", "Importar planilha", "Meu perfil", "Exportar leads",
   "Atualizar agora", "Gerenciar time" e "Sair" (index.html:61-68). */
  .menu{
    top:calc(var(--m-tap) + 10px);  /* DESFAZ styles.css:73 (top:46px), que era 38px de botão + 8 */
    min-width:0;                    /* DESFAZ styles.css:73 (min-width:240px) */
    width:min(320px, calc(100vw - 24px));
    padding:6px;
    border-radius:var(--m-r);
    /* LOAD-BEARING contra a regra normativa de camada vertical deste arquivo:
       8 itens de 46px + separador + padding passam de 400px. Em pé isso cabe;
       em PAISAGEM (375px de altura) o pé do menu entraria na faixa da barra
       inferior, que é opaca e fica no mesmo contexto de empilhamento do
       header — o último item ("Sair") ficaria intocável. Com o teto o menu
       rola dentro de si. */
    max-height:calc(100dvh - var(--m-header-h) - var(--m-nav-h) - var(--m-safe-b) - 16px);
    overflow-y:auto;
    overscroll-behavior:contain;
  }
  /* DESFAZ styles.css:75 (padding:9px 11px;font-size:13px) — 37px → 44px */
  .menu button{
    min-height:var(--m-tap);
    padding:11px 12px;
    font-size:15px;
    border-radius:var(--m-r-sm);
    -webkit-tap-highlight-color:transparent;
  }
  .menu .sep{margin:6px 2px}


/* ┌──────────────────────────────────────────────────────────────────────────┐
   │ 3 · A MESMA nav.tabs VAI PARA O RODAPÉ                                  │
   └──────────────────────────────────────────────────────────────────────────┘
   Nenhum DOM novo além do #tabsMais que mobile.js acrescenta DENTRO de #tabs.
   Motivo (DOSSIE "a navegação nova NÃO pode duplicar os botões"): o clique é
   delegado em `$("#tabs").onclick` (app.js:435), o `.active` é escrito em
   `$$("#tabs button")` (app.js:408), os badges são por ID único — #chatBadge
   (app.js:2197-2201, que também escreve o document.title), #agoraBadge
   (2719-2722), #agendaBadge (2840-2843) — e o papel põe/tira `.hide` nesses
   MESMOS nós (app.js:350 nfse, 353 contratos, 356 agenda, 361
   dashboard+campaign). Barra nova = ID duplicado = badge morto pra sempre. */
  nav.tabs{
    position:fixed;
    left:0;right:0;bottom:0;top:auto;
    margin:0;                       /* DESFAZ styles.css:59 (margin-left:6px) */
    z-index:50;
    /* Por que 50 e não 70: nav.tabs vive DENTRO de header.top, que é
       `position:sticky;z-index:40` (styles.css:52) e portanto um contexto de
       empilhamento. Contra o resto da página a barra vale 40 — ou seja fica
       ABAIXO do .scrim (z-index:80, styles.css:206) e da .drawer (90,
       styles.css:208), que é exatamente o certo: a folha de tela cheia da
       peça 20 cobre a barra. Dentro do header o que importa é ficar abaixo do
       .menu (z-index:60, styles.css:73), senão a barra pintaria por cima do
       menu ⋮. Nada em <main> passa de 40 (thead th 10, .chat-snips 30). */
    display:flex;
    justify-content:space-between;
    gap:2px;                        /* DESFAZ styles.css:59 (gap:4px) */
    min-width:0;
    /* DESFAZ styles.css:59 (overflow-x:auto). Este overflow é a CAUSA do
       defeito medido: a nav é o único item flex de header.top com min-width:0
       (todos os outros têm piso), então o algoritmo de flex descarregava todo
       o déficit nela até width=0, e o overflow-x:auto clipava 446px de
       conteúdo dentro de uma caixa de 0px — sem faixa visível e sem área de
       arraste. Fixa com left/right:0, a largura passa a ser a da tela. */
    overflow:visible;
    background:var(--surface);
    border-top:1px solid var(--border);
    /* 5px em cima + 46px de botão + 5px embaixo = 56px = --m-nav-h (+1px de
       borda, absorvido pelos 16px de folga do padding-bottom do main).
       --m-safe-b é env(safe-area-inset-bottom) e só devolve valor real porque
       mobile.js acrescenta viewport-fit=cover à meta viewport; sem isso a
       última fileira cai debaixo do indicador de home do iPhone. */
    padding-top:5px;
    padding-bottom:calc(5px + var(--m-safe-b));
    /* a faixa lateral do notch em paisagem: sem isto o 1º slot (Agora) e o último
       ("Mais", o único caminho para Agenda/Dashboard/Pipeline/Campanha/E-mail e, no
       admin, Qbank/Agente/Aquecimento) nascem debaixo do recorte. */
    padding-left:calc(4px + env(safe-area-inset-left, 0px));
    padding-right:calc(4px + env(safe-area-inset-right, 0px));
  }

  nav.tabs button{
    /* DESFAZ styles.css:60 (flex:none) — era o outro motivo de os 10 botões
       nunca caberem: eles não encolhiam. */
    flex:1 1 0;
    min-width:0;
    position:relative;              /* LOAD-BEARING: âncora do .tab-badge absoluto abaixo */
    flex-direction:column;
    justify-content:center;
    gap:1px;                        /* DESFAZ styles.css:60 (gap:7px, que era horizontal) */
    min-height:46px;
    padding:5px 2px;                /* DESFAZ styles.css:60 (padding:8px 14px) */
    /* 16px é o tamanho do EMOJI: ele é nó de texto direto do botão
       (index.html:48-57, ex. `🎯 <span>Agora</span>`) e herda o font-size do
       botão. O rótulo tem tamanho próprio na regra seguinte. */
    font-size:16px;
    line-height:1.05;
    border-radius:var(--m-r-sm);
    -webkit-tap-highlight-color:transparent;
  }

  /* DESFAZ styles.css:309 (nav.tabs span{display:none}) — O RÓTULO VOLTA.
     Especificidade: `nav.tabs button > span` = (0,1,3) contra (0,1,2) da 309.
     Era esse o defeito dos "10 emoji sem palavra".

     A CONTA DOS 6 SLOTS, em 375px (o mais estreito em uso):
       375 − 8 (padding 4+4) − 10 (5 gaps de 2px) = 357 ⇒ 59,5px por slot
       menos 4px de padding do botão = 55,5px de conteúdo.
     A palavra mais longa da barra tem 9 caracteres: "Conversas", "Contratos",
     "Dashboard". A 10,5px, no stack -apple-system/Roboto com font-weight 600,
     a média é ~0,55em ≈ 5,8px por caractere ⇒ 9 × 5,8 = 52,2px; com
     letter-spacing:-.2px cai para ~50,4px. Cabe nos 55,5 com ~5px de folga,
     e em telas de 390/393/414px a folga só cresce.
     O ellipsis é REDE, não plano: se a fonte do sistema for mais larga que a
     média (ou o usuário estiver com fonte ampliada), o rótulo corta em vez de
     empurrar o slot vizinho e estourar a barra. */
  nav.tabs button > span{
    display:block;
    max-width:100%;
    overflow:hidden;
    text-overflow:ellipsis;
    white-space:nowrap;
    font-size:10.5px;
    letter-spacing:-.2px;
    font-weight:600;
  }

  /* o badge sai do fluxo e vai para o canto do slot.
     DESFAZ styles.css:355 (margin-left:6px;display:inline-block;
     vertical-align:1px), que o punha em linha e, com flex-direction:column,
     criaria uma TERCEIRA fileira dentro do botão de 46px.
     Especificidade (0,1,0) = a da 355; vence por vir depois.
     Detalhe que isto resolve: o #chatBadge foi medido em x=433 numa tela de
     375 (EVIDENCIA §1) — o contador de não lidas simplesmente não existia no
     celular, e o único outro sinal era o document.title, que o navegador de
     celular não mostra. */
  .tab-badge{
    position:absolute;
    top:3px;
    right:4px;
    margin:0;
    vertical-align:baseline;
  }

  /* ── o botão "Mais" (mobile.js:72-81) ── */
  /* Vence o `#tabsMais{display:none}` do topo deste arquivo: mesma
     especificidade (1,0,0), e esta vem depois. */
  #tabsMais{
    display:flex;
    order:9;                        /* garante o último slot mesmo se o nó mudar de lugar no DOM */
  }


/* ┌──────────────────────────────────────────────────────────────────────────┐
   │ 4 · OS 6 SLOTS — decisão do dono                                        │
   └──────────────────────────────────────────────────────────────────────────┘
   Ordem fixa: Agora · Leads · Conversas · Vendas · Contratos · Mais.
   Ela sai de graça da ordem do DOM (index.html:48-57 é agora, dashboard,
   leads, pipeline, campaign, email, chats, agenda, nfse, contratos) mais o
   order:9 do #tabsMais — nenhum `order` é necessário nos destinos.
   Escondidas da barra e alcançáveis pela folha "Mais": dashboard, pipeline,
   campaign, email, agenda, qbank, aquecimento, agente. Especificidade desta
   regra: (0,2,2).
   ⚠️ QBANK NASCE AQUI, e não na barra: a aba entrou depois que o dono escolheu
   os seis slots, e ela só existe para admin. Sem esta linha ela viraria o 7º
   botão e a barra quebraria a decisão — justamente para quem tem todas as abas
   reveladas. Pela folha "Mais" ela continua a um toque.
   ⚠️ E O QBANK NÃO ACENDE O PONTO VERMELHO DO "MAIS" (seção 5), de propósito:
   consultoria "a agendar" é o estado NORMAL da fila — toda venda nasce assim —,
   então o ponto ficaria aceso o dia inteiro para o admin e deixaria de avisar a
   call aguardando confirmação da Agenda, que é o que ele existe para avisar. O
   número do Qbank aparece no próprio botão, dentro da folha.
   ⚠️ O AQUECIMENTO TAMBÉM NASCE AQUI (F3, 26/09/2026), pelo mesmo motivo do Qbank: só admin, e
   depois da decisão dos seis slots. Na barra ele seria um slot a mais, com "Aquecimento" (11
   letras) cortado em reticências; na folha "Mais" ele fica a um toque, com o rótulo inteiro. O
   corpo da aba no celular é da peça 60 (public/mobile/60-aquecimento.css).
   ⚠️ E A 🤖 AGENTE TAMBÉM (DECISÃO DO DONO, 27/09/2026). Ela era o 7º botão da barra do admin
   (só admin a revela, app.js:363): a conta dos 6 slots da seção 3 não fechava justamente para
   quem tem todas as abas. Agora mora na folha "Mais", ao lado da 🔥, a um toque; e quando ela
   está aberta, quem acende na barra é o "Mais" (a ponte da seção 6).
   ⚠️ E A 🛡️ VERIFICAÇÃO TAMBÉM (02/10/2026): só admin, como a 🔥 e a 🤖. Na barra ela seria o 7º
   slot do admin e a conta dos 6 não fecharia; na folha "Mais" fica a um toque, com o rótulo inteiro. */
  nav.tabs button[data-view="dashboard"],
  nav.tabs button[data-view="pipeline"],
  nav.tabs button[data-view="campaign"],
  nav.tabs button[data-view="email"],
  nav.tabs button[data-view="agenda"],
  nav.tabs button[data-view="qbank"],
  nav.tabs button[data-view="aquecimento"],
  nav.tabs button[data-view="agente"],
  nav.tabs button[data-view="equipe"]{display:none}

  /* ── PROMOÇÃO POR PAPEL, só com CSS ──
     Conferido em app.js:348-362 antes de escrever (papéis reais em
     server/schema.ts:16 = admin | rep | vendedor):
       admin    → revela nfse (350) e contratos (353): os 5 slots existem.
       vendedor → revela nfse e contratos; esconde dashboard+campaign (361),
                  que já não estão na barra: os 5 slots existem.
       rep      → nfse e contratos NUNCA são revelados (nascem com .hide em
                  index.html:56-57) E agenda GANHA .hide (356). Sobram 3
                  destinos + Mais = 4 slots; faltam 2.
     REDE DE SEGURANÇA que faz estas regras serem seguras por construção:
     `.hide{display:none !important}` (styles.css:314). Nenhuma promoção aqui
     usa !important, então uma aba que o PAPEL escondeu continua escondida,
     aconteça o que acontecer. É por isso que a regra da Agenda abaixo é
     inofensiva mesmo sendo, para o `rep`, inerte.
     Se o navegador não tiver :has(), nenhuma das três casa e o rep fica com
     3 slots + Mais — o resto continua acessível pela folha. Falha graciosa. */

  /* (a) sem Vendas ⇒ o slot vira Agenda. Decisão do dono.
         Para o `rep` isto é INERTE (agenda tem .hide por app.js:356 e o
         !important da styles.css:314 vence) — fica declarada porque é a
         ordem do dono e porque cobre qualquer papel futuro que perca Vendas
         sem perder Agenda. Especificidade (0,4,3). */
  body[data-papel] nav.tabs:has(button[data-view="nfse"].hide) button[data-view="agenda"]{display:flex}

  /* (b) sem Contratos ⇒ o slot vira Pipeline. Decisão do dono.
         Pipeline nunca recebe .hide por papel (conferido: não aparece em
         app.js:348-362), então esta é a promoção que de fato funciona para o
         `rep`. Especificidade (0,4,3) contra (0,2,2) do display:none. */
  body[data-papel] nav.tabs:has(button[data-view="contratos"].hide) button[data-view="pipeline"]{display:flex}

  /* (c) o 5º destino do `rep`, que a decisão do dono não previa porque supôs
         que ele tinha Agenda. Condição: sem Vendas E sem Agenda — e o único
         papel nessa situação é o rep (o vendedor tem Vendas; o admin tem as
         duas). Dashboard é escondido só para vendedor (app.js:361), que não
         casa aqui. Sem esta regra o rep ficaria com 4 slots e um vão.
         Especificidade (0,6,4). */
  body[data-papel] nav.tabs:has(button[data-view="nfse"].hide):has(button[data-view="agenda"].hide)
    button[data-view="dashboard"]{display:flex}
  /* Resultado por papel, sempre 6 slots (o admin também, desde que a 🤖 foi para o "Mais"):
       admin/vendedor → Agora · Leads · Conversas · Vendas · Contratos · Mais
       rep            → Agora · Dashboard · Leads · Pipeline · Conversas · Mais
     E, com qualquer aba aberta, exatamente UM slot aceso: aba promovida aqui acende a si mesma e
     não o "Mais" (a ponte da seção 6 nega a condição destas promoções, desde 27/09/2026). */


/* ┌──────────────────────────────────────────────────────────────────────────┐
   │ 5 · A FOLHA "MAIS" — a mesma nav vira grade                             │
   └──────────────────────────────────────────────────────────────────────────┘
   A classe `.m-aberta` é posta/tirada por mobile.js:101-102 no próprio #tabs.
   Nenhum overlay novo. */
  nav.tabs.m-aberta{
    flex-wrap:wrap;
    /* flex-start e NÃO flex-end: a folha já é ancorada em bottom:0 e a altura
       dela encolhe até o conteúdo, então em pé o alinhamento é indiferente.
       Em PAISAGEM (375px de altura) o conteúdo passa do max-height e a folha
       vira contêiner de rolagem — com align-content:flex-end o começo da
       grade fica inalcançável por rolagem em vários navegadores. */
    align-content:flex-start;
    gap:8px;
    max-height:calc(100dvh - var(--m-header-h));
    overflow-x:hidden;
    overflow-y:auto;
    overscroll-behavior:contain;    /* rolar até o fim da folha não vaza o gesto pra lista atrás */
    padding:10px 10px calc(10px + var(--m-safe-b));
    /* FUROS [20]: fundo e sombra pra folha. O background opaco vem da regra
       base de nav.tabs; a sombra e o raio são o que dizem "isto está EM CIMA
       da página", já que o scrim é de outra peça e o fechar-tocando-fora é
       feito por mobile.js:113-117. */
    box-shadow:var(--shadow-lg);
    border-top-left-radius:var(--m-r);
    border-top-right-radius:var(--m-r);
  }
  /* `:not(.hide)` é OBRIGATÓRIO e é a linha mais perigosa deste arquivo:
     `.hide{display:none !important}` (styles.css:314) é o que protege as abas
     que o PAPEL esconde. Sem o :not, revelar aqui daria a um vendedor o
     Dashboard e a Campanha da base inteira, e a um rep as Vendas e os
     Contratos. Especificidade (0,3,2): vence os display:none da seção 4 sem
     precisar de !important — e continua perdendo do !important da .hide. */
  nav.tabs.m-aberta button:not(.hide){
    display:flex;
    flex:1 1 30%;
    min-height:60px;
  }
  /* na folha o slot é largo: o rótulo pode voltar ao tamanho legível.
     line-height PRÓPRIO (02/10/2026, pedido do dono): o rótulo é `overflow:hidden` (seção 3) e herdava o
     `line-height:1.05` do botão — 13 px de caixa para 14 px de letra (medido: scrollHeight 14 > clientHeight 13 em
     TODOS os rótulos da folha), e a perna do "q" de "Aquecimento" e do "ç" de "Verificação" saía cortada embaixo.
     Com 1.3 a caixa tem 16 px; o botão continua com os 60 px do min-height acima (o conteúdo vai a ~44). A barra de
     baixo fechada não muda (rótulo de 10,5 px, medido sem corte). Conferido em porte/F5/capturas/barra-de-abas.mjs. */
  nav.tabs.m-aberta button:not(.hide) > span{
    font-size:12.5px;
    letter-spacing:0;
    line-height:1.3;
  }
  nav.tabs.m-aberta #tabsMais{
    flex:1 1 100%;
    order:99;
    min-height:var(--m-tap);
  }


/* ┌──────────────────────────────────────────────────────────────────────────┐
   │ 6 · ESTADOS DE TOQUE                                                    │
   └──────────────────────────────────────────────────────────────────────────┘ */
  nav.tabs button.active{background:var(--accent-soft);color:var(--accent-text)}
  nav.tabs button:active{background:var(--surface-2)}

  /* Quando a aba ATIVA e uma das que moram atras do "Mais", quem acende e o
     "Mais" — senao nenhum dos 6 slots fica aceso e a pessoa perde a referencia de
     onde esta. Acontece em todo carregamento frio do admin: index.html:49 marca
     `data-view="dashboard"` como `.active`, e dashboard nao esta na barra.
     setView (app.js:408) poe `.active` num botao que aqui e `display:none`, e o
     #tabsMais nao tem `dataset.view` — entao a ponte tem que ser por CSS. */
  /* ⚠️ BADGE QUE MORA ATRAS DO "MAIS". A Agenda esta entre as cinco secoes da folha, e
     e ela que carrega o badge de call aguardando confirmacao (setAgendaBadge, app.js:2840)
     — para um vendedor, o aviso de que tem call pra confirmar ficava invisivel ate alguem
     abrir o "Mais". O ponto no canto do botao devolve o sinal a barra.
     Escrito para as cinco secoes da folha, e nao so pra Agenda: se amanha outra ganhar
     badge, ja esta coberto. `:not(.hide)` e como setAgendaBadge/setChatUnread revelam. */
  nav.tabs:has(button[data-view="agenda"] .tab-badge:not(.hide)) #tabsMais::after,
  nav.tabs:has(button[data-view="dashboard"] .tab-badge:not(.hide)) #tabsMais::after,
  nav.tabs:has(button[data-view="pipeline"] .tab-badge:not(.hide)) #tabsMais::after,
  nav.tabs:has(button[data-view="campaign"] .tab-badge:not(.hide)) #tabsMais::after,
  nav.tabs:has(button[data-view="email"] .tab-badge:not(.hide)) #tabsMais::after{
    content:"";
    position:absolute;
    top:4px;
    right:calc(50% - 16px);
    width:9px;
    height:9px;
    border-radius:50%;
    background:var(--rose);
    box-shadow:0 0 0 2px var(--surface);
  }
  /* com a folha aberta o ponto some: a secao esta a vista, com o badge de verdade */
  nav.tabs.m-aberta #tabsMais::after{content:none}

  /* ⚠️ AGENDA, PIPELINE E DASHBOARD SÓ ACENDEM O "MAIS" QUANDO A PROMOÇÃO POR PAPEL (seção 4) NÃO
     OS PÔS NA BARRA (achado R1 do revisor, 27/09/2026). A ponte valia sempre, e no celular do `rep`
     — que abre no Dashboard (app.js: currentView = "dashboard") e tem Dashboard e Pipeline
     promovidos — ficavam DOIS slots acesos: o Dashboard (ou o Pipeline) e o "Mais". Cada linha
     abaixo é a NEGAÇÃO EXATA da condição da promoção da mesma aba: "sem papel carimbado" OU "a aba
     cuja falta promove não está escondida". Qbank, Campanha, E-mail, 🔥 e 🤖 não têm promoção e
     continuam incondicionais. Especificidade: todas têm o #tabsMais (1,x,x), acima de qualquer
     :hover/:active da barra — igual a antes. scripts/teste-aquecimento-tela.ts (seção 6) avalia
     esta regra em cada papel e exige exatamente um slot aceso. */
  nav.tabs:has(button[data-view="campaign"].active) #tabsMais,
  nav.tabs:has(button[data-view="email"].active) #tabsMais,
  nav.tabs:has(button[data-view="qbank"].active) #tabsMais,
  nav.tabs:has(button[data-view="aquecimento"].active) #tabsMais,
  nav.tabs:has(button[data-view="agente"].active) #tabsMais,
  nav.tabs:has(button[data-view="equipe"].active) #tabsMais,
  body:not([data-papel]) nav.tabs:has(button[data-view="agenda"].active) #tabsMais,
  nav.tabs:not(:has(button[data-view="nfse"].hide)):has(button[data-view="agenda"].active) #tabsMais,
  body:not([data-papel]) nav.tabs:has(button[data-view="pipeline"].active) #tabsMais,
  nav.tabs:not(:has(button[data-view="contratos"].hide)):has(button[data-view="pipeline"].active) #tabsMais,
  body:not([data-papel]) nav.tabs:has(button[data-view="dashboard"].active) #tabsMais,
  nav.tabs:not(:has(button[data-view="nfse"].hide)):has(button[data-view="dashboard"].active) #tabsMais,
  nav.tabs:not(:has(button[data-view="agenda"].hide)):has(button[data-view="dashboard"].active) #tabsMais{
    background:var(--accent-soft);
    color:var(--accent-text);
  }

  /* No iOS o :hover fica colado no último elemento tocado até o toque
     seguinte: a aba que a pessoa acabou de tocar continuava pintada,
     competindo com a .active de verdade (escrita por setView, app.js:408).
     DESFAZ styles.css:61 (nav.tabs button:hover) — especificidade (0,2,2),
     igual à original, vence por ordem; e styles.css:70 (.icon-btn:hover) e
     styles.css:76 (.menu button:hover), ambas (0,1,1).
     `tbody tr:hover` e `.kcard/.qcard:hover` NÃO estão aqui: são das peças
     30 e 50. */
  @media (hover:none){
    nav.tabs button:hover{background:transparent;color:var(--muted)}
    nav.tabs button.active:hover{background:var(--accent-soft);color:var(--accent-text)}
    .icon-btn:hover{background:var(--surface);color:var(--muted);border-color:var(--border)}
    .menu button:hover{background:transparent}
  }


/* ┌──────────────────────────────────────────────────────────────────────────┐
   │ 7 · main — ESPAÇO PARA A BARRA, EM TODA ABA                             │
   └──────────────────────────────────────────────────────────────────────────┘
   A peça 10 é a ÚNICA dona de `main` (FUROS [14] e [4]): o `main` da peça 40
   foi retirado do escopo dela justamente porque
   `body:has(#view-chats.active) main{padding:12px 0 0}` apagava o
   padding-bottom desta regra e jogava o compositor das Conversas para
   DEBAIXO da barra opaca de z-index 50 — sem nada avisar, porque o
   .chat-wrap é overflow:hidden (styles.css:359). */

  /* DESFAZ styles.css:310 (main{padding:16px 14px 50px}) e, por consequência,
     styles.css:82 (padding:22px 24px 60px). Especificidade (0,0,1) nas três:
     vence por ordem de carregamento. */
  main{
    padding-top:14px;
    padding-bottom:calc(var(--m-nav-h) + var(--m-safe-b) + 16px);
    padding-left:calc(14px + env(safe-area-inset-left, 0px));
    padding-right:calc(14px + env(safe-area-inset-right, 0px));
  }

  /* FUROS [14] + [4]: as Conversas querem os 28px de gutter lateral de volta
     (a caixa de chat vai de borda a borda) e um topo menor — mas NÃO podem
     zerar o rodapé. `padding-inline` e `padding-top` são LONGHANDS de
     propósito: eles sobrescrevem só o que precisam e deixam o padding-bottom
     da regra acima intacto.
     Especificidade: `body:has(#view-chats.active)` = body(1 tipo) +
     :has(#view-chats.active)(1 id + 1 classe) + main(1 tipo) = (1,1,2),
     bem acima de (0,0,1) — então os longhands ganham do shorthand mesmo que
     algum dia a ordem das duas regras se inverta.
     Confirmado que a classe existe: setView faz
     `$$(".view").forEach(s => s.classList.toggle("active", s.id === "view-"+v))`
     (app.js:409) e `.view.active{display:block}` (styles.css:84).
     A ALTURA do .chat-wrap é da peça 40 e consome os mesmos tokens. */
  body:has(#view-chats.active) main{
    padding-inline:0;
    padding-top:12px;
  }


/* ┌──────────────────────────────────────────────────────────────────────────┐
   │ 8 · STICKY DO CABEÇALHO DE COLUNA DO KANBAN (.khead)                    │
   └──────────────────────────────────────────────────────────────────────────┘
   DESFAZ a METADE do styles.css:312 que diz `.khead{top:0}`.
   Com o header.top sticky, opaco e de 60px (z-index 40 contra os 2 da .khead,
   styles.css:189), o rótulo do estágio parava em y=0, ou seja 60px ATRÁS do
   cabeçalho: durante toda a rolagem da coluna — que no celular é coluna única
   (styles.css:310) e pode ter milhares de pixels — a pessoa perdia a única
   âncora de "em que estágio eu estou". O .kcol (styles.css:187) não tem
   overflow, então a coluna rola contra o VIEWPORT e o offset do header é a
   referência certa.
   (--m-header-h é 60px: padding 8+8 + .icon-btn 44. O 1px de border-bottom do
   header não entra na conta, de propósito — é a mesma aproximação que
   styles.css:160/189 já fazem no desktop.)

   ⚠️ FUROS [6] — O QUE ESTE ARQUIVO DELIBERADAMENTE NÃO FAZ:
   não tocar em `thead th{top:0}` da styles.css:312. Para as 3 tabelas que
   viram cartão o thead é `display:none` (peça 30) e o offset é indiferente;
   para as 7 que CONTINUAM tabela (canais app.js:516-529, prévia de importação
   2121, campanhas 3273, destinatários 3572, ranking 5018, parcelamentos 5077,
   produtos 5199 — nenhuma tem data-lab) o `.tablewrap{overflow-x:auto}`
   (styles.css:311) segue valendo, o overflow-y computa para auto e o
   .tablewrap passa a ser o scrollport mais próximo: um `top:60px` ali
   prenderia a linha de cabeçalho 60px DENTRO do wrap, cobrindo as primeiras
   linhas de dados. Com `top:0` ela pelo menos encosta no topo do wrap.
   A propriedade de `thead th` foi transferida para a peça 30, que declara
   `table:has(td[data-lab]) thead th{top:var(--m-header-h)}` — coerência de
   token, sem efeito prático.

   ⚠️ `.khead` NÃO ganha offset aqui, de propósito. A peça 50 põe `overflow-x:auto`
   na `.kanban` para as colunas virarem faixa horizontal; por CSS Overflow 3 isso faz
   o `overflow-y` computar para `auto` e a `.kanban` passa a ser o scrollport mais
   próximo da `.khead`. Como a altura dela é a do conteúdo, o sticky nunca dispara e
   qualquer `top` aqui seria regra morta — o `top:0` de styles.css:312 é o valor
   efetivo e o correto. */

}
