/* PreservaCred — componentes (fonte: docs/ux-ui/01 §2 · redesign 2026-07) */

/* ============================== Header público — vidro */
.glass {
  background: rgba(255, 255, 255, .8);
  -webkit-backdrop-filter: blur(16px) saturate(1.6);
  backdrop-filter: blur(16px) saturate(1.6);
}
.site-header {
  position: sticky; top: 0; z-index: var(--z-sticky);
  background: rgba(255, 255, 255, .8);
  -webkit-backdrop-filter: blur(16px) saturate(1.6);
  backdrop-filter: blur(16px) saturate(1.6);
  border-bottom: 1px solid rgba(16, 27, 29, .06);
  transition: box-shadow var(--t-base), background-color var(--t-base);
}
.site-header.is-scrolled {
  background: rgba(255, 255, 255, .88);
  box-shadow: 0 1px 0 rgba(16, 27, 29, .05), 0 8px 24px rgba(11, 43, 48, .06);
}
.site-header .inner { display: flex; align-items: center; height: 68px; gap: var(--sp-6); }
.brand { font-size: 1.3rem; font-weight: 700; color: var(--pc-petrol-900); letter-spacing: -0.02em; white-space: nowrap; }
.brand .brand-light { font-weight: 400; }
.brand:hover { text-decoration: none; }

/* min-width:0 é REGRA DA BARRA, não ajuste de uma faixa. Um contêiner flex com
   min-width:auto não encolhe abaixo do próprio min-content — e o min-content
   deste nav são 832,6px medidos. O valor vivia só dentro de
   @media (min-width:1025px) and (max-width:1400px); acima de 1400 ele voltava a
   `auto` e .header-actions transbordava (rolagem horizontal medida em
   1401–1436px; e a partir de 1437 o bloco Entrar · Ver planos terminava 135,1px
   à DIREITA da grade de 1200px em 1920). */
.site-nav { display: flex; gap: var(--sp-1); flex: 1; min-width: 0; }
.site-nav > .nav-item { position: relative; }
.site-nav a.nav-link, .site-nav button.nav-link {
  display: inline-flex; align-items: center; gap: 5px;
  padding: var(--sp-2) var(--sp-3); border: 0; background: none;
  border-radius: var(--r-md); color: var(--pc-ink-700); font-size: var(--fs-body);
  font-weight: 500; cursor: pointer;
  transition: background-color var(--t-fast), color var(--t-fast);
}
.site-nav a.nav-link:hover, .site-nav button.nav-link:hover {
  background: var(--pc-petrol-50); color: var(--pc-petrol-900); text-decoration: none;
}
.nav-link .caret {
  width: 9px; height: 9px; flex: none;
  border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg) translateY(-2px);
  transition: transform var(--t-fast); opacity: .55;
}
.nav-item:hover .caret, .nav-item:focus-within .caret { transform: rotate(225deg) translateY(-1px); }

.nav-dropdown {
  position: absolute; top: calc(100% + 6px); left: 0; min-width: 360px; padding: var(--sp-2);
  background: var(--pc-bg-0); border: var(--hairline);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-4);
  z-index: var(--z-dropdown);
}
/* Só os itens DIRETOS do dropdown são blocos; os links inline do .dd-foot
   (API, glossário, análises) permanecem no fluxo do texto — nada de rodapé
   quebrado em fragmentos */
.nav-dropdown > a {
  display: block; padding: var(--sp-3); border-radius: var(--r-md);
  transition: background-color var(--t-fast);
}
.nav-dropdown > a:hover { background: var(--pc-petrol-50); text-decoration: none; }
.nav-dropdown .dd-title { font-weight: 600; color: var(--pc-ink-900); display: block; }
.nav-dropdown > a:hover .dd-title { color: var(--pc-petrol-700); }
.nav-dropdown .dd-desc { font-size: var(--fs-sm); color: var(--pc-ink-500); display: block; margin-top: 1px; }
.nav-dropdown .dd-foot {
  margin-top: var(--sp-2); padding: var(--sp-3);
  border-top: var(--hairline); font-size: var(--fs-sm);
}
.nav-dropdown .dd-foot a { display: inline; }
.nav-dropdown .dd-foot .link-arrow { display: inline-flex; }

/* ===== INSOLVE no header (identidade do caderno: serif + ponto terracota) ===== */
.nav-link--insolve { gap: 8px; }
.ins-word {
  font-family: 'Schibsted Grotesk', var(--font-sans);
  font-weight: 800; font-size: 1.14rem; line-height: 1; letter-spacing: -0.025em;
  color: var(--pc-ink-900);
}
.ins-word b { color: #B23A22; font-weight: 700; }
.ins-tag {
  font-size: 0.72rem; font-weight: 300; letter-spacing: 0.02em;
  color: var(--pc-ink-500); align-self: center;
}
.nav-link--insolve:hover { background: rgba(178, 58, 34, 0.06); }
.nav-link--insolve:hover .ins-word { color: var(--pc-ink-900); }
.nav-link--insolve:hover .ins-word b { color: #8F2C18; }
.nav-item--insolve .caret { opacity: 0.4; }
/* Insolve fica DEPOIS das abas (Serviços/Planos/Dados/Conteúdo) e antes da busca,
   entre divisores: | Insolve | (order entre as abas [0] e a busca [99]).
   Desde a reordenação do menu o próprio HTML já entrega o Insolve nessa posição —
   este `order` deixou de ser conserto e virou TRAVA: uma aba nova acrescentada
   depois dele no header.php continua caindo antes do caderno. */
.nav-item--insolve { order: 50; }
/* o item Insolve assenta ~3px acima do centro dos demais (métrica do serif + line-box);
   nudge no LINK inteiro p/ centralizar com Serviços/Dados/Planos e o botão Contratar. */
.nav-link--insolve { transform: translateY(3px); }
@media (min-width: 1025px) {
  .nav-item--insolve { margin: 0 6px; padding: 0 15px; border-left: 1px solid rgba(0, 0, 0, 0.09); border-right: 1px solid rgba(0, 0, 0, 0.09); }
}
/* mega-menu do Insolve: acento terracota no topo + cabeçalho com wordmark e copy */
.nav-dropdown--insolve { min-width: 384px; border-top: 3px solid #B23A22; }
.ins-dd-head {
  padding: var(--sp-3) var(--sp-3) var(--sp-3);
  border-bottom: var(--hairline); margin-bottom: var(--sp-2);
}
.ins-dd-eyebrow {
  display: block; font-size: 0.66rem; font-weight: 700; letter-spacing: 0.1em;
  text-transform: uppercase; color: #B23A22; margin-bottom: 7px;
}
.ins-dd-word {
  font-family: 'Schibsted Grotesk', var(--font-sans);
  font-weight: 800; font-size: 1.7rem; line-height: 1; letter-spacing: -0.025em;
  color: var(--pc-ink-900); display: block;
}
.ins-dd-word b { color: #B23A22; }
.ins-dd-desc { font-size: var(--fs-sm); line-height: 1.5; color: var(--pc-ink-500); margin: 9px 0 0; }
.header-actions { display: flex; gap: var(--sp-3); align-items: center; }

/* ============================== Explorador de CNPJ — busca no header
   Campo discreto no desktop (expande ao focar), full-width no drawer mobile.
   Degrada sem JS: o form submete a /dados/empresas?q= normalmente. */
.hdr-search { position: relative; flex: none; margin-left: auto; order: 99; }
/* Com foco, a busca fica POR CIMA do bloco Entrar · Ver planos. Ao focar, o
   campo cresce para a direita (244→320px; 180→260 no desktop) sobre o
   .hdr-cta-stack, que também é position:relative com z auto — e com os dois em
   z auto vale a ordem do DOM: o bloco, que vem DEPOIS, pintava por cima, e
   "Entrar" vazava pelo fundo branco do campo expandido. Só no foco, de
   propósito: na faixa 1025–~1150px (Windows) o campo já invade o botão SEM
   foco, e um z-index permanente roubaria o clique do "Entrar" ali. Os
   mega-menus (.nav-dropdown, --z-dropdown) seguem acima; as sugestões passam a
   empilhar dentro do próprio .hdr-search e o sticky do header (--z-sticky)
   continua contendo tudo sobre a página. Par desta regra: o :has() abaixo do
   :focus-within do campo, que some com o rótulo "Entrar". */
.hdr-search:focus-within { z-index: 1; }
.site-nav .hdr-search { margin-right: var(--sp-1); }
.hdr-search-field {
  display: flex; align-items: center; gap: 6px;
  width: 244px; max-width: 100%;
  padding: 7px var(--sp-3); border-radius: var(--r-full);
  background: rgba(16, 27, 29, .04);
  border: 1px solid transparent;
  transition: width var(--t-base), background-color var(--t-fast),
              border-color var(--t-fast), box-shadow var(--t-fast);
}
.hdr-search-field:focus-within {
  width: 320px;
  background: var(--pc-bg-0);
  border-color: var(--pc-petrol-300);
  /* Este halo é o ÚNICO indicador de foco do campo (o input abaixo desliga o
     anel próprio, de propósito). A 15% de opacidade ele media 1,2:1 sobre
     branco — decoração, não indicador. Sólido, é o mesmo anel do resto do site
     (6,34:1) e passa a SC 1.4.11. */
  box-shadow: var(--ring-focus), var(--shadow-2);
}
/* Enquanto a busca está aberta, "Entrar" SOME. Na grade de 1200px o campo
   expandido sempre invade o botão — 37px medidos no Windows e quase o botão
   inteiro no Mac, cuja fonte do sistema é mais larga e come a folga do nav. O
   z-index do foco põe o campo por cima, mas sozinho deixaria o resto do rótulo
   ("…trar") à mostra quando a invasão é parcial. visibility (não display) para
   o "Ver planos e preços" não pular de lugar. O seletor é o MESMO que abre o
   campo (:focus-within no .hdr-search-field), para os dois estados andarem
   juntos. Sem :has() degrada para só o z-index do foco.
   Tempos: some NA HORA (transition-delay:0) e só VOLTA depois que o campo
   recuou — `visibility 0s var(--t-base)` expande para "0s 260ms <easing>", ou
   seja, duração zero e atraso igual ao do width, sem repetir o número aqui. O
   resto da lista é a do .btn, repetida para o hover do botão não ficar seco. */
.site-header .header-actions .btn-ghost {
  transition: background-color var(--t-fast), border-color var(--t-fast),
              color var(--t-fast), transform var(--t-fast), box-shadow var(--t-fast),
              visibility 0s var(--t-base);
}
.site-header:has(.hdr-search-field:focus-within) .header-actions .btn-ghost {
  visibility: hidden; transition-delay: 0s;
}
.hdr-search-icon { display: inline-flex; color: var(--pc-ink-500); flex: none; }
.hdr-search-field:focus-within .hdr-search-icon { color: var(--pc-petrol-600); }
.hdr-search-input {
  flex: 1; min-width: 0; border: 0; background: none; outline: none;
  font-size: var(--fs-body); color: var(--pc-ink-900);
  font-family: inherit; padding: 0 2px 0 var(--sp-1);
}
/* UM anel de foco, não dois. Quem indica foco aqui é o CAMPO INTEIRO
   (.hdr-search-field:focus-within, borda petróleo + halo): o :focus-visible
   global de base.css desenhava um SEGUNDO anel, de raio 4px, colado ao texto
   DENTRO do primeiro — e era nele que a primeira letra digitada encostava. */
.hdr-search-input:focus-visible { box-shadow: none; outline: none; }
.hdr-search-input::placeholder { color: var(--pc-ink-500); }
/* remove a cruzinha nativa do type=search (usamos nosso próprio fluxo) */
.hdr-search-input::-webkit-search-decoration,
.hdr-search-input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }

/* spinner de carregamento (só visível durante o fetch) */
.hdr-search-spin {
  width: 14px; height: 14px; flex: none; display: none;
  border: 2px solid rgba(16, 27, 29, .15);
  border-top-color: var(--pc-petrol-600);
  border-radius: 50%;
  animation: hdr-spin .7s linear infinite;
}
.hdr-search.is-loading .hdr-search-spin { display: inline-block; }
@keyframes hdr-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .hdr-search-spin { animation-duration: 1.4s; } }

/* dropdown de sugestões */
.hdr-search-suggest {
  position: absolute; top: calc(100% + 8px); right: 0;
  width: 380px; max-width: min(88vw, 420px);
  max-height: min(64vh, 440px); overflow-y: auto; overscroll-behavior: contain;
  padding: var(--sp-1);
  background: var(--pc-bg-0); border: var(--hairline);
  border-radius: var(--r-lg); box-shadow: var(--shadow-4);
  z-index: var(--z-dropdown);
}
.hdr-search-suggest[hidden] { display: none; }
.hdr-suggest-item {
  display: block; padding: var(--sp-2) var(--sp-3); border-radius: var(--r-md);
  cursor: pointer; text-decoration: none;
  transition: background-color var(--t-fast);
}
.hdr-suggest-item:hover, .hdr-suggest-item.is-active {
  background: var(--pc-petrol-50); text-decoration: none;
}
.hdr-suggest-item:focus-visible {
  outline: 2px solid var(--pc-petrol-500); outline-offset: -2px;
}
.hdr-suggest-name {
  display: block; font-weight: 600; color: var(--pc-ink-900);
  font-size: var(--fs-body); line-height: 1.3;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.hdr-suggest-item:hover .hdr-suggest-name,
.hdr-suggest-item.is-active .hdr-suggest-name { color: var(--pc-petrol-700); }
.hdr-suggest-meta {
  display: block; margin-top: 2px; font-size: var(--fs-sm); color: var(--pc-ink-500);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.hdr-suggest-meta .mono { color: var(--pc-ink-700); }
.hdr-suggest-msg {
  padding: var(--sp-3); font-size: var(--fs-sm); color: var(--pc-ink-500);
}
.hdr-suggest-all {
  display: flex; align-items: center; justify-content: space-between;
  margin-top: var(--sp-1); padding: var(--sp-3);
  border-top: var(--hairline); font-size: var(--fs-sm); font-weight: 600;
  color: var(--pc-petrol-700); border-radius: 0 0 var(--r-md) var(--r-md);
}
.hdr-suggest-all:hover { background: var(--pc-petrol-50); text-decoration: none; }

/* ESQUELETO enquanto a lista carrega (app.js → hdrSkeleton). Vale para as
   QUATRO superfícies da busca — header, herói da home, fechamento da home e as
   LPs/hub — porque todas compartilham .hdr-search-suggest. A consulta cruza uma
   base de 68 milhões de linhas e demora ~2s; sem isto o campo fica mudo entre a
   tecla e o resultado, que é exatamente o que se lê como "travou".
   As barras imitam a forma do item real (nome forte + meta menor), então a
   lista não "pula" quando os dados chegam. */
.hdr-suggest-skel { padding: var(--sp-2) var(--sp-3); display: grid; gap: 6px; }
.hdr-skel-bar {
  display: block; height: 10px; border-radius: var(--r-full);
  background: linear-gradient(90deg,
    var(--pc-line-100) 0%, var(--pc-petrol-50) 18%, var(--pc-line-200) 34%,
    var(--pc-petrol-50) 50%, var(--pc-line-100) 66%);
  background-size: 300% 100%;
  animation: hdr-skel-sweep 1.25s linear infinite;
}
.hdr-skel-bar--name { height: 12px; width: 66%; }
.hdr-skel-bar--meta { width: 42%; }
/* defasagem entre as linhas: a varredura desce, não pisca em bloco */
.hdr-suggest-skel + .hdr-suggest-skel .hdr-skel-bar { animation-delay: .14s; }
.hdr-suggest-skel + .hdr-suggest-skel + .hdr-suggest-skel .hdr-skel-bar { animation-delay: .28s; }
@keyframes hdr-skel-sweep { from { background-position: 150% 0; } to { background-position: -150% 0; } }
/* Mesma escolha do .hdr-search-spin acima: em prefers-reduced-motion o
   movimento DESACELERA (o usuário continua sabendo que está carregando) em vez
   de sumir — é uma varredura de 10px, não um deslocamento de tela. */
@media (prefers-reduced-motion: reduce) {
  .hdr-skel-bar { animation-duration: 2.6s; }
  .hdr-suggest-skel + .hdr-suggest-skel .hdr-skel-bar,
  .hdr-suggest-skel + .hdr-suggest-skel + .hdr-suggest-skel .hdr-skel-bar { animation-delay: 0s; }
}

/* Botão hambúrguer → X animado */
.nav-toggle { display: none; }
@media (max-width: 1024px) {
  .site-nav { display: none; }
  /* FLEX-COLUNA, não block: o drawer repete a MESMA ordem visual do desktop.
     Com display:block o `order` dos itens é inerte (só vale para filho de
     flex/grid) e o drawer cairia na ordem crua do DOM. O HTML já sai na ordem
     certa das abas, mas é o flex-coluna que mantém o drawer PRESO ao desktop:
     a busca continua em 1º por decisão explícita (order:0 em .hdr-search,
     abaixo), o Insolve fecha as abas (order:50) e o convite de conta gratuita
     vem por último (order:60) — uma ordem só, não uma por largura.
     gap:0 anula o gap herdado de .site-nav — o espaçamento vertical do drawer
     é o margin-bottom de .nav-item, e somar os dois abriria o menu. */
  .site-nav.is-open {
    display: flex; flex-direction: column; gap: 0;
    position: absolute; top: 68px; left: 0; right: 0;
    background: #FFFFFF;
    -webkit-backdrop-filter: blur(20px) saturate(1.6);
    backdrop-filter: blur(20px) saturate(1.6);
    border-bottom: var(--hairline);
    padding: var(--sp-4) var(--sp-6) var(--sp-8);
    box-shadow: var(--shadow-4);
    max-height: calc(100vh - 68px); overflow-y: auto;
    animation: pc-drop-in 240ms var(--ease-out) both;
    transform-origin: top center;
  }
  .site-nav.is-open .nav-item { margin-bottom: var(--sp-1); }
  .site-nav.is-open .nav-link { width: 100%; justify-content: space-between; font-size: var(--fs-h4); padding: var(--sp-3) var(--sp-2); }
  .site-nav.is-open .nav-dropdown,
  .js .site-nav.is-open .nav-dropdown {
    position: static; opacity: 1; visibility: visible; box-shadow: none; border: 0;
    transform: none; min-width: 0; padding: 0 0 var(--sp-2) var(--sp-2); transition: none;
  }
  .site-nav.is-open .caret { display: none; }

  /* Busca: full-width no topo do drawer, sempre expandida */
  .hdr-search { margin: 0 0 var(--sp-4); width: 100%; order: 0; }
  .site-nav .hdr-search { margin-right: 0; }
  .hdr-search-field { width: 100%; background: var(--pc-bg-50); border-color: var(--pc-line-200); }
  .hdr-search-field:focus-within { width: 100%; }
  .hdr-search-suggest { position: static; width: 100%; max-width: 100%; box-shadow: none;
    margin-top: var(--sp-2); max-height: 50vh; }

  .nav-toggle {
    display: inline-flex; flex-direction: column; justify-content: center; gap: 5px;
    width: 40px; height: 40px; align-items: center;
    background: none; border: 0; border-radius: var(--r-md);
    cursor: pointer; margin-left: auto;
  }
  .nav-toggle span {
    width: 20px; height: 2px; border-radius: 2px; background: var(--pc-ink-700);
    transition: transform var(--t-base), opacity var(--t-base);
  }
  .nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
  .nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
  .nav-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }
  .site-header .inner { gap: var(--sp-3); }
  .header-actions .btn-ghost { display: none; }
}

/* ============================== HEADER: a barra CABE no celular
   Medido antes: os três filhos irredutíveis somavam 372,4px (marca 125,6 em
   nowrap + toggle 40 + 24 de gaps + o CTA de 182,8) num content-box de 327px a
   375px. O .nav-toggle era o único a ceder — encolhia de 40 para 32 — e sobrava
   um scrollWidth CONSTANTE de 388,4px em toda largura mobile. O sintoma não era
   barra de rolagem: com width=device-width o Chrome faz shrink-to-fit e a
   página inteira renderizava a 82% em 320px (--fs-xs de 11px virava 9,1px), o
   que não aparece em nenhum teste de scrollWidth e degrada tudo em silêncio.
   A barra cede na mesma ordem do desktop — primeiro o tamanho do rótulo, depois
   o respiro, e só então o botão sai. O corte fica em 374px (e não em 400) porque
   375 é o iPhone SE/6-8: "Ver planos e preços" é a única porta para preço acima
   da dobra, e cada degrau aqui foi calculado para preservá-la o mais fundo
   possível. Abaixo de 375 nenhuma combinação cabe — lá ela vive no drawer. */
@media (max-width: 480px) {
  .site-header .hdr-cta-row .btn-primary { font-size: var(--fs-sm); padding: 0 var(--sp-3); }
}
@media (max-width: 420px) {
  .site-header .inner { gap: var(--sp-2); }
  .site-header .hdr-cta-row .btn-primary { padding: 0 var(--sp-2); }
}
/* A marca cede 2,4px de corpo (14,5px de largura) para que 375 não fique com
   3px de folga: a largura do wordmark depende da fonte do SISTEMA (SF aqui,
   Roboto no Android, Segoe no Windows) e 3px não sobrevivem a uma métrica de
   glifo diferente. Com este degrau a folga a 375 vai a 17,5px — e a marca
   continua sendo o maior elemento da barra. */
@media (max-width: 400px) {
  .brand { font-size: 1.15rem; }
}
@media (max-width: 374px) {
  .site-header .hdr-cta-row .btn-primary { display: none; }
}

/* ============================== Footer */
.site-footer { background: var(--pc-dark-bg); color: var(--pc-dark-text-dim); margin-top: var(--sp-20); }
/* Página que termina em faixa escura (CTA final da home): os dois blocos
   escuros ficam contíguos — sem sanduíche escuro-claro-escuro */
main:has(> .section-dark:last-child) + .site-footer,
main:has(> .hero:last-child) + .site-footer { margin-top: 0; }
/* Página que termina em seção de ritmo: a seção JÁ paga o vão do rodapé
   (base.css §ritmo). O margin daqui dobrava o respiro — 128 + 80 = 208px de
   vazio antes do bloco escuro, em toda página do site. O --sp-20 fica só
   como piso para os finais que não são seção (ex.: tabela solta, listagem).
   O segundo seletor cobre as páginas que embrulham as seções num wrapper
   (o guia usa <div class="guia">): o último bloco continua sendo uma seção de
   ritmo, só que um nível abaixo. */
main:has(> :is(.section, .section-sm):last-child) + .site-footer,
main:has(> :last-child > :is(.section, .section-sm):last-child) + .site-footer { margin-top: 0; }
.site-footer .cols { display: grid; grid-template-columns: 1.4fr 1fr 1fr 1fr; gap: var(--sp-10); padding: var(--sp-16) 0 var(--sp-12); }
.site-footer h4, .site-footer h3 { /* h3: títulos de coluna viraram h3 (heading-order) — mantêm o estilo do rodapé */
  color: var(--pc-petrol-300); font-size: var(--fs-xs); font-weight: 650;
  text-transform: uppercase; letter-spacing: .1em; margin-bottom: var(--sp-4);
}
.site-footer ul { list-style: none; padding: 0; }
.site-footer li { margin-bottom: var(--sp-2); }
.site-footer a { color: var(--pc-dark-text-dim); font-size: var(--fs-sm); transition: color var(--t-fast); }
.site-footer a:hover { color: #fff; text-decoration: none; }
.site-footer .foot-brand { color: #fff; font-size: 1.2rem; font-weight: 700; letter-spacing: -0.02em; }
.site-footer .foot-brand .brand-light { font-weight: 400; }
.site-footer .foot-tagline { font-size: var(--fs-sm); max-width: 34ch; margin-top: var(--sp-3); line-height: 1.6; }
.site-footer .link-arrow { color: var(--pc-petrol-200); font-size: var(--fs-sm); }
.site-footer .link-arrow:hover { color: #fff; }
.site-footer .legal {
  border-top: 1px solid var(--pc-dark-line); padding: var(--sp-6) 0;
  font-size: var(--fs-xs); display: flex; justify-content: space-between; gap: var(--sp-4); flex-wrap: wrap;
}
.site-footer .legal a { font-size: var(--fs-xs); color: var(--pc-dark-text-dim); }
.site-footer .legal a:hover { color: #fff; }
@media (max-width: 900px) { .site-footer .cols { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px) { .site-footer .cols { grid-template-columns: 1fr; gap: var(--sp-8); } }

/* ============================== Cards */
.card {
  background: var(--pc-bg-0); border: var(--hairline);
  border-radius: var(--r-lg); box-shadow: var(--shadow-1);
}
.card-pad { padding: var(--sp-6); }
a.card {
  transition: transform var(--t-base), box-shadow var(--t-base), border-color var(--t-base);
}
a.card:hover {
  border-color: var(--pc-petrol-300); box-shadow: var(--shadow-3);
  transform: translateY(-3px); text-decoration: none;
}

/* Card de métrica (KPI) */
.kpi { position: relative; padding: var(--sp-6); overflow: hidden; container-type: inline-size; }
.kpi .kpi-body { position: relative; z-index: 1; }
/* Rótulo + selo (Experimental) em fluxo, não absoluto: o selo reserva o espaço
   dele em vez de flutuar por cima do rótulo em card estreito. flex-wrap é o que
   fecha a conta — onde os dois não cabem lado a lado (grid de 4 no painel), o
   selo cai para a linha de baixo e o rótulo continua inteiro numa linha só, em
   vez de quebrar em três. Baseline: o selo tem padding e alinharia torto por caixa. */
.kpi .kpi-head {
  display: flex; align-items: baseline; justify-content: space-between;
  flex-wrap: wrap; gap: var(--sp-1) var(--sp-2);
}
.kpi .kpi-head .tag-inline { flex: none; }

/* Marca d'água: ícone de linha grande e sutil no canto — nunca compete com o número */
.kpi-watermark {
  position: absolute; right: -18px; bottom: -20px; z-index: 0;
  width: 116px; height: 116px; pointer-events: none;
  fill: none; stroke: var(--pc-petrol-900); stroke-width: 1.1;
  stroke-linecap: round; stroke-linejoin: round; opacity: .055;
}
.section-dark .kpi-watermark, .surface-dark .kpi-watermark { stroke: #fff; opacity: .07; }

/* Accent semântico: filete superior de 3px que respeita o raio do card */
.kpi-accent::before {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 3px; z-index: 1;
  background: var(--kpi-accent-c, var(--pc-petrol-500));
}
.kpi-accent-petrol  { --kpi-accent-c: var(--pc-petrol-500); }
.kpi-accent-gold    { --kpi-accent-c: var(--pc-gold-500); }
.kpi-accent-success { --kpi-accent-c: var(--pc-success-600); }
.kpi-accent-danger  { --kpi-accent-c: var(--pc-danger-600); }
.kpi-accent-warning { --kpi-accent-c: var(--pc-warning-600); }
.kpi-accent-info    { --kpi-accent-c: var(--pc-info-600); }

/* Linha de apoio discreta sob o valor */
.kpi .kpi-note { font-size: var(--fs-sm); color: var(--pc-ink-500); margin-top: var(--sp-2); }
/* Ação discreta no rodapé do card ("Abrir uma ficha →", "Comprar créditos →") */
.kpi .kpi-acao { display: inline-block; margin-top: var(--sp-3); font-size: var(--fs-sm); font-weight: 600; color: var(--pc-petrol-500); text-decoration: none; }
.kpi .kpi-acao:hover, .kpi .kpi-acao:focus-visible { text-decoration: underline; }

/* Sparkline de rodapé — tendência em miniatura, sem eixos */
.kpi .kpi-spark-wrap { display: flex; align-items: flex-end; gap: var(--sp-3); margin-top: var(--sp-3); }
.kpi-spark { width: 120px; max-width: 100%; height: 30px; flex: none; overflow: visible; }
.kpi-spark .spark-line { fill: none; stroke: var(--pc-petrol-500); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.kpi-spark .spark-fill { fill: var(--pc-petrol-100); opacity: .55; stroke: none; }
.kpi-spark .spark-dot { fill: var(--pc-petrol-700); stroke: none; }
.kpi .kpi-spark-label { font-size: var(--fs-xs); color: var(--pc-ink-400); line-height: 1.3; padding-bottom: 1px; }
/* .kpi-value vale em QUALQUER card de estatística (não só .kpi) — mesma hierarquia em todos */
.kpi-value {
  font-size: var(--fs-kpi); font-weight: 700; line-height: 1.05;
  letter-spacing: -0.025em; color: var(--pc-petrol-900); margin-top: var(--sp-2);
  overflow-wrap: break-word;
}
/* Número comprido (R$ 231,60 mi, lista de UFs) encolhe até caber na largura real
   do card em vez de vazar — --kpi-len é a largura do valor em "em" (partial kpi).
   Piso de 1.5rem: além disso o texto quebra em duas linhas, não some. */
@supports (width: 1cqw) {
  .kpi-value {
    font-size: clamp(1.5rem, calc(100cqw / var(--kpi-len, 5)), var(--fs-kpi));
  }
}
.kpi-suffix { font-size: var(--fs-sm); font-weight: 450; color: var(--pc-ink-500); letter-spacing: 0; }

/* Faixa de KPI compacta — grid de trabalho (painel), onde o número é referência
   de apoio e não a manchete da tela. Menos ar e um degrau abaixo no valor:
   a linha de 4 cards deixa de empurrar o conteúdo útil para fora da dobra. */
.kpi-row-sm .kpi { padding: var(--sp-4) var(--sp-5); }
.kpi-row-sm .kpi .kpi-value { font-size: var(--fs-h2); margin-top: var(--sp-1); }
@supports (width: 1cqw) {
  .kpi-row-sm .kpi .kpi-value {
    font-size: clamp(1.25rem, calc(100cqw / var(--kpi-len, 5)), var(--fs-h2));
  }
}
.kpi-row-sm .kpi .kpi-watermark { width: 88px; height: 88px; right: -14px; bottom: -16px; }
/* A variante mexe em TAMANHO, não em layout do corpo: quem quiser outro arranjo
   interno (ex.: .mon-resumo, que põe número e nota na mesma linha) monta o flex
   do .kpi-body na folha da página, sem brigar com uma regra daqui.
   Unidade não quebra no meio da frase ("da carteira" / "com caso"): ou cabe ao
   lado do número, ou desce inteira para a linha de baixo. */
.kpi-row-sm .kpi-suffix { white-space: nowrap; }
.kpi .kpi-delta { font-size: var(--fs-sm); margin-top: var(--sp-2); font-weight: 500; }
.kpi .kpi-delta.up { color: var(--pc-success-600); }
.kpi .kpi-delta.down { color: var(--pc-danger-600); }

/* Faixa horizontal de números grandes (sensação de escala) */
.metric-row {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--sp-8);
}
/* Faixa de números logo abaixo da ABERTURA da página: ela é a prova do que o
   hero acabou de prometer, não um assunto novo. Cobrar dela o vão cheio de
   seção (--sp-section) soltava os cartões no meio do nada; aqui ela cola na
   abertura. É a mesma decisão que a home já toma com .home-metrics, que sobe
   40px por cima do hero. Só vale para a PRIMEIRA seção (:first-of-type): uma
   .metric-row no meio da página é seção normal e paga o ritmo normal — é o
   caso de /servicos/alertas-de-insolvencia. */
:is(.section, .section-sm):first-of-type:has(+ :is(.section, .section-sm) .metric-row) {
  padding-bottom: var(--sp-10);
}
.metric-row .metric { position: relative; padding-left: var(--sp-5); }
.metric-row .metric::before {
  content: ""; position: absolute; left: 0; top: 4px; bottom: 4px; width: 2px;
  border-radius: 2px; background: var(--pc-petrol-400);
}
.metric-row .metric-value {
  font-size: var(--fs-kpi); font-weight: 700; letter-spacing: -0.025em;
  line-height: 1.05; color: var(--pc-ink-900); font-variant-numeric: tabular-nums;
}
.metric-row .metric-label { font-size: var(--fs-sm); color: var(--pc-ink-500); margin-top: var(--sp-1); }
.section-dark .metric-row .metric-value, .surface-dark .metric-row .metric-value { color: #fff; }
.section-dark .metric-row .metric-label, .surface-dark .metric-row .metric-label { color: var(--pc-dark-text-dim); }
.section-dark .metric-row .metric::before, .surface-dark .metric-row .metric::before { background: var(--pc-gold-500); }

/* Variação com seta (partial stat-delta) */
.stat-delta {
  display: inline-flex; align-items: center; gap: 3px;
  font-size: var(--fs-sm); font-weight: 600; font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.stat-delta .arr { display: inline-block; transition: transform var(--t-base); }
.stat-delta.up { color: var(--pc-success-600); }
.stat-delta.down { color: var(--pc-danger-600); }
.stat-delta.flat { color: var(--pc-ink-400); }
/* Dado de mercado (fluxo de pedidos): variação é informação neutra — verde/
   vermelho ficam reservados a estados de sucesso/risco do próprio sistema */
.stat-delta.neutral { color: var(--pc-ink-500); }
.section-dark .stat-delta.up, .surface-dark .stat-delta.up { color: #7FD6A4; }
.section-dark .stat-delta.down, .surface-dark .stat-delta.down { color: #F2A69E; }

/* Tag EXPERIMENTAL / PARCIAL (componente de confiança) */
.tag-exp {
  position: absolute; top: var(--sp-3); right: var(--sp-3);
  font-size: var(--fs-xs); font-weight: 600; text-transform: uppercase; letter-spacing: .06em;
  color: var(--pc-warning-700); background: var(--pc-warning-100);
  padding: 2px 6px; border-radius: var(--r-xs);
}
.tag-inline {
  font-size: var(--fs-xs); font-weight: 600; text-transform: uppercase; letter-spacing: .06em;
  color: var(--pc-warning-700); background: var(--pc-warning-100);
  padding: 2px 6px; border-radius: var(--r-xs); white-space: nowrap;
}

/* Credor PESSOA FÍSICA (ficha do explorador e aba de credores do painel).
   Legenda do nome, não etiqueta de estado: sem ela o documento cortado em três
   caracteres parece dado truncado por defeito, e não por regra. */
.cred-pf { font-size: var(--fs-xs); color: var(--pc-ink-400); white-space: nowrap; }

/* Documento ESTIMADO pela razão social (mv_credores.doc_estimado): mesma tinta
   âmbar das tags de ressalva do site, para o asterisco ser achável varrendo a
   coluna e casar de cara com a nota de rodapé que o explica. */
.doc-estimado {
  display: inline-block; margin-left: 3px; padding: 0 4px;
  font-weight: 700; line-height: 1.4;
  color: var(--pc-warning-700); background: var(--pc-warning-100); border-radius: var(--r-xs);
}
.cred-estimado-nota { margin-top: var(--sp-3); margin-bottom: 0; }
.cred-estimado-nota .doc-estimado { margin-left: 0; }

/* ============================== Grid bento (home) */
.grid-bento {
  display: grid; gap: var(--sp-5);
  grid-template-columns: repeat(6, 1fr);
}
.grid-bento > * { min-width: 0; }
/* Combinada com .grid-2 (vitrines de 4 cards sem classes span): 4 colunas fluidas,
   nunca as 6 colunas estreitas do bento puro */
.grid-2.grid-bento { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 1024px) { .grid-2.grid-bento { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 640px)  { .grid-2.grid-bento { grid-template-columns: 1fr; } }
.grid-bento .span-2 { grid-column: span 2; }
.grid-bento .span-3 { grid-column: span 3; }
.grid-bento .span-4 { grid-column: span 4; }
.grid-bento .span-6 { grid-column: span 6; }
.grid-bento .row-2 { grid-row: span 2; }
@media (max-width: 1024px) {
  .grid-bento { grid-template-columns: repeat(2, 1fr); }
  .grid-bento .span-2, .grid-bento .span-3, .grid-bento .span-4 { grid-column: span 1; }
  .grid-bento .span-6 { grid-column: span 2; }
}
@media (max-width: 640px) {
  .grid-bento { grid-template-columns: 1fr; }
  .grid-bento .span-2, .grid-bento .span-3, .grid-bento .span-4, .grid-bento .span-6 { grid-column: span 1; }
  .grid-bento .row-2 { grid-row: span 1; }
}

/* ============================== Pill nav (filtros) */
.pill-nav { display: flex; gap: var(--sp-2); flex-wrap: wrap; }
.pill-nav a, .pill-nav button {
  display: inline-flex; align-items: center; gap: 6px;
  height: 34px; padding: 0 var(--sp-4); border-radius: var(--r-full);
  border: var(--hairline-strong); background: var(--pc-bg-0);
  font-size: var(--fs-sm); font-weight: 500; color: var(--pc-ink-700);
  cursor: pointer; white-space: nowrap;
  transition: background-color var(--t-fast), border-color var(--t-fast), color var(--t-fast), transform var(--t-fast);
}
.pill-nav a:hover, .pill-nav button:hover {
  border-color: var(--pc-petrol-400); color: var(--pc-petrol-800);
  text-decoration: none; transform: translateY(-1px);
}
.pill-nav .active, .pill-nav [aria-current] {
  background: var(--pc-petrol-800); border-color: var(--pc-petrol-800); color: #fff;
}
.pill-nav .active:hover, .pill-nav [aria-current]:hover { color: #fff; border-color: var(--pc-petrol-800); }

/* ============================== Molduras de demonstração */
/* Janela estilo macOS */
.browser-mock {
  background: var(--pc-bg-0); border: var(--hairline);
  border-radius: var(--r-xl); box-shadow: var(--shadow-4); overflow: hidden;
}
.browser-mock .bm-bar {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: 10px var(--sp-4); background: var(--pc-bg-50);
  border-bottom: var(--hairline);
}
.browser-mock .bm-dots { display: flex; gap: 6px; flex: none; }
.browser-mock .bm-dots i { width: 11px; height: 11px; border-radius: 50%; display: block; }
.browser-mock .bm-dots i:nth-child(1) { background: #F26D5F; }
.browser-mock .bm-dots i:nth-child(2) { background: #F5BE4F; }
.browser-mock .bm-dots i:nth-child(3) { background: #58C555; }
.browser-mock .bm-url {
  flex: 1; max-width: 420px; margin: 0 auto;
  height: 24px; line-height: 24px; text-align: center;
  background: var(--pc-bg-100); border-radius: var(--r-sm);
  font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--pc-ink-500);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding: 0 var(--sp-3);
}
.browser-mock .bm-body { padding: 0; }
/* Corpo com conteúdo "de página" (linha do processo, chips, legenda): o
   card-pad vale mesmo aqui — nenhum glifo encosta no raio do card */
.browser-mock .bm-body.card-pad { padding: var(--sp-6); }

/* Envelope de e-mail */
.mail-mock {
  background: var(--pc-bg-0); border: var(--hairline);
  border-radius: var(--r-lg); box-shadow: var(--shadow-3); overflow: hidden;
}
.mail-mock .mm-head { padding: var(--sp-4) var(--sp-5); border-bottom: var(--hairline); background: var(--pc-bg-50); }
.mail-mock .mm-from { display: flex; align-items: center; gap: var(--sp-3); }
.mail-mock .mm-avatar {
  width: 34px; height: 34px; border-radius: 50%; flex: none;
  background: var(--pc-petrol-800); color: #fff; font-weight: 700; font-size: var(--fs-sm);
  display: flex; align-items: center; justify-content: center;
}
.mail-mock .mm-sender { font-weight: 600; font-size: var(--fs-sm); color: var(--pc-ink-900); }
.mail-mock .mm-addr { font-size: var(--fs-xs); color: var(--pc-ink-400); font-family: var(--font-mono); }
.mail-mock .mm-subject { font-weight: 650; margin-top: var(--sp-3); color: var(--pc-ink-900); }
.mail-mock .mm-meta { font-size: var(--fs-xs); color: var(--pc-ink-400); margin-top: 2px; }
.mail-mock .mm-body { padding: var(--sp-5); font-size: var(--fs-sm); }

/* ============================== Tabela densa */
.table-card { overflow: hidden; }
.table-wrap { overflow-x: auto; min-width: 0; }
/* Tabela full-bleed (filha direta do card, após um .card-pad de cabeçalho):
   a 1ª/última coluna alinha ao recuo do card e a base respira — sem isto a
   1ª coluna ficava 12px da borda (desalinhada do cabeçalho, que usa 24px) e
   a última linha encostava na borda inferior do card. O hover das linhas
   continua varrendo o card inteiro (o padding é das células, não do wrap). */
.card > .table-wrap { padding-bottom: var(--sp-2); }
@media (min-width: 769px) {
  .card > .table-wrap table.data th:first-child,
  .card > .table-wrap table.data td:first-child { padding-left: var(--sp-6); }
  .card > .table-wrap table.data th:last-child,
  .card > .table-wrap table.data td:last-child { padding-right: var(--sp-6); }
}
table.data {
  width: 100%; border-collapse: collapse; font-size: var(--fs-sm); background: var(--pc-bg-0);
}
table.data th {
  background: var(--pc-bg-50); font-size: var(--fs-xs); font-weight: 650;
  text-transform: uppercase; letter-spacing: .07em; color: var(--pc-ink-500);
  text-align: left; padding: var(--sp-3); position: sticky; top: 0; z-index: 1;
  border-bottom: var(--hairline-strong); white-space: nowrap;
}
table.data td { padding: var(--sp-2) var(--sp-3); border-bottom: var(--hairline); height: 44px; }
table.data tr:last-child td { border-bottom: 0; }
table.data tbody tr { transition: background-color var(--t-fast); }
table.data tr:hover td { background: var(--pc-petrol-50); }
table.data td.num, table.data th.num { text-align: right; font-variant-numeric: tabular-nums; }
/* Valores monetários/numéricos nunca quebram no meio (ex.: "R$" órfão) —
   a leitura vertical da coluna permanece alinhada */
table.data td.num { white-space: nowrap; }
table.data td.mono { font-family: var(--font-mono); color: var(--pc-ink-700); white-space: nowrap; }
table.data a { font-weight: 500; }
/* Linha de GRUPO: um degrau ACIMA do hover das linhas comuns (petrol-50). Nos
   dois no mesmo tom, passar o mouse numa linha comum a igualava ao cabeçalho
   do grupo e a hierarquia da tabela sumia debaixo do cursor. */
table.data tr.group-row td {
  background: var(--pc-petrol-100); font-weight: 600; color: var(--pc-petrol-900); font-size: var(--fs-sm);
}
/* E a própria linha de grupo responde ao mouse — sem esta regra ela empata em
   especificidade com o tr:hover acima e, por vir depois, ficava inerte. */
table.data tr.group-row:hover td { background: var(--pc-petrol-200); }
table.data .bar-cell { position: relative; }
table.data .bar-cell .bar {
  position: absolute; right: 0; top: 22%; height: 56%;
  background: var(--pc-petrol-200); opacity: .55; z-index: 0; border-radius: 3px;
}
table.data .bar-cell span { position: relative; z-index: 1; }

/* Cabeçalho de LINHA (th[scope=row]) — no desktop parece célula comum; no
   mobile vira o título do bloco empilhado (sem prefixo "DIMENSÃO:") */
table.data tbody th[scope="row"] {
  background: none; text-transform: none; letter-spacing: 0;
  font-size: var(--fs-sm); font-weight: 500; color: var(--pc-ink-900);
  text-align: left; padding: var(--sp-2) var(--sp-3); height: 44px;
  border-bottom: var(--hairline); position: static; white-space: normal;
}
table.data tr:last-child th[scope="row"] { border-bottom: 0; }
table.data tr:hover th[scope="row"] { background: var(--pc-petrol-50); }

/* Largura contida: colunas distribuídas, conteúdo quebra em vez de vazar */
table.data.table-fit { table-layout: fixed; }
table.data.table-fit td { overflow-wrap: anywhere; }
table.data.table-fit .link-arrow { white-space: normal; display: inline; }
/* No fluxo inline a seta vira texto colado por word-joiner (\2060): nunca
   quebra sozinha para a linha seguinte; o respiro vem do margin-left */
table.data.table-fit .link-arrow::after {
  display: inline; content: "\2060\2192"; margin-left: .35em;
}
table.data .cnpj-cell { white-space: nowrap; font-size: var(--fs-xs); }
/* Badge que PODE quebrar: em tabela de colunas fixas (.table-fit) e em toda
   célula marcada .badge-cell. "Recuperação Judicial" numa linha só cobra ~180px
   de largura MÍNIMA da tabela inteira — e numa tabela larga essa largura sai da
   coluna que identifica a linha (a devedora, que então quebra palavra a
   palavra). Quebrado, o rótulo cabe em duas linhas dentro dos 44px da célula e
   só quebra quando falta espaço: com folga, a coluna volta a uma linha. */
table.data.table-fit .badge,
table.data td.badge-cell .badge {
  white-space: normal; height: auto; min-height: 22px;
  line-height: 1.5; padding: 1px 8px; max-width: 100%;
}

/* Página do sócio: o nome empresarial nunca determina a largura da tabela.
   A elipse é apenas visual; o texto completo permanece no DOM e no title. */
table.socio-company-table {
  table-layout: fixed;
  min-width: 980px;
}
table.socio-company-table col.socio-company-table__empresa { width: 32%; }
table.socio-company-table col.socio-company-table__cnpj { width: 14%; }
table.socio-company-table col.socio-company-table__situacao { width: 19%; }
table.socio-company-table col.socio-company-table__qualificacao { width: 11%; }
table.socio-company-table col.socio-company-table__entrada { width: 10%; }
table.socio-company-table col.socio-company-table__uf { width: 4%; }
table.socio-company-table col.socio-company-table__capital { width: 10%; }
table.socio-company-table .socio-company-name { min-width: 0; overflow: hidden; }
table.data.socio-company-table .socio-company-link {
  display: flex; align-items: center; width: 100%; max-width: 100%;
  min-width: 0; white-space: nowrap;
}
table.data.socio-company-table .socio-company-link::after { display: block; flex: none; }
table.socio-company-table .socio-company-name__text {
  display: block; min-width: 0; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap;
}

/* Tabela → cards no mobile */
@media (max-width: 768px) {
  /* A tabela empilhada nunca alarga a página: vira bloco limitado ao card e
     qualquer excedente rola dentro dela (o algoritmo de tabela ignoraria a
     largura do container e arrastaria o body lateralmente) */
  table.data.responsive { display: block; overflow-x: auto; max-width: 100%; }
  table.data.responsive tbody { display: block; }
  table.data.responsive thead { display: none; }
  table.data.responsive tr { display: block; border-bottom: var(--hairline-strong); padding: var(--sp-3) 0; }
  table.data.responsive td {
    display: flex; justify-content: space-between; gap: var(--sp-3);
    border: 0; height: auto; padding: var(--sp-1) var(--sp-3); text-align: right;
  }
  table.data.responsive td::before {
    content: attr(data-label); font-size: var(--fs-xs); text-transform: uppercase;
    letter-spacing: .06em; color: var(--pc-ink-500); font-weight: 600; text-align: left;
    white-space: nowrap; flex: none; /* rótulo nunca quebra ("EMP RESA") */
  }
  table.data.responsive tbody th[scope="row"] {
    display: block; border: 0; height: auto; padding: var(--sp-1) var(--sp-3);
    font-weight: 650; color: var(--pc-ink-900); font-size: var(--fs-body);
  }
  table.data.table-fit { table-layout: auto; }
  table.socio-company-table { min-width: 0; width: 100%; }
  table.data.socio-company-table .socio-company-link { flex: 1 1 auto; width: auto; }
}

/* Paginação */
.pagination { display: flex; gap: var(--sp-1); align-items: center; padding: var(--sp-3); font-size: var(--fs-sm); }
.pagination a, .pagination span.cur {
  padding: var(--sp-1) var(--sp-2); min-width: 32px; text-align: center;
  border-radius: var(--r-sm); border: 1px solid transparent;
  transition: background-color var(--t-fast);
}
.pagination a:hover { background: var(--pc-petrol-50); text-decoration: none; }
.pagination span.cur { background: var(--pc-petrol-800); color: #fff; }
.pagination .gap { color: var(--pc-ink-400); padding: var(--sp-1) 2px; }
.pagination .info { margin-left: auto; color: var(--pc-ink-500); font-size: var(--fs-xs); }

/* ============================== Badges e chips */
.badge {
  display: inline-block; height: 22px; line-height: 20px; padding: 0 8px;
  border-radius: var(--r-sm); border: 1px solid var(--pc-line-200);
  font-size: var(--fs-xs); font-weight: 600; text-transform: uppercase; letter-spacing: .05em;
  color: var(--pc-ink-500); background: var(--pc-bg-100); white-space: nowrap;
}
.badge-falencia { color: #A82C21; background: #FBEBE9; border-color: #F0C7C2; }
.badge-rj       { color: #8C5A03; background: #FCF3DF; border-color: #EED9A8; }
.badge-re       { color: #5E4699; background: #F1EDFA; border-color: #D8CDF0; }
.badge-tutela   { color: #2A5E8C; background: #E9F1F9; border-color: #C3D9EC; }
.badge-suspeita { color: #5B6E71; background: #F1F4F4; border-color: #C7D2D3; border-style: dashed; }

.chip {
  display: inline-block; height: 18px; line-height: 16px; padding: 0 6px;
  border-radius: var(--r-xs); border: 1px solid var(--pc-line-200);
  font-size: var(--fs-xs); white-space: nowrap; color: var(--pc-ink-500); background: var(--pc-bg-100);
}
.chip b { font-weight: 700; }
.chip-c1 { color: #2A5E8C; background: #E9F1F9; border-color: #C3D9EC; }
.chip-c2 { color: #8C5A03; background: #FCF3DF; border-color: #EED9A8; }
.chip-c3 { color: #186974; background: #DCEEEF; border-color: #B9DDE0; }
.chip-c4 { color: #5E4699; background: #F1EDFA; border-color: #D8CDF0; }
.chip-extra { color: #5B6E71; background: #F1F4F4; border-color: #C7D2D3; }

/* Chip clicável (personas, filtros leves) */
a.chip { transition: border-color var(--t-fast), color var(--t-fast), transform var(--t-fast); }
a.chip:hover { text-decoration: none; border-color: var(--pc-petrol-400); color: var(--pc-petrol-800); transform: translateY(-1px); }

.status-dot { display: inline-block; width: 8px; height: 8px; border-radius: var(--r-full); margin-right: 6px; vertical-align: 1px; }
.status-dot.ok { background: var(--pc-success-600); }
.status-dot.off { background: var(--pc-ink-300); }
.status-dot.err { background: var(--pc-danger-600); }

/* ============================== Timeline processual */
.timeline { list-style: none; padding: 0; position: relative; }
.timeline::before { content: ""; position: absolute; left: 5px; top: 6px; bottom: 6px; width: 2px; background: var(--pc-line-200); }
.timeline li { position: relative; padding: 0 0 var(--sp-6) var(--sp-8); }
.timeline .dot {
  position: absolute; left: 0; top: 5px; width: 12px; height: 12px; z-index: 1;
  border-radius: var(--r-full); background: var(--pc-bg-0); border: 2px solid var(--pc-ink-300);
  transition: transform var(--t-fast), border-color var(--t-fast);
}
.timeline li:hover .dot { transform: scale(1.25); border-color: var(--pc-petrol-500); }
.timeline li.marco .dot { background: var(--pc-petrol-600); border-color: var(--pc-petrol-600); box-shadow: 0 0 0 4px var(--pc-petrol-100); }
.timeline .ev-date { font-family: var(--font-mono); font-size: var(--fs-sm); color: var(--pc-ink-400); }
.timeline .ev-title { font-weight: 600; color: var(--pc-ink-900); }
.timeline .ev-desc { font-size: var(--fs-sm); color: var(--pc-ink-500); }
.timeline li.marco .ev-body { background: var(--pc-petrol-50); border: 1px solid var(--pc-petrol-100); border-radius: var(--r-md); padding: var(--sp-3) var(--sp-4); margin-top: var(--sp-1); }
.timeline .mes-divisor { font-size: var(--fs-xs); font-weight: 650; text-transform: uppercase; letter-spacing: .08em; color: var(--pc-ink-400); padding: var(--sp-2) 0 var(--sp-2) var(--sp-8); }

/* ============================== Mapa do Brasil (SVG geográfico) */
.map-brasil { width: 100%; max-width: 620px; height: auto; }
.map-brasil .uf-shape {
  cursor: pointer; stroke: #FFFFFF; stroke-width: 1.2; stroke-linejoin: round;
  transition: filter var(--t-fast), stroke var(--t-fast), stroke-width var(--t-fast);
}
.map-brasil a:focus-visible .uf-shape,
.map-brasil .uf-shape:hover, .map-brasil .uf-shape:focus {
  stroke: var(--pc-gold-500); stroke-width: 2;
  filter: brightness(1.08) drop-shadow(0 2px 6px rgba(11,43,48,.35));
  outline: none;
}
.map-brasil .uf-label {
  font-family: var(--font-sans); font-size: 17px; font-weight: 650;
  pointer-events: none; letter-spacing: .02em;
}
/* Rótulos externos com linha-guia (estados pequenos: RN, PB, PE, AL, SE, ES, RJ, DF) */
.map-brasil .uf-label-ext {
  fill: var(--pc-petrol-900); font-size: 15px;
  paint-order: stroke; stroke: #FFFFFF; stroke-width: 4px; stroke-linejoin: round;
}
.map-brasil .uf-leader { stroke: var(--pc-ink-300); stroke-width: 1.2; fill: none; }
/* Alternador "ver como tabela" — controle estilizado, coerente com o design system */
.map-toggle {
  margin-left: auto; display: inline-flex; align-items: center; gap: 6px;
  height: 28px; padding: 0 var(--sp-3); border-radius: var(--r-full);
  border: var(--hairline-strong); background: var(--pc-bg-0);
  font-size: var(--fs-xs); font-weight: 500; color: var(--pc-ink-700);
  cursor: pointer; user-select: none; white-space: nowrap;
  transition: border-color var(--t-fast), color var(--t-fast), background-color var(--t-fast);
}
.map-toggle:hover { border-color: var(--pc-petrol-400); color: var(--pc-petrol-800); }
.map-toggle input { accent-color: var(--pc-petrol-600); width: 14px; height: 14px; margin: 0; cursor: pointer; }
.map-toggle:has(input:checked) { background: var(--pc-petrol-50); border-color: var(--pc-petrol-400); color: var(--pc-petrol-800); }
/* Mobile: o SVG escala ~0,33× — siglas maiores no espaço do viewBox (≥10px
   renderizados) e micro-UFs com linha-guia saem de cena. DIREÇÃO ÚNICA para
   TODOS os mapas: no MESMO breakpoint em que os rótulos externos somem (senão
   RN, PB, PE, AL, SE, ES, RJ, DF ficam inidentificáveis e CE/PI/MA órfãos),
   a tabela de UFs abre por padrão logo abaixo do mapa (!important vence o
   display:none inline do toggle) e o alternador sai de cena — nunca existe
   faixa de largura com rótulos ausentes E tabela escondida. */
@media (max-width: 640px) {
  .map-brasil .uf-label { font-size: 32px; font-weight: 600; }
  /* mantém RJ e ES (volume alto) identificáveis; demais externos saem */
  .map-brasil .uf-label-ext, .map-brasil .uf-leader { display: none; }
  .map-brasil .uf-label-ext[data-uf="RJ"], .map-brasil .uf-label-ext[data-uf="ES"],
  .map-brasil .uf-leader[data-uf="RJ"], .map-brasil .uf-leader[data-uf="ES"] { display: block; font-size: 24px; }
  .map-table { display: block !important; }
  .map-toggle { display: none; }
}
/* compat: nome antigo dos tiles */
.map-brasil .uf-tile { transition: filter var(--t-fast), stroke var(--t-fast); cursor: pointer; }
.map-brasil .uf-tile:hover, .map-brasil .uf-tile:focus { stroke: var(--pc-gold-500); stroke-width: 1.5; }
.map-brasil text { font-family: var(--font-sans); pointer-events: none; }
.map-legend { display: flex; gap: var(--sp-3); align-items: center; font-size: var(--fs-xs); color: var(--pc-ink-500); margin-top: var(--sp-4); flex-wrap: wrap; }
.map-legend .sw { display: inline-block; width: 14px; height: 14px; border-radius: 3px; margin-right: 4px; vertical-align: -2px; border: 1px solid rgba(11,43,48,.08); }
.map-legend .scale { display: inline-flex; }
.map-legend .scale .sw { border-radius: 0; margin: 0; }
.map-legend .scale .sw:first-child { border-radius: 3px 0 0 3px; }
.map-legend .scale .sw:last-child { border-radius: 0 3px 3px 0; }

/* ============================== Gráficos SVG */
/* max-height trava a escala em containers largos: rótulos de eixo nunca
   renderizam "gigantes" — o SVG centraliza (letterbox) em vez de estourar */
.chart-svg { width: 100%; height: auto; max-height: 360px; }
.chart-svg .grid-line { stroke: var(--pc-line-100); stroke-width: 1; }
.chart-svg .axis-label { font-family: var(--font-sans); font-size: 11px; fill: var(--pc-ink-400); font-variant-numeric: tabular-nums; }
/* Mobile: o SVG escala ~0,3-0,5× — rótulos maiores no espaço do viewBox
   para renderizarem legíveis (mesma técnica do mapa) */
@media (max-width: 640px) {
  .chart-svg .axis-label { font-size: 24px; }
}
.chart-svg .bar { fill: var(--pc-petrol-500); transition: fill var(--t-fast); }
.chart-svg .bar-alt { fill: var(--pc-gold-500); }
/* Interação das barras. A .bar-hit cobre a COLUNA inteira (barra estreita é
   alvo hostil pro mouse) e, por ficar por cima, impede :hover na .bar — daí o
   realce sair numa cópia sobreposta. Tudo em CSS: o <title> nativo que havia
   aqui só aparecia depois de ~1s de parada e não era estilizável. */
.chart-svg .bar-wrap { cursor: pointer; outline: none; }
.chart-svg .bar-hit { fill: transparent; pointer-events: all; }
.chart-svg .bar-hl {
  fill: var(--pc-petrol-700);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}
.chart-svg .bar-wrap:hover .bar-hl,
.chart-svg .bar-wrap:focus .bar-hl { opacity: 1; visibility: visible; }
.chart-svg .bar-wrap:hover .chart-point-tooltip,
.chart-svg .bar-wrap:focus .chart-point-tooltip { opacity: 1; visibility: visible; }
.chart-svg .line { fill: none; stroke: var(--pc-petrol-600); stroke-width: 2; stroke-linejoin: round; }
.chart-svg .area { fill: var(--pc-petrol-100); opacity: .45; }
.chart-svg .line-point { fill: var(--pc-bg-0); stroke: var(--pc-petrol-600); stroke-width: 1.5; }
.chart-svg .line-point-wrap { cursor: pointer; outline: none; }
.chart-svg .line-point-hit { fill: transparent; stroke: none; pointer-events: all; }
.chart-svg .chart-point-tooltip {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity var(--t-fast);
}
.chart-svg .chart-point-tooltip-bg { fill: var(--pc-ink-900); }
.chart-svg .chart-point-tooltip-text {
  fill: #fff;
  font-family: var(--font-sans);
  font-size: 11px;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
}
.chart-svg .line-point-wrap:hover .chart-point-tooltip,
.chart-svg .line-point-wrap:focus .chart-point-tooltip {
  opacity: 1;
  visibility: visible;
}
.chart-svg .line-point-wrap:hover .line-point,
.chart-svg .line-point-wrap:focus .line-point {
  fill: var(--pc-petrol-600);
  stroke: var(--pc-bg-0);
  stroke-width: 2;
}
.chart-title { font-size: var(--fs-h4); font-weight: 600; }
.chart-sub { font-size: var(--fs-xs); color: var(--pc-ink-400); margin-bottom: var(--sp-3); }

/* Barras horizontais: para quando o rótulo da categoria é longo demais para
   caber no eixo X (nomes de setor, faixas de valor). */
.chart-hbar { max-height: none; }
.chart-hbar .chart-val { fill: var(--pc-ink-700); }
.chart-svg .chart-ref { stroke: var(--pc-ink-300); stroke-width: 1.5; }

/* ============================== Rosca + Pareto (panorama do painel)
   Dois gráficos com legenda, balão e leitura central. O SVG vem pronto do
   servidor (App\Core\Chart::donut/pareto) e é legível PARADO: sem JS restam as
   fatias, a régua dos 80%, a legenda com os números e a tabela no <details>.
   O panorama-charts.js só acrescenta o realce cruzado e o balão que segue o
   ponteiro — enfeite, nunca a única via para um valor. */
.pc-viz { position: relative; }
.pc-viz-plot { display: flex; justify-content: center; padding: var(--sp-2) 0 var(--sp-1); }

/* ---- Rosca */
.pc-donut-wrap { position: relative; display: inline-block; line-height: 0; }
.pc-donut-svg { width: 232px; max-width: 100%; max-height: none; }
.pc-donut-trilho { stroke: var(--pc-bg-100); }
.pc-donut-fatia { transition: opacity var(--t-fast); cursor: pointer; }
/* Realce por SUBTRAÇÃO: a fatia ativa fica como estava e as outras recuam.
   Clarear a ativa mudaria a cor que a legenda promete — o olho leria outra
   categoria. Recuar as vizinhas não mexe em cor nenhuma. */
.pc-viz.is-ativo .pc-donut-fatia { opacity: .28; }
.pc-viz.is-ativo .pc-donut-fatia.is-on { opacity: 1; }
.pc-donut-centro {
  position: absolute; inset: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 2px;
  line-height: 1.15; text-align: center; pointer-events: none; padding: 0 18%;
}
.pc-donut-centro-val { font-size: var(--fs-h4); font-weight: 650; color: var(--pc-ink-900); }
.pc-donut-centro-rot { font-size: var(--fs-xs); color: var(--pc-ink-400); }

/* ---- Legenda (também é o alvo de mouse das fatias finas: 0,5% do anel são
   ~3px de arco, que ninguém acerta; a linha da legenda tem 28px) */
.pc-legenda { list-style: none; margin: var(--sp-3) 0 0; padding: 0; }
.pc-legenda li {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: 5px var(--sp-5); font-size: var(--fs-sm); cursor: default;
  border-radius: var(--r-xs); transition: background-color var(--t-fast);
}
.pc-legenda li.is-on { background: var(--pc-bg-50); }
.pc-legenda .pc-chave { width: 10px; height: 10px; border-radius: 3px; flex: none; }
.pc-legenda .pc-chave-linha { width: 14px; height: 0; border-top: 2px solid currentColor; border-radius: 0; }
.pc-legenda .pc-nome { flex: 1; min-width: 0; color: var(--pc-ink-700); }
.pc-legenda .pc-val { color: var(--pc-ink-900); font-variant-numeric: tabular-nums; }
.pc-legenda .pc-pct { color: var(--pc-ink-400); font-variant-numeric: tabular-nums; min-width: 44px; text-align: right; }

/* ---- Pareto */
.pc-pareto-svg { max-height: none; }
.pc-pareto-bar { fill: var(--pc-petrol-500); transition: fill var(--t-fast); }
.pc-pareto-linha { fill: none; stroke: #eb6834; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
/* Anel na cor da superfície, não contorno de cor: mantém o ponto legível onde
   ele cruza a linha ou o topo de uma barra. */
.pc-pareto-ponto { fill: #eb6834; stroke: var(--pc-bg-0); stroke-width: 2; }
.pc-pareto-ref { stroke-width: 1; }
.pc-pareto-calo {
  font-family: var(--font-sans); font-size: 11px; font-weight: 600;
  fill: var(--pc-ink-500); font-variant-numeric: tabular-nums;
}
/* O salto global de rótulo no mobile (.chart-svg .axis-label = 24px, que existe
   porque lá o SVG encolhe ~0,3-0,5×) sobrepõe as SETE faixas deste eixo umas
   nas outras. Aqui o cartão ocupa a largura toda quando empilha, então a escala
   é ~0,75× e 14px já rende ~11px na tela. Especificidade 0,2,1 para ganhar da
   regra de 0,1,1 sem !important. */
@media (max-width: 640px) {
  .chart-svg.pc-pareto-svg .axis-label { font-size: 14px; }
  .chart-svg.pc-pareto-svg .pc-pareto-calo { font-size: 14px; }
}
.pc-pareto-hit { fill: transparent; pointer-events: all; cursor: pointer; outline: none; }
.pc-pareto-hit:focus-visible { fill: rgba(29,131,143,.10); }
.pc-viz.is-ativo .pc-pareto-bar { fill: var(--pc-petrol-300); }
.pc-viz.is-ativo .pc-pareto-bar.is-on { fill: var(--pc-petrol-700); }

/* ---- Balão: HTML, não <text> em SVG — texto em SVG não quebra linha sozinho
   e obrigaria a estimar largura por contagem de caractere. */
.pc-viz-tip {
  position: absolute; z-index: 3; top: 0; left: 0; max-width: 230px;
  padding: 7px 10px; border-radius: var(--r-sm);
  background: var(--pc-ink-900); color: #fff;
  font-size: var(--fs-sm); line-height: 1.35;
  box-shadow: var(--shadow-2); pointer-events: none;
  opacity: 0; visibility: hidden; transition: opacity var(--t-fast);
}
.pc-viz-tip.is-on { opacity: 1; visibility: visible; }
/* Valor primeiro e forte, nome depois: aqui o leitor JÁ tem a categoria (ele
   apontou para ela) e quer o número — hierarquia inversa à da legenda. */
.pc-viz-tip b { display: block; font-size: var(--fs-body); font-weight: 650; font-variant-numeric: tabular-nums; }
.pc-viz-tip span { color: var(--pc-dark-text-dim); }

/* ---- Tabela-espelho: nenhum valor fica preso ao hover (e é o que imprime) */
.pc-tabela-viz > summary {
  cursor: pointer; list-style: none; padding: var(--sp-2) var(--sp-5);
  font-size: var(--fs-sm); color: var(--pc-petrol-600); font-weight: 600;
}
.pc-tabela-viz > summary::-webkit-details-marker { display: none; }
.pc-tabela-viz > summary::before { content: "▸ "; display: inline-block; transition: transform var(--t-fast); }
.pc-tabela-viz[open] > summary::before { content: "▾ "; }
.pc-tabela-viz > summary:hover { color: var(--pc-petrol-700); }
/* Sem regra de @media print aqui de propósito: não há como abrir um <details>
   fechado por CSS em navegador que se possa assumir (::details-content é
   recente demais), e uma regra que não funciona é pior que a ausência dela —
   promete uma tabela impressa que não sai. Quem vai imprimir abre o detalhe. */

/* ============================== Gráfico dentro da reportagem
   O corpo da matéria guarda só [grafico:chave]; o SVG é montado ao servir
   (App\Services\GraficoNoticia). O bloco sangra para fora da coluna de texto,
   que é estreita por legibilidade e apertaria o gráfico. */
.nx-grafico {
  margin: var(--sp-8) 0;
  padding: var(--sp-5) var(--sp-5) var(--sp-4);
  border: 1px solid var(--pc-line-200);
  border-radius: 10px;
  background: var(--pc-bg-0);
}
.nx-grafico-tit {
  font-family: var(--font-sans);
  font-size: 1.02rem;
  font-weight: 700;
  line-height: 1.35;
  color: var(--pc-ink-900);
  margin: 0 0 var(--sp-1);
}
.nx-grafico-sub {
  font-family: var(--font-sans);
  font-size: .84rem;
  line-height: 1.5;
  color: var(--pc-ink-500);
  margin: 0 0 var(--sp-4);
  max-width: 68ch;
}
.nx-grafico-fonte {
  font-family: var(--font-sans);
  font-size: .76rem;
  color: var(--pc-ink-400);
  margin-top: var(--sp-3);
  padding-top: var(--sp-2);
  border-top: 1px solid var(--pc-line-100);
}

/* ============================== Tabela dentro da reportagem
   Números à direita e em algarismos de largura fixa, para as casas decimais
   empilharem — tabela de dados não é tabela de layout. */
.nx-corpo table {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--font-sans);
  font-size: .88rem;
  margin: var(--sp-8) 0;
  display: block;
  overflow-x: auto;
}
@media (min-width: 700px) { .nx-corpo table { display: table; } }
.nx-corpo table caption {
  caption-side: top;
  text-align: left;
  font-size: .84rem;
  line-height: 1.5;
  color: var(--pc-ink-500);
  padding: 0 0 var(--sp-3);
  max-width: 68ch;
}
.nx-corpo table th {
  text-align: left;
  font-weight: 600;
  font-size: .74rem;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--pc-ink-500);
  border-bottom: 2px solid var(--pc-petrol-600);
  padding: var(--sp-2) var(--sp-3);
  white-space: nowrap;
}
.nx-corpo table td {
  padding: var(--sp-3);
  border-bottom: 1px solid var(--pc-line-100);
  color: var(--pc-ink-900);
  vertical-align: baseline;
}
.nx-corpo table td:not(:first-child),
.nx-corpo table th:not(:first-child) {
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.nx-corpo table td:first-child { font-weight: 600; }
.nx-corpo table tbody tr:hover td { background: var(--pc-petrol-50); }
.nx-corpo table tbody tr:last-child td { border-bottom: 0; }

/* ============================== Skeleton */
@keyframes shimmer { from { background-position: -400px 0; } to { background-position: 400px 0; } }
.skeleton {
  background: linear-gradient(90deg, var(--pc-bg-100) 25%, #F7FAFA 37%, var(--pc-bg-100) 63%);
  background-size: 800px 100%; animation: shimmer 1.4s infinite linear; border-radius: var(--r-sm);
}

/* CARREGANDO um bloco [data-ajax-target] que JÁ TEM conteúdo. O pcAjax marca o
   alvo com .skeleton + aria-busy, mas o brilho do skeleton é um fundo: sob
   cards opacos — que é o caso do painel — ele fica escondido atrás do conteúdo
   antigo e a troca parece travada. Apagar o bloco velho é o sinal que o olho
   entende, e ele também impede o clique num controle que está prestes a ser
   substituído (duas trocas em voo, a última a chegar ganha).

   Não é `visibility:hidden` nem altura zero de propósito: o conteúdo antigo
   segura a altura da página, então a rolagem não salta quando o novo entra. */
[data-ajax-target][aria-busy="true"] {
  opacity: .45; pointer-events: none; transition: opacity var(--t-fast, .12s) ease-out;
}
@media (prefers-reduced-motion: reduce) {
  [data-ajax-target][aria-busy="true"] { transition: none; }
}

/* ============================== Empty state */
.empty { text-align: center; padding: var(--sp-16) var(--sp-6); color: var(--pc-ink-500); }
.empty h3, .empty h4 { color: var(--pc-ink-700); margin-bottom: var(--sp-2); font-size: var(--fs-h4); font-weight: 600; }
.empty p { font-size: var(--fs-sm); max-width: 46ch; margin: 0 auto var(--sp-4); }

/* ============================== Paywall (regra de ouro: placeholder, nunca dado real) */
.is-locked {
  filter: blur(5px); user-select: none; pointer-events: none;
  color: var(--pc-ink-400);
}
/* A zona SEMPRE comporta o card ancorado (bottom + altura típica do card):
   sem min-height, zonas de amostra curta (ex.: medidor de interesse) deixavam
   o card estourar para cima e invadir o conteúdo anterior. */
.paywall-zone { position: relative; min-height: 260px; }
/* ads-B6: a zona é quem reserva a altura (o card é absolute, ancorado no rodapé
   dela). Com a terceira porta o card cresce ~110px e estouraria PARA CIMA,
   invadindo o conteúdo anterior — o mesmo defeito que criou o min-height acima.
   O :has restringe a folga aos muros que de fato ganharam a porta: logado, ou
   portão newsletter_ativa desligado, a altura antiga continua valendo.
   Fica ANTES do @media de 640px de propósito — media query não muda
   especificidade, então a ordem no arquivo é o que deixa o override mobile
   vencer. */
.paywall-zone:has(.paywall-porta) { min-height: 380px; }
/* ESQUADRÃO FICHA: o muro que NOMEIA a empresa e enumera o fechado cresce ~250px
   (linha do sujeito + rótulo + até 4 itens + CTA nominal que quebra em 2 linhas).
   Mesma mecânica dos dois min-height acima — o card é `position:absolute`
   ancorado no rodapé da zona, então tudo o que ele ganha de altura sobe. Os dois
   seletores encadeados (:has + :has) têm especificidade 0,3,0 e vencem o 0,2,0
   da linha da porta, independentemente da ordem.

   OS NÚMEROS SÃO MEDIDOS, não estimados (Chrome, 712px e 375px, com a folha
   real): card + `bottom` = altura que a zona precisa para conter o cartão.
     desktop  sem porta 505 (típico) / 597 (nome longo + 4 itens) → 540
     desktop  com porta 641 (típico) / 733 (pior)                 → 660
     mobile   sem porta 690 / 781                                 → 730
     mobile   com porta 937 / 1057                                → 980
   A régua é o COMPORTAMENTO DE HOJE: o muro atual já sobe ~90px sobre o
   esqueleto borrado de propósito (é o que a .paywall-fade existe para cobrir).
   Cada valor acima contém o cartão TÍPICO inteiro e, no pior caso, sobe MENOS
   que os 98px do muro sem esta lista — ou seja, nenhuma regressão. */
.paywall-zone:has(.paywall-fechado) { min-height: 540px; }
.paywall-zone:has(.paywall-fechado):has(.paywall-porta) { min-height: 660px; }
.paywall-fade {
  position: absolute; inset: auto 0 0 0; height: 240px;
  background: linear-gradient(180deg, rgba(255,255,255,0) 0%, var(--pc-bg-0) 78%);
  pointer-events: none; z-index: 1;
}
.paywall-card {
  position: absolute; left: 50%; bottom: var(--sp-6); transform: translateX(-50%);
  background: var(--pc-bg-0); border: 1px solid var(--pc-gold-300); border-radius: var(--r-xl);
  box-shadow: var(--shadow-4); padding: var(--sp-6) var(--sp-8); text-align: center;
  width: min(500px, calc(100% - var(--sp-8)));
  z-index: 2; /* nenhum sibling pinta por cima do overlay opaco */
}
/* Mobile: o card empilha CTAs e cresce — a zona acompanha */
@media (max-width: 640px) {
  .paywall-zone { min-height: 500px; }
  .paywall-zone:has(.paywall-porta) { min-height: 660px; }
  .paywall-zone:has(.paywall-fechado) { min-height: 730px; }
  .paywall-zone:has(.paywall-fechado):has(.paywall-porta) { min-height: 980px; }
  .paywall-card .flex { flex-wrap: wrap; justify-content: center; }
}
.paywall-card .lock { color: var(--pc-gold-600); margin: 0 auto var(--sp-3); width: 28px; height: 28px; }
.paywall-card h4 { margin-bottom: var(--sp-1); }
.paywall-card p { font-size: var(--fs-sm); color: var(--pc-ink-500); margin-bottom: var(--sp-4); }
/* ── ESQUADRÃO FICHA ─────────────────────────────────────────────────────────
   A EMPRESA DITA DE VOLTA. Fica logo abaixo do título e acima do resumo: é a
   linha que prova que a página sabe qual CNPJ o leitor digitou. O nome vem em
   ink-900 porque é ele, não a frase, que a pessoa procura na tela. */
.paywall-card .paywall-sujeito { margin-bottom: var(--sp-3); color: var(--pc-ink-500); }
.paywall-card .paywall-sujeito strong { color: var(--pc-ink-900); font-weight: 650; }
/* O QUE ESTÁ FECHADO: lista à ESQUERDA dentro de um card centrado. Enumeração
   se lê em coluna — centralizar itens de comprimento diferente faz o olho
   procurar o início de cada linha. max-width em ch para a medida de leitura
   não estourar junto com a largura do card. */
.paywall-fechado { text-align: left; margin: 0 auto var(--sp-4); max-width: 40ch; }
.paywall-fechado__rot {
  display: block; font-size: var(--fs-xs); text-transform: uppercase;
  letter-spacing: 0.06em; color: var(--pc-ink-400); margin-bottom: var(--sp-2);
  font-weight: 600;
}
.paywall-fechado ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.paywall-fechado li {
  font-size: var(--fs-sm); color: var(--pc-ink-500); line-height: 1.35;
  padding-left: 18px; position: relative;
}
/* Marcador quadrado dourado — o dourado do design system é reservado a
   paywall/planos/premium, e aqui ele marca exatamente isso. */
.paywall-fechado li::before {
  content: ""; position: absolute; left: 2px; top: 0.52em;
  width: 6px; height: 6px; border-radius: 2px; background: var(--pc-gold-300);
}
.paywall-fechado li b { color: var(--pc-ink-900); font-weight: 650; }
/* CTA NOMINAL ("Abrir o quadro completo da Atma Participações"): `.btn` é
   `white-space: nowrap` com altura fixa de 42px — o rótulo com nome de empresa
   atravessaria o card de 500px e a tela do celular. Só dentro do paywall. */
.paywall-card .btn-nominal {
  white-space: normal; height: auto; min-height: 42px;
  padding-top: 9px; padding-bottom: 9px; line-height: 1.25;
  max-width: 100%; text-align: center;
}
/* Terceira porta (ads-B6): DEPOIS dos botões, alinhada à esquerda e em corpo
   menor — é a saída de quem não vai comprar hoje, não uma terceira oferta
   disputando atenção com o CTA pago. */
.paywall-porta { margin-top: var(--sp-4); padding-top: var(--sp-4); border-top: var(--hairline); text-align: left; }
.paywall-card .paywall-porta__copy { font-size: var(--fs-xs); color: var(--pc-ink-500); margin-bottom: var(--sp-2); }
.paywall-porta form { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.paywall-porta .input { flex: 1 1 200px; min-width: 0; }

/* ============================== Formulários */
.field { margin-bottom: var(--sp-5); }
.field label { display: block; font-size: var(--fs-sm); font-weight: 600; color: var(--pc-ink-700); margin-bottom: var(--sp-2); }
.field .help, .form-busca > .help { font-size: var(--fs-xs); color: var(--pc-ink-400); margin-top: var(--sp-1); }
/* Busca em linha (campo + botão + linha de ajuda). O botão precisa alinhar pela
   BARRA: com flex + align-items:flex-end ele alinhava pelo fim do .field, que
   inclui o .help, e ficava ~20px abaixo do input. No grid a ajuda cai numa 2ª
   linha, fora do eixo que alinha o botão. */
.form-busca { display: grid; grid-template-columns: 1fr auto; column-gap: var(--sp-3); align-items: end; }
.form-busca .field { margin-bottom: 0; }
.form-busca > .help { grid-column: 1; }
.field .error-msg { font-size: var(--fs-sm); color: var(--pc-danger-700); margin-top: var(--sp-1); }
.input, select.input, textarea.input {
  width: 100%; height: 42px; padding: 0 var(--sp-4); background: var(--pc-bg-0);
  border: var(--hairline-strong); border-radius: var(--r-md); color: var(--pc-ink-900);
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
textarea.input { height: auto; min-height: 110px; padding: var(--sp-3) var(--sp-4); resize: vertical; }
.input:focus { outline: none; border-color: var(--pc-petrol-600); box-shadow: var(--ring-focus); }
.input.is-invalid { border-color: var(--pc-danger-600); }
.input.mono { font-family: var(--font-mono); }
.input::placeholder { color: var(--pc-ink-400); }

/* ============================== Botões */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  height: 42px; padding: 0 var(--sp-5); border-radius: var(--r-md); border: 1px solid transparent;
  font-weight: 600; font-size: var(--fs-body); cursor: pointer; white-space: nowrap;
  text-decoration: none;
  transition: background-color var(--t-fast), border-color var(--t-fast),
              color var(--t-fast), transform var(--t-fast), box-shadow var(--t-fast);
}
.btn:hover { text-decoration: none; transform: translateY(-1px); }
.btn:active { transform: translateY(0); transition-duration: 80ms; }
.btn-primary { background: var(--pc-petrol-800); color: #fff; box-shadow: var(--shadow-1); }
.btn-primary:hover { background: var(--pc-petrol-700); box-shadow: var(--shadow-2); }
.btn-primary:active { background: var(--pc-petrol-900); }
.btn-secondary { background: var(--pc-bg-0); border-color: var(--pc-line-200); color: var(--pc-ink-700); box-shadow: var(--shadow-1); }
.btn-secondary:hover { border-color: var(--pc-petrol-400); color: var(--pc-petrol-800); }
.btn-ghost { background: none; color: var(--pc-petrol-700); }
.btn-ghost:hover { background: var(--pc-petrol-50); }
/* ghost sobre superfície escura (hero/footer) — contraste AA */
.surface-dark .btn-ghost, .section-dark .btn-ghost, .hero .btn-ghost { color: var(--pc-petrol-200); }
.surface-dark .btn-ghost:hover, .section-dark .btn-ghost:hover, .hero .btn-ghost:hover { background: rgba(255,255,255,.08); color: #fff; }
/* primário sobre escuro: inverte para não sumir */
.surface-dark .btn-primary, .section-dark .btn-primary, .hero .btn-primary {
  background: #fff; color: var(--pc-petrol-900);
}
.surface-dark .btn-primary:hover, .section-dark .btn-primary:hover, .hero .btn-primary:hover {
  background: var(--pc-petrol-100); color: var(--pc-petrol-950);
}
/* Mobile: quando os CTAs do hero empilham, o botão fantasma (sem caixa
   visível) perde o padding lateral — o rótulo alinha ao MESMO eixo esquerdo
   do botão primário, em vez de criar um segundo eixo de alinhamento */
@media (max-width: 480px) {
  .hero .flex > .btn-ghost, .hero .hero-actions .btn-ghost { padding-left: 0; padding-right: 0; }
  /* Rótulo longo quebra dentro do botão (só no conteúdo — o CTA do header
     depende do nowrap para não comprimir): o nowrap alargaria o card/página
     além da tela; botões de 1 linha permanecem idênticos (min-height) */
  main .btn {
    white-space: normal; height: auto; min-height: 42px;
    padding-top: var(--sp-2); padding-bottom: var(--sp-2); text-align: center;
  }
  main .btn-sm { min-height: 34px; }
  main .btn-lg { min-height: 50px; }
}

/* ALVO DE TOQUE. 42px é ritmo de desktop, onde o ponteiro é fino e a régua não
   se aplica; no dedo faltavam 2px para os 44×44 da HIG/WCAG 2.5.5 — e eram 42px
   em TODOS os CTAs da home. Escopado em `pointer: coarse` para não mexer em um
   pixel da geometria do desktop. `main .btn` precisa estar no seletor E depois
   da media query acima: a regra de quebra de rótulo declara min-height:42px com
   especificidade (0,1,1) e venceria um `.btn` solitário. .link-arrow e
   .footer-consent-link entram porque medem 20,8 e 17,6px de altura — abaixo dos
   24×24 que a WCAG 2.2 AA (2.5.8) exige até de ponteiro fino. */
@media (pointer: coarse) {
  .btn, main .btn { min-height: 44px; }
  .link-arrow { min-height: 44px; }
  .footer-consent-link { min-height: 44px; }
  /* O .nav-toggle ficou de fora da varredura porque nao e .btn: e o <button>
     do menu sanduiche, declarado 40x40 em linha 293 com min-height:auto. E o
     UNICO caminho para qualquer outra pagina no celular — todo o resto do
     cabecalho ja subiu para 44. Medido em 375px/pointer:coarse: 40x40.
     min-width entra junto porque a largura tambem e 40, e a regra de altura
     sozinha deixaria um alvo 44x40. */
  .nav-toggle { min-height: 44px; min-width: 44px; }
}
.btn-danger { background: var(--pc-danger-600); color: #fff; }
.btn-danger:hover { background: var(--pc-danger-700); }
.btn-premium { background: var(--pc-gold-600); color: #231A05; box-shadow: var(--shadow-1); }
.btn-premium:hover { background: var(--pc-gold-500); box-shadow: var(--shadow-2); }
.btn-sm { height: 34px; padding: 0 var(--sp-3); font-size: var(--fs-sm); }
.btn-lg { height: 50px; padding: 0 var(--sp-8); font-size: var(--fs-h4); border-radius: var(--r-lg); }
.btn[disabled] { opacity: .55; cursor: not-allowed; transform: none; }

/* ============================== Breadcrumbs */
.breadcrumbs { font-size: var(--fs-sm); color: var(--pc-ink-400); padding: var(--sp-4) 0; }
.breadcrumbs a { color: var(--pc-ink-400); }
.breadcrumbs a:hover { color: var(--pc-petrol-600); text-decoration: none; }
.breadcrumbs .sep { margin: 0 var(--sp-2); color: var(--pc-ink-300); }
.breadcrumbs .cur { color: var(--pc-ink-700); }

/* ============================== Área logada: shell + sidebar */
.app-shell { display: flex; min-height: 100vh; }
.app-sidebar {
  width: 252px; flex-shrink: 0; background: var(--pc-dark-bg); color: var(--pc-dark-text-dim);
  display: flex; flex-direction: column; position: sticky; top: 0; height: 100vh; overflow-y: auto;
}
.app-sidebar .brand { color: #fff; padding: var(--sp-6) var(--sp-5) var(--sp-4); font-size: 1.1rem; }
/* ---- Topo da coluna: marca + botão de ocultar (canto superior direito).
   GRUDADO no alto: o menu do /painel tem sete seções e ultrapassa a janela em
   telas baixas, e um controle que rola para fora de vista é um controle que o
   cliente procura. O fundo opaco é o que impede os links de aparecerem por
   baixo enquanto a lista corre. */
.app-sidebar .side-topo {
  display: flex; align-items: center; justify-content: space-between;
  position: sticky; top: 0; z-index: 2; background: var(--pc-dark-bg);
  padding-right: var(--sp-3);
}
.app-sidebar .side-topo .brand { padding-right: var(--sp-2); }
.side-toggle {
  display: none; /* sem JS não há volta: o botão só existe com `html.js` */
  align-items: center; justify-content: center; flex-shrink: 0;
  width: 32px; height: 32px; padding: 0; margin: 0;
  border: 0; border-radius: var(--r-full); background: transparent;
  color: var(--pc-dark-text-dim); cursor: pointer;
  -webkit-appearance: none; appearance: none;
  transition: background-color var(--t-fast), color var(--t-fast);
}
.js .side-toggle { display: inline-flex; }
.side-toggle svg { width: 19px; height: 19px; }
.side-toggle:hover { background: rgba(255,255,255,.08); color: #fff; }
/* Anel de foco CLARO: o --ring-focus do site é petróleo, e sobre a coluna
   escura ele desaparece justamente para quem navega pelo teclado. */
.side-toggle:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(255,255,255,.45); }
/* Rótulo de seção em dourado (mesmo tom do atalho "Admin" no topo do /painel):
   é o que separa os blocos do menu, e no cinza-dim ele se confundia com os
   próprios links. Sem opacidade reduzida — o dourado já é o degrau de hierarquia. */
.app-sidebar .nav-section { padding: var(--sp-5) var(--sp-5) var(--sp-2); font-size: var(--fs-xs); font-weight: 650; text-transform: uppercase; letter-spacing: .1em; color: var(--pc-gold-300); }
.app-sidebar a.side-link {
  display: flex; align-items: center; gap: var(--sp-2); padding: var(--sp-2) var(--sp-5);
  color: var(--pc-dark-text-dim); font-size: var(--fs-sm); border-left: 3px solid transparent;
  transition: background-color var(--t-fast), color var(--t-fast), border-color var(--t-fast);
}
.app-sidebar a.side-link:hover { color: var(--pc-dark-text); text-decoration: none; background: rgba(255,255,255,.05); }
.app-sidebar a.side-link.active { background: var(--pc-dark-bg-elev); color: #fff; border-left-color: var(--pc-gold-500); }
.app-sidebar .side-footer { margin-top: auto; padding: var(--sp-4) var(--sp-5); border-top: 1px solid var(--pc-dark-line); font-size: var(--fs-xs); }
.app-sidebar .side-footer a { color: var(--pc-petrol-200); }
.app-sidebar .side-footer a:hover { color: #fff; }

/* ---- CONTRATAR: os itens de compra do menu (layouts/app.php).
   DUAS LINHAS, não uma: nome em cima e preço embaixo. `.side-link` é uma linha
   flex centrada, e com os dois textos lado a lado o preço disputava a largura
   com o nome do produto — numa coluna de 252px "Acompanhamento de Processo"
   sozinho já ocupa duas linhas. O preço é o número que decide o clique; ele
   precisa de linha própria. */
.app-sidebar a.side-link--contratar { flex-direction: column; align-items: flex-start; gap: 2px; padding-top: var(--sp-2); padding-bottom: var(--sp-2); }
.app-sidebar .side-oferta__nome { line-height: 1.25; }
.app-sidebar .side-oferta__preco { font-size: var(--fs-xs); color: var(--pc-gold-300); }
/* "em teste" é ESTADO, não desconto: o mesmo dourado do prazo da degustação na
   faixa do topo, para as duas peças se lerem como a mesma informação. */
.app-sidebar .side-oferta__tag {
  display: inline-block; margin-right: var(--sp-1); padding: 0 5px;
  border: 1px solid var(--pc-gold-500); border-radius: var(--r-sm, 4px);
  font-size: 10px; text-transform: uppercase; letter-spacing: .06em; color: var(--pc-gold-300);
}
/* O BOTÃO SÓLIDO DO RODAPÉ — dourado, e isso foi medido, não escolhido por
   gosto: `.btn-primary` é petróleo-800 (#103C43) e a coluna é petróleo-900
   (#0B2B30), 1,37:1 de contraste entre a superfície do botão e o fundo. O
   rótulo branco continuava legível, mas a FORMA do botão sumia — virava uma
   mancha um tom mais clara, que é o oposto de "sólido". O dourado da marca dá
   5,6:1 contra a mesma coluna, e é a cor que a sidebar já usa para chamar
   atenção (rótulos de seção, borda do item ativo, atalho do admin) e que a casa
   reserva para comércio. Texto escuro sobre ele, pelos mesmos 5,6:1.
   Largura cheia: meio-botão encostado na borda de uma coluna escura lê-se como
   sobra de layout. */
/* O seletor carrega `.side-footer a` de propósito: a regra vizinha
   `.app-sidebar .side-footer a { color: var(--pc-petrol-200) }` tem
   especificidade 0,2,1 e vencia um `.app-sidebar .side-cta` (0,2,0) — o botão
   saía dourado com letra azul-clara, 2,1:1, ilegível. */
.app-sidebar .side-footer a.side-cta {
  display: block; width: 100%; text-align: center; margin-bottom: var(--sp-3);
  background: var(--pc-gold-500); color: var(--pc-petrol-900); border-color: var(--pc-gold-500);
  font-weight: 650;
}
.app-sidebar .side-footer a.side-cta:hover { background: var(--pc-gold-300); color: var(--pc-petrol-900); }
.app-sidebar .side-footer a.side-cta:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(255,255,255,.45); }

/* ---- "Mais opções": só existe no celular E só com JS (ver a faixa ≤1024px). */
.side-mais { display: none; }
.app-main { flex: 1; min-width: 0; padding: var(--sp-8); max-width: 1440px; }
.app-topbar { display: flex; justify-content: space-between; align-items: center; gap: var(--sp-4); margin-bottom: var(--sp-6); }

/* ---- MENU OCULTO. A classe vem do SERVIDOR, no <html> (layouts/app.php lê o
   cookie `pc_menu`), então a coluna já nasce fora — nada de 252px pintados e
   apagados a cada página para quem escolheu escondê-la. Tudo aqui exige `.js`
   junto: sem JS não existe o botão da volta, e um menu sumido sem volta é uma
   navegação trancada.

   `display:none` e não largura zero: some do fluxo E do tabulador de uma vez —
   menu invisível que ainda recebe foco é a armadilha clássica deste controle.
   Por isso também não há animação: o que sairia deslizando é justamente o que
   precisa deixar de existir. */
.js.menu-oculto .app-sidebar { display: none; }
/* A CALHA do botão da volta. Ele é fixo (acompanha a rolagem, sempre alcançável)
   e o <main> abre espaço à esquerda para ele — flutuar por cima do texto seria
   trocar 252px de menu por um pedaço de conteúdo tapado. */
.js.menu-oculto .app-main { padding-left: 68px; }
.menu-mostrar {
  display: none; /* só com o menu oculto — e só com JS */
  position: fixed; top: var(--sp-4); left: var(--sp-4); z-index: 60;
  align-items: center; justify-content: center;
  width: 36px; height: 36px; padding: 0;
  border: 1px solid var(--pc-line-200); border-radius: var(--r-md);
  background: var(--pc-bg-0); color: var(--pc-ink-500);
  box-shadow: var(--shadow-2); cursor: pointer;
  -webkit-appearance: none; appearance: none;
  transition: color var(--t-fast), border-color var(--t-fast);
}
.js.menu-oculto .menu-mostrar { display: inline-flex; }
.menu-mostrar svg { width: 20px; height: 20px; }
.menu-mostrar:hover { color: var(--pc-petrol-700); border-color: var(--pc-petrol-400); }
.menu-mostrar:focus-visible { outline: none; box-shadow: var(--ring-focus); }
@media (prefers-reduced-motion: reduce) { .side-toggle, .menu-mostrar { transition: none; } }

@media (max-width: 1024px) {
  .app-shell { display: block; }
  .app-sidebar { width: 100%; height: auto; position: static; flex-direction: row; flex-wrap: wrap; align-items: center; }
  /* Barra horizontal: o topo vira só mais um item da fila e o grudar não faz
     sentido nenhum (grudaria na janela, com a marca flutuando sobre a página). */
  .app-sidebar .side-topo { position: static; }
  .app-sidebar .nav-section { display: none; }
  .app-sidebar a.side-link { border-left: 0; border-bottom: 3px solid transparent; }
  .app-sidebar a.side-link.active { border-bottom-color: var(--pc-gold-500); }
  .app-sidebar .side-footer { margin: 0; border: 0; margin-left: auto; }
  .app-main { padding: var(--sp-4); }
  .menu-mostrar { top: var(--sp-3); left: var(--sp-3); }
  .js.menu-oculto .app-main { padding-left: 60px; }

  /* ---- MENU COLAPSADO (celular). O problema medido: com os rótulos de seção
     ocultos (regra acima), quatorze links caem numa fileira única sem
     hierarquia — "Início Estudos Alertas de Insolvência Alertas de CNPJs
     Acompanhamento de Processo Processos Empresas Credores Avaliações
     recebidas Relatórios API Financeiro e pedidos Usuários Suporte" —, e achar
     qualquer um deles é varrer a barra inteira.

     O que sobra colapsado responde às três perguntas do momento: onde é a
     saída (Início), onde eu estou (o serviço ativo) e o que eu posso comprar
     (CONTRATAR). O resto entra pelo botão "Mais opções", e ao abrir os RÓTULOS
     DE SEÇÃO voltam — é a hierarquia do desktop, empilhada.

     TUDO ancorado em `html.js`, pela mesma razão do menu que se esconde: sem
     JS não há botão para reabrir, e um link que some sem volta é navegação
     trancada. Sem JS a barra continua exatamente como era. */
  .js .app-sidebar a.side-link { display: none; }
  .js .app-sidebar a.side-link.active,
  .js .app-sidebar a.side-link[data-side-fixo],
  .js .app-sidebar a.side-link--admin { display: flex; }
  .js .app-sidebar.is-expandido a.side-link { display: flex; }

  /* CONTRATAR NO CELULAR É O BOTÃO SÓLIDO, não a lista de produtos — e isto foi
     MEDIDO, não estimado: numa tela de 375×812 a coluna recolhida com as quatro
     ofertas (nome + preço, duas linhas cada) ocupava 465px, 57% da janela, antes
     de o conteúdo começar. Sem elas são 245px. Manter a vitrine inteira acima da
     dobra em toda página do painel não é vender mais, é empurrar o trabalho do
     cliente para fora da tela.
     A porta de compra continua VISÍVEL o tempo todo: `.side-cta` no rodapé, que
     leva à vitrine com os quatro serviços. A lista por produto volta inteira —
     com preço e com o rótulo da seção — assim que o menu é aberto. */
  .js .app-sidebar:not(.is-expandido) a.side-link--contratar { display: none; }
  .js .app-sidebar.is-expandido { flex-direction: column; align-items: stretch; }
  .js .app-sidebar.is-expandido .nav-section { display: block; }
  .js .app-sidebar.is-expandido .side-topo,
  .js .app-sidebar.is-expandido .side-footer { width: 100%; margin-left: 0; }

  /* O botão fica no fim da fila colapsada e vira largura cheia quando o menu
     está aberto — ali ele é o "fechar", e um alvo estreito no meio de uma
     coluna longa é o alvo que ninguém acha. */
  .js .side-mais {
    display: inline-flex; align-items: center; gap: var(--sp-1);
    margin: 0 var(--sp-3); padding: var(--sp-2) var(--sp-3);
    border: 1px solid var(--pc-dark-line); border-radius: var(--r-md);
    background: transparent; color: var(--pc-dark-text-dim);
    font-size: var(--fs-sm); font-family: inherit; cursor: pointer;
    -webkit-appearance: none; appearance: none;
  }
  .js .side-mais:hover { color: #fff; background: rgba(255,255,255,.06); }
  .js .side-mais:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(255,255,255,.45); }
  .js .app-sidebar.is-expandido .side-mais { align-self: flex-start; }
  .js .app-sidebar.is-expandido .side-mais__seta { transform: rotate(180deg); }
  .side-mais__seta { display: inline-block; line-height: 1; }
  /* O rodapé recolhido não pode roubar a fila: no colapsado ele é só o botão de
     compra e o nome, empurrados para a direita pela regra `margin-left:auto`. */
  /* `.side-footer a.side-cta` também aqui: a regra de cor do rodapé obrigou o
     bloco de cima a essa especificidade (0,3,1), e um seletor mais fraco nesta
     faixa perderia para ele — o botão ficaria de largura cheia dentro da barra
     horizontal, empurrando a fila. */
  .js .app-sidebar .side-footer a.side-cta { display: inline-block; width: auto; margin-bottom: 0; }
  .js .app-sidebar.is-expandido .side-footer a.side-cta { display: block; width: 100%; margin-bottom: var(--sp-3); }
}
/* No papel o menu não é navegação, é ruído: a página impressa sai sem os dois
   botões e sem a calha reservada para eles. DEPOIS da faixa de ≤1024px de
   propósito: uma folha A4 tem ~794px de largura em CSS, então aquela faixa vale
   na impressão e reporia a calha se esta regra viesse antes. */
@media print {
  .side-toggle, .menu-mostrar, .side-mais { display: none !important; }
  .js.menu-oculto .app-main { padding-left: var(--sp-8); }
  /* A folha A4 cai dentro da faixa de ≤1024px, e lá o menu se COLAPSA (só
     Início, o serviço ativo e CONTRATAR). No papel isso seria uma mudança
     silenciosa em toda página do painel já existente — o menu impresso volta
     inteiro, como sempre foi. Quem não quer menu no papel esconde a coluna na
     própria folha de estilo da tela (ver pages/alertas-resumo.css). */
  .js .app-sidebar a.side-link { display: flex; }
}

/* ============================== Tabs */
/* Seletor de abas no padrão "primary tab" do Material 3 / Cloud Console:
   régua contínua + superfície de estado por aba + indicador de 3px apoiado na régua.
   Marcação server-rendered, INALTERADA (5 telas): .tabs > a[.active] > span.count.
   São <a> de navegação por querystring — nada aqui depende de estado que o CSS não
   enxergue: a fonte de verdade é a classe .active do servidor. [aria-current="page"]
   é aceito como sinônimo, mas é OPCIONAL: sem ele tudo funciona igual. */
.tabs {
  /* knobs: a densidade inteira se ajusta por aqui */
  --tab-h: 48px;                 /* alvo de toque M3; mantido também no mobile */
  --tab-pad-x: var(--sp-4);
  --tab-ind: 3px;
  /* Folga em volta do scrollport. O clipping do overflow acontece na PADDING BOX,
     então é este 4px que impede o --ring-focus (spread 3px) de ser cortado. Se algum
     dia o token do anel passar de 3px, este valor precisa subir junto. */
  --tab-gutter: var(--sp-1);

  display: flex;
  align-items: stretch;          /* todas as abas com a mesma altura */
  gap: var(--sp-1);              /* separa as superfícies: lê como segmentos, não como bloco */
  min-width: 0;                  /* apólice: se um dia o pai virar flex/grid, o scroller
                                    encolhe em vez de empurrar scroll lateral no <body> */
  max-width: 100%;
  padding: var(--tab-gutter);
  /* Só margin-bottom, NUNCA o atalho `margin`: .mt-6 (base.css) empata em
     especificidade com .tabs e perde por ordem de fonte — o atalho zeraria o
     respiro superior de /admin/alertas, que usa <div class="tabs mt-6">. */
  margin-bottom: var(--sp-6);

  /* A régua vive na BORDER box do scroller: não rola com as abas, cobre a largura
     visível inteira (2 abas não deixam linha curta) e nenhum fundo de aba a apaga. */
  border-bottom: var(--hairline-strong);

  overflow-x: auto;
  overflow-y: hidden;            /* overflow-x:auto forçaria 'auto' no eixo Y (barra fantasma) */
  overscroll-behavior-x: contain; /* rolar até o fim não puxa a página nem o gesto de "voltar" */
  scroll-padding-inline: var(--tab-gutter); /* Tab do teclado não encosta a aba focada no
                                    corte do scrollport — sem isto o anel raspa em /admin/leads */
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;         /* barra clássica comeria a régua e a altura do controle */
  -ms-overflow-style: none;
}
.tabs::-webkit-scrollbar { display: none; }

/* Vários engines ignoram o padding-inline-end de um flex container que rola. Este
   espaçador é o que garante a folga do anel de foco da ÚLTIMA aba. */
.tabs::after { content: ""; flex: 0 0 var(--tab-gutter); }

/* O componente aceita DOIS portadores: <a> (aba que navega por querystring, o
   caso das 5 telas server-rendered) e <label> (aba que troca um painel na mesma
   página, presa a um <input type=radio> irmão — /painel/carteira/alertas). A
   aparência e os estados são os mesmos; o que muda é de onde vem o "ativo":
   classe do servidor no <a>, :checked do rádio no <label>. Nenhuma tela tinha
   <label> dentro de .tabs antes desta linha, então acrescentá-lo não mexe em
   nada do que já existia. */
.tabs a,
.tabs label {
  position: relative;
  /* Cria contexto de empilhamento na própria aba: o ::before (z-index:-1) pinta acima
     do fundo do <a> e abaixo do texto, sem escapar para trás de um ancestral .card. */
  isolation: isolate;
  flex: 0 0 auto;

  /* inline-flex + gap normaliza as duas marcações que coexistem: "Andamentos<span>"
     (client/processo.php, sem espaço) e "Todos <span>" (admin/*, com espaço) — em flex
     o espaço final do nó de texto é aparado. Por isso .count não usa margin-left. */
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);

  min-height: var(--tab-h);
  padding: 0 var(--tab-pad-x);
  border-radius: var(--r-sm) var(--r-sm) 0 0;

  color: var(--pc-ink-500);      /* 5,37:1 no branco; 4,79:1 sobre a própria superfície → AA */
  font-size: var(--fs-body);
  /* Peso IGUAL nos dois estados (é o que o M3 faz: muda a cor, não o type style).
     Se só a ativa fosse 600, cada navegação remediria a faixa (~1,7px por aba) e
     deslocaria lateralmente todas as abas seguintes. O estado vem de cor + superfície
     + indicador, que são os sinais fortes. */
  font-weight: 600;
  letter-spacing: .01em;
  line-height: 1.2;
  white-space: nowrap;           /* rótulo longo não quebra: quem rola é a faixa */
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
  transition: color var(--t-fast);
}
/* base.css sublinha todo a:hover — aqui não. */
.tabs a:hover, .tabs a:focus-visible { text-decoration: none; }
/* O <a> já é ponteiro por natureza; o <label> precisa dizer que é clicável. */
.tabs label { cursor: pointer; }

/* Superfície de estado (state layer M3): cor sólida de token + opacidade. Desce
   --tab-gutter além da aba para encostar na régua, sem invadir a folga do anel. */
.tabs a::before,
.tabs label::before {
  content: "";
  position: absolute;
  inset: 0 0 calc(-1 * var(--tab-gutter));
  z-index: -1;
  border-radius: inherit;
  background: var(--pc-petrol-500);
  /* Repouso tingido: é isto que faz a faixa ler como um CONTROLE já parada, em vez de
     links soltos. Fraco o bastante para o rótulo inativo continuar AA sobre --pc-bg-50. */
  opacity: .04;
  transition: opacity var(--t-fast);
  pointer-events: none;
}

/* Indicador: 3px de topo arredondado, recuado das bordas da aba, apoiado na régua.
   scaleX é ESTADO (0/1), não animação — por isso sobrevive ao reduced-motion. */
.tabs a::after,
.tabs label::after {
  content: "";
  position: absolute;
  left: var(--sp-3);
  right: var(--sp-3);
  bottom: calc(-1 * var(--tab-gutter));   /* pousa exatamente sobre a régua, sem cobri-la */
  height: var(--tab-ind);
  border-radius: var(--tab-ind) var(--tab-ind) 0 0;
  background: var(--pc-petrol-600);       /* 6,34:1 no branco → vale como indicador (1.4.11) */
  transform: scaleX(0);
  transform-origin: 50% 100%;
  transition: transform var(--t-base);
  pointer-events: none;
}

/* ---- ATIVO (classe do servidor) */
.tabs a.active,
.tabs a[aria-current="page"] { color: var(--pc-petrol-700); }   /* 8,92:1 no branco, 7,67:1 sobre o slab */
.tabs a.active::before,
.tabs a[aria-current="page"]::before { opacity: .12; }
.tabs a.active::after,
.tabs a[aria-current="page"]::after { transform: scaleX(1); }

/* ---- Hover só onde hover existe (evita estado grudado no toque).
   Este bloco vem DEPOIS do ativo de propósito: .tabs a:hover::before empata em
   especificidade com .tabs a.active::before e venceria por ordem — as regras
   .active:hover abaixo são a rede de proteção. Não reordenar. */
@media (hover: hover) {
  .tabs a:hover, .tabs label:hover { color: var(--pc-ink-900); }
  .tabs a:hover::before, .tabs label:hover::before { opacity: .10; }
  .tabs a:hover .count,
  .tabs label:hover .count { background: var(--pc-petrol-200); color: var(--pc-petrol-900); }  /* 10,3:1 */

  .tabs a.active:hover,
  .tabs a[aria-current="page"]:hover { color: var(--pc-petrol-800); }
  .tabs a.active:hover::before,
  .tabs a[aria-current="page"]:hover::before { opacity: .16; }
  .tabs a.active:hover .count,
  .tabs a[aria-current="page"]:hover .count { background: var(--pc-petrol-700); color: var(--pc-bg-0); }  /* 8,9:1 */
}
/* Sem indicador-fantasma no hover das inativas: uma barra visível numa aba não
   selecionada é ambígua ("esta também está ativa?"). A affordance é o slab que
   escurece + o rótulo indo para ink-900. */

/* :active = clique (não confundir com a classe .active) */
.tabs a:active::before, .tabs label:active::before { opacity: .16; }

/* ---- Foco. NÃO redeclarar box-shadow em .tabs a / .tabs a.active: o :focus-visible
   global (0,1,0) seria derrotado em silêncio. Aqui só devolvemos o formato (base.css
   força border-radius:--r-xs) e reafirmamos o anel como guarda contra regressão. */
.tabs a:focus-visible,
.tabs a.active:focus-visible,
.tabs a[aria-current="page"]:focus-visible {
  box-shadow: var(--ring-focus);
  border-radius: var(--r-sm) var(--r-sm) 0 0;
  z-index: 1;
}

/* ---- Contagem: 1 a 6 dígitos. O ativo INVERTE o preenchimento — é o único jeito de o
   badge dar sinal de estado com ≥3:1 contra o entorno; trocar um tom claro por outro
   (bg-100 → petrol-100) daria delta de 1,07:1, invisível. */
.tabs .count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--sp-5);        /* badge de 1 dígito não fica raquítico */
  min-height: var(--sp-5);
  padding: 0 var(--sp-2);
  border-radius: var(--r-full);
  /* --pc-bg-100 aqui daria 1,04:1 contra a superfície tingida da aba: a pílula
     sumiria e sobraria um número nu. line-200 é o tom neutro mais claro que ainda
     se lê como pílula sobre o slab. */
  background: var(--pc-line-200);
  color: var(--pc-ink-700);      /* 8,54:1 sobre line-200 → AA folgado em 11px */
  font-size: var(--fs-xs);
  font-weight: 600;
  line-height: 1;
  letter-spacing: 0;
  font-variant-numeric: tabular-nums;  /* 2.437 / 10.004 não dançam entre estados */
  transition: background-color var(--t-fast), color var(--t-fast);
}
.tabs a.active .count,
.tabs a[aria-current="page"] .count {
  background: var(--pc-petrol-600);
  color: var(--pc-bg-0);         /* 6,34:1 → AA; o preenchimento tem 5,14:1 contra o slab */
}

/* ---- Aba de SAÍDA (.tab-ext): não seleciona conteúdo, leva para fora (hoje: a ficha
   pública do Explorador, em /painel/processos/{cnj}). Dourada justamente para não ser
   lida como "quarta seção desta tela" — e sem indicador, porque indicador significa
   "você está aqui" e aqui nunca se está. Vem DEPOIS do bloco de hover para não ser
   sobrescrita por .tabs a:hover, que empata em especificidade. */
/* gold-700 daria só 4,50:1 sobre a própria superfície tingida (e ~4,1:1 no hover, que
   escurece o slab): gold-800 é o tom que mantém ≥6:1 nos TRÊS fundos — página, repouso
   e hover — sem depender de o slab estar em uma opacidade específica. */
.tabs a.tab-ext { color: var(--pc-gold-800); }        /* 7,30:1 no bg-50; 6,1:1 no pior caso */
.tabs a.tab-ext::before { background: var(--pc-gold-600); opacity: .10; }  /* mais presente que
                                    o repouso .04 das outras: a aba precisa se destacar parada */
.tabs a.tab-ext::after { display: none; }             /* nunca ganha o indicador de ativo */
.tabs a.tab-ext .tab-ext-ico { width: 1em; height: 1em; opacity: .8; flex: 0 0 auto; }

@media (hover: hover) {
  .tabs a.tab-ext:hover { color: var(--pc-gold-800); }
  .tabs a.tab-ext:hover::before { opacity: .18; }
}
.tabs a.tab-ext:active::before { opacity: .24; }

@media (forced-colors: active) {
  .tabs a.tab-ext { color: LinkText; }
}

/* ---- Densidade adaptativa: conta ESTRUTURA (nº de filhos), nunca estado — por isso
   este :has() é legítimo. Sem ele as ~8 abas de /admin/leads já rolam a 1280px.
   Em navegador sem :has() degrada em silêncio: apenas volta a rolar. */
@supports selector(:has(*)) {
  /* Só o padding: o gap fica, senão as superfícies se fundem num bloco só e a
     faixa perde a leitura de segmentos justamente onde há mais abas. */
  .tabs:has(> a:nth-child(6)) { --tab-pad-x: var(--sp-2); }
  .tabs:has(> a:nth-child(6)) a::after { left: var(--sp-2); right: var(--sp-2); }
}

/* ---- Mobile: aperta o padding, preserva os 48px de alvo de toque (SC 2.5.5). */
@media (max-width: 640px) {
  .tabs { --tab-pad-x: var(--sp-3); margin-bottom: var(--sp-5); }
}

/* ---- Movimento reduzido: os estados (scaleX 0/1, opacidades) continuam corretos;
   some só o movimento. Redundante com o reset global de tokens.css, mantido porque
   este bloco precisa ser autocontido. */
@media (prefers-reduced-motion: reduce) {
  .tabs a,
  .tabs a::before,
  .tabs a::after,
  .tabs .count { transition-duration: 1ms; }
}

/* ---- Windows High Contrast: background-color é forçado e box-shadow descartado, ou
   seja, slab e badge preenchido somem. Palavras-chave de cor de sistema são o único
   valor válido nesse modo (e não contam como hex cravado). */
@media (forced-colors: active) {
  .tabs a::before { display: none; }
  .tabs a.active::after,
  .tabs a[aria-current="page"]::after { background: Highlight; }
  .tabs a.active,
  .tabs a[aria-current="page"] { color: Highlight; }
  .tabs .count { border: 1px solid CanvasText; }
}

/* ============================== Alertas/avisos */
.notice { padding: var(--sp-3) var(--sp-4); border-radius: var(--r-md); font-size: var(--fs-sm); margin-bottom: var(--sp-4); border: 1px solid; }
.notice-info { background: var(--pc-info-100); color: var(--pc-info-600); border-color: #C3D9EC; }
.notice-success { background: var(--pc-success-100); color: var(--pc-success-700); border-color: #BFE3CD; }
.notice-danger { background: var(--pc-danger-100); color: var(--pc-danger-700); border-color: #F0C7C2; }
.notice-warning { background: var(--pc-warning-100); color: var(--pc-warning-700); border-color: #F3D9B8; }

/* ============================== Hero público */
.hero {
  position: relative; overflow: hidden;
  background: linear-gradient(160deg, var(--pc-petrol-950) 0%, var(--pc-petrol-900) 45%, #0E3239 100%);
  color: var(--pc-dark-text);
  padding: var(--sp-section) 0;
}
.hero > .container, .hero > .container-wide { position: relative; z-index: 1; }
/* .hero h1 / .hero .lead MOVIDOS p/ base.css (render-blocking) — evita o CLS do
   salto fs-h1→fs-display quando este arquivo (async) aplicava após o 1º paint. */
.hero a { color: var(--pc-petrol-200); }
.hero a:hover { color: #fff; }
.hero .overline { color: var(--pc-petrol-300); }
.hero .text-dim, .hero .text-faint, .hero .stamp { color: var(--pc-dark-text-dim); }
.hero .hero-actions { display: flex; gap: var(--sp-3); flex-wrap: wrap; margin-top: var(--sp-8); }
.hero-art {
  position: absolute; inset: 0; pointer-events: none; z-index: 0;
}
.hero-art svg { width: 100%; height: 100%; object-fit: cover; }

/* ============================== Páginas de erro */
.error-page { padding: clamp(80px, 10vw, 140px) 0; text-align: center; position: relative; overflow: hidden; }
.error-page .ep-code {
  font-size: clamp(6rem, 20vw, 13rem); font-weight: 700; line-height: 1;
  letter-spacing: -0.05em; color: var(--pc-petrol-100);
  user-select: none; margin-bottom: calc(-1 * var(--sp-8));
  font-variant-numeric: tabular-nums;
}
.error-page .ep-line { width: min(560px, 88%); margin: 0 auto var(--sp-8); height: auto; opacity: .8; }
.error-page h1 { font-size: var(--fs-h1); }
.error-page .lead { max-width: 52ch; margin-left: auto; margin-right: auto; }
.error-page .ep-actions { display: flex; gap: var(--sp-3); justify-content: center; flex-wrap: wrap; }

/* Plano (pricing) — os 4 cards compartilham as MESMAS linhas de base:
   slot de selo com altura reservada em todos (visibility:hidden nos sem selo),
   prefixo "a partir de" em linha própria e preço que nunca quebra no meio */
.plan-card { position: relative; display: flex; flex-direction: column; }
.plan-card.featured { border-color: var(--pc-gold-300); box-shadow: var(--shadow-3); }
.plan-card .plan-flag { height: 22px; margin-bottom: var(--sp-2); }
.plan-card .plan-flag.is-empty { visibility: hidden; }
.plan-card .plan-name { font-size: var(--fs-h3); font-weight: 700; }
.plan-card .plan-price-prefix { display: block; height: 1.2em; font-size: var(--fs-sm); color: var(--pc-ink-500); margin-top: var(--sp-2); }
.plan-card .plan-price { font-size: var(--fs-h2); font-weight: 700; margin: 0 0 var(--sp-2); font-variant-numeric: tabular-nums; letter-spacing: -0.02em; white-space: nowrap; }
.plan-card .plan-price small { font-size: var(--fs-sm); font-weight: 400; color: var(--pc-ink-500); letter-spacing: 0; }
.plan-card ul { list-style: none; padding: 0; margin: var(--sp-4) 0; flex: 1; }
.plan-card li { padding: var(--sp-1) 0; font-size: var(--fs-sm); color: var(--pc-ink-700); }
.plan-card li::before { content: "—"; color: var(--pc-petrol-400); margin-right: var(--sp-2); }

/* Selo do plano destacado: nunca estoura o card (quebra/encolhe se preciso) */
.plan-card .plan-flag { height: auto; min-height: 22px; }
.plan-card .plan-flag .tag-inline {
  white-space: normal; display: inline-block; max-width: 100%;
  line-height: 1.3; padding-top: 3px; padding-bottom: 3px;
}

/* ============================== Trilha de MARCOS (partials/marcos.php)
   Componente reutilizável (ficha, guia, serviços) → CSS GLOBAL. */
/* ============================================================ MARCOS
   Trilha do ciclo de insolvência (partials/marcos.php). Stepper vertical
   com linha conectora, nós com ícone e textos didáticos por marco. */
.marcos-wrap { display: grid; gap: var(--sp-8); }

.marcos-trilha-head { display: flex; align-items: center; gap: var(--sp-3); margin-bottom: var(--sp-5); }
.marcos-resumo-txt { font-size: var(--fs-sm); color: var(--pc-ink-400); }

/* Trilhas recolhidas (resumo) quando um tipo específico é destacado */
.marcos-trilha.is-resumo { opacity: .78; }
.marcos-trilha.is-resumo .marcos-trilha-head { margin-bottom: 0; }
.marcos-trilha.is-destaque .marcos-trilha-head .badge-rj,
.marcos-trilha.is-destaque .marcos-trilha-head [class^="badge-"] { font-size: var(--fs-sm); }

/* Stepper */
.marcos-stepper { list-style: none; margin: 0; padding: 0; }
.marcos-no {
  position: relative; display: grid;
  grid-template-columns: 40px 1fr; column-gap: var(--sp-4);
  padding-bottom: var(--sp-6);
}
.marcos-no:last-child { padding-bottom: 0; }

/* Linha conectora vertical entre os nós */
.marcos-conector {
  position: absolute; left: 19px; top: 40px; bottom: -2px; width: 2px;
  background: linear-gradient(var(--pc-petrol-200), var(--pc-petrol-100));
}
.marcos-no:last-child .marcos-conector { display: none; }

/* Nó (círculo com ícone) */
.marcos-nodo {
  grid-row: 1 / span 2; position: relative; z-index: 1;
  width: 40px; height: 40px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--pc-bg-0); color: var(--pc-petrol-600);
  border: 2px solid var(--pc-petrol-200);
  box-shadow: 0 0 0 4px var(--pc-bg-0);
  transition: border-color var(--t-base), color var(--t-base), transform var(--t-base);
}
.marcos-no:hover .marcos-nodo { border-color: var(--pc-petrol-500); transform: scale(1.06); }
.marcos-nodo .icn { width: 20px; height: 20px; }

/* Corpo textual do marco */
.marcos-corpo { min-width: 0; padding-top: var(--sp-1); }
.marcos-titulo { font-weight: 600; color: var(--pc-ink-900); }
.marcos-oque { margin: var(--sp-1) 0 0; color: var(--pc-ink-500); font-size: var(--fs-sm); max-width: 62ch; }
.marcos-credor, .marcos-recebe {
  margin: var(--sp-2) 0 0; color: var(--pc-ink-700); font-size: var(--fs-sm); max-width: 62ch;
}
.marcos-lbl {
  display: inline-block; margin-right: var(--sp-2);
  font-family: var(--font-mono); font-size: var(--fs-xs); letter-spacing: .04em;
  text-transform: uppercase; color: var(--pc-petrol-600);
  border: var(--hairline); border-radius: var(--r-sm); padding: 1px 6px;
  vertical-align: 1px;
}
.marcos-lbl-recebe { color: var(--pc-gold-700); border-color: var(--pc-gold-300); background: var(--pc-gold-50); }

/* Versão compacta (ficha da empresa): fila horizontal só com rótulos */
.marcos-compacto .marcos-wrap,
.marcos-wrap.marcos-compacto { gap: var(--sp-6); }
.marcos-compacto .marcos-stepper {
  display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-5);
}
.marcos-compacto .marcos-no {
  grid-template-columns: 32px auto; column-gap: var(--sp-2);
  padding-bottom: 0; align-items: center;
}
.marcos-compacto .marcos-conector {
  left: auto; right: calc(var(--sp-5) * -.5); top: 50%; bottom: auto;
  width: var(--sp-3); height: 2px;
}
.marcos-compacto .marcos-nodo { grid-row: auto; width: 32px; height: 32px; box-shadow: none; }
.marcos-compacto .marcos-nodo .icn { width: 16px; height: 16px; }
.marcos-compacto .marcos-corpo { padding-top: 0; }
.marcos-compacto .marcos-titulo { font-size: var(--fs-sm); font-weight: 500; }

@media (max-width: 640px) {
  .marcos-compacto .marcos-stepper { flex-direction: column; align-items: flex-start; }
  .marcos-compacto .marcos-conector { display: none; }
}

/* Estado da trilha quando a ficha conhece o marco atual de um processo concreto
   (marcos-progresso): cumpridos preenchidos, atual em destaque, pendentes esmaecidos.
   Assim a trilha conta sozinha em que ponto o caso está. */
.marcos-progresso .marcos-no.is-feito .marcos-nodo {
  background: var(--pc-petrol-500); border-color: var(--pc-petrol-500); color: var(--pc-bg-0);
}
.marcos-progresso .marcos-no.is-feito .marcos-conector {
  background: var(--pc-petrol-400);
}
.marcos-progresso .marcos-no.is-atual .marcos-nodo {
  border-color: var(--pc-petrol-600); color: var(--pc-petrol-700);
  box-shadow: 0 0 0 4px var(--pc-bg-0), 0 0 0 6px var(--pc-petrol-200);
}
.marcos-progresso .marcos-no.is-atual .marcos-titulo { color: var(--pc-petrol-800); font-weight: 700; }
.marcos-progresso .marcos-no.is-futuro .marcos-nodo { opacity: .55; }
.marcos-progresso .marcos-no.is-futuro .marcos-titulo { color: var(--pc-ink-500); }
.marcos-tag-atual {
  display: inline-block; margin-left: var(--sp-1);
  font-family: var(--font-mono); font-size: var(--fs-xs); letter-spacing: .04em;
  text-transform: uppercase; color: var(--pc-petrol-700);
  border: 1px solid var(--pc-petrol-300); background: var(--pc-petrol-50);
  border-radius: var(--r-sm); padding: 0 6px; vertical-align: 1px;
}

/* ==============================================================================
   PROCESSO — JORNADA + ANDAMENTOS  (componentes GLOBAIS)
   ------------------------------------------------------------------------------
   Estas regras vestem partials/proc-jornada.php e partials/proc-andamentos.php,
   que a ficha pública do Explorador (/dados/empresas/…) e a aba de andamentos do
   /painel renderizam com o MESMO markup. Enquanto viveram em pages/empresa.css a
   área logada recebia a marcação sem estilo — por isso o bloco é global, e uma
   mudança aqui vale nas duas telas de uma vez.
   ============================================================================== */

/* keyframe do pulse da fase atual do stepper (reduced-motion respeitado abaixo) */
@keyframes fx-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(24,105,116,.40); }
  70%  { box-shadow: 0 0 0 7px rgba(24,105,116,0); }
  100% { box-shadow: 0 0 0 0 rgba(24,105,116,0); }
}

/* ============================== [5] PROCESSO — stepper datado + timeline scroll
   Datas sob cada nó do stepper compacto. */
.marcos-solo { /* uma trilha só — o partial já suprime as outras (soTipo) */ }
.marcos-data {
  display: block; margin-top: 2px; font-size: var(--fs-xs);
  color: var(--pc-petrol-600); font-variant-numeric: tabular-nums; font-weight: 600;
}
.marcos-progresso .marcos-no.is-futuro .marcos-data { color: var(--pc-ink-300); }
/* Nó sem data extraída na jornada: placeholder discreto (ausência = extração,
   não layout). Peso/cor menores para não competir com as datas reais. */
.marcos-data--vazia { color: var(--pc-ink-300); font-weight: 500; font-style: italic; }
/* pulse sutil na fase atual do stepper */
@media (prefers-reduced-motion: no-preference) {
  .marcos-progresso .fx-pulse-host .marcos-nodo { animation: fx-pulse 2.6s var(--ease-out) infinite; }
}

/* Andamentos numa CAIXA com scroll interno e altura fixa (pode ser enorme).
   Fundo rebaixado: cada andamento é um CARD branco — a separação entre itens
   é a moldura do card, não um hairline entre linhas. */
.fx-tl-box {
  position: relative; max-height: 420px; overflow-y: auto;
  border: var(--hairline); border-radius: var(--r-md);
  background: var(--pc-bg-50); padding: var(--sp-3) var(--sp-4);
  -webkit-overflow-scrolling: touch;
}
/* Visão de admin ("Últimos andamentos"): metade da janela — a lista pode ter
   1.000 itens e, em ordem DESC, o que interessa já está no topo. */
.fx-tl-box--compacta { max-height: 210px; }
/* fade no topo e na base indicando mais conteúdo */
.fx-tl-box::before, .fx-tl-box::after {
  content: ""; position: sticky; left: 0; right: 0; display: block; height: 14px;
  pointer-events: none; z-index: 1;
}
.fx-tl-box::before { top: calc(var(--sp-3) * -1); margin-bottom: -14px; background: linear-gradient(var(--pc-bg-50), transparent); }
.fx-tl-box::after  { bottom: calc(var(--sp-3) * -1); margin-top: -14px; background: linear-gradient(transparent, var(--pc-bg-50)); }
.fx-tl { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-2); }
.fx-tl__item {
  position: relative; display: grid;
  grid-template-columns: 22px auto 1fr; column-gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-3); align-items: baseline;
  background: var(--pc-bg-0); border: var(--hairline); border-radius: var(--r-sm);
}
/* Marco: filete petróleo à esquerda (inset — não desloca o conteúdo do card). */
.fx-tl__item.is-marco { box-shadow: inset 3px 0 0 var(--pc-petrol-500); }
.fx-tl__dot {
  grid-column: 1; width: 12px; height: 12px; border-radius: var(--r-full);
  background: var(--pc-bg-0); border: 2px solid var(--pc-petrol-300);
  align-self: start; margin-top: 3px; z-index: 1;
}
.fx-tl__item.is-marco .fx-tl__dot { background: var(--pc-petrol-500); border-color: var(--pc-petrol-500); }
.fx-tl__date {
  grid-column: 2; font-size: var(--fs-xs); font-weight: 650; white-space: nowrap;
  color: var(--pc-ink-500); font-variant-numeric: tabular-nums; align-self: start; margin-top: 2px;
}
.fx-tl__body { grid-column: 3; min-width: 0; }
.fx-tl__head { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.fx-tl__titulo { font-size: var(--fs-sm); font-weight: 650; color: var(--pc-ink-900); }
.fx-tl__classe {
  font-size: var(--fs-xs); font-weight: 600; text-transform: uppercase; letter-spacing: .04em;
  color: var(--pc-petrol-700); background: var(--pc-petrol-50);
  border: 1px solid var(--pc-petrol-200); border-radius: var(--r-sm); padding: 1px 6px;
}
.fx-tl__anexo {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: var(--fs-xs); font-weight: 600;
  color: var(--pc-gold-800); background: var(--pc-gold-50);
  border: 1px solid var(--pc-gold-300); border-radius: var(--r-sm); padding: 1px 7px;
  /* Item de um flex container: sem isto o selo ENCOLHE e quebra o próprio
     rótulo em 3 linhas em vez de descer inteiro para a linha de baixo (o
     .fx-tl__head já é flex-wrap: wrap). Aparece com "Ver documento anexado",
     que é bem mais largo que o selo inerte. */
  flex: none; white-space: nowrap;
}
.fx-tl__anexo .icn { width: 12px; height: 12px; color: var(--pc-gold-700); }
/* Selo que virou BOTÃO: na visão liberada a peça abre em nova aba. O estado
   inerte (público, sem liberação) continua sendo o <span> acima — mesma
   moldura, e é o hover/cursor que diz qual dos dois está na tela. */
a.fx-tl__anexo--link { cursor: pointer; transition: background var(--t-fast), border-color var(--t-fast); }
a.fx-tl__anexo--link:hover,
a.fx-tl__anexo--link:focus-visible {
  text-decoration: none; background: var(--pc-gold-100);
  border-color: var(--pc-gold-500); color: var(--pc-gold-800);
}
.fx-tl__desc, .fx-tl__explica { margin: 3px 0 0; font-size: var(--fs-sm); color: var(--pc-ink-500); line-height: 1.5; overflow-wrap: anywhere; }
.fx-tl__explica { color: var(--pc-ink-700); }
@media (max-width: 560px) {
  .fx-tl__item { grid-template-columns: 22px 1fr; row-gap: 2px; }
  .fx-tl__date { grid-column: 2; margin-top: 0; }
  .fx-tl__body { grid-column: 2; }
}

/* ---- Recorte "com documento" × "todos" (visão de admin) -----------------
   O recorte é PADRÃO: em mil trâmites o que se procura é a peça anexada.
   Tudo aqui é escopado em html.js — sem JS não há como voltar para "todos",
   então sem JS o recorte não acontece e a lista inteira fica na tela (a nota
   do server descreve o acervo, então continua correta nos dois casos). */
/* Título + recorte dividem a linha: o controle encosta no que ele controla e
   some da coluna de texto. O h4 zera as PRÓPRIAS margens e elas sobem para a
   faixa — senão a margem inferior dele empurraria só metade da linha. */
.fx-tl-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--sp-2) var(--sp-4); flex-wrap: wrap;
  margin: var(--pc-r-secao, var(--sp-5)) 0 var(--pc-r-bloco, var(--sp-3));
}
/* O h4 zera as PRÓPRIAS margens em qualquer superfície — senão a margem
   inferior dele empurraria só metade da linha. Os seletores mais específicos
   existem para vencer o `#processos .proc-body h4` da ficha do Explorador. */
.fx-tl-head h4 { margin: 0; }
#processos .proc-body .fx-tl-head h4,
.proc-body .fx-tl-head h4 { margin: 0; }
.fx-tl-filtro { display: none; gap: 6px; margin: 0; }
.js .fx-tl-filtro { display: flex; flex-wrap: wrap; }
.fx-tl-filtro__btn {
  display: inline-flex; align-items: center; gap: 5px; cursor: pointer;
  padding: 5px 11px; border: var(--hairline); border-radius: var(--r-full);
  background: var(--pc-bg-0); color: var(--pc-ink-500);
  font-size: var(--fs-xs); font-weight: 650; line-height: 1.4;
  transition: border-color var(--t-fast), color var(--t-fast), background var(--t-fast);
}
.fx-tl-filtro__btn .icn { width: 13px; height: 13px; color: currentColor; }
.fx-tl-filtro__btn:hover { border-color: var(--pc-petrol-400); color: var(--pc-petrol-800); }
.fx-tl-filtro__btn.is-selected {
  background: var(--pc-petrol-50); border-color: var(--pc-petrol-400); color: var(--pc-petrol-800);
}
.fx-tl-filtro__n {
  font-variant-numeric: tabular-nums; font-weight: 700;
  color: var(--pc-ink-700); background: var(--pc-bg-100);
  border-radius: var(--r-full); padding: 0 6px;
}
.fx-tl-filtro__btn.is-selected .fx-tl-filtro__n { background: var(--pc-bg-0); color: var(--pc-petrol-800); }
/* A nota não troca com o botão: ela fala do acervo, não do recorte em tela. */
.js .fx-tl-wrap.is-so-anexo .fx-tl__item:not(.is-anexo) { display: none; }

/* ---- Linha de recorte dos andamentos ------------------------------------ */
.proc-recorte {
  display: flex; align-items: flex-start; gap: var(--sp-2);
  margin: 0 0 var(--sp-4); padding: var(--sp-3) var(--sp-4);
  background: var(--pc-bg-50); border-left: 3px solid var(--pc-petrol-300);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  font-size: 0.6875rem; color: var(--pc-ink-500); line-height: 1.55;
}
.proc-recorte .icn { width: 14px; height: 14px; flex: none; color: var(--pc-petrol-600); margin-top: 2px; }
.proc-recorte strong { color: var(--pc-ink-700); font-weight: 650; }


/* ---- Jornada horizontal (marcos.php --h) ---------------------------------- */
/* A trilha compacta (components.css) é flex-wrap; aqui a viramos numa FAIXA
   horizontal com nós datados e scroll-x no mobile. Só CSS, nenhum dado novo. */
.proc-journey { position: relative; margin: 0 calc(var(--sp-1) * -1) var(--sp-2); }
/* (P4/journey) Sombras de scroll: sinalizam fases fora da janela visível.
   Gradientes sobre a moldura (não rolam com o trilho); ligados pelos flags
   .has-scroll-l/.has-scroll-r que o JS alterna no trilho. */
.proc-journey::before,
.proc-journey::after {
  content: ""; position: absolute; top: 0; bottom: var(--sp-2); width: 36px;
  pointer-events: none; opacity: 0; transition: opacity .18s ease; z-index: 2;
}
.proc-journey::before {
  left: 0;
  background: linear-gradient(to right, var(--pc-bg-0), transparent);
}
.proc-journey::after {
  right: 0;
  background: linear-gradient(to left, var(--pc-bg-0), transparent);
}
.proc-journey:has(.marcos-stepper--h.has-scroll-l)::before { opacity: 1; }
.proc-journey:has(.marcos-stepper--h.has-scroll-r)::after { opacity: 1; }
/* A jornada é SEMPRE um único trilho horizontal com scroll-x — nunca quebra em
   linhas. Como o partial roda com .marcos-compacto (que em components.css força
   flex-wrap:wrap, especificidade 0,2,0), a variante --h precisa igualar essa
   especificidade para não depender de ordem de cascata: por isso os seletores
   compostos .marcos-compacto .marcos-stepper--h abaixo. Um só padrão, decidido:
   trilho horizontal com scroll. */
.marcos-stepper--h,
.marcos-compacto .marcos-stepper--h {
  display: flex; flex-direction: row; flex-wrap: nowrap; gap: 0; align-items: flex-start;
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  padding: var(--sp-2) var(--sp-1) var(--sp-3);
}
/* A jornada NÃO pode alargar a coluna do dashboard: a faixa de scroll é o
   stepper (overflow-x:auto acima), mas os ancestrais precisam poder encolher
   abaixo do conteúdo. O bloco .marcos-trilha vem com min-width:auto (min-content
   = soma dos nós), o que abre a grade e faz a faixa passar POR BAIXO do rail.
   Travar o track em minmax(0,1fr) e o wrapper em min-width:0 mantém o trilho
   contido na coluna, com scroll-x interno. */
.proc-journey .marcos-wrap { grid-template-columns: minmax(0, 1fr); }
.proc-journey .marcos-trilha,
.proc-journey .marcos-stepper--h { min-width: 0; max-width: 100%; }
/* No mobile, components.css força .marcos-compacto .marcos-stepper a empilhar
   (flex-direction:column) — a jornada precisa continuar sendo um trilho ROW com
   scroll-x, então reafirmamos aqui (mesma especificidade, cascata posterior). */
@media (max-width: 640px) {
  .marcos-compacto .marcos-stepper--h { flex-direction: row; align-items: flex-start; }
  /* components.css esconde o conector compacto no mobile; na jornada horizontal
     ele é a própria trilha entre os nós — mantê-lo visível (exceto no último). */
  .marcos-compacto .marcos-stepper--h .marcos-conector { display: block; }
  .marcos-compacto .marcos-stepper--h .marcos-no:last-child .marcos-conector { display: none; }
}
.marcos-stepper--h .marcos-no {
  flex: 0 0 auto; width: 118px;
  display: flex; flex-direction: column; align-items: center; text-align: center;
  grid-template-columns: none; column-gap: 0; padding: 0;
}
.marcos-stepper--h .marcos-nodo { grid-row: auto; margin-bottom: var(--sp-2); }
/* conector = linha horizontal entre nós (à direita do nodo, centrada nele) */
.marcos-stepper--h .marcos-conector {
  position: absolute; left: 50%; right: auto; top: 16px; bottom: auto;
  width: 118px; height: 2px;
  background: linear-gradient(90deg, var(--pc-petrol-200), var(--pc-petrol-100));
}
.marcos-stepper--h .marcos-no:last-child .marcos-conector { display: none; }
.marcos-stepper--h .marcos-corpo { padding-top: 0; display: flex; flex-direction: column; align-items: center; gap: 2px; }
.marcos-stepper--h .marcos-titulo {
  font-size: var(--fs-xs); font-weight: 600; line-height: 1.25;
  max-width: 106px; overflow-wrap: anywhere;
}
.marcos-stepper--h .marcos-tag-atual { display: block; margin: 3px auto 0; width: fit-content; }
.marcos-stepper--h .marcos-data { margin-top: 3px; }
/* progresso na versão horizontal: conector preenchido até o atual */
.marcos-stepper--h.marcos-progresso .marcos-no.is-feito .marcos-conector { background: var(--pc-petrol-400); }

/* ---- P1: fase CONCLUÍDA = CHECK branco no nodo pintado ---------------------
   O círculo já é preenchido em petrol com color:branco; mas o dono quer um
   CHECK inequívoco de "concluído", não o ícone temático. Escondemos o ícone
   temático e desenhamos um check branco (borda rotacionada) por cima. Não
   depende de novo asset nem de ícone no sprite. Vale para a jornada horizontal
   e para qualquer .marcos-progresso (seletor independente de --h). */
.marcos-progresso .marcos-no.is-feito .marcos-nodo { position: relative; color: var(--pc-bg-0); }
.marcos-progresso .marcos-no.is-feito .marcos-nodo .icn { opacity: 0; }
.marcos-progresso .marcos-no.is-feito .marcos-nodo::after {
  content: ""; position: absolute; left: 50%; top: 45%;
  width: 30%; height: 56%;
  border: solid var(--pc-bg-0); border-width: 0 2.5px 2.5px 0;
  transform: translate(-50%, -55%) rotate(45deg);
}
/* Fase ATUAL e FUTURAS: garantir o ícone temático visível e com contraste
   (o círculo dessas fases é claro/vazado). */
.marcos-progresso .marcos-no.is-atual .marcos-nodo .icn { opacity: 1; color: var(--pc-petrol-700); }
.marcos-progresso .marcos-no.is-futuro .marcos-nodo .icn { opacity: 1; color: var(--pc-petrol-400); }
/* nó hipotético do rito (ex.: convolação) — tracejado, "possibilidade, não previsão" */
.marcos-no--hipotetico .marcos-nodo {
  background: var(--pc-bg-0); border-style: dashed; border-color: var(--pc-line-200);
  color: var(--pc-ink-300); opacity: 1;
}
.marcos-no--hipotetico .marcos-titulo { color: var(--pc-ink-400); }
@media (prefers-reduced-motion: reduce) {
  .marcos-stepper--h { scroll-behavior: auto; }
}

/* ---- Andamentos: o empty-state ilustrado (.proc-empty*) SAIU --------------
   Nenhuma marcação o produz mais: partials/proc-andamentos não rende nada com
   lista vazia e a ficha do Explorador oculta a seção inteira (03/09/2026). O
   /painel tem estado vazio próprio, e ele usa `.empty` (client/processo.php). */

/* ---- Aviso de extração pendente ------------------------------------------
   Âmbar de atenção, com filete grosso à esquerda: nada aqui está errado nem em
   risco — o caso é novo e a fila de extração ainda não chegou nele. Mora em
   components.css (e não mais na página) porque a mesma peça atende DUAS
   superfícies: a ficha pública do Explorador e a aba Credores do /painel. As
   duas dizem a mesma coisa sobre o mesmo vazio; dizer com dois desenhos
   diferentes seria dar ao cliente a impressão de que são dois problemas. A
   colagem à barra de identidade (.proc-id) é do Explorador e ficou lá. */
.proc-extracao {
  display: flex; align-items: flex-start; gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5); margin: 0 0 var(--sp-5);
  border: 1px solid #F3D9B8; border-left: 3px solid var(--pc-warning-600);
  border-radius: var(--r-md); background: var(--pc-warning-100);
}
.proc-extracao > .icn { width: 20px; height: 20px; flex: none; margin-top: 1px; color: var(--pc-warning-600); }
.proc-extracao__txt { min-width: 0; display: flex; flex-direction: column; gap: var(--sp-2); }
.proc-extracao__h { margin: 0; font-size: var(--fs-sm); font-weight: 700; color: var(--pc-warning-700); }
.proc-extracao__p { margin: 0; max-width: 82ch; font-size: var(--fs-sm); color: var(--pc-ink-700); line-height: 1.55; }
.proc-extracao__p strong { color: var(--pc-ink-900); }
.proc-extracao__cta {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: var(--sp-1) var(--sp-2);
  margin: 0; font-size: var(--fs-sm); color: var(--pc-ink-700);
}
/* Quando o CTA é um BOTÃO (aba Credores do painel, onde pedir prioridade é a
   única ação da tela) o alinhamento passa de baseline para center: contra a
   caixa de 40px do botão, a linha de base joga a nota de prazo para o meio do
   rótulo. Com o link-arrow do Explorador o baseline continua valendo. */
.proc-extracao__cta:has(.btn) { align-items: center; }
.proc-extracao__cta .link-arrow { color: var(--pc-warning-700); font-weight: 650; }
.proc-extracao__cta .link-arrow:hover { color: var(--pc-gold-800); }
.proc-extracao__nota { font-size: var(--fs-xs); color: var(--pc-ink-500); }
@media (max-width: 560px) {
  .proc-extracao { padding: var(--sp-3) var(--sp-4); }
}

/* ==============================================================================
   FAKE-BLUR de zona paga (anti-scraping) — barras-esqueleto DECORATIVAS.
   Sem texto, sem dado. Larguras de classes fixas w-1..w-5 — jamais de valor real
   (invariante PW-1). Véu + card vêm de components.css (.paywall-fade/.paywall-card).
   ============================================================================ */
.pc-blur-zone { position: relative; z-index: 0; padding: var(--sp-2) 0; user-select: none; }
.pc-blur-row {
  display: flex; gap: var(--sp-6); align-items: center;
  padding: var(--sp-3) var(--sp-1); border-bottom: var(--hairline);
}
.pc-blur-row:last-child { border-bottom: 0; }
.pc-blur-cell { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
/* timeline: 1ª coluna estreita (data), 2ª larga (corpo) */
.pc-blur-timeline .pc-blur-row .pc-blur-cell:first-child { flex: 0 0 84px; }
.pc-blur-timeline .pc-blur-row .pc-blur-cell:last-child  { flex: 1 1 auto; }
/* table: credor larga, classe estreita, valor média (à direita) */
.pc-blur-table .pc-blur-row .pc-blur-cell:nth-child(1) { flex: 1 1 auto; }
.pc-blur-table .pc-blur-row .pc-blur-cell:nth-child(2) { flex: 0 0 96px; }
.pc-blur-table .pc-blur-row .pc-blur-cell:nth-child(3) { flex: 0 0 120px; align-items: flex-end; }
/* a "barra de texto": gradiente petrol → transparente; filter:blur sela a
   estética de borrado. Não há conteúdo para desborrar. */
.pc-blur {
  display: block; height: 12px; border-radius: var(--r-full);
  background: linear-gradient(90deg,
      color-mix(in srgb, var(--pc-petrol-200) 70%, transparent) 0%,
      color-mix(in srgb, var(--pc-petrol-100) 90%, transparent) 60%,
      transparent 100%);
  filter: blur(2.5px); opacity: .85;
}
/* larguras FIXAS por classe — únicas larguras permitidas (nunca inline/derivadas) */
.pc-blur.w-1 { width: 42%; }
.pc-blur.w-2 { width: 68%; }
.pc-blur.w-3 { width: 55%; }
.pc-blur.w-4 { width: 80%; }
.pc-blur.w-5 { width: 34%; }
/* shimmer discreto (respeita reduced-motion). content vazio: nunca vira caractere */
@media (prefers-reduced-motion: no-preference) {
  .pc-blur { position: relative; overflow: hidden; }
  .pc-blur::after {
    content: ""; position: absolute; inset: 0;
    background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--pc-bg-0) 55%, transparent), transparent);
    transform: translateX(-100%); animation: pcBlurShimmer 2.4s ease-in-out infinite;
  }
  @keyframes pcBlurShimmer { to { transform: translateX(100%); } }
}
/* o fade cobre a zona-esqueleto INTEIRA (nenhuma barra nítida) */
.paywall-zone:has(.pc-blur-zone) .paywall-fade {
  inset: 0; height: auto;
  background: linear-gradient(180deg,
      color-mix(in srgb, var(--pc-bg-0) 30%, transparent) 0%,
      var(--pc-bg-0) 88%);
}


/* ============================================================ Web Push card
   Convite pré-permissão do Insolve. Injetado por /assets/js/push.js em QUALQUER
   página pública, por isso vive no components.css (global). Autossuficiente,
   tema-aware e com respeito a prefers-reduced-motion. */
.nx-pushcard{
  position:fixed; z-index:1200; right:20px; bottom:20px; width:360px; max-width:calc(100vw - 32px);
  display:flex; gap:12px; padding:16px 16px 15px; align-items:flex-start;
  background:#fff; color:#1a1c1e; border:1px solid #e7e3dc; border-radius:16px;
  box-shadow:0 18px 48px -12px rgba(30,20,10,.30), 0 4px 12px -6px rgba(30,20,10,.20);
  font-family:inherit; opacity:0; transform:translateY(14px) scale(.98);
  transition:opacity .28s ease, transform .28s cubic-bezier(.2,.8,.2,1);
}
.nx-pushcard.is-in{ opacity:1; transform:none; }
.nx-pushcard-x{
  position:absolute; top:8px; right:10px; border:0; background:transparent; cursor:pointer;
  font-size:20px; line-height:1; color:#9aa0a6; padding:4px; border-radius:6px;
}
.nx-pushcard-x:hover{ color:#5b6472; background:rgba(0,0,0,.05); }
.nx-pushcard-ico{
  flex:none; width:42px; height:42px; border-radius:11px; display:grid; place-items:center; color:#fff;
  background:linear-gradient(135deg,#C0492E,#7c2817); box-shadow:0 4px 12px -4px rgba(124,40,23,.6);
}
.nx-pushcard-head{ margin:0 14px 0 0; font-size:.98rem; font-weight:650; line-height:1.28; letter-spacing:-.01em; }
.nx-pushcard-sub{ margin:.35rem 0 0; font-size:.82rem; line-height:1.4; color:#5b6472; }
.nx-pushcard-acts{ display:flex; gap:8px; margin-top:12px; }
.nx-pushcard-yes,.nx-pushcard-no{
  font:inherit; font-size:.84rem; font-weight:600; border-radius:9px; padding:.5rem .9rem; cursor:pointer; border:1px solid transparent;
}
.nx-pushcard-yes{ background:#B23A22; color:#fff; }
.nx-pushcard-yes:hover{ background:#9a3019; }
.nx-pushcard-no{ background:transparent; color:#5b6472; border-color:#e0dcd4; }
.nx-pushcard-no:hover{ background:rgba(0,0,0,.04); color:#3a4048; }
@media (max-width:520px){
  .nx-pushcard{ right:12px; left:12px; bottom:12px; width:auto; }
}
@media (prefers-reduced-motion:reduce){
  .nx-pushcard{ transition:opacity .01s; transform:none; }
}

/* ============================== HEADER: faixa 1025–1400px
   Entre o breakpoint do drawer (1024px) e telas largas, a barra somava
   marca + busca de 244px + 5 itens de menu + Entrar + "Contratar agora" +
   a linha "ou crie uma conta gratuita" — e ESTOURAVA a viewport em 1280px,
   a resolução de laptop mais comum: o CTA principal aparecia cortado e a
   página inteira ganhava rolagem horizontal. Aqui a barra cede na ordem certa:
   primeiro a busca encolhe, depois o respiro entre itens, por último o texto
   auxiliar — o CTA nunca é sacrificado. */
/* O TETO DE 1400px CAIU (19/08). A régua de cedência não era "faixa estreita":
   era a única largura em que a barra CABIA. Medido a 1920, sem ela: os filhos do
   .site-nav pedem 829px e a barra oferece 698 — 131px de excesso que, com
   min-width:0, viravam SOBREPOSIÇÃO ("Entrar" desenhado por cima do campo de
   busca, 107px de invasão) e, sem min-width:0, empurravam o bloco Entrar · Ver
   planos 135,1px para FORA da grade de 1200px. Nenhum dos dois é aceitável, e a
   causa é a mesma nas duas: 1200px de grade não comportam a barra em tamanho
   cheio. Acima de 1400 a barra passa a ceder igual ao laptop — desenho que o
   site já servia na resolução mais comum. */
@media (min-width: 1025px) {
  .site-header .inner { gap: var(--sp-2); }
  .site-nav { gap: 0; }   /* min-width:0 subiu para a regra base (linha 26) */
  .hdr-search-field { width: 180px; }
  .hdr-search-field:focus-within { width: 260px; }
  .nav-item--insolve { margin: 0 2px; padding: 0 9px; }
  .nav-link { padding-left: var(--sp-2); padding-right: var(--sp-2); }
  .header-actions { gap: var(--sp-2); flex: none; }
}
@media (min-width: 1025px) and (max-width: 1240px) {
  /* Última cedência antes do drawer: a linha auxiliar sai (a conta gratuita
     continua acessível pelo /planos e pelo rodapé). */
  .hdr-free { display: none; }
  .hdr-search-field { width: 150px; }
}

/* ============================== Seção recolhível (chevron no canto superior)
   Marcação: [data-secao] na CAIXA da seção; [data-secao="recolhido"] nasce
   fechada. O botão e o estado recolhido são injetados por app.js — o HTML
   servido continua ABERTO e completo, então sem JS (e na impressão) nada some,
   e nenhum conteúdo desaparece para rastreador.

   Só o BOTÃO alterna. O cabeçalho inteiro NÃO é clicável de propósito: título
   e pílulas ao lado carregam links e tooltips que perderiam o clique. */
.sec-colapso { position: relative; }
/* respiro no cabeçalho para o botão não pisar no que mora na ponta direita da
   .sec-head (contagem do QSA, tag "Experimental" da exposição) */
.sec-colapso .js-sec-head { padding-right: 40px; }
.sec-toggle {
  /* Alinhamento ÓPTICO, não geométrico: o topo cai no centro da linha do título
     (24px de .card-pad + meia linha) e o botão é puxado 6px para fora à direita,
     para o GLIFO de 20px — não a caixa de 32px — encostar na borda do conteúdo. */
  position: absolute; top: 26px; right: 18px; z-index: 3;
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; padding: 0; margin: 0;
  border: 0; border-radius: var(--r-full); background: transparent;
  color: var(--pc-ink-400); cursor: pointer;
  -webkit-appearance: none; appearance: none;
  transition: background-color .16s ease, color .16s ease;
}
.sec-toggle:hover { background: var(--pc-line-100); color: var(--pc-ink-700); }
.sec-toggle:focus-visible { outline: none; box-shadow: var(--ring-focus); }
.sec-toggle .icn-chev { width: 20px; height: 20px; transition: transform .2s ease; }
.sec-colapso.is-recolhido > .sec-toggle .icn-chev { transform: rotate(180deg); }
@media (prefers-reduced-motion: reduce) {
  .sec-toggle, .sec-toggle .icn-chev { transition: none; }
}
/* RECOLHIDO — só na tela. De pé fica a cadeia do título (o cabeçalho e os
   ancestrais dele até a raiz, porque em #processos o título mora dentro de um
   .card-pad); todo o resto some. */
@media screen {
  .sec-colapso.is-recolhido > :not(.js-sec-headblock):not(.js-sec-head):not(.sec-toggle) { display: none; }
  .sec-colapso.is-recolhido .js-sec-headblock > :not(.js-sec-headblock):not(.js-sec-head) { display: none; }
}
@media print { .sec-toggle { display: none; } }
@media (max-width: 640px) { .sec-colapso .js-sec-head { padding-right: 36px; } }

/* ============================== Busca de CNPJ no hero das landings pagas (ads-B7)
   Vive AQUI, na camada compartilhada, e não numa pages/*.css, porque o layout
   injeta UM único page_css: as oito landings que recebem anúncio se repartem
   entre pages/guia.css e pages/servicos.css, e nenhuma das duas carrega o
   .hh-busca* da home. Família de classes PRÓPRIA (.lpb-) em vez de reaproveitar
   .hh-busca: aquele conjunto é desenhado para herói ESCURO (campo branco,
   sombra de 34px) e é global dentro de pages/home.css — herdá-lo aqui obrigaria
   a desfazer meia dúzia de regras no claro e colocaria a home, que hoje rejeita
   15,7% no desktop, no caminho de qualquer ajuste feito para as landings.
   O que É compartilhado de propósito: .hdr-search-suggest (o dropdown de
   sugestões, logo acima neste arquivo) e a classe .hdr-search-input, que é o
   gancho que app.js procura. */
.lpb { position: relative; margin-top: var(--sp-5); max-width: 600px; }
.lpb-rot {
  display: block; margin-bottom: var(--sp-2);
  font-size: var(--fs-body); font-weight: 600; line-height: 1.4;
  color: var(--pc-ink-900);
}
.lpb-campo {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: 6px 6px 6px var(--sp-4);
  background: var(--pc-bg-0);
  border: 1px solid var(--pc-line-200); border-radius: var(--r-full);
  box-shadow: var(--shadow-1);
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
/* O halo mora no CAMPO INTEIRO, e o input desliga o anel próprio — mesma
   decisão do .hdr-search-field: dois anéis concêntricos, um deles colado à
   primeira letra digitada, é o que se vê quando cada um cuida do seu. */
.lpb-campo:focus-within { border-color: var(--pc-petrol-300); box-shadow: var(--ring-focus), var(--shadow-2); }
.lpb-ico { position: relative; display: inline-flex; flex: none; color: var(--pc-ink-400); }
.lpb-campo:focus-within .lpb-ico { color: var(--pc-petrol-600); }
.lpb-input.hdr-search-input { flex: 1; min-width: 0; padding: 12px 0 12px var(--sp-1); font-size: 1rem; }
.lpb-btn { flex: none; border-radius: var(--r-full); padding-left: var(--sp-5); padding-right: var(--sp-5); }
.lpb-micro { margin: var(--sp-2) 0 0; font-size: var(--fs-sm); line-height: 1.5; color: var(--pc-ink-500); }
/* O dropdown de components.css nasce ancorado à DIREITA e com 380px, medida do
   campo pequeno do cabeçalho. Aqui o ancoradouro é o form e a largura é a do
   campo — sem isto a caixa assume a largura do container e desalinha. */
.lpb .hdr-search-suggest { left: 0; right: auto; width: 100%; max-width: 600px; }
/* Carregando: o glifo da lupa cede lugar a um giro no MESMO espaço de 20px que
   ele já reservava (sem elemento novo na view, sem reflow). A consulta cruza
   uma base grande e demora ~2s: campo mudo nesse intervalo lê-se como travado. */
.lpb.is-loading .lpb-ico { color: var(--pc-petrol-600); }
.lpb.is-loading .lpb-ico > svg { opacity: 0; }
.lpb-ico > svg { transition: opacity var(--t-fast); }
.lpb.is-loading .lpb-ico::after {
  content: ""; position: absolute; top: 50%; left: 50%;
  width: 18px; height: 18px; margin: -9px 0 0 -9px;
  border: 2px solid var(--pc-line-200); border-top-color: var(--pc-petrol-600);
  border-radius: 50%; animation: lpb-spin .7s linear infinite;
}
@keyframes lpb-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .lpb.is-loading .lpb-ico::after { animation-duration: 1.6s; }
  .lpb-ico > svg { transition: none; }
}
/* No celular o botão desce para linha própria: a pílula com dois filhos lado a
   lado deixa o campo com ~150px úteis, estreito demais para um CNPJ formatado
   caber sem rolar dentro do input. E o orçamento vertical da primeira tela é o
   recurso escasso desta página (ads-B8), então tudo o que não decide nada
   encolhe: metade da linha de apoio sai (a ressalva de alcance é reimpressa no
   resultado da busca, que é onde ela pesa) e as folgas fecham. */
@media (max-width: 640px) {
  .lpb { margin-top: var(--sp-3); }
  .lpb-rot { margin-bottom: var(--sp-1); }
  .lpb-campo { flex-wrap: wrap; gap: var(--sp-1); border-radius: var(--r-lg); padding: var(--sp-2) var(--sp-3); }
  .lpb-input.hdr-search-input { padding: 4px 0 4px var(--sp-1); }
  .lpb-btn { width: 100%; }
  .lpb-micro-desk { display: none; }
}

/* ============================== Porta grátis do RESULTADO da busca (ads-B7)
   Uma linha só, entre a contagem de resultados e a tabela: é o instante de
   maior intenção do site inteiro (o visitante acabou de digitar o CNPJ que o
   preocupa) e, até aqui, o único desfecho oferecido ali era clicar numa ficha.
   Deliberadamente RASO — um campo de e-mail e nada mais. Pedir mais aqui é
   competir com a própria ficha, que é para onde o visitante quer ir. */
.bnl {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: var(--sp-2) var(--sp-5);
  margin: 0 0 var(--sp-4);
  padding: var(--sp-3) var(--sp-4);
  background: var(--pc-petrol-50);
  border: 1px solid var(--pc-petrol-200);
  border-left: 3px solid var(--pc-gold-500);
  border-radius: var(--r-lg);
}
.bnl-copy { margin: 0; font-size: var(--fs-sm); line-height: 1.5; color: var(--pc-ink-700); max-width: 60ch; }
.bnl-copy strong { color: var(--pc-ink-900); }
.bnl-form { display: flex; flex-wrap: wrap; gap: var(--sp-2); align-items: center; flex: 1 1 320px; max-width: 460px; }
.bnl-form .input { flex: 1 1 190px; min-width: 0; }
.bnl-hp { position: absolute; left: -9999px; top: -9999px; }
@media (max-width: 640px) {
  .bnl-form { flex: 1 1 100%; max-width: none; }
  .bnl-form .btn { width: 100%; }
}
/* ⚠ ESTA CHAVE FALTAVA (achada em 31/08/2026 pela minificação, que reprovava
   components.css com "fonte 894{ 893}"). Sem ela o navegador auto-fechava o
   arquivo no EOF e TUDO o que vem abaixo — .cta-assinar (a chamada de compra) e
   .pc-dlg (o <dialog> da confirmação de crédito, que abre na ficha PÚBLICA) —
   ficava dentro do @media (max-width: 640px): estilo só no celular, cru no
   desktop. Era também a razão de a folha inteira escapar do build minificado,
   então a home servia 137 KB de CSS comentado render-blocking. */

/* ============================== Chamada de assinatura (client/_cta-assinar)
   "Apenas assinantes de X podem …" + preço + Assinar/Conhecer. Nome, preço e
   links vêm do catálogo (CatalogoProdutos::cta). */
.cta-assinar { max-width: 72ch; }
.cta-assinar--centro { margin: 0 auto; text-align: center; }
.cta-assinar--esquerda { text-align: left; }
.cta-assinar__txt { font-size: var(--fs-sm); color: var(--pc-ink-500); line-height: 1.55; margin: 0 0 var(--sp-3); }
.cta-assinar__preco { display: block; margin-top: var(--sp-2); font-size: var(--fs-xs); color: var(--pc-ink-400); }
.cta-assinar__acts { flex-wrap: wrap; gap: var(--sp-2); }
.cta-assinar--centro .cta-assinar__acts { justify-content: center; }
/* "Outros pacotes" da chamada de AMPLIAÇÃO (client/_cta-ampliar — o produto
   já contratado bateu no teto): a escada inteira numa linha miúda abaixo dos
   botões; cada pacote é um link que não quebra no meio do preço. */
.cta-assinar__outros { margin: var(--sp-3) 0 0; font-size: var(--fs-xs); color: var(--pc-ink-400); line-height: 1.6; }
.cta-assinar__outros a { white-space: nowrap; }

/* ============================== Modal nativo (<dialog>) — .pc-dlg
   Nativo e não div-com-overlay: ESC fecha, o foco fica preso dentro e o
   ::backdrop é do navegador. Sem JS o elemento chega com [open] do servidor e
   ainda assim mostra o formulário — degradado, mas nunca inacessível.
   Nasceu em pages/painel.css (escopado em .app-main) para /painel/carteira e
   /painel/alertas; veio para cá em 22/08/2026 porque a confirmação de crédito
   (partials/dlg-credito) também abre na ficha PÚBLICA, que não carrega o CSS
   do painel. Mesmas regras, sem o prefixo. Gatilhos genéricos em app.js
   ([data-dlg-abrir] / [data-dlg-fechar], para os diálogos com data-dlg-auto). */
.pc-dlg {
  border: 0; padding: 0; margin: auto;
  border-radius: var(--r-lg); box-shadow: var(--shadow-4);
  background: var(--pc-bg-0); color: var(--pc-ink-900);
  width: calc(100vw - 40px); max-width: 560px;
}
.pc-dlg::backdrop { background: rgba(11, 43, 48, .5); }
/* O corpo rola, não a página: formulário longo em tela baixa não pode empurrar
   os botões de ação para fora do alcance. */
.pc-dlg__inner { padding: var(--sp-6); max-height: min(82vh, 760px); overflow-y: auto; }
.pc-dlg h3 { margin: 0 0 var(--sp-4); font-size: var(--fs-h4); }
/* Ações GRUDADAS no rodapé do modal. Um formulário longo estoura os 760px do
   corpo em qualquer tela normal: sem o sticky, o botão principal nascia abaixo
   da dobra do próprio modal e só aparecia depois de rolar até o fim — o usuário
   via uma caixa sem saída. O bottom negativo cancela o padding de baixo do
   corpo, para a barra encostar na borda em vez de flutuar sobre ela; as margens
   laterais negativas fazem a faixa opaca cobrir a largura toda, senão o
   conteúdo rolaria visível pelas beiradas. */
.pc-dlg__acts {
  position: sticky; bottom: calc(var(--sp-6) * -1); z-index: 1;
  display: flex; justify-content: flex-end; gap: var(--sp-2);
  margin: var(--sp-5) calc(var(--sp-6) * -1) calc(var(--sp-6) * -1);
  padding: var(--sp-4) var(--sp-6);
  background: var(--pc-bg-0);
  border-top: var(--hairline);
}
@media (max-width: 560px) {
  .pc-dlg__inner { padding: var(--sp-5) var(--sp-4); }
  .pc-dlg__acts {
    flex-direction: column-reverse;
    bottom: calc(var(--sp-5) * -1);
    margin: var(--sp-5) calc(var(--sp-4) * -1) calc(var(--sp-5) * -1);
    padding: var(--sp-4);
  }
  .pc-dlg__acts .btn { width: 100%; }
}
