/* ================================================================
   custom.css — OneRank × Quanto (Creative Agency Template)
   Aplicado APÓS o style.css do template Envato (site/includes/header.php:102, logo depois do
   partial _head.php do tema). Nunca altere o style.css do template — use apenas este arquivo.
   ================================================================

   CONTRATO DE DESENVOLVIMENTO — OneRank
   ──────────────────────────────────────────────
   Este arquivo é o ÚNICO lugar para customizações por cliente.
   REGRA: usar sempre var(--token) em vez de valores hardcoded
   para as 5 propriedades de identidade que o cliente controla:

     var(--marca-primaria)    → cor principal da marca
     var(--marca-secundaria)  → cor secundária / hover
     var(--texto-principal)   → cor base do corpo de texto
     var(--texto-secundario)  → texto auxiliar / muted
     var(--texto-link)        → cor de links e âncoras

   Estes tokens são configurados em admin > Empresa > Cores e
   injetados automaticamente via Colors::toCssVars() no <head>.

   Ao adaptar para um novo template Envato:
   1. Mantenha este bloco de contrato intacto
   2. Mapeie os tokens do template para as variáveis acima
   3. Nunca escreva cores de marca com valores hardcoded
   ================================================================

   NOTA (25/08/2026, retrofit Quanto) — troca de template Azurio → Quanto (mesmo fork
   institucional). O Quanto é BASE-5 (Bootstrap 5.3.3 real) + paleta monocromática de 10 tokens
   (:root em style.css:42-62: --color-primary/white/black/1..5, cada um com par -rgb). O style.css
   compilado usa 7 variáveis que o próprio vendor NUNCA declara (--color-primary-orange,
   --title-color, --smoke-color, --heading-color, --color-light-black, --white-color,
   --light-bg2) — sem defini-las aqui, as declarações que as referenciam são descartadas em
   silêncio pelo parser CSS. Ver BLOCO 0. */

/* ================================================================
   BLOCO 0 — Tokens que o Quanto usa e nunca define + mapeamento marca → paleta
   ================================================================ */
:root {
    /* marca → paleta Quanto — ENTRA POR ACENTO, não substituição. --color-primary é ao mesmo
       tempo cor do CORPO DE TEXTO (h1..h6, .main-menu a) e fundo de blocos inteiros (footer,
       process-box, menu de fundo escuro) — trocá-lo pelo azul da marca deixaria enormes áreas
       de fundo/texto na cor de marca em vez de neutro, e o próprio texto ilegível sobre si
       mesmo. Mapeado para o neutro escuro do cliente (--texto-principal). */
    --color-primary: var(--texto-principal, #1A2332);

    /* --color-primary-orange é o ÚNICO slot cromático do template inteiro (spinner do
       preloader + hover das setas de slider/paginação) — aqui SIM entra a marca, sem ela
       essas 4 declarações do vendor eram mortas (variável nunca definida). */
    --color-primary-orange: var(--marca-primaria, #0B3D91);

    /* Borda sutil (setas de navegação de slider) — tom neutro translúcido, não é papel de marca. */
    --color-light-black: rgba(0, 0, 0, .12);

    /* --title-color é usado como cor de ÍCONE/texto forte (ex.: .quanto-mobile-menu-btn
       .social-btn a, style.css:1832) e como FUNDO no :hover do mesmo elemento — mesmo papel de
       --color-primary (neutro escuro/texto), não de marca. */
    --title-color: var(--color-primary);
    --smoke-color: var(--color-2);   /* fundo sutil (badge do social-btn) */
    --white-color: var(--color-white);
    --heading-color: var(--color-primary); /* só em .optech-* — classe morta, nenhuma página do vendor usa; definida por higiene */
    --light-bg2: var(--color-2);           /* idem — só em .optech-* */
}

/* ================================================================
   BLOCO 0.5 — TOKENS DO SISTEMA DE DESIGN (evolução visual, 25/08/2026)
   Completa a estética do Quanto com o que o template monocromático nunca teve: profundidade
   (sombra/elevação/raio) e temperatura de marca (o azul institucional como estrutura, o dourado
   como pontuação cerimonial — NUNCA como texto sobre fundo claro, ver auditoria em
   includes/Colors.php:221 "marca-destaque é feito p/ RECEBER texto, não pra SER texto"). Uso do
   dourado é lista FECHADA: caret de hero, traço do eyebrow/divisor, botão do CTA final, selo
   "Recomendado" do pricing, e (só no dark) o texto do eyebrow. Fora dessa lista, o site continua
   monocromático — o dourado deixa de significar destaque no instante em que aparece em toda parte.
   ================================================================ */
:root {
    --or-ink-deep: #05132b;                                  /* fecho do gradiente de marca (era hardcoded em .or-home-hero) */
    --or-dourado: var(--marca-destaque, #E8B53D);
    --or-grad-marca: linear-gradient(160deg, var(--marca-primaria, #0B3D91) 0%, var(--marca-secundaria, #082C6A) 55%, var(--or-ink-deep) 100%);
    /* Malha plexus (28/08/2026) — o MESMO motivo do vídeo do hero (pontos ligados por linhas),
       usado como mask-image no fundo dos cards de #dor. É MÁSCARA, não imagem: a cor sai do CSS,
       então a malha acompanha tema e hover de graça — um .webp congelaria a paleta, erro já
       documentado 3× neste arquivo. Tile 360×360 repetível SEM COSTURA (as arestas que cruzam a
       borda são emitidas dos dois lados). 1,3 KB, zero requisição.
       Regerar: php bin/cliente/gerar-malha-plexus.php [--seed=N] [--nos=N] */
--or-malha-plexus: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 360 360'%3E%3Cpath fill='none' stroke='%23fff' stroke-width='.7' d='M9.6 52.8L-21 33.6M369.6 52.8L339 33.6M9.6 52.8L46.2 84M91.2 33L86.4 85.2M91.2 33L153 31.2M153 31.2L165.6 78M217.8 46.8L223.8 76.8M217.8 46.8L165.6 78M277.8 11.4L339 33.6M277.8 11.4L280.8 81M339 33.6L326.4 76.2M46.2 84L86.4 85.2M86.4 85.2L81 129.6M165.6 78L148.8 130.2M223.8 76.8L280.8 81M280.8 81L326.4 76.2M23.4 139.2L81 129.6M23.4 139.2L46.2 84M81 129.6L46.2 84M148.8 130.2L81 129.6M227.4 168L228 211.8M227.4 168L254.4 204.6M266.4 136.8L310.2 151.2M266.4 136.8L227.4 168M310.2 151.2L311.4 188.4M50.4 195.6L67.8 252.6M50.4 195.6L23.4 139.2M105 228L67.8 252.6M105 228L50.4 195.6M166.8 196.8L228 211.8M166.8 196.8L227.4 168M228 211.8L254.4 204.6M311.4 188.4L254.4 204.6M20.4 279L67.8 252.6M20.4 279L50.4 195.6'/%3E%3Cpath fill='none' stroke='%23fff' stroke-width='3.4' stroke-linecap='round' d='M9.6 52.8h0M91.2 33h0M153 31.2h0M217.8 46.8h0M277.8 11.4h0M339 33.6h0M46.2 84h0M86.4 85.2h0M165.6 78h0M223.8 76.8h0M280.8 81h0M326.4 76.2h0M23.4 139.2h0M81 129.6h0M148.8 130.2h0M227.4 168h0M266.4 136.8h0M310.2 151.2h0M50.4 195.6h0M105 228h0M166.8 196.8h0M228 211.8h0M254.4 204.6h0M311.4 188.4h0M20.4 279h0M67.8 252.6h0'/%3E%3C/svg%3E");

    --or-radius-s: 8px;
    --or-radius-m: 12px;
    --or-radius-l: 20px;
    --or-radius-pill: 40px;

    /* ── RITMO VERTICAL — escala de espaçamento em base 4px (28/08/2026) ────────────────────────
       Motivo de existir: o arquivo acumulou ~40 valores de margem ad-hoc (8, 10, 12, 16, 18, 20,
       24, 28, 32, 36, 38, 40, 44…), e o resultado previsível foi um bug de "elementos grudados"
       achado ao vivo pelo dono — os chips de #geo encostavam no painel de resposta com 0px entre
       eles, porque estavam em .row IRMÃS e o gutter do Bootstrap (g-4) só age entre COLUNAS da
       MESMA row, nunca entre linhas.

       A escala não é decorativa: é o que torna "quanto respiro isto pede?" uma pergunta com
       resposta, em vez de um chute por elemento. Regra de uso completa em CLAUDE.md (§Padrão de
       Espaçamento). Resumo: bloco irmão dentro de uma seção nunca fica com menos de --or-esp-5.

       Legado NÃO foi convertido em massa de propósito — reescrever 40 margens testadas para ganhar
       consistência de 2px é risco visual sem retorno. Os tokens valem para código NOVO e para o
       que for tocado por outro motivo. ── */
    --or-esp-1: 4px;    /* micro: ícone↔label, chip interno */
    --or-esp-2: 8px;    /* item↔item numa lista densa */
    --or-esp-3: 12px;   /* label↔campo, linha↔linha de um card */
    --or-esp-4: 16px;   /* card↔card num grid */
    --or-esp-5: 24px;   /* PISO entre blocos irmãos — nunca menos que isto */
    --or-esp-6: 32px;   /* bloco↔bloco com troca de assunto */
    --or-esp-7: 48px;   /* sub-bloco↔sub-bloco dentro da mesma seção */
    --or-esp-8: 64px;   /* separação máxima interna a uma seção */

    /* Sombras calibradas pro fundo claro (--marca-primaria-rgb é derivado por Colors::toCssVars()). */
    --or-shadow-1: 0 1px 2px rgba(8, 20, 40, .05), 0 4px 14px rgba(8, 20, 40, .06);
    --or-shadow-2: 0 2px 6px rgba(8, 20, 40, .06), 0 14px 34px rgba(8, 20, 40, .10);
    --or-shadow-brand: 0 14px 40px rgba(var(--marca-primaria-rgb, 11, 61, 145), .20);
}
/* No dark, elevação por sombra não lê bem sobre superfície já escura — vira borda (mesmo
   raciocínio do Design System do admin: dark-safe é token semântico, não a mesma sombra mais fraca). */
[data-bs-theme="dark"] {
    --or-shadow-1: none;
    --or-shadow-2: var(--or-elev, 0 8px 24px rgba(0, 0, 0, .35));
    --or-shadow-brand: none;
}

/* ================================================================
   Tipografia — Instrument Sans self-hospedada (fidelidade ao vendor: mantida, não trocada por
   Poppins/Inter da marca). @font-face ÚNICO lugar de declaração — o preload em _head.php usa a
   MESMA URL, sem cache-bust, pra bater byte a byte (preload só é aproveitado se a URL casar).
   ================================================================ */
@font-face {
    font-family: 'Instrument Sans';
    font-style: normal;
    font-weight: 400 700;
    font-display: swap;
    src: url(../fonts/instrument-sans-400-700-normal-latin.woff2) format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: 'Instrument Sans';
    font-style: normal;
    font-weight: 400 700;
    font-display: swap;
    src: url(../fonts/instrument-sans-400-700-normal-latin-ext.woff2) format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ================================================================
   BLOCO 1 — CONTRATO DE MARCA + COMPONENTES CORE SEMPRE ATIVOS (herdado do Azurio — só as 3
   regras GENUINAMENTE genéricas sobrevivem: nenhuma delas dependia de classe do Azurio).
   ================================================================ */

/* --- Tipografia da marca em elementos genéricos (contrato de marca, não Quanto-específico) ---
   1 ajuste em relação ao Azurio: font-family agora aponta pra Instrument Sans (a fonte que o
   PRÓPRIO style.css do Quanto já usa via var(--ff-instrument-sans) em h1..h6 — style.css:110) —
   fica redundante/inofensiva na prática, mantida só pelo contrato "marca define a tipografia".
   O letter-spacing:-0.01em do Azurio foi DESCARTADO de propósito: o style.css do Quanto já
   define tracking negativo PRÓPRIO por nível (h1 -4.2px … h6 -0.24px, style.css:97-154) — um
   valor uniforme por cima pisava nesse ajuste fino e achatava a hierarquia que o vendor desenhou. */
h1, h2, h3, h4, h5, h6,
.display-1, .display-2, .display-3, .display-4 {
    font-family: 'Instrument Sans', system-ui, -apple-system, sans-serif;
}
body { color: var(--texto-principal, #212529); }
a { color: var(--texto-link, var(--marca-primaria, #0B3D91)); transition: color .15s ease; }
a:hover { color: var(--marca-secundaria, var(--marca-primaria)); }

/* --- Banner de cookies (site/includes/cookie_banner.php) — CORE, ativo em toda página --- */
#or-lgpd-banner {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 9998;
    background: rgba(30,30,30,.97);
    color: #f0f0f0;
    padding: 14px 24px;
    font-size: .85rem;
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 12px;
}
#or-lgpd-banner a { color: #aad4f5; }

/* --- Ícones SVG inline (\OneRank\Icon::render()) — CORE, emitido em toda página ---
   SEM fill fixo: Icon::render() já define fill/stroke via atributo inline no próprio <svg>,
   conforme o tipo do ícone (outline = stroke; filled = fill). */
.or-icon {
    width: 1em;
    height: 1em;
    vertical-align: -0.125em;
    display: inline-block;
    flex-shrink: 0;
}

/* ================================================================
   BLOCO 1.5 — SISTEMA TIPOGRÁFICO (evolução visual, 25/08/2026)

   Achado real: o vendor pula de h4=60px pra h5=28px sem nada no meio (style.css:127-154), e
   `.title` — a classe que TODA seção usa pro próprio h3 (home/planos/sobre/serviços…) — não tem
   NENHUMA regra global no style.css (só variantes escopadas a 3 heros que não usamos). Resultado:
   todo `<h3 class="title">` caía no h3 CRU do vendor (80px) e todo `<h4>` de card caía no h4 cru
   (60px) — sem guerra de especificidade a resolver aqui, já que a regra abaixo é a ÚNICA que casa.

   Escopado a `.or-pg` (a classe que \OneRank\Acessibilidade::mainOpen() sempre emite no <main> —
   nunca vaza pro header/rodapé/marquee, que ficam fora dele). */
:root {
    --or-fs-display:         clamp(2.6rem, 1.6rem + 5vw, 5.5rem);     /* hero comercial — mesmo clamp do .or-hero-interno__title, agora token */
    --or-fs-display-hero:    clamp(2.4rem, 1.5rem + 3.4vw, 4.25rem);  /* SÓ .or-home-hero__title — teto 68px (era 88px via --or-fs-display): a frase-âncora + complemento rotativo cabe em 3 linhas em vez de 4, evitando que o hero estoure a viewport em notebooks baixos (achado 26/08/2026, print 2560×919) */
    --or-fs-h1:              clamp(2.1rem, 1.4rem + 3.2vw, 4rem);     /* hero editorial/listagem */
    --or-fs-secao:           clamp(1.9rem, 1.2rem + 2.4vw, 4rem);     /* conserta .title / h3 de seção — teto 4rem (era 3.25rem, truncava 35% da rampa) */
    --or-fs-secao-compacta:  clamp(1.9rem, 1.2rem + 2.4vw, 3.25rem);  /* teto ANTIGO de --or-fs-secao — pra quem não deve crescer (.or-hero-interno--doc, .or-funfacts) */
    --or-fs-h3:              clamp(1.5rem, 1.15rem + 1.2vw, 2rem);    /* subtítulos internos */
    --or-fs-card:            clamp(1.2rem, 1.05rem + .7vw, 1.5rem);   /* conserta h4 de card (era 60px cru) */
    --or-fs-lead:            clamp(1.05rem, 1rem + .4vw, 1.25rem);
    --or-fs-small:           .875rem;
    --or-fs-eyebrow:         .78rem;

    /* Prosa de leitura longa (artigo do blog, legais) — promovendo a token o valor que já estava
       em uso: 72ch já era o teto de linha real de .or-doc-body (achado de 27/08/2026, ver o
       comentário da regra de max-width abaixo) e 1.7 já era o line-height do próprio seletor.
       Não é escala nova — é o mesmo número, nomeado, pra parar de repetir o literal a cada regra. */
    --or-medida-prosa: 72ch;
    --or-lh-prosa: 1.7;
}

/* Tracking PROPORCIONAL (não em px fixo). O vendor prende letter-spacing à TAG em px (h3 −2px@80px,
   h4 −1,5px@60px — ambos −0,025em); toda regra que REESCALA um heading sem reescalar o tracking
   herda um valor absoluto calibrado pra outro corpo — era -1,5px sobre um h4 de 16,8px = -8,9% do
   corpo (letras colidindo, achado real em .or-prova-card). Os valores abaixo são os do PRÓPRIO
   vendor na escala equivalente: -.01em é literalmente o -0,24px@24px do h6 (style.css:151-153).
   .or-pg h3.move-anim:not(.title) agora joga no MESMO seletor que .title — antes só herdava
   font-size e ficava com -2,00px crus do vendor (quase o dobro do -1,04px dos irmãos). */
/* h2.title entrou em 28/08/2026 (auditoria A-08): os títulos de seção eram <h3>, com a página
   saltando de h1 direto para h3 — 19 h3 contra 3 h2. Leitor de tela navegando por heading percebia
   as seções como subordinadas a algo inexistente, e é sinal de estrutura para o crawler, que é
   justamente o que este site vende. A tag mudou para h2; o VISUAL não muda, porque o tamanho vem
   desta regra (não da tag), e é por isso que h2 e h3 dividem o mesmo seletor. */
.or-pg h2.title,
.or-pg h3.title,
.or-pg .quanto__header .title,
.or-pg h3.move-anim:not(.title) {
    font-size: var(--or-fs-secao);
    line-height: 1.12;
    letter-spacing: -.02em;
    /* text-wrap:balance (27/08/2026) — conserta a ÓRFÃ. Achado ao vivo em #dor: "Se sua empresa
       não aparece, ela / não existe." deixa "ela" pendurada no fim da linha 1; com col-8 a linha
       fica ainda mais longa e a chance de órfã sobe. Balance reparte as linhas em larguras
       parecidas — cálculo que o vendor nunca fez. Progressive enhancement puro (Chrome 114+,
       Safari 17.4+, Firefox 121+): onde não existe, o navegador descarta a declaração e nada
       muda. SOBREVIVE ao SplitText (main.js:442 fatia .move-anim em <div> por LINHA): o split LÊ
       o layout já balanceado e congela essas linhas — CSS pinta primeiro, JS lê depois. Entra no
       seletor global do sistema tipográfico, não escopado a #dor: órfã em título de seção é
       problema de TODA página, mesma lógica do tracking proporcional documentado acima. */
    text-wrap: balance;
}
.or-pg :is(.quanto-service-box3, .quanto-service-box4, .quanto-service-box5, .quanto-service-box6) h4,
.or-pg .or-prova-card :is(h3, h4) {
    font-size: var(--or-fs-card);
    /* O peso vinha da TAG: h4 do vendor é 700, h3 é 600. Ao promover o card de prova para h3 o
       título emagreceu — diferença que a medição pegou e o olho não pegaria. Declarado aqui, a
       regra deixa de depender da tag também nisso. */
    font-weight: 700;
    line-height: 1.25;
    letter-spacing: -.01em;
}

/* Utilitários t-* — promovidos de "só dentro de .or-doc-body" pra globais em .or-pg. Achado real:
   t-medium/t-bold NÃO EXISTEM em CSS nenhum (nem aqui, nem no vendor) e t-large/-small/-muted só
   valiam dentro de .or-doc-body — ~40 usos em 21 arquivos (todo empty-state de listagem, as
   legendas de estatística de /planos, a frase-manifesto de /sobre) renderizavam sem nenhum estilo.
   t-muted usa var(--or-text-muted) — achado extra: a versão antiga usava var(--color-4) (#313131,
   cru, nunca flipado pro dark), texto quase invisível em fundo escuro (~mesma família do achado de
   contraste da F9). Substituída aqui — não há mais declaração own de --color-4 pra t-muted. */
.or-pg .t-large  { font-size: var(--or-fs-lead); }
.or-pg .t-small  { font-size: var(--or-fs-small); }
.or-pg .t-muted  { color: var(--or-text-muted); }
.or-pg .t-medium { font-weight: 500; }
.or-pg .t-bold   { font-weight: 700; }

/* ── RITMO TIPOGRÁFICO DE FALLBACK — o par heading→parágrafo (05/09/2026) ───────────────────
   CAUSA RAIZ (CLAUDE.md §Padrão de Espaçamento): o vendor zera h1-h6{margin-bottom:0} E
   p{margin-bottom:0}. Um <p> logo abaixo de um heading, sem classe que traga margem, fica
   COLADO — sem erro, sem aviso. Achado ao vivo em /planos (h2.title + p.t-muted dentro de
   .text-center.mb-4: o .mb-4 separa o WRAPPER do form abaixo, nunca os dois filhos entre si —
   pagina-planos.php, bloco do formulário de contato).

   Varredura dos arquivos .php de site/_template/pages/: 43 pares h+p adjacentes; 19 já têm classe com margem própria
   (.or-lead, .or-blog-resumo, .or-hero-interno__subtitle…), ~15 estavam colados
   (pagina-busca.php, 404.php, home.php, pagina-planos.php entre eles).

   ⚠️ A ESPECIFICIDADE É O DESENHO, não um detalhe. Os DOIS :where() zeram a contribuição do
   escopo e dos headings: o seletor inteiro pesa (0,0,1) — o mesmo de um `p` cru. Consequências,
   todas desejadas:
     · QUALQUER regra com uma classe (0,1,0+) vence sem esforço e sem !important — .or-lead,
       .or-blog-resumo, .or-hero-interno__subtitle, e também os utilitários mt-* / my-* do
       Bootstrap. Zero regressão nos pares que já têm margem própria.
     · Componente cujo PAI é flex/grid com gap (Regime A do CLAUDE.md) neutraliza com uma
       linha trivial de classe — o respiro nunca dobra por acidente, e a correção é local:
       `.componente :is(h1,h2,h3,h4,h5,h6) + p { margin-top: 0 }` (0,1,2 > 0,0,1).
     · Só perde para outro seletor de peso (0,0,1) que venha DEPOIS no arquivo — não existe
       nenhum seletor de elemento puro `p{}` no custom.css. O único concorrente é o
       `p{margin-bottom:0}` do vendor (style.css), que carrega ANTES — vencemos por ordem.

   `+` (irmão ADJACENTE), nunca `~`: só o parágrafo que abre logo abaixo do título. Comentário
   HTML e bloco <?php ?> entre os dois não são elementos e não quebram a adjacência.
   --or-esp-5 é o PISO documentado entre blocos irmãos (24px), não um valor escolhido aqui. */
:where(.or-pg) :where(h1, h2, h3, h4, h5, h6) + p { margin-top: var(--or-esp-5); }
:where(.or-pg) :where(h1, h2, h3, h4, h5, h6) + :where(ul, ol, blockquote, dl) {
    margin-top: var(--or-esp-5);
}

/* --- Padding de seção mais denso na HOME (F6 da reestruturação — orçamento de rolagem; reduzido
   de novo em 27/08/2026 — pedido do dono ao ver o hiato #superficies→#dor: "este espaçamento entre
   sessões pode ser menor"). A home tem 12+ seções (contra 1-3 de página interna); os 130px do
   vendor (style.css:340-343) em cada uma somam ~1,5x mais respiro do que uma home com tantos blocos
   precisa. Primeira rodada (F6) foi 130→96; esta caiu mais 24px (96→72, -25%, mesma proporção do
   corte anterior) — é a alavanca que aperta o espaço entre TODAS as seções de uma vez, não só a que
   apareceu no print. Só ≥1200px — as reduções do vendor pra tablet/mobile (80px/65px) já são
   proporcionalmente menores e ficam intocadas (o seletor teria especificidade maior e as
   sobrescreveria se não escopado à mesma media query).

   FURO ACHADO NA AUDITORIA (28/08/2026, CLAUDE.md §Padrão de Espaçamento): o seletor só cobria
   `.section-padding-top-bottom`. #portfolio e a faixa de parceiros usam `.section-padding-bottom`
   SOZINHA (sem a top) — escapavam do corte e ficavam nos 130px do vendor. Resultado medido:
   #portfolio→#servicos e parceiros→#blog somavam 202px (130 do topo da seção seguinte + 72 daqui),
   40% ACIMA do padrão de 144px (72+72) — exatamente o oposto do que este bloco existe pra fazer.
   As 3 classes do vendor (style.css:332-343) são cada uma DONA de UMA propriedade só (top-only,
   bottom-only, ambas) — cada regra abaixo toca só a que a classe original já tinha. Dar
   padding-top a `.section-padding-bottom` seria inventar um respiro no TOPO que o vendor nunca
   declarou (ex.: #portfolio encosta em #lgpd de propósito, sem gap — é o próximo padding-bottom que
   faltava, não um padding-top que nunca existiu).

   DOIS ACHADOS MEDIDOS AO VIVO em 29/08/2026 (Playwright, offsetTop — imune ao transform do
   ScrollSmoother/GSAP, que distorce getBoundingClientRect() em tudo com fade-anim/move-anim):

   1) O override só cobria ≥1200px — a faixa 992-1199px (tablet) ficava com os 80px do vendor,
      MAIS respiro entre seções (160px) que o DESKTOP (144px). Inversão de hierarquia por
      acidente de breakpoint, não por design. Corrigido subindo a media query pro breakpoint `lg`
      do próprio Bootstrap (992px), onde as colunas ainda ficam lado a lado — abaixo disso tudo
      empilha e a proporção já é outra por natureza.

   2) `row-padding-top` (60px, classe do vendor que separa ROWS irmãs dentro de uma seção — ver
      CLAUDE.md §Padrão de Espaçamento) nunca foi reescalado junto do corte 130→72 do PADDING de
      seção. Vão entre seções 144px contra degrau interno de 60px = razão 2,4× — perto demais:
      "nova seção" e "nova row" liam quase igual. --or-esp-7 (48px) é literalmente o token da
      escala pra "sub-bloco↔sub-bloco dentro da mesma seção" (custom.css :root) e devolve a razão
      pra 3,0× (144/48), o mesmo tipo de proporção que já existia antes do corte de padding. */
/* --- RITMO GLOBAL (02/09/2026) — o corte deixou de ser exclusivo da home.
   Ele nasceu escopado em `.or-pg--home` porque foi lá que o problema apareceu, e ficou assim. O
   efeito colateral so ficou visivel quando as paginas internas de servico cresceram para 9+ secoes:
   a home respirava 144px entre secoes e a interna 260px — 80% a mais, na pagina que MAIS precisa de
   leitura continua. Nao era decisao de design, era o alcance de um seletor.

   Medido antes de mexer (1440px, offsetTop): home 72+72 com degrau de 48px; qualquer `.or-pg--*`
   que nao fosse a home caia nos 130+130/60 do vendor. Tirar o `.or-pg--home` iguala o site inteiro
   ao ritmo que ja tinha sido calibrado e aprovado — nao inventa um terceiro valor.

   A media query continua em 992px (breakpoint `lg` do Bootstrap, onde as colunas ainda ficam lado a
   lado). Abaixo disso tudo empilha e valem os 65/45 do vendor, que ja sao proporcionais.
   O `.or-pg` no seletor mantem o escopo dentro do <main> — o header/rodape do vendor nao entram. --- */
@media (min-width: 992px) {
    .or-pg .section-padding-top-bottom { padding-top: 72px; padding-bottom: 72px; }
    .or-pg .section-padding-top        { padding-top: 72px; }
    .or-pg .section-padding-bottom     { padding-bottom: 72px; }
    .or-pg .row-padding-top            { padding-top: var(--or-esp-7); }
    .or-pg .row-padding-bottom         { padding-bottom: var(--or-esp-7); }
}

/* --- Respiro do empilhamento mobile — rows que trocaram g-* por gx-* (achado do "gutter come
   padding-top da seção" — ver o comentário de cada row em home.php) perderam o gutter VERTICAL
   nativo do Bootstrap, que era quem separava as 2 colunas quando empilham (<992px). Mesmo remédio
   já usado em #geo/#lgpd (classe marcadora na row + margin-top no 2º filho). Valores da escala
   --or-esp-* conforme o peso do par: blocos grandes (devices/swiper) usam --or-esp-6 (32px);
   título+link mais leve usa --or-esp-5 (o piso).
   .or-faqs-stack SAIU (29/08/2026) — #faqs deixou de usar gx-*: agora é g-4 g-xl-5, um grid de 2
   colunas de verdade (4 grupos, não mais 1 título estreito + 1 acordeão largo), e o gutter
   VERTICAL nativo do g-4 já resolve o empilhamento mobile sozinho — nenhuma compensação extra
   precisa. --- */
@media (max-width: 991.98px) {
    .or-painel-stack > :nth-child(2)      { margin-top: var(--or-esp-6); }
    .or-depoimentos-stack > :nth-child(2) { margin-top: var(--or-esp-6); }
}
/* .or-blog-header-stack REMOVIDA em 09/09/2026: o cabeçalho de #blog virou coluna única
   (col-lg-10) e o link "Ver todos os artigos" desceu para uma row própria depois dos cards. A
   regra dava respiro entre a 1ª e a 2ª coluna no empilhamento mobile — sem 2ª coluna, o seletor
   :nth-child(2) não tem mais o que atingir. CSS sem markup não quebra nada, mas mente para quem
   lê depois: sugere um componente vivo que nenhuma tela renderiza. */

/* .quanto-about__content.style-2 .price-info tinha override aqui (achado 28/08/2026) porque
   #sobre-onerank (home) media o "9 recursos de acessibilidade" com o odômetro. A seção SAIU da
   home em 29/08/2026 (só os diferenciais migraram, para /sobre — o odômetro não, /sobre já tem
   bloco próprio de indicadores) e este era o ÚNICO uso de .price-info na home — regra removida
   por não ter mais seletor a atingir. */

/* ================================================================
   BLOCO 2 — TEMA · CHASSI (cursor/preloader/menu mobile/header/rodapé/hero interno — comum a
   TODA página do tema, não só a home).
   ================================================================ */

/* Rede de segurança documentada (docs/layout-tema.md): bundle Envato minificado de Swiper pode
   trazer CSS nesting corrompido (&:only-child vira :only-child GLOBAL após a minificação) — como
   <html> é estruturalmente filho único do document, a página inteira fica display:none, sem erro
   de servidor/console. Já aconteceu de verdade com o swiper-bundle do Azurio; o do Quanto é outro
   arquivo/versão, mas a mesma classe de bug do minificador pode se repetir. Custo: 1 linha. */
html:only-child { display: block !important; }

/* --- Logo (header + menu mobile) — dimensiona qualquer logo enviada no admin (o vendor não
   define altura própria: .header-logo/.mobile-logo só limitam largura, style.css:1050/1389). --- */
.header-logo img,
.header-logo .or-logo-swap img,
.header-logo .or-logo-swap {
    max-height: 42px;
    width: auto;
}
.header-logo .or-logo-swap { display: inline-flex; align-items: center; }
.quanto-menu-wrapper .mobile-logo img,
.quanto-menu-wrapper .mobile-logo .or-logo-swap img {
    max-height: 34px;
    width: auto;
}
.quanto-menu-wrapper .mobile-logo .or-logo-swap { display: inline-flex; align-items: center; }

/* --- Acento de marca (mín. 3 pontos — o resto do template é monocromático de propósito):
   1) :focus-visible global já usa var(--marca-primaria) via site/assets/css/or-a11y.css (core,
      carregado em toda página, !important) — nenhum CSS extra necessário aqui.
   2) CTAs principais (header/hero/pricing) ganham a cor real da marca em vez do neutro --color-primary.
   3) Hover-overlay (painel que desliza atrás de pricing-box/process-box no hover, injetado por
      main.js) troca de neutro pra marca. --- */
.quanto-header .quanto-link-btn.btn-pill,
.quanto-pricing-box .quanto-link-btn.btn-pill {
    background-color: var(--marca-primaria);
    border-color: var(--marca-primaria);
}
.quanto-header .quanto-link-btn.btn-pill:hover,
.quanto-pricing-box .quanto-link-btn.btn-pill:hover {
    background-color: var(--marca-secundaria, var(--marca-primaria));
    border-color: var(--marca-secundaria, var(--marca-primaria));
}
/* Hover-overlay: PAR de tokens por componente (painel + tinta), não um azul único. Os dois cards
   partem de superfícies OPOSTAS — .process-box é card escuro (vendor deu overlay claro,
   style.css:5679-5687) · .quanto-pricing-box é card claro (vendor deu overlay escuro,
   style.css:5178) — daí terem cores de TEXTO opostas no :hover (style.css:5727-5733 usa
   var(--color-primary), escuro; style.css:5284-5290 usa var(--color-white), claro). Um único azul
   de marca aqui deixou a cor de texto do vendor "desencontrada": 1,57:1 no .process-box (claro) e
   1,78:1 no .quanto-pricing-box (escuro) — medido ao vivo. A correção da TINTA fica no bloco 3.5,
   depois do bloco DARK de propósito (ver comentário lá). */
.process-box {
    --or-hover-painel: color-mix(in srgb, var(--marca-primaria) 12%, #fff);
    --or-hover-tinta:  var(--marca-primaria);
}
.quanto-pricing-box {
    --or-hover-painel: var(--marca-primaria);
    --or-hover-tinta:  #fff;
}
.quanto-pricing-box .hover-overlay,
.process-box .hover-overlay {
    background: var(--or-hover-painel);
}

.or-header-actions { gap: 14px; }

/* --- Breadcrumb (_hero-interno.php) — o Quanto não tem componente nativo (zero uso de
   "breadcrumb" em qualquer página HTML do vendor; só existe CSS órfão .breadcrumb-area, sem
   markup correspondente). Componente novo, mínimo, no vocabulário visual do template (mesma
   fonte/peso das listas .custom-ul). --- */
.or-breadcrumb { margin-bottom: 18px; }
.or-breadcrumb ol {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    margin: 0;
    padding: 0;
    list-style: none;
    font-size: 14px;
    font-weight: 500;
    color: var(--color-1);
}
.or-breadcrumb li:not(:last-child)::after {
    content: '/';
    margin-left: 6px;
    color: var(--color-1);
}
.or-breadcrumb a { color: var(--color-primary); text-decoration: underline; text-underline-offset: 3px; }
.or-breadcrumb a:hover { color: var(--marca-primaria); }
.or-breadcrumb li[aria-current] { color: var(--color-1); }

/* --- Hero interno (_hero-interno.php) — 4 variantes visuais (evolução F2), decididas por página
   em $orHero['variante']. Até aqui TODA página interna usava o mesmo hero vazio de ~330px em
   branco (padding-top:200px do vendor + section-padding-bottom 130px) com só título — 13 das 27
   nem tinham subtítulo. clamp() escopado a .or-pg (nunca vaza pra outro contexto — a marquee da
   home usa seletor inteiramente diferente). O h1{font-size:140px} cru do vendor foi pensado pra
   títulos curtos em inglês; títulos em PT-BR são ~40% mais longos e estourariam a viewport em
   telas estreitas (mesmo achado já registrado na migração Azurio). --- */
.or-pg .or-hero-interno__title {
    font-size: var(--or-fs-h1);
    letter-spacing: -0.02em;
}
.or-hero-interno__subtitle {
    margin-top: 16px;
    /* Sem teto próprio (era 640px), mesma razão do __title logo abaixo: a coluna do hero já é o
       limite desde que ela passou a col-lg-10/col-xl-8. Com os dois, o subtítulo quebrava numa
       medida bem menor que a do título acima, deixando um degrau de largura entre os dois. */
    max-width: 100%;
    font-size: 18px;
    line-height: 1.6;
    color: var(--color-primary);
    opacity: .72;
}
.or-hero-interno__stat {
    margin: 0;
    font-size: var(--or-fs-card);
    font-weight: 700;
    color: var(--marca-primaria);
    text-align: right;
}
[data-bs-theme="dark"] .or-hero-interno__stat { color: var(--or-brand-accent); }

/* ═══════════════════════════════════════════════════════════════════════════════════════════════
   SUPERFÍCIE COMUM DAS 4 VARIANTES DE HERO INTERNO — 08/09/2026
   ═══════════════════════════════════════════════════════════════════════════════════════════════
   Pedido do dono, por print: o hero de /presenca-em-ia (variante `comercial`) é o EXEMPLO, e
   /acessibilidade (`doc`, cinza chapado) "precisa seguir a padronização" dele. A varredura mostrou
   que o problema era maior que uma página: `doc` tinha fundo `var(--color-2)` e `listagem` NÃO
   TINHA UMA ÚNICA REGRA PRÓPRIA no arquivo inteiro — herdava fundo branco, título grafite e eyebrow
   azul do padrão. Metade das páginas internas estava numa família visual e metade na oposta, sem
   nenhum critério que o visitante percebesse.

   POR QUE LISTA DE SELETORES E NÃO CÓPIA: `comercial` e `editorial` já repetiam, cada uma, as
   MESMAS tintas (título branco, subtítulo .82, breadcrumb .55/.85, hover dourado). Acrescentar
   `doc` e `listagem` copiando de novo daria QUATRO cópias da mesma regra — e a próxima correção
   de contraste seria feita em uma só. Aqui fica o que é comum; abaixo, só o que distingue cada uma.

   O QUE CONTINUA DISTINGUINDO AS QUATRO é a ESCALA DO TÍTULO (decisão do dono nesta sessão:
   "mesma família visual, tamanho de título próprio"):
     comercial → --or-fs-display (até 88px)   · frase-âncora curta de página de venda
     listagem  → --or-fs-h1 (até 64px)        · herda a base, sem regra própria
     editorial → --or-fs-h1 + max-width:900px · medida de prosa, título de artigo real
     doc       → --or-fs-secao-compacta (52px)· documento legal não é campanha

   INCONDICIONAL, nunca escopado a [data-bs-theme="dark"]: o gradiente da marca não muda com o
   tema (mesmo raciocínio de .or-home-hero). Regra de tinta que fosse só-dark deixaria o tema
   claro — que é o default — com texto escuro sobre fundo escuro. */
.or-hero-interno--comercial,
.or-hero-interno--listagem,
.or-hero-interno--editorial,
.or-hero-interno--doc {
    background: var(--or-grad-marca);
    position: relative;
    isolation: isolate;
}
/* !important no título: [data-bs-theme="dark"] :is(h1..h6){color:var(--or-text)!important} (linha
   ~508) venceria por !important mesmo com especificidade menor (0,1,1 contra 0,2,0 daqui) — achado
   ao vivo (título saía cinza --or-text em vez de branco no dark). */
.or-hero-interno--comercial .or-hero-interno__title,
.or-hero-interno--listagem .or-hero-interno__title,
.or-hero-interno--editorial .or-hero-interno__title,
.or-hero-interno--doc .or-hero-interno__title { color: #fff !important; }

.or-hero-interno--comercial .or-hero-interno__subtitle,
.or-hero-interno--listagem .or-hero-interno__subtitle,
.or-hero-interno--editorial .or-hero-interno__subtitle,
.or-hero-interno--doc .or-hero-interno__subtitle { color: #fff; opacity: .82; }

.or-hero-interno--comercial .or-breadcrumb ol,
.or-hero-interno--comercial .or-breadcrumb li:not(:last-child)::after,
.or-hero-interno--comercial .or-breadcrumb li[aria-current],
.or-hero-interno--listagem .or-breadcrumb ol,
.or-hero-interno--listagem .or-breadcrumb li:not(:last-child)::after,
.or-hero-interno--listagem .or-breadcrumb li[aria-current],
.or-hero-interno--editorial .or-breadcrumb ol,
.or-hero-interno--editorial .or-breadcrumb li:not(:last-child)::after,
.or-hero-interno--editorial .or-breadcrumb li[aria-current],
.or-hero-interno--doc .or-breadcrumb ol,
.or-hero-interno--doc .or-breadcrumb li:not(:last-child)::after,
.or-hero-interno--doc .or-breadcrumb li[aria-current] { color: rgba(255, 255, 255, .55); }

.or-hero-interno--comercial .or-breadcrumb a,
.or-hero-interno--listagem .or-breadcrumb a,
.or-hero-interno--editorial .or-breadcrumb a,
.or-hero-interno--doc .or-breadcrumb a { color: rgba(255, 255, 255, .85); }

.or-hero-interno--comercial .or-breadcrumb a:hover,
.or-hero-interno--listagem .or-breadcrumb a:hover,
.or-hero-interno--editorial .or-breadcrumb a:hover,
.or-hero-interno--doc .or-breadcrumb a:hover { color: var(--or-dourado); }

/* Eyebrow dourado nas três "etiqueta"; a `editorial` sobrescreve logo abaixo com o tom discreto
   que a caracteriza (lá é metadado do artigo, não etiqueta de campanha). */
.or-hero-interno--comercial .or-eyebrow,
.or-hero-interno--listagem .or-eyebrow,
.or-hero-interno--doc .or-eyebrow { color: var(--or-dourado); }

/* .or-tag nasce var(--color-primary) — texto grafite sobre o gradiente escuro da marca é quase
   invisível (achado real: presenca-em-ia/sobre/planos usam 'tags' com frase-âncora longa no hero;
   /faq/<slug> usa 'tags' para o nome do grupo). Mesmos valores de .or-tag--invert, mas por ESCOPO
   DE DESCENDÊNCIA (não modificador): página nova com hero + tags herda o contraste certo sem
   lembrar de aplicar a classe --invert no PHP. */
.or-hero-interno--comercial .or-tag,
.or-hero-interno--listagem .or-tag,
.or-hero-interno--editorial .or-tag,
.or-hero-interno--doc .or-tag { border-color: rgba(var(--color-white-rgb), .3); color: var(--color-white); }

.or-hero-interno--comercial .or-tag:hover,
.or-hero-interno--listagem .or-tag:hover,
.or-hero-interno--editorial .or-tag:hover,
.or-hero-interno--doc .or-tag:hover { border-color: var(--color-white); background: rgba(var(--color-white-rgb), .08); color: var(--color-white); }

/* Mesmo caso do .or-tag, para o contador ("N artigos" em /blog, "N perguntas" em /faq):
   .or-hero-interno__stat nasce var(--marca-primaria), que sobre o gradiente feito DA PRÓPRIA MARCA
   é ilegível. A única regra que existia era [data-bs-theme="dark"] (linha ~472) — override de TEMA,
   não de VARIANTE: no tema claro (default) o stat ficava azul-sobre-azul.
   ⚠️ `listagem` é quem usa `stat` em /faq — esquecê-la aqui apagaria o número da tela.
   NÃO usar --or-brand-accent: no claro essa variável É var(--marca-primaria) pura
   (or-dark.css:22) — a mesma cor do problema. */
.or-hero-interno--comercial .or-hero-interno__stat,
.or-hero-interno--listagem .or-hero-interno__stat,
.or-hero-interno--editorial .or-hero-interno__stat,
.or-hero-interno--doc .or-hero-interno__stat { color: var(--color-white); }

/* ── O que é EXCLUSIVO de cada variante ──────────────────────────────────────────────────────── */

/* --comercial: título em display — frase-âncora curta das páginas do funil (serviços/sobre/planos/
   contato/presença em IA/detalhe de serviço). */
.or-hero-interno--comercial .or-hero-interno__title { font-size: var(--or-fs-display); }

.or-home-hero__glow,
.or-hero-interno__glow {
    position: absolute;
    inset: 0;
    z-index: -1;
    background: radial-gradient(60% 60% at 82% 22%, rgba(232, 181, 61, .16) 0%, transparent 70%);
    pointer-events: none;
}

/* --editorial: título com largura de PROSA (não estica a linha até a borda em telas largas) —
   post/artigo do blog. O resto (fundo, tintas, breadcrumb) já vem do bloco comum acima; aqui fica
   só o que é exclusivo: a medida de leitura e o tom discreto do eyebrow (metadado do artigo —
   categoria · data · tempo de leitura —, não etiqueta de campanha como nas outras três).

   NÃO virou `--comercial`: aquela variante usa `--or-fs-display` (até 88px), calibrado para
   frase-âncora curta de página de venda — um título de artigo real ("O que muda quando seu
   negócio aparece nas respostas de IA") em 88px ocuparia a tela inteira. A tipografia de prosa
   é o que distingue as duas, não mais a superfície (unificada em 08/09/2026). */
.or-hero-interno--editorial .or-hero-interno__title { max-width: 900px; }
.or-hero-interno--editorial .or-eyebrow {
    color: rgba(255, 255, 255, .78);
    opacity: 1;
    text-transform: none;
    letter-spacing: 0;
    font-weight: 500;
}
.or-hero-interno--editorial .or-eyebrow::before { background: var(--or-dourado); }

/* --doc: título compacto — políticas/acessibilidade/FAQ-detalhe/página CMS genérica. Documento
   legal não é campanha; o degradê entrou em 08/09/2026 (pedido do dono, "seguir a padronização do
   hero de /presenca-em-ia"), mas o título continua menor que o das páginas de venda — é a única
   coisa que ainda distingue esta variante das demais.
   `--or-fs-secao-compacta` (não `--or-fs-secao`): não deve herdar o teto de 64px do D3. */
.or-hero-interno--doc .or-hero-interno__title { font-size: var(--or-fs-secao-compacta); }

/* --- Tag list (usada por _hero-interno.php E pela seção "Para quem é" da home) — o Quanto não
   tem componente de chip/tag nativo (nenhuma ocorrência de .tag/.chip/.badge em style.css). --- */
.or-tag-list {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    list-style: none;
    margin: 0;
    padding: 0;
}
.or-tag-list--center { justify-content: center; }
.or-tag {
    display: inline-flex;
    align-items: center;
    padding: 10px 22px;
    border-radius: 40px;
    border: 1px solid var(--color-1);
    font-size: 15px;
    font-weight: 600;
    color: var(--color-primary);
    transition: all .3s ease;
}
.or-tag:hover { border-color: var(--marca-primaria); color: var(--marca-primaria); }
.or-tag--invert { border-color: rgba(var(--color-white-rgb), .3); color: var(--color-white); }
.or-tag--invert:hover { border-color: var(--color-white); background: rgba(var(--color-white-rgb), .08); color: var(--color-white); }

/* --- Estado .active do filtro (evolução F7, achado: portfolio.php/produtos.php alternam a classe
   .active via JS — data-filter — mas ela nunca teve CSS; o chip "selecionado" ficava visualmente
   idêntico aos demais, nenhuma pista de qual filtro estava ativo). Reusa .or-tag/.or-portfolio-
   filtro em ambas as páginas (mesmo componente, nomeado só uma vez). */
.or-tag.active,
.or-portfolio-filtro.active {
    background: var(--marca-primaria);
    border-color: var(--marca-primaria);
    color: var(--color-white);
}
.or-tag.active:hover,
.or-portfolio-filtro.active:hover {
    border-color: var(--marca-secundaria, var(--marca-primaria));
    background: var(--marca-secundaria, var(--marca-primaria));
    color: var(--color-white);
}

/* --- .or-social-links/.or-social-link (Social::render()/::shareButtons(), includes/Social.php) —
   evolução F7, achado: 0% de CSS em 3 usos reais (compartilhar do post, redes de equipe-membro,
   redes de parceiro) — os <a> apareciam como link cru, ícone SVG do tamanho que Icon::render()
   emitir, sem alinhamento. Botões circulares 40px (mesmo vocabulário de .or-tag: borda neutra,
   hover preenche com a marca). --- */
.or-social-links { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.or-social-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    border: 1px solid var(--color-1);
    color: var(--color-primary);
    transition: all .3s ease;
}
.or-social-link svg { width: 18px; height: 18px; }
.or-social-link:hover { background: var(--marca-primaria); border-color: var(--marca-primaria); color: var(--color-white); }
[data-bs-theme="dark"] .or-social-link { border-color: var(--or-border); }

/* --- Filtro de /portfolio e /produtos — transição suave no show/hide (evolução F7; MixItUp
   tentado e revertido por bug real no build do vendor, ver docblock de or-tema-motion.js). Não
   colapsa o espaço do item no grid ao esconder — isso exigiria recalcular o layout via JS (o que
   é literalmente o que o MixItUp faria se funcionasse); troca visível é opacidade+escala, não um
   reflow perfeito, mas já é muito melhor que o display:none instantâneo anterior. visibility com
   transition-delay: ao esconder, primeiro perde opacidade, só sai da árvore de acessibilidade
   DEPOIS da animação; ao reaparecer, visibility volta na hora e a opacidade some com ela. */
.or-portfolio-filter-item {
    transition: opacity .35s ease, transform .35s ease;
}
.or-portfolio-filter-item--oculto {
    opacity: 0;
    transform: scale(.92);
    pointer-events: none;
    visibility: hidden;
    transition: opacity .35s ease, transform .35s ease, visibility 0s .35s;
}
/* Compartilhar do post (post.php) — label + botões na mesma linha. */
.or-blog-share { display: flex; align-items: center; flex-wrap: wrap; gap: 14px; }

/* --- .or-empty — estado vazio padrão (evolução F7, achado: 9 listagens usavam só um <p
   class="t-muted"> cru, sem peso visual nenhum). var(--or-text-muted) já é dark-safe (mesmo
   token de .t-muted) — sem override extra necessário. --- */
.or-empty { text-align: center; padding: 60px 20px; }
.or-empty__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 48px;
    height: 48px;
    margin-bottom: 18px;
    color: var(--or-text-muted);
}
.or-empty__icon svg { width: 100%; height: 100%; }
.or-empty__titulo { color: var(--color-primary); margin-bottom: 0; }

/* ================================================================
   MEGA-RODAPÉ EDITORIAL (_rodape.php) — F3 do plano de alinhamento de layout/estrutura
   (26/08/2026). Substitui as ~290 linhas de CSS de rodapé do vendor que nunca tiveram markup
   correspondente (style.css 5877-5879, 5884-5933, 5996-6010, 6046-6109, 6150-6236, 6238-6345) e
   as classes vivas que embutiam a armadilha de flip abaixo.

   REGRA DE COR — o rodapé é a ÚNICA superfície PERMANENTEMENTE ESCURA nos dois temas (a regra
   dark mais abaixo força footer.bg-color-primary → --or-surface-2, pra impedir a inversão
   fotográfica que trataria isto como "card claro"). Nesse contexto var(--color-white)/
   var(--color-primary) são ARMADILHA — os dois FLIPAM no dark (bloco de tokens acima) e viram
   quase-preto sobre fundo escuro. Bug VIVO achado nesta fase: style.css:5963
   (.footer-widgets .widget-links{color:var(--color-white)}) media ~1,05:1 de contraste no dark.
   Por isso os tokens abaixo são LITERAIS rgba() — imunes ao flip, um único ponto de ajuste. Mesmo
   raciocínio já usado em .or-llms-file (janela de terminal) e no bezel de .or-device--phone.

   Contraste medido sobre o fundo real do rodapé (bg-color-primary claro / --or-surface-2 dark):
     --or-rd-tinta    (#fff)                 ≈ 15:1  → títulos
     --or-rd-tinta-2  (rgba(255,255,255,.78)) ≈ 9,5:1 → corpo de texto e links (AA normal ✔)
     --or-rd-tinta-3  (rgba(255,255,255,.58)) ≈ 5,8:1 → texto auxiliar/copyright (AA normal ✔ — PISO)
     --or-rd-borda    (rgba(255,255,255,.14)) ≈ 3,2:1 → fronteira de componente (1.4.11 ✔)
   Nada abaixo de .58 pode carregar texto. ================================================================ */
.or-rd {
    --or-rd-tinta:    #fff;
    --or-rd-tinta-2:  rgba(255, 255, 255, .78);
    --or-rd-tinta-3:  rgba(255, 255, 255, .58);
    --or-rd-camada:   rgba(255, 255, 255, .05);
    --or-rd-camada-2: rgba(255, 255, 255, .09);
    --or-rd-borda:    rgba(255, 255, 255, .14);
    /* Default real (não só o fallback do var()): _rodape.php sempre sobrescreve por instância via
       style="--or-rd-cols:N" no <nav> (3 ou 4 colunas conforme o banco — PHP conta em runtime,
       nunca auto-fit, pra não esticar 2 colunas a 50% cada ao lado da coluna de marca). Mesmo
       padrão de --or-fab-lift (fab-stack.php:116 declara :root com default, lgpd-banner.js
       sobrescreve depois via setProperty) — aqui é local ao componente, não ao documento. */
    --or-rd-cols: 3;
    color: var(--or-rd-tinta-2);
}
/* .or-pg (sistema tipográfico) termina no mainClose(), ANTES do <footer> — todo h2..h4 aqui cai
   no CRU do vendor (h2=100px, h3=80px, style.css:120-152) com color:var(--color-black) (#000,
   nunca flipado → invisível no rodapé escuro). Cada heading precisa de font-size E color
   explícitos por isso — é a causa raiz de o rodapé antigo usar <h6> (24px) com .text-color-white:
   não era escolha semântica, era o único par que "funcionava". */
.or-rd :is(h2, h3, h4) { color: var(--or-rd-tinta); }

/* --- Andar 1: faixa de CTA (condicional — só home/404, ver _rodape.php) --- */
.or-rd-cta {
    position: relative;
    isolation: isolate;
    overflow: hidden;
    padding-block: clamp(56px, 6vw, 88px); /* −32px de ar puro: abre espaço para a escada de atrito sem crescer a faixa. */
    background: var(--or-grad-marca);
    text-align: center;
}
.or-rd-cta__glow {
    position: absolute; inset: 0; z-index: 0; pointer-events: none;
    background: radial-gradient(55% 65% at 50% 30%, rgba(232, 181, 61, .18) 0%, transparent 70%);
}
/* Marquee decorativo — era .or-rd-cta__marquee, só aqui. Virou componente compartilhado
   (05/09/2026, F2 do alinhamento de layout): .or-marquee-fundo, BLOCO 21 mais abaixo neste
   arquivo — usado também por .or-secao-cta e pagina-planos.php. */
.or-rd-cta__conteudo { position: relative; z-index: 1; }
/* !important obrigatório — achado ao vivo de 29/08/2026 (print do dono, eyebrow "PRÓXIMO PASSO"
   literalmente invisível): esta regra sempre tentou color:var(--or-dourado), mas .or-eyebrow
   base (~linha 1043, color:var(--marca-primaria)) empata em especificidade (0,1,0 cada) e vem
   DEPOIS no arquivo — a base vencia. Medido: texto var(--marca-primaria) sobre
   var(--or-grad-marca), a MESMA cor de marca como fundo, 1,00:1. .or-rd-cta nunca muda no escuro
   (fundo fixo, ver comentário do bloco acima) — dourado é seguro nos dois temas, sem variante. */
.or-rd-cta__eyebrow { justify-content: center; color: var(--or-dourado) !important; }
.or-rd-cta__titulo {
    font-size: var(--or-fs-secao);
    line-height: 1.1;
    letter-spacing: -.02em;
    margin-bottom: 12px;
}
.or-rd-cta__sub {
    max-width: 560px; margin: 0 auto 32px;
    font-size: var(--or-fs-lead);
    color: var(--or-rd-tinta-2);
}
/* Botão dourado: MESMO papel do .or-secao-cta__btn (ponto nº3 da lista fechada do dourado) — as
   duas faixas nunca coexistem na mesma página ($orCtaEmitido), então não há 2º ponto dourado. */
.or-rd-cta__btn.quanto-link-btn.btn-pill,
.or-rd-cta__btn.quanto-link-btn.btn-pill span .arry1,
.or-rd-cta__btn.quanto-link-btn.btn-pill span .arry2 { color: var(--or-ink-deep); }
.or-rd-cta__btn.quanto-link-btn.btn-pill {
    background-color: var(--or-dourado);
    border-color: var(--or-dourado);
}

/* --- Andar 2: corpo (marca + colunas de links) --- */
.or-rd-corpo { padding-block: clamp(56px, 6vw, 88px); }

/* 1fr|2.15fr desde 28/08/2026 (era 1.1fr|2.6fr): com a coluna "Links" removida sobraram 3 colunas,
   e a proporção antiga deixava a zona de links larga demais enquanto a marca continuava com buraco.
   Medido a 1580px: marca ≈481px, links ≈1035px → 3 colunas de ~329px (eram 248px). */
.or-rd-topo {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 2.15fr);
    gap: 48px 64px;
    padding-bottom: 56px;
    border-bottom: 1px solid var(--or-rd-borda);
}
/* Casos degenerados — fork sem serviços e/ou sem contato cadastrados. Sem isto, 1 coluna solitária
   esticaria por toda a zona B. Mesma doutrina da contagem server-side: grade determinística. */
.or-rd-topo--cols-1,
.or-rd-topo--cols-2 { grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr); }
@media (max-width: 991.98px) {
    .or-rd-topo,
    .or-rd-topo--cols-1,
    .or-rd-topo--cols-2 { grid-template-columns: 1fr; gap: 40px; padding-bottom: 40px; }
}

/* 440px (era 380px): a zona da marca ficou mais larga com a nova proporção, e o texto precisa de
   teto de medida de leitura — sem ele a descrição estica além do confortável. */
.or-rd-marca { max-width: 440px; }
.or-rd-marca__logo { display: inline-block; margin-bottom: 24px; }
.or-rd-marca__logo img { max-height: 40px; width: auto; display: block; }
.or-rd-marca__nome { font-size: 1.375rem; font-weight: 700; color: var(--or-rd-tinta); margin-bottom: 16px; }
.or-rd-marca__texto { font-size: .95rem; line-height: 1.65; color: var(--or-rd-tinta-2); margin-bottom: 0; overflow-wrap: anywhere; }
.or-rd-social { margin-top: 28px; }
.or-rd-social__lista { display: flex; flex-wrap: wrap; gap: 10px; list-style: none; margin: 0; padding: 0; }
.or-rd-social__link {
    display: inline-flex; align-items: center; justify-content: center;
    width: 42px; height: 42px; border-radius: 50%;
    border: 1px solid var(--or-rd-borda);
    color: var(--or-rd-tinta);
    transition: background-color .15s ease, border-color .15s ease, transform .15s ease;
}
.or-rd-social__link svg { width: 18px; height: 18px; }
/* `color` reafirmado no :hover pela MESMA razão do .or-secao-cta__canal (ver a nota longa no BLOCO
   11): a regra global `a:hover` deste arquivo pinta todo <a> com --marca-secundaria, e sobre o
   rodapé (--or-rd-camada, permanentemente escuro) isso derrubava o ícone social de branco para
   #082C6A — contraste medido de 1,19:1, praticamente invisível. A regra local já vencia por
   especificidade, mas declarava só background/border-color, e propriedade não declarada não é
   herdada da regra mais específica. */
.or-rd-social__link:hover {
    background: var(--or-rd-camada-2);
    border-color: var(--or-rd-tinta);
    color: var(--or-rd-tinta);
    transform: translateY(-2px);
}

/* Colunas: N vem de PHP via --or-rd-cols (custom property inline no <nav>). Com auto-fit, 2
   colunas restantes esticariam a 50% cada ao lado da coluna de marca — contagem server-side
   deixa a grade determinística nos 3 estados reais (3/4/5 colunas conforme banco). */
.or-rd-links {
    display: grid;
    grid-template-columns: repeat(var(--or-rd-cols, 3), minmax(0, 1fr));
    gap: 40px 24px;
}
@media (max-width: 991.98px) { .or-rd-links { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 479.98px) { .or-rd-links { grid-template-columns: 1fr; gap: 32px; } }
/* minmax(0,1fr) no TRACK não basta — o ITEM de grid ainda nasce com min-width:auto por padrão
   (a "gotcha" clássica do CSS Grid), então um link/e-mail longo sem espaço pra quebrar podia
   estourar a coluna mesmo com o track corretamente limitado. */
.or-rd-col { min-width: 0; }

.or-rd-col__titulo {
    font-size: .8125rem; font-weight: 600;
    letter-spacing: .1em; text-transform: uppercase;
    color: var(--or-rd-tinta);
    margin-bottom: 20px;
}
.or-rd-lista { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 12px; }

/* Sublinhado deslizante — mesma técnica do vendor (style.css:5983-5995), reescrita com tinta
   imune a flip. .or-rd-link serve <a> e <button> (o de "Preferências de cookies") — por isso
   o reset de chrome nativo (background/border/padding/text-align/font-family). */
.or-rd-link {
    position: relative; display: inline-block;
    max-width: 100%;
    font-size: .95rem; line-height: 1.45;
    color: var(--or-rd-tinta-2);
    background: none; border: 0; padding: 0; text-align: left; font-family: inherit;
    cursor: pointer;
    transition: color .15s ease;
}
.or-rd-link::after {
    content: ''; position: absolute; left: 0; bottom: -2px;
    width: 0; height: 1px; background: currentColor;
    transition: width .25s ease;
}
.or-rd-link:hover { color: var(--or-rd-tinta); }
.or-rd-link:hover::after { width: 100%; }
.or-rd-link:focus-visible { outline: 2px solid var(--or-dourado); outline-offset: 3px; border-radius: 2px; }

.or-rd-contato { font-style: normal; display: flex; flex-direction: column; gap: 14px; margin: 0; }
.or-rd-contato__item { display: flex; align-items: flex-start; gap: 10px; margin: 0; font-size: .95rem; line-height: 1.5; color: var(--or-rd-tinta-2); }
.or-rd-contato__ico { flex-shrink: 0; width: 17px; height: 17px; margin-top: .18em; opacity: .7; }

/* --- Andar 3: newsletter em faixa própria (fora dos 25% que ocupava antes) — proporção 5/7 já
   provada pelo rodapé Canvas do core. newsletter_form.php é CORE, não editado — só recebe
   $nlFormId/$nlEscuro. --- */
.or-rd-nl {
    display: grid;
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    align-items: center;
    gap: 24px 48px;
    margin-top: 48px;
    padding: 32px;
    border-radius: var(--or-radius-l);
    background: var(--or-rd-camada);
    border: 1px solid var(--or-rd-borda);
}
@media (max-width: 991.98px) { .or-rd-nl { grid-template-columns: 1fr; padding: 24px; } }
.or-rd-nl__texto { min-width: 0; } /* mesma gotcha do grid-item — ver .or-rd-col acima */
.or-rd-nl__titulo { font-size: var(--or-fs-h3); line-height: 1.2; letter-spacing: -.015em; margin-bottom: 8px; }
.or-rd-nl__sub { font-size: .95rem; line-height: 1.55; color: var(--or-rd-tinta-2); margin: 0; }
/* SEM teto de largura (era max-width:520px) — a coluna do form é 7fr (~893px a 1580px) e o teto
   deixava ~375px vazios à direita, sobra visível medida ao vivo (29/08/2026). O input já cresce
   (flex:1 1 auto) e o texto de consentimento ganha mais linha útil, então preencher a coluna toda
   não piora a leitura — só fecha o buraco. */
.or-rd-nl__form .or-newsletter-form { max-width: 100%; }

.or-rd-nl .or-newsletter-form .input-group { display: flex; align-items: stretch; }
/* input/botão do form do core — 2 fixes de contraste achados nesta fase (WCAG 1.4.11, mínimo
   3:1 de fronteira de componente): o input tinha bg var(--color-3) sem borda (~1,15:1 no dark);
   o botão tem background INLINE no core (style="background-color:var(--marca-primaria)") — só
   vencível com !important — que contra o fundo do rodapé media ~1,41:1. */
.or-rd-nl .or-newsletter-form input[type="email"].form-control {
    flex: 1 1 auto;
    height: 60px;
    padding: 0 20px;
    border: 1px solid var(--or-rd-borda);
    border-radius: .5rem 0 0 .5rem;
    background: rgba(0, 0, 0, .22);
    color: var(--or-rd-tinta);
}
.or-rd-nl .or-newsletter-form input[type="email"].form-control::placeholder { color: var(--or-rd-tinta-3); opacity: 1; }
.or-rd-nl .or-newsletter-form input[type="email"].form-control:focus,
.or-rd-nl .or-newsletter-form input[type="email"].form-control:active {
    background: rgba(0, 0, 0, .3);
    color: var(--or-rd-tinta);
    border-color: var(--or-dourado);
    box-shadow: 0 0 0 3px rgba(232, 181, 61, .25);
}
.or-rd-nl .or-newsletter-form button.button.button-rounded {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    height: 60px;
    padding: 0 24px;
    border: none;
    border-radius: 0 .5rem .5rem 0;
    font-weight: 600;
    font-size: 15px;
    white-space: nowrap;
    cursor: pointer;
    transition: background-color .3s ease;
    background-color: #fff !important;
    border-color: #fff !important;
    color: var(--or-ink-deep) !important;
}
.or-rd-nl .or-newsletter-form button.button.button-rounded:hover { background-color: var(--or-dourado) !important; border-color: var(--or-dourado) !important; }
.or-rd-nl .or-newsletter-form .form-check { margin-top: 14px; }
.or-rd-nl .or-newsletter-form .form-check-label { color: var(--or-rd-tinta-2); }
.or-rd-nl .or-newsletter-form .form-check-label a { color: inherit; text-decoration: underline; }
.or-rd-nl .or-newsletter-form .or-newsletter-feedback { color: var(--or-rd-tinta-2); font-size: .85rem; margin-top: 8px; }
.or-rd-nl .or-newsletter-form .or-newsletter-feedback:focus-visible { outline: 2px solid var(--or-dourado); outline-offset: 4px; border-radius: var(--or-radius-s); }

/* --- Andar 4: faixa de prova --- */
.or-rd-prova { margin-top: 40px; }
.or-rd-prova__titulo {
    font-size: .8125rem; font-weight: 600; letter-spacing: .1em; text-transform: uppercase;
    color: var(--or-rd-tinta-3); margin-bottom: 16px;
}
.or-rd-prova__lista { display: flex; flex-wrap: wrap; gap: 12px; list-style: none; margin: 0; padding: 0; }
.or-rd-prova__item {
    display: inline-flex; align-items: center; gap: 10px;
    padding: 10px 18px;
    border: 1px solid var(--or-rd-borda);
    border-radius: var(--or-radius-pill);
    font-size: .875rem; font-weight: 500;
    color: var(--or-rd-tinta-2);
    transition: background-color .15s ease, border-color .15s ease, color .15s ease, transform .15s ease;
}
.or-rd-prova__item:hover { background: var(--or-rd-camada-2); border-color: var(--or-rd-tinta); color: var(--or-rd-tinta); transform: translateY(-2px); }
.or-rd-prova__ico { display: inline-flex; flex-shrink: 0; color: var(--or-dourado); }
.or-rd-prova__ico svg { width: 18px; height: 18px; }
.or-rd-prova__label { white-space: nowrap; }
@media (max-width: 575.98px) { .or-rd-prova__label { white-space: normal; } }

/* --- Andar 5: barra inferior — SEM "Voltar ao topo" (ver docblock de _rodape.php) --- */
.or-rd-rodape-barra { border-top: 1px solid var(--or-rd-borda); }
.or-rd-bottom {
    display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
    gap: 12px 24px;
    padding-block: 24px;
}
@media (max-width: 767.98px) { .or-rd-bottom { justify-content: center; text-align: center; } }
.or-rd-bottom__copy { margin: 0; font-size: .875rem; color: var(--or-rd-tinta-3); }
.or-footer-onerank { display: inline-flex; align-items: center; gap: 5px; color: var(--or-rd-tinta-3); }
.or-footer-onerank a { color: inherit; text-decoration: none; font-weight: 700; }
.or-footer-onerank:hover { color: var(--or-rd-tinta); }

/* --- prefers-reduced-motion (WCAG 2.3.3) — animações CSS NATIVAS do vendor (@keyframes ...
   infinite), fora do alcance de gsap.globalTimeline.timeScale() (or-tema-a11y.js), que só afeta
   tweens GSAP. Levantamento completo de "infinite" em style.css: marquee (home + rodapé),
   bounce do "scroll down"/"section-jump", ripple do header sticky, spinners de variantes de hero
   que hoje não usamos (hero1/hero2) — cobertos por completude, sem custo (seletor não casa se a
   página não os usa). O spinner do PRELOADER fica de fora de propósito: é feedback de carregamento
   essencial (WCAG 2.3.3 é sobre movimento NÃO essencial), não decoração.
   Dois gatilhos: a preferência do SO (media query) e o override manual do widget de acessibilidade
   da plataforma (`data-or-rm`, site/assets/js/or-a11y.js) — o segundo cobre quem não mudou a
   preferência do sistema mas pediu menos movimento pelo próprio site.
   `.or-hero-caret::after` (BLOCO 2, evolução visual) é autoral, não do vendor — entra aqui pela
   mesma razão: @keyframes CSS puro, fora do timeScale do GSAP. `opacity:1` junto do animation:none
   porque o keyframe pisca opacity — sem fixar, o caret podia congelar invisível a meio-piscar. */
@media (prefers-reduced-motion: reduce) {
    .marquee-container .marquee,
    .quanto-hero3__content .content-info .section-jump,
    .scroll-down img,
    .quanto-header.v6 .status .status-dot::before,
    .quanto-header.v6 .status .status-dot::after,
    .quanto-hero__content .title span img,
    .hero2-circle-text .circle-text,
    .or-hero-caret::after {
        animation: none !important;
        opacity: 1;
    }
    /* Fade+scale do filtro de /portfolio e /produtos (evolução F7) — transition, não animation;
       reset separado porque a propriedade CSS envolvida é outra. */
    .or-portfolio-filter-item { transition: none !important; }
    /* Hovers do mega-rodapé (F3) — sublinhado deslizante + elevação (translateY). Mesma razão:
       transition, não animation; o .marquee-container .marquee acima já cobre a textura de
       fundo de TODO marquee do tema (.or-marquee-fundo reusa as classes do vendor — BLOCO 21). */
    .or-rd-link::after,
    .or-rd-social__link,
    .or-rd-prova__item,
    .or-rd-busca__btn,
    .or-rd-assinatura,
    .or-rd-assinatura__logo,
    .or-rd-cta__canal { transition: none !important; }
    .or-rd-social__link:hover,
    .or-rd-prova__item:hover { transform: none !important; }
    /* .or-card--hover (achado A4) — translateY(-4px) no hover, nunca registrado nos dois gatilhos. */
    .or-card--hover { transition: none !important; }
    .or-card--hover:hover { transform: none !important; }
    /* malha plexus do #dor: mata a transição de tinta e o scale do hover. O parallax já morre
       sozinho pelo caminho do .has-smooth (or-tema-a11y.js), sem matchMedia novo. */
    .or-dor-card__malha { transition: none !important; scale: 1 !important; }
    /* .fade/.collapsing do Bootstrap (abas de #servicos + accordion de #faqs/#como-funciona) — o
       bootstrap.min.css só protege via @media (prefers-reduced-motion), nunca o gatilho PRÓPRIO
       da plataforma (data-or-rm). Lacuna já viva no #faqs antes desta mudança — corrigida aqui pros
       dois. .or-servicos-tab tem :hover/.active com transition própria. */
    .fade, .collapsing, .or-servicos-tab { transition: none !important; }
}
html[data-or-rm="reduce"] .marquee-container .marquee,
html[data-or-rm="reduce"] .quanto-hero3__content .content-info .section-jump,
html[data-or-rm="reduce"] .scroll-down img,
html[data-or-rm="reduce"] .quanto-header.v6 .status .status-dot::before,
html[data-or-rm="reduce"] .quanto-header.v6 .status .status-dot::after,
html[data-or-rm="reduce"] .quanto-hero__content .title span img,
html[data-or-rm="reduce"] .hero2-circle-text .circle-text,
html[data-or-rm="reduce"] .or-hero-caret::after {
    animation: none !important;
    opacity: 1;
}
html[data-or-rm="reduce"] .or-portfolio-filter-item { transition: none !important; }
html[data-or-rm="reduce"] .or-rd-link::after,
html[data-or-rm="reduce"] .or-rd-social__link,
html[data-or-rm="reduce"] .or-rd-prova__item,
html[data-or-rm="reduce"] .or-rd-busca__btn,
html[data-or-rm="reduce"] .or-rd-assinatura,
html[data-or-rm="reduce"] .or-rd-assinatura__logo,
html[data-or-rm="reduce"] .or-rd-cta__canal { transition: none !important; }
html[data-or-rm="reduce"] .or-rd-social__link:hover,
html[data-or-rm="reduce"] .or-rd-prova__item:hover { transform: none !important; }
html[data-or-rm="reduce"] .or-card--hover { transition: none !important; }
html[data-or-rm="reduce"] .or-card--hover:hover { transform: none !important; }
html[data-or-rm="reduce"] .or-dor-card__malha { transition: none !important; scale: 1 !important; }
html[data-or-rm="reduce"] .fade,
html[data-or-rm="reduce"] .collapsing,
html[data-or-rm="reduce"] .or-servicos-tab { transition: none !important; }

/* --- Prosa (política, acessibilidade, página CMS genérica, resposta de FAQ) — conteúdo vindo de
   \OneRank\Content::render() (HTML sanitizado do editor rico). Tokens do Quanto (--color-primary
   é o texto neutro no claro), não os do Azurio (--t-medium/--t-bright não existem mais). */
.or-doc-body { color: var(--color-primary); font-size: 1.05rem; line-height: var(--or-lh-prosa, 1.7); }
.or-doc-body + .or-doc-body { margin-top: 32px; }
/* font-size explícito: o h3 "cru" do vendor herda 40-44px (style.css:128+) — desproporcional
   pra um subtítulo de prosa ("Documentos", "Outras perguntas"). */
.or-doc-body h2 { color: var(--color-primary); margin: 2rem 0 1rem; font-weight: 600; font-size: clamp(1.5rem, 3vw, 2rem); }
.or-doc-body h3 { color: var(--color-primary); margin: 2rem 0 1rem; font-weight: 600; font-size: clamp(1.25rem, 2.2vw, 1.5rem); }
.or-doc-body h2:first-child, .or-doc-body h3:first-child { margin-top: 0; }
.or-doc-body p { margin: 0 0 1rem; }
/* style.css não reseta list-style globalmente (diferente do main.css do Azurio) — ainda assim,
   fixamos aqui pra o conteúdo do editor nunca depender do reset padrão do browser mudar. */
.or-doc-body ul { list-style: disc; margin: 0 0 1rem; padding-left: 1.4rem; }
.or-doc-body ol { list-style: decimal; margin: 0 0 1rem; padding-left: 1.4rem; }
.or-doc-body li { margin-bottom: .4rem; }
.or-doc-body a { color: var(--texto-link, var(--marca-primaria)); text-decoration: underline; }
.or-doc-body li > ul, .or-doc-body li > ol { margin-top: .4rem; margin-bottom: 0; }
/* .t-large/.t-muted/.t-small dentro de .or-doc-body herdam do bloco global .or-pg (BLOCO 1.5) —
   não duplicar aqui (a versão antiga usava var(--color-4), nunca flipado pro dark). */

/* --- Elementos do editor rico (TinyMCE nível "completo") sem regra própria dentro de .or-doc-body
   (achado do levantamento blog/contato/legais, 04/09/2026): h4-h6 herdavam título de landing page
   do vendor, blockquote/tabela/código/hr saíam sem tratamento nenhum, e img/iframe podiam estourar
   o container. Tokens dark-safe (--texto-secundario, --or-surface-2, --or-border) — nunca hex fixo. */
.or-doc-body h4, .or-doc-body h5, .or-doc-body h6 { color: var(--color-primary); margin: 1.5rem 0 .75rem; font-weight: 600; font-size: 1.05rem; }
.or-doc-body h4:first-child, .or-doc-body h5:first-child, .or-doc-body h6:first-child { margin-top: 0; }

.or-doc-body blockquote { margin: 1.5rem 0; padding: .25rem 0 .25rem 1.25rem; border-left: 3px solid var(--marca-primaria); color: var(--texto-secundario); font-style: italic; }
.or-doc-body blockquote > :last-child { margin-bottom: 0; }

.or-doc-body table { width: 100%; border-collapse: collapse; margin: 0 0 1rem; font-style: normal; }
.or-doc-body th, .or-doc-body td { padding: .6rem .75rem; border: 1px solid var(--or-border, rgba(0, 0, 0, .08)); text-align: left; }
.or-doc-body thead th { background: var(--or-surface-2, #f6f8fb); font-weight: 600; }

.or-doc-body img { max-width: 100%; height: auto; border-radius: 8px; }
.or-doc-body figure { margin: 0 0 1rem; }
.or-doc-body figure img { display: block; margin: 0 auto; }
.or-doc-body figcaption { margin-top: .5rem; font-size: .875rem; color: var(--texto-secundario); text-align: center; }

.or-doc-body code { padding: .15em .4em; border-radius: 4px; background: var(--or-surface-2, #f6f8fb); font-size: .9em; }
.or-doc-body pre { margin: 0 0 1rem; padding: 1rem; border-radius: 8px; background: var(--or-surface-2, #f6f8fb); overflow-x: auto; }
.or-doc-body pre code { padding: 0; background: none; }

.or-doc-body hr { margin: 2rem 0; border: none; border-top: 1px solid var(--or-border, rgba(0, 0, 0, .08)); }

.or-doc-body iframe { max-width: 100%; width: 100%; aspect-ratio: 16 / 9; height: auto; border: 0; border-radius: 8px; }
.or-doc-anexos ul { list-style: none; padding-left: 0; }
.or-doc-anexos li { padding: 10px 0; border-bottom: 1px solid var(--color-1); }
.or-doc-anexos li:last-child { border-bottom: none; }
.or-doc-imagem { width: 100%; height: auto; border-radius: 8px; margin-bottom: 1rem; }

/* --- CTA de fecho (_secao-cta.php) — "momento dourado" consertado (evolução F7; o nome do
   componente já prometia isso desde a migração, mas só __link/__btn tinham CSS — a <section> em
   si herdava bg-color-2 cru, sem nenhum tratamento especial). 1 dos 6 pontos fechados de uso do
   dourado (BLOCO 0.5): botão + glow. --color-white não é flipado (sempre #fff), mas o !important
   global de h1-h6 no dark exige !important aqui também (mesmo caso já resolvido em
   .or-hero-interno--comercial). --- */
.or-secao-cta__link { display: block; text-decoration: none; }
.or-secao-cta__link .title { font-size: clamp(1.8rem, 3.5vw, 3rem); margin-bottom: 28px; }
.or-secao-cta__btn { display: inline-flex; position: relative; z-index: 1; }
.or-secao-cta { position: relative; background: var(--or-grad-marca); }
.or-secao-cta .title { color: #fff !important; }
.or-secao-cta .or-secao-cta__link:hover .title { color: var(--or-dourado) !important; }
.or-secao-cta .container { position: relative; z-index: 1; }
.or-secao-cta__glow {
    position: absolute;
    inset: 0;
    z-index: 0;
    background: radial-gradient(55% 65% at 50% 30%, rgba(232, 181, 61, .18) 0%, transparent 70%);
    pointer-events: none;
}
.or-secao-cta .or-secao-cta__btn.quanto-link-btn.btn-pill,
.or-secao-cta .or-secao-cta__btn.quanto-link-btn.btn-pill span .arry1,
.or-secao-cta .or-secao-cta__btn.quanto-link-btn.btn-pill span .arry2 {
    color: var(--or-ink-deep);
}
.or-secao-cta .or-secao-cta__btn.quanto-link-btn.btn-pill {
    background-color: var(--or-dourado);
    border-color: var(--or-dourado);
}

/* --soft — páginas documentais (política/acessibilidade/FAQ/CMS genérica): o momento dourado
   destoaria do tom neutro dessas páginas. Fundo volta a ser o bg-color-2 theme-aware original. */
.or-secao-cta--soft { background: var(--color-2); }
[data-bs-theme="dark"] .or-secao-cta--soft { background: var(--or-surface-2); }
.or-secao-cta--soft .title { color: var(--color-primary) !important; }
.or-secao-cta--soft .or-secao-cta__link:hover .title { color: var(--marca-primaria) !important; }
.or-secao-cta--soft .or-secao-cta__btn.quanto-link-btn.btn-pill,
.or-secao-cta--soft .or-secao-cta__btn.quanto-link-btn.btn-pill span .arry1,
.or-secao-cta--soft .or-secao-cta__btn.quanto-link-btn.btn-pill span .arry2 {
    color: var(--color-white);
}
.or-secao-cta--soft .or-secao-cta__btn.quanto-link-btn.btn-pill {
    background-color: var(--marca-primaria);
    border-color: var(--marca-primaria);
}

/* --- .or-card — componente único de card sutil. Substitui 3 cópias do MESMO estilo escritas à
   mão: style="padding:28px;border-radius:12px;background:var(--color-2);height:100%;" em
   filiais.php, style="background:var(--color-2);border-radius:12px;padding:28px;" em
   vaga-detalhe.php, e a classe .or-planos-addons__item (BLOCO 4) — as três nasceram do mesmo
   card e divergiram por terem sido escritas 3 vezes. Primeira sombra autoral do site (o vendor
   inteiro não tem um único box-shadow próprio — style.css é 100% retângulo chapado). */
.or-card {
    background: var(--color-2);
    border-radius: var(--or-radius-m);
    padding: 28px;
    border: 1px solid transparent;
}
.or-card--claro { background: var(--color-white); box-shadow: var(--or-shadow-1); }
.or-card--hover { transition: transform .3s ease, box-shadow .3s ease; }
.or-card--hover:hover { transform: translateY(-4px); box-shadow: var(--or-shadow-2); }
[data-bs-theme="dark"] .or-card,
[data-bs-theme="dark"] .or-card--claro {
    background: var(--or-surface-2);
    border-color: var(--or-border);
    box-shadow: none;
}

/* --- .or-eyebrow — etiqueta de abertura de seção (traço dourado + texto caps). É 1 dos 6 pontos
   fechados de uso do dourado (ver BLOCO 0.5): aqui o traço é sempre dourado; o TEXTO só vira
   dourado no dark (contraste ~8:1 sobre --or-surface — no claro o dourado não tem contraste
   suficiente pra ser texto, por isso usa a marca). */
.or-eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    font-size: var(--or-fs-eyebrow);
    font-weight: 600;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--marca-primaria);
    margin-bottom: 14px;
}
.or-eyebrow::before {
    content: '';
    display: inline-block;
    width: 28px;
    height: 2px;
    background: var(--or-dourado);
    border-radius: 1px;
}
[data-bs-theme="dark"] .or-eyebrow { color: var(--or-dourado); }

/* --- .or-divisor — hairline com traço dourado central, pra separar blocos de prosa longa
   (manifesto/sobre) sem depender de heading. Ornamento não-textual: sem exigência de contraste. */
.or-divisor {
    position: relative;
    height: 1px;
    background: var(--color-1);
    margin: 40px 0;
}
.or-divisor::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 28px;
    height: 3px;
    background: var(--or-dourado);
    border-radius: 2px;
}
[data-bs-theme="dark"] .or-divisor { background: var(--or-border); }

/* --- .or-hero-caret — assinatura visual da marca ("a resposta sendo digitada"): cursor dourado
   piscante no fim do título de todo hero. CSS puro, sem GSAP — sobrevive ao pipeline de reduced-
   motion do vendor por estar fora dele (registrado nos 2 blocos de reduced-motion existentes,
   abaixo). */
.or-hero-caret::after {
    content: '';
    display: inline-block;
    width: .14em;
    height: .9em;
    margin-left: .12em;
    vertical-align: baseline;
    background: var(--or-dourado);
    animation: or-caret 1.1s steps(2) infinite;
}
@keyframes or-caret { 50% { opacity: 0; } }

/* --- .or-device — moldura de dispositivo 100% CSS (evolução F5, "prova visual" aprovada: screenshot
   REAL do admin local, nunca mockup fabricado). Sem imagem de moldura — a barra de 3 pontos e o
   notch do phone são divs/CSS puro, então funcionam com QUALQUER captura (não dependem de recorte
   prévio). --claro força fundo branco fixo (a "janela" do device nunca deve escurecer sozinha —
   quem escurece é o CONTEÚDO da própria screenshot, que já é o admin real). */
.or-device {
    border-radius: var(--or-radius-l);
    overflow: hidden;
    box-shadow: var(--or-shadow-2);
    background: var(--color-white);
    border: 1px solid var(--color-1);
}
.or-device__screen img { display: block; width: 100%; height: auto; }
.or-device--browser .or-device__bar {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 12px 16px;
    background: var(--color-2);
    border-bottom: 1px solid var(--color-1);
}
.or-device__dot { width: 10px; height: 10px; border-radius: 50%; background: var(--color-1); }
.or-device__dot:nth-child(1) { background: #ED6A5E; }
.or-device__dot:nth-child(2) { background: #F4BF4F; }
.or-device__dot:nth-child(3) { background: #61C454; }
[data-bs-theme="dark"] .or-device {
    background: var(--or-surface);
    border-color: var(--or-border);
}
[data-bs-theme="dark"] .or-device--browser .or-device__bar {
    background: var(--or-surface-2);
    border-bottom-color: var(--or-border);
}

/* --- .or-device--phone — bezel físico (var(--or-ink-deep) fixo de propósito: um aparelho é
   preto/escuro na mão do usuário nos dois temas do SITE — não é superfície do tema, não flipa). --- */
.or-device--phone {
    position: relative;
    max-width: 260px;
    margin-inline: auto;
    border-radius: 32px;
    border: 8px solid var(--or-ink-deep);
    background: var(--or-ink-deep);
}
.or-device--phone .or-device__notch {
    position: absolute;
    top: 0;
    left: 50%;
    transform: translateX(-50%);
    width: 46%;
    height: 20px;
    background: var(--or-ink-deep);
    border-radius: 0 0 12px 12px;
    z-index: 2;
}
.or-device--phone .or-device__screen { position: relative; overflow: hidden; border-radius: 24px; }

/* --- .or-link--claro — variante de .quanto-link-btn pra fundo escuro fixo (bg-color-primary,
   footer, hero da home). O vendor hardcoda var(--color-primary) em 3 lugares (borda, span,
   .arry1/.arry2 — nenhum usa currentColor), então "adicionar text-color-white" sozinho NÃO basta
   (texto fica branco, seta e sublinhado continuam escuros). Precisa igualar a especificidade do
   :hover do vendor (0,3,1) pra não perder a cor no hover — carregado depois de style.css, cascata
   resolve o empate a favor daqui.
   #fff LITERAL, nunca var(--color-white): esse token FLIPA no dark (linha ~939, vira
   var(--or-surface) = #15171c) — sobre um fundo permanentemente escuro isso é texto quase-preto,
   ilegível. Bug vivo achado no plano de alinhamento de layout (sobre.php:94, ~1,1:1 de contraste)
   e corrigido aqui na fonte, não com um override [data-bs-theme=dark] a mais. --- */
.or-link--claro,
.or-link--claro span,
.or-link--claro span .arry1,
.or-link--claro span .arry2 {
    color: #fff;
}
.or-link--claro { border-bottom-color: #fff; }
/* ⚠️ O :hover PRECISA declarar a cor do PRÓPRIO link, não só das setas (achado 03/09/2026, pego
   pelo dono num print do CTA do rodapé): até aqui esta regra cobria apenas `.arry1`/`.arry2`, então
   no hover o texto do <a> caía na global `a:hover { color: var(--marca-secundaria) }` (linha ~168)
   — #082C6A, que é EXATAMENTE um dos stops do gradiente escuro desta faixa. O texto sumia e sobrava
   só o sublinhado branco.
   É a MESMA armadilha já documentada em .or-secao-cta__btn2 (linha ~4505): propriedade não
   declarada na regra específica não é "herdada" dela — cada uma resolve por conta própria, e a
   global de elemento alcança todo <a> do site. A correção tinha sido aplicada lá e nunca aqui.
   Regra: link novo sobre fundo escuro declara o `color` do :hover junto, sempre. */
.or-link--claro:hover,
.or-link--claro:hover span,
.or-link--claro:hover span .arry1,
.or-link--claro:hover span .arry2 {
    color: #fff;
}
/* <button> disfarçado de link (toggle de tema): reset de chrome nativo pra ficar idêntico aos <a>
   irmãos. NÃO usar a shorthand "border" sozinha — apagaria o border-bottom que .quanto-link-btn
   depende pro sublinhado; por isso restaura só esse lado.

   ⚠️ NASCEU ACOPLADO A .or-link--claro e deixou de poder ser (03/09/2026). A regra fixava
   `border-bottom: 1px solid #fff` e contava com o `color:#fff` da variante clara — funcionava
   porque o único uso vivia numa faixa escura. Quando o bloco "Este site é a demonstração" (/sobre)
   passou a fundo CLARO na remodelação, o botão ficou órfão: sublinhado branco sobre branco
   (invisível) e texto na cor default do <button>, PRETO ao lado de três <a> azuis — a mesma
   armadilha que o comentário do :hover logo acima descreve, com o agravante de que a global
   `a { color: … }` sequer alcança um <button>.

   currentColor na borda faz o sublinhado seguir o texto em qualquer fundo. O :not() carrega a cor
   de link só quando a variante clara NÃO está presente — e é :not(), não uma regra solta, porque
   .or-link--claro vem ANTES no arquivo: com especificidade igual a última venceria, e o botão em
   faixa escura voltaria a ficar azul. */
.or-link--botao {
    background: none;
    border: none;
    border-bottom: 1px solid currentColor;
    padding: 0 0 4px;
    cursor: pointer;
    font-family: inherit;
}
/* border-bottom-color explícito, e não só currentColor: o .quanto-link-btn do vendor sublinha em
   var(--color-primary) enquanto o TEXTO do <a> vem da global de link (--texto-link). Sem esta
   linha o botão sublinharia na própria cor do texto e ficaria com um traço azul entre três
   escuros — quase igual, que num bloco cuja tese é "somos a demonstração" é pior que diferente. */
.or-link--botao:not(.or-link--claro) {
    color: var(--texto-link);
    border-bottom-color: var(--color-primary);
}

/* ================================================================
   BLOCO 3 — TEMA · HOME (componentes usados só na home; ao migrar as próximas páginas, o que for
   compartilhado sobe pro BLOCO 2).
   ================================================================ */

/* --- Hero da home — .quanto-hero4-section (grade prova/conteúdo, ALTURA DE CONTEÚDO). Substitui
   o .quanto-hero3-section/marquee anterior: aquele tinha min-height:100vh COM justify-content:end,
   mas os paddings do vendor somavam mais que uma tela (≥1400px: padding-top 450 + marquee 200+200
   + padding-bottom 160 ≈ 1010px só de espaçamento — min-height:100vh é PISO, não teto). Medido ao
   vivo: 1176px de hero numa tela de 900px (achado do plano de alinhamento de layout/estrutura).
   O vendor entrega pouquíssimo pro hero-4 (só padding-top, .title br, e p{max-width:544px}/
   __info p{max-width:244px} — style.css:2322-2374; index-4.html não existe neste fork, só no
   zip). Fundo, padding-bottom, tipografia do título e a prova são 100% autorais.
   isolation:isolate é o que faz .or-home-hero__glow (z-index:-1, ver .or-hero-interno__glow
   acima) existir: sem contexto de empilhamento próprio ele sobe pro #smooth-content (que tem
   transform do GSAP) e é pintado ATRÁS do gradiente — mesmo fix já em .or-hero-interno--comercial
   (linha ~326). Sem ::before aqui: era só pra neutralizar o hero3-overlay.png do hero anterior;
   .quanto-hero4-section não tem ::before nenhum no vendor. --- */
.or-home-hero {
    position: relative;
    isolation: isolate;
    background: var(--or-grad-marca);
    padding-bottom: 110px;
}
@media only screen and (max-width: 1199.98px) { .or-home-hero { padding-bottom: 80px; } }
@media only screen and (max-width: 991.98px)  { .or-home-hero { padding-bottom: 64px; } }
/* Notebook baixo-e-largo (1920×800, 2560×919 — a tela onde o defeito foi relatado): o
   padding-top:200px do vendor (.quanto-hero-section, herdado por _hero-interno.php) olha só
   LARGURA, nunca altura. Único ponto onde o hero antigo estourava por espaçamento puro, não por
   min-height.
   max-height CORRIGIDO de 780px pra 960px (26/08/2026): o bloco já citava "1920×800, 2560×919" na
   doc acima, mas 780px nunca cobriu NENHuma das duas (800 e 919 > 780) — a compensação nunca
   disparava nas telas que o próprio comentário descrevia. padding-bottom entra na compensação
   agora também (antes só o top era ajustado, e o hero seguia fechando com 110px cheios). */
@media only screen and (min-width: 1400px) and (max-height: 960px) {
    /* O padding-top absoluto virou respiro: o topo agora é `header real + --or-hero-ar` (bloco "A
       faixa do hero", fim do arquivo). Nesta largura o padrão já é 90 + 32 = 122px — abaixo dos
       140px que esta compensação entregava antes de 02/09 — então não precisa mais de um
       `--or-hero-ar` maior aqui: só o padding-bottom continua reduzido, para a tela baixa. */
    .or-home-hero { padding-bottom: 70px; }
}

/* O vendor limita o parágrafo do hero a `max-width: 544px` (style.css:2357) — uma medida fixa,
   herdada do layout original, que não conversa com a coluna onde o texto vive aqui. A coluna já
   define a largura da linha; um teto em pixels dentro dela só estreita o parágrafo mais do que o
   necessário e força quebras cedo demais. Soltar para 100% devolve o controle à coluna.
   Override no custom.css — o style.css do template NUNCA é editado. */
.or-home-hero .quanto-hero4__content p { max-width: 100%; }

/* Slot de vídeo de fundo (F4.2 da evolução "primeira tela") — pronto e inerte, só existe no DOM
   quando site/_template/video/hero.{mp4,webm} está no disco (home.php, is_file()). Vídeo (z:0) +
   overlay com --or-grad-marca semi-opaco (z:1) por cima — NUNCA o vídeo cru: o texto branco do
   hero precisa manter contraste ≥4,5:1 independente do que está sendo filmado. .or-home-hero>
   .container ganha z:2 pra ficar acima dos dois — sem isso, um elemento position:absolute com
   z-index:0 pinta DEPOIS de conteúdo estático em fluxo normal (CSS2.1 Apêndice E) e cobriria o
   texto. Sem vídeo (hoje, sempre), nada disto existe no DOM — .or-home-hero mantém o próprio
   background sólido (regra acima) e o hero é byte-idêntico ao de antes desta evolução. */
.or-home-hero--com-video { background: var(--or-ink-deep); }
.or-home-hero__video {
    position: absolute;
    inset: 0;
    z-index: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.or-home-hero__video-overlay {
    position: absolute;
    inset: 0;
    z-index: 1;
    background: var(--or-grad-marca);
    opacity: .84;
}
.or-home-hero > .container { position: relative; z-index: 2; }

/* Eyebrow: .or-eyebrow nasce var(--marca-primaria) — azul de marca sobre o gradiente de marca é
   invisível. Não é um 7º ponto dourado: é o mesmo ponto nº6 da lista fechada (eyebrow em fundo
   escuro), já autorizado em .or-hero-interno--comercial .or-eyebrow (linha ~322). */
.or-home-hero .or-eyebrow { color: var(--or-dourado); }

/* Título: .title num <h1> cai no h1 CRU do vendor (140px/-4.2px, style.css:117-121 — pensado pra
   1-2 palavras em inglês). !important é cinto-e-suspensório do padrão da casa: hoje
   [data-bs-theme=dark] :is(h1..h6) (linha ~508) não tem !important — (0,1,1) já perderia pra
   (0,2,0) daqui — mas imuniza contra o core voltar a usar !important ali (como já fez em
   .text-color-white, linha ~939).
   font-size usa --or-fs-display-hero (token PRÓPRIO, não o --or-fs-display compartilhado com
   .or-hero-interno--comercial das páginas internas) — teto 68px em vez de 88px: com a frase-âncora
   + o complemento rotativo mais longo do seed de banners, 88px estourava em 4 linhas e cortava o
   hero em notebooks baixos (achado 26/08/2026). Baixar o token global mudaria as internas junto;
   este é escopado só ao hero da home. */
.or-pg .or-home-hero__title {
    margin: 0;
    font-size: var(--or-fs-display-hero);
    line-height: 1.03;
    letter-spacing: -.02em;
    color: #fff !important;
}
.or-home-hero__subtitulo {
    margin: 20px 0 0;
    max-width: 544px;
    font-size: var(--or-fs-lead);
    line-height: 1.55;
    color: rgba(255, 255, 255, .82);
}

/* Rotator (F3 da evolução "primeira tela") — troca o complemento do H1/subtítulo entre banners de
   tbl_banners (BAN_SECAO='hero'). [hidden] nativo (display:none) já tira o item inativo do fluxo
   visual E da árvore de acessibilidade — zero CSS extra pra "esconder". .is-active só existe pra
   dar um gancho estável ao JS (or-tema-motion.js) sem depender de reler o atributo hidden.
   .or-hero-rotator__pausa/__proxima moram ao lado dos CTAs (não dentro do H1) — precisam ser
   elementos focáveis de verdade pro WCAG 2.2.2 (Pause/Stop/Hide) ter um controle discoverável por
   teclado; só são renderizados quando há 2+ banners vigentes (home.php). Ícone via Icon::render,
   herda #fff. */
.or-hero-rotator { display: inline; }
.or-hero-rotator__item { display: inline; }
/* 44×44 (auditoria A-15, 28/08/2026): eram 40×40, abaixo do alvo de toque mínimo. Vale o dobro
   aqui porque um deles é o botão de PAUSA da rotação — controle exigido por WCAG 2.2.2, e alvo
   pequeno demais compromete exatamente quem mais precisa dele. */
.or-hero-rotator__pausa,
.or-hero-rotator__proxima {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    padding: 0;
    border: 1px solid rgba(255, 255, 255, .3);
    border-radius: 50%;
    background: transparent;
    color: #fff;
    line-height: 0;
    transition: background-color .15s ease, border-color .15s ease;
}
.or-hero-rotator__pausa:hover,
.or-hero-rotator__pausa:focus-visible,
.or-hero-rotator__proxima:hover,
.or-hero-rotator__proxima:focus-visible { background: rgba(255, 255, 255, .12); border-color: rgba(255, 255, 255, .5); }
.or-hero-rotator__pausa:focus-visible,
.or-hero-rotator__proxima:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.or-hero-rotator__pausa svg,
.or-hero-rotator__proxima svg { width: 16px; height: 16px; }

/* Feedback visual do estado pausado (achado real, 26/08/2026): o handler de or-tema-motion.js só
   trocava aria-pressed/aria-label — o SVG continuava sendo player-pause mesmo depois de pausar,
   sem sinal nenhum pro usuário vidente (só quem lê aria-label percebia a mudança). O botão agora
   emite os DOIS ícones (home.php) e o CSS alterna por [aria-pressed], sem tocar em classList. */
.or-hero-rotator__pausa svg:last-child { display: none; }
.or-hero-rotator__pausa[aria-pressed="true"] svg:first-child { display: none; }
.or-hero-rotator__pausa[aria-pressed="true"] svg:last-child { display: inline; }

/* CTAs — flex-wrap é o conserto direto do defeito de origem: a .content-info do hero-3 era flex
   SEM wrap, e em 375px sobravam ~117px pro subtítulo (o resto ia pro .price-info sem quebrar). */
.or-home-hero__acoes {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 16px 28px;
    margin-top: 32px;
}
/* Primário: pílula BRANCA LITERAL, nunca .btn-light do vendor — usa var(--color-white)/
   var(--color-primary), que FLIPAM no dark (linha ~939-940); o botão viraria escuro sobre um
   gradiente que não flipa. Especificidade (0,4,0), e as setas em (0,5,1) vencem o :hover do
   vendor (0,3,1) — sem precisar de !important. Hover NÃO vira dourado: a lista de 6 pontos
   cerimoniais é fechada e o CTA de hero não está nela — o feedback é a elevação. */
.or-home-hero .or-home-hero__cta.quanto-link-btn.btn-pill {
    background-color: #fff;
    border-color: #fff;
    color: var(--or-ink-deep);
    transition: box-shadow .3s ease;
}
.or-home-hero .or-home-hero__cta.quanto-link-btn.btn-pill span .arry1,
.or-home-hero .or-home-hero__cta.quanto-link-btn.btn-pill span .arry2 { color: var(--or-ink-deep); }
.or-home-hero .or-home-hero__cta.quanto-link-btn.btn-pill:hover { box-shadow: 0 10px 28px rgba(0, 0, 0, .28); }

/* Prova — 3 indicadores reais (53 módulos · 12 segmentos · 3 níveis de plano; ver home.php).
   .counter-item não tem NENHUMA regra no vendor (só é gancho de main.js:64/or-tema-motion.js —
   .find(".odometer")): a tipografia do número é toda daqui.

   REDESENHADO (evolução "primeira tela", 26/08/2026) — era rail vertical ao lado do conteúdo
   (grid de 3 colunas que virava 1 coluna empilhada ≥1200px); virou tira horizontal compacta SOB
   os CTAs (.custom-container trava em 1604px mesmo a 2560px de viewport — o painel de resposta
   novo só cabe como 2ª coluna se o conteúdo ficar largo, e uma 3ª coluna pro rail não fecha a
   conta). .or-home-hero__prova = list-reset genérico; .or-home-hero__prova--inline = a moldura
   nova (única usuária hoje). */
.or-home-hero__prova {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
}
.or-home-hero__prova--inline {
    gap: 10px 32px;
    margin-top: 36px;
    padding-top: 24px;
    border-top: 1px solid rgba(255, 255, 255, .16);
}
.or-home-hero__prova--inline .or-home-hero__stat {
    display: flex;
    align-items: baseline;
    gap: 10px;
    padding-right: 32px;
    border-right: 1px solid rgba(255, 255, 255, .16);
}
.or-home-hero__prova--inline .or-home-hero__stat:last-child { border-right: none; padding-right: 0; }
.or-home-hero__num {
    margin: 0;
    font-size: 1.7rem;
    font-weight: 700;
    line-height: 1;
    letter-spacing: -.01em;
    color: #fff;
    white-space: nowrap;
}
.or-home-hero__rotulo {
    margin: 0;
    max-width: 150px;
    font-size: var(--or-fs-small);
    line-height: 1.3;
    color: rgba(255, 255, 255, .72);
}
@media only screen and (max-width: 575.98px) {
    .or-home-hero__prova--inline { flex-direction: column; gap: 14px; }
    .or-home-hero__prova--inline .or-home-hero__stat { width: 100%; border-right: none; padding-right: 0; }
}

/* --- .or-hero-resposta — painel "resposta" do hero (F4.1 da evolução "primeira tela"). Visual
   AUTORAL (não existe vídeo/fotografia profissional neste projeto hoje): mostra o mesmo texto
   REAL que este site publica pras IAs (EMP_DESCRICAO — a mesma string do /llms.txt, do
   Organization.description no JSON-LD e do rodapé), rotulado como "o que este site publica",
   nunca como "o que a IA respondeu" — a diferença entre prova verificável e print forjado de
   conversa. Superfície de vidro sobre o gradiente do hero (nunca flipa com o tema — tokens
   literais, mesma doutrina de .or-superficies). .or-icon-wrap fica NEUTRO (branco translúcido),
   de propósito: o dourado é lista fechada (BLOCO 0.5) e só o caret de resposta (.or-hero-caret,
   ponto nº1 dela) se repete aqui — 2 ícones a mais virando dourado diluiria o que ele sinaliza. */
.or-hero-resposta {
    background: rgba(255, 255, 255, .07);
    border: 1px solid rgba(255, 255, 255, .16);
    border-radius: var(--or-radius-l);
    padding: 28px 26px;
}
.or-hero-resposta .or-icon-wrap {
    display: inline-flex;
    flex-shrink: 0;
    color: rgba(255, 255, 255, .7);
}
.or-hero-resposta .or-icon-wrap .or-icon { width: 1em; height: 1em; }
.or-hero-resposta__consulta {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    margin: 0;
    font-size: var(--or-fs-small);
    line-height: 1.5;
    color: rgba(255, 255, 255, .68);
}
.or-hero-resposta__consulta .or-icon-wrap { margin-top: .15em; }
.or-hero-resposta__consulta em { color: rgba(255, 255, 255, .86); font-style: italic; }
.or-hero-resposta__divisor {
    height: 1px;
    margin: 18px 0;
    background: rgba(255, 255, 255, .16);
}
.or-hero-resposta__rotulo {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0 0 10px;
    font-size: var(--or-fs-small);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: rgba(255, 255, 255, .78);
}
.or-hero-resposta__texto {
    margin: 0;
    font-size: 1.05rem;
    line-height: 1.55;
    color: #fff;
}
.or-hero-resposta__rodape {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 10px 16px;
    margin: 0;
    font-size: var(--or-fs-small);
}
.or-hero-resposta__rodape span { color: rgba(255, 255, 255, .5); }
.or-hero-resposta__rodape a { display: inline-flex; align-items: center; gap: 6px; color: #fff; font-weight: 600; }
.or-hero-resposta__rodape a:hover { text-decoration: underline; } /* NÃO dourado — hover do hero é sempre feedback neutro, ver .or-home-hero__cta acima */

/* --- .or-marquee__texto — a home NÃO usa mais o marquee (F3 da reestruturação: virou
   .or-superficies, ver bloco abaixo). Esta classe FICA: /sobre (sobre.php:189) ainda usa o
   marquee como fechamento clicável de verdade (link real pra /planos, não decoração) — a
   tipografia do vendor é presa à TAG (.marquee-section.extend h1, style.css:4935 — fora do
   .extend, h1 cru de 140-230px), por isso precisou virar classe própria em vez de herdar do h1. */
.or-marquee__texto {
    display: inline-block;
    font-family: var(--ff-instrument-sans);
    font-weight: 600;
    line-height: 1;
    letter-spacing: -.03em;
    white-space: nowrap;
    font-size: clamp(3rem, 1.5rem + 7vw, 8rem);
    color: rgba(255, 255, 255, .16);
}
/* No rodapé e em /sobre a faixa segue sobre bg-color-primary (flipa pra --or-surface-2 no dark) —
   ali o texto precisa ser sólido (eco visível), não fantasma como no hero. */
.footer-area .or-marquee__texto,
.marquee-section.bg-color-primary .or-marquee__texto { color: #fff; }

/* --- .or-superficies — faixa "onde a empresa precisa aparecer", substitui o marquee logo abaixo
   do hero (F3 da reestruturação da home). Superfície PERMANENTEMENTE escura nos 2 temas (mesmo
   raciocínio do rodapé/.or-llms-file) ⇒ tokens LITERAIS, imunes ao flip de --color-white/
   --color-primary. Ícone dourado é o mesmo ponto nº2 da lista fechada de uso do dourado (BLOCO
   0.5) — eyebrow/marcador sobre superfície escura, já autorizado em .or-home-hero .or-eyebrow. --- */
.or-superficies {
    --or-sup-tinta:   #fff;
    --or-sup-tinta-2: rgba(255, 255, 255, .62);
    --or-sup-borda:   rgba(255, 255, 255, .14);
    background: var(--or-ink-deep);
    padding: 28px 0;
}
.or-superficies__grid {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 16px 32px;
}
.or-superficies__rotulo {
    margin: 0;
    font-size: var(--or-fs-eyebrow);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .1em;
    color: var(--or-sup-tinta-2);
    white-space: nowrap;
}
.or-superficies__grupo {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 6px 14px;
}
.or-superficies__tipo {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-size: var(--or-fs-small);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--or-dourado);
    white-space: nowrap;
}
.or-superficies__tipo .or-icon { width: 1.1em; height: 1.1em; }
.or-superficies__lista {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 4px 14px;
    margin: 0;
    padding: 0;
    list-style: none;
}
.or-superficies__item {
    font-size: var(--or-fs-lead);
    font-weight: 600;
    letter-spacing: -.01em;
    color: var(--or-sup-tinta);
}
.or-superficies__sep {
    display: block;
    width: 1px;
    align-self: stretch;
    background: var(--or-sup-borda);
}

/* --- (28/08/2026) .or-superficies__divisor e .or-superficies__entrega SAÍRAM daqui. Eram a "linha
   2" desta faixa (pílulas-link "O que a OneRank entrega"), cujo MARKUP foi removido da home em
   26/08/2026 — o CSS ficou órfão no arquivo desde então, sem um único usuário. A geometria
   (pílula com borda, raio pill, wash de hover, rail com scroll-snap no mobile) foi MOVIDA para
   .or-ia__chips/.or-ia__chip, que a reusa nos chips de pergunta da seção de Presença em IA.
   Movida, não copiada: nada de órfão novo, nada de duplicata. --- */
@media only screen and (max-width: 767.98px) {
    .or-superficies__grid { flex-direction: column; align-items: flex-start; gap: 14px; }
    .or-superficies__sep { width: 100%; height: 1px; align-self: auto; }
}

/* --- Dor → consequência: wrapper PRÓPRIO (não .process-box-wrapper/.horizontal-scroll — evitar
   colisão com document.querySelector(".horizontal-scroll") do main.js, que pegaria esta seção
   em vez da seção real de Etapas). counter-reset independente: numeração recomeça do 1 aqui,
   sem interferir na contagem da seção de Etapas mais abaixo. --- */
.or-dor-grid {
    counter-reset: process-number;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 32px;
}
@media (min-width: 1200px) {
    .or-dor-grid { grid-template-columns: repeat(3, 1fr); gap: 40px; }
}
/* --- .or-dor-grid--compacto (F5.1 da reestruturação da home) — .process-box do vendor tem
   gap:208px + padding:54px 48px (style.css:5664-5678), calibrado pra um card com MUITO mais
   conteúdo do que 2 linhas de texto; é por isso que #dor tinha 1105px pra 3 cards. Zero markup,
   zero risco — só reduz o respiro interno do card. --- */
.or-dor-grid--compacto .process-box { gap: 32px; padding: 36px 32px; }

/* --- #dor · ILUSTRAÇÕES DOS 3 CARDS (27/08/2026) — mock-ups explicativos gerados por
   bin/cliente/gerar-artes-dor.php, servidos de uploads/identidade/ (pasta VERSIONADA — o deploy é
   `git reset --hard`, asset gitignored novo nunca sobe). Antes, a seção que carrega a tese do site
   ("se sua empresa não aparece, ela não existe") era 3 retângulos escuros com 2 linhas de texto.

   ⚠️ A ARTE É UM BITMAP: ele é o MESMO em TRÊS fundos diferentes, medidos ao vivo —
      claro   .process-box .............. #191919 (var(--color-3), style.css)
      escuro  [data-bs-theme=dark] ...... var(--or-surface-2)
      hover   .hover-overlay ............ color-mix(marca 12%, #fff) — o painel é injetado por
                                          main.js (não pelo markup deste template)
   Nenhum token que flipa com o tema resolve isso — por isso a paleta da arte é literal DENTRO do
   .webp e a moldura aqui é um anel literal, não var(). Mesma doutrina já escrita para o bezel de
   .or-device--phone e para o fundo de .or-llms-file: "é uma janela, não uma superfície do site —
   não flipa".

   O anel rgba(120,139,165,.45) é o único valor que dá fronteira visível nos TRÊS: sobre #191919
   compõe ~#4A5568, sobre o painel claro de hover compõe ~#B4BFCF. Sem ele, no HOVER (painel quase
   branco) a arte — que é um painel branco — perderia a borda e "derreteria" no card (WCAG 1.4.11,
   fronteira de componente ≥3:1). Foi o ÚNICO risco real que esta evolução introduziu no hover; o
   hover em si nunca esteve quebrado (o overlay é injetado pelo main.js, existe nos 3 cards).

   radius --or-radius-s (8px) e não um raio maior: o .process-box tem canto vivo (border-radius:0);
   um raio grande dentro de um card de canto vivo brigaria. 8px basta pra ler como "tela".

   WCAG 1.4.5 (Images of Text): a arte contém texto, e isso é deliberado — cai na exceção de "texto
   que é parte de uma imagem com outro conteúdo visual significativo" (é um mock-up de SERP/chat/
   gráfico, não um parágrafo rasterizado). Toda a INFORMAÇÃO está em texto real: título do card,
   BLC_TEXTO, .or-dor-consequencia e o alt (WCAG 1.1.1). --- */
.or-dor-arte {
    border-radius: var(--or-radius-s);
    overflow: hidden;
    line-height: 0;               /* mata o espaço de baseline abaixo do <img> inline */
    box-shadow: 0 0 0 1px rgba(120, 139, 165, .45);
}
.or-dor-arte img { display: block; width: 100%; height: auto; }

/* No escuro, um painel branco de 270px dentro de um card #1c1f26 é agressivo à noite. -7% de
   brilho aproxima da superfície sem alterar contraste INTERNO da arte (texto e fundo escurecem
   juntos) — mesmo espírito do filter que o rodapé já usa na logo (or-dark.css). */
[data-bs-theme="dark"] .or-dor-arte img { filter: brightness(.93) saturate(.96); }

/* --- Linha de consequência (o "e daí?" de cada card). Vive DENTRO de .process-info pra herdar de
   graça o hover do vendor+fork (.process-box:hover .process-info p) — sem isso ela seria a única
   linha do card que não vira azul de marca no hover.
   ::before em currentColor (não um "▸" literal): o glifo seria ANUNCIADO por leitor de tela
   ("black right-pointing small triangle") no meio de uma frase de venda, e um caractere fixo não
   acompanharia o flip repouso→hover→dark. currentColor acompanha os três de graça.
   border-top em color-mix com currentColor pelo mesmo motivo: um rgba(255,255,255,.14) sumiria
   sobre o painel claro do hover. --- */
.or-dor-consequencia {
    display: flex;
    align-items: flex-start;
    gap: 11px;
    margin: 16px 0 0;
    padding-top: 16px;
    border-top: 1px solid color-mix(in srgb, currentColor 22%, transparent);
    font-size: var(--or-fs-small);   /* 14px — o <p> irmão herda 20px de body (style.css) */
    font-weight: 700;
    line-height: 1.4;
    letter-spacing: .005em;
}
.or-dor-consequencia::before {
    content: '';
    flex: 0 0 auto;
    width: 14px;
    height: 2px;
    margin-top: .62em;               /* alinha o traço com a 1ª linha do texto */
    border-radius: 1px;
    background: currentColor;
    opacity: .55;
}

/* --- Solta o max-width:430px do vendor SÓ no grid compacto (#dor da home). Medido a 2560×919: a
   coluna do grid é 500px e o .process-box travava em 430 — 70px mortos por coluna, 210px na linha,
   e a arte renderizava menor do que podia. Escopado a --compacto de propósito: sobre.php usa
   .or-dor-grid SEM o modificador para os 3 planos, e alargar aqueles cards não foi pedido. Abaixo
   de 1200px o vendor já faz max-width:100% (style.css) — nada a fazer. --- */
@media (min-width: 1200px) {
    .or-dor-grid--compacto .process-box { max-width: none; }
}

/* --- Números "01./02./03." REMOVIDOS do grid compacto (27/08/2026 — pedido do dono: "assim o
   bloco fica menor de altura e pode ter mais conteúdo visível"). display:none, não remoção do
   markup/counter: .process-number é filho flex de .process-box (column, gap:32px) — escondê-lo
   tira o elemento do fluxo E o gap que o precedia de graça, sem buraco órfão (diferente de mexer
   em margin, que deixaria um resto). O counter-reset em .or-dor-grid (BLOCO acima) continua de pé
   — é compartilhado com sobre.php, que usa .or-dor-grid SEM --compacto e mantém os números. Sem
   efeito colateral no contador: counter-increment num elemento display:none simplesmente não
   ocorre (a caixa não é gerada), não há "buraco" na sequência pros outros usos da classe base. */
.or-dor-grid--compacto .process-number { display: none; }

/* --- Corpo do card também justificado (27/08/2026 — mesmo pedido: "o texto desses cards também
   precisam ser justify"). Reabre a exceção que o BLOCO 5 tinha fixado pra .process-box (motivo
   original: card de 2 linhas produz rio) — não se aplica mais: a copy foi expandida pra 4-6 linhas
   nesta mesma evolução, o mesmo regime de "prosa sustentada" do .or-doc-body/.or-lead. Pega os DOIS
   <p> de .process-info (texto principal + .or-dor-consequencia) com um seletor só; a consequência é
   1 linha só, então text-align:justify não tem o que esticar ali (sem text-align-last, a única
   linha nunca é forçada) — incluir no seletor é inofensivo, não precisa de exceção. Escopado
   a --compacto: os 3 cards de tier de sobre.php (mesmo componente, texto de 1 frase) não herdam.

   hyphens:none desde 03/09/2026 — mesmo regime do .or-doc-body/.or-lead (ver bloco correspondente,
   ~linha 3785): hyphens:auto partia palavra comum ao meio, e o pedido foi categórico contra isso
   em qualquer texto, título ou corpo. */
.or-dor-grid--compacto .process-info p {
    text-align: justify;
    text-justify: inter-word;
    -webkit-hyphens: none;
    hyphens: none;
}

/* ═══ #dor — FUNDO PLEXUS nos cards (28/08/2026, pedido do dono: "imagem abstrata, algo parecido
   com a estrutura do vídeo do hero") ═══

   Saiu o #191919 chapado; entrou uma superfície de 3 camadas na MESMA família cromática em que o
   gradiente do hero termina (--or-ink-deep), com a malha plexus por cima.

   POR QUE O CO-SELETOR [data-bs-theme="dark"] AQUI: a regra dark do process-box (linha ~1924) usa
   `background-color: var(--or-surface-2) !important` — especificidade sozinha não vence, e ordem no
   arquivo também não. Com o co-seletor + !important, este bloco pode viver junto do resto de #dor
   (coesão) em vez de precisar ir para depois daquele bloco.

   O CARD DEIXA DE FLIPAR, e isso é deliberado: é a mesma doutrina de .or-ia e .or-segmentos-bg —
   superfícies que carregam identidade de marca não trocam de cor com o tema. O texto é branco nos
   dois temas, e o contraste medido continua alto (16,4:1 fora da malha).

   ESCOPADO A --compacto: sobre.php:142 usa .or-dor-grid SEM o modificador (3 cards de tier). Sem o
   escopo, aquela página mudaria junto — e não foi pedido. */
.or-dor-grid--compacto .process-box,
[data-bs-theme="dark"] .or-dor-grid--compacto .process-box {
    background-color: var(--or-ink-deep) !important;
    background-image:
        /* SCRIM no topo da pilha: trava o piso de luminância independente dos orbes abaixo. É a
           camada de proteção de contraste — custo zero de rede. */
        linear-gradient(180deg, rgba(3, 10, 22, .30), rgba(3, 10, 22, .66)),
        radial-gradient(120% 90% at 100% 0%, color-mix(in srgb, var(--marca-primaria) 46%, transparent) 0%, transparent 62%),
        radial-gradient(90% 70% at 0% 100%, color-mix(in srgb, var(--marca-secundaria, #082C6A) 40%, transparent) 0%, transparent 66%);
    background-repeat: no-repeat;
}

/* A malha. z-index:0 é load-bearing: põe a camada ACIMA da .hover-overlay (que é z-index:-1,
   style.css:5679) e ABAIXO do conteúdo — é isso que faz a malha ATRAVESSAR a transição de hover e
   reaparecer tingida dentro do painel, em vez de ser coberta por ele. */
.or-dor-card__malha {
    position: absolute;
    inset: -18%;                 /* sangria: o parallax nunca expõe borda (deriva máx. ~72px) */
    z-index: 0;
    pointer-events: none;
    background-color: rgba(255, 255, 255, .17);
    -webkit-mask-image: var(--or-malha-plexus);
            mask-image: var(--or-malha-plexus);
    -webkit-mask-size: 300px 300px;
            mask-size: 300px 300px;
    -webkit-mask-repeat: repeat;
            mask-repeat: repeat;
    transition: background-color .45s ease, scale .6s cubic-bezier(.22, .61, .36, 1);
}
/* Obrigatório: um elemento posicionado com z-index:0 pinta DEPOIS do conteúdo em fluxo (CSS 2.1,
   Apêndice E). Sem isto a malha passaria por cima do texto. */
.or-dor-grid--compacto .process-info,
.or-dor-grid--compacto .or-dor-arte { position: relative; z-index: 1; }

/* 3 leituras com 1 asset só: recorte diferente do MESMO tile. mask-position, NUNCA transform —
   transform é território do GSAP (data-speed escreve inline e vence CSS externo; bug documentado
   em custom.css:2041). Três eixos, zero colisão: transform=GSAP · mask-position=variação · scale=hover. */
.or-dor-grid--compacto .process-box:nth-child(2) .or-dor-card__malha { -webkit-mask-position: 148px 66px; mask-position: 148px 66px; }
.or-dor-grid--compacto .process-box:nth-child(3) .or-dor-card__malha { -webkit-mask-position: 62px 208px; mask-position: 62px 208px; }

/* HOVER — a malha inverte junto, não é apagada. É a resposta ao "hover em destaque moderno": o
   card lê como uma superfície viva que virou, não como duas telas trocadas. 22% de tinta deixa o
   pior pixel em 5,8:1 (o teto antes de cair abaixo de 4,5:1 seria ~33%). */
.or-dor-grid--compacto .process-box:hover .or-dor-card__malha {
    background-color: color-mix(in srgb, var(--marca-primaria) 22%, transparent);
    scale: 1.06;
}

/* --- .or-geo-titulo (F5.1) — heading da "resposta" (2º tempo, fundida com #dor). H4, não H3: é
   subordinado ao h3 da dor, não um par dele. Sem regra própria cairia no h4 cru do vendor
   (60px/-1,5px, mesma família do achado D2). --- */
.or-pg .or-geo-titulo {
    font-size: var(--or-fs-h3);
    line-height: 1.2;
    letter-spacing: -.015em;
    margin-bottom: 12px;
    /* É h4, fora do seletor de h3 do BLOCO 1.5 — precisa da própria declaração. Entra junto com a
       col-8 de #geo (27/08/2026): coluna mais larga, mais risco de órfã. */
    text-wrap: balance;
}

/* --- Parágrafo de apoio (dor / planos) ---
   margin-bottom (28/08/2026) — CAUSA RAIZ da violação de espaçamento em #servicos (home.php:999,
   achado na auditoria do CLAUDE.md §Padrão de Espaçamento): o vendor zera `p{margin-bottom:0}`
   (style.css:286-288) e .or-lead só trazia margin-TOP — nada separava o lead do bloco seguinte
   quando os dois viviam na mesma coluna (Regime B). --or-esp-5 é o PISO documentado (nunca menos
   entre blocos irmãos). :last-child zera de novo quando o lead é o último filho da coluna (4 dos
   10 usos) — sem isso sobraria un espaço morto antes do fechamento da </div>. --- */
.or-lead {
    /* 18px→var(--or-esp-5) em 05/09/2026: era o único valor da família de margem que ficava
       abaixo do PISO de 24px que o próprio CLAUDE.md declara entre blocos irmãos — alinha os
       ~11 usos ao mesmo piso do fallback global logo acima, sem mudar o valor de baixo. */
    margin-top: var(--or-esp-5);
    margin-bottom: var(--or-esp-5);
    max-width: 640px;
    font-size: var(--or-fs-lead); /* era 18px fixo, ignorava o token (D2 — mesma família) */
    line-height: 1.6;
    color: var(--color-primary);
    opacity: .75;
}
.or-lead:last-child { margin-bottom: 0; }

/* --- Diferenciais (seção "Por que OneRank", #painel + /sobre) — lista title+descrição, não chip
   (BLC_TEXTO tem conteúdo real por item, diferente dos segmentos de "Para quem é", que são só um
   rótulo). margin-top era 28px — valor solto, fora da escala --or-esp-* (4/8/12/16/24/32/48/64,
   custom.css :root). --or-esp-6 é o degrau de "bloco↔bloco com troca de assunto" (texto→lista),
   exatamente o papel aqui — achado na auditoria de 29/08/2026. --- */
.or-diferenciais-list {
    list-style: none;
    margin: var(--or-esp-6) 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 18px;
}
.or-diferenciais-list li { padding-top: 18px; border-top: 1px solid var(--color-1); }
.or-diferenciais-list li:first-child { border-top: none; padding-top: 0; }
.or-diferenciais-list strong { display: block; font-size: 17px; font-weight: 600; color: var(--color-primary); margin-bottom: 4px; }
.or-diferenciais-list span { display: block; font-size: 15px; color: var(--color-primary); opacity: .68; }

/* --- Planos: selo do tier recomendado + sufixo de periodicidade no preço --- */
.or-pricing-tag {
    position: absolute;
    top: 24px;
    right: 24px;
    z-index: 1;
    background: var(--marca-primaria);
    color: var(--color-white);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .02em;
    text-transform: uppercase;
    padding: 6px 14px;
    border-radius: 40px;
}
.or-pricing-periodo { font-size: 16px; font-weight: 500; opacity: .55; margin-left: 2px; }

/* .pricing (h3, o preço em si) não tem font-size próprio no vendor (style.css:5221 só define
   margin/transition) — cai no h3 CRU de 80px. Medido: "R$1.499/mês" preenche os 403px disponíveis
   do card por inteiro; um preço de 5 dígitos estouraria (D3/A3). --or-fs-secao-compacta (não a
   --or-fs-secao de 64px) porque o card tem largura fixa, não deve crescer com a viewport. */
.quanto-pricing-box .pricing { font-size: var(--or-fs-secao-compacta); letter-spacing: -.02em; }

/* --- Card do tier recomendado (evolução F4, plano "borda superior dourada + elevação") — 1 dos 6
   pontos fechados de uso do dourado (BLOCO 0.5). border-top segue o raio do próprio box por padrão
   do CSS (mesma técnica de .or-planos-table__recomendada, BLOCO 4). --- */
.quanto-pricing-box.or-card--recomendado {
    border-top: 3px solid var(--or-dourado);
    box-shadow: var(--or-shadow-brand);
}

/* --- Hierarquia de ação (D.5) — antes os 3 CTAs de #planos competiam igual (mesmo pill sólido).
   O card RECOMENDADO mantém o pill sólido; os outros 2 viram outline — mesma forma/tamanho, sem
   disputar destaque com o card que a própria OneRank usa. Escopado pela AUSÊNCIA de
   .or-card--recomendado — zero classe nova no markup dos 2 CTAs. No :hover, a regra existente
   (~acima, "botão CONTINUA invertendo") já cobre os 3 igual: outline também vira preenchido. */
.quanto-pricing-box:not(.or-card--recomendado) .quanto-link-btn.btn-pill {
    background-color: transparent;
    border-color: var(--color-primary);
}
.quanto-pricing-box:not(.or-card--recomendado) .quanto-link-btn.btn-pill,
.quanto-pricing-box:not(.or-card--recomendado) .quanto-link-btn.btn-pill span,
.quanto-pricing-box:not(.or-card--recomendado) .quanto-link-btn.btn-pill span .arry1,
.quanto-pricing-box:not(.or-card--recomendado) .quanto-link-btn.btn-pill span .arry2 {
    color: var(--color-primary);
}

/* --- Bloco de ativação (D.4, 29/08/2026) — a home nunca mencionava a ativação de R$ 1.199 nem
   como o processo funciona (só /planos tinha); "quanto custa pra começar" ficava sem resposta no
   ponto exato da decisão. Superfície --color-2 (mesmo token de .or-planos-addons__item — precedente
   de "card sobre section branca"), 4 passos em grid (2 no tablet, 1 no mobile — nunca 3, que
   quebraria a leitura par/ímpar), número em círculo espelhando .or-etapas-acordeao__num (mesma
   forma, cor de marca em vez de branco-sobre-escuro porque aqui o fundo é claro). */
.or-ativacao {
    background: var(--color-2);
    border-radius: var(--or-radius-l);
    padding: var(--or-esp-7) var(--or-esp-6);
}
.or-ativacao__passos {
    list-style: none;
    margin: 0 0 var(--or-esp-6);
    padding: 0;
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: var(--or-esp-6);
}
.or-ativacao__num {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    margin-bottom: var(--or-esp-3);
    border-radius: 50%;
    background: var(--marca-primaria);
    color: #fff;
    font-size: .9rem;
    font-weight: 700;
}
.or-ativacao__passos strong { display: block; font-size: 16px; font-weight: 600; color: var(--color-primary); margin-bottom: 4px; }
.or-ativacao__passos p { font-size: var(--or-fs-small); color: var(--color-primary); opacity: .68; margin: 0; }
.or-ativacao__aviso {
    padding-top: var(--or-esp-6);
    border-top: 1px solid var(--color-1);
    font-size: var(--or-fs-lead);
    color: var(--color-primary);
    margin: 0 0 var(--or-esp-3);
}
.or-ativacao__reforco { font-size: var(--or-fs-small); color: var(--color-primary); opacity: .6; margin: 0; }
@media (max-width: 991.98px) {
    .or-ativacao__passos { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 575.98px) {
    .or-ativacao { padding: var(--or-esp-6) var(--or-esp-5); }
    .or-ativacao__passos { grid-template-columns: 1fr; }
}

/* ================================================================
   DARK MODE — Camada 3 do adapter (Quanto). Equivalente ao bloco "ADAPTER do template atual"
   que normalmente vive em site/assets/css/or-dark.css (core) — mas esse arquivo é CORE e
   tests/site_dark_test.php trava os seletores do Canvas 7 que já estão lá. O adapter do Quanto
   mora aqui, no fork. Usa os tokens --or-* (Camada 2, core, template-agnóstica — já ativa
   globalmente assim que or-dark.css carrega) e var(--marca-primaria) (já remapeada por
   Colors::toCssVars()) — nunca cor hardcoded.

   ATIVADO — F9 (25/08/2026): `site_dark_ativo=true`, as 29 páginas do site já são Quanto (migração
   Azurio→Quanto completa), então o flip abaixo se aplica ao site inteiro sem risco de quebrar
   página em template antigo.
   ================================================================ */
[data-bs-theme="dark"] {
    /* Par de tintas duplas do Quanto: --color-white é usado como TEXTO (h1..h6 sobre fundo
       escuro, .text-color-white) e como FUNDO (cards claros); --color-primary é usado como
       FUNDO (footer, process-box, menu escuro do próprio design claro) e como TEXTO
       (body/headings/.main-menu a). Os dois papéis trocam de lugar no escuro. */
    --color-white: var(--or-surface);
    --color-primary: var(--or-text);

    /* --color-2 é usado SÓ como FUNDO de card sutil (form-control, sidebar de candidatura,
       card de filial, add-on de planos) — papel único, sem par a trocar, então flipa direto
       pra superfície escura secundária. Achado F9: sem isto, esses cards ficavam claros
       (#f5f5f5) e o texto var(--color-primary) dentro deles virava --or-text (quase branco) —
       texto quase invisível sobre fundo quase branco (contraste ~1.03:1, medido ao vivo). */
    --color-2: var(--or-surface-2);
}

/* Títulos: --color-black NUNCA é flipado globalmente (ver nota abaixo) — cobertos por seletor,
   com o token de TEXTO (não a marca — títulos usam neutro, a marca fica pros acentos). */
[data-bs-theme="dark"] :is(h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6) {
    color: var(--or-text);
}

/* Blocos JÁ escuros no claro (fundo --color-primary/--color-3 + texto branco fixo via
   .text-color-white) — sem isto, ficariam CLAROS no escuro (inversão fotográfica errada: o
   footer e os cards de processo, que já são a superfície mais escura do design CLARO, teriam
   fundo clareado bem no momento em que o resto da página escurece). */
[data-bs-theme="dark"] footer.bg-color-primary,
[data-bs-theme="dark"] section.bg-color-primary,
[data-bs-theme="dark"] div.bg-color-primary,
[data-bs-theme="dark"] .process-box,
[data-bs-theme="dark"] .quanto-mobile-menu-btn .social-btn a {
    background-color: var(--or-surface-2) !important;
}
[data-bs-theme="dark"] .text-color-white {
    color: var(--or-text) !important;
}

/* Header (bg-color-white + sticky) e dropdown do menu principal — sem isto o header "claro"
   fica invisível contra o resto da página escurecida. */
[data-bs-theme="dark"] .quanto-header.bg-color-white .sticky-active {
    background-color: var(--or-surface) !important;
}
[data-bs-theme="dark"] .main-menu ul.sub-menu {
    background-color: var(--or-surface) !important;
    box-shadow: var(--or-elev);
}

/* Menu mobile: painel branco fixo (.quanto-menu-area) vira superfície escura; o backdrop preto
   (rgba(var(--color-black-rgb),.6)) continua preto — --color-black NÃO É FLIPADO acima de
   propósito: tem 5 usos que se contradizem (h1..h6{color:var(--color-black)} quereria inverter,
   mas o MESMO token faz o overlay do menu mobile — flipá-lo globalmente afundaria um overlay
   BRANCO cobrindo a tela inteira ao abrir o menu). Cobrimos só os pontos que precisam mesmo
   flipar, por seletor — nunca a variável inteira. */
[data-bs-theme="dark"] .quanto-menu-wrapper .quanto-menu-area,
[data-bs-theme="dark"] .quanto-menu-wrapper .mobile-logo {
    background-color: var(--or-surface) !important;
}

/* #blog trocou bg-color-2→bg-color-white (29/08/2026, achado ao vivo na reordenação #faqs/#blog:
   #planos(branco)→#faqs ficaria colado se #faqs continuasse branco — #faqs virou o cinza livre,
   #blog assumiu o branco). .quanto-blog-content perdeu o contraste natural do cinza atrás dele;
   sombra própria substitui. var(--or-shadow-1) já é dark-mode-aware (vira `none` no escuro,
   linha ~116 — o card já ganha diferenciação por cor de fundo lá, sombra seria redundante). */
.quanto-blog-content.bg-color-white { box-shadow: var(--or-shadow-1); }

/* Cards com fundo claro fixo (bg-color-2/bg-color-white) — flipam pra superfície escura */
[data-bs-theme="dark"] .quanto-pricing-box,
[data-bs-theme="dark"] .quanto-service-box3.bg-color-white,
[data-bs-theme="dark"] .testimonial3-content {
    background-color: var(--or-surface) !important;
    color: var(--or-text);
}
[data-bs-theme="dark"] section.bg-color-2,
[data-bs-theme="dark"] .bg-color-2:not(.slider-arrow-left):not(.slide-btn) {
    background-color: var(--or-surface-2) !important;
}
/* .quanto-blog-content.bg-color-white SAIU do grupo acima (29/08/2026, achado ao vivo na troca
   de fundo #blog: bg-color-2→bg-color-white — ver comentário na abertura da seção, home.php) —
   a SEÇÃO também é .bg-color-white, e --color-white flipa pra --or-surface (linha ~1874). Ficando
   no grupo acima, o CARD flipava pro MESMO --or-surface da seção — mesclava, invisível, com a
   sombra desligada de propósito no escuro (--or-shadow-1:none). --or-surface-2 (1 degrau mais
   claro, o mesmo token que .quanto-pricing-box usa contra a seção branca de #planos — ver o
   .bg-color-2 acima) devolve a distinção sem depender de sombra. */
[data-bs-theme="dark"] .quanto-blog-content.bg-color-white {
    background-color: var(--or-surface-2) !important;
    color: var(--or-text);
}

/* Acento da marca clareado no escuro (mesmo tratamento do Canvas em or-dark.css). Achado F9: todo
   uso de var(--marca-primaria) como COR DE TEXTO/ícone (não fundo) precisa entrar aqui — o azul
   cru (#0B3D91) tem só ~1,7:1 de contraste contra as superfícies escuras (--or-surface/-2),
   var(--or-brand-accent) é a MESMA marca clareada (color-mix c/ branco, já usada por Locale/links). */
[data-bs-theme="dark"] .accordion-button:not(.collapsed),
[data-bs-theme="dark"] .or-tag:hover,
[data-bs-theme="dark"] .or-breadcrumb a:hover,
[data-bs-theme="dark"] .or-secao-cta__link:hover .title,
[data-bs-theme="dark"] .or-servico-icon svg {
    color: var(--or-brand-accent) !important;
}

/* Componentes que já nasciam ESCUROS no claro (texto var(--color-white) sobre fundo próprio
   escuro OU sobre var(--marca-primaria), que nunca flipa — newsletter do rodapé, chips invertidos
   de "Para quem é", selo de plano recomendado, CTA azul do header): sem isto, o flip global de
   --color-white (linha acima) escurece o TEXTO, resultado quase ilegível (~1:1 a ~1,8:1, medido
   ao vivo). O CTA do header é o mais grave dos achados — está em TODAS as 29 páginas, acima da
   dobra. Mesmo raciocínio de .text-color-white (linha 487), só que aplicado a regras que fixam a
   cor direto (não usam a classe utilitária do vendor). */
[data-bs-theme="dark"] .or-tag--invert,
[data-bs-theme="dark"] .or-tag--invert:hover,
[data-bs-theme="dark"] .or-tag.active,
[data-bs-theme="dark"] .or-tag.active:hover,
[data-bs-theme="dark"] .or-portfolio-filtro.active,
[data-bs-theme="dark"] .or-portfolio-filtro.active:hover,
[data-bs-theme="dark"] .or-social-link:hover,
[data-bs-theme="dark"] .or-pricing-tag,
[data-bs-theme="dark"] .quanto-header .quanto-link-btn.btn-pill,
[data-bs-theme="dark"] .quanto-header .quanto-link-btn.btn-pill span .arry1,
[data-bs-theme="dark"] .quanto-header .quanto-link-btn.btn-pill span .arry2,
[data-bs-theme="dark"] .or-secao-cta--soft .or-secao-cta__btn.quanto-link-btn.btn-pill,
[data-bs-theme="dark"] .or-secao-cta--soft .or-secao-cta__btn.quanto-link-btn.btn-pill span .arry1,
[data-bs-theme="dark"] .or-secao-cta--soft .or-secao-cta__btn.quanto-link-btn.btn-pill span .arry2 {
    color: var(--or-text) !important;
}

/* Form-control do vendor (.quanto-contact__form — contato.php/pagina-planos.php): a cor de texto
   é #6b6b6b HARDCODED no style.css (style.css:5837, não é var()), calibrada pro fundo claro
   original — o flip de --color-2 acima (que corrige o FUNDO) não alcança essa declaração. Sem
   este pin o texto digitado ficaria cinza-médio sobre o novo fundo escuro (~3,4:1, abaixo do
   4.5:1 exigido). */
[data-bs-theme="dark"] .quanto-contact__form .form-control {
    color: var(--or-text) !important;
}

/* ================================================================
   BLOCO 3.5 — HOVER-OVERLAY: tinta imune ao flip de tema
   Posicionado DEPOIS do bloco DARK acima de propósito: [data-bs-theme="dark"] .process-box (0,2,0)
   empata em especificidade com .process-box:hover (0,2,0) — quem vence é a ORDEM no arquivo. Os
   tokens --or-hover-painel/--or-hover-tinta (bloco 0.5, ~linha 261) resolvem o par painel/texto do
   #dor; aqui consumimos --or-hover-tinta no seletor que o vendor deixou de pé (style.css:5727-5733
   calibrou a cor de texto pro overlay ORIGINAL, não pro azul de marca único que passou a ser
   injetado). --- */

/* !important obrigatório: o markup traz .text-color-white em .process-title/p (home.php) e a regra
   de ~linha 487 força [data-bs-theme=dark] .text-color-white{color:var(--or-text) !important}. Sem
   !important aqui, no ESCURO o título do hover ficaria var(--or-text) sobre --or-hover-painel (que
   é quase branco) — a correção criaria um bug PIOR que o original (medido: ~1:1). */
.process-box:hover .process-number::before,
.process-box:hover .process-info .process-title,
.process-box:hover .process-info p { color: var(--or-hover-tinta) !important; }

/* Card de PREÇO (#planos + /planos) — a inversão de cor no hover foi DESLIGADA em 29/08/2026,
   achado ao vivo do dono ("Autoridade" apagado no print): o overlay que deveria dar contraste ao
   texto branco é injetado por JS (main.js:254-267) e animado pelo GSAP em 0,5s, DESSINCRONIZADO da
   troca instantânea de cor via CSS puro (esta era a regra .quanto-pricing-box:hover{color:var(
   --or-hover-tinta)} que existia aqui). Resultado medido em qualquer frame da transição — e sempre
   que o overlay simplesmente não existe (achado secundário: main.js só o injeta dentro de um
   DOMContentLoaded aninhado; se disparar tarde, o overlay NUNCA existe): texto branco sobre
   bg-color-2 (#f5f5f5), 1,09:1 — WCAG AA exige 4,5:1. Num card de PREÇO o visitante está lendo
   comparativamente; apagar o que ele está lendo no hover é hostil à própria tarefa. O overlay sai
   (display:none — .process-box do #dor continua com o efeito, seletor não o alcança) e o card passa
   a se destacar só por elevação/sombra, nunca por troca de paleta — os valores abaixo são os MESMOS
   tokens que o vendor usa em repouso (style.css:97-104 h1-h6→var(--color-black); o corpo do card
   herda var(--color-primary) do body/section, sem regra própria), só re-declarados para vencer o
   .quanto-pricing-box:hover{color:var(--color-white)} do vendor (style.css:5284-5290). */
.quanto-pricing-box .hover-overlay { display: none; }
.quanto-pricing-box:hover,
.quanto-pricing-box:hover .pricing-info,
.quanto-pricing-box:hover .pricing-list ul li { color: var(--color-primary); }
.quanto-pricing-box:hover .pricing-title,
.quanto-pricing-box:hover .pricing { color: var(--color-black); }
.quanto-pricing-box:hover {
    /* SÓ sombra, sem translateY — achado ao vivo: os 3 cards carregam .fade-anim (entrada
       data-direction="right"), e main.js:464-528 nunca chama clearProps depois do tween. GSAP
       deixa `transform` como estilo INLINE (mesmo resolvendo pra translate(0,0)) — inline sempre
       vence regra externa na mesma propriedade, :hover ou não, sem !important. Testado ao vivo:
       um translateY aqui não se manifestava depois do card entrar em cena. box-shadow não é
       tocado pelo GSAP, então funciona sempre, sem essa disputa. */
    box-shadow: var(--or-shadow-brand);
    transition: box-shadow .3s ease-in-out;
}

/* Rótulo do CTA do card de plano EM REPOUSO — o bloco de acento de marca (~linha 261) trocou o
   FUNDO do botão pra marca e deixou o color:var(--color-primary) do vendor (style.css:5270) de pé:
   1,57:1 medido ao vivo, SEM hover, na home E em /planos — "Solicitar diagnóstico" ilegível no
   estado padrão, no ponto exato de conversão, em 6 cards. #fff literal porque o fundo é
   var(--marca-primaria), que não flipa. */
.quanto-pricing-box .quanto-link-btn.btn-pill,
.quanto-pricing-box .quanto-link-btn.btn-pill span,
.quanto-pricing-box .quanto-link-btn.btn-pill span .arry1,
.quanto-pricing-box .quanto-link-btn.btn-pill span .arry2 { color: #fff; }

/* O botão CONTINUA invertendo no hover (fundo branco / texto marca) — é CSS puro, sem dependência
   de JS/timing, e o contraste em QUALQUER ponto da transição de 0,5s já foi medido legível (a
   troca de bg e de texto correm juntas, no mesmo transition). Diferente do bug acima: não é a
   mesma família de defeito, é uma affordance de botão que funciona. Não tocar. */
.quanto-pricing-box:hover .quanto-link-btn.btn-pill { background-color: #fff; border-color: #fff; }
.quanto-pricing-box:hover .quanto-link-btn.btn-pill,
.quanto-pricing-box:hover .quanto-link-btn.btn-pill span,
.quanto-pricing-box:hover .quanto-link-btn.btn-pill span .arry1,
.quanto-pricing-box:hover .quanto-link-btn.btn-pill span .arry2 { color: var(--marca-primaria); }

/* O selo ("⭐ Escolha da própria OneRank") NÃO precisa mais de tratamento de hover — a versão
   anterior invertia bg:#fff/texto:marca porque o CARD inteiro virava marca-primária sob o overlay
   (o selo "sumia como forma" sobre o próprio tom). Sem overlay, o fundo do card nunca muda no
   hover — o selo permanece com o MESMO bg:var(--marca-primaria) do repouso (:1743-1756 + o ajuste
   de cor no escuro, :1883), que já tem contraste correto nos dois temas. Uma regra de hover aqui
   voltaria a inverter o selo sobre um fundo que não mudou — bug novo, não correção. */

/* --- #geo — arquivo /llms.txt REAL exibido como "arquivo" (evolução F5). Fundo fixo escuro nos
   dois temas de propósito — é uma janela de código/terminal, não uma superfície do site (mesmo
   raciocínio do bezel do .or-device--phone: não flipa). --- */
.or-llms-file {
    border-radius: var(--or-radius-l);
    overflow: hidden;
    box-shadow: var(--or-shadow-2);
    background: var(--or-ink-deep);
}
.or-llms-file__bar {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 12px 16px;
    background: rgba(255, 255, 255, .06);
}
.or-llms-file__nome {
    margin-left: 10px;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: .82rem;
    color: rgba(255, 255, 255, .55);
}
.or-llms-file__conteudo {
    margin: 0;
    padding: 22px 20px;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: .8rem;
    line-height: 1.65;
    color: rgba(255, 255, 255, .82);
    white-space: pre-wrap;
    word-break: break-word;
    max-height: 300px;
    overflow: hidden;
    /* Fade em vez de corte seco — o conteúdo real varia de tamanho por instalação (nome/descrição/
       nº de páginas), um max-height fixo cortaria no meio da palavra em vez de sinalizar "tem mais". */
    mask-image: linear-gradient(to bottom, #000 70%, transparent 100%);
    -webkit-mask-image: linear-gradient(to bottom, #000 70%, transparent 100%);
}

/* --- #prova — cards de dogfooding (F5.4 da reestruturação: grid auto-fit no lugar de 3 breakpoints
   fixos — comporta 4 ou 5 cards sem regra nova). Reusa .or-card/.or-card--claro/.or-card--hover
   (BLOCO 0.5) em vez de repetir borda/raio/dark-pin — era a 4ª cópia do mesmo estilo escrito à
   mão. --- */
.or-prova-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 24px;
}
.or-prova-card {
    display: flex;
    flex-direction: column;
    gap: 12px;
}
.or-prova-card__ico { color: var(--marca-primaria); }
[data-bs-theme="dark"] .or-prova-card__ico { color: var(--or-brand-accent); }
/* Chip de estado — tinta de marca a 12% sobre fundo, cor de marca no texto. (A receita nasceu em
   .or-economia-item__badge, removida em 03/09/2026 com a seção #economia; a documentação dela
   passa a viver aqui.) "Mostra estado, não afirma" (F5.4): só aparece quando há dado real
   por trás (ver($orLlmsDisponivel)/$indicadores[3]/contagem de controles — nunca texto fixo).

   POSIÇÃO (mudou em 09/09/2026): o chip desceu no markup — era ícone→CHIP→h3→p→botão, virou
   ícone→h3→p→CHIP→botão (home.php, pedido do dono sobre o "9 controles"). NENHUMA regra de
   margem foi acrescentada aqui, e isso é deliberado: .or-prova-card é flex column com gap:12px,
   ou seja REGIME A do CLAUDE.md (§Padrão de Espaçamento) — o filho não traz margem própria na
   direção do gap, senão margem + gap somam dobrado. Quem encosta o chip no botão é o
   `flex-grow:1` do <p> logo abaixo, que empurra tudo o que vem depois dele para o rodapé do
   card — o mesmo mecanismo que já alinhava os botões dos quatro cards entre si. */
.or-prova-card__chip {
    display: inline-flex;
    align-self: flex-start;
    padding: 4px 12px;
    border-radius: 40px;
    background: color-mix(in srgb, var(--marca-primaria) 12%, transparent);
    color: var(--marca-primaria);
    font-size: .75rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
}
[data-bs-theme="dark"] .or-prova-card__chip { color: var(--or-brand-accent); }
/* font-size/line-height/letter-spacing do h4 vêm do bloco tipográfico (.or-pg .or-prova-card h4,
   ~linha 207) — aqui só peso e cor. ERA font-size:1.05rem FIXO (ignorava --or-fs-card, que daria
   24px) + herdava letter-spacing:-1.5px do h4 cru do vendor (-8,9% do corpo — D2). */
.or-prova-card h4 { font-weight: 700; color: var(--color-primary); margin: 0; }
.or-prova-card p { font-size: 1rem; line-height: 1.6; color: var(--color-primary); opacity: .75; margin: 0; flex-grow: 1; }
.or-prova-card .quanto-link-btn.btn-pill { align-self: flex-start; }

/* --- #painel "O painel é seu" — par de .or-device em escadinha (evolução F5; recomposto em
   29/08/2026, achado ao vivo: a legenda do 1º device sumia sob o 2º).

   CAUSA: a escadinha era VERTICAL (margin-top:-70px). Entre os dois devices mora a legenda1
   (F5.3) — 10px de margem + 1 linha de 14px = ~32px, e ela ocupa 100% do espaço entre os dois.
   .or-device tem fundo OPACO (--color-white) + z-index:2, então QUALQUER sobreposição vertical
   > 0 já cobria a legenda inteira — não era questão de calibrar o número do pull-up, a legenda
   é todo o espaço disponível. E o número nem era estável: com data-speed divergente nos dois
   devices (0.97 / 1.04) e o ScrollSmoother rodando com effects:true acima de 1025px
   (main.js:234), a distância real entre os dois oscilava durante o scroll.

   CORREÇÃO: a escadinha passou a ser só HORIZONTAL (72% alinhado à direita — já era o que dava
   a leitura de camada; o eixo Y é que sobrava problema). E o data-speed migrou do .or-device
   para o WRAPPER .or-painel-device (home.php), que envolve device+legenda como uma unidade só —
   antes só o device tinha data-speed e a legenda ficava para trás, então o device chegava a
   descer sobre a PRÓPRIA legenda nas posições em que o efeito o atrasava. --- */
.or-device--secundario {
    max-width: 72%;
    margin: var(--or-esp-6) 0 0 auto;
}
@media (max-width: 991.98px) {
    .or-device--secundario { margin: var(--or-esp-6) 0 0; max-width: 100%; }
}
/* Wrapper do par device+legenda em #painel — alvo do data-speed (home.php). Sem propriedades de
   layout de propósito: largura/alinhamento do recuo continuam em .or-device--secundario. */
.or-painel-device { position: relative; }
/* Legenda sob cada device (F5.3) — hoje o visitante via 2 retângulos sem saber o que eram. */
/* color explícito, não --or-text-muted (auditoria A-12, 28/08/2026): o token resolvia para
   #6c757d, que sobre o #f5f5f5 de bg-color-2 dá 4,3:1 — reprova o mínimo AA de 4,5:1 para texto
   de 14px. Foi a ÚNICA falha real de contraste em 276 elementos medidos. #5a6268 dá 5,2:1.
   O dark tem token próprio logo abaixo, então só o claro precisa do override. */
.or-device__legenda { margin: 10px 0 0; font-size: var(--or-fs-small); color: #5a6268; }
[data-bs-theme="dark"] .or-device__legenda { color: var(--or-text-muted); }
/* A legenda do device recuado acompanha largura/alinhamento dele. Seletor de irmão adjacente
   ancorado em .or-device--secundario (1 uso no site, home.php) — as 3 legendas de #lgpd (que não
   têm esse modificador) ficam intocadas. */
.or-device--secundario + .or-device__legenda {
    max-width: 72%;
    margin-left: auto;
}
@media (max-width: 991.98px) {
    .or-device--secundario + .or-device__legenda { max-width: 100%; margin-left: 0; }
}

/* --- .or-pilar (/sobre, bloco "O que nos diferencia") — os 4 pilares da marca.
   SUBSTITUIU .or-selos em 03/09/2026: a página tinha DOIS blocos de 4 itens (diferenciais + selos
   de capacidade), repetição estrutural em que o leitor não distinguia um do outro e "IA" aparecia
   nos dois. Os pilares absorveram ambos; o conteúdo dos selos virou a linha de LINKS DE
   VERIFICAÇÃO do bloco "Este site é a demonstração" — mais forte que o texto que substituiu
   ("Acessibilidade real" é promessa; "veja a declaração" é prova).

   Só três propriedades, e todas existem por um motivo: os cards vivem numa .row g-4 (regime A do
   §Padrão de Espaçamento — quem espaça é o gap do pai, então NENHUMA margem própria aqui), e o
   texto é editável pelo painel, logo vai crescer. height:100% + flex-column é o que mantém os 4
   cards da mesma linha com a mesma altura independentemente do tamanho do texto cadastrado — o
   mesmo mecanismo de .or-faq-atalho e .or-segmento-card. Fundo, raio, padding e o pin de dark
   vêm de .or-card/.or-card--claro; nada é redeclarado. --- */
.or-pilar {
    display: flex;
    flex-direction: column;
    height: 100%;
}

/* --- .or-nivel (/sobre, bloco "O que você contrata") — card ilustrado de cada nível.
   SUBSTITUIU o .process-box do vendor em 03/09/2026, por dois defeitos medidos em tela: o
   componente traz `gap: 208px` (cards de 518px com um vazio enorme no meio, texto espremido na
   base) e o título herdava o h3 CRU do vendor — 80px numa caixa de 334px, com os TRÊS nomes
   transbordando. Aqui o tamanho é declarado, não herdado: é a regra de ouro do BLOCO 1 (~linha
   224) — reescalar heading exige redeclarar tamanho E tracking.

   Como o .or-pilar, só declara o que precisa; fundo, raio, padding e o pin de dark vêm de
   .or-card/.or-card--claro. height:100% mantém os 3 cards da mesma linha com a mesma altura por
   mais que o texto cadastrado cresça, e o padding do .or-card é zerado no topo porque a arte
   sangra até a borda (moldura interna seria uma segunda borda dentro do card). --- */
.or-nivel {
    display: flex;
    flex-direction: column;
    height: 100%;
    padding-top: 0;
    overflow: hidden;
}
.or-nivel__arte {
    margin: 0 -28px var(--or-esp-6);   /* -28px = o padding lateral de .or-card: a arte sangra */
    /* aspect-ratio reservado ANTES do load: sem isto o card cresce quando a imagem chega e empurra
       tudo abaixo dele (CLS). 16/10 é a proporção nativa das artes (1600×1000). */
    aspect-ratio: 16 / 10;
    background: var(--or-surface-2, var(--color-2));
    line-height: 0;
    overflow: hidden;
}
.or-nivel__img { width: 100%; height: 100%; object-fit: cover; display: block; }
.or-nivel__num {
    margin: 0 0 var(--or-esp-2);
    font-size: .8125rem;
    font-weight: 700;
    letter-spacing: .1em;
    color: var(--marca-primaria);
}
[data-bs-theme="dark"] .or-nivel__num { color: var(--or-brand-accent); }
.or-nivel__titulo {
    margin: 0 0 var(--or-esp-3);
    font-size: var(--or-fs-h3);
    letter-spacing: -.015em;
    line-height: 1.15;
    color: var(--color-primary);
}
.or-nivel__tagline {
    margin: 0;
    font-size: .9375rem;
    line-height: 1.6;
    color: var(--texto-secundario);
}

/* --- .or-comparativo (/presenca-em-ia) — matriz "busca tradicional × busca com IA".
   É <table> DE VERDADE, e isso é decisão de acessibilidade: uma matriz de comparação precisa que o
   leitor de tela navegue por linha e coluna anunciando o cabeçalho de cada célula. <div> com
   aparência de tabela perde isso.

   ⚠️ POR QUE NÃO REUSAR .or-planos-table: aquela resolve o mobile com `overflow-x: auto` +
   `white-space: nowrap` na primeira coluna — ou seja, ROLAGEM HORIZONTAL por projeto. Numa matriz
   de 3 colunas de texto corrido isso obriga a arrastar para ler metade do conteúdo, e o briefing
   desta página proíbe explicitamente. Aqui a linha EMPILHA.

   ⚠️ E POR QUE O MARKUP TRAZ role="table"/"row"/"cell" APARENTEMENTE REDUNDANTES: trocar o
   `display` de um elemento de tabela (que é o que o breakpoint faz para empilhar) APAGA a
   semântica nativa de tabela no leitor de tela — comportamento conhecido do CSS, não bug de
   navegador. Os papéis explícitos são o que devolve a semântica; sem eles, o ganho visual do
   mobile custaria a acessibilidade que motivou usar <table>.

   Zero token novo: raio, sombra, espaçamento e cor saem do Bloco 0. --- */
.or-comparativo {
    width: 100%;
    border-collapse: collapse;
    background: var(--color-white);
    border-radius: var(--or-radius-m);
    box-shadow: var(--or-shadow-1);
    overflow: hidden;
}
[data-bs-theme="dark"] .or-comparativo {
    background: var(--or-surface-2);
    box-shadow: none;
    border: 1px solid var(--or-border);
}
.or-comparativo th,
.or-comparativo td {
    padding: var(--or-esp-4) var(--or-esp-5);
    border-bottom: 1px solid var(--color-1);
    text-align: left;
    vertical-align: top;
}
[data-bs-theme="dark"] .or-comparativo th,
[data-bs-theme="dark"] .or-comparativo td { border-bottom-color: var(--or-border); }
.or-comparativo tbody tr:last-child th,
.or-comparativo tbody tr:last-child td { border-bottom: 0; }
.or-comparativo thead th {
    font-size: .8125rem;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--texto-secundario);
}
.or-comparativo tbody th {
    font-size: .9375rem;
    font-weight: 600;
    /* Tracking proporcional — ver a nota do BLOCO 1 (~linha 224): <th> não é heading, mas herda a
       escala do corpo; declarar aqui mantém a coluna previsível se a fonte base mudar. */
    letter-spacing: -.005em;
    color: var(--color-primary);
}
.or-comparativo tbody td {
    font-size: .9375rem;
    line-height: 1.55;
    color: var(--texto-secundario);
}
/* A coluna da IA é o lado que a página defende — recebe o tom da marca, não um fundo colorido
   (que brigaria com o zebrado do tema e com o dark). */
.or-comparativo .or-comparativo__destaque { color: var(--color-primary); font-weight: 600; }
[data-bs-theme="dark"] .or-comparativo tbody th,
[data-bs-theme="dark"] .or-comparativo .or-comparativo__destaque { color: var(--or-text); }

@media (max-width: 767.98px) {
    /* Cada linha vira um cartão empilhado: o rótulo da linha é o título, e cada célula ganha o
       nome da sua coluna pelo data-label — sem isso, empilhado, ninguém sabe qual valor é de qual
       lado. O thead some porque seus rótulos passam a viver dentro das células. */
    .or-comparativo,
    .or-comparativo tbody,
    .or-comparativo tr,
    .or-comparativo th,
    .or-comparativo td { display: block; width: 100%; }
    .or-comparativo thead { display: none; }
    .or-comparativo tbody tr {
        padding: var(--or-esp-4) 0;
        border-bottom: 1px solid var(--color-1);
    }
    [data-bs-theme="dark"] .or-comparativo tbody tr { border-bottom-color: var(--or-border); }
    .or-comparativo tbody tr:last-child { border-bottom: 0; }
    .or-comparativo th,
    .or-comparativo td { border-bottom: 0; padding: var(--or-esp-2) var(--or-esp-5); }
    .or-comparativo tbody th { font-size: 1rem; padding-bottom: var(--or-esp-3); }
    .or-comparativo tbody td::before {
        content: attr(data-label);
        display: block;
        margin-bottom: 2px;
        font-size: .75rem;
        font-weight: 700;
        letter-spacing: .06em;
        text-transform: uppercase;
        color: var(--texto-secundario);
    }
}

/* --- .or-trabalho__num — o índice de cada frente de trabalho (/presenca-em-ia).
   Classe própria, e não reuso de .or-nivel__num, porque aquele pertence ao card de PLANO: mudar o
   visual de um arrastaria o outro sem relação de causa. Mesma escala, papel diferente. --- */
.or-trabalho__num {
    margin: 0 0 var(--or-esp-2);
    font-size: .8125rem;
    font-weight: 700;
    letter-spacing: .1em;
    color: var(--marca-primaria);
}
[data-bs-theme="dark"] .or-trabalho__num { color: var(--or-brand-accent); }

/* --- .or-plano-fronteira__titulo — o "em qual plano isso entra" dentro de um .or-card.
   Só reescala: <h3> cru herdaria os 80px do vendor (regra de ouro do BLOCO 1, ~linha 224). --- */
.or-plano-fronteira__titulo {
    margin: 0 0 var(--or-esp-4);
    font-size: var(--or-fs-h3);
    letter-spacing: -.015em;
    line-height: 1.2;
    color: var(--color-primary);
}

/* --- .or-faq-sobre — o acordeão do vendor virando cartão (/sobre).
   O molde do vendor desenha LINHAS soltas (border-top, padding lateral ZERO). Numa coluna estreita
   isso lê bem; na /sobre o acordeão herdava col-12 dentro do .custom-container, que passa de
   1500px no desktop — uma pergunta de 40 caracteres sozinha numa linha de 1536px, com o chevron
   perdido na borda oposta. O markup já foi para col-lg-10 (metade do problema); esta regra resolve
   a outra metade dando ao conjunto uma superfície com respiro interno, em vez de traços colados
   na margem.

   Zero valor novo: raio, sombra e espaçamento saem dos tokens. No escuro a sombra vira borda —
   mesmo precedente de .or-card (~linha 1128), porque sombra não lê sobre fundo escuro. --- */
.or-faq-sobre {
    background: var(--color-white);
    border-radius: var(--or-radius-m);
    box-shadow: var(--or-shadow-1);
    padding: 0 var(--or-esp-6);
    overflow: hidden;
}
[data-bs-theme="dark"] .or-faq-sobre {
    background: var(--or-surface-2);
    box-shadow: none;
    border: 1px solid var(--or-border);
}
/* O vendor fecha a última linha com border-bottom: dentro de um cartão isso desenha um traço
   colado na borda inferior. Aqui a régua separa APENAS item de item. */
.or-faq-sobre .accordion-item:first-child { border-top: 0; }
.or-faq-sobre .accordion-item:last-child { border-bottom: 0; }
.or-faq-sobre .accordion-button { padding-inline: 0; }
.or-faq-sobre .accordion-body { padding-inline: 0; }
@media (max-width: 575.98px) {
    .or-faq-sobre { padding: 0 var(--or-esp-4); }
}
.or-pilar__titulo {
    /* Tracking proporcional — ver a nota do BLOCO 1 (~linha 224). Sem isto herdaria os -2px que o
       vendor calibrou para o h3 cru de 80px, e as letras colariam neste corpo de ~20px. */
    margin-bottom: var(--or-esp-3);
    font-size: 1.125rem;
    font-weight: 600;
    letter-spacing: -.01em;
    line-height: 1.35;
    color: var(--color-primary);
}
.or-pilar__texto {
    margin-bottom: 0;
    font-size: .9375rem;
    line-height: 1.65;
    color: var(--texto-secundario);
}

/* ================================================================
   BLOCO 4 — TEMA · PÁGINAS COMUNS (serviços, contato, planos — compartilhado entre várias páginas
   do funil comercial, não só a home).
   ================================================================ */

/* --- Ícone de serviço (\OneRank\Icon::render(), SVG inline) — o slot .quanto-iconbox-icon do
   vendor nasceu pra uma <img> de tamanho fixo do vendor; o SVG do catálogo próprio da plataforma
   herda currentColor, então dimensionamos e coloramos aqui. */
.or-servico-icon svg { width: 40px; height: 40px; color: var(--marca-primaria); }
.or-servico-icon--detalhe svg { width: 56px; height: 56px; }

/* --- Mídia por serviço (evolução F5) — largura própria menor que a coluna de prosa (col-lg-9/8):
   o par .or-device com sobreposição foi desenhado pra coluna de metade de página (home #painel),
   aqui é fluxo único mais estreito. --- */
.or-servico-midia { max-width: 560px; }

/* --- Composição browser + phone flutuante (aba "Presença digital em plataforma própria",
   evolução "primeira dobra", 26/08/2026) — moldura --browser (tela de login) com a moldura
   --phone (dashboard em viewport de celular) sobreposta no canto inferior direito, reforçando
   visualmente a tag "Responsivo em qualquer tela". position:relative no wrapper porque aqui o
   --phone é position:absolute (diferente do uso em #painel, onde --secundario empilha em fluxo
   normal, deslocado só por margin negativa). --- */
.or-servico-midia--composto { position: relative; }
.or-servico-midia--composto .or-device--phone-flutuante {
    position: absolute;
    right: -18px;
    bottom: -28px;
    max-width: 130px;
    margin: 0;
    z-index: 2;
}
@media (max-width: 575.98px) {
    .or-servico-midia--composto .or-device--phone-flutuante { right: -8px; bottom: -18px; max-width: 96px; }
}

/* --- #servicos "O que você contrata" — mostruário com abas (F5.2 da reestruturação da home).
   Mecânica 100% Bootstrap 5.3 (já carregado, _head.php) — .or-servicos-tab é só a PELE do botão;
   tab-content/tab-pane/fade/show/active continuam do Bootstrap, nunca reescritos. Sem
   .nav/.nav-link/.nav-tabs de propósito: o Tab do Bootstrap só exige role="tab"+data-bs-toggle,
   nav-link traria o cromo padrão brigando com o Quanto. */
.or-servicos-showcase__lista {
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.or-servicos-tab {
    display: flex;
    align-items: center;
    gap: 14px;
    width: 100%;
    padding: 16px 18px;
    background: transparent;
    border: none;
    border-left: 3px solid transparent;
    border-radius: 0 var(--or-radius-m) var(--or-radius-m) 0;
    text-align: left;
    cursor: pointer;
    transition: background-color .2s ease, border-color .2s ease;
}
.or-servicos-tab:hover { background: color-mix(in srgb, var(--marca-primaria) 6%, transparent); }
.or-servicos-tab.active {
    background: var(--color-white);
    border-left-color: var(--marca-primaria);
    box-shadow: var(--or-shadow-1);
}
[data-bs-theme="dark"] .or-servicos-tab.active { background: var(--or-surface); }
.or-servicos-tab__ico { flex-shrink: 0; }
.or-servicos-tab__ico svg { width: 28px; height: 28px; color: var(--marca-primaria); }
[data-bs-theme="dark"] .or-servicos-tab__ico svg { color: var(--or-brand-accent); }
.or-servicos-tab__txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.or-servicos-tab__titulo {
    font-size: var(--or-fs-card);
    font-weight: 600;
    letter-spacing: -.01em;
    color: var(--color-primary);
}
.or-servicos-tab.active .or-servicos-tab__titulo { color: var(--marca-primaria); }
[data-bs-theme="dark"] .or-servicos-tab.active .or-servicos-tab__titulo { color: var(--or-brand-accent); }
/* .or-servicos-tab__sub — SAIU o par white-space:nowrap + text-overflow:ellipsis (29/08/2026).
   Motivo: com a lista de abas em col-lg-7 (era col-5) a coluna de texto ficou larga o bastante
   pros 6 subtítulos reais do seed caberem sem cortar. -webkit-line-clamp:2 fica como TETO de
   segurança pro que o operador digitar no admin, não como corte de rotina. */
.or-servicos-tab__sub {
    font-size: var(--or-fs-small);
    color: var(--or-text-muted);
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
            line-clamp: 2;
    overflow: hidden;
}
/* min-height só ≥992px (era 420px incondicional) — abaixo disso o palco é col-12 e a mídia sozinha
   já passa dos 470px; o piso ficaria inerte.

   RECALIBRADO 01/09/2026 — CAUSA RAIZ de "a tela sobe e volta" ao clicar nas 6 abas em sequência
   (achado do dono). Os 620px antigos foram escolhidos pra "casar visualmente com a lista de abas
   ao lado", NUNCA medidos contra o maior painel real — mesmo raciocínio de design, resultado
   estrutural diferente do irmão .or-ia__palco (custom.css, ~linha 2989), que desde 28/08/2026 é
   calibrado pelo maior conteúdo MEDIDO ao vivo e por isso nunca precisou de refresh() reativo pra
   evitar salto (ver home.php:1885-1899). Aqui a altura SEMPRE variou por aba — o comentário antigo
   já admitia isso ("continua variando, só varia menos") — e cada troca de aba fazia o
   ScrollTrigger.refresh() do listener shown.bs.tab recalcular uma altura de documento
   GENUINAMENTE diferente, e essa mudança real de altura é o que o ScrollSmoother sentia como
   salto. Não era o refresh() em si (a causa do bug de 29/08, dois listeners simultâneos, não se
   repetia aqui — confirmado, só existe um).

   MEDIDO AO VIVO via Playwright (01/09/2026), as 6 abas em várias larguras: o comportamento NÃO É
   monotônico com a viewport (a imagem do device mockup cresce livre até o .custom-container
   saturar em 1604px — `.or-servicos-showcase__palco .or-servico-midia{max-width:none}` abaixo — e
   o layout de 2 colunas das tags muda de forma discreta em algum ponto entre ~1150-1600px,
   produzindo picos em faixas diferentes: 671,3px em 992-1150px (aba "SEO e presença em IA"),
   620px flat em 1200-1440px, até 699,41px em ≥1604px (aba "Manutenção, monitoramento e
   segurança" — estável e idêntico em 1604/1920/2560px, confirmando que é o teto real de vez que
   o container para de crescer). 700px = 699,41 arredondado pra cima, mesmo critério do
   .or-ia__palco ("teto arredondado pra cima zera o shift residual").

   Consequência aceita: o palco fica ~60px mais alto que a lista de abas ao lado (que mede 640px em
   1440px) — abrir mão do "casar visualmente" é o preço de eliminar o salto de verdade; ver
   comparação visual antes de aceitar como definitivo. */
@media (min-width: 992px) {
    .or-servicos-showcase__palco { min-height: 700px; }
}
/* .or-servico-midia nasceu com max-width:560px pensando em /servicos/<slug> (coluna de prosa
   larga, col-lg-9) — no palco a coluna é a própria col-lg-5 (era col-7): o teto de 560px sobrava
   como vão morto à direita da imagem em telas grandes. Escopado ao palco: /servicos/<slug>
   continua com os 560px. */
.or-servicos-showcase__palco .or-servico-midia { max-width: none; }
.or-servicos-showcase__legenda { max-width: none; }

/* --- Bloco de info da aba: legenda + tags + CTA (evolução "primeira dobra", 26/08/2026; teto de
   560px removido em 29/08/2026 pelo mesmo motivo do .or-servico-midia acima — a coluna já é a
   medida certa, o teto só sobrava vão morto em telas grandes). --- */
.or-servicos-showcase__info {
    max-width: none;
    display: flex;
    flex-direction: column;
    gap: 14px;
    margin-top: 18px;
}

/* --- Tags do palco em grade 2×N (o "col-6" pedido pelo dono, 29/08/2026) -----------------------
   ESCOPO POR DESCENDÊNCIA, não modificador: .or-tag é o chip compartilhado por _hero-interno,
   portfolio, produtos e servico.php — mexer na regra base mudaria os 4 contextos. (#para-quem-e
   usava .or-tag/.or-tag-list até 29/08/2026 — migrou pra .or-segmento-card na reestruturação de
   conversão, ver abaixo; os outros 4 usos continuam intocados.)
   .or-servicos-showcase__info (1 uso no site) vence por especificidade sem !important e sem
   classe .or-* nova.

   GRID, não .row/.col: uma row do Bootstrap aqui dentro reintroduziria a família de bug do
   gutter negativo (row-padding-top + g-*) dentro de uma coluna que já vive numa row assim.
   minmax(0,1fr) e não 1fr: 1fr tem min-width:auto e uma palavra longa esticaria a trilha.

   As 2 exceções de 1 coluna vêm da conta de largura, não de gosto (col-lg-5 interno menos o gap
   de 8px, dividido por 2, menos ~30px de cromo da pílula compacta, a ~7,37px/caractere):
     1920px → 38 chars/tag · 1440px → 33 · 1200px → 27  ⇒ 2 colunas cabem
     992-1199px → 21 chars  ← o vendor trava .custom-container em 970px FIXOS nessa faixa
     ≤575,98px  → 19 chars  ← container de 540px
   Nas duas o orçamento de copy (25 caracteres, ver _servicos-midia.php) não cabe ⇒ 1 coluna. --- */
.or-servicos-showcase__info .or-tag-list {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--or-esp-2);
}
@media (max-width: 575.98px),
       (min-width: 992px) and (max-width: 1199.98px) {
    .or-servicos-showcase__info .or-tag-list { grid-template-columns: minmax(0, 1fr); }
}
/* Pílula compacta SÓ aqui: a 15px/padding 22px (tamanho base de .or-tag) o orçamento no gargalo
   de 1200px cairia de 27 pra ~22 caracteres — curto demais pra "Relatório de conformidade" sem
   virar telegrama. Como item de grid o .or-tag (inline-flex) recebe justify-self:stretch, então
   as 2 pílulas de cada linha saem com a MESMA largura — é o que dá a leitura de "col-6". */
.or-servicos-showcase__info .or-tag {
    padding: 8px 14px;
    font-size: var(--or-fs-small);
    line-height: 1.4;
}

/* --- #para-quem-e — 12 cards de segmento + fundo em 3 camadas (reestruturação de conversão,
   29/08/2026). SEÇÃO NÃO FLIPA no dark — mesmo molde de .or-ia (#geo, ~linha 2643): background
   fixo próprio (não .bg-color-primary, que flipa pra --or-surface-2), então .text-color-white é
   PROIBIDA aqui (mesma razão documentada no bloco de .or-ia) — cor literal escopada abaixo. */
.or-segmentos-bg {
    position: absolute;
    inset: 0;
    z-index: 0;
    overflow: hidden;
    pointer-events: none;
}
#para-quem-e {
    position: relative;
    background: var(--or-grad-marca);
}
#para-quem-e > .container { position: relative; z-index: 1; }
#para-quem-e .title { color: #fff; }
#para-quem-e .or-lead { color: rgba(255, 255, 255, .78); opacity: 1; } /* .or-lead nasce --color-primary + opacity .75 */

/* Camada 2 — malha de pontos, CSS puro (radial-gradient repetido), zero byte de rede. */
.or-segmentos-bg__malha {
    position: absolute;
    inset: -10%;
    background-image: radial-gradient(rgba(255, 255, 255, .14) 1px, transparent 1.5px);
    background-size: 26px 26px;
}
/* Camada 3 — 2 orbes de luz difusa em cantos opostos, profundidade em 3 planos com a malha e o
   gradiente de base. Blur via filter (não box-shadow) pra não pesar no compositing do parallax. */
.or-segmentos-bg__orbe {
    position: absolute;
    width: 46vw;
    height: 46vw;
    max-width: 560px;
    max-height: 560px;
    border-radius: 50%;
    filter: blur(70px);
    opacity: .35;
}
/* var(--marca-primaria)/var(--marca-secundaria) nos dois orbes, NUNCA var(--or-dourado) — o
   dourado é lista FECHADA de 6 pontos (BLOCO 0.5, ~linha 71): "deixa de significar destaque no
   instante em que aparece em toda parte". Um orbe decorativo de fundo não entra na lista. */
.or-segmentos-bg__orbe--1 { top: -14%; left: -10%; background: var(--marca-primaria); }
.or-segmentos-bg__orbe--2 { bottom: -18%; right: -8%; background: var(--marca-secundaria, #082C6A); }

/* Cards — "vidro" translúcido sobre o gradiente (nenhum card claro funcionaria aqui: o fundo é
   sempre escuro, ver acima). Ícone em branco a 85% — nem literal #fff (mais forte que precisa
   pro papel de suporte do título) nem var(--or-brand-accent) (token SÓ definido dentro de
   [data-bs-theme=dark] no core — indefinido no claro, que é o tema default; ver comentário em
   .or-ia mais abaixo pro mesmo raciocínio aplicado a texto). */
.or-segmento-card {
    height: 100%;
    padding: 22px;
    border-radius: var(--or-radius-m);
    background: rgba(255, 255, 255, .06);
    border: 1px solid rgba(255, 255, 255, .12);
    transition: background-color .25s ease, border-color .25s ease;
}
.or-segmento-card:hover {
    background: rgba(255, 255, 255, .1);
    border-color: rgba(255, 255, 255, .22);
}
.or-segmento-card__ico {
    display: inline-flex;
    color: rgba(255, 255, 255, .85);
    font-size: 28px;
    margin-bottom: 14px;
}
.or-segmento-card :is(h3, h4) {
    color: #fff;
    font-size: 17px;
    font-weight: 600;
    /* DEFEITO MEDIDO em 03/09/2026: a regra declarava tamanho e esquecia o tracking, então o
       heading herdava os -1.5px que o vendor calibrou para 60px. Em 17px isso é -8,8% do corpo —
       as letras encostavam umas nas outras. É a armadilha documentada no BLOCO 1 (~linha 224), e
       já era a terceira vez neste arquivo (.or-servico-card__titulo e .or-faq-atalho__titulo
       foram as anteriores). Declarar tamanho SEM declarar tracking é meio conserto. */
    letter-spacing: -.01em;
    margin-bottom: 6px;
}
.or-segmento-card p {
    color: rgba(255, 255, 255, .7);
    font-size: var(--or-fs-small);
    line-height: 1.5;
    margin: 0;
}
@media (max-width: 991.98px) {
    .or-segmentos-bg__orbe { width: 70vw; height: 70vw; }
}

/* --- Lista compacta de frentes adicionais (evolução "primeira dobra", 26/08/2026; ampliada de
   5 pra 15 itens e movida pra row própria col-lg-10 centralizada em 29/08/2026 — ver home.php).
   margin-top SAIU: quem separa esta row da row das abas agora é o row-padding-top da PRÓPRIA row
   (CLAUDE.md §Padrão de Espaçamento: "nunca os dois no mesmo ponto" — manter os dois somaria).
   padding-top + border-top FICAM: não são espaçamento entre rows, são a fronteira interna que faz
   o bloco ler como rodapé da seção. Conteúdo centralizado (não só a coluna): num bloco col-10
   centrado, texto encostado à esquerda lê como desalinho acidental. --- */
.or-frentes-extra {
    padding-top: 20px;
    border-top: 1px solid var(--or-border);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    text-align: center;
}
.or-frentes-extra__titulo {
    font-size: var(--or-fs-small);
    font-weight: 600;
    color: var(--or-text-muted);
    text-transform: uppercase;
    letter-spacing: .04em;
}
.or-frentes-extra__lista {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 8px;
    list-style: none;
    margin: 0;
    padding: 0;
}
.or-frentes-extra__item {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    border-radius: var(--or-radius-pill);
    background: color-mix(in srgb, var(--marca-primaria) 6%, transparent);
    font-size: var(--or-fs-small);
    color: var(--color-primary);
}
.or-frentes-extra__item svg { width: 16px; height: 16px; color: var(--marca-primaria); }
[data-bs-theme="dark"] .or-frentes-extra__item {
    background: color-mix(in srgb, var(--or-brand-accent) 12%, transparent);
    color: var(--or-text);
}
[data-bs-theme="dark"] .or-frentes-extra__item svg { color: var(--or-brand-accent); }
/* Nota de plano abaixo da lista — a lista passou a citar capacidades gateadas por tier (app
   instalável/crawlers de IA/estrelas = Autoridade; 301/canônica = Destaque). t-small/t-muted já
   têm regra própria (BLOCO 1.5); esta classe só carrega medida e respiro. */
.or-frentes-extra__nota {
    margin: 6px 0 0;
    max-width: 62ch;
}
.or-frentes-extra__nota a { text-decoration: underline; }

@media (max-width: 991.98px) {
    /* Respiro do EMPILHAMENTO entre a row das abas/palco e a row das frentes: agora que a
       primeira é g-4 g-xl-5 (não gx-), o gutter vertical nativo já separa abas↔palco quando
       empilham — mas a row 3 (frentes) é row-padding-top sozinha (60/45px), que já é suficiente
       entre ROWS. O que falta é o respiro entre o PALCO (fim da row 2) e a lista de abas quando
       ela aparece DEPOIS dele no fluxo empilhado — mesmo remédio de .or-ia__linha-resposta. */
    .or-servicos-showcase__palco { margin-top: var(--or-esp-5); }

    .or-servicos-showcase__lista {
        flex-direction: row;
        overflow-x: auto;
        gap: 8px;
        padding-bottom: 4px;
        -webkit-overflow-scrolling: touch;
    }
    .or-servicos-tab {
        flex-direction: column;
        align-items: flex-start;
        gap: 8px;
        width: auto;
        min-width: 200px;
        max-width: 260px;
        border-left: none;
        border-bottom: 3px solid transparent;
        border-radius: var(--or-radius-m) var(--or-radius-m) 0 0;
    }
    .or-servicos-tab.active { border-bottom-color: var(--marca-primaria); }
    /* SUBTÍTULO SOME NO TRILHO (29/08/2026) — não é economia de espaço, é DUPLICATA: o palco
       renderiza $serDescr, que É o próprio SER_SUBTITULO (home.php) quando cadastrado, a poucos
       pixels abaixo. Manter os dois obrigaria caber ~100 caracteres numa aba de 260px (2 linhas
       cortando) pra repetir o que a legenda do palco já diz inteiro. Em ≥992px o subtítulo volta
       (é a coluna larga que fez o line-clamp:2 acima nunca precisar cortar de verdade). */
    .or-servicos-tab__sub { display: none; }
}
/* Celular estreito: a 375px a col-12 dá ~351px e um chip de frente-extra de ~28 caracteres já
   ocupa a linha toda — 15 chips virariam ~15 linhas empilhadas. Encolher o chip devolve pelo
   menos 2 por linha nos aparelhos mais curtos. */
@media (max-width: 575.98px) {
    .or-frentes-extra__item { padding: 5px 10px; font-size: .8125rem; }
    .or-frentes-extra__item svg { width: 14px; height: 14px; }
}

/* --- Acordeão de etapas "Como funciona" — Bootstrap nativo (F5.5 da reestruturação; era
   .horizontal-scroll, pin GSAP com scroll-jacking, main.js:405-418 end:"+=3000px" — remover a
   classe mata o pin com segurança, ambos os pontos de uso já têm guarda `if (!hs) return`).
   MIGROU da home (#como-funciona) para /servicos em 29/08/2026 — a classe .or-etapas-acordeao é
   a mesma, só o markup que a usa mudou de arquivo (ver pages/servicos.php). Reusa
   .quanto-faq-accordion (mesmo CSS de #faqs) — este bloco só existe pra fazer o accordion
   funcionar sobre bg-color-primary, que é PERMANENTEMENTE escuro nos 2 temas (não flipa) —
   tokens literais, mesma doutrina do rodapé. Sobrescreve as custom properties do próprio
   Bootstrap (--bs-accordion-*) em vez de brigar com especificidade regra a regra. */
.or-etapas-acordeao {
    --bs-accordion-bg: transparent;
    --bs-accordion-color: #fff;
    --bs-accordion-btn-color: #fff;
    --bs-accordion-btn-bg: transparent;
    --bs-accordion-active-color: #fff;
    --bs-accordion-active-bg: transparent;
    --bs-accordion-border-color: rgba(255, 255, 255, .16);
    --bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23ffffff'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
    --bs-accordion-btn-active-icon: var(--bs-accordion-btn-icon);
}
.or-etapas-acordeao .accordion-button { font-weight: 600; }
/* --bs-accordion-bg cobre o FUNDO (.accordion-item usava var(--bs-body-bg), branco cru — as
   "caixas brancas" medidas ao vivo). O TEXTO do item expandido é outro achado: o vendor tem
   .quanto-faq-accordion .accordion-button:not(.collapsed){color:initial} (style.css) — 3 classes/
   pseudo = especificidade (0,3,0), maior que a var(--bs-accordion-btn-color) da regra base do
   Bootstrap (0,1,0) E que a nossa primeira tentativa aqui (0,2,0). Precisa iguakar a
   especificidade (mesma cadeia .quanto-faq-accordion .accordion-button:not(.collapsed)) pra vencer
   por ordem de arquivo (custom.css carrega depois do style.css). */
.quanto-faq-accordion.or-etapas-acordeao .accordion-button:not(.collapsed) { color: #fff; }
.or-etapas-acordeao .accordion-body { color: rgba(255, 255, 255, .78); }
.or-etapas-acordeao__num {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 32px;
    height: 32px;
    margin-right: 16px;
    border: 1px solid rgba(255, 255, 255, .3);
    border-radius: 50%;
    font-size: .9rem;
    font-weight: 700;
}

/* --- #faqs: 4 grupos temáticos lado a lado (reestruturação de conversão, 29/08/2026 — largura
   total, pedido do dono). Cards com o componente .or-card/.or-card--claro (padronização de
   espaçamento, 29/08/2026, achado ao vivo do dono) — antes .or-faq-grupo era uma coluna sem
   fundo/borda/padding, e o único respiro próprio da seção (título→acordeão) ficava em 16px,
   abaixo do piso de 24px do CLAUDE.md. Ícone segue o padrão de .or-prova-card__ico (marca no
   claro, --or-brand-accent no escuro).
   height:auto (não 100%): os 4 grupos têm quantidades desiguais de pergunta (5/5/5/4) — esticar
   o par pra mesma altura sobrava ~134px de área vazia no card mais curto, só visível depois que
   o card ganhou fundo/sombra. Decisão do dono: altura própria por card (topos alinhados pela
   .row, rodapés podem divergir). */
.or-faq-grupo { display: flex; flex-direction: column; height: auto; }
/* letter-spacing explícito obrigatório (mesmo padrão D2 já registrado em .or-prova-card h4 e
   .or-lgpd-bastidor__titulo): o vendor prende letter-spacing à TAG em px (h4 -1,5px calibrado
   pra 60px cru) — sem override, um <h4> de 17px herdava a mesma -1,5px (-8,8% do corpo, letras
   coladas). */
.or-faq-grupo__titulo {
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 17px;
    font-weight: 600;
    letter-spacing: -.01em;
    color: var(--color-primary);
    margin-bottom: var(--or-esp-5);
}
.or-faq-grupo__ico { display: inline-flex; color: var(--marca-primaria); font-size: 22px; }
[data-bs-theme="dark"] .or-faq-grupo__ico { color: var(--or-brand-accent); }

/* último item do accordion sem a borda inferior do vendor (style.css:5044) — dentro do .or-card
   ela ficava órfã, flutuando 28px acima do canto arredondado sem nada abaixo pra separar. */
.or-faq-grupo .quanto-faq-accordion .accordion-item:last-child { border-bottom: none; }

/* --- Formulário (contato + planos) — sobre .quanto-contact__form .form-control já estilizado
   pelo vendor (style.css:5834+); aqui só o que falta: label visível (o vendor usa só placeholder,
   mas a plataforma exige label pra a11y), consentimento LGPD e alerta de resultado (sem
   componente equivalente no vendor). */
.or-form__field { margin-bottom: 0; }
.or-form__field label { display: block; font-size: .85rem; font-weight: 600; color: var(--color-primary); margin-bottom: 6px; }
.or-form-alert { padding: 14px 18px; border-radius: 8px; font-size: .92rem; margin-bottom: 20px; }

/* ── CAMPOS DO FORMULÁRIO — borda, foco e altura (05/09/2026) ────────────────────────────────
   Print 2 do dono: "o form de contato nem tem padronização de campos, está totalmente
   desalinhado, sem bordas entre campos". Medido: o vendor (style.css:5834-5846) define
   `border: none` no `.form-control` E `box-shadow: none` no `:hover, :focus`. Duas consequências:

     1. Campo sem contorno — o único sinal de "aqui se digita" era um cinza levemente diferente
        do fundo do card, que praticamente some quando o formulário está DENTRO de um card
        (é o caso desde a F4). Campos adjacentes viram uma mancha só.
     2. O `box-shadow:none` no `:focus` apaga o anel do Bootstrap sem colocar nada no lugar —
        quem navega por teclado perdia o campo ativo de vista. Isso é WCAG 2.4.7 (foco visível),
        não preferência de estilo.

   Altura: 22px de padding vertical sobre 18px de fonte dava 70px de campo — desproporcional ao
   rótulo de 13,6px acima dele e a causa da sensação de "desalinhado" quando dois campos pareiam
   na mesma linha. 15px/18px devolve ~58px, alinhado à escala do resto do site.

   Especificidade: `.quanto-contact__form .form-control` do vendor pesa (0,2,0); repetimos o
   MESMO peso e vencemos por ordem de carregamento (custom.css vem depois de style.css). */
.quanto-contact__form .form-control {
    border: 1px solid var(--or-border, rgba(0, 0, 0, .12));
    background: var(--or-surface, #fff);
    padding: 15px 18px;
    font-size: 1rem;
    color: var(--color-primary);
    transition: border-color .15s ease, box-shadow .15s ease;
}
.quanto-contact__form .form-control::placeholder { color: var(--or-text-muted); opacity: 1; }
/* Hover escurece a borda por color-mix sobre o MESMO token do repouso — sem inventar um segundo
   token de borda que teria de ser mantido em sincronia com --or-border nos dois temas. */
.quanto-contact__form .form-control:hover {
    border-color: color-mix(in srgb, var(--or-border, rgba(0, 0, 0, .12)) 100%, var(--color-primary) 25%);
}

/* Foco: anel da marca reconstruído (o vendor zera o do Bootstrap). box-shadow em vez de outline
   para acompanhar o border-radius do campo sem o "canto quadrado" que o outline produz. */
.quanto-contact__form .form-control:focus {
    border-color: var(--marca-primaria);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--marca-primaria) 18%, transparent);
    outline: none;
}
/* Erro (or-form.js marca aria-invalid) — a borda existe, então ela mesma carrega o estado; sem
   isto o único sinal de campo inválido seria a mensagem abaixo, longe do olhar de quem digita. */
.quanto-contact__form .form-control[aria-invalid="true"] {
    border-color: #A23B2C;
}
.quanto-contact__form .form-control[aria-invalid="true"]:focus {
    box-shadow: 0 0 0 3px color-mix(in srgb, #A23B2C 18%, transparent);
}
[data-bs-theme="dark"] .quanto-contact__form .form-control {
    background: var(--or-surface-2);
    border-color: var(--or-border);
    color: var(--or-text);
}
.or-form-alert--success { background: color-mix(in srgb, #1F7A4D 15%, transparent); color: #1F7A4D; }
.or-form-alert--error { background: color-mix(in srgb, #A23B2C 15%, transparent); color: #A23B2C; }

/* ═══════════════════════════════════════════════════════════════════════════════════════════
   BLOCO 20 — CONSENTIMENTO LGPD (.or-consent) — 05/09/2026
   ═══════════════════════════════════════════════════════════════════════════════════════════
   Substitui .or-form__consent, que somava quatro defeitos: font-size:.82rem FORA da escala
   tipográfica do projeto (--or-fs-small é .875rem), opacity:.75 por cima disso, checkbox de
   ~14px (1em herdado do .82rem — regra base do Bootstrap), muito abaixo de qualquer alvo de
   toque razoável e do piso de 24px do WCAG 2.5.8, e :checked no azul #0d6efd fixo do Bootstrap,
   estranho à marca nos dois temas. O aceite é a peça que dá VALIDADE JURÍDICA ao dado captado —
   tratá-lo como letra miúda é o oposto do que a LGPD pede (art. 8º §4º: consentimento destacado
   das demais cláusulas). Usado por TODOS os formulários do tema que incluem
   site/includes/consent-checkbox.php (CORE — markup intocável pelo fork): contato, planos,
   candidatura a vaga — a única alavanca do fork é a classe passada em $consentDivCls.

   Markup do CORE (fixo, não editável aqui):
     <div class="or-consent">
       <input class="form-check-input" type="checkbox" ...>
       <label class="form-check-label small ..." for="...">texto + link</label>
     </div>
   Input e label são IRMÃOS — não é um <label> envolvendo tudo. Por isso o "alvo de clique"
   cresce pelo tamanho real do checkbox (20px) + a área do texto (que já é clicável via `for`),
   não por um wrapper universal — o markup não permite outra coisa sem tocar o core. */
.or-consent {
    display: flex;
    align-items: flex-start;
    gap: var(--or-esp-3, 12px);
    margin-top: var(--or-esp-3, 12px);
    padding: var(--or-esp-4, 16px);
    border-radius: var(--or-radius-s, 8px);
    background: var(--or-surface-2, rgba(0, 0, 0, .025));
    border: 1px solid var(--or-border, rgba(0, 0, 0, .08));
}

/* Checkbox — 20px reais (o piso de toque de 24px vem da soma com o padding do wrapper, não de
   inflar o próprio quadrado, que ficaria desproporcional ao texto). accent-color assume a cor da
   marca nos navegadores que suportam (Chromium/Firefox atuais); onde não suporta, cai no azul
   nativo do SO — degrada sem quebrar função. */
.or-consent .form-check-input {
    flex: 0 0 auto;
    width: 20px;
    height: 20px;
    margin: 1px 0 0;
    accent-color: var(--marca-primaria);
    cursor: pointer;
}
.or-consent .form-check-input:focus-visible {
    outline: 2px solid var(--marca-primaria);
    outline-offset: 2px;
}

/* Texto — sai da escala fora-do-padrão (.82rem) pra --or-fs-small (.875rem, a MESMA de
   .or-pg .t-small); (0,2,0) já vence o `.small`/`small{font-size:.875em}` do Bootstrap
   (0,1,0/0,0,1) sem precisar de !important. opacity:.75 SAI — texto de consentimento não é nota
   de rodapé. */
.or-consent .form-check-label {
    margin: 0;
    font-size: var(--or-fs-small, .875rem);
    line-height: 1.5;
    color: var(--color-primary);
    cursor: pointer;
}
.or-consent .form-check-label a {
    color: var(--texto-link, var(--marca-primaria));
    text-decoration: underline;
    text-underline-offset: 2px;
    font-weight: 600;
}
.or-consent .form-check-label a:hover { color: var(--marca-secundaria, var(--marca-primaria)); }

/* Realce da caixa inteira quando o checkbox está focado — só progressive enhancement (:has()),
   sem função nenhuma dependendo dele: quem não suporta vê só o outline do próprio input acima. */
.or-consent:has(.form-check-input:focus-visible) {
    border-color: var(--marca-primaria);
}

/* dark-safe: --or-surface-2/--or-border já flipam sozinhos (contrato em site/CLAUDE.md) — regra
   aqui só pra deixar explícito que o componente foi verificado nos dois temas, não uma exceção. */
[data-bs-theme="dark"] .or-consent { background: var(--or-surface-2); border-color: var(--or-border); }

/* ═══════════════════════════════════════════════════════════════════════════════════════════
   BLOCO 21 — MARQUEE DE FUNDO PADRONIZADO (.or-marquee-fundo) — 05/09/2026
   ═══════════════════════════════════════════════════════════════════════════════════════════
   Faixa de texto passando ao fundo, como TEXTURA (aria-hidden, opacity baixa, sem link dentro —
   elemento focável em aria-hidden reprovaria aria-hidden-focus do axe). Existia só no CTA do
   rodapé (era .or-rd-cta__marquee, visível em 4 das ~30 páginas). O dono pediu que a faixa
   existisse em TODO CTA (print 4: "esta section é o exemplo de como todas essas sessões devem
   se manter") — fatorada em partial compartilhado (_marquee-fundo.php) + este bloco único de
   CSS, usado por .or-rd-cta (rodapé), .or-secao-cta (26 páginas) e pagina-planos.php.

   Mesma mecânica do vendor (.marquee-container/.marquee/@keyframes scroll_x, style.css) —
   reaproveitada, não reimplementada; o reduced-motion de .marquee-container .marquee (~linha
   1020/1058 deste arquivo) já cobre esta faixa de graça, por reusar as MESMAS classes do vendor.

   Tinta por VARIANTE, nunca fixa: dourado (fundo escuro/gradiente de marca) usa branco
   translúcido — a mesma tinta já medida e aprovada no rodapé. soft (fundo claro — páginas
   documentais, ou uma seção comum como a de /planos) usa a cor de TEXTO do próprio tema em
   opacidade baixa; branco a .08 seria invisível sobre fundo claro. */
.or-marquee-fundo {
    position: absolute; inset: 0; z-index: 0;
    padding: 0 !important;
    display: flex; align-items: center;
    pointer-events: none;
    user-select: none;
    opacity: var(--or-mq-opacidade, .08);
}
.or-marquee-fundo .marquee-item {
    gap: 28px;
    /* teto 128px→88px (achado de 28/08/2026, herdado do .or-rd-cta__marquee original): a 128px
       as palavras viravam borrão abstrato e roubavam peso visual da linha de ações. Textura, não
       protagonista — vale nas 3 superfícies que usam este componente. */
    font-size: clamp(2.5rem, 6vw, 5.5rem);
    font-weight: 600;
    letter-spacing: -.03em;
    text-transform: lowercase;
    color: var(--or-mq-tinta, #fff);
    white-space: nowrap;
}
.or-marquee-fundo__sep { opacity: .5; }

/* dourado = default explícito (fundo escuro/gradiente de marca — .or-rd-cta, .or-secao-cta sem
   --soft). Branco fixo: essas superfícies nunca flipam no dark (fundo já é escuro nos dois temas).
   Declaração em linhas separadas (não `{ --a: x; --b: y; }` compacto) — é o formato que
   tests/tema_quanto_test.php reconhece como "definição" de var(--x) (regex ^\s*--token:). */
.or-marquee-fundo--dourado {
    --or-mq-tinta: #fff;
    --or-mq-opacidade: .08;
}

/* soft = fundo claro. --color-primary já flipa sozinho no dark (contrato do design system), mas
   nesse caso o FUNDO também flipa pra escuro — então a tinta clara certa é branco, não a cor de
   texto (que ficaria escura sobre escuro). Opacidade um pouco maior no dark: telas escuras
   comprimem contraste de camadas translúcidas mais que telas claras. */
.or-marquee-fundo--soft {
    --or-mq-tinta: var(--color-primary);
    --or-mq-opacidade: .05;
}
[data-bs-theme="dark"] .or-marquee-fundo--soft {
    --or-mq-tinta: #fff;
    --or-mq-opacidade: .07;
}

/* Hospedeiro da faixa fora de .or-rd-cta/.or-secao-cta: a seção-formulário de /planos não tem
   componente próprio (é a única página cujo fecho é o form, não _secao-cta.php/_rodape.php), e o
   id #contato-planos já é âncora estável no markup — vira o hook de posicionamento aqui. Mesmo
   contrato de `.or-secao-cta .container { position:relative; z-index:1 }`: sem isto, o conteúdo
   pintaria ATRÁS da camada absoluta do marquee (mesmo a .05 de opacidade, o glifo pintaria por
   cima do texto do form em vez de ficar sob ele). */
/* GRADIENTE DE MARCA (05/09/2026) — a seção de fecho de /planos era a única do site que fechava
   em branco; ver o docblock no markup (pagina-planos.php, seção #contato-planos) para o porquê.
   O formulário fica num .or-card--claro por cima, então só título e lead precisam de tinta clara.
   `isolation: isolate` cria contexto de empilhamento próprio: sem ele, o glow/marquee poderia
   competir com o z-index de elementos de outras seções. */
/* `.or-planos-fecho` é a classe SEMÂNTICA do componente; o `#contato-planos` do mesmo elemento é
   uma ÂNCORA de navegação (os botões dos cards de plano apontam para ela) e continua existindo
   só para isso. Estilizar pela classe mantém o padrão do projeto — id vira alvo de link, não
   gancho de CSS. */
.or-planos-fecho {
    position: relative;
    overflow: hidden;
    isolation: isolate;
    background: var(--or-grad-marca);
}
.or-planos-fecho > .container { position: relative; z-index: 1; }
/* !important pelo mesmo motivo já registrado em .or-hero-interno--comercial: a regra
   [data-bs-theme="dark"] :is(h1..h6){color:var(--or-text)!important} venceria por !important
   mesmo com especificidade menor, e o título sairia cinza no tema escuro. O gradiente da marca
   não muda com o tema, então o branco aqui é incondicional. */
.or-planos-fecho .title { color: #fff !important; }
.or-planos-fecho__lead {
    max-width: 620px;
    margin-inline: auto;
    font-size: var(--or-fs-lead);
    line-height: 1.6;
    color: rgba(255, 255, 255, .82);
}

/* --- BUG achado ao vivo em 04/09/2026 (print do dono: botão do CTA final sem rótulo, só a seta).
   O vendor define .quanto-link-btn span { width:16px; height:14px; overflow:hidden } pensado só
   pro <span> do ÍCONE (duas setas absolutamente posicionadas, alternadas no hover — a caixa
   pequena com overflow escondido É a receita do efeito). Os botões de FORM (contato + planos)
   também embrulham o TEXTO num <span id="btn-*-texto"> — necessário pro JS trocar "Enviando..."
   no submit —, e esse span cai na MESMA regra do vendor: o texto fica espremido numa caixa de
   16×14px, invisível (só o ícone aparece). Os outros botões da página escapam porque o texto ali
   é nó de texto solto, não embrulhado em <span>. Fix: uma classe própria SÓ no span do texto,
   resetando a caixa herdada — o span do ícone continua sem ela. --- */
/* Especificidade: .quanto-link-btn span (vendor) é (0,1,1) — mais específica que uma classe só
   (0,1,0). .quanto-link-btn__label sozinha perdia a cascata e o bug persistia mesmo com a regra
   carregada (confirmado ao vivo: cssText presente em document.styleSheets, computed style igual ao
   do vendor). Escopando ao pai (.quanto-link-btn .quanto-link-btn__label, especificidade 0,2,0) a
   regra nova vence sem precisar de !important.
   `color: inherit` é a SEGUNDA metade do mesmo bug, achada só depois de corrigir a primeira: o
   vendor também fixa `color: var(--color-primary)` neste mesmo seletor `.quanto-link-btn span` —
   inofensivo pro span do ÍCONE (vazio, sem texto direto; quem pinta são os .arry1/.arry2 filhos,
   com override próprio pro contexto .btn-pill), mas o span do RÓTULO tem texto direto e herdava a
   cor escura — texto escuro sobre o MESMO fundo escuro do .btn-pill (branco só é aplicado a
   .arry1/.arry2, nunca ao span em si). Confirmado ao vivo: rect correto (172×26, overflow visible),
   texto simplesmente invisível por contraste zero. `inherit` acompanha a variante do botão que
   embrulha o rótulo (branco no .btn-pill, escuro no .btn-pill.btn-light) em vez de fixar uma cor. */
.quanto-link-btn .quanto-link-btn__label { width: auto; height: auto; overflow: visible; display: inline; color: inherit; }

/* --- Coluna de informações de contato (endereço/telefone/e-mail/horário/redes) --- */
.or-contato-info { display: flex; flex-direction: column; gap: 22px; }
.or-contato-info__item a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.or-contato-info__item ul.custom-ul { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 6px; }

/* ── Os rótulos viraram HEADINGS em 03/09/2026 ────────────────────────────────────────────────
   Antes: <p class="…__titulo"> para a coluna e <p> para cada rótulo, estilizados por POSIÇÃO
   (p:first-child = rótulo, p:last-child = valor). Era texto no tamanho de título, com peso de
   título, cumprindo papel de título — e completamente invisível para quem navega por heading.
   Agora são <h2> e <h3> reais.

   Duas consequências que ESTA regra existe para tratar, e nenhuma delas é opcional:

   1. Seletor por posição não sobrevive à mudança. Com o rótulo virando <h3>, o único <p> restante
      passaria a ser first-child E last-child ao mesmo tempo, acumulando as duas regras (peso 600
      do rótulo + opacidade .7 do valor). Por isso a estilização passa a ser por TAG, não por
      ordem — o que também deixa de quebrar quando alguém acrescenta uma linha ao item.

   2. Heading promovido HERDA a escala do vendor. Um <h2> sem font-size declarado nasce com os
      ~60px que o tema calibrou para título de seção — dentro de uma coluna lateral de 4/12. É a
      armadilha documentada no BLOCO 1 (~linha 224), e o tracking em px absolutos vem junto: por
      isso font-size E letter-spacing são declarados aqui, não só o primeiro. */
.or-contato-info__titulo {
    font-size: var(--or-fs-card, 1.25rem);
    line-height: 1.25;
    letter-spacing: -.01em;
    font-weight: 700;
    color: var(--color-primary);
    margin: 0 0 var(--or-esp-2, 8px);
}
.or-contato-info__item h3 {
    font-size: 1rem;
    line-height: 1.35;
    letter-spacing: 0;
    font-weight: 600;
    color: var(--color-primary);
    margin: 0 0 2px;
}
.or-contato-info__item p { color: var(--color-primary); opacity: .7; margin: 0; }

/* Horário por dia da semana (tbl_empresa_horarios). <dl> porque é literalmente par termo→valor;
   a grade de duas colunas alinha os horários entre si, que é o que torna a lista escaneável. */
.or-contato-horarios {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 2px var(--or-esp-4, 16px);
    margin: 0;
}
.or-contato-horarios dt { font-weight: 500; color: var(--color-primary); opacity: .7; }
.or-contato-horarios dd { margin: 0; color: var(--color-primary); opacity: .7; }

/* Nome da área ("Comercial", "SAC") antes do contato dela — pílula discreta, não outro heading:
   são muitos itens curtos e um h4 por linha inflaria o outline sem informar nada a mais. */
.or-contato-setor {
    display: inline-block;
    margin-right: 6px;
    font-weight: 600;
    color: var(--color-primary);
}

/* Título do formulário. Mesmo raciocínio do .or-contato-info__titulo: <h2> novo precisa de escala
   própria — aqui na medida de subtítulo interno, não de título de seção, porque ele divide a
   linha visual com a coluna de canais ao lado e não pode dominá-la. */
.or-contato-form__titulo {
    font-size: var(--or-fs-h3, 1.5rem);
    line-height: 1.2;
    letter-spacing: -.01em;
    margin: 0 0 var(--or-esp-5, 24px);
}

/* Mapa (EMP_MAPS_URL). Proporção fixa em vez de altura fixa: em 360px uma altura de 450px come a
   tela inteira, e no desktop uma de 300px vira uma faixa sem contexto. O iframe do Google Maps
   não traz proporção intrínseca, então ela é declarada aqui. */
/* ⚠️ margin-inline:auto é LOAD-BEARING (09/09/2026) — sem ele o mapa fica encostado à esquerda
   mesmo dentro de uma coluna centralizada, e essa era a metade do desalinhamento que o dono
   apontou em "Onde estamos" (a outra metade era o text-center no lugar errado — ver contato.php).

   A causa não é óbvia à leitura: `aspect-ratio: 16/9` combinado com `max-height: 520px` limita a
   LARGURA a 924px. Medido em 1440px: a coluna dá 1171px e o mapa ocupa 924 — sobram 247px, e como
   um bloco sem margem automática encosta no início do fluxo, os 247 iam todos para a direita.
   O título centralizado terminava em 1303 e o mapa em 1056, a 247px de distância um do outro.
   Alargar a coluna não resolve; centralizar a row não resolve. Só a margem automática resolve. */
.or-contato-mapa {
    position: relative;
    margin-inline: auto;
    aspect-ratio: 16 / 9;
    max-height: 520px;
    border-radius: var(--or-radius-m);
    overflow: hidden;
    border: 1px solid var(--or-border, rgba(0, 0, 0, .08));
}
.or-contato-mapa iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
@media (max-width: 575.98px) {
    .or-contato-mapa { aspect-ratio: 4 / 3; }
}

/* --- Protocolo de teste da /presenca-em-ia (redesenhado 03/09/2026 — achado real): o markup
   anterior reaproveitava .or-inclusos-lista--coluna, que NUNCA teve efeito — é declarada ANTES de
   .or-inclusos-lista (linha ~2864) no arquivo, então a regra base (grid auto-fit de 2+ colunas,
   pensada pra itens curtos tipo "SSL grátis") sempre vencia por ordem de cascata, mesma
   especificidade. Cada passo (frase longa + link inline) ficava espremido numa coluna de ~300px,
   quebrando de forma ilegível. Componente PRÓPRIO (só esta página usa) — <ol> numerado, 1 coluna
   sempre, sem depender de nenhuma outra classe pra vencer a cascata. */
.or-protocolo-lista { list-style: none; margin: 0 0 28px; padding: 0; max-width: 640px; display: flex; flex-direction: column; gap: 16px; }
.or-protocolo-lista li { display: flex; align-items: flex-start; gap: 14px; }
.or-protocolo-lista__num {
    flex-shrink: 0;
    display: flex; align-items: center; justify-content: center;
    width: 28px; height: 28px;
    border-radius: 50%;
    background: var(--marca-primaria);
    color: #fff;
    font-size: .8rem;
    font-weight: 700;
}
[data-bs-theme="dark"] .or-protocolo-lista__num { background: var(--or-brand-accent); color: var(--or-ink-deep, #05132b); }
.or-protocolo-lista__texto { padding-top: 3px; font-size: .98rem; color: var(--color-primary); }
/* A nota de fecho acompanha a MESMA medida de leitura da lista (640px). Com o card alinhado à
   esquerda (03/09/2026), sem isto ela esticaria pela largura inteira do card (~900px em col-lg-9)
   — ~110 caracteres por linha, bem acima do confortável, e desalinhada do bloco acima. */
.or-protocolo-nota { max-width: 640px; margin-inline: auto; }

/* --- /planos: dois rótulos que eram style="" inline no PHP. O nome do add-on e a linha de nomes
       comerciais das estatísticas (que substituiu o "T1 ⊂ T2 ⊂ T3" técnico) agora são texto vindo
       do banco — o peso e o tamanho não podem depender de alguém lembrar do inline ao editar. --- */
.or-planos-addons__nome { font-weight: 600; }
/* O nome do avulso virou link para /servicos/<slug> em 04/09/2026 (o item passou a vir de
   tbl_servicos, que tem a página de detalhe). Herda a cor do texto em repouso — um bloco de seis
   nomes todos na cor de link viraria uma parede azul dentro de uma seção que é, antes de tudo,
   uma tabela de preços. */
.or-planos-addons__nome a { color: inherit; text-decoration: none; }
.or-planos-addons__nome a:hover,
.or-planos-addons__nome a:focus-visible { color: var(--texto-link); text-decoration: underline; }
.or-stat-nomes { font-size: clamp(1.15rem, 0.9rem + 1vw, 1.75rem); line-height: 1.25; }

/* --- .or-planos-table REMOVIDA em 04/09/2026: a /planos passou a usar .or-comparativo, o mesmo
   componente da /presenca-em-ia. O motivo é a regra de mobile — aquela resolvia telas pequenas com
   `overflow-x: auto` PURO, sem coluna fixa, e numa tabela de quatro colunas isso faz o leitor
   perder a referência da linha assim que arrasta: ele vê "2 por mês" sem saber se é artigo,
   publicação ou e-mail. .or-comparativo EMPILHA cada linha como um cartão e injeta o nome da
   coluna via `data-label`, que é o regime correto aqui.
   O grid de add-ons (.or-planos-addons, logo abaixo) CONTINUA — só a fonte dos dados mudou, de
   tbl_textos para tbl_servicos.

   COLUNAS EXPLÍCITAS por breakpoint (04/09/2026), não mais auto-fit: com 6 itens, minmax(260px,1fr)
   media pra exatamente 5 colunas de 262px em 1440px de largura (medido ao vivo) — 5 numa linha, o
   6º sozinho na de baixo. Print do dono pediu "4 por linha, padronizado" — mesmo espírito de
   .or-base-lista (BLOCO 2), que já usa colunas fixas por breakpoint nesta mesma página em vez de
   auto-fit. .or-planos-addons__price REMOVIDA junto do <p> que ela estilizava — preço saiu da
   vitrine (pedido do dono: "não vamos colocar preço, são blocos que apenas serão consultados"),
   segue existindo em tbl_servicos e na página de detalhe do serviço. --- */
.or-planos-addons { display: grid; grid-template-columns: 1fr; gap: var(--or-esp-5); }
@media (min-width: 576px) { .or-planos-addons { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 992px) { .or-planos-addons { grid-template-columns: repeat(4, 1fr); } }

/* ── REMODELAÇÃO DO CARD (05/09/2026) ─────────────────────────────────────────────────────────
   Era `background: var(--color-2)` — o MESMO token do fundo da seção (#avulsos é .bg-color-2).
   Card cinza sobre fundo cinza: não existia card, só texto solto em 4 colunas, que é exatamente
   o que o print 6 do dono mostra. Superfície branca + borda dão o contraste que faltava; no
   escuro, --or-surface (um degrau acima de --or-surface-2, o fundo da seção lá) faz o mesmo
   trabalho — mesma doutrina já usada por .quanto-blog-content.bg-color-white contra a seção
   branca do blog.

   `position: relative` ancora o .stretched-link do título; `height: 100%` iguala a altura dos
   cards da mesma linha (subtítulos de serviço têm comprimentos bem diferentes). */
.or-planos-addons__item {
    position: relative;
    display: flex;
    flex-direction: column;
    height: 100%;
    padding: var(--or-esp-6) var(--or-esp-5);
    border-radius: var(--or-radius-m);
    background: var(--color-white);
    border: 1px solid var(--or-border, rgba(0, 0, 0, .08));
    transition: border-color .2s ease, box-shadow .2s ease;
}
.or-planos-addons__item:hover,
.or-planos-addons__item:focus-within {
    border-color: var(--marca-primaria);
    box-shadow: var(--or-shadow-1);
}
[data-bs-theme="dark"] .or-planos-addons__item {
    background: var(--or-surface);
    border-color: var(--or-border);
}

/* Ícone: mesmo tamanho e tratamento do .or-servico-card__ico da grade de /servicos — os dois
   listam o MESMO tipo de coisa (serviço), e divergir aqui criaria dois vocabulários visuais
   para uma entidade só. */
.or-planos-addons__ico {
    display: inline-flex;
    margin-bottom: var(--or-esp-4);
    color: var(--marca-primaria);
    font-size: 26px;
}
[data-bs-theme="dark"] .or-planos-addons__ico { color: var(--or-brand-accent); }
.or-planos-addons__ico svg { width: 26px; height: 26px; }

/* <h3> real (era <p> com peso de título). font-size explícito: um h3 "cru" herda os 80px do
   vendor — a armadilha já registrada no BLOCO 1.5 para todo heading promovido. */
.or-planos-addons__nome {
    font-size: 1.0625rem;
    line-height: 1.35;
    letter-spacing: -.01em;
    font-weight: 600;
    color: var(--color-primary);
    margin: 0 0 var(--or-esp-3);
}
.or-planos-addons__nome a { color: inherit; text-decoration: none; }
.or-planos-addons__item:hover .or-planos-addons__nome a { color: var(--texto-link, var(--marca-primaria)); }

/* margin-top:auto encosta o texto no rodapé do card quando o título ocupa 1 linha e o vizinho
   ocupa 2 — sem isso os subtítulos "flutuam" em alturas diferentes na mesma linha da grade. */
.or-planos-addons__texto {
    margin: 0;
    font-size: var(--or-fs-small);
    line-height: 1.6;
    color: var(--or-text-muted);
}

@media (prefers-reduced-motion: reduce) { .or-planos-addons__item { transition: none !important; } }
html[data-or-rm="reduce"] .or-planos-addons__item { transition: none !important; }
/* Sub-bloco↔sub-bloco dentro da mesma seção (grade de avulsos → nota de fecho) — antes era um
   mt-4 inline (24px) direto no <p>; print do dono: "não tem o devido espaçamento". Medido ao vivo:
   o gap real hoje é só 24px entre o fim da grade e a nota, bem abaixo do que os outros blocos da
   página usam pra essa mesma transição. */
.or-avulsos-nota { margin-top: var(--or-esp-7); }
/* Segunda nota (multi-idioma, D6) colada na primeira: as duas são RESSALVAS da mesma grade, e
   --or-esp-7 (48px) é o token de "sub-bloco↔sub-bloco" — separa a primeira nota da grade de cards,
   que é uma troca real de assunto. Entre as duas notas não há troca de assunto nenhuma, e 48px lê
   como se fossem blocos independentes, cada uma órfã da outra (print do dono, 09/09/2026). Cai
   para --or-esp-5, que é o PISO documentado entre blocos irmãos — mais perto que isso violaria a
   regra de espaçamento do CLAUDE.md. Regime B: quem traz a margem é o bloco de baixo. */
.or-avulsos-nota + .or-avulsos-nota { margin-top: var(--or-esp-5); }
/* Segundo achado ao vivo (mesmo print, olhar de novo depois do primeiro fix): os 72px de
   padding-bottom do próprio #avulsos (bg-color-2) são a ÚNICA fonte de respiro antes de
   "Antes de assinar" — #contratacao usa section-padding-bottom (só a margem DELE mesmo é zero no
   topo). Um respiro que vem inteiro de UM lado só lê como insuficiente numa transição de cor
   (cinza→branco): o olho espera folga dos dois lados do corte, não só de um. Escopado à página (o
   componente #contratacao é só daqui) — sem tocar a classe global do vendor. */
.or-pg--planos #contratacao { padding-top: var(--or-esp-7); }

/* --- Funfacts (evolução F4, generalizado na F6 — /planos E /sobre) — o h2 cru do vendor é
   70-100px (style.css:2851-2867), desenhado pra numeral curto ("10K+"); "T1 ⊂ T2 ⊂ T3" e "R$ 1.199"
   nessa escala estourariam a coluna. Reescala pro token de seção; --color-1 vira --or-border no
   dark (a divisória some no escuro sem isto — --color-1 nunca é flipado, ver nota da F9 em
   site_dark_test). Nasceu .or-funfacts-planos (só /planos); renomeado .or-funfacts quando /sobre
   passou a usar o mesmo componente — era o MESMO fix, evitando 2 regras quase-idênticas. --- */
/* --or-fs-secao-compacta (não --or-fs-secao): coluna estreita, conteúdo tipo "T1 ⊂ T2 ⊂ T3" —
   não deve herdar o teto novo de 64px do D3 (estouraria a coluna mais cedo). */
/* ANCORADO EM .counter-item, NÃO no seletor h2 (03/09/2026). O odômetro contém APENAS o número —
   o rótulo real vive no <p class="funfact-info"> ao lado —, então marcá-lo como heading inventava
   títulos que não titulam nada: a /sobre chegava a emitir 4 <h2> vazios de significado, quebrando
   a hierarquia da página inteira. A /sobre passou a <p class="counter-item"> (mesmo precedente já
   adotado no hero da home, .or-home-hero__num) e /planos segue com <h2 class="counter-item"> —
   este seletor cobre os dois. Por isso peso, margem e line-height agora são EXPLÍCITOS: eram
   herdados do h2 do vendor (600 / 0 / 110%), e um <p> herdaria os do corpo — as duas páginas
   renderizariam o mesmo número em tamanhos diferentes. */
.or-funfacts .quanto-funfact-box .counter-item {
    margin-bottom: 0;
    font-size: var(--or-fs-secao-compacta);
    font-weight: 600;
    line-height: 1.1;
    letter-spacing: -0.02em;
    color: var(--color-primary);
}
.or-funfacts .quanto-funfact-box { border-left-color: var(--color-1); }
[data-bs-theme="dark"] .or-funfacts .quanto-funfact-box { border-left-color: var(--or-border); }

/* Os blocos .or-economia-* ("A conta de contratar avulso", #economia) e .or-inclusos-*
   ("Tudo que o Presença já inclui") foram REMOVIDOS em 03/09/2026 junto das duas seções de
   pagina-planos.php que os usavam — decisão do dono. CSS sem markup não quebra nada, mas mente
   para quem lê depois: sugere um componente vivo que nenhuma tela renderiza. A receita do chip
   (tinta de marca a 12% sobre fundo) sobrevive em .or-prova-card__chip, que a documenta. */

/* O destaque da coluna recomendada mudou de nome junto com a tabela: virou
   .or-comparativo__recomendada, definido no BLOCO 18 ao final deste arquivo. */

/* O bloco de FAQ de /planos (acordeão + Schema::setFaqs correspondente) foi REMOVIDO em 04/09/2026,
   decisão do dono — junto com ele saem .or-planos-faq (regras acima) e .or-planos-faq__grid (BLOCO
   8.1, mais abaixo). CSS sem markup não quebra nada, mas mente pra quem lê depois: sugere um
   componente vivo que nenhuma tela renderiza. Mesmo precedente de .or-economia-* e .or-inclusos-*
   (nota logo acima). ⚠️ Nunca escreva "-*" seguido de "/" num comentário — a sequência fecha o
   comentário ali mesmo (achado ao vivo pelo guard C do bin/cliente/auditar-espacamento.php, nesta
   própria frase, na primeira tentativa de escrevê-la). */

/* ================================================================
   PRELOADER — marca embutida inline (evolução "identidade visual", 26/08/2026). Substitui o
   spinner genérico do vendor (anel branco/laranja em torno do <img> raster) quando o cliente tem
   símbolo em SVG (EMP_LOGO_SIMBOLO — or_preloader_simbolo_inline(), _helpers.php). Fundo reusa
   var(--or-grad-marca) — o MESMO gradiente do hero — então o preloader deixa de ser uma tela preta
   genérica e vira a primeira metade do reveal do hero: some sem costura visual.

   Sem gate de prefers-reduced-motion / data-or-rm de propósito, mesma decisão já registrada acima
   pro .spinner do vendor (BLOCO de reduced-motion, ~linha 797): feedback de carregamento é
   movimento ESSENCIAL — WCAG 2.3.3 trata de movimento NÃO essencial, não deste caso. Sem
   strobe/flash (só rotação e opacidade suaves em ciclo > 1s), então também não esbarra no limiar
   de 2.3.1 mesmo fora do gate. O dead-man switch (_head.php, inline) continua intocado: mira
   .preloader (classe-base, sempre presente), não .or-preloader.
   ================================================================ */
.or-preloader { background: var(--or-grad-marca); }
.or-preloader__mark {
    position: relative;
    width: 132px;
    height: 132px;
    color: #fff; /* traço dos brackets (currentColor via or_preloader_simbolo_inline()) */
}
.or-preloader__mark svg { position: relative; z-index: 1; display: block; width: 100%; height: 100%; }
.or-preloader__mark::before {
    content: '';
    position: absolute;
    inset: -55%;
    border-radius: 50%;
    background: radial-gradient(circle, color-mix(in srgb, var(--or-dourado) 40%, transparent) 0%, transparent 72%);
    filter: blur(18px);
    animation: or-preloader-glow 2.4s ease-in-out infinite;
}
/* transform-box:view-box ancora a rotação/pulso no CENTRO REAL do símbolo (48,48 no viewBox
   96x96) — sem isso, o navegador gira em torno do bounding-box do próprio <path> do arco (uma
   forma assimétrica), produzindo uma órbita torta em vez de girar no eixo do círculo. */
.or-preloader__arc {
    transform-box: view-box;
    transform-origin: 48px 48px;
    animation: or-preloader-spin 1.15s linear infinite;
}
.or-preloader__dot {
    transform-box: view-box;
    transform-origin: 48px 48px;
    animation: or-preloader-pulse 1.15s ease-in-out infinite;
}
@keyframes or-preloader-spin { to { transform: rotate(360deg); } }
@keyframes or-preloader-pulse {
    0%, 100% { transform: scale(1); opacity: 1; }
    50%      { transform: scale(1.4); opacity: .7; }
}
@keyframes or-preloader-glow {
    0%, 100% { opacity: .45; }
    50%      { opacity: 1; }
}
@media (max-width: 575.98px) {
    .or-preloader__mark { width: 104px; height: 104px; }
}

/* ================================================================
   BLOCO 4.5 — SEÇÃO PRESENÇA EM IA (#geo) · simulador de perguntas (28/08/2026)
   ================================================================

   #geo era uma <div class="row"> pendurada no fim de <section id="dor"> (fusão F5.1, 26/08/2026).
   Vira SEÇÃO PRÓPRIA com fundo escuro: a página passa a alternar claro (#dor) → escuro (#geo) →
   claro (#lgpd) → cinza (#servicos), e o painel de vidro .or-hero-resposta só funciona sobre
   escuro. O <hr class="or-divisor"> que separava dor/geo saiu junto — com fundos diferentes, a
   troca de fundo É o divisor. Efeito colateral bem-vindo: some o traço dourado central do
   .or-divisor, ou seja, esta evolução deixa a página com MENOS dourado, não mais.

   DOURADO — ZERO ponto novo (lista fechada de 6, BLOCO 0.5):
     · .or-eyebrow dourada aqui = o MESMO ponto nº6 (eyebrow sobre fundo escuro), já autorizado em
       .or-home-hero .or-eyebrow e .or-hero-interno--comercial: --marca-primaria sobre fundo de
       marca é invisível, não é escolha estética.
     · caret = .or-hero-caret reusado (ponto nº1), zero regra nova.
     · chip selecionado é BRANCO, não dourado — o vocabulário de "primário sobre escuro" desta base
       já é a pílula branca (.or-home-hero__cta).
   ================================================================ */
.or-ia {
    position: relative;
    background: var(--or-ink-deep);
}
/* Profundidade sem markup extra — ::before, e não uma <div class="__glow"> como no hero: lá o glow
   carrega data-speed (parallax do ScrollSmoother), aqui não há o que pendurar. */
.or-ia::before {
    content: '';
    position: absolute;
    inset: 0;
    background: radial-gradient(72% 90% at 12% 0%, rgba(var(--marca-primaria-rgb, 11, 61, 145), .5) 0%, transparent 68%);
    pointer-events: none;
}
.or-ia > .container { position: relative; z-index: 1; }

/* .text-color-white é PROIBIDA nesta seção, pelo mesmo motivo do hero: o bloco dark reescreve
   .text-color-white → var(--or-text) !important, e esta superfície NÃO flipa — a classe "branca"
   do vendor deixaria de ser branca no escuro. Branco literal, escopado. */
.or-ia .or-eyebrow { color: var(--or-dourado); }
.or-ia .or-lead    { color: rgba(255, 255, 255, .78); opacity: 1; } /* .or-lead nasce --color-primary + opacity .75 */

.or-ia__titulo { color: #fff; }

/* margin-top SAIU daqui (28/08/2026, CLAUDE.md §Padrão de Espaçamento): quem separava a row do
   título da row da instrução era este filho (36px, abaixo do piso --or-esp-5) — agora é a PRÓPRIA
   row (row-padding-top, 60px, home.php), Regime B corretamente aplicado no nível certo. */
.or-ia__instrucao {
    margin: 0 0 16px;
    font-size: var(--or-fs-small);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: rgba(255, 255, 255, .62);
}

/* --- .or-ia__chips/.or-ia__chip — SEGUNDA VIDA do CSS órfão de .or-superficies__entrega, escrito
   em 26/08/2026 para uma 2ª linha de pílulas-link que foi removida do markup no MESMO dia (o CSS
   ficou no arquivo, sem nenhum usuário, até aqui). Borda, raio pill, wash de hover e o rail com
   scroll-snap no mobile são o MESMO código, MOVIDO — não copiado.
   O que mudou no transporte:
     a) TOKENS — lá as cores vinham de --or-sup-tinta/--or-sup-borda, custom properties declaradas
        DENTRO do bloco .or-superficies; fora dali elas não resolvem. Aqui são literais (mesma
        escolha de .or-hero-resposta, que também vive sobre escuro fixo).
     b) ELEMENTO — lá eram <a> (navegação), aqui são <button> (troca de estado NA página): daí o
        reset de font-family, que um <a> não precisa. <button> herda a fonte do UA, não do body —
        sem isto o chip sai em Arial no meio da Instrument Sans.
     c) ESTADO — pílula-link nunca teve "selecionada". [aria-expanded="true"] é o atributo que o
        PRÓPRIO botão carrega (28/08/2026 — trocou de tabs/[aria-selected] pra disclosure, ver
        or-tema-motion.js): o CSS lê o estado REAL do widget, nunca uma classe paralela que possa
        dessincronizar. --- */
.or-ia__chips {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px 12px;
    margin: 0;
    padding: 0;
    list-style: none;
}
.or-ia__chip {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 10px 20px;
    border: 1px solid rgba(255, 255, 255, .22);
    border-radius: var(--or-radius-pill);
    background: transparent;
    font-family: inherit;              /* <button> não herda do body sozinho */
    font-size: var(--or-fs-small);
    font-weight: 600;
    color: #fff;
    white-space: nowrap;
    cursor: pointer;
    transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}
.or-ia__chip:hover { background: rgba(255, 255, 255, .08); border-color: rgba(255, 255, 255, .38); }
.or-ia__chip:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.or-ia__chip[aria-expanded="true"] {
    background: #fff;
    border-color: #fff;
    color: var(--or-ink-deep);
}

/* [hidden] explícito (28/08/2026) — mesmo reforço defensivo de or-a11y.css:181 (.or-a11y-panel
   [hidden]{display:none}): o UA já faz isto por padrão, mas alguma regra de especificidade maior
   em cascata (aqui ou em código futuro) poderia sobrescrever o `display` sem tocar em `[hidden]`.
   Explícito não custa nada e documenta a intenção. */
.or-ia__convite[hidden],
.or-ia__resposta[hidden] { display: none; }

/* --- Palco. min-height absorve a diferença de altura entre respostas de tamanhos diferentes ⇒ o
   conteúdo abaixo não "pula" ao trocar de aba (mesmo remédio de .or-servicos-showcase__palco).
   284px = o MAIOR painel MEDIDO ao vivo em 1440px (28/08/2026): as 4 respostas ocupam 257px quando
   a frase cabe em 1 linha e 283px quando quebra em 2 — o teto arredondado pra cima zera o shift
   residual de 26px que um valor menor deixaria passar na troca de aba. Não é chute: com o
   min-height em 268 o palco ainda encolhia de 283→268 ao ir de uma resposta de 2 linhas para uma
   de 1. Solto abaixo de 992px: ali a mesma frase ocupa de 3 a 7 linhas conforme o comprimento, e
   um min-height fixo criaria buraco em vez de evitá-lo. --- */
.or-ia__palco { min-height: 284px; }
@media (max-width: 991.98px) { .or-ia__palco { min-height: 0; } }

.or-hero-resposta--consulta { padding: 30px 28px; }

/* --- Digitação sem layout shift e sem leitura parcial (o par __real/__eco, ver home.php).
   .or-ia__real é o texto VERDADEIRO: sempre no DOM, sempre na árvore de acessibilidade, e é ele
   que DEFINE a altura do painel — durante a animação ele só perde opacity (não visibility, não
   display: os dois o tirariam da árvore de acessibilidade E do fluxo, que é exatamente o que
   causaria o pulo). .or-ia__eco é aria-hidden, absoluto por cima, mesma largura/fonte ⇒ quebra de
   linha idêntica. Sem JS ou com reduced-motion a classe .is-digitando nunca é aplicada: o eco fica
   display:none e o texto real fica visível desde o servidor.
   Cada um tem seu .or-hero-caret: o do __real marca o repouso, o do __eco acompanha a digitação.
   Só um dos dois é visível por vez, sem nenhuma cirurgia de DOM. --- */
.or-ia__texto { position: relative; }
.or-ia__eco   { display: none; position: absolute; inset: 0; }
.or-ia__real  { display: block; }
.or-ia__texto.is-digitando .or-ia__eco  { display: block; }
.or-ia__texto.is-digitando .or-ia__real { opacity: 0; }

.or-ia__nota {
    margin: 0 0 24px;
    padding-left: 18px;
    border-left: 2px solid rgba(255, 255, 255, .22);
    font-size: var(--or-fs-small);
    line-height: 1.65;
    color: rgba(255, 255, 255, .66);
}
.or-ia__nota strong { color: #fff; font-weight: 700; }
.or-ia__acoes { display: flex; flex-wrap: wrap; align-items: center; gap: 14px 24px; }
/* Link secundário sobre fundo escuro — o .quanto-link-btn do vendor nasce --color-primary (texto
   quase-preto), invisível aqui. */
.or-ia .or-link--claro { color: rgba(255, 255, 255, .82); }
.or-ia .or-link--claro:hover { color: #fff; }

@media only screen and (max-width: 767.98px) {
    /* Rail com scroll-snap em vez de empilhar 4 pílulas e alongar a página — regra herdada
       verbatim do .or-superficies__entrega órfão (26/08/2026). */
    .or-ia__chips {
        flex-wrap: nowrap;
        width: 100%;
        overflow-x: auto;
        scroll-snap-type: x proximity;
        padding-bottom: 6px;
        -webkit-overflow-scrolling: touch;
    }
    .or-ia__chip { scroll-snap-align: start; }
    .or-hero-resposta--consulta { padding: 24px 20px; }
}
/* REMOVIDA em 29/08/2026 (era @media max-width:991.98px { .or-ia__linha-resposta .or-ia__nota {
   margin-top:var(--or-esp-5) } }, e junto saiu a classe marcadora .or-ia__linha-resposta da row
   em home.php — ficou sem função). Existia porque a row do palco/nota do #geo tinha trocado
   g-4 g-xl-5 por gx-4 gx-xl-5 — e gx- mata o gutter VERTICAL do Bootstrap, que é quem dá o
   respiro entre palco e nota quando as colunas empilham (<992px). A troca para gx- partia de uma
   premissa errada (ver o comentário da mesma row em home.php): medido ao vivo, g-4 g-xl-5 NÃO
   briga com row-padding-top — a margem negativa da row é cancelada pela margem positiva das
   colunas. Com g- de volta, o respiro do empilhamento mobile volta de graça (23px nativos,
   medido) e esta regra bespoke fica sem função. */

/* --- Reduced motion. PAR OBRIGATÓRIO: a media query do sistema + o atributo data-or-rm (escolha
   EXPLÍCITA no painel de acessibilidade — ORA11y.motionReduzido(), or-a11y.js).
   ⚠️ O valor real do atributo é "reduce", NÃO "reduzir". Os ~20 seletores html[data-or-rm="reduce"]
   mais acima neste arquivo NUNCA casam — bug pré-existente, fora do escopo desta mudança e
   deliberadamente NÃO replicado aqui. .or-hero-caret e .fade já estão registrados nos blocos
   existentes; aqui só o chip. --- */
@media (prefers-reduced-motion: reduce) {
    .or-ia__chip { transition: none !important; }
}
html[data-or-rm="reduce"] .or-ia__chip { transition: none !important; }

/* Nota de localização: o PAR OBRIGATÓRIO de reduced motion pros reveals do tema
   (.fade-anim/.move-anim/.word-anim) NÃO mora aqui — está inline em
   site/_template/pages/_head.php, junto do dead-man switch do preloader. Ali, não neste .css
   externo, de propósito: é uma rede de SEGURANÇA (garante que conteúdo nunca fique invisível pra
   sempre), e uma rede de segurança não pode depender de um asset que pode falhar em carregar. Ver
   o bloco 5 de site/_template/js/or-tema-motion.js para o resto do mecanismo (Camada C, JS). */

/* ================================================================
   BLOCO 4.6 — SEÇÃO LGPD (#lgpd) · "os 5 direitos + o fluxo" (28/08/2026)
   ================================================================

   FUNDO CLARO de propósito: a seção de IA logo acima é escura e #servicos logo abaixo é
   bg-color-2 (cinza). Sem classe de fundo = branco do body ⇒ escuro → branco → cinza, três
   superfícies distintas em sequência. bg-color-2 aqui colaria visualmente em #servicos.

   ZERO JS: nada é interativo além de dois <a>; os chips são renderizados no servidor e os 5
   direitos precisam estar TODOS visíveis ao mesmo tempo (o número 5 é a mensagem). Consequência
   direta: _scripts.php fica intocado (assert 10 do guard) e não há animação nova a registrar nos
   dois gatilhos de reduced-motion. ⚠️ Se algum dia entrar animação aqui, registrar em @media
   (prefers-reduced-motion: reduce) E em html[data-or-rm="reduce"] — NUNCA em "reduzir".
   ================================================================ */

/* --- Chips de ESTADO (padrão do $orProvas: mostram estado, nunca afirmação; somem sem dado real).
   O tint com color-mix acompanha a cor de marca do tenant sem uma segunda variável; no escuro é
   derivado de --or-brand-accent (a MESMA marca já clareada 35% pela Camada 2 do core), que compõe
   visível sobre a superfície escura. --- */
.or-lgpd-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    list-style: none;
    margin: 24px 0 0;
    padding: 0;
}
.or-lgpd-chip {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 7px 15px;
    border-radius: var(--or-radius-pill);
    background: color-mix(in srgb, var(--marca-primaria) 12%, transparent);
    color: var(--marca-primaria);
    font-size: var(--or-fs-small);
    font-weight: 600;
    line-height: 1.3;
}
[data-bs-theme="dark"] .or-lgpd-chip {
    color: var(--or-brand-accent);
    background: color-mix(in srgb, var(--or-brand-accent) 16%, transparent);
}

/* --- Sub-títulos <h4> da seção. font-size E letter-spacing explícitos são OBRIGATÓRIOS, não
   cosmética: o vendor prende letter-spacing à TAG em px (h4 −1,5px calibrado para 60px). Qualquer
   h4 reescalado para ~20-32px herda esse valor absoluto e fica com −5% a −8% do corpo — letras
   colidindo. É o achado D2 já documentado em .or-prova-card h4 e em .or-selos .awards-title. --- */
.or-lgpd-subtitulo,
.or-lgpd-fluxo__titulo,
.or-lgpd-bastidor__titulo {
    font-size: var(--or-fs-h3);
    line-height: 1.25;
    letter-spacing: -.015em;
    color: var(--color-primary);
    margin: 0 0 22px;
    text-wrap: balance;   /* mesma razão do .or-pg h3.title (BLOCO 1.5): mata a órfã em título longo */
}
/* --- Bastidor: título centralizado sobre o par de telas (pedido do dono, 27/08/2026 — "mais
   padronizado"), mesmo padrão de header centrado já usado em .quanto__header.text-center noutras
   seções. Regra própria (não entra no combinado acima) porque .or-lgpd-subtitulo/__fluxo__titulo
   continuam alinhados à esquerda, coerentes com a prosa/lista que os segue. --- */
.or-lgpd-bastidor__titulo { text-align: center; }

/* --- Os 5 direitos. Colunas EXPLÍCITAS por breakpoint, não auto-fit: são exatamente 5 itens, e
   repeat(auto-fit, minmax(Npx,1fr)) produz uma linha órfã de 1 card em quase toda largura
   intermediária (5 nunca é múltiplo de 2, 3 ou 4). A rampa abaixo escolhe divisores que deixam a
   última linha com 2 ou 3 cards, nunca com 1 solitário. --- */
.or-direitos-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 16px;
    list-style: none;
    margin: 0;
    padding: 0;
}
@media (min-width: 576px)  { .or-direitos-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 992px)  { .or-direitos-grid { grid-template-columns: repeat(3, 1fr); gap: 20px; } }
@media (min-width: 1200px) { .or-direitos-grid { grid-template-columns: repeat(5, 1fr); } }

.or-direito {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 24px;   /* < 28px de .or-card: 5 colunas estreitas não sobrevivem ao padding padrão */
}
.or-direito__ico { color: var(--marca-primaria); font-size: 1.5rem; line-height: 1; }
[data-bs-theme="dark"] .or-direito__ico { color: var(--or-brand-accent); }
/* h5: o vendor dá 28px + letter-spacing próprio. Aqui o nome do direito é um RÓTULO, não um título
   de card — --or-fs-lead (16,8→20px) é a escala certa. */
.or-direito__nome {
    margin: 0;
    font-size: var(--or-fs-lead);
    line-height: 1.2;
    letter-spacing: -.01em;
    font-weight: 700;
    color: var(--color-primary);
}
/* A fala do titular — peso 600 sem itálico: as aspas curvas no markup já marcam a citação, e
   itálico numa fonte variável a 16px reduz legibilidade sem ganho semântico. */
.or-direito__pedido {
    margin: 0;
    font-size: 1rem;
    line-height: 1.5;
    font-weight: 600;
    color: var(--color-primary);
}
/* opacity (não uma cor cinza fixa) pelo mesmo motivo de .or-prova-card p: acompanha o flip de
   --color-primary no dark sem precisar de override próprio. */
.or-direito__acao {
    margin: 0;
    font-size: var(--or-fs-small);
    line-height: 1.65;
    color: var(--color-primary);
    opacity: .72;
}

/* --- Modificador NUMERADO de .or-diferenciais-list. counter CSS, não <ol>: a lista já é um <ul>
   estilizado com hairline entre itens em 3 lugares do tema, e trocar a tag mudaria o componente
   para todos. O offset do ::before acompanha o padding-top:18px que .or-diferenciais-list aplica
   em todo li exceto o primeiro (:first-child tem padding-top:0). --- */
.or-diferenciais-list--passos { counter-reset: or-passo; }
.or-diferenciais-list--passos li {
    counter-increment: or-passo;
    position: relative;
    padding-left: 46px;
}
.or-diferenciais-list--passos li::before {
    content: counter(or-passo);
    position: absolute;
    left: 0;
    top: 18px;
    width: 30px;
    height: 30px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: color-mix(in srgb, var(--marca-primaria) 12%, transparent);
    color: var(--marca-primaria);
    font-size: .82rem;
    font-weight: 700;
    line-height: 1;
}
.or-diferenciais-list--passos li:first-child::before { top: 0; }
[data-bs-theme="dark"] .or-diferenciais-list--passos li::before {
    color: var(--or-brand-accent);
    background: color-mix(in srgb, var(--or-brand-accent) 16%, transparent);
}

/* --- Par de CTAs (pílula + link). Mesmo molde de .or-home-hero__acoes: flex com wrap e gap
   assimétrico (linha menor que coluna) para que, ao quebrar no mobile, os dois não colem. --- */
.or-lgpd-acoes {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 14px 28px;
    margin-top: 30px;
}

/* --- Bastidor (RoPA + retenção). Grid próprio em vez de row/col do Bootstrap porque o par precisa
   de gap vertical GENEROSO no empilhamento (device + legenda + parágrafo é um bloco alto; o g-4 do
   Bootstrap deixaria os dois quase encostados no mobile).
   max-width nos devices: hierarquia visual (o executor é a prova principal) E é o que torna o
   sizes="(min-width: 992px) 520px" do markup EXATO — sem o teto, a coluna larga pediria ~780px e o
   navegador baixaria um derivativo maior sem necessidade. --- */
.or-lgpd-bastidor {
    display: grid;
    grid-template-columns: 1fr;
    gap: 44px;
}
@media (min-width: 992px) {
    .or-lgpd-bastidor { grid-template-columns: repeat(2, 1fr); gap: 40px; }
}
/* margin-inline:auto (não text-align no item — .or-device é bloco, não inline) centra o executor
   dentro da coluna quando ela é mais larga que o teto de 520px. Legenda e parágrafo abaixo TAMBÉM
   centralizados (pedido do dono, 27/08/2026 — "o texto das imagens também precisa estar
   centralizado nesta proposta"): a leitura corrida de 2-3 linhas centralizada não é o padrão do
   resto do site (prosa longa segue à esquerda em toda outra seção), mas aqui é deliberado — o par
   texto+imagem forma um bloco visual único e centrado, coerente com o título acima. Escopado a
   `.or-lgpd-bastidor` — NÃO vira regra geral de `.or-device__legenda` (usada em #painel, onde
   continua à esquerda). */
.or-lgpd-bastidor .or-device { max-width: 520px; margin-inline: auto; }
.or-lgpd-bastidor__item { min-width: 0; }   /* trava o overflow do grid item (min-width:auto é o default) */
.or-lgpd-bastidor .or-device__legenda { text-align: center; }
.or-lgpd-bastidor__texto {
    margin: 14px auto 0;
    font-size: 1rem;
    line-height: 1.65;
    color: var(--color-primary);
    opacity: .75;
    max-width: 52ch;   /* mesma medida de linha do BLOCO 5 para prosa sem coluna própria */
    text-align: center;
}

/* --- Nota de tier. Reusa .or-card (fundo/raio/borda + o pin de dark já escrito lá) e só reescreve
   o padding — a declaração vem DEPOIS de .or-card no arquivo, mesma especificidade (0,1,0), então
   a ordem resolve o empate. font-size e cor NÃO são declarados aqui de propósito: vêm de
   .or-pg .t-small / .or-pg .t-muted (BLOCO 1.5, especificidade 0,2,0 — venceriam de qualquer
   forma). O <strong> volta ao texto cheio: é o nome do plano, o dado da frase.
   .or-prova-nota (achado ao vivo, 31/08/2026) reusa a MESMA regra: era um <p> nu na seção #prova,
   sem fundo/borda próprios — o row-padding-top acima dela media os mesmos 48px desta nota, mas sem
   a caixa do .or-card a separação não lia como intencional. --- */
/* Largura de 10/12 colunas + centralizado (pedido do dono, 27/08/2026 — a barra ia de ponta a
   ponta do container, larga e baixa demais; "10 colunas preenchidas" é a mesma linguagem de
   Bootstrap grid que o resto do tema usa). 83.3333% = 10/12 — width (não max-width): a caixa deve
   ENCOLHER pro tamanho-alvo mesmo em telas largas, não só limitar um crescimento que não existiria
   de qualquer forma dentro do col-12. */
.or-lgpd-nota,
.or-prova-nota {
    width: 83.3333%;
    margin: 38px auto 0;
    padding: 18px 22px;
    line-height: 1.7;
    text-align: center;
}
.or-lgpd-nota strong,
.or-prova-nota strong { color: var(--color-primary); }
@media (max-width: 767.98px) {
    .or-lgpd-nota,
    .or-prova-nota { width: 100%; }   /* 10/12 de uma tela de celular sobra espaço vazio nas bordas sem ganho nenhum */
}
[data-bs-theme="dark"] .or-lgpd-nota strong,
[data-bs-theme="dark"] .or-prova-nota strong { color: var(--or-text); }

/* ================================================================
   BLOCO 5 — MEDIDA DE LINHA E ALINHAMENTO DE PROSA (27/08/2026)
   ================================================================

   Duas mudanças pedidas pelo dono que se cruzam na mesma propriedade: (a) a coluna de #dor/#geo na
   home sai de col-xl-7 pra col-lg-8 (home.php) e (b) o corpo de texto longo do site passa a ser
   justificado. Moram aqui, no fim do arquivo, de propósito — o conjunto é TRANSVERSAL (encosta no
   BLOCO 1.5/sistema tipográfico, no BLOCO 2/.or-doc-body e no BLOCO 3/.or-lead) e nenhum bloco
   existente é dono dele. Ser o último também é LOAD-BEARING: .or-lead--largo e .or-lead têm a
   MESMA especificidade (0,1,0) — quem vence é a ordem de origem, e é só aqui que ela está
   garantida sem !important.

   PRINCÍPIO que decide os dois números abaixo: trava a medida onde a leitura é SUSTENTADA
   (política, artigo, página CMS — dezenas de linhas, onde o olho perde o retorno de linha) e
   solta onde o bloco tem 2-3 linhas (deck editorial). Não é inconsistência, é o mesmo critério
   aplicado a dois regimes de leitura diferentes.

   ─── 1. MEDIDA DE LINHA (#dor / #geo) ──────────────────────────────────────────────────────────
   ARMADILHA achada ao planejar: alargar a <div class="col-*"> NÃO alarga o subtítulo. .or-lead
   trava em max-width:640px e a trava vence a coluna — o pedido ("o subtítulo também é col-8")
   morreria em silêncio. Daí um MODIFICADOR, não a edição do .or-lead base: são 11 usos em 5
   páginas (/planos, /sobre, /presenca-em-ia) e só 2 são os de #dor/#geo — mexer na base alargaria
   9 parágrafos que ninguém pediu pra alargar.

   max-width:none (e não um teto tipo 72ch) é escolha consciente, com o custo medido: col-8 num
   .container.custom-container de 1604px dá ~1029px de linha, e --or-fs-lead no teto (20px) põe
   ~100 caracteres por linha — acima da faixa confortável de 65-75. O que salva o caso é o TAMANHO
   do texto: os dois parágrafos têm 237 e 161 caracteres, ou seja 3 e 2 linhas nessa largura. Se a
   QA achar rio de espaço em branco, a correção é de uma linha: trocar `none` por `72ch`. --- */
.or-lead--largo { max-width: none; }

/* ─── 2. JUSTIFICAÇÃO — SÓ PROSA LONGA ──────────────────────────────────────────────────────────
   Alvo deliberadamente curto: .or-doc-body (as 18 superfícies de editor rico, \OneRank\Content::
   render()) e .or-lead (parágrafo de apoio editorial). NUNCA justify em CONTAINER, sempre no
   elemento de texto — isso não é estilo, é seguro: text-align é HERDADO, e um justify no wrapper
   escorreria pra .or-hero-interno__stat (text-align:right), .or-empty (center), .or-consent
   (left) e .or-planos-table th/td (left). No elemento, zero herança, zero necessidade de blindar
   essas quatro regras.

   NÃO ENTRAM (varredura de todo <p> das pages, 27/08/2026): .process-box p (cards de 2-4 linhas de
   #dor), .or-device__legenda / .or-servicos-showcase__legenda (legendas), .or-inclusos-lista
   (checklist de /planos), .or-rd-* (rodapé — fica FORA do .or-pg, o <main> fecha antes do
   <footer>), .or-hero-interno__subtitle, e todo <p> nu que sobrou (rótulos de /contato
   "Endereço"/"Telefone", endereço de /filiais, "Empresas que confiam na OneRank"): justificar
   rótulo de 1-2 linhas só produz UMA linha esticada. O <p> nu de prosa REAL (pagina.php,
   acessibilidade.php) já está dentro de .or-doc-body — não precisa de seletor novo, e um `.or-pg p`
   genérico justificaria "Endereço".

   ⚠️ hyphens:auto FOI removido daqui em 03/09/2026 — decisão revertida, registro do porquê ficou
   pra não reabrir por engano. A justificativa original era: em pt-BR sem hifenização
   ("posicionamento", "conformidade", "ranqueamento") o justify abre rios de espaço em branco.
   Verdade em tese, mas o efeito colateral MEDIDO foi pior que o problema que evitava — o mesmo
   `hyphens:auto` partiu "pergunta" em "per-/gunta" num h1 (achado ao vivo, print do dono,
   .or-hero-interno__title logo abaixo neste arquivo) e o pedido que se seguiu foi categórico:
   palavra que não cabe vai INTEIRA pra linha de baixo, nunca hifenizada — título OU texto. Manter
   hyphens:auto só na prosa justificada e tirar só do título criaria a mesma regressão aqui na
   primeira palavra composta longa de uma resposta de FAQ ou de política. text-align:justify
   PERMANECE (não é o que foi pedido) — o risco aceito agora é rio de espaço ocasional em palavra
   muito longa dentro de coluna estreita, não hífen no meio da palavra. hyphenate-limit-chars saiu
   junto: sem hyphens:auto ele não faz nada, e deixá-lo é isca pra alguém religar por engano. */
.or-pg .or-doc-body p,
.or-pg .or-doc-body li,
.or-pg .or-lead {
    text-align: justify;
    text-justify: inter-word;
    -webkit-hyphens: none;
    hyphens: none;
}

/* Teto de medida em prosa SUSTENTADA — achado de 27/08/2026, não pedido originalmente: .or-doc-body
   nunca teve max-width. Em col-xl-8 num container de 1604px dá ~1029px (~123 caracteres a 16,8px),
   e galeria.php põe o bloco DIRETO no .container.custom-container, sem coluna nenhuma: ~1580px,
   ~150 caracteres. Era um problema de leitura já vivo — o justify só o torna visível. Escopado ao
   FILHO DIRETO de texto e não ao container: capar o .or-doc-body caparia junto .or-doc-imagem
   (width:100%) e as tabelas do editor rico, que devem seguir usando a coluna inteira. */
.or-pg .or-doc-body > :is(p, ul, ol, blockquote, h2, h3, h4, h5, h6) { max-width: var(--or-medida-prosa, 72ch); }

/* EXCEÇÃO das páginas DOCUMENTAIS de duas colunas (09/09/2026, pedido do dono: "o texto das
   páginas legais deve cumprir corretamente a largura de 100% da col-8"). A marca `.or-doc-col` é
   posta explicitamente em politica.php e acessibilidade.php — não uso `.or-doc-body` solto porque
   blog/portfólio/evento/galeria também o usam, e ali o teto de medida continua valendo (galeria.php
   é o caso extremo que motivou a regra: bloco direto no container, ~150 caracteres por linha).

   ⚠️ RESSALVA REGISTRADA, não silenciada: a col-lg-8 dá ~1030px, o que a 16,8px são ~123 caracteres
   por linha — acima dos ~80 que a WCAG 1.4.8 recomenda para prosa sustentada, e foi exatamente esse
   o defeito que a regra acima passou a corrigir em 27/08/2026. A decisão de ocupar a coluna inteira
   é do dono e está tomada; fica anotado aqui o que se troca por ela, para quem ler depois não achar
   que o teto de medida foi esquecido. O `hyphens:none` + `justify` do bloco acima seguem valendo. */
.or-pg .or-doc-col .or-doc-body > :is(p, ul, ol, blockquote, h2, h3, h4, h5, h6) { max-width: none; }

/* Exceções DENTRO do alvo — cada uma é um caso real do markup, não precaução:
   .or-doc-body.or-doc-anexos li → lista de LINKS de 1 linha ("Documentos", "Outras perguntas"),
                                   não prosa.
   .or-doc-body.t-small          → aviso curto em corpo .875rem — menos caracteres por linha é
                                   justamente onde o justify fica pior.
   .or-doc-body p.t-small        → legenda de imagem, mesma família das legendas.
   .text_invert/.word-anim/.move-anim → ACHADO (main.js): esses elementos passam por SplitText
                                   type:"lines", que fatia o parágrafo num <div> POR LINHA. Cada
                                   linha vira "última linha" e o justify some — pior, ele muda a
                                   conta de quebra ANTES do split e some depois, o que dá reflow
                                   visível no load. sobre.php tem exatamente esses casos (<p
                                   class="text_invert"> dentro de .or-doc-body).
   .or-lead.text-center          → home.php (bloco de /planos, "Presença, Destaque e Autoridade").
                                   Aqui o text-align abaixo é DECORATIVO: as utilitárias
                                   .text-center/.text-lg-start do Bootstrap usam !important e vencem
                                   de qualquer jeito. O que é LOAD-BEARING nesta linha é o
                                   hyphens:manual — o Bootstrap não controla hifenização, e hífen em
                                   parágrafo centralizado fica feio. */
.or-pg .or-doc-body.or-doc-anexos li,
.or-pg .or-doc-body.t-small p,
.or-pg .or-doc-body.t-small li,
.or-pg .or-doc-body p.t-small,
.or-pg .or-doc-body p.text_invert,
.or-pg .or-doc-body p.word-anim,
.or-pg .or-doc-body p.move-anim,
.or-pg .or-lead.text-center {
    text-align: start;
    -webkit-hyphens: manual;
    hyphens: manual;
}

/* Cabeçalho CENTRALIZADO (#prova, #para-quem-e) — achado ao vivo de 29/08/2026 (print do dono): o
   <h3 class="title"> centraliza por HERANÇA do .quanto__header.text-center, mas o <p class="or-lead">
   é alvo DIRETO da regra de justify acima (declaração no próprio elemento sempre vence herança) —
   lê como "título centralizado, subtítulo caindo pra esquerda". Duas causas somadas, não uma: (1)
   justify em vez de center, (2) .or-lead tem max-width:640px (linha ~1716) SEM margin-inline:auto,
   então mesmo com o texto centralizado a CAIXA ficava encostada na borda esquerda da coluna (medido:
   12px à esquerda × 782px à direita numa col-12 de 1434px). Diferente da exceção .or-lead.text-center
   acima (que é #planos, onde o lead vive FORA do header e usa a utilitária do Bootstrap) — aqui o
   lead vive DENTRO do header centralizado, então o seletor é escopado a essa relação, não à classe
   solta no <p>.

   SEGUNDA FORMA DO MESMO DEFEITO (achado ao vivo 09/09/2026, print do dono no #escada da /planos):
   nem toda seção centralizada usa .quanto__header. A /planos tem duas que centralizam pela COLUNA
   — `<div class="row justify-content-center"><div class="col-lg-7 text-center">` com o <h2> e o <p
   class="or-lead"> soltos dentro dela (#escada, #upgrade). O h2 centraliza por herança; o lead cai
   nas MESMAS duas causas de sempre (alvo direto do justify + max-width:640px sem margin-inline),
   e lê exatamente igual: "título centralizado, subtítulo torto". O seletor do .quanto__header não
   alcança essa forma porque o wrapper simplesmente não existe aqui.

   Por que generalizar em vez de acrescentar um .quanto__header ao markup: envolver o conteúdo num
   wrapper novo mexe na estrutura de duas seções vivas por uma questão de alinhamento de texto —
   custo desproporcional, e o .quanto__header carrega outras regras que essas seções não pedem. O
   segundo seletor descreve a RELAÇÃO ("lead solto dentro de coluna centralizada"), que é o que de
   fato caracteriza o defeito, e não uma classe específica.

   Alcance medido antes de escrever: `col-* text-center` existe em 2 pontos do tema inteiro, ambos
   na /planos (linhas 288 e 439). O #upgrade só tem título hoje — entra no seletor de graça, e fica
   protegido se algum dia ganhar um lead. */
.or-pg .quanto__header.text-center .or-lead,
.or-pg .row > [class*="col-"].text-center > .or-lead {
    margin-inline: auto;
    text-align: center;
    -webkit-hyphens: manual;
    hyphens: manual;
}

/* ─── 3. OPT-OUT DE ACESSIBILIDADE (WCAG 1.4.12 × 1.4.8) ────────────────────────────────────────
   WCAG 1.4.8 (Presentation, AAA) desaconselha texto justificado. Este site DECLARA conformidade
   A/AA — o justify não quebra a promessa feita ao visitante. O que ele quebra na prática é a
   COMBINAÇÃO com o controle "espaçamento de texto" do painel de acessibilidade (WCAG 1.4.12):
   or-a11y.css aplica word-spacing:.16em + letter-spacing:.12em !important em p/li quando
   html[data-or-ts="1"], e espaço entre palavras já inflado + espaço esticado pelo justify = rio de
   verdade, exatamente para quem ligou o controle porque TEM dificuldade de leitura. Quem liga
   data-or-ts volta pro alinhamento à esquerda.

   Escrito AQUI e não no or-a11y.css de propósito: o or-a11y.css é core da frota (site/assets/), o
   justify é decisão deste fork — o opt-out tem que morar do lado da decisão, senão vira regra órfã
   em N clientes que não justificam nada. Especificidade (0,3,2) vence tanto a regra que liga
   (0,2,1) quanto as exceções (0,3,1), então não depende de ordem de origem — o que importa, já que
   o custom.css é carregado ANTES do or-a11y.css (header.php).

   Os outros flags do painel NÃO pedem opt-out: data-or-fs aumenta o corpo dentro de uma coluna de
   largura FIXA em px, ou seja MELHORA a medida de linha; data-or-hc e data-or-lk só mexem em cor;
   data-or-rm e data-or-cu não tocam texto. Não existe flag de dislexia neste painel. --- */
html[data-or-ts="1"] .or-pg :is(.or-doc-body p, .or-doc-body li, .or-lead) {
    text-align: start;
    -webkit-hyphens: manual;
    hyphens: manual;
}

/* ================================================================
   SUBMENU — seta do dropdown sem fonte de ícone (auditoria A-02, 28/08/2026)

   O vendor desenha a seta do submenu com um GLIFO do Remixicon (style.css:1085 `content:"\ea4d"`
   + `font-family:"remixicon"`, e style.css:1171 `content:"\ea6d"`). Como o remixicon.css saiu do
   _head.php (173 KB de woff2 para 1 uso no site inteiro), esses dois `content` virariam retângulo
   de "glifo ausente" — mas SÓ se o operador cadastrar um item de menu com filhos: o menu de hoje
   é plano, então nada quebra agora. Esta regra é a blindagem para quando isso mudar.

   Chevron desenhado em CSS puro (borda rotacionada), sem fonte, sem SVG, sem requisição. Zera o
   `content` do vendor e reconstrói a forma — herda `currentColor`, então acompanha tema e hover.
   ================================================================ */
.main-menu ul.sub-menu li.menu-item-has-children > a::after,
.main-menu ul.sub-menu li.menu-item-has-children a.no-border::after {
    content: "";
    font-family: inherit;
    width: 7px;
    height: 7px;
    border-right: 2px solid currentColor;
    border-bottom: 2px solid currentColor;
    transform: rotate(-45deg);
    margin-left: 6px;
    top: -1px;
}

/* ================================================================
   /busca — página de busca do site (auditoria A-10, 28/08/2026)

   Criada porque o SearchAction do JSON-LD precisava de um destino REAL: declarar a busca sem ter
   a página seria dado estruturado mentindo, num site que existe para demonstrar o contrário.
   Reusa o que o tema já tem (.form-control do vendor, .quanto-link-btn, tokens de espaçamento) —
   o CSS abaixo é só o arranjo próprio da página.
   ================================================================ */
/* max-width no form: o campo de busca dentro de uma col-lg-8 esticaria por ~900px em telas
   largas — caixa de texto muito mais larga que qualquer termo que se digite nela. */
.or-busca-form { max-width: 640px; }
.or-busca-form__linha {
    display: flex;
    gap: var(--or-esp-3);
    align-items: stretch;
    flex-wrap: wrap;
    margin-top: var(--or-esp-2);
}
.or-busca-form__linha .form-control { flex: 1 1 260px; min-width: 0; }

/* Regime B (§Padrão de Espaçamento): o bloco de baixo traz a própria margem. O :first-child zera
   porque o primeiro grupo já é separado do formulário pelo row-padding-top da row. */
.or-busca-grupo { margin-top: var(--or-esp-7); font-size: 1.6rem; }
/* O 1º grupo ("Serviços") abre a lista de resultados e não precisa do respiro que separa um grupo
   do anterior — a margem é do bloco de baixo (Regime B do padrão de espaçamento). */
.or-busca-grupo:first-of-type { margin-top: 0; }

.or-busca-lista { margin: 0; padding: 0; list-style: none; }
.or-busca-lista li {
    padding: var(--or-esp-4) 0;
    border-bottom: 1px solid var(--color-1);
}
.or-busca-lista li:last-child { border-bottom: none; }
.or-busca-lista a {
    font-size: var(--or-fs-lead);
    font-weight: 600;
    color: var(--color-primary);
    letter-spacing: -.01em;
}
.or-busca-lista a:hover { color: var(--marca-primaria); }
.or-busca-lista p { margin: var(--or-esp-2) 0 0; }

[data-bs-theme="dark"] .or-busca-lista li { border-bottom-color: var(--or-border); }
[data-bs-theme="dark"] .or-busca-lista a { color: var(--or-text); }

/* ================================================================
   RODAPÉ v2 — busca, pílula social e base institucional (28/08/2026)

   Contexto das 3 mudanças estruturais:
   · A coluna "Links" saiu (duplicava o header e servia um href="#" em 30 páginas).
   · A zona da marca tinha 184px mortos — ganhou BUSCA (ação real) em vez de enfeite.
   · Prova e barra legal fundiram numa base institucional única (a prova estava no ponto de
     menor atenção da página, espremida entre o form de newsletter e o copyright).

   Todas as cores saem dos tokens --or-rd-* (literais rgba). NUNCA var(--color-white) ou
   var(--color-primary) aqui: os dois FLIPAM no dark e o rodapé é escuro permanente nos dois
   temas — guard automático em tests/tema_quanto_test.php.
   ================================================================ */

/* ── Busca (zona da marca) ─────────────────────────────────────── */
.or-rd-busca { margin-top: var(--or-esp-6); max-width: 420px; }
.or-rd-busca__label {
    display: block;
    font-size: .8125rem;
    font-weight: 600;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--or-rd-tinta);
    margin-bottom: var(--or-esp-3);
}
.or-rd-busca__linha {
    display: flex;
    align-items: stretch;
    gap: var(--or-esp-2);
}
.or-rd-busca__campo {
    flex: 1 1 auto;
    min-width: 0;
    height: 46px;
    padding: 0 16px;
    border-radius: var(--or-radius-m);
    border: 1px solid var(--or-rd-borda);
    background: rgba(0, 0, 0, .22);
    color: var(--or-rd-tinta);
    font-size: .9375rem;
}
.or-rd-busca__campo::placeholder { color: var(--or-rd-tinta-3); }
.or-rd-busca__campo:focus {
    outline: none;
    border-color: var(--or-dourado);
    box-shadow: 0 0 0 3px rgba(232, 181, 61, .22);
}
.or-rd-busca__btn {
    flex: 0 0 auto;
    width: 46px; height: 46px;
    display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid var(--or-rd-borda);
    border-radius: var(--or-radius-m);
    background: var(--or-rd-camada);
    color: var(--or-rd-tinta);
    cursor: pointer;
    transition: background-color .15s ease, border-color .15s ease;
}
/* Achado ao vivo (29/08/2026): era rgba(255,255,255, var(--or-rd-camada)) — aninhava uma cor
   (--or-rd-camada JÁ é rgba(...)) dentro do alfa de outra rgba(). CSS inválido: o navegador
   descarta a declaração inteira e o botão nunca ganhava o fundo, em repouso OU no hover. */
.or-rd-busca__btn:hover { background: var(--or-rd-camada-2); border-color: var(--or-rd-tinta-3); }
.or-rd-busca__btn:focus-visible { outline: 2px solid var(--or-dourado); outline-offset: 3px; }
.or-rd-busca__btn svg { width: 18px; height: 18px; }

/* Atalho para /faq logo abaixo da busca (01/09/2026) — mesma intenção ("achar uma resposta"), por
   isso mora na zona da busca e não na coluna de documentos legais. Herda .or-rd-link no <a>. */
.or-rd-busca__atalho {
    margin: var(--or-esp-3) 0 0;
    max-width: 420px;
    font-size: .875rem;
    color: var(--or-rd-tinta-3);
}

/* ── Rede social solitária vira pílula rotulada ────────────────── */
.or-rd-social--rotulado .or-rd-social__link {
    width: auto;
    height: 40px;
    padding: 0 18px;
    border-radius: var(--or-radius-pill);
    gap: 10px;
}
.or-rd-social__nome { font-size: .875rem; font-weight: 500; }

/* ── Base institucional (prova + barra legal) ──────────────────── */
.or-rd-base { border-top: 1px solid var(--or-rd-borda); }

/* A prova vira faixa INLINE: o título deixa de ser <h3> empilhado e passa a eyebrow à esquerda
   das pílulas. Economiza ~40px, que é o que paga os 2 chips a mais. */
.or-rd-prova {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px 24px;
    margin: 0;
    padding-block: var(--or-esp-5);
}
.or-rd-prova__titulo {
    flex: 0 0 auto;
    margin: 0;
    font-size: .75rem;
    font-weight: 600;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--or-rd-tinta-3);
}
/* Um dos chips é <button> (revogar consentimento age NESTA página). Reset de chrome nativo do
   <button> — SEM font-size aqui (achado ao vivo, 31/08/2026): declarar `font-size: inherit` nesta
   2ª classe (mesma especificidade de .or-rd-prova__item, mas depois no arquivo → vence por ordem)
   subia até o font-size do <body> (20px no style.css do vendor) em vez do .875rem do chip base,
   deixando este botão ~43% maior que os outros 4 pills da lista. Sem a linha, o .875rem de
   .or-rd-prova__item (que o <button> também carrega no markup) vale normalmente. */
.or-rd-prova__item--acao {
    background: none;
    font-family: inherit;
    cursor: pointer;
    text-align: left;
}
.or-rd-prova__item:focus-visible { outline: 2px solid var(--or-dourado); outline-offset: 3px; }

/* ── Barra legal + assinatura da plataforma ────────────────────── */
.or-rd-bottom { border-top: 1px solid var(--or-rd-borda); align-items: flex-start; }
.or-rd-bottom__legal { display: flex; flex-direction: column; gap: 4px; }
/* `.or-rd-bottom__doc` REMOVIDA em 09/09/2026 junto com o markup: a linha da razão social saiu do
   rodapé por decisão do dono (só o CNPJ fica, concatenado à linha de copyright). Regra sem markup
   correspondente é CSS morto — e o guard `tema_quanto_test` cobra o inverso (classe usada sem
   regra), então deixá-la não quebraria nada e por isso mesmo ninguém a removeria depois. O
   `flex-direction: column` + `gap` do `__legal` acima ficam: sustentam a linha única igualmente, e
   voltam a servir sem edição se um segundo parágrafo retornar ao bloco. */

/* Selo/pílula (29/08/2026, referência: print do dono) — era texto+logo soltos, sem contorno,
   quase invisíveis contra o fundo do rodapé. Vira CHIP com a MESMA linguagem visual dos outros
   pílulas desta base (.or-rd-prova__item, .or-rd-social__link): contorno em repouso, preenchimento
   só no hover — consistência interna pesa mais que reproduzir literalmente um fundo preenchido. */
.or-rd-assinatura {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    padding: 9px 18px;
    border: 1px solid var(--or-rd-borda);
    border-radius: var(--or-radius-pill);
    color: var(--or-rd-tinta-3);
    transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}
.or-rd-assinatura:hover { background: var(--or-rd-camada-2); border-color: var(--or-rd-tinta-2); color: var(--or-rd-tinta); }
.or-rd-assinatura:focus-visible { outline: 2px solid var(--or-dourado); outline-offset: 3px; border-radius: var(--or-radius-pill); }
.or-rd-assinatura__rotulo { font-size: .8125rem; }
.or-rd-assinatura__logo {
    height: 18px; width: auto; display: block;
    opacity: .72;
    transition: opacity .15s ease;
}
.or-rd-assinatura:hover .or-rd-assinatura__logo { opacity: 1; }

/* ── Chip de classificação do card de blog — home E /blog (28/08/2026; compartilhado 08/09/2026) ──
   Substitui a data. A seção #blog da home virou portfólio: 3 posts fixos, um por plano, e o chip diz
   qual capacidade cada texto exemplifica. Tint da marca no claro; --or-brand-accent no escuro (a
   marca já clareada pelo core), mesmo padrão de .or-lgpd-chips.
   Desde 08/09/2026 a LISTAGEM usa o mesmo componente, na mesma posição (abaixo do título), com o
   mesmo conteúdo quando o artigo está no mapa de planos e a categoria como fallback — as duas
   grades pararam de classificar o mesmo card de dois jeitos.
   Contraste medido: #0B3D91 sobre o tint 8% (#EBF0F6) = 8,75:1. */
.or-blog-plano {
    display: inline-flex;
    align-items: center;
    gap: var(--or-esp-2);
    margin-top: var(--or-esp-3);
    padding: 6px 14px;
    border-radius: var(--or-radius-pill);
    background: color-mix(in srgb, var(--marca-primaria) 8%, transparent);
    border: 1px solid color-mix(in srgb, var(--marca-primaria) 22%, transparent);
    color: var(--marca-primaria);
    font-size: var(--or-fs-small);
    font-weight: 600;
    line-height: 1.2;
}
.or-blog-plano .or-icon { width: 1.05em; height: 1.05em; flex: 0 0 auto; }
[data-bs-theme="dark"] .or-blog-plano {
    background: color-mix(in srgb, var(--or-brand-accent) 12%, transparent);
    border-color: color-mix(in srgb, var(--or-brand-accent) 30%, transparent);
    color: var(--or-brand-accent);
}

/* ── Faixa de CTA v2 — escada de atrito (28/08/2026) ────────────────────────────────
   Só o dourado do .or-rd-cta__btn segue como ponto de destaque (lista fechada do BLOCO 0.5); o 2º
   CTA usa .or-link--claro (#fff literal, imune ao flip do tema). */
.or-rd-cta__acoes {
    display: flex; flex-wrap: wrap;
    align-items: center; justify-content: center;
    gap: 16px 28px;
    margin-bottom: var(--or-esp-6);
}
.or-rd-cta__canais {
    display: flex; flex-wrap: wrap;
    align-items: center; justify-content: center;
    gap: 8px 20px;
    margin: 0 0 var(--or-esp-3);
    font-size: .95rem;
    color: var(--or-rd-tinta-2);
}
.or-rd-cta__canais-rotulo { color: var(--or-rd-tinta-3); }
.or-rd-cta__canal {
    display: inline-flex; align-items: center; gap: 8px;
    color: var(--or-rd-tinta-2);
    border-bottom: 1px solid var(--or-rd-borda);
    transition: color .15s ease, border-color .15s ease;
}
.or-rd-cta__canal:hover { color: var(--or-rd-tinta); border-color: var(--or-rd-tinta); }
.or-rd-cta__canal:focus-visible { outline: 2px solid var(--or-dourado); outline-offset: 3px; border-radius: 2px; }
.or-rd-cta__canal .or-icon { width: 16px; height: 16px; opacity: .7; flex: 0 0 auto; }
.or-rd-cta__garantia { margin: 0; font-size: .8125rem; color: var(--or-rd-tinta-3); }

/* ═══════════════════════════════════════════════════════════════════════════════════════════════
   BLOCO 6 — ÍNDICE DE DOCUMENTO LEGAL (.or-doc-indice) — 01/09/2026
   ═══════════════════════════════════════════════════════════════════════════════════════════════

   Nasce com as políticas ganhando conteúdo real: o corpo saiu de 80 caracteres de placeholder para
   ~3.500-4.800, e documento legal não é lido do início ao fim — é consultado por trecho ("por
   quanto tempo vocês guardam?"). Sem índice, a resposta exige rolar o documento inteiro.

   Os `id` das seções são injetados pelo TEMPLATE (politica.php), não escritos no editor:
   Content::sanitize remove `id` (GLOBAL_ATTRS = class, title). Índice e âncoras saem da mesma
   passada de DOM, então não têm como divergir.

   SEM COR NOVA: reusa os tokens já mapeados no BLOCO 1 (--color-primary = texto, --color-1 =
   borda sutil, --or-dourado = acento). Como --color-primary deriva de --texto-principal, o bloco
   acompanha o modo escuro pela Camada 2 do or-dark.css sem regra própria. */

.or-doc-indice { margin-bottom: var(--or-esp-6); }
.or-doc-indice + .or-doc-indice { margin-top: var(--or-esp-6); }

.or-doc-indice__titulo {
    margin: 0 0 var(--or-esp-3);
    font-size: .8125rem;
    font-weight: 600;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--color-primary);
    opacity: .6;
}

.or-doc-indice ol,
.or-doc-indice ul { list-style: none; margin: 0; padding-left: 0; counter-reset: or-doc-idx; }

.or-doc-indice li { margin: 0; border-bottom: 1px solid var(--color-1); }
.or-doc-indice li:last-child { border-bottom: none; }

.or-doc-indice a {
    display: block;
    padding: 10px 0;
    font-size: .9375rem;
    line-height: 1.45;
    color: var(--color-primary);
    text-decoration: none;
    opacity: .82;
    transition: opacity .2s ease, color .2s ease, padding-left .2s ease;
}

.or-doc-indice a:hover,
.or-doc-indice a:focus-visible { opacity: 1; color: var(--texto-link, var(--marca-primaria)); padding-left: 6px; }
.or-doc-indice a:focus-visible { outline: 2px solid var(--or-dourado); outline-offset: 3px; border-radius: 2px; }

/* Numeração só no índice da própria página (ol) — a lista de documentos irmãos (ul) é navegação
   lateral, não sumário, e numerá-la sugeriria uma ordem de leitura que não existe. */
.or-doc-indice ol a::before {
    counter-increment: or-doc-idx;
    content: counter(or-doc-idx) ". ";
    color: var(--or-dourado);
    font-weight: 600;
}

/* O heading que recebe o id fica sob o header sticky quando alcançado por âncora. */
.or-doc-body h2[id] { scroll-margin-top: 96px; }

/* ═══════════════════════════════════════════════════════════════════════════════════════════════
   BLOCO 7 — HUB /faq (.or-faq-hub, .or-faq-indice, .or-faq-permalink, .or-faq-atalho) — 01/09/2026,
   REFORMULADO 08/09/2026
   ═══════════════════════════════════════════════════════════════════════════════════════════════

   Print do dono: "/faq completamente fora da padronização esperada". Três defeitos medidos:
     1. `.quanto-faq-accordion` (vendor puro) era o acordeão MAIS CRU do site — sem superfície, sem
        raio, sem padding lateral, chevron ::after do Bootstrap esticado na altura do botão. O site
        já tinha um componente moderno pronto, `.or-faq-svc` (usado em /servicos/<slug>), cujo
        próprio docblock (_servico-faq.php:19-21) diz ter sido feito PENSANDO em corrigir /faq
        também — nunca foi aplicado aqui. Passa a ser reusado, zero CSS de acordeão novo.
     2. Acordeão em `col-12` de um `.custom-container` de até 1604px: uma pergunta de 40 caracteres
        ficava sozinha numa linha absurdamente larga, chevron perdido na borda oposta — o mesmo
        defeito já corrigido em /sobre (sobre.php:362-367, "não faltava padding, sobrava largura").
     3. Título de grupo em `--or-fs-secao` (até 64px, herdado da classe `.title`), repetido 4× ao
        longo da página, competindo com o H1 do hero.

   NOVO ESQUELETO — mesma anatomia de /politica e /acessibilidade (índice lateral fixo + coluna de
   leitura), decisão do dono: "26 perguntas em 4 grupos" pede ORIENTAÇÃO, não uma parede de texto.
   .or-faq-indice é MODIFICADOR de .or-doc-indice (markup: class="or-doc-indice or-faq-indice") —
   herda toda a base (título uppercase, item com borda, hover/focus dourado) e adiciona só o que é
   exclusivo daqui: vira chips horizontais no mobile (abaixo). */

.or-faq-hub__titulo {
    display: flex;
    align-items: center;
    gap: var(--or-esp-3);
    margin-bottom: var(--or-esp-3);
    /* Escala própria, não mais a classe `.title` (que aplicava --or-fs-secao, até 64px, pensada
       pra título de SEÇÃO — repetida 4× na mesma página competia com o H1 do hero). --or-fs-h3
       ("subtítulos internos") é a escala certa pra cabeçalho de bloco dentro de uma coluna de
       conteúdo — mesmo papel que o índice ao lado já sinaliza no wrapper "Nesta página". */
    font-size: var(--or-fs-h3);
    line-height: 1.2;
    letter-spacing: -.01em;
    color: var(--color-primary);
}
.or-faq-hub__titulo .or-icon { width: 22px; height: 22px; flex: 0 0 auto; }

/* Contagem de respostas do grupo, encostada na direita da box (09/09/2026). `margin-left:auto`
   dentro do flex do <h2> é o que a empurra — não `float`, não `position:absolute`: o título já é
   flex, então basta consumir o espaço livre, e o alinhamento sobrevive a nome de grupo de
   qualquer tamanho. `flex-shrink:0` para que o número nunca quebre em duas linhas quando o nome
   do grupo for longo; quem cede espaço é o nome, que tem para onde crescer.
   Escala e peso próprios (não herda o --or-fs-h3 do título) porque é DADO DE APOIO: se tiver o
   mesmo peso visual do nome do grupo, disputa a leitura com ele em vez de ajudar. */
.or-faq-hub__contagem {
    margin-left: auto;
    flex: 0 0 auto;
    font-size: .8125rem;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--color-primary);
    opacity: .55;
}
[data-bs-theme="dark"] .or-faq-hub__contagem { color: var(--or-text-muted, rgba(255, 255, 255, .7)); opacity: .8; }
@media (max-width: 575.98px) {
    /* No celular o nome do grupo já ocupa a linha inteira — a contagem desce em vez de espremer o
       título. `margin-left:0` desfaz o empurrão; a ordem do flex-wrap faz o resto. */
    .or-faq-hub__titulo { flex-wrap: wrap; }
    .or-faq-hub__contagem { margin-left: 0; }
}

/* Um bloco por grupo, empilhados na MESMA coluna (não mais uma `.row` por grupo) — Regime B do
   CLAUDE.md §Padrão de Espaçamento: sem gap de pai aqui (a coluna é fluxo normal), então quem
   separa é a margem do BLOCO DE BAIXO. `id` aqui, não no `<h2>`: o índice ancora no CONTAINER do
   grupo (título + lead + acordeão inteiro), não só na linha do título — clicar no índice traz o
   bloco todo pro topo da viewport, título incluído. */
.or-faq-grupo-bloco { scroll-margin-top: 96px; }
.or-faq-grupo-bloco + .or-faq-grupo-bloco { margin-top: var(--or-esp-8); }

/* ── Índice do hub — chips horizontais no mobile ────────────────────────────────────────────────
   Acima de 991.98px, .or-faq-indice é 100% .or-doc-indice (sticky, lista vertical com borda —
   igual /política). Abaixo, viraria uma lista de 4 links empilhados ANTES do conteúdo, empurrando
   as perguntas pra baixo da dobra — decisão do dono: "chips horizontais". */
@media (max-width: 991.98px) {
    .or-faq-indice {
        display: flex;
        gap: var(--or-esp-3);
        overflow-x: auto;
        overflow-y: hidden;
        padding-bottom: var(--or-esp-2);
        margin-bottom: var(--or-esp-6);
        /* esconde a barra de scroll nativa sem esconder a rolagem — o gesto de arrastar continua
           funcionando, só o trilho visual some (mesmo tratamento já usado em carrosséis do tema). */
        scrollbar-width: none;
    }
    .or-faq-indice::-webkit-scrollbar { display: none; }
    /* .or-doc-indice__titulo é o filho ("Nesta página") — não cabe/não ajuda em chip horizontal */
    .or-faq-indice .or-doc-indice__titulo { display: none; }
    .or-faq-indice ol,
    .or-faq-indice ul {
        display: flex;
        gap: var(--or-esp-2);
        counter-reset: none; /* números do índice de documento não fazem sentido em chip */
    }
    .or-faq-indice li { flex: 0 0 auto; border-bottom: none; }
    .or-faq-indice a {
        display: inline-flex;
        align-items: center;
        white-space: nowrap;
        padding: 8px 16px;
        border-radius: var(--or-radius-pill);
        border: 1px solid var(--color-1);
        opacity: 1;
    }
    .or-faq-indice a:hover,
    .or-faq-indice a:focus-visible {
        padding-left: 16px; /* sem o desloc. de 6px do :hover vertical — em chip isso empurra a fila */
        background: color-mix(in srgb, var(--marca-primaria) 8%, transparent);
        border-color: color-mix(in srgb, var(--marca-primaria) 30%, transparent);
    }
    .or-faq-indice ol a::before { content: none; } /* idem — numeração é de sumário vertical */
}

/* Permalink para /faq/<slug>. Discreto de propósito: a resposta já está aberta na frente do
   visitante, então o link é saída para quem quer compartilhar/citar aquela pergunta — não a ação
   principal. Antes desta página, as 19 rotas individuais não tinham NENHUM link de entrada. */
.or-faq-permalink {
    display: inline-flex;
    align-items: center;
    gap: var(--or-esp-2);
    margin-top: var(--or-esp-4);
    font-size: .875rem;
    font-weight: 500;
    color: var(--texto-link, var(--marca-primaria));
    text-decoration: none;
}
.or-faq-permalink:hover { text-decoration: underline; }
.or-faq-permalink:focus-visible { outline: 2px solid var(--or-dourado); outline-offset: 3px; border-radius: 2px; }
.or-faq-permalink svg { width: 14px; height: 14px; }

/* Card de atalho — o <a> É o card inteiro (alvo grande, bom no toque). */
.or-faq-atalho {
    display: flex;
    flex-direction: column;
    height: 100%;
    text-decoration: none;
    transition: transform .3s ease, box-shadow .3s ease;
}
.or-faq-atalho:hover { transform: translateY(-4px); box-shadow: var(--or-shadow-2); }
.or-faq-atalho:focus-visible { outline: 2px solid var(--or-dourado); outline-offset: 3px; }

/* letter-spacing: mesma armadilha do BLOCO 1 ("Tracking PROPORCIONAL", ~linha 224) — este <h3>
   é reescalado para 18px e herdava os -2px crus que o vendor calibrou para 80px, colando as
   palavras. Passou despercebido quando o bloco nasceu (01/09/2026) e foi pego junto com o mesmo
   defeito em .or-servico-card__titulo. */
.or-faq-atalho__titulo { color: var(--color-primary); font-size: 1.125rem; letter-spacing: -.01em; margin: 0 0 var(--or-esp-3); }
.or-faq-atalho__texto  { color: var(--color-primary); opacity: .72; font-size: .9375rem; line-height: 1.6; margin: 0 0 var(--or-esp-4); flex-grow: 1; }
.or-faq-atalho__link {
    display: inline-flex;
    align-items: center;
    gap: var(--or-esp-2);
    font-size: .9375rem;
    font-weight: 600;
    color: var(--texto-link, var(--marca-primaria));
}
.or-faq-atalho__link svg { width: 14px; height: 14px; }

/* ═══════════════════════════════════════════════════════════════════════════════════════════════
   BLOCO 8 — CARD DO BLOG: resumo (01/09/2026)
   ═══════════════════════════════════════════════════════════════════════════════════════════════

   O resumo já era SELECIONADO pelo controller do core (site/blog.php:19) e descartado no template —
   o card mostrava título e data e nada mais.

   .or-blog-cat SAIU em 08/09/2026: a categoria continua sendo exibida, mas dentro de
   `.or-blog-plano` (o chip da home), como fallback para artigo fora do conjunto curado. Manter uma
   segunda pílula só para a categoria era exatamente a divergência que o dono apontou ("dois tipos
   de grade com conteúdos classificatórios diferentes"). Regra sem markup vira componente que
   nenhuma tela renderiza — mesma doutrina já aplicada em .or-post-autor__cargo.

   .line-clamp-3 é utilitária do próprio vendor (style.css:494) — não reimplementada aqui. */

.or-blog-resumo {
    margin: 0 0 var(--or-esp-3);
    font-size: .9375rem;
    line-height: 1.6;
    color: var(--color-primary);
    opacity: .74;
}

/* --- Assinatura do autor no artigo (post.php, 03/09/2026): EQU_FOTO já existia no controller e no
   JSON-LD (Person.image), mas a página só mostrava o nome. Foto circular + nome + cargo, no molde
   de avatar já usado em equipe.php. Sem foto cadastrada o bloco não renderiza (PHP), então não há
   estado "placeholder" pra estilizar. --- */
.or-post-autor {
    display: flex;
    align-items: center;
    gap: var(--or-esp-4, 16px);
    margin-bottom: var(--or-esp-6, 32px);
}
.or-post-autor__foto {
    flex-shrink: 0;
    display: block;
    width: 48px;
    height: 48px;
    border-radius: 50%;
    overflow: hidden;
}
.or-post-autor__foto img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Só o nome: usuário do painel não tem cargo cadastrado nem página pública (o membro de equipe
   tinha os dois). As regras de __cargo e do link saíram junto com o markup — CSS sem markup sugere
   um componente que nenhuma tela renderiza. */
.or-post-autor__nome { font-weight: 600; color: var(--color-primary); line-height: 1.3; }

/* --- Resposta direta (§3.6 do levantamento blog/contato/legais, 04/09/2026) — convenção
   editorial, sem campo próprio no banco (pendência em docs/cliente/pendencias-core.md): o 1º
   parágrafo do corpo do artigo responde a pergunta do título em 2-4 frases. Escopado a
   .blog-body (post.php), não a .or-doc-body em geral — política/FAQ/página CMS não têm essa
   convenção. MESMO seletor de schema_speakable_seletores (config_parametros) — visual e dado
   estruturado apontam pro mesmo trecho, nunca dois critérios. .blog-body era classe morta (o
   CSS do vendor exige ancestral .blog-item, que post.php não tem) — reaproveitada aqui em vez
   de removida. */
.blog-body p:first-of-type {
    font-size: 1.15rem;
    font-weight: 500;
    color: var(--color-primary);
    border-left: 3px solid var(--marca-primaria);
    padding-left: 1rem;
    margin-bottom: 1.5rem;
}

/* --- Card de artigo (.quanto-blog-box — vendor, usado na grade de /blog e, nas variantes base e
   style-2, em /eventos e /comunicados; o "Leia também" do artigo virou navegação anterior/próximo
   em 05/09/2026 e não usa mais este card): o vendor não tem box-shadow nenhum ("o vendor inteiro é retângulo chapado", nota do
   .or-card mais acima), então o card era um retângulo solto no branco. Tokens JÁ existentes, zero
   cor nova. SÓ sombra, sem translateY no hover: mesma régua do .or-servico-card (grade com muitos
   cards, levantar fica ruidoso). O dark não precisa de regra de sombra — --or-shadow-1 já resolve
   pra `none` sozinho (bloco de tokens, linha ~123); precisa só da borda, mesmo par claro/escuro
   que .or-card--claro usa. O zoom 1.1x da thumb no hover é do vendor e continua valendo. --- */
.quanto-blog-box {
    border-radius: var(--or-radius-m);
    box-shadow: var(--or-shadow-1);
    transition: box-shadow .3s ease;
}
.quanto-blog-box:hover { box-shadow: var(--or-shadow-2); }
[data-bs-theme="dark"] .quanto-blog-box { border: 1px solid var(--or-border); }

/* ═══════════════════════════════════════════════════════════════════════════════════════════════
   BLOCO 8.5 — SUPERFÍCIE MODERNA DO CARD DE ARTIGO (.or-artigo-card) — 05/09/2026
   ═══════════════════════════════════════════════════════════════════════════════════════════════
   Camada ADITIVA sobre `.quanto-blog-box.style-3` — o MESMO molde da seção de blog da home
   (home.php:1839), que o dono validou como referência em 05/09/2026 ("leve em consideração já a
   section que temos na home, que está excelente"). Do style-3 vêm o padding interno de 32px 40px
   (style.css:4364) e o sublinhado deslizante do título no hover — este último SÓ na listagem, e não
   por opção: o seletor do vendor é `h5 a`, e a home titula em `h3`. Da `.quanto-blog-content
   .bg-color-white` vem a sombra sobre seção branca (custom.css ~2174).

   Esta camada acrescenta SÓ o que o style-3 não cobre, porque a listagem tem exigências que a
   vitrine da home não tem: altura igual entre cards irmãos (a home tem 3 títulos curados de
   tamanho parecido; aqui os resumos variam), proporção fixa da capa e a ação presa ao rodapé.

   SEM translateY no hover — decisão já registrada no bloco .quanto-blog-box acima ("grade com
   muitos cards, levantar fica ruidoso"); esta camada respeita a mesma régua, só anima a seta da
   ação (gap crescente), que é affordance sem ruído de movimento de layout. */
.or-artigo-card {
    position: relative;   /* ancora o .stretched-link do título — sem isto ele cobriria a página inteira */
    display: flex;
    flex-direction: column;
    height: 100%;          /* cards da mesma row terminam na mesma altura (col-* já estica por padrão) */
    overflow: hidden;       /* recorta o topo da capa no MESMO raio do card — sem isto a thumb ficava
                                quadrada por cima de um card com cantos arredondados */
}

/* Proporção fixa da capa — sem isto a grade "pulava" de altura conforme a proporção original de
   cada imagem enviada no painel (achado real: capas de artigos vêm em proporções livres).
   16/9 (era 16/10 até 08/09/2026): a home não força proporção nenhuma, e as capas reais medem
   475×267 = 1.779 ≈ 16/9 — o 16/10 recortava ~10% da altura de TODA capa, e era por isso que a
   mesma imagem parecia diferente nas duas grades (medido: thumb 1.599 aqui × 1.780 na home).
   A restrição continua existindo (é ela que impede o card de "pular" com upload fora de padrão),
   só que agora no valor que o material real já tem. */
.or-artigo-card .quanto-blog-thumb { aspect-ratio: 16 / 9; }
.or-artigo-card .quanto-blog-thumb img { width: 100%; height: 100%; object-fit: cover; }

/* flex + flex-grow para a ação colar no rodapé do card (margin-top:auto abaixo). O PADDING vem do
   style-3 do vendor — não redeclarar aqui, ou a listagem divergiria da home de novo. */
.or-artigo-card__corpo {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
}

/* ⚠️ FILHO DE FLEX É BLOQUIFICADO — a causa raiz do "pill cinza esticado" do print de 08/09/2026.
   Tornar o corpo do card um flex column (regra acima, para prender a ação no rodapé) fez o
   navegador converter `display:inline-block`/`inline-flex` dos filhos em `block`, e o
   `align-items:stretch` padrão os esticou de borda a borda: o chip de categoria media 374px de
   largura (medido) em vez de abraçar o texto, virando uma barra. Na home o mesmo chip é inline
   porque lá o corpo NÃO é flex. `align-self: flex-start` devolve o comportamento de pílula sem
   desfazer o flex — os filhos de TEXTO (h5, resumo) continuam esticando, que é o desejado. */
.or-artigo-card__corpo > .or-blog-plano,
.or-artigo-card__corpo > .or-artigo-card__acao { align-self: flex-start; }

/* Respiro entre o chip e o resumo: o chip só tinha margin-top (na home ele é o último elemento do
   card). Aqui vem texto depois dele, e o piso do CLAUDE.md §Padrão de Espaçamento vale igual. */
.or-artigo-card__corpo .or-blog-plano + .or-blog-resumo { margin-top: var(--or-esp-4); }

/* stretched-link (Bootstrap, plugins.bundle.css) já resolve o alvo de clique cobrindo
   .or-artigo-card inteiro — nada a redeclarar aqui além do sublinhado padrão do <a>.

   COR: o vendor força `color: inherit` no título do style-3 (style.css:4381), e como o seletor
   dele é `h5 a`, a regra pegava a LISTAGEM (h5) e não a home (h3) — daí o título preto aqui e azul
   lá, no mesmo card (medido: rgb(0,0,0) × rgb(11,61,145)). Devolver o azul do link é o que iguala
   as duas grades; `--texto-link` já é theme-aware (clareia no escuro), então não há override de
   dark a escrever. Especificidade (0,4,2) repetindo a cadeia do vendor (0,3,2) — mesma lição já
   registrada no bloco das listas de check: contra seletor longo do vendor, ganhar por classe,
   nunca por !important. */
.or-artigo-card__corpo h5 a { text-decoration: none; }
.quanto-blog-box.style-3 .quanto-blog-content.or-artigo-card__corpo h5 a {
    color: var(--texto-link, var(--marca-primaria));
}

/* Ação "Ler artigo" — ocupa o lugar que a data tinha (a data agora é opcional por artigo,
   controle editorial da migration 108 do core). margin-top:auto empurra a ação pro FIM do card,
   alinhando a base entre cards de resumo mais curto/mais longo na mesma row. */
.or-artigo-card__acao {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-top: auto;
    padding-top: var(--or-esp-4);
    font-size: .875rem;
    font-weight: 600;
    color: var(--texto-link, var(--marca-primaria));
}
[data-bs-theme="dark"] .or-artigo-card__acao { color: var(--or-brand-accent); }
.or-artigo-card__acao svg { width: 16px; height: 16px; transition: transform .2s ease; }
.or-artigo-card:hover .or-artigo-card__acao svg,
.or-artigo-card:focus-within .or-artigo-card__acao svg { transform: translateX(4px); }

@media (prefers-reduced-motion: reduce) {
    .or-artigo-card__acao svg { transition: none !important; }
}
html[data-or-rm="reduce"] .or-artigo-card__acao svg { transition: none !important; }

/* ═══════════════════════════════════════════════════════════════════════════════════════════════
   BLOCO 8.6 — PÁGINA DE ARTIGO: progresso de leitura + índice ativo — 05/09/2026
   ═══════════════════════════════════════════════════════════════════════════════════════════════
   Print 7 do dono: /blog/<slug> "não apresenta qualquer padronização ou modernização". Três
   defeitos endereçados aqui (o quarto, o ritmo da prosa dentro de .or-doc-body, já tinha sido
   corrigido no levantamento blog/contato/legais de 04/09 — h4-h6/blockquote/table/img/code/pre). */

/* --- Vão morto entre hero e corpo — CAUSA RAIZ ENCONTRADA, não estética. .blog-detail-page é do
   vendor (style.css) e traz padding-top:200px (150/120/100 nos breakpoints menores) — o espaço
   reservado pro header FIXO na blog-details.html original, que NÃO TINHA hero. Aqui
   _hero-interno.php já entrega eyebrow+h1+meta+breadcrumb inteiros, então aqueles 200px viravam
   vão morto entre o fim do hero e o primeiro parágrafo. Nenhum override existia pra essa classe.
   Mesmo defeito, mesma causa, em evento-detalhe.php (única outra página que usa
   .blog-detail-page) — a regra corrige as duas de uma vez. Escopado a .or-pg (0,2,0) pra vencer
   a regra do vendor (0,1,0) sem !important. */
.or-pg .blog-detail-page { padding-top: var(--or-esp-8); }
@media (max-width: 991.98px) {
    .or-pg .blog-detail-page { padding-top: var(--or-esp-7); }
}

/* --- Barra de progresso de leitura (post.php) — markup em _chrome-topo.php, fora de
   #smooth-content (razão estrutural documentada lá: transform do ScrollSmoother cria containing
   block, position:fixed dentro dele fica preso ao conteúdo). Colada na borda de baixo do header
   via --or-header-h (a MESMA variável que o próprio header publica) — sem disputar z-index com
   ele, só nasce logo abaixo. JS: or-tema-motion.js. */
.or-progresso-leitura {
    position: fixed;
    top: var(--or-header-h, 90px);
    left: 0;
    right: 0;
    height: 3px;
    z-index: 1000;
    background: transparent;
    pointer-events: none;
}
.or-progresso-leitura__barra {
    height: 100%;
    width: 0%;
    background: var(--marca-primaria);
    transition: width .1s linear;
}
@media (prefers-reduced-motion: reduce) { .or-progresso-leitura__barra { transition: none !important; } }
html[data-or-rm="reduce"] .or-progresso-leitura__barra { transition: none !important; }

/* --- Item ativo do índice sticky (.or-doc-indice, BLOCO 6 acima) — JS marca .is-active via
   IntersectionObserver conforme o heading correspondente cruza a faixa de leitura. Mesmos tokens
   do :hover/:focus-visible já declarados ali (nenhuma cor nova); dourado à esquerda reforça o
   item corrente sem duplicar o `::before` numerado. */
.or-doc-indice a.is-active {
    opacity: 1;
    color: var(--texto-link, var(--marca-primaria));
    padding-left: 6px;
    border-left: 2px solid var(--or-dourado);
}

/* --- Navegação entre artigos (.or-post-nav) — substituiu a grade "Leia também" em 05/09/2026,
   a pedido do dono ("apenas listar como se fosse atalho simples, para próximo post e para post
   anterior"). Dois atalhos direcionais, sem capa/resumo/chip: o peso de card competia com a
   leitura em vez de encerrá-la.

   grid de 2 colunas com `1fr 1fr` e não flex: com só UM dos lados presente (primeiro/último
   artigo do blog), o grid mantém o item na coluna dele — `justify-content: space-between` num
   flex jogaria um "Próximo artigo" solitário para a esquerda, no lugar de onde o "anterior"
   deveria estar. `--prox` se alinha à direita pela regra própria abaixo, então a leitura
   direcional (← esquerda / direita →) sobrevive aos dois casos degenerados. */
.or-post-nav {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--or-esp-4);
    border-top: 1px solid var(--or-border, rgba(0, 0, 0, .1));
    padding-top: var(--or-esp-6);
}
/* Um lado só: ocupa a coluna certa em vez de escorregar para a primeira. */
.or-post-nav__item--prox:only-child { grid-column: 2; }

.or-post-nav__item {
    display: flex;
    flex-direction: column;
    gap: var(--or-esp-2);
    padding: var(--or-esp-5);
    border: 1px solid var(--or-border, rgba(0, 0, 0, .1));
    border-radius: var(--or-radius-m);
    text-decoration: none;
    color: inherit;
    transition: border-color .2s ease, background-color .2s ease;
}
.or-post-nav__item:hover {
    border-color: var(--marca-primaria);
    background: var(--or-surface-2, rgba(0, 0, 0, .02));
}
.or-post-nav__item:focus-visible {
    outline: 2px solid var(--marca-primaria);
    outline-offset: 3px;
}
.or-post-nav__item--prox { text-align: right; align-items: flex-end; }

.or-post-nav__rotulo {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: .8125rem;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--texto-link, var(--marca-primaria));
}
[data-bs-theme="dark"] .or-post-nav__rotulo { color: var(--or-brand-accent); }
.or-post-nav__rotulo svg { width: 15px; height: 15px; transition: transform .2s ease; }
.or-post-nav__item--ant:hover .or-post-nav__rotulo svg { transform: translateX(-3px); }
.or-post-nav__item--prox:hover .or-post-nav__rotulo svg { transform: translateX(3px); }

/* line-clamp:2 e não 1: título de artigo real quebra em 2 linhas com frequência, e cortar no meio
   da primeira esconderia o assunto — que é a única informação que este atalho carrega. */
.or-post-nav__titulo {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    font-size: 1.0625rem;
    font-weight: 600;
    line-height: 1.35;
    color: var(--color-primary);
}

/* Mobile: os dois atalhos empilham e o "próximo" volta a alinhar à esquerda — numa coluna só, o
   texto à direita seria leitura irregular sem ganho direcional nenhum. */
@media (max-width: 575.98px) {
    .or-post-nav { grid-template-columns: 1fr; }
    .or-post-nav__item--prox { text-align: left; align-items: flex-start; }
    .or-post-nav__item--prox:only-child { grid-column: 1; }
}

@media (prefers-reduced-motion: reduce) {
    .or-post-nav__item, .or-post-nav__rotulo svg { transition: none !important; }
}
html[data-or-rm="reduce"] .or-post-nav__item,
html[data-or-rm="reduce"] .or-post-nav__rotulo svg { transition: none !important; }

/* ═══════════════════════════════════════════════════════════════════════════════════════════════
   BLOCO 9 — CARD DE SERVIÇO DA GRADE /servicos (.or-servico-card) — 01/09/2026
   ═══════════════════════════════════════════════════════════════════════════════════════════════

   SUBSTITUI o .quanto-service-box.style-2 do vendor, que era a causa MEDIDA do "muito grande e com
   muito espaçamento" apontado pelo dono. Aquele componente zera o padding do card e no lugar dele
   empilha margin-bottom:60px no ícone (style.css:3182) + margin-top:90px no link (style.css:3226)
   = 150px de ar morto por card no desktop. Ele foi desenhado para um layout diferente (colunas
   separadas por borda vertical, sem fundo próprio) e o fork nunca o sobrescreveu — era 100% vendor.

   Compõe com .or-card + .or-card--claro (fundo/raio/sombra já definidos no BLOCO 2), então aqui só
   entra o que é específico da grade: densidade, o ícone, e o empurrão do link para o rodapé do card
   (margin-top:auto num flex column) — que é o que mantém a linha "Ver detalhes" alinhada entre
   cards de altura diferente SEM precisar de altura fixa nem dos 90px do vendor.

   O hover NÃO usa .or-card--hover: aquele levanta 4px, e num grid de até 4 colunas com 6+ cards o
   movimento fica ruidoso. Aqui é só sombra + a cor da marca no título/seta, que é o que sinaliza
   "isto abre alguma coisa" sem sacudir a grade. */

.or-servico-card {
    display: flex;
    flex-direction: column;
    height: 100%;
    padding: var(--or-esp-6);
    transition: box-shadow .15s ease, border-color .15s ease;
    /* Âncora do stretched link abaixo — sem isto o ::after do título se prenderia ao primeiro
       ancestral posicionado (a seção) e cobriria a página inteira. */
    position: relative;
}
.or-servico-card:hover { box-shadow: var(--or-shadow-2); border-color: var(--color-1); }

/* ── O CARD INTEIRO É A ÁREA DE CLIQUE (stretched link) — 02/09/2026 ──────────────────────────
   Achado num print do dono: o "Ver detalhes" parecia botão e não clicava. Era verdade — ele é um
   <span aria-hidden> (só o título é <a>), e essa escolha continua certa: transformá-lo em <a>
   devolveria a DUAS paradas de teclado por card para o mesmo destino, que é o defeito que o
   comentário de _servico-card.php documenta (com 16 serviços seriam 32 paradas).

   A saída é a do Bootstrap (.stretched-link), reimplementada aqui para não depender de classe no
   markup: o ::after do link do título vira uma camada transparente sobre todo o card. Resultado —
   UM link no DOM (teclado e leitor de tela inalterados), área de clique inteira e cursor de mão em
   qualquer ponto, inclusive sobre o "Ver detalhes".

   z-index 1 e não 0: precisa ficar acima do conteúdo do card para receber o clique. Não há outro
   link dentro do card que isto pudesse capturar — o título é o único. */
.or-servico-card__titulo a::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 1;
    border-radius: inherit;
}

/* Ícone: 40px é o mesmo tamanho já usado pelo .or-servico-icon (BLOCO 4) — a cor vem de lá
   (var(--marca-primaria), e --or-brand-accent no escuro), não se repete aqui. */
.or-servico-card__ico { display: inline-flex; margin-bottom: var(--or-esp-5); }

.or-servico-card__titulo {
    margin: 0 0 var(--or-esp-3);
    font-size: 1.125rem;
    line-height: 1.35;
    /* OBRIGATÓRIO ao reescalar um heading — ver a nota de "Tracking PROPORCIONAL" no BLOCO 1
       (linha ~224). O vendor prende letter-spacing à TAG em px (h3 = -2px calibrado para 80px);
       um <h3> reescalado para 18px herda os -2px crus = -11% do corpo, e as palavras colam umas
       nas outras. Achado ao vivo no print da grade, 01/09/2026 — exatamente o mesmo defeito que a
       nota do BLOCO 1 já registrava para .or-prova-card. -.01em é o valor proporcional do próprio
       vendor nesta escala (o -0,24px@24px do h6). */
    letter-spacing: -.01em;
    color: var(--color-primary);
}
.or-servico-card__titulo a { color: inherit; text-decoration: none; transition: color .15s ease; }
.or-servico-card:hover .or-servico-card__titulo a { color: var(--texto-link, var(--marca-primaria)); }
.or-servico-card__titulo a:focus-visible { outline: 2px solid var(--or-dourado); outline-offset: 3px; border-radius: 2px; }

.or-servico-card__texto {
    margin: 0 0 var(--or-esp-5);
    font-size: .9375rem;
    line-height: 1.6;
    color: var(--color-primary);
    opacity: .74;
}

/* margin-top:auto cola o link no rodapé do card — é ele que alinha a linha "Ver detalhes" entre
   cards de alturas diferentes. Substitui os 90px fixos do vendor, que eram espaço morto quando o
   subtítulo era curto. É <span>, não <a>: o título já linka para o mesmo destino (ver o comentário
   em servicos.php sobre a duplicação de parada no teclado/leitor de tela) — e desde 02/09/2026 ele
   CLICA assim mesmo, porque o stretched link acima cobre o card inteiro. */
.or-servico-card__link {
    display: inline-flex;
    align-items: center;
    gap: var(--or-esp-2);
    margin-top: auto;
    font-size: .875rem;
    font-weight: 600;
    color: var(--texto-link, var(--marca-primaria));
}
.or-servico-card__link svg { width: 14px; height: 14px; transition: transform .15s ease; }
.or-servico-card:hover .or-servico-card__link svg { transform: translateX(3px); }

/* Densidade nas telas pequenas: em 2 colunas num celular a coluna tem ~170px, então o padding do
   card e o corpo do texto encolhem — senão sobra moldura e falta texto. */
@media (max-width: 575.98px) {
    .or-servico-card { padding: var(--or-esp-5); }
    .or-servico-card__ico { margin-bottom: var(--or-esp-4); }
    .or-servico-card__titulo { font-size: 1rem; }
    .or-servico-card__texto { font-size: .875rem; margin-bottom: var(--or-esp-4); }
}

/* Movimento reduzido — os DOIS gates do projeto (a preferência do SO e o override manual do widget
   de acessibilidade). Esquecer o segundo é o furo que este projeto já corrigiu duas vezes. */
@media (prefers-reduced-motion: reduce) {
    .or-servico-card,
    .or-servico-card__titulo a,
    .or-servico-card__link svg { transition: none !important; }
    .or-servico-card:hover .or-servico-card__link svg { transform: none !important; }
}
html[data-or-rm="reduce"] .or-servico-card,
html[data-or-rm="reduce"] .or-servico-card__titulo a,
html[data-or-rm="reduce"] .or-servico-card__link svg { transition: none !important; }
html[data-or-rm="reduce"] .or-servico-card:hover .or-servico-card__link svg { transform: none !important; }

/* ═══════════════════════════════════════════════════════════════════════════════════════════════
   BLOCO 10 — LINHA DO TEMPO DE ETAPAS (.or-etapas) — 01/09/2026
   ═══════════════════════════════════════════════════════════════════════════════════════════════

   SUBSTITUI o acordeão .or-etapas-acordeao na seção #como-funciona de /servicos (o CSS antigo
   continua no BLOCO 4 porque a home ainda pode voltar a usá-lo; se ficar órfão de vez, é remoção
   à parte). Motivo da troca: 4 descrições de 82-137 caracteres cabem abertas — acordeão pedia 4
   cliques para revelar 4 frases e destruía a leitura em sequência.

   SUPERFÍCIE ESCURA PERMANENTE (bg-color-primary nos 2 temas). Por isso as tintas aqui são
   literais rgba(255,255,255,…) e NÃO tokens: --color-primary/--color-white FLIPAM com o tema, e
   usá-los aqui produziria texto escuro sobre fundo escuro no dark. Mesma doutrina já registrada em
   .or-rd (rodapé) e no docblock desta seção em servicos.php. Os degraus .78/.62 são os mesmos já
   medidos e aprovados no rodapé (≈9,5:1 e ≈5,8:1 sobre a superfície escura — acima do piso AA).

   O comprimento de linha é controlado aqui (max-width no texto), e não por uma coluna Bootstrap
   capada — foi o que permitiu a row voltar a col-12, como manda o padrão canônico. */

/* 3 COLUNAS, NÃO 4 (01/09/2026). A grade nasceu com repeat(4,1fr) porque havia exatamente 4 etapas —
   número de conteúdo virado layout, e o layout quebrou assim que a jornada passou a 6 fases (seed
   037). Com 3 colunas: 6 preenche 2 fileiras cheias, os passos ficam mais largos (cabe a <ul> de
   entregáveis sem espremer) e a quebra para 2 colunas no tablet passa a ser 3→2, não 4→2. */
.or-etapas {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: var(--or-esp-7);
    grid-template-columns: repeat(3, 1fr);
    counter-reset: or-etapa;
}
.or-etapas__item { position: relative; display: flex; flex-direction: column; }

/* A trilha que liga um passo ao seguinte — é o que faz ler como SEQUÊNCIA, não como cards soltos.
   Desenhada com ::after do próprio marcador (sem elemento extra no HTML).

   ESCONDIDA NO ÚLTIMO DE CADA FILEIRA, não só no último de todos (correção de 01/09/2026). Enquanto
   havia 4 etapas em 4 colunas os dois casos coincidiam; com 6 em 3 colunas, o passo 3 desenhava uma
   trilha apontando para o VAZIO à direita — ligando visualmente o fim de uma fileira ao nada, e não
   ao passo 4, que está embaixo à esquerda.

   :nth-child(3n) + :last-child vale para QUALQUER quantidade, não só para 6: com 5 etapas o 3 fecha
   a fileira e o 5 é o último; com 7, o 6 fecha e o 7 é o último. O dono pode acrescentar uma fase
   pelo painel sem que ninguém precise voltar aqui.

   Note que o `:last-child` fica no seletor que CRIA o pseudo-elemento, e o "fecha fileira" é uma
   regra SEPARADA de `display`. A diferença não é estilística: `content` não existe quando o seletor
   não casa, e nenhum breakpoint consegue reativar um ::after que nunca foi criado — que é
   exatamente o que o de 1199px precisa fazer, porque em 2 colunas quem fecha a fileira deixa de ser
   o 3n e passa a ser o 2n. */
.or-etapas__marca {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 56px;
    height: 56px;
    margin-bottom: var(--or-esp-5);
    border: 1px solid rgba(255, 255, 255, .22);
    border-radius: 50%;
    background: rgba(255, 255, 255, .06);
    color: #fff;
    flex: 0 0 auto;
}
.or-etapas__item:not(:last-child) .or-etapas__marca::after {
    content: '';
    position: absolute;
    left: calc(100% + 1px);
    top: 50%;
    width: calc(var(--or-esp-7) - 2px);
    height: 1px;
    background: linear-gradient(90deg, rgba(255, 255, 255, .22), rgba(255, 255, 255, .04));
}
/* Fecha a fileira: em 3 colunas, quem termina a linha não liga a nada à direita. */
.or-etapas__item:nth-child(3n) .or-etapas__marca::after { display: none; }

/* ── .or-etapas--centro (03/09/2026, /sobre) — a mesma linha do tempo, centrada ───────────────
   MODIFICADOR, nunca a base: /servicos lê a jornada de 6 fases alinhada à esquerda e não muda.

   A TRILHA PRECISOU SER REDESENHADA, não só recentrada. A original nasce do ::after do MARCADOR e
   vale `width: var(--or-esp-7)` — exatamente o gap do grid —, o que só fecha a distância enquanto
   os círculos estão encostados na margem esquerda de cada coluna: aí a borda direita de um círculo
   fica a um gap da borda esquerda do próximo. Centrando os itens, os círculos vão para o meio das
   colunas e essa mesma medida cobre menos de metade do caminho — o traço morreria no vazio, e o
   bloco voltaria a ler como três cards soltos, que é justamente o que a trilha existe para evitar.

   A variante move o pseudo-elemento para o ITEM (que é `position: relative`), onde `100%` é a
   largura da COLUNA e não os 56px do círculo. Daí a geometria fecha sozinha, seja qual for a
   largura da coluna: começa 8px depois da borda direita do círculo (50% + 28 + 8) e corre até 8px
   antes da borda esquerda do próximo (100% + gap − 28 − 8), ou seja
   `100% + gap − 72px` de largura. 28px = raio do círculo de 56px; 8px = respiro dos dois lados.

   As regras de "fecha fileira" são reescritas em vez de herdadas porque o seletor mudou de lugar:
   `content` não existe quando o seletor não casa, e nenhum breakpoint reativa um ::after que nunca
   foi criado — é a mesma armadilha que a nota da trilha original já documenta. */
/* O GAP DE COLUNA ENTRA POR VARIÁVEL, não literal — e isso é correção de um bug real, pego ao
   medir em 1100px: a grade troca o gap horizontal de --or-esp-7 (48px) para --or-esp-6 (32px) no
   breakpoint de 1199px, e a trilha, calculada com 48 fixo, passava 8px PARA DENTRO do círculo
   seguinte em vez de parar 8px antes. Com a variável, o media query troca um valor só e a
   geometria continua fechando sozinha. */
.or-etapas--centro {
    --or-etapa-gap-col: var(--or-esp-7);
}
.or-etapas--centro .or-etapas__item { align-items: center; text-align: center; }
.or-etapas--centro .or-etapas__marca::after { display: none; }
.or-etapas--centro .or-etapas__item:not(:last-child)::after {
    content: '';
    position: absolute;
    top: 28px;                                            /* metade dos 56px do círculo */
    left: calc(50% + 36px);                               /* 28 do raio + 8 de respiro */
    width: calc(100% + var(--or-etapa-gap-col) - 72px);   /* até 8px antes do próximo círculo */
    height: 1px;
    background: linear-gradient(90deg, rgba(255, 255, 255, .22), rgba(255, 255, 255, .04));
}
.or-etapas--centro .or-etapas__item:nth-child(3n)::after { display: none; }
/* O texto do passo é centrado, então o max-width de 34ch precisa de margem automática — sem isto
   ele encosta à esquerda dentro de um item que está centrado, e só o texto sai do eixo. */
.or-etapas--centro .or-etapas__texto { margin-inline: auto; }

@media (max-width: 1199.98px) {
    /* 2 colunas: quem fecha a fileira passa a ser o 2n, e o 3n volta a ligar. */
    .or-etapas--centro .or-etapas__item:nth-child(3n)::after { display: block; }
    .or-etapas--centro .or-etapas__item:nth-child(2n)::after { display: none; }
    /* A grade troca o gap horizontal aqui — a trilha acompanha (ver a nota da variável acima).
       Declaração em linha PRÓPRIA, não inline com o seletor: o guard tema_quanto_test lê as
       definições com `/^\s*(--x)\s*:/m` e uma variável declarada depois da chave na mesma linha
       fica invisível para ele — passaria como "usada e nunca definida". */
    .or-etapas--centro {
        --or-etapa-gap-col: var(--or-esp-6);
    }
}
@media (max-width: 991.98px) {
    /* 1 coluna: não há vizinho à direita de ninguém. */
    .or-etapas--centro .or-etapas__item:nth-child(n)::after { display: none; }
    /* O círculo acompanha o texto centrado (a base o alinha à esquerda via inline-flex). */
    .or-etapas--centro .or-etapas__marca { margin-inline: auto; }
}
.or-etapas__ico svg { width: 26px; height: 26px; }
.or-etapas__num { font-size: 1.25rem; font-weight: 700; line-height: 1; }

/* Corpo do passo — min-width:0 é o que impede uma palavra longa (ex.: "Autoridade") de estourar a
   célula do grid: item de grid nasce com min-width:auto, que se recusa a encolher abaixo do
   conteúdo. Sem isto, a coluna alarga e desalinha a trilha entre os passos. */
.or-etapas__corpo { min-width: 0; }

.or-etapas__passo {
    margin: 0 0 var(--or-esp-2);
    font-size: .75rem;
    font-weight: 600;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--or-dourado);
}
.or-etapas__titulo {
    margin: 0 0 var(--or-esp-3);
    font-size: 1.25rem;
    /* Tracking proporcional — ver a nota do BLOCO 1 (~linha 224). Sem isto, o heading herdaria os
       -1.5px que o vendor calibrou para 60px. É esta regra que torna a TAG livre: os dois
       consumidores (sobre.php e servicos.php) usam <h3>, e o tamanho vem daqui, não da tag. */
    letter-spacing: -.01em;
    line-height: 1.3;
    color: #fff;
}
.or-etapas__texto {
    max-width: 34ch;
    font-size: .9375rem;
    line-height: 1.65;
    color: rgba(255, 255, 255, .78);
}
.or-etapas__texto p { margin: 0; }
.or-etapas__texto p + p { margin-top: var(--or-esp-3); }

/* ENTREGÁVEIS DO PASSO (01/09/2026) — a <ul> que cada ETP_DESCRICAO passou a trazer depois do
   parágrafo. É o que dá a profundidade que o dono pediu sem acrescentar caixa nenhuma na tela.

   Marcador próprio (li::before) em vez de list-style: o disco padrão herda a cor do texto e, sobre
   superfície escura a .78 de opacidade, some. O traço em --or-dourado é o mesmo sinal já usado no
   rótulo "PASSO N" logo acima — a coluna inteira lê como um bloco só.

   padding-left + text-indent negativo mantêm o alinhamento da 2ª linha do item embaixo da 1ª (e não
   embaixo do marcador), que é o detalhe que separa uma lista legível de uma lista bagunçada. */
.or-etapas__texto ul {
    list-style: none;
    margin: var(--or-esp-3) 0 0;
    padding: 0;
}
.or-etapas__texto li {
    position: relative;
    padding-left: 1.1em;
    margin-top: var(--or-esp-2);
}
.or-etapas__texto li::before {
    content: '';
    position: absolute;
    left: 0;
    top: .72em;
    width: .55em;
    height: 1px;
    background: var(--or-dourado);
}

/* 3 → 2 → 1. Em 2 colunas a trilha horizontal só faz sentido dentro da mesma fileira; abaixo disso
   ela some (o empilhamento já comunica a sequência, e uma linha horizontal apontando para o vazio
   seria pior que nenhuma).

   O `display:none` do 3n precisa ser DESFEITO aqui: a regra base esconde a trilha do 3º item porque
   ele fecha a fileira em 3 colunas — mas com 2 colunas quem fecha a fileira é o par (2n), e o 3º
   passa a ABRIR uma fileira, precisando da trilha de volta. Sem este `display:block`, a linha entre
   o passo 3 e o 4 sumiria só no tablet, sem motivo visível. */
@media (max-width: 1199.98px) {
    .or-etapas { grid-template-columns: repeat(2, 1fr); gap: var(--or-esp-7) var(--or-esp-6); }
    .or-etapas__item:nth-child(3n) .or-etapas__marca::after { display: block; }
    .or-etapas__item:nth-child(2n) .or-etapas__marca::after { display: none; }
    .or-etapas__texto { max-width: none; }
}
@media (max-width: 575.98px) {
    .or-etapas { grid-template-columns: 1fr; gap: var(--or-esp-6); }
    .or-etapas__marca { width: 48px; height: 48px; margin-bottom: var(--or-esp-4); }
    /* ⚠️ `:nth-child(n)` não é enfeite — é ESPECIFICIDADE, e sem ele esta regra não vale.
       Abaixo de 576px as DUAS media queries se aplicam (575.98 também é ≤ 1199.98), e lá em cima há
       `.or-etapas__item:nth-child(3n) .or-etapas__marca::after { display: block }` para devolver a
       trilha ao 3º item quando a grade vira 2 colunas. Aquele seletor pesa (0,3,2); um
       `.or-etapas__marca::after` pelado pesa (0,1,1) e PERDE — ordem no arquivo não desempata
       especificidade diferente. Medido ao vivo em 390px: com a versão pelada, o passo 3 era o único
       da coluna única a exibir uma trilha horizontal apontando para o nada. O `:nth-child(n)` casa
       todo item e empata em (0,3,2); como esta regra vem depois, ganha o desempate por ordem. */
    .or-etapas__item:nth-child(n) .or-etapas__marca::after { display: none; }
    .or-etapas__titulo { font-size: 1.125rem; }
}

/* ═══════════════════════════════════════════════════════════════════════════════════════════════
   BLOCO 10.5 — ADD-ONS AVULSOS na grade de /servicos — 01/09/2026
   ═══════════════════════════════════════════════════════════════════════════════════════════════

   Os 3 add-ons (redes sociais, migração de conteúdo, multi-idioma) ficam num sub-bloco à parte dos
   12 serviços de plano: são cobrados fora do valor mensal, e uma grade única faria o preço do plano
   parecer incluir o que não inclui.

   .or-addons-titulo precisa de tracking próprio pela armadilha do tracking proporcional (nota do
   BLOCO 1, ~linha 224): o vendor amarra letter-spacing à TAG em px absolutos — h2 e h3 nascem com
   -2px ou mais, calibrados para 60-80px. Reescalar o heading sem reescalar o tracking cola as
   palavras. Já aconteceu duas vezes neste arquivo (.or-servico-card__titulo e
   .or-faq-atalho__titulo). Por declarar tamanho E tracking, a regra é indiferente à tag — o
   markup virou <h2> em 03/09/2026 (o bloco AGRUPA os add-ons: estava no mesmo nível dos itens
   que anuncia) sem mudar um pixel.

   .or-addons-grade traz a própria margem porque é bloco irmão da row do cabeçalho — e traz aqui, no
   CSS, em vez de um mt-* no markup: `mt-*` do Bootstrap SOBRESCREVE o `margin-top` negativo que a
   .row usa para cancelar o gutter-y, e cada coluna passaria a somar +24px não cancelados no topo (é
   a mesma armadilha de `g-*` vs `gx-*`, medida e documentada na home). Margem em classe própria
   não toca no par margem-negativa/gutter.

   ⚠️ ESTA FRASE JÁ CAUSOU UM BUG, e é por isso que ela agora escreve os dois nomes separados.
   Até 04/09/2026 ela dizia "g-" e "gx-" grudados por uma barra, e a sequência asterisco-barra
   ENCERRA O COMENTÁRIO CSS onde quer que apareça, inclusive no meio de uma palavra. O comentário terminava ali, o resto do parágrafo virava seletor, e o parser engolia a REGRA
   SEGUINTE inteira: .or-addons-titulo ficou sem margin nenhuma em /servicos, com o título colado
   no parágrafo de baixo. Sem erro no console e sem falha de guard — só um espaçamento errado que
   ninguém liga ao texto de um comentário. Nunca escreva a sequência de fechamento dentro de um
   comentário, nem em exemplo de código. Travado pela Parte C do bin/cliente/auditar-espacamento.php. */
.or-addons-titulo {
    margin: 0 0 var(--or-esp-3);
    font-size: var(--or-fs-h3, 1.5rem);
    letter-spacing: -.01em;
    line-height: 1.25;
}
.or-addons-grade { margin-top: var(--or-esp-5); }

/* ═══════════════════════════════════════════════════════════════════════════════════════════════
   BLOCO 10.6 — PÁGINA DE DETALHE DO SERVIÇO (/servicos/<slug>) — 01/09/2026
   ═══════════════════════════════════════════════════════════════════════════════════════════════

   A página era uma coluna de prosa só (o docblock dela admitia o molde: "mesmo molde de
   politica.php"). Ganhou as seções "O que está incluído", "Em qual plano entra" e "Outros serviços",
   seguindo a anatomia canônica de sobre.php/pagina-faq.php.

   SUPERFÍCIE CLARA/ESCURA CONFORME O TEMA (diferente do BLOCO 10, que é escuro permanente): aqui as
   seções usam bg-color-2 e o fundo base, que FLIPAM. Logo, as tintas destes componentes são TOKENS
   (--texto-principal, --or-border…), nunca literais rgba() — o oposto exato da regra do BLOCO 10.
   Trocar os dois de lugar é o erro que produz texto invisível num dos temas. */

/* ── O que está incluído ────────────────────────────────────────────────────────────────────────
   align-items:start mantém o ✓ alinhado à PRIMEIRA linha do texto quando o item quebra em duas —
   com center, um item de 2 linhas empurraria o ícone para o meio e a coluna perderia o prumo. */
.or-incluido {
    display: flex;
    align-items: flex-start;
    gap: var(--or-esp-3);
}
.or-incluido__ico {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 26px;
    height: 26px;
    margin-top: .1em;
    border-radius: 50%;
    background: rgba(var(--marca-primaria-rgb, 11, 61, 145), .10);
    color: var(--marca-primaria);
}
.or-incluido__ico svg { width: 15px; height: 15px; }
.or-incluido__texto {
    margin: 0;
    min-width: 0;                       /* impede palavra longa de estourar a coluna do grid */
    line-height: 1.55;
    color: var(--texto-principal);
}

/* ── Régua de planos ────────────────────────────────────────────────────────────────────────────
   Três pílulas lado a lado com a mínima em diante marcada. Mostra que os planos são CUMULATIVOS
   sem precisar escrever a palavra: o cliente vê o ✓ se repetindo para cima.

   Grade de 3 colunas em vez de flex-wrap: com wrap, o 3º item cairia sozinho numa linha e ficaria
   com o dobro da largura dos outros dois — a régua deixaria de ler como régua. */
.or-plano-regua {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--or-esp-4);
}
.or-plano-regua__item {
    display: flex;
    align-items: center;
    gap: var(--or-esp-3);
    flex-wrap: wrap;
    padding: var(--or-esp-4) var(--or-esp-5);
    border: 1px solid var(--or-border, rgba(0, 0, 0, .10));
    border-radius: var(--or-radius-m);
    color: var(--texto-secundario);
}
.or-plano-regua__item.is-incluso {
    border-color: rgba(var(--marca-primaria-rgb, 11, 61, 145), .35);
    background: rgba(var(--marca-primaria-rgb, 11, 61, 145), .06);
    color: var(--texto-principal);
}
.or-plano-regua__ico {
    display: inline-flex;
    flex: 0 0 auto;
    color: var(--texto-secundario);
}
.or-plano-regua__item.is-incluso .or-plano-regua__ico { color: var(--marca-primaria); }
.or-plano-regua__ico svg { width: 18px; height: 18px; }
.or-plano-regua__nome { font-weight: 600; }
/* Empurrado para a direita, mas só quando cabe na mesma linha — no wrap ele desce alinhado ao nome. */
.or-plano-regua__preco { margin-left: auto; white-space: nowrap; }

.or-addon-preco { white-space: nowrap; color: var(--texto-principal); }
.or-plano-nota  { margin: var(--or-esp-4) 0 0; }
.or-plano-link  { margin: var(--or-esp-5) 0 0; }

@media (max-width: 767.98px) {
    .or-plano-regua { grid-template-columns: 1fr; gap: var(--or-esp-3); }
}

/* ═══════════════════════════════════════════════════════════════════════════════════════════════
   BLOCO 11 — CTA DE FECHO AMPLIADO (.or-secao-cta__*) — 01/09/2026
   ═══════════════════════════════════════════════════════════════════════════════════════════════

   O partial _secao-cta.php ganhou campos opcionais (eyebrow, subtítulo, ação secundária, canal de
   WhatsApp, nota). As regras base do componente estão no BLOCO 2 (~linha 1028); aqui entram só os
   elementos novos. Este bloco vem DEPOIS de .or-eyebrow (~1094) de propósito — ver a nota de
   especificidade logo abaixo.

   ⚠️ ESCALA DE TINTA LOCAL POR VARIANTE — a parte que mais morde, e já mordeu antes.
   custom.css:694-700 registra um achado real de 29/08/2026: um eyebrow ficou LITERALMENTE
   invisível na variante dourada porque .or-eyebrow nasce em var(--marca-primaria) e o fundo é
   var(--or-grad-marca) — a MESMA cor de marca, medido em 1,00:1. .or-lead tem o mesmo defeito
   (var(--color-primary) sobre gradiente escuro), e ambos os tokens FLIPAM com o tema.
   Por isso nenhum elemento novo aqui reusa .or-eyebrow/.or-lead: a cor vem de 4 variáveis locais,
   redefinidas por variante. As regras de texto ficam agnósticas, e é impossível esquecer um
   override — ele passa a ser estrutural, não item de checklist.
   No dourado as tintas são literais rgba(255,255,255,…), imunes ao flip; os degraus .80/.62 são os
   mesmos já medidos no rodapé (≈9,5:1 e ≈5,8:1 — acima do piso AA). */

.or-secao-cta {
    --cta-tinta-2: rgba(255, 255, 255, .80);   /* corpo */
    --cta-tinta-3: rgba(255, 255, 255, .62);   /* auxiliar — piso AA */
    --cta-borda:   rgba(255, 255, 255, .22);
    --cta-link-2:  #fff;
    --cta-foco:    #fff;
}
.or-secao-cta--soft {
    --cta-tinta-2: var(--color-primary);
    --cta-tinta-3: var(--color-primary);
    --cta-borda:   rgba(0, 0, 0, .18);
    --cta-link-2:  var(--marca-primaria);
    --cta-foco:    var(--marca-primaria);
}
[data-bs-theme="dark"] .or-secao-cta--soft {
    --cta-tinta-2: rgba(255, 255, 255, .80);
    --cta-tinta-3: rgba(255, 255, 255, .62);
    --cta-borda:   rgba(255, 255, 255, .16);
    --cta-link-2:  var(--or-brand-accent);
    --cta-foco:    var(--or-brand-accent);
}

/* Classe PRÓPRIA, não .or-eyebrow — ver a nota de contraste acima. O traço dourado é reproduzido
   aqui porque no soft ele também precisa existir, e no dourado ele é o único acento permitido. */
.or-secao-cta__eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    margin: 0 0 var(--or-esp-4);
    font-size: .8125rem;
    font-weight: 600;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--cta-tinta-2);
}
.or-secao-cta__eyebrow::before {
    content: '';
    width: 28px;
    height: 2px;
    background: var(--or-dourado);
    flex: 0 0 auto;
}
.or-secao-cta--soft .or-secao-cta__eyebrow::before { background: var(--marca-primaria); }

/* Sem .or-lead (que traz opacity:.75 e cor que flipa) — cor e medida vêm daqui. */
.or-secao-cta__sub {
    max-width: 560px;
    margin: -12px auto var(--or-esp-6);
    font-size: var(--or-fs-lead);
    line-height: 1.6;
    color: var(--cta-tinta-2);
}

/* Escada de atrito: 1 botão primário + 1 ação secundária + 1 canal direto. Só existe com 2+ ações
   (o partial não emite este wrapper com uma). Wrap + gap para não estourar no mobile. */
.or-secao-cta__acoes {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: var(--or-esp-4) var(--or-esp-6);
}

/* Ação secundária: link sublinhado, NUNCA um 2º botão preenchido — custom.css:712 fecha a lista
   dos 6 usos do dourado, e dois botões cheios competiriam entre si em vez de formar escada. */
.or-secao-cta__btn2,
.or-secao-cta__canal {
    display: inline-flex;
    align-items: center;
    gap: var(--or-esp-2);
    padding-bottom: 2px;
    border-bottom: 1px solid var(--cta-borda);
    font-size: .9375rem;
    font-weight: 600;
    color: var(--cta-link-2);
    text-decoration: none;
    transition: border-color .15s ease, opacity .15s ease;
}
/* ⚠️ O `color` AQUI NÃO É REDUNDANTE — é o que impede o link de sumir no hover.
   Achado ao vivo em 02/09/2026, pego pelo dono num print: ao passar o mouse, "Ver planos e preços"
   e "Falar no WhatsApp" ficavam invisíveis, sobrando só a linha de baixo.

   A causa não é o vendor: é a regra GLOBAL deste próprio arquivo (linha ~168),
   `a:hover { color: var(--marca-secundaria) }`. Ela é correta no caso geral — link de prosa sobre
   fundo claro escurece no hover — e desastrosa aqui: --marca-secundaria é #082C6A, e o gradiente
   desta seção tem EXATAMENTE rgb(8,44,106) no stop de 55%. Ou seja, em parte da faixa o texto fica
   idêntico ao fundo. Medido: 18,51:1 em repouso → 1,39:1 no hover.

   Especificidade explica por que passou: `a:hover` pesa (0,1,1) e
   `.or-secao-cta__canal:hover` pesa (0,2,0), então a regra local JÁ vencia — mas ela só declarava
   `border-color`. Propriedade não declarada não é herdada da regra mais específica: cada uma é
   resolvida por conta própria, e `color` continuava vindo da global. Declarar a cor no repouso
   (acima) não protege o estado :hover.

   É a MESMA armadilha de "cor de marca sobre fundo de marca" já documentada em custom.css:694-700
   — a diferença é que ali ela vinha de reusar .or-eyebrow/.or-lead, e aqui vem de um seletor de
   elemento que alcança todo <a> do site. Ao criar link novo sobre superfície escura, declare o
   `color` do :hover junto: é a única defesa contra a global. */
.or-secao-cta__btn2:hover,
.or-secao-cta__canal:hover {
    border-color: var(--cta-link-2);
    color: var(--cta-link-2);
}
.or-secao-cta__btn2:focus-visible,
.or-secao-cta__canal:focus-visible { outline: 2px solid var(--cta-foco); outline-offset: 3px; border-radius: 2px; }
.or-secao-cta__canal svg { width: 18px; height: 18px; }

/* O botão dourado sobre fundo dourado precisa de anel BRANCO — o foco padrão da marca sumiria. */
.or-secao-cta__btn:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }
.or-secao-cta--soft .or-secao-cta__btn:focus-visible { outline-color: var(--marca-primaria); }

.or-secao-cta__nota {
    margin: var(--or-esp-5) 0 0;
    font-size: .8125rem;
    color: var(--cta-tinta-3);
}

/* Movimento reduzido — os DOIS gates do projeto. */
@media (prefers-reduced-motion: reduce) {
    .or-secao-cta__btn2, .or-secao-cta__canal { transition: none !important; }
}
html[data-or-rm="reduce"] .or-secao-cta__btn2,
html[data-or-rm="reduce"] .or-secao-cta__canal { transition: none !important; }

/* ═══════════════════════════════════════════════════════════════════════════════════════════════
   BLOCO 12 — SEÇÕES ESTRUTURADAS DA PÁGINA DE SERVIÇO — 02/09/2026
   ═══════════════════════════════════════════════════════════════════════════════════════════════

   Os componentes das seções que passaram a vir de `tbl_detalhes` (componente \OneRank\Detalhe,
   herdado do core): o problema · detalhe técnico do entregável · ficha técnica · como entregamos ·
   prova. A FAQ por serviço NÃO tem regra aqui, de propósito — reusa o `.quanto-faq-accordion`
   canônico do tema, e um seletor novo só para ela criaria uma segunda verdade sobre o mesmo
   componente.

   MESMA REGRA DE TINTA DO BLOCO 10.6: estas seções vivem sobre superfícies que FLIPAM (fundo base e
   bg-color-2 alternando), então toda cor sai de token (--texto-principal, --texto-secundario,
   --or-border, --marca-primaria-rgb) e nunca de literal rgba() calibrado para um tema só. O oposto
   vale para o BLOCO 10, que é escuro permanente — trocar os dois de lugar é o que produz texto
   invisível em um dos temas. */

/* ── 2. O problema (.or-dor) ────────────────────────────────────────────────────────────────────
   Compõe com .or-card + .or-card--claro (fundo/raio/sombra já no BLOCO 2); aqui entra só o arranjo
   interno. Altura total no grid para que três cards de textos desiguais fechem a linha alinhados. */
.or-dor {
    display: flex;
    flex-direction: column;
    gap: var(--or-esp-3);
    height: 100%;
}
.or-dor__ico {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border-radius: var(--or-radius-s, 10px);
    background: rgba(var(--marca-primaria-rgb, 11, 61, 145), .10);
    color: var(--marca-primaria);
}
.or-dor__ico svg { width: 22px; height: 22px; }
.or-dor__titulo {
    margin: 0;
    font-size: 1.125rem;
    line-height: 1.35;
    /* Tracking proporcional — nota do BLOCO 1 (~linha 224). Um <h3> reescalado para 18px herdaria
       os -2px crus que o vendor calibrou para 80px (-11% do corpo, letras colando umas nas outras). */
    letter-spacing: -.01em;
    color: var(--color-primary);
}
.or-dor__texto {
    margin: 0;
    line-height: 1.6;
    color: var(--texto-secundario);
}
.or-dor__texto p:last-child { margin-bottom: 0; }

/* ── 4. Detalhe técnico do entregável (.or-incluido__tecnico) ───────────────────────────────────
   A camada 2 da copy: o leigo lê a linha do entregável, quem é técnico abre o detalhe. <details>
   nativo — sem JS, indexável fechado, e o estado é anunciado sozinho por leitor de tela.

   O .or-incluido__corpo entrou porque o item deixou de ser um <p> solto: sem ele, o <details>
   ficaria irmão do ícone no flex e desceria para fora do prumo do texto. */
.or-incluido__corpo { min-width: 0; }
.or-incluido__tecnico { margin-top: var(--or-esp-2); }
.or-incluido__tecnico > summary {
    cursor: pointer;
    font-size: .8125rem;
    font-weight: 600;
    color: var(--texto-link, var(--marca-primaria));
    /* list-style:none + ::marker zerado cobrem os dois motores: o triângulo padrão brigaria com o
       check do item e colocaria dois marcadores na mesma linha. */
    list-style: none;
}
.or-incluido__tecnico > summary::-webkit-details-marker { display: none; }
.or-incluido__tecnico > summary::marker { content: ""; }
.or-incluido__tecnico > summary::after { content: " +"; font-weight: 700; }
.or-incluido__tecnico[open] > summary::after { content: " −"; }
.or-incluido__tecnico > summary:focus-visible {
    outline: 2px solid var(--or-dourado);
    outline-offset: 3px;
    border-radius: 2px;
}
.or-incluido__tecnico-corpo {
    margin-top: var(--or-esp-2);
    padding-left: var(--or-esp-3);
    border-left: 2px solid var(--or-border, rgba(0, 0, 0, .10));
    font-size: .9375rem;
    line-height: 1.6;
    color: var(--texto-secundario);
}
.or-incluido__tecnico-corpo p:last-child { margin-bottom: 0; }

/* ── 5. Ficha técnica (.or-ficha) ───────────────────────────────────────────────────────────────
   <dl> com uma <div> por par — o wrapper é o que permite a grade de duas colunas mantendo a
   semântica de lista de definição (dt/dd soltos numa grade perderiam o vínculo visual par a par).

   Grade 1fr/1.4fr em vez de duas colunas iguais: a chave é curta ("Acessibilidade"), o valor
   carrega número mais observação. Colunas iguais deixariam a esquerda com metade da linha vazia. */
.or-ficha {
    margin: 0;
    border-top: 1px solid var(--or-border, rgba(0, 0, 0, .10));
}
.or-ficha__linha {
    display: grid;
    grid-template-columns: 1fr 1.4fr;
    gap: var(--or-esp-4);
    padding: var(--or-esp-4) 0;
    border-bottom: 1px solid var(--or-border, rgba(0, 0, 0, .10));
}
.or-ficha__chave {
    margin: 0;
    font-weight: 600;
    line-height: 1.5;
    color: var(--texto-principal);
}
.or-ficha__valor {
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: var(--or-esp-1);
    line-height: 1.5;
    color: var(--texto-secundario);
}
.or-ficha__destaque { font-weight: 600; color: var(--texto-principal); }
.or-ficha__obs { font-size: .875rem; }

@media (max-width: 575.98px) {
    /* Uma coluna: com 1fr/1.4fr abaixo de 576px a chave quebra em três linhas e o par deixa de ler
       como par. Empilhado, o rótulo vira cabeçalho do valor — que é como se lê ficha no papel. */
    .or-ficha__linha { grid-template-columns: 1fr; gap: var(--or-esp-2); }
}

/* ── 6. Como entregamos (.or-etapa-servico) ─────────────────────────────────────────────────────
   <ol> real, numeração na marcação e não em ::before: o número existe para quem lê o HTML puro,
   inclusive as IAs que resumem a página. O list-style é zerado porque o marcador nativo ficaria ao
   lado do disco numerado — dois números para o mesmo passo. */
.or-etapa-servico-lista {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--or-esp-5);
}
.or-etapa-servico {
    display: flex;
    align-items: flex-start;
    gap: var(--or-esp-4);
}
.or-etapa-servico__num {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: rgba(var(--marca-primaria-rgb, 11, 61, 145), .10);
    color: var(--marca-primaria);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}
.or-etapa-servico__corpo { min-width: 0; }
/* Título e prazo na mesma linha quando cabe; no wrap o prazo desce alinhado ao título, e não
   pendurado na borda direita, que é o que um justify-content:space-between faria. */
.or-etapa-servico__cabeca {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: var(--or-esp-2) var(--or-esp-3);
    margin-bottom: var(--or-esp-2);
}
.or-etapa-servico__titulo {
    margin: 0;
    font-size: 1.125rem;
    line-height: 1.35;
    letter-spacing: -.01em;   /* tracking proporcional — nota do BLOCO 1 */
    color: var(--color-primary);
}
.or-etapa-servico__prazo {
    padding: 2px 10px;
    border-radius: 999px;
    background: rgba(var(--marca-primaria-rgb, 11, 61, 145), .10);
    color: var(--marca-primaria);
    font-size: .78rem;
    font-weight: 600;
    white-space: nowrap;
}
.or-etapa-servico__texto { line-height: 1.6; color: var(--texto-secundario); }
.or-etapa-servico__texto p:last-child { margin-bottom: 0; }

/* ── 8. Prova por entregável (.or-prova-entrega) ────────────────────────────────────────────────
   NÃO confundir com .or-prova-card (BLOCO 9), que é o card de prova social da home. Aqui a prova é
   o entregável do primeiro mês — o número é opcional e some quando não há número real a citar. */
.or-prova-entrega {
    display: flex;
    flex-direction: column;
    gap: var(--or-esp-2);
    height: 100%;
}
.or-prova-entrega__num {
    font-size: clamp(1.75rem, 1.4rem + 1.2vw, 2.25rem);
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: -.02em;
    color: var(--marca-primaria);
    font-variant-numeric: tabular-nums;
}
.or-prova-entrega__titulo {
    margin: 0;
    font-size: 1.125rem;
    line-height: 1.35;
    letter-spacing: -.01em;   /* tracking proporcional — nota do BLOCO 1 */
    color: var(--color-primary);
}
.or-prova-entrega__texto { line-height: 1.6; color: var(--texto-secundario); }
.or-prova-entrega__texto p:last-child { margin-bottom: 0; }

/* ═══════════════════════════════════════════════════════════════════════════════════════════════
   BLOCO 13 — REVITALIZAÇÃO DE LAYOUT DA PÁGINA DE SERVIÇO — 02/09/2026
   ═══════════════════════════════════════════════════════════════════════════════════════════════

   A revisão do dono aprovou o hero e o CTA e reprovou o miolo: "cru", "fora da padronização da
   box", sem animação. Este bloco é a parte visual da resposta — os componentes das seções novas
   (resumo de 30 segundos, blocos alternados de texto+imagem, "não é para você se…", grade
   comparativa de planos, índice lateral) e o reforço dos que já existiam (entregável, dor, etapa).

   MESMA REGRA DE TINTA DOS BLOCOS 10.6 E 12: tudo aqui vive sobre superfícies que FLIPAM (fundo
   base ↔ bg-color-2), então toda cor sai de token — --texto-principal, --texto-secundario,
   --or-border, rgba(var(--marca-primaria-rgb), α). Nenhum literal calibrado para um tema só.

   ESPAÇAMENTO pela escala --or-esp-* (piso --or-esp-5 entre blocos irmãos). O respiro EXTERNO das
   seções continua vindo das utilitárias do vendor, agora com o corte global de ritmo (BLOCO 1.5). */

/* ── Blocos alternados de texto + imagem (.or-servico-visual) ───────────────────────────────────
   A anatomia é a de #painel na home: duas colunas, imagem de um lado, texto do outro, invertendo
   a cada bloco. O respiro entre blocos vem do row-padding-top (rows irmãs), NUNCA de margem aqui —
   somar os dois dobraria o vão, que é o erro documentado no §Padrão de Espaçamento. */
.or-servico-visual__media { position: relative; }
.or-servico-visual__prosa > *:last-child { margin-bottom: 0; }
.or-servico-visual__titulo {
    font-size: var(--or-fs-h3, 1.5rem);
    font-weight: 700;
    line-height: 1.3;
    letter-spacing: -.01em;
    margin: 0 0 var(--or-esp-3);
    color: var(--texto-principal);
}
.or-servico-visual__legenda {
    margin: 0;
    font-size: var(--or-fs-lead, 1.0625rem);
    line-height: 1.65;
    color: var(--texto-secundario);
}
/* O bloco 1 empilha prosa, chips e CTA na mesma coluna: cada um traz a própria margem SUPERIOR
   (regime B do §Padrão de Espaçamento — o vendor zera margem de p/h*, então nada herda respiro). */
.or-servico-visual__tags { margin-top: var(--or-esp-5); }
.or-servico-visual__cta  { margin: var(--or-esp-5) 0 0; }
.or-servico-visual__video { border-radius: var(--or-radius-m, 12px); overflow: hidden; }

/* ── Não é para você se… (.or-naoe) ─────────────────────────────────────────────────────────────
   Lista, não grade de cards: são recusas, e recusa em card colorido lê como oferta. O traço à
   esquerda dá a leitura de "linha de corte" sem precisar de cor de alerta — vermelho aqui seria
   erro de tom, porque a seção é honestidade, não aviso de problema. */
.or-naoe-lista { list-style: none; margin: 0; padding: 0; }
.or-naoe {
    display: flex;
    align-items: flex-start;
    gap: var(--or-esp-4);
    padding: var(--or-esp-5) 0;
    border-bottom: 1px solid var(--or-border);
}
.or-naoe:first-child { border-top: 1px solid var(--or-border); }
.or-naoe__ico {
    display: inline-flex;
    width: 30px;
    height: 30px;
    flex: 0 0 30px;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: rgba(var(--marca-primaria-rgb), .08);
    color: var(--texto-secundario);
    margin-top: 2px;
}
.or-naoe__ico svg { width: 16px; height: 16px; }
.or-naoe__corpo { min-width: 0; }
.or-naoe__titulo {
    margin: 0;
    font-size: 1.0625rem;
    font-weight: 600;
    line-height: 1.45;
    color: var(--texto-principal);
}
.or-naoe__texto {
    margin-top: var(--or-esp-2);
    line-height: 1.6;
    color: var(--texto-secundario);
}
.or-naoe__texto > *:last-child { margin-bottom: 0; }

/* ── Entregável com peso (.or-incluido) ─────────────────────────────────────────────────────────
   Era uma linha de texto com um check de 15px numa grade de três colunas. Virou card (compõe com
   .or-card--claro + --hover), com o ícone em caixa e TRÊS camadas: o entregável, o que ele entrega
   (sempre visível, a camada nova) e o técnico recolhido. As regras do BLOCO 10.6 para .or-incluido
   ficam onde estão — aqui só o que mudou de arranjo. */
.or-incluido {
    display: flex;
    align-items: flex-start;
    gap: var(--or-esp-4);
    height: 100%;
}
.or-incluido__ico {
    display: inline-flex;
    width: 44px;
    height: 44px;
    flex: 0 0 44px;
    align-items: center;
    justify-content: center;
    border-radius: var(--or-radius-s, 10px);
    background: rgba(var(--marca-primaria-rgb), .10);
    color: var(--marca-primaria);
}
.or-incluido__ico svg { width: 21px; height: 21px; }
.or-incluido__titulo {
    margin: 0;
    font-size: 1.0625rem;
    font-weight: 700;
    line-height: 1.35;
    letter-spacing: -.01em;
    color: var(--texto-principal);
}
.or-incluido__valor {
    margin: var(--or-esp-2) 0 0;
    font-size: .9375rem;
    line-height: 1.55;
    color: var(--texto-secundario);
}

/* ── Ícone no lugar do número da etapa (.or-etapa-servico__num--icone) ──────────────────────────
   A seção `etapa` oferece ícone no admin desde que o componente nasceu, e o tema nunca renderizou.
   Quando há ícone ele ocupa o disco; sem ícone, o número continua — a sequência nunca fica sem
   marcador. Mesmo disco de 40px nos dois casos, para a coluna não desalinhar item a item. */
.or-etapa-servico__num--icone { color: var(--marca-primaria); }
.or-etapa-servico__num--icone svg { width: 19px; height: 19px; }

/* ── Grade comparativa de planos (.or-plano-grade) ──────────────────────────────────────────────
   A régua antiga (.or-plano-regua, BLOCO 10.6) respondia só "a partir de qual plano". Esta grade
   responde "o que muda em cada um" — e continua sendo a régua quando o operador não cadastrou o
   conteúdo por plano (o PHP escolhe; as duas convivem).

   A coluna de ENTRADA é a resposta visual à pergunta da seção, então ela é a única que ganha borda
   de marca e selo. As posteriores ficam inclusas mas discretas: destacar as três destruiria a
   informação, que é justamente onde o serviço COMEÇA. */
.or-plano-grade {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--or-esp-4);
    align-items: stretch;
}
.or-plano-grade__col {
    position: relative;
    display: flex;
    flex-direction: column;
    padding: var(--or-esp-6) var(--or-esp-5);
    border: 1px solid var(--or-border);
    border-radius: var(--or-radius-m, 12px);
    background: var(--fundo-card, #fff);
    opacity: .65;                       /* fora do plano: presente, mas claramente secundário */
    transition: transform .3s ease, box-shadow .3s ease;
}
.or-plano-grade__col.is-incluso { opacity: 1; }
.or-plano-grade__col.is-entrada {
    border-color: rgba(var(--marca-primaria-rgb), .40);
    background: rgba(var(--marca-primaria-rgb), .05);
    box-shadow: var(--or-shadow-1);
}
.or-plano-grade__col.is-incluso:hover { transform: translateY(-3px); box-shadow: var(--or-shadow-2); }
.or-plano-grade__selo {
    position: absolute;
    top: 0;
    left: var(--or-esp-5);
    transform: translateY(-50%);
    padding: 3px 12px;
    border-radius: 999px;
    background: var(--marca-primaria);
    color: #fff;                        /* sobre a cor da marca, não sobre superfície: não flipa */
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    white-space: nowrap;
}
.or-plano-grade__nome {
    margin: 0;
    font-size: 1.125rem;
    font-weight: 700;
    letter-spacing: -.01em;
    color: var(--texto-principal);
}
.or-plano-grade__preco {
    margin: var(--or-esp-1) 0 var(--or-esp-4);
    font-size: 1.375rem;
    font-weight: 700;
    line-height: 1.2;
    color: var(--marca-primaria);
    font-variant-numeric: tabular-nums;
}
.or-plano-grade__preco .t-small { font-size: .8125rem; font-weight: 500; color: var(--texto-secundario); }
.or-plano-grade__corpo { margin-top: auto; padding-top: var(--or-esp-3); border-top: 1px solid var(--or-border); }
.or-plano-grade__entrega,
.or-plano-grade__fora {
    display: flex;
    align-items: flex-start;
    gap: var(--or-esp-2);
    margin: 0;
    font-size: .9375rem;
    line-height: 1.5;
    font-weight: 600;
    color: var(--texto-principal);
}
.or-plano-grade__fora { font-weight: 500; color: var(--texto-secundario); }
.or-plano-grade__ico {
    display: inline-flex;
    flex: 0 0 auto;
    margin-top: 2px;
    color: var(--marca-primaria);
}
.or-plano-grade__fora .or-plano-grade__ico { color: var(--texto-secundario); }
.or-plano-grade__ico svg { width: 15px; height: 15px; }
.or-plano-grade__detalhe {
    margin-top: var(--or-esp-2);
    font-size: .875rem;
    line-height: 1.55;
    color: var(--texto-secundario);
}
.or-plano-grade__detalhe > *:last-child { margin-bottom: 0; }

@media (max-width: 767.98px) {
    /* Três colunas de 33% num telefone viram três colunas ilegíveis. Empilhar mantém a ordem de
       leitura (Presença → Destaque → Autoridade), que é a mesma da página de planos. */
    .or-plano-grade { grid-template-columns: 1fr; gap: var(--or-esp-5); }
    .or-plano-grade__col { opacity: 1; }   /* empilhado, opacidade baixa vira "quebrado", não "secundário" */
    .or-plano-grade__col:not(.is-incluso) .or-plano-grade__nome { color: var(--texto-secundario); }
}

@media (prefers-reduced-motion: reduce) {
    .or-plano-grade__col,
    .or-plano-grade__col.is-incluso:hover { transition: none; transform: none; }
}
html[data-or-rm="reduce"] .or-plano-grade__col,
html[data-or-rm="reduce"] .or-plano-grade__col.is-incluso:hover { transition: none; transform: none; }

/* ── Listas dentro de rich text das seções de serviço ───────────────────────────────────────────
   O DEFEITO que esta regra corrige: `Content::render()` permite `<ul>`, `<ol>` e `<li>`, e o
   operador usa isso. Nenhum dos containers de rich text criados em 02/09/2026 tinha regra de
   lista, então a `<ul>` interna caía no default do user-agent — `disc` mais `padding-inline-start:
   40px`. O resultado eram marcadores pretos aparecendo SOLTOS, deslocados para fora da caixa do
   componente, sem que nada no CSS explicasse de onde vinham.

   Por que a lista externa não protege: `.or-plano-grade { list-style: none }` vale para o próprio
   `<ul>` raiz. `list-style` é herdável, mas a regra `ul { list-style-type: disc }` da folha do
   agente casa a lista ANINHADA diretamente e vence o valor herdado.

   `.or-doc-body` já tinha o tratamento equivalente (BLOCO 1) — estes seis containers ficaram de
   fora quando nasceram. Especificidade 0,1,0 basta: o concorrente é o user-agent. */
.or-plano-grade__detalhe :is(ul, ol),
.or-naoe__texto :is(ul, ol),
.or-dor__texto :is(ul, ol),
.or-etapa-servico__texto :is(ul, ol),
.or-incluido__tecnico-corpo :is(ul, ol),
.or-prova-entrega__texto :is(ul, ol),
.or-servico-visual__legenda :is(ul, ol) {
    margin: var(--or-esp-2) 0 0;
    padding-left: var(--or-esp-5);
    list-style-position: outside;
}
.or-plano-grade__detalhe ul,
.or-naoe__texto ul,
.or-dor__texto ul,
.or-etapa-servico__texto ul,
.or-incluido__tecnico-corpo ul,
.or-prova-entrega__texto ul,
.or-servico-visual__legenda ul { list-style-type: disc; }
.or-plano-grade__detalhe li,
.or-naoe__texto li,
.or-dor__texto li,
.or-etapa-servico__texto li,
.or-incluido__tecnico-corpo li,
.or-prova-entrega__texto li,
.or-servico-visual__legenda li { margin-bottom: var(--or-esp-1); }

/* ── H1 do hero comercial: quebra, hifenização e teto de largura ────────────────────────────────
   O DEFEITO: `.or-hero-interno--comercial .or-hero-interno__title` usa `--or-fs-display`
   (clamp até 88px) sem nenhuma proteção de quebra — não tinha `overflow-wrap`, `hyphens`,
   `max-width` nem `text-wrap`. Título longo em pt-BR ("Google Meu Negócio e busca local")
   estourava a caixa, e o `overflow-hidden` do <section> só CORTAVA o excesso na borda: o sintoma
   era texto decepado, não barra de rolagem, e por isso passou despercebido.

   As receitas já existiam no arquivo, aplicadas a outros seletores — `text-wrap:balance` no
   BLOCO 1.5, `max-width` na variante --editorial. Nenhuma alcançava este seletor. Aqui elas
   chegam — SEM a hifenização automática que o BLOCO 5 usa em prosa justificada (ver nota abaixo).

   ⚠️ CORREÇÃO 03/09/2026 (achado ao vivo, print do dono): `hyphens:auto` estava ligado aqui desde
   a origem deste bloco, sob a tese de que era "rede de segurança para palavra longa em pt-BR" — o
   comentário anterior já registrava um sintoma da MESMA causa ("torre de 4 linhas com hifenização
   agressiva: 'Presença e autori-dade digital…'"), e a correção de então foi só afrouxar o
   max-width, mantendo a hifenização. Ela voltou a quebrar palavra comum ao meio ("per-/gunta" em
   /presenca-em-ia) — não é caso extremo de palavra longa, é qualquer palavra que caia perto da
   borda da coluna. O pedido agora é categórico: quando a linha quebra, a palavra inteira vai para
   a linha nova, nunca hifenizada. `hyphens:none` explícito (não omitir a propriedade — sem ela o
   navegador cai no default do <html lang="pt-BR">, que PERMITE hifenização automática em Chrome/
   Edge/Safari recentes). `text-wrap:balance` continua: ele só reparte pontos de quebra em ESPAÇOS,
   nunca precisou de hífen para funcionar. */
.or-hero-interno--comercial .or-hero-interno__title {
    /* Sem teto próprio (era 18ch): quem limita a largura agora é a COLUNA do hero — que passou a
       col-lg-10/col-xl-8 em 03/09/2026 (padronização pedida pelo dono). */
    max-width: 100%;
    overflow-wrap: break-word; /* rede só p/ token sem espaço que não caiba nem sozinho — não gera hífen */
    -webkit-hyphens: none;
    hyphens: none;
    text-wrap: balance;
    line-height: 1.04;
}
@media (max-width: 991.98px) {
    /* Empilhado, a coluna é a tela inteira: 18ch quebraria cedo demais e criaria uma torre de
       palavras soltas. O limite passa a ser a própria caixa. */
    .or-hero-interno--comercial .or-hero-interno__title { max-width: none; line-height: 1.1; }
}

/* ── Grade de planos: o selo não colide, e as três divisórias alinham ───────────────────────────
   Dois ajustes vindos da revisão:

   1. O selo "Entra aqui" é absoluto com `translateY(-50%)` sobre a borda superior do card. Sem
      folga no topo ele encostava no nome do plano. O padding extra é aplicado SÓ na coluna que
      tem selo — dar folga às três desalinharia o conteúdo das outras duas.
   2. As três colunas tinham o cabeçalho (nome + preço) com alturas diferentes quando um preço
      ocupava mais dígitos, e a divisória interna saía em três alturas. `min-height` comum no
      cabeçalho resolve sem recorrer a grid de subgrade (que o Safari só suporta desde 16). */
.or-plano-grade__col.is-entrada { padding-top: calc(var(--or-esp-6) + var(--or-esp-3)); }
.or-plano-grade__cabeca {
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    min-height: 4.75rem;
}

/* ── Dark: pílulas e acentos das seções de serviço ──────────────────────────────────────────────
   ACHADO na medição de 02/09/2026, e o defeito é MAIS ANTIGO que o rail que o revelou.

   `.or-tag` em repouso usa `color: var(--color-primary)` — o neutro ESCURO do vendor, que não
   flipa. No tema escuro isso é texto rgb(26,35,50) sobre superfície #15171c: contraste perto de
   1:1, ilegível. O bloco dark existente cobre `.or-tag:hover` e `.or-tag.active`, mas nunca o
   estado de repouso — o que passou despercebido porque, até aqui, `.or-tag` aparecia em grupos de
   três ou quatro chips. O rail de navegação da página de serviço tem dez, e o problema ficou
   impossível de não ver. Corrigir na classe base conserta junto os chips do hero e os filtros de
   /portfolio e /produtos, que sofriam do mesmo mal em silêncio.

   O preço em destaque segue a mesma regra de sempre: todo uso de var(--marca-primaria) como COR DE
   TEXTO precisa virar var(--or-brand-accent) no escuro — o azul cru tem ~1,7:1 contra as
   superfícies escuras. Só FUNDO pode continuar usando a marca crua. */
[data-bs-theme="dark"] .or-tag {
    color: var(--texto-principal);
    border-color: var(--or-border, rgba(255, 255, 255, .18));
}
[data-bs-theme="dark"] .or-plano-grade__preco,
[data-bs-theme="dark"] .or-plano-grade__ico {
    color: var(--or-brand-accent);
}


/* ── Acordeão da FAQ (.or-faq-svc) ──────────────────────────────────────────────────────────────
   O DEFEITO que motivou o componente: `.quanto-faq-accordion .accordion-button` do vendor declara
   `font-size: inherit` (style.css:5047), então o botão herda o tamanho da TAG do cabeçalho. Com
   `<h3>` isso são 80px (style.css:128) — as perguntas saíam em escala de display, duas linhas cada.
   A home escapava usando `<h6>`, o que conserta o tamanho e quebra a hierarquia de headings
   (h2 → h6, pulando dois níveis). Aqui o componente tem tamanho PRÓPRIO, o que libera o `<h3>`
   semanticamente correto e não depende mais de qual tag alguém escolher amanhã.

   A correção de tamanho abaixo alcança também `.quanto-faq-accordion`, e com isso conserta a página
   /faq — que tinha o mesmo defeito, pela mesma causa, sem ninguém ter notado.

   Cor por token: a seção alterna entre fundo base e bg-color-2, então nada de literal. */
.quanto-faq-accordion .accordion-button,
.or-faq-svc .accordion-button {
    font-size: clamp(1.0625rem, 1rem + .35vw, 1.25rem);
    font-weight: 600;
    line-height: 1.45;
    letter-spacing: -.01em;
}

/* Token do componente numa linha própria: o guard tema_quanto_test coleta definições com
   `^\s*--x:` (âncora de início de linha), então a forma compacta `.sel { --x: v; }` era lida como
   USO sem definição e reprovava a asserção de cobertura de var(). Zero efeito visual. */
.or-faq-svc {
    --or-faq-sinal: 34px;
}
.or-faq-svc__item {
    background: transparent;
    border: none;
    border-top: 1px solid var(--or-border, rgba(0, 0, 0, .08));
}
.or-faq-svc__item:last-child { border-bottom: 1px solid var(--or-border, rgba(0, 0, 0, .08)); }
.or-faq-svc__header { margin: 0; }

.or-faq-svc__botao {
    display: flex;
    align-items: flex-start;
    gap: var(--or-esp-5);
    width: 100%;
    padding: var(--or-esp-5) 0;
    background: transparent;
    border: none;
    box-shadow: none;
    text-align: left;
    color: var(--texto-principal);
    transition: color .25s ease;
}
/* O vendor desenha um chevron no `::after` esticado na altura do botão: numa pergunta de duas
   linhas ele flutua no meio do nada. O indicador aqui é um <span> de tamanho fixo, alinhado ao
   topo — acompanha a primeira linha, que é onde o olho está. */
.or-faq-svc__botao::after { display: none !important; }
.or-faq-svc__botao:not(.collapsed) { background: transparent; box-shadow: none; color: var(--marca-primaria); }
.or-faq-svc__botao:hover { color: var(--marca-primaria); }
.or-faq-svc__botao:focus { box-shadow: none; }
.or-faq-svc__botao:focus-visible { outline: 2px solid var(--or-dourado); outline-offset: 3px; }

/* ── DARK MODE — achado ao vivo, 08/09/2026, medindo /faq depois de reusar este componente ──────
   `color: var(--texto-principal)` (regra acima) e `color: var(--marca-primaria)` (linha acima)
   NUNCA tiveram override de dark — gap pré-existente, não introduzido por este componente ter
   ganho um segundo consumidor (/faq). Medido: texto do botão fechado saía #1a2332 (quase preto)
   sobre #15171c (fundo dark do body) — contraste ~1,3:1, muito abaixo do 4.5:1 do WCAG AA, e o
   estado aberto (var(--marca-primaria), azul #0B3D91 — não theme-aware) teria o mesmo problema.
   Especificidade (0,2,0), maior que a base (0,1,0) — vence sem !important. `--or-brand-accent` é o
   mesmo token que `.or-blog-plano`/heroes já usam pra marca no escuro (clareada por color-mix). */
[data-bs-theme="dark"] .or-faq-svc__botao { color: var(--texto-principal); }
[data-bs-theme="dark"] .or-faq-svc__botao:not(.collapsed),
[data-bs-theme="dark"] .or-faq-svc__botao:hover { color: var(--or-brand-accent); }

.or-faq-svc__pergunta { flex: 1 1 auto; min-width: 0; }

/* O sinal é desenhado com dois traços em ::before/::after: o horizontal fica, o vertical gira 90°
   e some ao abrir — "+" vira "−" sem trocar glifo, sem fonte de ícone e sem imagem. */
.or-faq-svc__sinal {
    position: relative;
    flex: 0 0 var(--or-faq-sinal);
    width: var(--or-faq-sinal);
    height: var(--or-faq-sinal);
    margin-top: 1px;
    border-radius: 50%;
    border: 1px solid var(--or-border, rgba(0, 0, 0, .12));
    transition: background-color .25s ease, border-color .25s ease;
}
.or-faq-svc__sinal::before,
.or-faq-svc__sinal::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 13px;
    height: 1.5px;
    background: currentColor;
    transform: translate(-50%, -50%);
    transition: transform .25s ease, opacity .25s ease;
}
.or-faq-svc__sinal::after { transform: translate(-50%, -50%) rotate(90deg); }
.or-faq-svc__botao:not(.collapsed) .or-faq-svc__sinal {
    background: rgba(var(--marca-primaria-rgb), .10);
    border-color: rgba(var(--marca-primaria-rgb), .30);
}
.or-faq-svc__botao:not(.collapsed) .or-faq-svc__sinal::after { transform: translate(-50%, -50%) rotate(0deg); opacity: 0; }
.or-faq-svc__botao:hover .or-faq-svc__sinal { border-color: rgba(var(--marca-primaria-rgb), .35); }

.or-faq-svc__corpo {
    padding: 0 calc(var(--or-faq-sinal) + var(--or-esp-5)) var(--or-esp-6) 0;
    max-width: 68ch;                        /* medida de leitura, como o resto da prosa do site */
    line-height: 1.7;
    color: var(--texto-secundario);
}
.or-faq-svc__corpo > *:last-child { margin-bottom: 0; }
/* Mesmo tratamento de lista dos outros containers de rich text da página — sem ele a <ul> aninhada
   cai no disc + padding-inline-start:40px do user-agent e o marcador escapa da caixa. */
.or-faq-svc__corpo :is(ul, ol) { margin: var(--or-esp-3) 0; padding-left: var(--or-esp-5); }
.or-faq-svc__corpo ul { list-style-type: disc; }
.or-faq-svc__corpo li { margin-bottom: var(--or-esp-1); }

@media (max-width: 575.98px) {
    .or-faq-svc { --or-faq-sinal: 28px; }
    .or-faq-svc__botao { gap: var(--or-esp-4); padding: var(--or-esp-4) 0; }
    .or-faq-svc__corpo { padding-right: 0; padding-bottom: var(--or-esp-5); }
}

@media (prefers-reduced-motion: reduce) {
    .or-faq-svc__botao,
    .or-faq-svc__sinal,
    .or-faq-svc__sinal::before,
    .or-faq-svc__sinal::after { transition: none; }
}
html[data-or-rm="reduce"] .or-faq-svc__botao,
html[data-or-rm="reduce"] .or-faq-svc__sinal,
html[data-or-rm="reduce"] .or-faq-svc__sinal::before,
html[data-or-rm="reduce"] .or-faq-svc__sinal::after { transition: none; }

/* ── O link "Ver o que cada plano inclui" em row própria ────────────────────────────────────────
   Zera a margem que `.or-plano-link` traz: agora o respiro vem do `row-padding-top` da row que o
   segura. Regime A do §Padrão de Espaçamento — quem tem o gap do pai não traz margem própria na
   mesma direção, senão soma dobrado. */
.or-plano-link-row { margin-top: 0; }

/* ── A faixa do hero: um token só governa topo e base ────────────────────────────────────────────
   MEDIDO em 02/09/2026 (Playwright, 14 larguras de 390 a 2560px, print do dono em 1600px). O
   `padding-top` do hero paga por DUAS coisas ao mesmo tempo: (a) livrar o `.quanto-header`, que é
   `position: fixed` e portanto está FORA do fluxo — sem essa folga o conteúdo nasce ATRÁS de uma
   faixa branca opaca; e (b) dar o respiro entre a faixa e o primeiro conteúdo. O `padding-bottom`
   paga só por (b) — do outro lado. O vendor escreve o topo como um absoluto por breakpoint
   (200/160/150/130px, style.css:1907-1922 e 2322-2334) e o fork tinha escrito a base com OUTRO
   raciocínio (o vão até a seção seguinte). Dois números, duas contas — e a faixa que o visitante
   vê (ele nunca vê o header, que é opaco) saía torta: o print do dono mostrou 88px acima do
   breadcrumb contra 32px abaixo do subtítulo, em 1600px.

   A CORREÇÃO faz UM token — `--or-hero-ar`, o respiro de design — governar os dois lados. O topo
   soma `--or-header-h` (a altura REAL do header, publicada por `_chrome-topo.php` via
   ResizeObserver — mesmo padrão de `--or-fab-lift` do banner LGPD) porque precisa livrar uma barra
   fixa que a base não tem. O valor de `--or-hero-ar` é o MESMO dos dois lados, então a faixa nasce
   simétrica por construção — não por dois números calibrados para coincidir.

   RESPIRO: 32px (`--or-esp-6`) em >= 992px — o valor que já tinha sido calibrado para o fecho
   (32 + 72 da seção seguinte = 104px de vão até o conteúdo, ~1,4× o vão entre seções, a proporção
   certa pra uma troca de contexto maior). Empilhado, 24px (`--or-esp-5`, o piso entre blocos
   irmãos da escala) — a tela é menor e a seção seguinte já contribui com os 65px do vendor.

   Vale para as QUATRO variantes, inclusive a `--doc`: a faixa é igual em todas agora — o que torna
   a `--doc` "a mais quieta" é só o título em `--or-fs-secao-compacta`, não mais um respiro próprio
   (o override que ela tinha, `--or-hero-ar: var(--or-esp-7)`, foi removido: não fazia sentido a
   variante mais quieta ter uma faixa MAIOR que as outras três).

   ── A ALTURA REAL DO HEADER, por faixa (medida após a navegação trocar para `d-xl-*`, ver bloco
   "Navegação: hambúrguer até o breakpoint xl" em `_chrome-topo.php`):

     < 992px ....... 101px  (`.sticky-wrap{padding:10px 0}` só nesta faixa, style.css:1045-1049)
     992–1199px .... 81px   (só hambúrguer + CTA; SEM os 90px do menu completo — não existe mais
                     quebra de 2 linhas: a navegação completa só aparece a partir de 1200px)
     >= 1200px ..... 90px   (menu completo em 1 linha; `.custom-container` já tem 1500px+)

   Os FALLBACKS abaixo são essas alturas medidas, para o caso de o JS não rodar — com o JS ativo o
   valor é sempre o real (publicado pelo ResizeObserver) e nenhum fallback é usado. */
:root {
    --or-header-h: 101px;             /* barra mobile (logo + hambúrguer) */
    --or-hero-ar:  var(--or-esp-5);   /* 24px empilhado */
}
@media (min-width: 992px) {
    :root { --or-header-h: 81px; --or-hero-ar: var(--or-esp-6); }   /* 32px — só hambúrguer + CTA */
}
@media (min-width: 1200px) {
    :root { --or-header-h: 90px; }                                  /* menu completo em 1 linha */
}

/* Dois seletores, uma conta só — o hero das internas (_hero-interno.php, as 4 variantes) e o da
   home (_home-hero, .quanto-hero4-section) tinham o MESMO defeito, nas MESMAS faixas.
   (0,2,0) para vencer os absolutos do vendor (0,1,0) sem depender da ordem do cascade. */
.or-pg .or-hero-interno,
.or-pg .or-home-hero { padding-top: calc(var(--or-header-h) + var(--or-hero-ar)); }

/* A base do hero interno usa o MESMO `--or-hero-ar` do topo — é o que faz a faixa nascer simétrica
   sem precisar calibrar dois números pra coincidir. (A home tem padding-bottom PRÓPRIO, hardcoded
   — bloco `.or-home-hero`, acima — porque a faixa dela não é uma tarja de cor fechada como a das
   internas: funde com o degradê da seção seguinte por design, sempre foi assim.) */
.or-pg .or-hero-interno.section-padding-bottom { padding-bottom: var(--or-hero-ar); }


/* ═══════════════════════════════════════════════════════════════════════════════════════════════
   SUPERFÍCIES CORE — revestimento do <style> inline do core (03/09/2026)
   ═══════════════════════════════════════════════════════════════════════════════════════════════
   Três componentes vivem em site/includes/ (CORE, que o fork NUNCA edita — invariante zero-diff da
   \OneRank\CoreSync): o popup, a barra de comunicados e o banner de cookies. Os três carregam o
   próprio <style> inline, com paleta genérica da plataforma (#1e1e2d, #7986cb, #55556a) e
   vocabulário Canvas — e apareciam sobre o tema como peça de outro site. O banner de cookies é a
   PRIMEIRA coisa que todo visitante vê.

   POR QUE +1 DE ESPECIFICIDADE EM TUDO. O <style> desses partials é emitido no <body>, DEPOIS do
   <link> deste arquivo. Em empate de especificidade, quem vem depois vence — então `#or-lgpd-banner
   button` (0,1,0,1) do core ganharia de um `.or-lgpd-btn-primary` (0,0,1,0) daqui. Prefixar com
   `body` resolve sem !important e sem tocar no core.

   O QUE NÃO SE MEXE: nada de posicionamento (`position:fixed`, `z-index`, o `--or-fab-lift` que o
   banner publica para empurrar a pilha de FABs) e nada de comportamento. Isto aqui é revestimento
   — cor, tipografia, raio e sombra. Mexer no resto quebraria contrato de core no primeiro sync.
   ═══════════════════════════════════════════════════════════════════════════════════════════════ */

/* ── 1 · Banner de consentimento de cookies ────────────────────────────────────────────────────
   O core já pinta o botão primário com var(--marca-primaria) — isso estava certo. O que destoava
   era todo o resto: fundo roxo-acinzentado fixo, botões de contorno cinza-azulado e o link de
   preferências num lilás que não existe na paleta. */
body #or-lgpd-banner {
    background: var(--or-ink-deep, #05132b);
    box-shadow: 0 -2px 24px rgba(0, 0, 0, .28);
    font-family: inherit;
}
body #or-lgpd-banner .or-lgpd-wrap { padding: var(--or-esp-4) var(--or-esp-6); }
body #or-lgpd-banner p { color: rgba(255, 255, 255, .82); font-size: .9rem; }
body #or-lgpd-banner a { color: #fff; text-decoration-thickness: 1px; text-underline-offset: 3px; }
body #or-lgpd-banner button {
    border-radius: var(--or-radius-pill, 40px);
    padding: .6rem 1.35rem;
    font-size: .875rem;
    transition: background-color .18s ease, border-color .18s ease, color .18s ease, opacity .18s ease;
}
body #or-lgpd-banner .or-lgpd-btn-primary {
    background: var(--marca-primaria);
    border-color: var(--marca-primaria);
    color: #fff;
}
body #or-lgpd-banner .or-lgpd-btn-primary:hover { filter: brightness(1.12); opacity: 1; }
body #or-lgpd-banner .or-lgpd-btn-ghost {
    background: transparent;
    color: rgba(255, 255, 255, .78);
    border-color: rgba(255, 255, 255, .28);
}
body #or-lgpd-banner .or-lgpd-btn-ghost:hover {
    background: rgba(255, 255, 255, .08);
    border-color: rgba(255, 255, 255, .5);
    color: #fff;
    opacity: 1;
}
body #or-lgpd-banner .or-lgpd-btn-link { color: rgba(255, 255, 255, .72); }
body #or-lgpd-banner .or-lgpd-btn-link:hover { color: #fff; opacity: 1; }

/* Painel de categorias (Personalizar) — mesma tinta do banner, contraste conferido em AA. */
body #or-lgpd-panel { border-top-color: rgba(255, 255, 255, .16); }
body #or-lgpd-panel h2 { font-size: .95rem; color: #fff; }
body #or-lgpd-panel .or-lgpd-cat { border-bottom-color: rgba(255, 255, 255, .1); }
body #or-lgpd-panel .or-lgpd-cat label { color: #fff; }
body #or-lgpd-panel .or-lgpd-cat small { color: rgba(255, 255, 255, .62); }
body #or-lgpd-panel input[type=checkbox] { accent-color: var(--marca-primaria); }

/* ── 2 · Popup promocional ─────────────────────────────────────────────────────────────────────
   Só renderiza com popup vigente cadastrado (zero byte sem isso), mas quando renderiza é um modal
   Bootstrap cru sobre um tema que não tem nada de cru. */
body #or-popup .modal-content {
    border-radius: var(--or-radius-l, 20px);
    box-shadow: var(--or-shadow-2, 0 24px 60px rgba(5, 19, 43, .28));
    background: var(--or-surface, #fff);
    color: var(--or-text, inherit);
}
body #or-popup .or-popup-body { padding: var(--or-esp-6); }
body #or-popup .or-popup-conteudo { font-size: 1rem; line-height: 1.65; }
body #or-popup .btn-close {
    background-color: rgba(255, 255, 255, .92);
    box-shadow: 0 2px 10px rgba(5, 19, 43, .18);
}
/* O botão de ação traz background-color e border-color INLINE (site/includes/popup.php) — só
   !important venceria, e não vale gastar isso: a cor inline já é var(--marca-primaria), que é
   justamente a que queremos. Ajustamos o que o inline não trava (forma, peso, hover por filtro). */
body #or-popup .or-popup-body .button {
    border-radius: var(--or-radius-pill, 40px);
    font-weight: 600;
    padding: .7rem 1.6rem;
    font-size: 1rem;
    line-height: 1.2;
    /* AZUL SOBRE AZUL (achado na prova visual, 03/09/2026): o .button do vendor define
       `color` como a cor primária do template, e o popup do core traz só o BACKGROUND inline
       (var(--marca-primaria)). Resultado: rótulo azul-marca sobre fundo azul-marca — o botão
       renderizava como uma pílula sólida sem texto legível. */
    color: #fff;
    transition: filter .18s ease, transform .18s ease;
}
body #or-popup .or-popup-body .button:hover { filter: brightness(.92); transform: translateY(-1px); color: #fff; }

/* TIPOGRAFIA DO CONTEÚDO (mesmo achado): o corpo do popup passa por Content::render e fica FORA
   do escopo `.or-pg`, onde vive a escala tipográfica do tema. Os headings caíam no h1-h6 cru do
   vendor, dimensionado para título de seção de página inteira — um <h3> dentro do modal
   renderizava a 80px, ocupando o popup todo. Escala própria, proporcional à caixa. */
body #or-popup .or-popup-conteudo h1,
body #or-popup .or-popup-conteudo h2,
body #or-popup .or-popup-conteudo h3 { font-size: 1.5rem; line-height: 1.25; margin-bottom: var(--or-esp-3); }
body #or-popup .or-popup-conteudo h4,
body #or-popup .or-popup-conteudo h5,
body #or-popup .or-popup-conteudo h6 { font-size: 1.15rem; line-height: 1.3; margin-bottom: var(--or-esp-2); }
body #or-popup .or-popup-conteudo p { font-size: 1rem; line-height: 1.6; margin-bottom: var(--or-esp-3); }
body #or-popup .or-popup-conteudo > :last-child { margin-bottom: 0; }

/* ── 3 · Barra de comunicados ──────────────────────────────────────────────────────────────────
   O core pinta a faixa com as utilitárias .text-bg-{cor} do Bootstrap, cujas cores não pertencem a
   nenhuma paleta de marca (o azul do "info" não é o azul da OneRank). Como a barra fica no topo,
   acima do header, ela é a primeira cor que a página mostra. Aqui as cinco variantes passam a
   derivar da marca — mantendo a distinção semântica entre elas, que é o ponto da cor. */
body .or-comunicado-bar {
    padding: var(--or-esp-2) 0;
    font-size: .875rem;
    letter-spacing: .01em;
}
body .or-comunicado-bar .or-com-msg a { text-underline-offset: 3px; }
body .or-comunicado-bar.text-bg-primary,
body .or-comunicado-bar.text-bg-info {
    /* !important obrigatório: .text-bg-* do Bootstrap (plugins/bootstrap.min.css) declara
       `background-color: RGBA(var(--bs-primary-rgb)) !important` — sem isso o azul padrão do
       framework, que não é o azul da marca, venceria a linha inteira. */
    background: var(--marca-primaria) !important;
    color: #fff !important;
}
body .or-comunicado-bar.text-bg-success {
    background: #1F7A4D !important;
    color: #fff !important;
}
body .or-comunicado-bar.text-bg-warning {
    background: var(--or-dourado, #E8B53D) !important;
    color: var(--or-ink-deep, #05132b) !important;
}
body .or-comunicado-bar.text-bg-danger {
    background: #A23B2C !important;
    color: #fff !important;
}


/* ═══════════════════════════════════════════════════════════════════════════════════════════════
   BLOCO 14 — DIÁLOGO DE ALERTA (SweetAlert2) THEME-AWARE — 03/09/2026
   ═══════════════════════════════════════════════════════════════════════════════════════════════

   ACHADO MEDIDO, não suposto: no modo escuro o título do diálogo saía em #E6E8EC sobre o fundo
   BRANCO do próprio popup — contraste 1,23:1. Praticamente invisível, e a mensagem de erro de um
   formulário é o pior lugar do site para um texto sumir.

   A causa não estava no SweetAlert. O .swal2-title é um <h2>, e o site no escuro pinta TODO
   h1–h6 com var(--or-text) — regra legítima, que existe justamente para o conteúdo da página
   funcionar no dark. Só que o popup do SweetAlert não segue o tema: ele traz fundo branco fixo
   embutido no próprio bundle. Texto de tema escuro sobre superfície que ficou clara.

   Duas regras aplicavam a cor, uma delas em site/assets/css/or-dark.css, que é CORE e não se
   edita daqui (invariante zero-diff). Consertar "tirando a cor do h2" seria mexer no lugar errado
   de qualquer forma: o defeito é a SUPERFÍCIE não ter acompanhado o tema, não o texto. Então é a
   superfície que passa a acompanhar — os mesmos tokens que o resto do site usa.

   Vale para o site inteiro, não só /contato: o Swal é o canal de erro e confirmação de todo
   formulário da plataforma. O defeito estava em qualquer um deles, no escuro.

   O botão de confirmação também sai do roxo #7066E0 (padrão do bundle, que não é cor de ninguém)
   para a cor da marca do cliente — var(--marca-primaria), como todo o resto do site. */
[data-bs-theme="dark"] .swal2-popup {
    background: var(--or-surface);
    color: var(--or-text);
    border: 1px solid var(--or-border);
}
[data-bs-theme="dark"] .swal2-title,
[data-bs-theme="dark"] .swal2-html-container {
    color: var(--or-text);
}
[data-bs-theme="dark"] .swal2-close {
    color: var(--or-text-muted);
}
/* O botão herda a marca em AMBOS os temas — o roxo do bundle não pertence a nenhuma identidade. */
.swal2-styled.swal2-confirm {
    background-color: var(--marca-primaria) !important;
}
.swal2-styled.swal2-confirm:focus-visible {
    outline: 2px solid var(--marca-primaria);
    outline-offset: 2px;
    box-shadow: none;
}


/* ═══════════════════════════════════════════════════════════════════════════════════════════════
   BLOCO 15 — HIERARQUIA DE TÍTULOS DA HOME — 03/09/2026
   ═══════════════════════════════════════════════════════════════════════════════════════════════

   A home saltava de h2 para h4, para h5 e para h6 conforme o card, e em #planos a hierarquia
   estava INVERTIDA: o preço em <h3> acima do nome do plano em <h5>. Quem navega por heading ouvia
   "R$249/mês" anunciado como seção e "Presença" como um subitem dele. Duas seções não tinham
   heading nenhum. Nada disso aparecia na tela — só para quem lê a estrutura, que é exatamente
   quem este site precisa convencer.

   ── POR QUE ESTE BLOCO EXISTE, EM VEZ DE SÓ TROCAR AS TAGS ──────────────────────────────────
   Porque no tema Quanto a TAG carrega o tamanho. As classes destes cards (.process-title,
   .pricing-title, .client-name, .line-clamp-*, .accordion-header) não declaram font-size: o h5
   valia 28px porque era h5. Trocar a tag sem trazer a métrica junto explodiria os títulos para os
   ~60px do h2/h3 do vendor — foi assim que os cards de nível transbordaram dias atrás.

   Os valores abaixo foram MEDIDOS na página renderizada antes da troca (getComputedStyle), não
   estimados. O objetivo declarado é zero diferença visual: só a árvore de headings muda.

   E o tracking vem junto, sempre. O vendor amarra letter-spacing à tag em px absolutos (h5 nasce
   com -0.28px, h6 com -0.24px), então um heading promovido sem tracking próprio herda o valor
   calibrado para outro corpo. É a armadilha do BLOCO 1 (~linha 224) — a mesma que acabou de ser
   encontrada, já instalada, em .or-segmento-card. */

/* #dor — o card era h5 sob o h2 da seção (28px/600, tracking -0.28px ≡ -.01em) */
.or-pg .process-title {
    font-size: 28px;
    font-weight: 600;
    line-height: 1.35;
    letter-spacing: -.01em;
}

/* #planos — o nome do plano assume o papel de título do card, na métrica que o h5 tinha */
.or-pg .pricing-title {
    font-size: 28px;
    font-weight: 600;
    line-height: 1.35;
    letter-spacing: -.01em;
}

/* #depoimentos — nome de quem depõe */
.or-pg .client-name {
    font-size: 28px;
    font-weight: 600;
    line-height: 1.35;
    letter-spacing: -.01em;
}

/* #portfolio e #blog — títulos de card. O .line-clamp-* corta a altura, nunca definiu o corpo. */
.or-pg .quanto-project-content .line-clamp-1,
.or-pg .quanto-blog-content .line-clamp-2 {
    font-size: 28px;
    font-weight: 600;
    line-height: 1.35;
    letter-spacing: -.01em;
}

/* #faqs — a pergunta desceu de h6 para h4 (o grupo subiu para h3), mantendo os 24px do h6.
   O seletor mira só a home: em /sobre, /contato e /faq o acordeão já nasce em h3, com o
   .or-faq-sobre cuidando da métrica. */
.or-pg .or-faq-grupo .accordion-header {
    font-size: 24px;
    font-weight: 600;
    line-height: 1.41;
    letter-spacing: -.01em;
    margin: 0;
}

/* #planos — o preço deixou de ser <h3> e virou <p>, perdendo o font-weight que a tag entregava.
   A classe .pricing sempre declarou o tamanho (52px) e nunca o peso, porque não precisava. */
.or-pg .pricing {
    font-weight: 600;
}

/* Menu mobile — dados de contato. Eram <h6> (métrica medida: 18px/600, tracking -0.24px ≡ -.013em)
   e viraram <p>, porque endereço e telefone não titulam nada. A métrica vem para cá para que a
   troca de tag não mude um pixel. */
.or-sidebar-info {
    font-size: 18px;
    font-weight: 600;
    line-height: 1.22;
    letter-spacing: -.013em;
    margin: 0;
}

/* ═══════════════════════════════════════════════════════════════════════════════════════════════
   BLOCO 16 — PILHA DE FABs: consolidação mobile + auto-esconder no scroll + ocultar sob o LGPD
   (03/09/2026)
   ═══════════════════════════════════════════════════════════════════════════════════════════════
   Medição real (Playwright, 8 rotas, 360px): a pilha ESQUERDA de FABs (site/includes/fab-stack.php,
   CORE) cobre texto/controle em 94,5% das posições de scroll testadas. Com acessibilidade + tema
   dedicado + idioma + cookies (pós-consentimento) ligados ao mesmo tempo, ela empilha até 4
   círculos — até 224px de banda fixa, sempre por cima do conteúdo, contra 12px de padding lateral
   do container em mobile. A pilha DIREITA (WhatsApp + voltar ao topo, no máximo 2 itens) não
   mostrou o mesmo problema e fica como está — as regras só-esquerda usam `.or-fab-mais*`; as que
   valem para as duas pilhas usam `.or-fab-stack` puro.

   fab-stack.php é CORE (invariante zero-diff — o fork nunca edita). A ESTRUTURA (criar o wrapper,
   mover os FABs para dentro dele, ligar/desligar as classes abaixo) mora no JS de
   site/_template/pages/_scripts.php, logo depois do FAB de preferências de cookies; aqui só a PELE
   (tamanho/cor/transição) e as regras de estado que dependem de especificidade.

   POR QUE opacity SÓ NO CONTÊINER MAS visibility/pointer-events TAMBÉM NOS DESCENDENTES (`*`):
   opacity composita pai×filho sem escapatória — um filho com opacity:1 dentro de um pai opacity:0
   continua invisível, então repetir a regra nos descendentes só arriscaria opacidade em dobro
   (0,35 × 0,35, mais escuro que o previsto) se algum dia um filho também declarar a própria
   opacity. visibility é diferente: um filho PODE se religar com visibility:visible mesmo dentro de
   um ancestral hidden — é assim, aliás, que a própria Camada 1 revela o mini-menu — e
   pointer-events é uma propriedade herdada comum, sem blindagem contra a regra do próprio filho.
   Sem o `*`, o mini-menu da Camada 1, se estivesse aberto no exato momento em que a página começa
   a rolar (Camada 2) ou o LGPD aparece (Camada 3), escaparia do esconder: a regra
   `.or-fab-mais-menu.or-fab-aberto` (abaixo) tem 2 classes; `body.<estado> .or-fab-stack *` tem 2
   classes + 1 elemento — já o bastante para vencer sem !important. */

/* ── Espelho de --or-fab-gap/--or-fab-size — só para o guard estático, NÃO é a fonte de verdade ──
   tests/tema_quanto_test.php (assert 7, CORE) reprova var(--x) usada em custom.css sem definição
   visível em custom.css/style.css/or-dark.css/Colors — ele não lê site/includes/fab-stack.php, que
   é onde estas duas variáveis REALMENTE nascem (:root + a media query ≤575.98px que troca 20px/48px
   por 16px/44px). _scripts.php já usa esses mesmos tokens (o CSS do #or-cookie-fab) há tempos sem
   o guard notar, porque ele nunca varreu aquele arquivo — aqui, dentro de custom.css, é a primeira
   vez que aparecem, e o guard tem razão em pedir uma definição que ele consiga ler.
   Este :root SEMPRE perde a cascata: o <link> deste arquivo é emitido no <head>, e o <style>
   inline de fab-stack.php só existe no <body>, depois — em empate de especificidade (ambos miram
   :root), quem vem depois no documento vence. Ou seja, os valores abaixo nunca chegam a valer em
   runtime; existem só para o assert 7 encontrar uma definição e não reprovar um token que, na
   prática, sempre está presente (a pilha só existe quando há FAB, e fab-stack.php sempre emite o
   próprio <style> junto). Se os valores do core mudarem um dia, este espelho fica desatualizado
   sem quebrar nada — é fallback estático, não comportamento. */
:root {
    --or-fab-gap: 20px;
    --or-fab-size: 48px;
}
@media (max-width: 575.98px) {
    :root {
        --or-fab-gap: 16px;
        --or-fab-size: 44px;
    }
}

/* ── Camada 1 — trigger "mais opções" + mini-menu (≤991.98px; estrutura no JS) ───────────────── */
.or-fab-mais-menu {
    display: flex;
    flex-direction: column-reverse;
    align-items: flex-start;
    gap: var(--or-fab-gap, 20px);
    /* Os FABs originais viram NETOS da pilha ao entrar aqui (netos, não filhos diretos dela) — a
       regra do core `.or-fab-stack > *{pointer-events:auto}` só alcança filhos DIRETOS. Sem esta
       linha eles herdariam pointer-events:none do container e ficariam clicáveis-mas-mortos. */
    pointer-events: auto;
}
.or-fab-mais {
    display: none; /* some no desktop — a media query abaixo é a ÚNICA fonte de display:flex dele */
    width: var(--or-fab-size, 48px);
    height: var(--or-fab-size, 48px);
    padding: 0;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    border: 1px solid rgba(0, 0, 0, .14);
    background: #fff;
    color: #1a2332;
    box-shadow: 0 4px 14px rgba(0, 0, 0, .18);
    cursor: pointer;
    transition: background .2s ease, color .2s ease, border-color .2s ease, transform .15s ease, box-shadow .2s ease;
}
.or-fab-mais:hover { transform: translateY(-2px); box-shadow: 0 6px 20px rgba(0, 0, 0, .25); }
.or-fab-mais[aria-expanded="true"] { background: var(--marca-primaria, #0B3D91); border-color: var(--marca-primaria, #0B3D91); color: #fff; }
.or-fab-mais .or-icon { width: 22px; height: 22px; }
[data-bs-theme="dark"] .or-fab-mais { background: #1c1f26; color: #e6e8ec; border-color: rgba(255, 255, 255, .16); }
/* :focus-visible não precisa de regra própria — or-a11y.css (F0) já aplica o anel de foco
   estrutural a QUALQUER <button> do site (html body :is(...button...):focus-visible). */

@media (max-width: 991.98px) {
    .or-fab-mais { display: flex; }
    .or-fab-mais-menu {
        opacity: 0;
        visibility: hidden;
        pointer-events: none;
        transition: opacity .18s ease, visibility 0s linear .18s;
    }
    .or-fab-mais-menu.or-fab-aberto {
        opacity: 1;
        visibility: visible;
        pointer-events: auto;
        transition: opacity .18s ease, visibility 0s linear 0s;
    }
}

/* ── Camada 2 — esmaecer durante o scroll ativo (≤991.98px, as DUAS pilhas) ──────────────────── */
.or-fab-stack { transition: opacity .15s ease, visibility 0s linear 0s; }
@media (max-width: 991.98px) {
    body.or-fab-scroll-ativo .or-fab-stack { opacity: .35; }
    body.or-fab-scroll-ativo .or-fab-stack,
    body.or-fab-scroll-ativo .or-fab-stack * { pointer-events: none; }
}

/* ── Camada 3 — ocultar a pilha inteira sob o banner/painel LGPD (todos os viewports) ────────── */
body.or-lgpd-aberto .or-fab-stack {
    opacity: 0;
    transition: opacity .15s ease, visibility 0s linear .15s;
}
body.or-lgpd-aberto .or-fab-stack,
body.or-lgpd-aberto .or-fab-stack * { visibility: hidden; pointer-events: none; }
/* Esta regra de opacity e a da Camada 2 empatam em especificidade (0,2,1 cada) — em empate, quem
   vem DEPOIS no arquivo vence. Por isso a Camada 3 está escrita depois: se as duas coincidirem (o
   visitante rola a página com o banner LGPD aberto por baixo — nenhum dos dois trava scroll),
   esconder tem que ganhar de esmaecer. Não reordene os dois blocos sem preservar isso. */

@media (prefers-reduced-motion: reduce) {
    .or-fab-mais-menu, .or-fab-mais, .or-fab-stack { transition: none; }
    .or-fab-mais:hover { transform: none; }
}
html[data-or-rm="reduce"] .or-fab-mais-menu,
html[data-or-rm="reduce"] .or-fab-mais,
html[data-or-rm="reduce"] .or-fab-stack { transition: none; }
html[data-or-rm="reduce"] .or-fab-mais:hover { transform: none; }

/* ═══════════════════════════════════════════════════════════════════════════════════════════════
   BLOCO 17 — RESÍDUO GEOMÉTRICO: encolher + esmaecer em repouso (03/09/2026)
   ═══════════════════════════════════════════════════════════════════════════════════════════════
   O BLOCO 16 reduziu a colisão medida de 94,5% para ~78% (varredura mecânica, 8 rotas, 360px) —
   melhora real, não eliminação. A causa remanescente é a mesma de sempre: um ÚNICO círculo de
   44px também não cabe nos 12px de margem do container. Consolidar 4 botões em 1 encolheu a
   BANDA VERTICAL, mas não faz esse botão sozinho parar de intersectar texto.

   Duas mitigações, combinadas, pedidas explicitamente depois de eu relatar o resíduo com números:

   1. ENCOLHER o círculo VISÍVEL (44px → 28px) sem encolher a ÁREA DE TOQUE (continua 44px, WCAG
      2.5.5) — a área clicável fica com um "anel" de folga em volta do círculo pintado, do jeito
      que o próprio texto por baixo já usava antes.
   2. ESMAECER em repouso (opacidade .6, não .35 da Camada 2 — ali é "rolando", aqui é "parado sem
      uso"; mais forte deixaria o ícone difícil de achar) — o texto por trás fica LEGÍVEL através
      do círculo, não só menor. Ao passar o mouse, focar via teclado, tocar, ou quando o próprio
      botão está com o painel aberto (aria-expanded), volta a 44px/opacidade 1 — o afordance de
      "isto é clicável" nunca desaparece, só descansa quando ninguém está olhando.

   POR QUE SÓ TRÊS FABS (gatilho "mais opções", voltar-ao-topo, WhatsApp), NÃO TODOS: são os três
   que ficam PASSIVAMENTE visíveis o tempo todo, fora de qualquer disclosure — os causadores reais
   do resíduo medido (o trigger é o único remanescente da pilha esquerda consolidada; os dois da
   direita nunca foram tocados pela Camada 1). Os FABs individuais de acessibilidade/tema/idioma só
   ficam "soltos" (visíveis sem serem um item de menu já aberto) em ≥992px, onde cada um replica um
   ESTADO PRÓPRIO (aria-expanded muda a cor de fundo pra `--a11y-accent`/marca-primária) que este
   bloco teria que duplicar cor a cor, tema a tema, sem necessidade real — no mobile, que é o pedido
   original, eles já nascem invisíveis dentro do menu fechado (Camada 1). Ganham só a Camada 2
   (esmaecer-por-CSS de repouso, sem encolher) no BLOCO seguinte, mais barata e sem esse risco.

   POR QUE ::before EM VEZ DE `background` DIRETO NO BOTÃO: os três têm superfícies diferentes
   (branco/escuro por tema, ou verde fixo do WhatsApp) e um deles (WhatsApp) já expõe a própria cor
   via `style=""` INLINE em fab-stack.php (CORE) — só `!important` vence estilo inline. Um
   pseudo-elemento próprio, absolutamente posicionado e centralizado (`inset:0;margin:auto`), pinta
   o círculo pequeno SEM tocar no `background` real do botão nem replicar a lógica de cada um — o
   botão original continua exatamente como era, só com o próprio fundo tornado transparente (que
   PRECISA da mesma técnica de especificidade/!important pra vencer, então a cor precisa ser
   reproduzida aqui mesmo, uma vez, e não por herança).

   POR QUE NÃO `transform:scale()`: encolhe a CAIXA pintada, mas o hit-test do clique/toque segue a
   geometria PÓS-transformação em todo navegador moderno — encolheria a área de toque junto,
   exatamente o problema que este bloco existe para evitar (WCAG 2.5.5, alvo ≥44px).

   ⚠️ Custo de manutenção aceito conscientemente: as cores abaixo são CÓPIAS das que já existem em
   fab-stack.php/or-dark.css/locale-panel.php (CORE) — se um dia essas telas mudarem de cor, este
   bloco fica desatualizado até alguém notar. Mesmo padrão que .or-cookie-fab e .or-fab-mais (BLOCO
   16) já assumem: cada FAB pequeno duplica sua própria paleta em vez de compartilhar uma variável
   — é a convenção já em uso neste arquivo, não uma exceção nova. */

.or-fab-mais,
.or-gototop-fab {
    position: relative; /* ancora o ::before — inofensivo em qualquer largura, fica fora do media */
}

/* ⚠️ ACHADO AO VIVO EM 04/09/2026 (print do dono: "os botões da direita perderam caracterização,
   estão muito menores no desktop do que os da esquerda"). Todo o encolhimento abaixo NASCEU pensado
   só pro mobile — a prosa do BLOCO 17 é explícita ("no mobile, que é o pedido original", "resíduo
   medido... 360px") — mas foi escrito SEM @media nenhum, então rodava em QUALQUER largura,
   inclusive desktop. Fix: mesmo breakpoint das Camadas 1 e 2 deste arquivo (≤991.98px) — o "gatilho
   mais opções" nem aparece acima disso (display:none).
   ⚠️ SEGUNDO ACHADO AO VIVO, mesmo dia: o WhatsApp SAIU deste bloco inteiro (não só do desktop). O
   dono pediu explicitamente "deixe apenas o WhatsApp, sem opacidade, para que somente ele fique
   vivo na tela" — é o canal de conversão principal, e a decisão de produto é ele NUNCA esmaecer/
   encolher, nem no mobile (aceitando de propósito abrir mão da mitigação de colisão original do
   BLOCO 17 só pra este botão). "Voltar ao topo" continua no shrink mobile E ganha o esmaecer-sem-
   encolher no desktop, abaixo, espelhando literalmente o tratamento que os FABs individuais de
   acessibilidade/tema/idioma já tinham (mesma regra, "SÓ esmaecer, sem encolher"). */
@media (max-width: 991.98px) {
.or-fab-mais::before,
.or-gototop-fab::before {
    content: '';
    position: absolute;
    inset: 0;
    margin: auto;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    box-shadow: 0 4px 14px rgba(0, 0, 0, .18);
    opacity: .6;
    transition: width .18s ease, height .18s ease, opacity .18s ease;
    pointer-events: none; /* decorativo — quem recebe o toque/clique é sempre o botão de 44px */
}
/* Estado ATIVO (qualquer um dos dois): círculo volta a 44px, opacidade plena. O botão real por
   baixo já tinha os próprios estilos de :hover/:focus-visible (transform, box-shadow, cor) — este
   bloco só cuida do TAMANHO/OPACIDADE do círculo, nunca duplica o que já funcionava. */
.or-fab-mais:hover::before, .or-fab-mais:focus-visible::before, .or-fab-mais:active::before,
.or-fab-mais[aria-expanded="true"]::before,
.or-gototop-fab:hover::before, .or-gototop-fab:focus-visible::before, .or-gototop-fab:active::before {
    width: 44px;
    height: 44px;
    opacity: 1;
}

/* O botão real perde o próprio fundo em repouso — quem pinta agora é o ::before, do tamanho certo.
   body-prefix (não !important) vence por especificidade a regra de mesmo-nome do core (fab-stack.php
   e or-dark.css são <style>/<link> que vêm DEPOIS deste arquivo no documento — em empate de
   especificidade eles venceriam por ordem; +1 elemento no seletor resolve sem !important). */
body .or-fab-mais, body .or-gototop-fab {
    background: transparent;
    border-color: transparent;
    box-shadow: none;
}
body .or-fab-mais::before { background: #fff; }
[data-bs-theme="dark"] body .or-fab-mais::before { background: #1c1f26; }
body .or-fab-mais[aria-expanded="true"]::before { background: var(--marca-primaria, #0B3D91); }

body .or-gototop-fab::before { background: #fff; }
[data-bs-theme="dark"] body .or-gototop-fab::before { background: #1c1f26; }
} /* fim @media (max-width: 991.98px) — BLOCO 17, mobile-only, SEM o WhatsApp */

@media (prefers-reduced-motion: reduce) {
    .or-fab-mais::before, .or-gototop-fab::before { transition: none; }
}
html[data-or-rm="reduce"] .or-fab-mais::before,
html[data-or-rm="reduce"] .or-gototop-fab::before { transition: none; }

/* "Voltar ao topo" no desktop — SÓ esmaecer, sem encolher, mesmo tratamento e mesma frase dos FABs
   individuais de acessibilidade/tema/idioma logo abaixo. O WhatsApp fica de fora desta regra (e de
   toda a Camada 2/BLOCO 17 acima) de propósito — ver o comentário no topo do bloco mobile. */
@media (min-width: 992px) {
    .or-gototop-fab { opacity: .6; transition: opacity .18s ease; }
    .or-gototop-fab:hover, .or-gototop-fab:focus-visible, .or-gototop-fab:active { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
    .or-gototop-fab { transition: none; }
}
html[data-or-rm="reduce"] .or-gototop-fab { transition: none; }

/* ── FABs individuais de acessibilidade/tema/idioma — SÓ esmaecer, sem encolher (≥992px, quando a
   Camada 1 os deixa "soltos" dentro de #or-fab-mais-menu sempre visível). No mobile fechado eles já
   nascem opacity:0/visibility:hidden (BLOCO 16) — esta regra não tem efeito ali, e é por isso que
   não precisa de exceção pro `.or-fab-aberto`: quando o menu ABRE no mobile, o item já não bate
   mais com ":not(.or-fab-aberto) >", some da seleção sozinho. */
#or-fab-mais-menu:not(.or-fab-aberto) > a,
#or-fab-mais-menu:not(.or-fab-aberto) > button {
    opacity: .6;
    transition: opacity .18s ease;
}
#or-fab-mais-menu:not(.or-fab-aberto) > a:hover,
#or-fab-mais-menu:not(.or-fab-aberto) > a:focus-visible,
#or-fab-mais-menu:not(.or-fab-aberto) > button:hover,
#or-fab-mais-menu:not(.or-fab-aberto) > button:focus-visible,
#or-fab-mais-menu:not(.or-fab-aberto) > [aria-expanded="true"] {
    opacity: 1;
}
@media (prefers-reduced-motion: reduce) {
    #or-fab-mais-menu:not(.or-fab-aberto) > a,
    #or-fab-mais-menu:not(.or-fab-aberto) > button { transition: none; }
}
html[data-or-rm="reduce"] #or-fab-mais-menu:not(.or-fab-aberto) > a,
html[data-or-rm="reduce"] #or-fab-mais-menu:not(.or-fab-aberto) > button { transition: none; }


/* ═══════════════════════════════════════════════════════════════════════════════════════════════
   BLOCO 18 — /planos remodelada: base comum, ativação, contratação e o comparativo de cotas
   (04/09/2026)
   ═══════════════════════════════════════════════════════════════════════════════════════════════
   Três blocos novos e um componente reaproveitado. ZERO token novo: raio, sombra, espaçamento e
   cor saem todos do Bloco 0 — a página inteira é composta com o que já existe.

   POR QUE A TABELA MUDOU DE COMPONENTE: ver a nota em .or-planos-table (removida). Resumo: quatro
   colunas com `overflow-x: auto` e sem coluna fixa fazem o leitor perder a referência da linha ao
   arrastar. .or-comparativo empilha e rotula cada célula pelo data-label. */

/* ── O comparativo desta página: 4 colunas em vez das 2 da /presenca-em-ia ────────────────────
   O componente base já resolve estrutura, empilhamento mobile e dark. Aqui só entram as
   diferenças de uma matriz de PREÇO: as colunas de plano são estreitas e centradas (valores curtos
   como "2 por mês", "Sim", "—" alinhados à esquerda ficam soltos numa coluna larga), e a primeira
   coluna não pode encolher a ponto de quebrar "Monitoramento de citações em IA" em quatro linhas. */
.or-comparativo--planos { table-layout: fixed; }
.or-comparativo--planos thead th:not(:first-child),
.or-comparativo--planos tbody td { text-align: center; }
.or-comparativo--planos thead th:first-child,
.or-comparativo--planos tbody th { width: 34%; }
.or-comparativo--planos tbody td { font-variant-numeric: tabular-nums; }

/* A coluna do plano recomendado. Tinta de marca a 8% em vez de fundo chapado: o zebrado do vendor
   e o dark continuam legíveis por baixo. Mesma receita que a tabela anterior usava. */
.or-comparativo thead th.or-comparativo__recomendada,
.or-comparativo tbody td.or-comparativo__recomendada {
    background: color-mix(in srgb, var(--or-dourado) 8%, transparent);
}
.or-comparativo thead th.or-comparativo__recomendada { border-top: 3px solid var(--or-dourado); }

@media (max-width: 767.98px) {
    /* Empilhado, cada célula é uma linha "rótulo → valor": centrar deixaria o valor flutuando
       longe do próprio rótulo. E o destaque de coluna perde o sentido quando não há colunas —
       a marcação visual passa a ser o data-label, que já nomeia o plano. */
    .or-comparativo--planos thead th:not(:first-child),
    .or-comparativo--planos tbody td { text-align: left; }
    .or-comparativo--planos tbody th { width: auto; }
    .or-comparativo tbody td.or-comparativo__recomendada { background: transparent; }
}

/* ── BLOCO 2 — a base comum ──────────────────────────────────────────────────────────────────
   Duas colunas: o argumento à esquerda, a lista à direita. A lista usa o mesmo item com ícone de
   confirmação dos cards de plano (.custom-ul + or_planos_check), então não há componente novo —
   só a grade de duas colunas que a lista ganha quando há espaço, para não virar uma coluna de
   nove linhas ao lado de um parágrafo de quatro. */
.or-base-lista { margin: 0; }
/* .custom-ul li do vendor não traz margem nenhuma — os itens só se separavam pela própria altura
   de linha (medido ao vivo: 0 de gap real). Achado ao vivo em 04/09/2026 (print do dono na lista da
   Ativação, mesmo defeito aqui por herdar a mesma .custom-ul base). Token "linha↔linha de um card". */
.or-base-lista li { margin-bottom: var(--or-esp-3); }

/* ── ITEM DE LISTA COM CHECK — respiro e alinhamento (05/09/2026) ─────────────────────────────
   Print 7 do dono: "um espaçamento maior e mais intuitivo entre a frase e o check, isso em TODOS
   os lugares dessa página que referenciam esse modelo". Medido antes da correção:

       display .......... list-item   (não flex — o <svg> era só um inline no meio do texto)
       gap .............. normal      (zero: o ícone encostava na primeira letra)
       svg margin-right . 0px

   Além do aperto, havia um defeito de alinhamento que só aparece com texto de 2+ linhas: sem
   flex, a segunda linha voltava para baixo do ÍCONE em vez de alinhar com a primeira letra —
   a lista perdia a coluna de texto e ficava visualmente irregular (é o que se vê no print).

   `align-items: flex-start` (não center): com item de 2-3 linhas, centralizar joga o check para o
   meio do parágrafo, longe do começo da frase que ele marca. `flex-shrink: 0` impede o ícone de
   ser espremido quando o texto é longo. `margin-top` de 2px acerta a altura ótica do check contra
   a primeira linha (o glifo do ✓ não preenche a caixa de 16px inteira).

   Cobre as TRÊS listas do modelo na página, como pedido — a da base, a da ativação e a dos cards
   de preço — via seletor único, para as três não voltarem a divergir por edição isolada.

   ⚠️ ESPECIFICIDADE nos cards de preço: o vendor declara `.quanto-pricing-box .pricing-list ul li`
   (style.css:5235) com `align-items: center`, peso (0,3,1). Uma primeira tentativa com
   `.pricing-list .custom-ul li` (0,2,1) PERDIA a cascata em silêncio — medido ao vivo: o flex e o
   gap aplicavam nas outras duas listas e nos cards continuava `align-items: center; gap: 10px`.
   Por isso o seletor abaixo repete a cadeia do vendor: empata em (0,3,1) e vence por ordem
   (custom.css carrega depois). */
.or-base-lista li,
.or-ativacao__lista li,
.quanto-pricing-box .pricing-list ul li {
    display: flex;
    align-items: flex-start;
    gap: var(--or-esp-3);
}
.or-base-lista li > svg,
.or-ativacao__lista li > svg,
.quanto-pricing-box .pricing-list ul li > svg {
    flex-shrink: 0;
    margin-top: 2px;
}
@media (min-width: 576px) {
    .or-base-lista { display: grid; grid-template-columns: 1fr 1fr; column-gap: var(--or-esp-5); }
}
@media (min-width: 992px) {
    .or-base-lista { grid-template-columns: 1fr; }
}
@media (min-width: 1200px) {
    .or-base-lista { grid-template-columns: 1fr 1fr; }
}
/* A nota de fecho fica destacada do parágrafo acima: é ela que responde "então o que muda entre
   os planos?", a pergunta que este bloco levanta ao dizer que a base é igual para todos. */
.or-base-nota {
    margin-top: var(--or-esp-5);
    padding-left: var(--or-esp-4);
    border-left: 3px solid var(--or-dourado);
}

/* ── BLOCO 3 — a ativação ────────────────────────────────────────────────────────────────────
   Cartão próprio, e não um quarto card de plano nem uma nota de rodapé: a ativação não compete
   com os planos (não é uma alternativa a eles) e não é detalhe (é obrigatória para todo cliente
   novo). O peso visual vem do valor grande, na mesma escala do preço dos planos. */
.or-ativacao { padding: var(--or-esp-6); }
.or-ativacao__titulo {
    /* Mesma métrica do .pricing-title dos cards — este h2 é irmão visual daqueles títulos, não do
       h2 de abertura de seção (que é o dobro disso e faria o bloco competir com o comparativo). */
    font-size: 28px;
    font-weight: 600;
    line-height: 1.35;
    letter-spacing: -.01em;
    margin-bottom: var(--or-esp-3);
}
.or-ativacao__preco {
    font-size: var(--or-fs-secao-compacta);
    font-weight: 600;
    line-height: 1.1;
    letter-spacing: -.02em;
    color: var(--color-primary);
    margin-bottom: var(--or-esp-4);
}
.or-ativacao__periodo { font-size: 16px; font-weight: 500; opacity: .55; margin-left: var(--or-esp-2); }
.or-ativacao__porque {
    margin-top: var(--or-esp-4);
    padding-left: var(--or-esp-4);
    border-left: 3px solid var(--or-dourado);
}
.or-ativacao__lista { margin: 0; }
/* Mesmo achado do .or-base-lista acima (BLOCO 2) — print do dono: "precisa dar mais espaçamento
   também para essa lista". Medido ao vivo: 0 de margem própria entre os <li>, 32px de "gap" medido
   era só a altura da linha de texto. */
.or-ativacao__lista li { margin-bottom: var(--or-esp-3); }
@media (max-width: 991.98px) {
    /* Empilhado, a lista precisa do respiro que o gutter da row dava entre as colunas. Regime B do
       padrão de espaçamento: quem traz a margem é o bloco de baixo. */
    .or-ativacao__lista { margin-top: var(--or-esp-5); }
    .or-ativacao { padding: var(--or-esp-5); }
}

/* ── BLOCO 4 — altura uniforme e campos novos do card de plano ───────────────────────────────
   MEDIDO em 1440px antes da correção: as três COLUNAS já vinham com 921px (o `align-items:
   stretch` implícito da .row do Bootstrap faz isso sozinho), mas os CARTÕES dentro delas mediam
   783 / 880 / 921 — cada um encolhendo até o próprio conteúdo. O resultado é o defeito que a
   página de preços menos pode ter: três caixas de alturas diferentes, com os botões de ação em
   três linhas distintas, sugerindo que o plano mais alto "tem mais" por ser fisicamente maior em
   vez de por entregar mais.

   Escopado a .or-pg--planos de propósito. O MESMO componente aparece na âncora #planos da home,
   onde é teaser, não comparação — e nivelar altura lá é uma mudança visual numa página que não faz
   parte deste trabalho. A classe vem do mainOpen() em _chrome-topo.php ('or-pg or-pg--<slug>'). */
.or-pg--planos .quanto-pricing-box {
    height: 100%;
    display: flex;
    flex-direction: column;
}
/* Empurra o botão para a base do cartão: sem isto, altura uniforme só cria um vazio no fim dos
   cartões mais curtos, com as três chamadas de ação ainda desalinhadas entre si. */
.or-pg--planos .quanto-pricing-box .quanto-link-btn { margin-top: auto; }
/* A nota do plano recomendado — só o cartão com selo a tem, então ela não pode ser o que empurra
   o botão: é o botão que carrega o `margin-top:auto`, e a nota vem acima dele no markup. */
.or-pg--planos .or-pricing-nota { margin-top: var(--or-esp-4); margin-bottom: var(--or-esp-4); }

/* O compromisso vem logo abaixo do preço porque é parte da mesma informação: "R$ 799/mês" sem
   "6 meses de compromisso" é meia resposta. */
.or-pricing-compromisso {
    margin-top: calc(var(--or-esp-2) * -1);
    margin-bottom: var(--or-esp-4);
    font-size: .875rem;
    font-weight: 600;
    color: var(--texto-secundario);
}
.or-pricing-descricao { margin-bottom: var(--or-esp-4); }
/* O que o plano NÃO inclui. Fora da lista de propósito — com ícone de confirmação ao lado, "não
   inclui produção de conteúdo mensal" lê como se incluísse. Aqui a marcação é tipográfica (itálico
   + hairline acima), sem cor de erro: não é um alerta, é um limite declarado. */
.or-pricing-limite {
    margin-top: var(--or-esp-4);
    padding-top: var(--or-esp-3);
    border-top: 1px solid var(--color-1);
    font-size: .875rem;
    font-style: italic;
    color: var(--texto-secundario);
}
[data-bs-theme="dark"] .or-pricing-limite { border-top-color: var(--or-border); }
/* O hover do card do vendor troca a cor de todo o texto para escuro (custom.css ~2226). Estes dois
   nasceram depois e não estavam na lista — sem isto, some no hover. */
.quanto-pricing-box:hover .or-pricing-compromisso,
.quanto-pricing-box:hover .or-pricing-limite { color: var(--color-primary); }

/* ── BLOCO 7 — como funciona a contratação ───────────────────────────────────────────────────
   Grade de cartões irmãos, altura própria. auto-fit com minmax garante que os três caibam lado a
   lado no desktop e empilhem sozinhos sem media query — e que o bloco continue correto se o
   operador esvaziar o título de um dos três (o array filtra, e sobram dois). */
.or-contrato-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: var(--or-esp-5);
}
/* Altura explícita, e não herdada do `align-items: stretch` que o grid dá de graça: no dia em que
   alguém trocar o container para flex (ou acrescentar `align-items` para alinhar outra coisa), os
   três cartões passariam a ter alturas diferentes conforme o texto de cada um — e o bloco que
   explica fidelidade e multa é o último lugar do site onde se quer um desalinhamento chamando
   atenção. */
.or-contrato-item { height: 100%; }
.or-contrato-item__titulo {
    /* Métrica do h5 do vendor, que é o papel visual deste título dentro do cartão. Declarada aqui
       porque a tag é <h3> — o nível certo na árvore, já que estes são subtítulos do h2 da seção. */
    font-size: 22px;
    font-weight: 600;
    line-height: 1.35;
    letter-spacing: -.01em;
    margin-bottom: var(--or-esp-3);
}

/* BLOCO 8 (pergunta do acordeão <h6>→<h3>) e BLOCO 8.1 (grade de 2 colunas) removidos em 04/09/2026
   junto com o bloco de FAQ de /planos (decisão do dono) — mesmas regras .or-planos-faq* removidas
   no BLOCO 4, mais acima neste arquivo. */

/* ── BLOCO 9 — a escada de posicionamento, ANTES de qualquer preço (D8/2.2, 08/09/2026) ─────────
   As mesmas 3 promessas que abrem cada card ali embaixo (.pricing-info) aparecem aqui lado a lado,
   como caminho — não como tabela. Reusa .or-card/.or-card--claro (fundo/raio/sombra já definidos
   no BLOCO 2 deste arquivo); aqui só o arranjo dos 3 itens. .t-muted já é dark-safe (var(--or-text-
   muted)) — sem override próprio necessário para a promessa. */
.or-escada-item {
    height: 100%;
    text-align: center;
}
.or-escada-item__numero {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: var(--marca-primaria);
    color: var(--color-white);
    font-size: var(--or-fs-small);
    font-weight: 700;
    margin-bottom: var(--or-esp-3);
}
.or-escada-item__nome {
    font-size: var(--or-fs-card);
    font-weight: 600;
    margin-bottom: var(--or-esp-2);
}
.or-escada-item__promessa { font-weight: 500; margin-bottom: 0; }


/* ── BLOCO 10 — COLUNA LATERAL FIXA: o pin do GSAP vai num WRAPPER, nunca na coluna (08/09/2026) ──
   ⚠️ CORREÇÃO DE BUG SITEWIDE, medida ao vivo em 6 páginas.

   O DEFEITO: o tema declarava `.gsap-sticky` na própria COLUNA de grid, e o main.js:838-852 faz
   `ScrollTrigger.create({ pin: element, pinSpacing: false })`. Pinar um elemento faz o GSAP
   envolvê-lo num `<div class="pin-spacer">` — e esse wrapper NÃO herda a classe `col-lg-4`. O filho
   direto da `.row` deixava de ser uma coluna do Bootstrap e virava um bloco com `width` fixo em px
   + `flex-basis:auto` (estilo inline do GSAP).

   Medido em /faq/<slug> a 2560px: o spacer recebia `width:535px` e a `.col-lg-8` irmã calculava
   66,66% de 1604px = 1069px. 535+1069 = exatamente 100% da row — o subpixel do gutter estourava o
   flex-wrap e jogava a resposta para a linha DE BAIXO (`top:920` contra `top:429` do menu). Em
   1440px sobrava folga e o defeito passava despercebido; por isso ficou meses no ar.

   A CORREÇÃO é de MARKUP, não de CSS: `.gsap-sticky` passou para um `<div>` wrapper DENTRO da
   coluna. O `.pin-spacer` nasce dentro da `.col-lg-4`, que continua sendo uma coluna íntegra do
   Bootstrap — o grid não tem como quebrar, em nenhuma largura.

   ⚠️ POR QUE NÃO `position: sticky` (tentado e REVERTIDO nesta mesma rodada): o site roda
   ScrollSmoother, que rola o conteúdo por `transform` no `#smooth-content`. Um ancestral com
   `transform` cria containing block, e o sticky passa a se referenciar a ele em vez da viewport —
   medido: o elemento ficava com offset CONSTANTE de +114px (o valor do `top`) e nunca grudava, nem
   no scroll 0 nem em scroll 600. `position:sticky` e scroll suavizado por transform são
   incompatíveis; o pin do GSAP existe justamente porque é da mesma família do ScrollSmoother e
   conversa com ele. Não trocar de volta.

   O pin em si é criado pelo BLOCO 9 do or-tema-motion.js (não pelo main.js do vendor — a classe é
   própria do fork de propósito, para não receber dois pins). Aqui fica só o que é visual. */
.or-indice-fixo {
    /* O elemento entra e sai de `position:fixed` a cada pin/unpin do ScrollTrigger. Sem uma largura
       declarada ele herdaria a da viewport ao ser fixado (fixed tira do fluxo e a largura deixa de
       vir da coluna), e o índice "explodiria" para a tela inteira no primeiro scroll. */
    width: 100%;
}
@media (max-width: 991.98px) {
    /* Abaixo de lg as colunas empilham e o bloco 9 nem cria o pin — o wrapper vira um <div>
       transparente. Margem zerada para não somar respiro ao que a coluna já dá. */
    .or-indice-fixo { margin-bottom: 0; }
}

/* ── BLOCO 11 — 404 sem buraco (08/09/2026, print do dono) ──────────────────────────────────────
   `.error-section` chegava com `min-vh-100` e NENHUMA regra própria (nem no fork, nem no
   style.css do vendor — grep confirmado): `display:block`, conteúdo grudado no topo e o resto da
   viewport vazio. Medido: seção 919px, conteúdo 412px, **435px de vazio** antes do rodapé.
   Centraliza no eixo vertical mantendo o min-vh-100 (a 404 continua ocupando a tela, que é o
   comportamento desejado — o que não se quer é o buraco). */
.error-section {
    display: flex;
    align-items: center;
}
.error-section > .container { width: 100%; }


/* --- BLOCO 18 — Resumo em linguagem clara ("duas camadas", levantamento das legais 04/09/2026) —
   Privacidade e Termos abrem com este callout antes das seções numeradas. Tokens dark-safe
   (or-surface-2/or-border), mesma família já usada em blockquote/code/table de .or-doc-body. */
.or-doc-body .or-resumo-legal {
    margin: 0 0 2rem;
    padding: 1.25rem 1.5rem;
    border-radius: var(--or-radius-m, 12px);
    background: var(--or-surface-2, #f6f8fb);
    border: 1px solid var(--or-border, rgba(0, 0, 0, .08));
}
.or-doc-body .or-resumo-legal p:last-child { margin-bottom: 0; }
.or-doc-body .or-resumo-legal__titulo {
    font-weight: 700;
    text-transform: uppercase;
    font-size: .78rem;
    letter-spacing: .04em;
    color: var(--texto-secundario);
    margin-bottom: .5rem;
}

/* --- BLOCO 19 — Impressão limpa (levantamento das legais, §5.7: "a página precisa imprimir bem,
   alguém vai salvar em PDF"). Esconde SÓ o chrome de navegação/interação — nada disso ajuda quem
   está lendo um documento impresso, e o FAB fixed em particular pode se repetir em toda página
   impressa do documento. Aplicado sitewide (não só nas legais): não há motivo pra outra página
   imprimir com FAB/banner por cima do conteúdo. */
@media print {
    #header, .or-fab-stack, #or-lgpd-banner, #or-popup,
    .or-comunicados-bar, .or-secao-cta, .or-newsletter-form,
    .or-doc-indice, .quanto__breadcrumb, .header-wrap-clone {
        display: none !important;
    }
    body { background: #fff !important; color: #000 !important; }
    a { color: #000 !important; text-decoration: underline !important; }
    .or-doc-body { color: #000 !important; }
}

/* ═══════════════════════════════════════════════════════════════════════════════════════════════
   BLOCO 22 — CABEÇALHO DE SEÇÃO: A LARGURA CANÔNICA (09/09/2026)
   ═══════════════════════════════════════════════════════════════════════════════════════════════

   Este bloco não define nenhuma regra — é DOCUMENTAÇÃO da convenção de markup, e mora aqui porque
   o custom.css é do fork. O CLAUDE.md da raiz é arquivo de CORE (invariante zero-diff): escrever
   uma regra de tema lá viraria drift no protect-core. Vários comentários do tema citavam
   "CLAUDE.md §Padrão de Espaçamento" como autoridade do col-lg-8 — mas o CLAUDE.md nunca disse
   isso; a seção de lá trata de row-padding-top e gap, não de largura de coluna. Os comentários
   foram corrigidos para apontar para cá, que é onde a convenção realmente pode viver.

   ── A CONVENÇÃO ────────────────────────────────────────────────────────────────────────────────
   Cabeçalho de seção alinhado à ESQUERDA (eyebrow + h2.title + p.or-lead):

       <div class="row">
           <div class="col-lg-10">                    ← a largura canônica
               <div class="quanto__header">
                   <p class="or-eyebrow">…</p>
                   <h2 class="title">…</h2>
               </div>
               <p class="or-lead or-lead--largo">…</p> ← --largo é OBRIGATÓRIO aqui
           </div>
       </div>

   Antes de 09/09/2026 conviviam 15 larguras diferentes para o mesmo papel (col-lg-8,
   col-lg-8 col-xl-7, col-lg-9, col-lg-10, col-12, col-lg-7…) em ~60 pontos — o dono pediu uma só.
   As ~33 seções alinhadas à esquerda foram unificadas em col-lg-10.

   ── AS TRÊS EXCEÇÕES (deliberadas, não esquecimento) ───────────────────────────────────────────
   1. SEÇÕES CENTRALIZADAS continuam centralizadas — decisão explícita do dono nesta mesma rodada.
      São #prova e #para-quem-e (home), #escada/#upgrade/prova/fecho (/planos), 6 seções de
      /presenca-em-ia, 4 de /sobre, "Onde estamos" (/contato) e o _secao-cta.php (~26 páginas).
   2. COLUNA QUE É METADE DE UM PAR não vira col-lg-10 — alargar quebraria o layout de duas
      colunas. São #painel e #depoimentos (home), #base-comum e #ativacao (/planos), o bloco de
      conceito de /presenca-em-ia, e as colunas de conteúdo que ficam ao lado de um índice lateral
      (/faq, /politica, /acessibilidade, /blog/<slug>).
   3. /blog "Por que escrevemos" é col-lg-10 CENTRALIZADO — exceção pedida nominalmente pelo dono.

   ── A ARMADILHA (já documentada no BLOCO 5, repetida aqui porque é onde se erra) ────────────────
   Alargar a <div class="col-*"> NÃO alarga o subtítulo: .or-lead trava em max-width:640px e a
   trava vence a coluna. Toda coluna que virar col-lg-10 e tiver .or-lead PRECISA de
   .or-lead--largo junto, senão a mudança não aparece na tela — e o erro é silencioso.

   ── DÍVIDA TÉCNICA REGISTRADA ──────────────────────────────────────────────────────────────────
   A padronização de verdade seria um partial único (_secao-header.php) em vez de markup repetido.
   Não foi feito nesta rodada por ser refatoração de ~60 call-sites com eyebrow/lead/animação/id/
   classes de título próprios (6 títulos nem usam .title) — risco alto para o ganho. Fica anotado.
   ═══════════════════════════════════════════════════════════════════════════════════════════════ */

/* ═══════════════════════════════════════════════════════════════════════════════════════════════
   BLOCO 23 — CARD DE PLANO NO MOBILE: o selo em cima do título e o preço colado (09/09/2026)
   ═══════════════════════════════════════════════════════════════════════════════════════════════

   Dois defeitos apontados pelo dono em print de celular. Os dois têm a MESMA origem: são heranças
   do vendor que só faziam sentido no arranjo ANTERIOR do card, e sobreviveram à reordenação de
   08/09/2026 ("escopo antes do preço"). Nenhum aparece no desktop, e é por isso que passaram.

   ── 1 · O SELO SOBRESCREVIA O TÍTULO ──────────────────────────────────────────────────────────
   `.or-pricing-tag` é `position:absolute; top:24px; right:24px` (custom.css:2077). Fora do fluxo,
   ele não empurra nada — funciona enquanto o título couber no espaço que sobra à esquerda. No
   desktop cabe; num card de ~340px, "Autoridade" ocupa a largura inteira e o selo cai EM CIMA.
   Medido em 390px: selo em left 167→398, título em 87→397, ambos no mesmo topo (6237).

   Alargar o card não resolve (o selo continua absoluto) e encurtar o texto do selo é tratar
   sintoma. A correção é devolver o selo ao FLUXO: ele vira o primeiro bloco do card, empurra o
   título para baixo e a colisão deixa de ser possível.

   ⚠️ EM TODAS AS LARGURAS, NÃO SÓ NO MOBILE — e essa decisão vale explicação, porque a primeira
   versão desta correção era `@media (max-width: 767.98px)` e teria deixado metade do defeito de
   pé. Medido no desktop (1440, card de 454px): o selo ocupa 1217→1448 e a CAIXA do título
   1078→1424 — 207px de sobreposição de caixa. Na tela parece correto só porque a palavra
   "Autoridade" mede 148px e termina em 1226, a 9px de encostar no selo. Ou seja: o desktop não
   estava certo, estava com folga de 9 pixels, dependente do comprimento de UMA string.
   Qualquer nome de plano mais longo — ou o mesmo rótulo traduzido, com o add-on multi-idioma que
   já está no roteiro deste site — reproduz no desktop exatamente o que o dono viu no celular.

   No fluxo, `margin-left: auto` mantém o selo encostado à direita e o desenho fica visualmente
   equivalente ao anterior: selo no alto à direita, título logo abaixo à esquerda. O que muda é
   que o título passa a começar DEPOIS do selo em vez de disputar a mesma faixa. Os três cards
   têm altura igual (esticados pela row), então o selo no fluxo não desalinha nada.

   ── 2 · O PREÇO COLADO NA LISTA ───────────────────────────────────────────────────────────────
   O vendor dá a `.pricing` APENAS `margin-bottom` (32px / 20px / 15px por breakpoint,
   style.css:5221-5234) e NENHUM `margin-top`. Isso estava certo no layout original, em que o
   preço vinha ANTES da lista: a margem de baixo era o respiro entre os dois. Quando a ordem foi
   invertida, o respiro foi junto — e a margem passou a separar o preço do que vem DEPOIS dele,
   deixando `0px` entre a última linha da lista e o preço. Medido: lista termina em 6974, preço
   começa em 6974.

   É exatamente o Regime B do CLAUDE.md §Padrão de Espaçamento — "o bloco de baixo traz a própria
   margem". O preço passou a ser o bloco de baixo e não trouxe nada. `--or-esp-6` (32px) é o
   degrau de "troca de assunto" (lista de entregas → preço), o mesmo usado entre texto e lista no
   resto do tema. Vale em todas as larguras: no desktop o respiro também era 0, só menos evidente
   porque a lista é mais curta e o card, mais largo.

   ⚠️ Na HOME o preço vem ANTES da lista (a inversão de 08/09 foi só na /planos), então lá esta
   margem separa o preço da tagline em vez da lista. Medido: 32px nos dois casos, coerente — é o
   mesmo degrau de troca de assunto, e a regra não precisa saber em que página está. */

/* ⚠️ `line-height` JUNTO, e não é enfeite: o preço herdava `line-height: 32px` com `font-size:
   52px` — entrelinha MENOR que a fonte. O texto transborda a própria caixa em 12px para cima, e é
   por isso que a caixa media 32px de respiro enquanto o olho via 20px. Foi o que fez o dono
   apontar "muito junto" mesmo depois de a margem existir. Com 1.1 a caixa passa a conter o
   glifo, e o respiro medido volta a ser o respiro visto. */
.quanto-pricing-box .pricing {
    margin-top: var(--or-esp-6);
    line-height: 1.1;
}

.or-pricing-tag {
    position: static;
    /* `display: flex` + `width: fit-content`, NÃO `inline-flex`: margem automática só empurra
       elemento de nível de BLOCO. Com `inline-flex` o `margin-left: auto` é ignorado e o selo
       voltaria a nascer colado à esquerda — testado. */
    display: flex;
    width: fit-content;
    margin-left: auto;              /* mantém encostado à direita, como no desenho absoluto */
    margin-bottom: var(--or-esp-4);
    /* `top: 24px` / `right: 24px` continuam declarados no bloco original (~linha 2077) e ficam
       INERTES sob `position: static` — não os removo de lá porque aquela regra é a definição
       visual do selo (cor, raio, tipografia) e mexer nela por causa de posicionamento misturaria
       dois assuntos. Quem manda no posicionamento é este bloco, que carrega depois. */
}
/* O card recomendado tinha padding-top extra para acomodar o selo absoluto; no fluxo esse espaço
   viraria vazio duplicado acima do selo. */
.quanto-pricing-box.or-card--recomendado { padding-top: var(--or-esp-6); }

/* ═══════════════════════════════════════════════════════════════════════════════════════════════
   BLOCO 24 — MODAL DE FORMULÁRIO (.or-form-modal) — 09/09/2026
   ═══════════════════════════════════════════════════════════════════════════════════════════════
   Pedido do dono: o CTA da /planos passa a ser o padrão da plataforma e o botão abre "um modal
   100% responsivo e padronizado e moderno com o form correto para envio".

   BASE É O MODAL DO BOOTSTRAP 5, não um overlay próprio — o bundle já é carregado em toda página
   deste tema. Isso traz de graça: trap de foco, `Esc`, clique no backdrop, `aria-modal`, devolução
   do foco ao gatilho e, principalmente, o DARK MODE (o `.modal` do 5.3 responde a
   `[data-bs-theme="dark"]` — Camada 1 do or-dark.css). Este bloco só veste; não reimplementa nada
   do comportamento. É por isso que quase não há regra de cor aqui: as que existem apontam para os
   tokens semânticos (--or-surface/--or-text/--or-border), que já invertem no escuro.

   ⚠️ NENHUM #hex de superfície/texto/borda abaixo. Cor fixa não segue o tema e o campo some no
   escuro — é a mesma regra que vale no admin (CLAUDE.md §Padrão de cores theme-aware).
   ═══ */

/* O diálogo respira nas bordas no mobile (o default do Bootstrap são 8px, apertado para um
   formulário) e nunca ultrapassa a leitura confortável no desktop.

   ⚠️ VIA AS VARIÁVEIS DO COMPONENTE (`--bs-modal-margin`/`--bs-modal-width`), NUNCA por `margin`
   e `max-width` crus no `.modal-dialog`. Escrever a margem por cima foi a primeira tentativa e
   produziu um defeito silencioso: o `.modal-dialog-scrollable` dimensiona a altura com
   `calc(100% - var(--bs-modal-margin) * 2)` — ou seja, continua contando os 8px do default. Com
   margem real de 16px, o diálogo passava a medir 100% + 16px, o `.modal` (e não o `.modal-body`)
   ganhava barra de rolagem própria, e essa barra comia 21px de UM lado só: medido a 375×667, 16px
   de margem à esquerda contra 37px à direita, visivelmente descentrado.

   Alimentando a variável, todas as contas internas do Bootstrap — altura do scrollable, min-height
   do centered, margem do diálogo — passam a usar o mesmo número, e o componente volta a fechar. */
.or-form-modal {
    --bs-modal-margin: var(--or-esp-4);
    --bs-modal-width: 560px;
}
@media (min-width: 576px) {
    .or-form-modal { --bs-modal-margin: var(--or-esp-7); }
}

.or-form-modal__content {
    border: 1px solid var(--or-border, rgba(0, 0, 0, .08));
    border-radius: 18px;
    /* Sombra generosa porque o fundo atrás é o gradiente escuro da marca: sem ela o card branco
       "cola" no backdrop e perde a leitura de camada. */
    box-shadow: 0 24px 64px rgba(5, 19, 43, .28);
    overflow: hidden;
}

.or-form-modal__header {
    border-bottom: 1px solid var(--or-border, rgba(0, 0, 0, .08));
    padding: var(--or-esp-6) var(--or-esp-6) var(--or-esp-4);
    align-items: flex-start;
}

/* O h2 do modal NÃO usa --or-fs-secao: aqui ele é o título de um diálogo, não de uma seção da
   página, e a escala de seção (até 4rem) estouraria a caixa. Escala própria, contida. */
.or-form-modal__titulo {
    font-size: clamp(1.35rem, 1.15rem + .8vw, 1.75rem);
    font-weight: 700;
    letter-spacing: -.02em;
    line-height: 1.15;
    color: var(--or-text, var(--color-primary));
    margin: 0;
}

.or-form-modal__body { padding: var(--or-esp-5) var(--or-esp-6) var(--or-esp-6); }

/* Não é `.or-lead`: aquele carrega max-width 640px e justify — num diálogo de 560px isso vira
   linha esticada e rio de espaço. Aqui a frase é curta e alinhada à esquerda, como rótulo de
   contexto do formulário. */
.or-form-modal__lead {
    color: var(--or-text-muted, var(--texto-secundario));
    font-size: .95rem;
    line-height: 1.55;
    margin: 0 0 var(--or-esp-5);
}

/* Regime B (CLAUDE.md §Padrão de Espaçamento): o bloco de baixo traz a própria margem. O `.row`
   do formulário usa gap do Bootstrap (g-3), então o botão é quem se separa dos campos. */
.or-form-modal__submit { margin-top: var(--or-esp-3); }
.or-form-modal__nota   { margin-top: var(--or-esp-4); margin-bottom: 0; }

/* ── MOBILE: só respiro interno ───────────────────────────────────────────────────────────────
   ⚠️ AQUI HOUVE UMA TENTATIVA DESCARTADA, e ela vale registrada porque parece boa ideia: colar o
   diálogo no topo com `align-items: flex-start` no `.modal-dialog-centered`, para não gastar
   margem morta acima quando o teclado virtual abre. **Não fazer.** Medido a 375×667: quebra o
   contrato do `modal-dialog-scrollable`, que dimensiona o diálogo em `height: calc(100% - margem*2)`
   contando com o alinhamento central. Sem ele o conteúdo transborda, o `.modal` (e não o
   `.modal-body`) ganha barra de rolagem própria, e essa barra come 21px de UM lado só — o diálogo
   fica visivelmente descentrado (medido: 16px à esquerda contra 37px à direita).

   O `modal-dialog-scrollable` já resolve o caso que a regra tentava resolver: quando falta altura,
   quem rola é o corpo do formulário, com cabeçalho e botão fixos. Deixar o Bootstrap trabalhar. */
@media (max-width: 575.98px) {
    .or-form-modal__header { padding: var(--or-esp-5) var(--or-esp-5) var(--or-esp-3); }
    .or-form-modal__body   { padding: var(--or-esp-4) var(--or-esp-5) var(--or-esp-5); }
}
