/* ============================================================================
   ui.css — base compartilhada do ZapSync
   ============================================================================

   CARREGADO COMO ÚLTIMO FILHO DO <head>, depois do <style> inline da página.
   Isso não é detalhe: é exatamente a posição que o antigo mobile.css ocupava
   (era injetado por nav.js com head.appendChild). Carregar antes do <style>
   faria as regras mobile perderem empates de especificidade que hoje ganham.

   Três camadas:

     A — TOKENS. Fonte única do tema. Durante a migração ficaram em
         :where(:root) (especificidade zero) para que o :root inline de cada
         página continuasse vencendo e nada mudasse de cor. Concluída a
         migração — nenhuma página define mais :root — voltaram a :root
         simples: se um navegador não entender :where(), ele descartaria a
         regra inteira e o app ficaria SEM tokens, ou seja, sem cor alguma.

     B — PRIMITIVAS. Vazia de propósito. Definir .btn/.card/.chip globalmente
         adicionaria propriedades que as páginas não declaram (uma página que só
         define padding no .btn herdaria fundo verde). Entram junto com a
         limpeza do CSS inline de cada página.

     C — CAMADA MOBILE. Tudo sob .zap-mobile, classe posta em <html> pelo
         boot.js (sincronamente, antes do primeiro paint) e espelhada em <body>
         pelo mobile.js. Escrever ".zap-mobile .x" dá 0,2,0 e vence o ".x"
         (0,1,0) do inline; onde a regra de página é mais específica, usa-se
         !important — sempre dentro do escopo mobile, então o desktop nunca vê.

   BREAKPOINTS — escala única para todo CSS novo:
     480px  celular estreito · 768px  mobile↔desktop · 1024px  tablet↔desktop

   Dívida conhecida: as páginas ainda carregam 14 breakpoints próprios (760,
   700, 820, 680, 620, 900, 860, 800, 640, 600, 560, 520, 500). Quase todos são
   ajustes de desktop estreito que não competem com a camada mobile; migram
   junto com cada tela. O único que importava — os 760px do dash.css, que
   decidiam layout dentro da faixa onde o modo mobile liga — já foi alinhado.

   CACHE: sw.js é cache-first para CSS/JS. Ao mudar este arquivo, suba o ?v=N
   nos <link> das páginas E o CACHE_NAME em sw.js, senão o celular fica preso
   na versão velha.
   ============================================================================ */


/* ════════════════════════════════════════════════════════════════════════════
   CAMADA A — TOKENS
   União das variáveis que hoje estão duplicadas em 19 blocos :root.
   Fonte canônica da paleta: dash.css:11-30.
   ════════════════════════════════════════════════════════════════════════════ */

:root {
  color-scheme: light;

  /* Superfícies */
  --bg-page: #ECE5DD;
  --bg-card: #FFFFFF;
  --bg-nav: #008069;
  --bg-input: #F0F2F5;
  --bg-hover: #F5F6F6;
  --bg-sidebar: #FFFFFF;
  --bg-2: #F7F8FA;
  /* Balões de mensagem (gerenciar, e-mail, tela inicial) */
  --recv-bg: #FFFFFF;
  --sent-bg: #D9FDD3;

  /* Bordas */
  --border-c: #E9EDEF;
  --border-s: #D1D7DB;

  /* Texto */
  --text-1: #111B21;
  --text-2: #3B4A54;
  --text-3: #667781;
  --text-nav: #FFFFFF;

  /* Marca */
  --accent: #00A884;
  --accent-dk: #008069;
  --accent-bg: rgba(0, 168, 132, .10);
  --btn-bg: #00A884;
  --btn-hover: #008069;

  /* Estados */
  --ok-bg: #D9FDD3;   --ok-fg: #027561;
  --er-bg: #FEECEC;   --er-fg: #C0392B;
  --warn-bg: #FFF4D6; --warn-fg: #8A6D00;
  --wa-bg: #FFF8E1;   --wa-fg: #856404;
  --pu-bg: rgba(0, 168, 132, .12); --pu-fg: #027561;

  /* Elevação */
  --shadow: 0 1px 3px rgba(0, 0, 0, .08);
  --shadow-md: 0 4px 16px rgba(0, 0, 0, .10);
  --nav-hover: rgba(255, 255, 255, .15);
  --nav-active: rgba(255, 255, 255, .25);

  /* ── Escalas novas (não existiam: tudo era valor literal repetido) ── */
  --sp-1: 4px;  --sp-2: 8px;  --sp-3: 12px;
  --sp-4: 16px; --sp-5: 24px; --sp-6: 32px;

  --fs-xs: 12px; --fs-sm: 13px; --fs-md: 14px;
  --fs-lg: 16px; --fs-xl: 21px;

  --r-sm: 8px; --r-md: 12px; --r-lg: 16px; --r-full: 999px;

  --z-nav: 200; --z-drawer: 400; --z-modal: 600; --z-toast: 800;

  /* Altura mínima de alvo tocável (WCAG 2.5.5) */
  --touch: 44px;
}

[data-theme="dark"] {
  color-scheme: dark;

  --bg-page: #0B141A;
  --bg-card: #202C33;
  --bg-nav: #202C33;
  --bg-input: #2A3942;
  --bg-hover: #2A3942;
  --bg-sidebar: #111B21;
  --bg-2: #111B21;
  --recv-bg: #202C33;
  --sent-bg: #005C4B;

  --border-c: #2A3942;
  --border-s: #3B4A54;

  --text-1: #E9EDEF;
  --text-2: #8696A0;
  --text-3: #667781;
  --text-nav: #E9EDEF;

  --accent: #00A884;
  --accent-dk: #00A884;
  --accent-bg: rgba(0, 168, 132, .15);

  --ok-bg: rgba(0, 168, 132, .15);   --ok-fg: #00A884;
  --er-bg: rgba(192, 57, 43, .15);   --er-fg: #E74C3C;
  --warn-bg: rgba(214, 164, 0, .15); --warn-fg: #E1B000;
  --wa-bg: rgba(245, 158, 11, .15);  --wa-fg: #fbbf24;
  --pu-fg: #4ADE80;

  --shadow: 0 1px 3px rgba(0, 0, 0, .4);
  --shadow-md: 0 4px 16px rgba(0, 0, 0, .5);
  --nav-hover: rgba(255, 255, 255, .08);
  --nav-active: rgba(0, 168, 132, .25);
}


/* ════════════════════════════════════════════════════════════════════════════
   CAMADA B — PRIMITIVAS
   Reservada. Ver o cabeçalho: entram junto com a migração de cada página.
   ════════════════════════════════════════════════════════════════════════════ */


/* ════════════════════════════════════════════════════════════════════════════
   CAMADA C — MOBILE
   ════════════════════════════════════════════════════════════════════════════ */

/* ── Navegação: gaveta (drawer) ──────────────────────────────────────────────
   Substitui a antiga barra inferior de abas, que empilhava 10-11 abas de ~25px
   e ainda escondia o fim das listas. A gaveta cabe qualquer número de itens e
   libera a faixa de baixo da tela inteira.
   O menu horizontal do topo é escondido no celular e vive aqui dentro.        */

.zap-burger { display: none; }
.zap-tabbar { display: none !important; }   /* neutraliza mobile.js em cache antigo */

.zap-mobile .navbar .nav-links { display: none; }
.zap-mobile .navbar { padding: 0 var(--sp-3, 12px); gap: var(--sp-2, 8px); }

/* A barra do topo fica no limite em 360px: com ☰ + marca + tema + sino + pílula
   do usuário sobra pouco. O nome do usuário sai (o avatar já identifica quem
   está logado, e o nome completo aparece no menu que o botão abre). */
.zap-mobile #zapNavNome, .zap-mobile .zap-chev { display: none; }
.zap-mobile .zap-user-btn { padding: 3px; border-radius: var(--r-full, 999px); }

.zap-mobile .zap-burger {
  display: flex; align-items: center; justify-content: center;
  width: var(--touch, 44px); height: var(--touch, 44px); flex-shrink: 0;
  margin-left: -6px;
  border: none; background: none; cursor: pointer;
  color: var(--text-nav, #fff); border-radius: var(--r-sm, 8px);
}
.zap-mobile .zap-burger:active { background: var(--nav-hover); }

/* No desktop os dois somem do DOM visível E da navegação por teclado — o
   elemento é montado sempre (para o resize funcionar), mas fica display:none. */
.zap-scrim, .zap-drawer { display: none; }

.zap-mobile .zap-scrim {
  display: block;
  position: fixed; inset: 0; z-index: calc(var(--z-drawer, 400) - 1);
  background: rgba(0, 0, 0, .45);
  opacity: 0; pointer-events: none; transition: opacity .2s ease;
}
.zap-drawer-open .zap-scrim { opacity: 1; pointer-events: auto; }

.zap-mobile .zap-drawer {
  position: fixed; top: 0; bottom: 0; left: 0; z-index: var(--z-drawer, 400);
  width: min(84vw, 320px);
  display: flex; flex-direction: column;
  background: var(--bg-card); border-right: 1px solid var(--border-c);
  box-shadow: 4px 0 24px rgba(0, 0, 0, .18);
  transform: translateX(-100%); transition: transform .24s ease;
  overscroll-behavior: contain;
  padding-bottom: env(safe-area-inset-bottom, 0);
}
.zap-drawer-open .zap-drawer { transform: none; }

.zap-drawer-head {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2, 8px);
  padding: calc(var(--sp-3, 12px) + env(safe-area-inset-top, 0)) var(--sp-4, 16px) var(--sp-3, 12px);
  background: var(--bg-nav); color: #fff;
  font-weight: 700; font-size: var(--fs-lg, 16px);
  flex-shrink: 0;
}
.zap-dclose {
  display: flex; align-items: center; justify-content: center;
  width: var(--touch, 44px); height: var(--touch, 44px); margin-right: -8px;
  border: none; background: none; cursor: pointer; color: #fff;
}
.zap-drawer-nav {
  flex: 1; overflow-y: auto; -webkit-overflow-scrolling: touch;
  padding: var(--sp-2, 8px);
}
.zap-drawer-foot {
  flex-shrink: 0; padding: var(--sp-2, 8px);
  border-top: 1px solid var(--border-c);
}

.zap-ditem {
  display: flex; align-items: center; gap: var(--sp-3, 12px);
  min-height: var(--touch, 44px); padding: 0 var(--sp-3, 12px);
  border-radius: var(--r-sm, 8px);
  color: var(--text-1); text-decoration: none;
  font-size: var(--fs-md, 14px); font-weight: 500;
}
.zap-ditem svg { width: 19px; height: 19px; flex-shrink: 0; color: var(--text-3); }
.zap-ditem.active { background: var(--accent-bg); color: var(--accent-dk); font-weight: 700; }
.zap-ditem.active svg { color: var(--accent-dk); }
[data-theme="dark"] .zap-ditem.active,
[data-theme="dark"] .zap-ditem.active svg { color: var(--accent); }

.zap-dgroup { margin-top: var(--sp-2, 8px); }
.zap-dgroup-lbl {
  display: flex; align-items: center; gap: var(--sp-2, 8px);
  padding: var(--sp-2, 8px) var(--sp-3, 12px) var(--sp-1, 4px);
  color: var(--text-3); font-size: var(--fs-xs, 12px);
  font-weight: 700; text-transform: uppercase; letter-spacing: .5px;
}
.zap-dgroup-lbl svg { width: 15px; height: 15px; }
.zap-dsub {
  display: flex; align-items: center;
  min-height: var(--touch, 44px);
  padding: 0 var(--sp-3, 12px) 0 var(--sp-6, 32px);
  border-radius: var(--r-sm, 8px);
  color: var(--text-2); text-decoration: none; font-size: var(--fs-sm, 13px);
}
.zap-dsub.active { background: var(--accent-bg); color: var(--accent-dk); font-weight: 700; }
[data-theme="dark"] .zap-dsub.active { color: var(--accent); }

.zap-ddesktop {
  width: 100%; min-height: var(--touch, 44px);
  border: 1px solid var(--border-c); border-radius: var(--r-sm, 8px);
  background: none; color: var(--text-3);
  font-size: var(--fs-sm, 13px); font-family: inherit; cursor: pointer;
}

/* Com a gaveta aberta a página atrás não rola */
.zap-drawer-open, .zap-drawer-open body { overflow: hidden; }


/* ── Cabeçalho fixo dos modais (montado pelo mobile.js) ──────────────────────
   Editar tarefa tem uns 10 campos: o modal rola inteiro, o título some no topo
   e o único jeito de fechar era rolar até o "Cancelar" no fim. No celular o
   título vira barra grudada com ✕ ao lado.
   No desktop `display:contents` faz o embrulho sumir do layout — a tela fica
   exatamente como era antes.                                                  */
.zap-mhead { display: contents; }
.zap-mclose { display: none; }

.zap-mobile .modal-bg { padding: var(--sp-2, 8px); }
.zap-mobile .modal-bg > .modal {
  width: 100%; max-height: 92dvh; padding: var(--sp-4, 16px);
}

.zap-mobile .zap-mhead {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-2, 8px);
  position: sticky; top: 0; z-index: 2;
  margin: calc(var(--sp-4, 16px) * -1) calc(var(--sp-4, 16px) * -1) var(--sp-3, 12px);
  padding: var(--sp-2, 8px) var(--sp-3, 12px) var(--sp-2, 8px) var(--sp-4, 16px);
  background: var(--bg-card); border-bottom: 1px solid var(--border-c);
  border-radius: 14px 14px 0 0;
}
.zap-mobile .zap-mhead > h3 { margin: 0; }

/* Modal que já traz cabeçalho próprio (chamadas.html) só precisa dele grudado:
   o ✕ dele já existe. `.modal-body` tem o padding, então aqui não há margem
   negativa a compensar. */
.zap-mobile .modal-bg > .modal > .zap-mhead-nativo {
  position: sticky; top: 0; z-index: 2;
  background: var(--bg-card); border-radius: 14px 14px 0 0;
}
.zap-mobile .modal-bg > .modal:has(> .zap-mhead-nativo) { padding: 0; }

.zap-mobile .zap-mclose {
  display: flex; align-items: center; justify-content: center;
  width: var(--touch, 44px); height: var(--touch, 44px); flex-shrink: 0;
  border: none; background: none; cursor: pointer;
  color: var(--text-2); border-radius: var(--r-sm, 8px);
}
.zap-mobile .zap-mclose:active { background: var(--bg-hover); }


/* ── Respiro lateral e safe-area dos containers de página ────────────────────
   `.page` e `.container` entraram na lista: contatos.html e sistema.html usam
   `.page` e ficavam de fora de todo o tratamento mobile.                      */
.zap-mobile .page-content,
.zap-mobile .page-wrap,
.zap-mobile .page,
.zap-mobile .container {
  padding-left: var(--sp-3, 12px);
  padding-right: var(--sp-3, 12px);
  padding-bottom: calc(var(--sp-5, 24px) + env(safe-area-inset-bottom, 0));
}

/* Altura REAL da tela. As duas páginas de layout fixo — email.html:56 e
   admin.html:73 — usam `height:100vh;overflow:hidden`, e no celular os 100vh
   incluem a barra de URL do navegador: o fundo da tela fica inalcançável.
   Só elas são alvo (o :has evita mexer nas páginas que rolam normalmente); o
   mesmo fix já existia isolado para o gerenciar.html. */
.zap-mobile body:has(> .mail-layout),
.zap-mobile body:has(> .admin-layout),
body.zap-mobile:has(> .mail-layout),
body.zap-mobile:has(> .admin-layout) { height: 100dvh; }

/* Grades de painel viram uma coluna */
.zap-mobile .dash-grid,
.zap-mobile .dash-2col,
.zap-mobile .stats-row,
.zap-mobile .gauges-row,
.zap-mobile .two-col,
.zap-mobile .charts-row,
.zap-mobile .bottom-row,
.zap-mobile .config-row,
.zap-mobile .cfg-field-row { grid-template-columns: 1fr !important; }

/* sessoes.html: minmax(360px,1fr) não encolhe abaixo de 360px e era o único
   overflow horizontal real do app. */
.zap-mobile .contas-grid,
.zap-mobile .sessoes-grid { grid-template-columns: 1fr !important; }

/* Tabelas largas rolam na horizontal. Seletor amplo de propósito: o app só tem
   5 tabelas de verdade, e a versão antiga só alcançava as que estavam dentro de
   .page-content/.page-wrap — deixando de fora as 9 colunas do admin.html. */
.zap-mobile table {
  display: block; max-width: 100%;
  overflow-x: auto; white-space: nowrap;
  -webkit-overflow-scrolling: touch;
}
/* usuarios.html: o wrapper com overflow:hidden cortava as colunas finais sem
   scroll possível — as ações ficavam inalcançáveis. */
.zap-mobile .tabela-wrap,
.zap-mobile .table-wrap,
.zap-mobile .dtable-wrap { overflow-x: auto !important; }


/* ── Formulários: fim do zoom automático do iOS ──────────────────────────────
   O Safari dá zoom ao focar qualquer campo com font-size < 16px e NÃO desfaz o
   zoom ao sair. Nenhum campo do app chegava a 16px (o pior tinha 10.5px).
   O !important é necessário: os piores casos são regras de classe, mais
   específicas que qualquer seletor de elemento. Escopado no modo mobile, então
   o desktop continua com a tipografia compacta de sempre.                     */
.zap-mobile input:not([type=checkbox]):not([type=radio]):not([type=range]),
.zap-mobile select,
.zap-mobile textarea {
  font-size: 16px !important;
  max-width: 100%;
  /* min-width:0 é obrigatório junto com os 16px: a largura intrínseca de um
     <input> vem do atributo size (20 caracteres por padrão), então aumentar a
     fonte aumenta o mínimo do campo. Sem isto o campo deixa de encolher e
     empurra o grid/flex que o contém — foi o que alargou a tela de Tarefas. */
  min-width: 0;
}
/* E os contêineres precisam poder encolher junto: item de grid/flex tem
   min-width:auto por padrão, que respeita o mínimo do conteúdo. */
.zap-mobile .wrap > *,
.zap-mobile .painel,
.zap-mobile .busca-wrap,
.zap-mobile .campo,
.zap-mobile .linha2 > * { min-width: 0; }


/* ── Alvos de toque ──────────────────────────────────────────────────────────
   O padrão do app era 26-34px; o mínimo acessível é 44px. Lista explícita das
   classes reais em uso — um `button{}` genérico atingiria célula de calendário,
   seletor de emoji e afins.                                                    */
.zap-mobile .btn,
.zap-mobile .btn-primario, .zap-mobile .btn-neutro,
.zap-mobile .btn-primary, .zap-mobile .btn-sec,
.zap-mobile .btn-filtro, .zap-mobile .btn-exportar,
.zap-mobile .icon-btn, .zap-mobile .ico-btn, .zap-mobile .ic-btn,
.zap-mobile .attach-btn, .zap-mobile .mic-btn, .zap-mobile .send-btn,
.zap-mobile .btn-nova-conv, .zap-mobile .theme-toggle,
.zap-mobile .rt-btn, .zap-mobile .cmd,
.zap-mobile .refresh-btn, .zap-mobile .sess-sel {
  min-height: var(--touch, 44px);
  min-width: var(--touch, 44px);
}
/* Controles da barra do topo e das barras de abas/seções internas. Por container
   em vez de por classe: pega também os botões sem classe (ex.: o alternador
   Mês/Lista da agenda). */
.zap-mobile .navbar button,
.zap-mobile .navbar > a,
.zap-mobile .zap-notif-btn, .zap-mobile .zap-user-btn,
.zap-mobile .theme-toggle,
.zap-mobile .tabs-visao button,
.zap-mobile .tabs .tab,
.zap-mobile .sb-item,
.zap-mobile .range-tabs a,
.zap-mobile .badge-google { min-height: var(--touch, 44px); }
/* Botões redondos de ícone: a largura é fixa no CSS de origem, e min-width
   sempre prevalece sobre width. */
.zap-mobile .zap-notif-btn,
.zap-mobile .theme-toggle { min-width: var(--touch, 44px); }
.zap-mobile .tabs .tab, .zap-mobile .sb-item,
.zap-mobile .tabs-visao button { display: inline-flex; align-items: center; }
/* Chips continuam compactos na caixa (senão viram botões enormes), mas ganham
   área tocável de 44px por fora. */
.zap-mobile .chip, .zap-mobile .fchip, .zap-mobile .pill {
  position: relative;
  min-height: 40px;
  display: inline-flex; align-items: center;
}
.zap-mobile .chip::after, .zap-mobile .fchip::after {
  content: ""; position: absolute; inset: -4px; /* 48px de área tocável */
}
/* Ícones dentro de listas densas: mesma técnica, para não esticar a linha. */
.zap-mobile .conv-menu-btn, .zap-mobile .action-dot-btn, .zap-mobile .del {
  position: relative;
}
.zap-mobile .conv-menu-btn::after,
.zap-mobile .action-dot-btn::after,
.zap-mobile .del::after { content: ""; position: absolute; inset: -8px; }


/* ── Ações que só existiam no :hover ─────────────────────────────────────────
   Num celular não há hover: editar mensagem, o menu da conversa e renomear /
   excluir lista de tarefas simplesmente não existiam. Em iOS o primeiro toque
   simula hover e o segundo dispara o clique no elemento de baixo — errático.  */
@media (hover: none) {
  .lista-acoes { display: flex !important; }
  .conv-menu-btn, .action-dot-btn, .del, .zap-notif-x {
    opacity: 1 !important; pointer-events: auto !important;
  }
  /* Sobre a bolha da mensagem fica translúcido para não poluir a leitura. */
  .bubble-edit-btn { opacity: .55 !important; pointer-events: auto !important; }
}


/* ── Toasts ──────────────────────────────────────────────────────────────────
   Os ~10 toasts do app usam a mesma classe mas cada página fixa seu próprio
   canto (bottom:24px + right:24px, ou left:50% com translate). No celular
   viravam uma tarja atravessada; aqui viram uma faixa inferior única, acima da
   safe-area do iPhone.                                                        */
.zap-mobile .toast,
.zap-mobile .zap-pop-stack {
  left: var(--sp-3, 12px) !important;
  right: var(--sp-3, 12px) !important;
  bottom: calc(var(--sp-3, 12px) + env(safe-area-inset-bottom, 0)) !important;
  transform: none !important;
  max-width: none !important;
  width: auto !important;
  z-index: var(--z-toast, 800);
}


/* Botão "Instalar app" (pwa.js:72) — desenhado por style.cssText inline, então
   só !important alcança. Sobe acima da safe-area e ganha altura tocável. */
.zap-mobile #pwa-install-btn {
  min-height: var(--touch, 44px) !important;
  bottom: calc(var(--sp-4, 16px) + env(safe-area-inset-bottom, 0)) !important;
}


/* ── Modais viram bottom sheet ───────────────────────────────────────────────
   Um diálogo centralizado de 380px numa tela de 360px não tem margem e obriga o
   polegar a subir. Vindo de baixo, ele nasce onde a mão já está.              */
/* A safe-area do iPhone é reservada no overlay, não no box: mexer no
   padding-bottom do box apagaria o respiro interno que cada página define. */
.zap-mobile .modal-overlay,
.zap-mobile .modal-bg {
  align-items: flex-end !important;
  padding: 0 0 env(safe-area-inset-bottom, 0) !important;
}
.zap-mobile .modal-box,
.zap-mobile .modal-bg > .modal {
  width: 100% !important;
  max-width: none !important;
  border-radius: var(--r-lg, 16px) var(--r-lg, 16px) 0 0 !important;
  max-height: 88dvh !important;
  animation: zap-sheet-up .22s ease;
}
@keyframes zap-sheet-up { from { transform: translateY(12%); } to { transform: none; } }
/* Corpo do modal rola por dentro em vez de estourar a tela */
.zap-mobile .modal-body { overflow-y: auto; -webkit-overflow-scrolling: touch; }

@media (prefers-reduced-motion: reduce) {
  .zap-drawer, .zap-scrim { transition: none; }
  .zap-mobile .modal-box, .zap-mobile .modal-bg > .modal { animation: none; }
}


/* ── ia.html: abas internas rolam na horizontal ──────────────────────────── */
.zap-mobile .tabs { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.zap-mobile .tabs::-webkit-scrollbar { height: 0; }
.zap-mobile .tabs .tab { flex-shrink: 0; }


/* ── admin.html: menu lateral vira barra horizontal rolável ──────────────── */
.zap-mobile .admin-layout { flex-direction: column; }
.zap-mobile .admin-sidebar {
  width: 100%; min-width: 0; flex-direction: row; gap: var(--sp-1, 4px);
  padding: var(--sp-2, 8px) var(--sp-3, 12px); position: static; flex-shrink: 0;
  border-right: none; border-bottom: 1px solid var(--border-c);
  overflow-x: auto; -webkit-overflow-scrolling: touch;
}
.zap-mobile .admin-sidebar::-webkit-scrollbar { height: 0; }
.zap-mobile .admin-sidebar .sb-item { width: auto; flex-shrink: 0; white-space: nowrap; }
.zap-mobile .admin-sidebar .sb-sep,
.zap-mobile .admin-sidebar .sb-group-lbl { display: none; }
.zap-mobile .admin-main {
  padding: var(--sp-3, 12px) var(--sp-3, 12px)
           calc(var(--sp-5, 24px) + env(safe-area-inset-bottom, 0));
}
.zap-mobile .admin-main .page-header { flex-direction: column; align-items: stretch; gap: var(--sp-3, 12px); }


/* ── Dashboards ──────────────────────────────────────────────────────────────
   Os KPIs já caem em 2 colunas sozinhos (auto-fit minmax(170px)); o que
   atrapalhava era a densidade: rótulo de 11.5px em caixa alta com
   letter-spacing, e canvas de altura fixa espremendo os rótulos do eixo.      */
.zap-mobile .stat-label {
  font-size: var(--fs-xs, 12px);
  text-transform: none;
  letter-spacing: .2px;
}
.zap-mobile .stat-val { font-size: 24px; }
/* Os KPIs da tela inicial são cartões horizontais (ícone + número + rótulo):
   ficam bem em uma coluna, mas com o padding do desktop cinco deles ocupam duas
   telas de rolagem. Compactados, cabem quase todos de uma vez. */
.zap-mobile .stat-card { padding: 12px 14px; gap: 12px; }
.zap-mobile .stat-icon { width: 38px; height: 38px; flex-shrink: 0; }

/* O botão "Instalar app" nasce no mesmo canto do assistente de IA flutuante.
   No celular ele vai para o canto oposto. */
.zap-mobile #pwa-install-btn { right: auto !important; left: var(--sp-3, 12px) !important; }
.zap-mobile .chart-wrap { height: min(58vw, 240px); min-height: 190px; }
.zap-mobile .chart-wrap.sm { height: min(50vw, 200px); min-height: 170px; }
.zap-mobile .dash-tools { width: 100%; flex-wrap: wrap; }
.zap-mobile .dash-tools > * { flex: 1; }
.zap-mobile .dash-header h1 { font-size: 19px; }


/* ── Tarefas: linha de adição e itens da lista ───────────────────────────────
   O "adicionar rápido" tem campo + 2 botões numa linha; em 360px o campo fica
   com ~130px, curto demais para ler o que se digita. Empilha. Os itens ganham
   respiro vertical, porque a caixa de marcar precisa de alvo próprio.         */
.zap-mobile .add-row { flex-wrap: wrap; }
.zap-mobile .add-row > input { flex: 1 1 100%; }
.zap-mobile .add-row > button { flex: 1; }
.zap-mobile .tarefa { padding: 12px 8px; gap: 12px; }
.zap-mobile .tarefa input[type=checkbox] { width: 20px; height: 20px; flex-shrink: 0; }


/* ── Conversas: a lista precisa de altura, não de cabeçalho ──────────────────
   Categorias, busca e abas ocupavam ~190px do topo antes da primeira conversa.
   Compactados, e as abas rolam na horizontal em vez de espremer 4 rótulos.    */
.zap-mobile .sb-cats .cat-btn { padding: 6px 4px; font-size: 11px; }
.zap-mobile .sb-tabs {
  overflow-x: auto; -webkit-overflow-scrolling: touch; padding: 6px 12px;
}
.zap-mobile .sb-tabs::-webkit-scrollbar { height: 0; }
.zap-mobile .sb-tabs .filter-btn { flex: 0 0 auto; padding: 8px 14px; font-size: 13px; }


/* ── Cabeçalho de página: título e ações empilham ────────────────────────────
   Lado a lado num celular, o botão de ação é espremido a ponto de quebrar o
   rótulo em duas linhas. Alcança as 10 telas que usam .page-header.           */
.zap-mobile .page-header {
  flex-direction: column; align-items: stretch;
  gap: var(--sp-3, 12px);
}
.zap-mobile .page-header .btn { justify-content: center; }


/* ── Barras de filtro / ferramentas: quebram linha em vez de estourar ─────── */
.zap-mobile .filtros-bar,
.zap-mobile .filtros,
.zap-mobile .toolbar,
.zap-mobile .filters { flex-wrap: wrap; }
/* A barra de comandos do e-mail tem ~10 botões numa linha só (747px de conteúdo
   em 390px de tela). Rola na horizontal em vez de esticar a página inteira. */
.zap-mobile .cmdbar {
  overflow-x: auto; -webkit-overflow-scrolling: touch;
}
.zap-mobile .cmdbar::-webkit-scrollbar { height: 0; }
.zap-mobile .cmdbar > * { flex-shrink: 0; }
/* Linhas em flex que cortavam conteúdo dentro da própria caixa em 360px:
   o cabeçalho de endpoint da API e o título de seção com as abas de período. */
.zap-mobile .ep-header,
.zap-mobile .section-title { flex-wrap: wrap; }


/* ── gerenciar.html: dois painéis viram painel único ─────────────────────────
   A lista ocupa a tela; ao tocar numa conversa o chat entra deslizando por cima,
   com botão voltar integrado ao histórico do navegador (mobile.js).           */
.zap-back { display: none; }
.zap-mobile .zap-back {
  display: flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; flex-shrink: 0;
  border: none; background: none; cursor: pointer;
  color: var(--text-2); margin: 0 -2px 0 -4px;
}

.zap-mobile .chat-layout { position: relative; }
.zap-mobile .sidebar { width: 100%; min-width: 0; max-width: none; border-right: none; }
.zap-mobile .sb-list { padding-bottom: calc(var(--sp-4, 16px) + env(safe-area-inset-bottom, 0)); }

.zap-mobile .chat-main {
  position: absolute; inset: 0; z-index: 250;
  transform: translateX(100%);
  transition: transform .22s ease;
  background: var(--bg-page);
}
/* zap-chat-open é marcado em <html> junto com zap-mobile (mobile.js), então as
   duas classes casam no mesmo elemento. */
.zap-mobile.zap-chat-open .chat-main { transform: translateX(0); }

.zap-mobile .chat-header { gap: var(--sp-2, 8px); padding: var(--sp-2, 8px) var(--sp-3, 12px); }
.zap-mobile .chat-header .chat-info { flex: 1; min-width: 0; }
.zap-mobile .chat-header .chat-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.zap-mobile .msgs-area { padding: var(--sp-3, 12px); }
.zap-mobile .chat-input-area {
  padding-bottom: calc(var(--sp-2, 8px) + env(safe-area-inset-bottom, 0));
  flex-wrap: wrap;
}
.zap-mobile #audioPreviewWrap { order: -1; }

/* A página do chat usa a altura DINÂMICA da tela; o ajuste fino do teclado é
   feito por JS (visualViewport) no mobile.js. */
body.zap-mobile.zap-chatpage,
.zap-mobile.zap-chatpage body { height: 100dvh; }

/* No mobile o "Ir" do teclado já envia o texto, então o botão enviar fica
   escondido. Ele reaparece durante a gravação, quando serve para mandar o
   áudio direto num toque (ver mobile.js). */
.zap-mobile .chat-input-area .send-btn { display: none; }
.zap-mobile .chat-input-area .mic-btn.recording ~ .send-btn { display: flex; }
