/* ============================================================================
   mobile.css — Portal GT Home & ABC
   Lote 1a da versão mobile. Criado em 30/07/2026.

   REGRA QUE GOVERNA ESTE ARQUIVO INTEIRO, e que o mobile_css_guard.mjs verifica
   a cada deploy:

   1. NADA fora de @media, com a única exceção do bloco :root abaixo, que só
      DECLARA custom properties novas (prefixo --mob-, --tap-, --z-, --sheet-,
      --safe-). Nenhum token existente do design-tokens.css ou do tema.css é
      renomeado ou reatribuído: no CLAUDE.md, trocar VALOR propaga sozinho para
      ~30 painéis e RENOMEAR quebra tudo em silêncio.

   2. Toda media query carrega `screen and`. Sem isso, a geração de PDF a partir
      de HTML (motor de apresentação em 423x238mm, comprovante do lote da folha,
      holerite em 612x432pt = 816x576px CSS) cairia abaixo de 920px CSS e
      acionaria as regras de celular no documento impresso.

   3. `pointer:coarse` e `hover:none` NUNCA aparecem sozinhos, sempre em
      conjunção com `screen and (max-width:920px)`. Sozinhos, casam com iPad em
      paisagem (1180px), notebook com tela de toque e telão touch, ou seja
      seriam um caminho aprovado para alterar o desktop em qualquer largura.

   4. Nenhuma regra vale acima de 920px. Acima disso é território intocável.

   Onde este arquivo é carregado: menu_topbar.php, logo depois do
   design-tokens.css, portanto de dentro do <body> e DEPOIS do <head> das
   páginas. Isso resolve empate de especificidade pela ordem da cascata, mas
   ordem só desempata em IGUALDADE de especificidade: por isso os seletores
   abaixo foram calculados um a um pelo invent_campos.mjs, que mediu qual regra
   vence hoje em cada um dos 2.120 campos do portal.
   ============================================================================ */

:root {
  /* Toque */
  --tap-min: 44px;            /* alvo de projeto (Apple HIG / Material) */
  --tap-wcag: 24px;           /* piso legal (WCAG 2.2 SC 2.5.8) */
  --tap-gap: 8px;

  /* Safe area. 0 onde não houver recorte de tela. */
  --safe-t: env(safe-area-inset-top, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-l: env(safe-area-inset-left, 0px);
  --safe-r: env(safe-area-inset-right, 0px);

  /* Métrica do compacto */
  --mob-gutter: 12px;
  --mob-input-fs: 16px;       /* piso que evita o zoom automático do Safari iOS */
  --mob-min-fs: 12px;         /* piso de legibilidade do texto de apoio */
  --mob-anchor-max: min(40%, 160px);
  --mob-chart-min-h: 180px;
  --mob-chart-min-w: 280px;

  /* Camadas: acima do rail (1100) e do backdrop (1090) do menu_topbar */
  --z-actionbar: 1180;
  --z-sheet-backdrop: 1190;
  --z-sheet: 1200;
  --sheet-radius: 16px;
  --sheet-max-h: 85dvh;       /* dvh, nunca vh: a barra do Safari corta o vh */
}

/* ==========================================================================
   1. PISO DE 16px EM CAMPO
   Motivo: o Safari iOS dá ZOOM automático ao focar campo com font-size < 16px,
   e o zoom desloca o layout inteiro. Medido: 2.113 de 2.120 campos do portal
   estavam abaixo de 16px, incluindo os 92 campos de /inadimplencia/painel e o
   campo de senha do login.

   Os seletores abaixo NÃO são decorativos: cada um foi extraído do
   invent_campos.mjs, que usou CDP (CSS.getMatchedStylesForNode) para descobrir
   qual regra vence hoje em cada campo, e calculou a especificidade dela.
   O sufixo [id] ou [class] sobe a especificidade em +1 sem mudar o elemento
   nem exigir edição de HTML: é como ganhar de uma regra de mesma força que
   vem de um arquivo carregado depois.
   ========================================================================== */
@media screen and (max-width: 920px) {

  /* base: pega os 87 campos sem regra específica */
  input, select, textarea { font-size: var(--mob-input-fs); }

  /* mesma especificidade: basta este arquivo vir depois na cascata */
  .unit-actions select,
  .fp-cell input,
  .fp-tipo select,
  .cons-input, .cons-select, .cons-textarea,
  .filter-select, .filter-date, .filter-month,
  .aud-filtros select, .aud-filtros input,
  .evol-zoom-input, .search-box,
  .fl-drop input[type=file], .fl-select,
  .aco-select, .nf-input-sm,
  .imob-search input { font-size: var(--mob-input-fs); }

  /* especificidade +1 pelo atributo, sem tocar no HTML */
  .jf input.cell[class],
  .emp-select[id],
  .cat-sel[class],
  .obs-inp[class],
  input.it[class], select.it[class],
  .filter-input[id],
  .field input[name], .field select[name],
  .fg select[name], .fg input[name],
  .fg input[type=month][name],
  .filter-group input[type=month][name], .filter-group select[name],
  .date-input[class], .ef-input[class], .jtext[class],
  .ctrl[id], .ctrl-select[id], .ctrl-search[id],
  .per-input[id], .rk-busca[id],
  .search-wrap input[id],
  .form-row select[id], .form-row input[id],
  select[id], textarea[id] { font-size: var(--mob-input-fs); }

  /* último recurso, restrito a este seletor e nunca global: 14 campos cuja regra
     vencedora já usa !important na origem. */
  input { font-size: var(--mob-input-fs) !important; }

  /* o piso não pode espremer o campo: cresce por altura, não por fonte */
  input, select, textarea { min-height: var(--tap-min); }
  input[type=checkbox], input[type=radio] { min-height: 0; }
}

/* ==========================================================================
   2. SAFE AREA
   Medido: env(safe-area-inset-*) aparecia em 1 rota de 43, embora TODAS as que
   carregam o menu tenham a barra fixa #gt-slim colada em top:0. Em iPhone com
   recorte, a barra fica por baixo do recorte.
   Cuidado acoplado: o #gt-slim tem 56px e a primeira dobra do plano depende
   disso. Aqui só entra padding do lado seguro, sem alterar a altura declarada.
   ========================================================================== */
@media screen and (max-width: 920px) {
  #gt-slim {
    padding-top: var(--safe-t);
    padding-left: max(18px, var(--safe-l));
    padding-right: max(18px, var(--safe-r));
    height: calc(56px + var(--safe-t));
  }
  #gt-rail { padding-bottom: var(--safe-b); }
}

/* ==========================================================================
   3. PISO TIPOGRÁFICO DO CHROME
   Medido: rótulos de KPI e elementos do menu entre 9,3px e 11,2px. O número
   aparecia grande e o nome dele ilegível.
   Cresce só a fonte do texto de apoio, sem mexer em altura de barra.
   ========================================================================== */
@media screen and (max-width: 920px) {
  .rail-sub-section, .user-caret, .kpi-title, .kpi-label, .filter-label,
  .fl-legend, .fl-badge-mini, .s-bar-title .tag {
    font-size: max(var(--mob-min-fs), 1em);
  }
  #notifBadge { font-size: var(--mob-min-fs); }
}

/* ==========================================================================
   3b. PISO TIPOGRÁFICO QUE REALMENTE GANHA A CASCATA

   POR QUE ESTE BLOCO EXISTE (o de cima não bastava):
   auditado em 03/08/2026 pelo CDP, regra a regra. O bloco 3 acima CASA com
   `.user-caret`, mas a folha da própria página tem `.user-caret{.65rem}` com a
   MESMA especificidade (0,1,0) e vem depois na cascata, então ela ganha. Medido:
   o texto continuava em 9,1px em 42 das 43 rotas, e eu teria jurado que estava
   corrigido. A conta de especificidade é o que decide, não a intenção da regra.

   O `[class]` é o desempate: sobe para (0,2,0) sem encostar no HTML, sem
   `!important` (que atropelaria também os ajustes legítimos das páginas) e sem
   depender de qual folha carrega primeiro.

   POR QUE 12px CRAVADO E NÃO `max(12px, 1em)`:
   `1em` é a fonte do PAI, não a do próprio elemento. Num rótulo de 10px dentro
   de um bloco de 16px, `max(12px,1em)` dá 16px: infla o texto de apoio até o
   tamanho do texto principal e desmancha a hierarquia. Como cada seletor daqui
   foi MEDIDO abaixo de 12px em todas as rotas onde aparece (inventário em
   _inv_tipografia.json), 12px é piso, nunca redução.

   O QUE FICOU DE FORA, de propósito:
   · rótulo de eixo de gráfico (118 nós em <svg>): subir reintroduz colisão de
     rótulo, que já custou uma correção. 10-11px em eixo é praxe de gráfico.
   · célula de tabela (964 nós): o texto é pequeno JUSTAMENTE para a tabela larga
     caber. Mexer aqui é a decisão de tabela que ficou em aberto com a diretoria.
   · /estoque/painel (.unit-*): é a única rota que ainda estoura de lado (3px em
     360px) e lá o texto subiria 25%. Tratada em separado, com medição própria.
   ========================================================================== */
@media screen and (max-width: 920px) {
  /* menu e cabeçalho: aparecem em todas as rotas, então valem por 43 */
  .user-caret[class], .rail-caret[class], .rail-sub-caret[class],
  .rail-sub-section[class], .rail-section-toggle[class],
  /* rótulo e apoio de indicador: o número era grande e o nome dele ilegível */
  .kpi-sub[class], .kpi-lbl[class], .kpi-t-label[class], .kpi-t-sub[class],
  .kpi-meta-item[class], .kpi-label-sub[class],
  /* controles */
  .info-btn[class], .rank-toggle-btn[class],
  /* apoio e legenda */
  .cons-badge[class], .last-update[class],
  .page-footer[class], .fc-rec-sub[class], .mobbar-nota[class],
  .l4-cont[class], .torre-stat[class], .emp-stat-lbl[class],
  .ab-lbl[class], .fl-num[class], .mini-help[class], .sub-text[class],
  .chart-hint[class], .b-item[class], .fck-label[class], .fck-sub[class],
  .forn-rank[class], .forn-pct[class],
  #lastUpdate {
    font-size: var(--mob-min-fs);
  }

  /* Estes dois NÃO cabem no 12px cravado, e a medição é que disse isso.
     `.filter-btn` é declarado .72rem (11,5px) em 4 rotas e .8rem (12,8px) no
     /contratos/admin; `.k-l` é 10,6px numa rota e 12,5px no /lab. Cravar 12px
     ENCOLHERIA o exemplar maior — foi exatamente o que a comparação antes/depois
     pegou (dois elementos caindo de 12,8→12 e 12,5→12). Um piso que reduz alguma
     coisa deixou de ser piso.
     `max()` contra o MAIOR tamanho declarado resolve: sobe quem está abaixo e não
     toca em quem já passa. Sai um pouco acima de 12px, e tudo bem: o objetivo é
     legibilidade, não bater exatamente no número. */
  .filter-btn[class] { font-size: max(var(--mob-min-fs), .8rem); }
  .k-l[class]        { font-size: max(var(--mob-min-fs), .78rem); }

  /* `.section-title` é rótulo miúdo (10,4px) em duas rotas e TÍTULO <h2> de 16px
     em outras duas. A comparação antes/depois flagrou o estrago: /custos/painel e
     /admin_webhooks perderiam o título de 16 para 12px. Mesma classe, dois papéis.
     Excluir os cabeçalhos separa os dois casos sem precisar renomear nada no HTML. */
  .section-title[class]:not(h1):not(h2):not(h3):not(h4):not(h5):not(h6) {
    font-size: var(--mob-min-fs);
  }
}

/* ==========================================================================
   4. AFFORDANCE SEM HOVER
   No toque não existe hover nem tooltip de title. O que hoje só aparece no
   hover precisa ficar permanente.
   pointer/hover SEMPRE em conjunção com a largura, nunca sozinhos.
   ========================================================================== */
@media screen and (max-width: 920px) and (hover: none) {
  .kpi[data-drill]::after, .kpi-tile[data-drill]::after { opacity: .55; }
}

/* ==========================================================================
   5. ALVO DE TOQUE
   WCAG 2.2 SC 2.5.8 exige 24x24 CSS px; 44px é o alvo de projeto.
   Cresce por padding e min-height, NUNCA por font-size, para não empurrar
   layout. Classe utilitária, aplicada onde o Lote 1b marcar.
   ========================================================================== */
@media screen and (max-width: 920px) and (pointer: coarse) {
  .gt-tap {
    min-block-size: var(--tap-min);
    min-inline-size: var(--tap-min);
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
  /* o hambúrguer é o ÚNICO caminho de navegação no celular e media 36x33px:
     o alvo mais crítico da tela era o menor. */
  #railMobileToggle {
    min-width: var(--tap-min);
    min-height: var(--tap-min);
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
}

/* ==========================================================================
   5b. ALVOS PEQUENOS MEDIDOS, tratados por CLASSE DE RISCO
   Lote 1b. A lista saiu do mob_audit (baseline de 30/07/2026): 1.277 alvos abaixo
   dos 24px do WCAG 2.2 nas 43 rotas, e 511 pares a menos de 8px de folga.

   Não existe uma regra só para todos, porque o remédio depende do que o toque faz:

   (a) AÇÃO DESTRUTIVA e botão com rótulo: crescem de forma VISÍVEL. Aumentar área
       invisível de um "Excluir" que já tem 511 pares colados aumentaria a exclusão
       acidental, que é exatamente o oposto do objetivo. O usuário precisa VER onde
       está mirando.
   (b) ÍCONE DE AJUDA e link de voltar: crescem por área INVISÍVEL, com padding
       compensado por margem negativa. O alvo passa de 12 a 18px para 44px sem
       mover um pixel do layout em volta.
   (c) CAIXA DE SELEÇÃO: cresce de verdade. 13px de checkbox não se acerta com o
       dedo, e aqui o erro custa aprovação de folha de pagamento.
   ========================================================================== */
@media screen and (max-width: 920px) and (pointer: coarse) {

  /* (a) visível: destrutivo e botão com rótulo */
  .delete-btn,
  .aud-acao-btn,
  .btn-kpi-toggle,
  .btn-action,
  .kpi-tog {
    min-height: var(--tap-min);
    padding-block: 10px;
  }
  /* o Excluir do jurídico fica dentro de uma linha inteiramente clicável
     (tr onclick=openModal): além de crescer, precisa de folga do que está ao lado,
     senão o dedo escolhe por sorte. */
  .delete-btn { margin-inline: var(--tap-gap); }

  /* Últimos 11 alvos abaixo de 24px do portal, os dois em /custos/fornecedores.
     Não são ícones: são a LEGENDA do histograma (cada item abre o drill-down do
     fornecedor) e os rótulos de período do comparativo. Largos (200 a 344px) e
     baixos: 18 e 19px de altura, contra os 24px do WCAG 2.2 SC 2.5.8.

     24px e não 44px de propósito: a legenda tem 9 itens, e 44px cada somaria quase
     400px de página para uma ação SECUNDÁRIA (o gráfico já está logo acima e é o
     que a pessoa veio ver). 24px cumpre a norma sem empurrar o conteúdo principal
     para fora da tela. Ação primária continua com os 44px do resto do portal.

     O <span> da legenda já nasce com display:flex no atributo style, então
     min-height pega direto; e como min-height não está no style inline, não há
     disputa com ele. */
  #legendHistograma > span { min-height: var(--tap-wcag); }
  .comp-period label { padding-block: 3px; }

  /* (b) invisível: o padding cresce o alvo, a margem negativa devolve o espaço.
     Sem pseudo-elemento de propósito: vários destes já usam ::after para o ícone,
     e sobrescrever quebraria o desenho. */
  /* ⚠️ `.open` e `.back` viraram `a.open` e `a.back` em 05/08/2026, depois de um
     estrago que o dono achou. `.open` é dos nomes de classe mais genéricos que
     existem ("isto está aberto") e NÃO tem lugar numa folha global. Medido nas 43
     rotas, ele acertava:
       · 49 `li.rail-sub-group.open` e 38 `li.rail-item.has-sub.open` (o MENU, em 38 a
         42 rotas), que nem são clicáveis, levando padding e margem negativa à toa;
       · o `#detail-panel.open` do /estoque/painel, que é um modal `position:fixed;
         z-index:5000`. O `position:relative; z-index:0` daqui o tirava do contexto da
         janela e o jogava ATRÁS do backdrop (z-index 4999): tocar numa unidade da
         torre embaçava a tela e não mostrava painel nenhum;
       · e o alvo que eu realmente queria: UM `a.open` ("Abrir →"), em 1 rota.
     Ou seja, o seletor servia a 2 elementos e atrapalhava 87. `a.` na frente resolve
     sem perder o alvo. */
  .info-btn, .kpi-info-btn, .itip, .btn-detalhar, .sec-link,
  .back-link, a.back, a.open, .btn-logout {
    padding: 12px;
    margin: -12px;
    /* o alvo maior não pode capturar toque de quem está por cima */
    position: relative;
    z-index: 0;
  }

  /* (c) caixa de seleção: 13px não se acerta com o dedo.
     24px e não 22: 24 é o piso do WCAG 2.2 SC 2.5.8, e 22 reprovaria por 2px. */
  input[type=checkbox], input[type=radio], .fl-sel {
    inline-size: 24px;
    block-size: 24px;
  }
  /* na folha o nome do funcionário é o que abre o holerite: é a ação principal da
     linha e estava com 16px de altura. */
  .fl-nome { display: inline-flex; align-items: center; min-height: var(--tap-min); }
  /* fechar o painel de detalhe (drill) some no canto com 18px */
  .drill-close { padding: 12px; margin: -12px; position: relative; }
}

/* ==========================================================================
   5b. TABELA ESTREITA QUE ROLAVA DE LADO SEM PRECISAR

   Medido em 03/08/2026, tabela a tabela, nas 6 que ainda rolavam. Nenhuma delas
   rola por ter dado demais: todas têm de 3 a 6 colunas visíveis. Rolavam por dois
   motivos que não têm nada a ver com o conteúdo:

     1. `white-space: nowrap` na coluna de nome. "LINK COMERCIAL IMPOR..." vira uma
        única linha de 260px, e só ela já come 80% de uma tela de 390px.
     2. padding de desktop. 12 ou 13px de cada lado × 6 colunas = até 156px gastos
        em respiro, numa tela que tem 390.

   Deixar o nome quebrar linha e apertar o respiro devolve a largura sem esconder
   NADA. É por isso que este bloco vem antes de qualquer conversa sobre esconder
   coluna: some com o problema mantendo todo o dado na tela.

   As colunas de NÚMERO continuam com nowrap de propósito: "R$ 20.510.346,32"
   partido em duas linhas é pior de ler que a tabela rolando. Por isso a quebra é
   liberada só no cabeçalho e na primeira coluna, que é onde mora o texto longo.
   ========================================================================== */
@media screen and (max-width: 920px) {
  .tbl[class] th, .tbl[class] td,
  .cons-table[class] th, .cons-table[class] td,
  .ranking[class] th, .ranking[class] td,
  #tabelaCentros th, #tabelaCentros td,
  .drill-table[class] th, .drill-table[class] td {
    padding-inline: 6px;
    white-space: normal;
  }
}

/* ==========================================================================
   5c. CONTENÇÃO DE LARGURA (Lote 1b)
   Medido em 30/07/2026: 13 rotas faziam o DOCUMENTO rolar de lado, e com ele a
   barra do topo e a gaveta saíam do lugar. Duas causas, dois remédios.

   (A) Tabela mais larga que a tela sem container rolável. O `/js/mobile.js` marca
       o pai que já existe com `.gt-tblscroll` (marcar classe é aditivo; envolver
       num `<div>` novo mudaria a árvore e o portal tem CSS de filho direto e JS
       que anda por parentElement). Aqui só se dá o comportamento de rolagem.
       Isto NÃO decide a questão em aberto de tabela virar cartão: conter o
       estouro é melhor que a página inteira rolar, seja qual for a decisão.

   (B) Barra e fileira de botões em flex que não quebram linha. `flex-wrap` sozinho
       não basta: filho de flex tem `min-width:auto` e não encolhe abaixo do próprio
       conteúdo, então é preciso os dois.
   ========================================================================== */
@media screen and (max-width: 920px) {

  /* (A) */
  .gt-tblscroll {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    max-width: 100%;
  }
  /* a tabela dentro do container rolável não pode ser espremida: ela mantém a
     largura natural e quem rola é o container */
  .gt-tblscroll > table { max-width: none; }

  /* (B) contenção das barras que empurravam o documento */
  .modo-bar,                    /* /contratos/dashboard: 618px numa tela de 390 */
  .period-presets,              /* /suprimentos/suprimentos */
  .tab-btn-row, .tabs, .aba-row, .tab-bar,   /* .tab-bar: 6px de estouro em /fluxo_caixa/ */
  .filter-row, .filters {
    flex-wrap: wrap;
    min-width: 0;
  }
  .modo-bar > *, .period-presets > *, .filter-row > *, .filters > * { min-width: 0; }

  /* o carimbo "ao vivo" do /suprimentos/aco tem 213px de texto numa barra de 390 */
  .aco-live { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

  /* filho de flex do #gt-slim precisa poder encolher, senão a barra estica o
     documento e o resto da página passa a rolar junto.
     EXCEÇÃO: o hambúrguer. Medido em 31/07/2026, esta regra (especificidade 1,0,1)
     vencia a `#railMobileToggle{min-width:44px}` (1,0,0) do bloco de alvos, no MESMO
     arquivo, e deixava o botão com 35,4px de largura. Ou seja, o remédio do estouro
     cancelava o remédio do alvo. E o hambúrguer é o ÚNICO caminho de navegação no
     celular: é o alvo mais crítico da tela. */
  #gt-slim > *:not(#railMobileToggle) { min-width: 0; }
  #gt-slim > #railMobileToggle { min-width: var(--tap-min); flex: 0 0 auto; }
  #gt-slim .slim-spacer { overflow: hidden; }

  /* (B2) os culpados que sobraram depois da primeira rodada, medidos em 31/07/2026.
     Aparecem em mais de uma rota porque são padrões compartilhados, então uma
     regra resolve várias páginas. */

  /* barra de ação da página: 672px em /custos/cpn_orc, 337px em /suprimentos.
     flex-wrap sozinho não resolve: filho de flex tem min-width:auto e não encolhe
     abaixo do conteúdo. Os dois juntos, sempre. */
  .topbar, .topbar-right, .topbar-left {
    flex-wrap: wrap;
    min-width: 0;
    max-width: 100%;
  }
  .topbar > *, .topbar-right > *, .topbar-left > * { min-width: 0; }

  /* /fechamento_trimestral: div.head > div.l e div.r sao filhos de flex com
     min-width:auto e min-content de 350px (o .badge tem white-space:nowrap), numa
     caixa de 262px. Faltavam 88px. */
  .head { flex-wrap: wrap; }
  .head > .l, .head > .r { min-width: 0; max-width: 100%; }
  /* .tag e .badge: os dois sao selos de texto com white-space:nowrap, e o .tag
     media 350px numa caixa de 262px. Quebrar linha e o unico jeito de caberem
     sem cortar informacao. */
  .head .badge, .head .tag, .head .r > *, .head .l > * { white-space: normal; max-width: 100%; }

  /* campo de formulário com largura fixa: 659px numa tela de 390 (/fechamento/justificativas) */
  .field, .subgrid > .field, .mini-help { max-width: 100%; min-width: 0; }
  .field > label, .field > .mini-help { max-width: 100%; }

  /* grupo de filtro com select de min-width:170px (/contratos/comissoes: 447px) */
  .fg, .filter-bar, .filter-group { flex-wrap: wrap; min-width: 0; max-width: 100%; }
  .fg > *, .filter-bar > *, .filter-group > * { min-width: 0; max-width: 100%; }
  .fg select, .fg input, .filter-group select, .filter-group input { min-width: 0; max-width: 100%; }

  /* balão de ajuda renderizado EM FLUXO: 312px empurrando o documento
     (/fechamento_trimestral). Sai do fluxo e passa a caber na tela. */
  .itip { position: relative; }
  .itip > .pop, .pop {
    max-width: min(280px, calc(100vw - 2 * var(--mob-gutter)));
    inline-size: max-content;
  }
  /* `left: auto` é obrigatório: a página ancora o balão em `left:-6px`, e sem zerar
     isso o `right` não tem efeito (com width definida, o `left` manda). Era por isso
     que só limitar a largura não tirava o estouro. */
  .itip .pop { left: auto; right: 0; }

  /* item de grid e de flex tem min-width:auto e NÃO encolhe abaixo do conteúdo,
     mesmo quando a grade já está em 1 coluna. Era o caso do .card de 591px em
     /custos/cpn_orc, cuja grade de 2 colunas já virava 1 em 520px e mesmo assim
     empurrava o documento. */
  .grid-2 > *, .grid-3 > *, .kpi-strip > *, .card { min-width: 0; max-width: 100%; }

  /* select com opção longa estica sozinho: 429px soltos dentro de um <form>
     em /admin_webhooks.
     `max-width:100%` sozinho NAO resolve: 100% resolve contra o PAI, e se o pai
     tambem esticou (form em linha de flex), 100% continua sendo 429px. Por isso o
     pai tambem precisa poder encolher. */
  select, .ef-input { max-width: 100%; }
  form, .toolbar, .section-header { min-width: 0; max-width: 100%; }
  .toolbar > *, .section-header > *, form > * { min-width: 0; max-width: 100%; }

  /* ── mapa de torres do /estoque/painel ──────────────────────────────────
     `.towers-row` tem `min-width: max-content` cravado e 2.085px: era o maior
     estouro do portal (1.709px), e fazia a PAGINA INTEIRA rolar de lado, levando
     junto a barra do topo e a gaveta.
     Aqui a rolagem passa a acontecer DENTRO da fileira, com encaixe por torre:
     cada arrasto para uma torre inteira em vez de parar no meio de um apartamento.
     A versao com acordeao por torre (uma torre por vez, sem arrasto) e a proposta
     de fundo, e fica para a analise conjunta junto com a decisao de tabela. */
  .towers-row {
    min-width: 0;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scroll-padding-inline: var(--mob-gutter);
  }
  .towers-row > .tower-card { scroll-snap-align: start; flex: 0 0 auto; }

  /* toast fixo fora da tela some do lado direito e estica o documento */
  .toast { max-width: calc(100vw - 2 * var(--mob-gutter)); right: var(--mob-gutter); }
}

/* ==========================================================================
   5d. RESPIRO DO CARTAO NO APARELHO PEQUENO (Lote 7)
   Em 360px de largura, o gráfico do /conselho/painel_fluxo renderiza com 274px,
   6px abaixo do piso de 280 em que a leitura ainda funciona. A culpa não é do
   gráfico: são 86px somados de padding de container numa tela de 360.
   Só abaixo de 400px, para não mexer no respiro do celular comum.
   ========================================================================== */
@media screen and (max-width: 400px) {
  .card, .panel, .box, .chart-card, .cons-card, .aco-chart-card, .chart-box {
    padding-left: 10px;
    padding-right: 10px;
  }
}

/* ==========================================================================
   6. ESQUELETOS que os Lotes 4 e 6 vão consumir
   Nascem aqui, sem consumidor ainda, para que aqueles lotes não dependam de
   lote posterior. São CSS puro dentro de media query: inertes até alguém pôr
   a classe no HTML.
   ========================================================================== */
@media screen and (max-width: 600px) {

  /* barra de ação fixa no rodapé: resolve "conferir e agir em pontos opostos" */
  .gt-actionbar {
    position: sticky;
    bottom: 0;
    z-index: var(--z-actionbar);
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px var(--mob-gutter) calc(10px + var(--safe-b));
    background: var(--bg-card, #121212);
    border-top: 1px solid var(--border, rgba(255,255,255,.10));
  }
  .gt-actionbar .gt-actionbar-resumo { flex: 1; min-width: 0; font-size: 13px; line-height: 1.25; }
  .gt-actionbar button { min-height: var(--tap-min); }

  /* tabela vira cartão empilhado.
     O rótulo da coluna vem por ::before lendo --col, definido por :nth-child no
     CSS, sem custo de HTML. Os roles são REPOSTOS de propósito: o Safari
     descarta a semântica nativa da tabela em qualquer mudança de display, e o
     Safari é o aparelho da diretoria. */
  .gt-cardlist thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .gt-cardlist tr {
    display: block;
    margin: 0 0 10px;
    padding: 12px;
    border: 1px solid var(--border, rgba(255,255,255,.10));
    border-radius: var(--radius, 12px);
    background: var(--bg-card, #121212);
  }
  .gt-cardlist td {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    padding: 4px 0;
    border: 0;
    text-align: right;
  }
  .gt-cardlist td::before {
    content: attr(data-label);
    flex: 0 0 auto;
    text-align: left;
    color: var(--text-muted, #979796);
    font-weight: 600;
  }
}

/* ==========================================================================
   6b. GAVETA DE NAVEGAÇÃO (Lote 1b)
   Medido em 31/07/2026: dos 4 comportamentos que o aceite pede, NENHUM existia.
   Com a gaveta aberta o fundo rolava 600px, Escape não fechava, não havia botão de
   fechar, e os 13 itens do menu tinham 36px de altura com 2px de folga entre si.
   Alvo de 36px com 2px de vizinho é onde o dedo escolhe por sorte.
   ========================================================================== */
@media screen and (max-width: 920px) {
  /* O fundo não rola enquanto a gaveta está aberta. Sem isto o usuário rola a
     página por baixo do menu e perde o lugar onde estava.
     PRECISA DO `html` TAMBÉM: travar só o body não resolve, porque em várias
     páginas quem rola é o elemento raiz. Medido no /home, que tem
     `@media (max-width:900px){ html, body { overflow:auto } }`: com o body em
     hidden o documento ainda rolou 600px. */
  html.gt-gaveta-aberta, body.rail-open { overflow: hidden; }
  /* `html.gt-gaveta-aberta` e posta pelo /js/mobile.js espelhando a body.rail-open.
     Tentei antes com `html:has(body.rail-open)` e NAO funcionou na medicao (o
     documento continuou rolando 600px), entao a classe explicita substitui: nao
     depende de suporte a :has() nem de como cada navegador resolve o seletor no
     elemento raiz. */

  /* itens do menu: 44px de altura e 8px de folga, que é o que o lote pede */
  #gt-rail .rail-link { min-height: var(--tap-min); }
  #gt-rail .nav > li + li { margin-top: var(--tap-gap); }
  #gt-rail .rail-sub li + li { margin-top: 4px; }
  #gt-rail .rail-sub a { min-height: var(--tap-min); display: flex; align-items: center; }

  /* botão de fechar: o .rail-collapse-btn já existe no HTML e estava escondido no
     mobile (não há colapso em celular). Aqui ele é reaproveitado como "fechar",
     em vez de injetar elemento novo na árvore. */
  #gt-rail .rail-collapse-btn {
    display: inline-flex !important;
    align-items: center; justify-content: center;
    min-width: var(--tap-min); min-height: var(--tap-min);
    font-size: 20px; line-height: 1;
  }
}

/* ==========================================================================
   7. PRIMEIRA DOBRA (Lote 5)
   Medido em 31/07/2026 nas 6 rotas executivas, em 390x844 (788px úteis abaixo da
   barra fixa): em /fluxo_caixa/, /custos/painel e /vgv o PRIMEIRO conteúdo da tela
   é o link "← Portal", e o primeiro KPI só começa entre y=193 e y=633. Ou seja, o
   topo da tela é gasto com moldura antes de qualquer número.

   O remédio não é mexer nos KPIs: é encolher a moldura. Nada some (o link continua
   lá e continua com 44px de alvo), só muda de tamanho e de peso visual.
   ========================================================================== */
@media screen and (max-width: 920px) {

  /* título da página: no celular ele competia em tamanho com o número herói */
  .page-head h1, .fl-head h1, .topbar h1, main > header h1, .cons-head h1 {
    font-size: clamp(1.25rem, 5.2vw, 1.6rem);
    line-height: 1.15;
    margin: 0 0 2px;
  }
  /* subtítulo explicativo: some da PRIMEIRA dobra, não da página. Continua legível
     logo abaixo, mas deixa de empurrar o dado para fora da tela. */
  .fl-sub, .page-sub, .subtitulo, .topbar .sub { font-size: .86rem; line-height: 1.3; margin: 0 0 6px; }

  /* o "← Portal" vira âncora compacta no canto, não uma linha inteira.
     Mantém os 44px de alvo por padding (o alvo cresce, a caixa visual não). */
  .back-link, .back, .voltar-portal {
    display: inline-flex; align-items: center;
    font-size: .82rem;
    padding: 12px;
    margin: -12px 0 -12px -12px;
  }

  /* respiro entre o topo e o primeiro cartão */
  main, .fl-wrap, .wrap, .container { padding-top: 8px; }
  .page-head, .fl-head, main > header { margin-bottom: 8px; gap: 4px; }

  /* ── /home: a faixa de KPI deixa de ser rolador horizontal ──────────────
     Medido em 390x844: os 5 KPIs vivem numa `.kpi-strip` com `overflow-x:auto` e
     `scrollbar-width:none`, somando 1.178px numa tela de 390. Ou seja, o usuário vê
     2 e NÃO TEM COMO SABER que existem mais três: a barra de rolagem está escondida
     de propósito. Rolador horizontal sem pista é o pior padrão da página.
     Vira grade de 2 colunas, com o primeiro cartão em largura cheia (o herói). */
  .kpi-strip {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px;
    overflow-x: visible;
    overflow-y: visible;
  }
  .kpi-strip > .kpi-tile { min-width: 0; }
  .kpi-strip > .kpi-tile:first-child { grid-column: 1 / -1; }
  /* O herói ganha corpo de número: 24px é o piso em que um valor lidera a tela.
     A classe é `.kpi-t-value` (medida no HTML servido, não adivinhada: a primeira
     tentativa mirou `.kpi-value`/`.kpi-val`, que não existem nesta página, e o
     número continuou em 18px). */
  .kpi-strip > .kpi-tile:first-child .kpi-t-value { font-size: clamp(24px, 7vw, 30px); }

  /* ⚠️ CONSERTO de um estrago que a regra acima causou (relatado pelo dono em
     05/08/2026, reproduzido e medido no mesmo dia).
     A regra `.kpi-strip` acima é GLOBAL, e eu a escrevi olhando só para a /home.
     O /estoque/painel usa a mesma classe, mas lá a faixa mora dentro de um
     `#kpi-strip-wrap` que tem `max-height:120px; overflow:hidden`. Esse teto não é
     descuido: ele existe para a animação do botão "Ocultar resumo", que transiciona
     de 120px para 0.
     No desktop os cartões ficam numa linha só e cabem nos 120px. Virando grade, eles
     passam a ocupar 792px numa tela de 390, e o teto escondia TUDO menos o primeiro
     cartão, sem deixar rolar em nenhuma direção: o painel ficava inutilizável, e o
     único jeito de mexer nele era "Ocultar resumo", que sumia com o que restava.
     Medido: caixa 390x120 para um conteúdo de 390x792.

     `:not(.kpi-collapsed)` de propósito: sobe para (1,1,0) e vence o `max-height:120px`
     da página por ESPECIFICIDADE, sem depender de qual folha carrega primeiro, e não
     briga com `#kpi-strip-wrap.kpi-collapsed{max-height:0}`, porque os dois seletores
     nunca casam ao mesmo tempo. 200vh em vez de `none` para a transição do botão
     continuar animando. */
  #kpi-strip-wrap:not(.kpi-collapsed) { max-height: 200vh; }

  /* ── /vgv: o herói é `.card.hero .valor`, e renderizava a 22,4px ─────────── */
  .kpi-wrapper .card.hero .val { font-size: clamp(24px, 7vw, 30px); }

  /* Barra de filtros recolhida. O botão é criado pelo /js/mobile.js e mostra quantos
     filtros estão aplicados: sem isso, alguém lê número filtrado achando que é total. */
  .gt-filtro-tog {
    display: flex; align-items: center; justify-content: space-between;
    width: 100%; min-height: 44px;
    margin: 0 0 8px;
    padding: 10px 12px;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--bg-card);
    color: var(--text-primary);
    font: inherit; font-size: .9rem; font-weight: 600;
    cursor: pointer;
  }
  .gt-filtro-tog::after { content: "▾"; color: var(--brand); transition: transform .15s; }
  .gt-filtro-tog.aberto::after { transform: rotate(180deg); }
  .gt-filtro-recolhido { display: none !important; }
}
