/* IAJUS landing : visual system "Asterisco de Origem" (nanquim quente, acento
   dourado champanhe #b89244; direção C , ver saas/brand/BOARD.md). Progressive enhancement
   via html.js / html.vt classes set inline in <head>; everything degrades to a
   static, readable page. */

/* Nav typeface (decisão de design 2026-06-10, consultoria gemini-3.1-pro):
   Inter Medium sentence case como default provisório, SELF-HOSTED (subset
   latin + latin-ext para os diacríticos PT-BR), font-display:swap para nunca
   bloquear a primeira pintura. woff2 variável cobre os pesos 500 e 600.
   Alternativas para o operador (Public Sans, Instrument Sans) já vivem no stack
   do corpo; trocar `--font-nav` abaixo aplica a escolha final sem novo download. */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 500 600;
  font-display: swap;
  src: url('./assets/fonts/inter-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;
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 500 600;
  font-display: swap;
  src: url('./assets/fonts/inter-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;
}

/* Brand webfonts (Lora display / Public Sans body-UI / Fira Code mono) self-hosted
   2026-07-08 (DI-F2, docs/design/IAJUS_DESIGN_IDENTITY_2026-07-08.md §4): mesmos
   arquivos woff2 que o Google serve hoje para a query
   css2?family=Lora:ital,wght@0,400;0,500;0,600;1,400;1,600&family=Public+Sans:ital,wght@0,400;0,500;0,600;0,700;1,400&family=Fira+Code:wght@400;500;600
   (fidelidade 1:1, subset latin + latin-ext apenas — cyrillic/greek/vietnamese
   fora de escopo para PT-BR), variable fonts com o peso colapsado no range
   real coberto por cada arquivo (mesmo padrão do Inter acima). */
@font-face {
  font-family: 'Lora';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url('./assets/fonts/lora-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;
}
@font-face {
  font-family: 'Lora';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url('./assets/fonts/lora-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: 'Lora';
  font-style: italic;
  font-weight: 400 600;
  font-display: swap;
  src: url('./assets/fonts/lora-italic-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;
}
@font-face {
  font-family: 'Lora';
  font-style: italic;
  font-weight: 400 600;
  font-display: swap;
  src: url('./assets/fonts/lora-italic-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: 'Public Sans';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('./assets/fonts/public-sans-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;
}
@font-face {
  font-family: 'Public Sans';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('./assets/fonts/public-sans-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: 'Public Sans';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url('./assets/fonts/public-sans-italic-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;
}
@font-face {
  font-family: 'Public Sans';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url('./assets/fonts/public-sans-italic-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: 'Fira Code';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url('./assets/fonts/fira-code-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;
}
@font-face {
  font-family: 'Fira Code';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url('./assets/fonts/fira-code-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;
}

/* Fallbacks com métricas ajustadas (CLS do swap ~0): enquanto a webfont baixa, a
   local renderiza JÁ com o tamanho/altura da titular — o swap deixa de refluir o
   layout (shift 0.17 flagrado no Lighthouse de /integracoes, 2026-07-02). Números
   calculados com fontTools sobre os arquivos reais (hhea + avg advance a-z+espaço):
   Lora upm1000 asc1006 desc-274 avg514.4 vs Georgia upm2048 asc1878 desc-449 avg1002.7;
   Public Sans upm2000 asc1900 desc-450 avg1036.9 e Inter upm2048 asc1984 desc-494
   avg1079.1 vs Arial upm2048 asc1854 desc-434 gap67 avg986.5.
   #108 T2 (2026-09-24): a média a-z+espaço errava a largura do texto real em ~6 % (Public
   Sans) — o fallback ficava LARGO, o parágrafo ganhava uma linha e o swap a devolvia: CLS
   0,16-0,24 em /termos. size-adjust recalibrado no Chromium pela razão de largura webfont /
   local a 100 % sobre ~80 mil caracteres das páginas (termos, home, privacidade, cobertura,
   blog) no peso dominante de cada uso: Public Sans 400 (corpo), Lora 500 (títulos), Inter 500
   (nav); o itálico ganha face própria (o .hl dourado de todo H1 é Lora itálico). Os overrides
   verticais são a métrica da titular DIVIDIDA pelo size-adjust, porque o size-adjust também
   escala os overrides (CSS Fonts 5). */
@font-face {
  font-family: 'Lora Fallback';
  src: local('Georgia');
  size-adjust: 104.06%;
  ascent-override: 96.68%;
  descent-override: 26.33%;
  line-gap-override: 0%;
}
@font-face {
  font-family: 'Lora Fallback';
  font-style: italic;
  src: local('Georgia Italic');
  size-adjust: 99.54%;
  ascent-override: 101.07%;
  descent-override: 27.53%;
  line-gap-override: 0%;
}
@font-face {
  font-family: 'Public Sans Fallback';
  src: local('Arial');
  size-adjust: 101.56%;
  ascent-override: 93.54%;
  descent-override: 22.15%;
  line-gap-override: 0%;
}
@font-face {
  font-family: 'Public Sans Fallback';
  font-style: italic;
  src: local('Arial Italic');
  size-adjust: 98.31%;
  ascent-override: 96.63%;
  descent-override: 22.89%;
  line-gap-override: 0%;
}
@font-face {
  font-family: 'Inter Fallback';
  src: local('Arial');
  size-adjust: 105.48%;
  ascent-override: 91.84%;
  descent-override: 22.87%;
  line-gap-override: 0%;
}

:root {
  /* ⛔ ESTA FOLHA É A QUARTA CÓPIA DA PALETA DA MARCA, e a fonte de verdade é
     saas/shared/brand-tokens.css (as outras duas são as vendorizadas de saas/app e
     saas/admin/app, presas entre si por saas/app/spec/brand-tokens-paridade.test.js).
     A landing NÃO alcança o partilhado em tempo de execução: nenhuma das 71 páginas
     HTML de saas/landing (48 BR + 21 PT + as duas de erro) o carrega por <link> ou
     @import — `grep -rl brand-tokens saas/landing --include=*.html` devolve ZERO —,
     e a raiz web servida pelo nginx
     é este diretório (saas/front/Dockerfile: `COPY landing/`). Por isso os tokens vivem
     aqui, e por isso «sincronizado por comentário» não bastava — comentário não é teste.
     ⭐ Quem prende esta cópia ao canônico é spec/tokens-da-marca-nao-divergem-em-silencio.test.js:
     todo token que os dois lados declaram tem de carregar o MESMO valor EFETIVO por tema,
     e cada desvio vive numa lista com razão E locator. Ao editar um valor daqui, ou o
     canônico muda no mesmo passe, ou o desvio entra declarado — não há terceira saída.
     Native form controls + scrollbars follow the active theme; light overrides this in
     the [data-theme='light'] block below. */
  color-scheme: dark;
  /* Nav typeface token: change this single value to swap the operator's choice
     (Inter | 'Public Sans' | 'Instrument Sans'); the fallback stack stays. */
  --font-nav: 'Inter', 'Inter Fallback', 'Public Sans', 'Public Sans Fallback', system-ui, -apple-system, sans-serif;
  /* Ink & paper : navy base, off-white ink, gold accents */
  --bg: #161b28;
  --bg-2: #1a1f2e;
  --bg-3: #202637;
  --ink: #f8f9fa;          /* off-white (decisão #85: corpo off-white sobre navy) : headings / strongest emphasis */
  --ink-soft: #e7e8ea;

  /* ---- Text contrast ladder (semantic, by ROLE) -------------------------------
     Three deliberate tiers so reading content stands above meta. Targets follow
     a perceptual-lightness ramp; primary stops short of pure white to avoid
     halation/glare on the near-black ground.
       primary   ~86% L  : body paragraphs, list items, the things you READ
       secondary ~64% L  : supporting meta, captions, secondary descriptions
       tertiary  ~48% L  : mono labels, eyebrows, fine print, placeholders
     `--muted` / `--muted-2` are kept as aliases so existing selectors keep
     working; they now point at the ladder instead of a single flat gray. */
  --text-primary: #e9e7dd;    /* warm stone : ~13:1 on bg-2 (AAA) */
  --text-secondary: #b4b1a5;  /* ~8.4:1 (AAA) */
  --text-tertiary: #9c9a8e;   /* ~5.7:1 (AA) : small mono labels & fine print */
  --muted: var(--text-secondary);   /* alias : legacy secondary body */
  --muted-2: var(--text-tertiary);  /* alias : legacy tertiary / mono labels */

  --gold: #b89244;         /* champanhe sóbrio : acento primário (era #c9a227 — chroma -30%, +quente; gilt de capa de código jurídico, não amarelo neon). AA 5.9:1 sobre navy. Sync c/ saas/shared/brand-tokens.css */
  --gold-bright: #d8b86a;   /* champanhe claro (era #e0b73a) — AA 9:1 */
  /* Ouro-de-SUPERFÍCIE (A1, design plan 2026-07-02): par THEME-INVARIANT para
     background de botão/CTA dourado. Os --gold* do tema claro foram re-tunados
     para TEXTO sobre creme e reprovam AA como superfície com tinta escura —
     este par NÃO flipa (sem override no bloco light). A tinta do rótulo é o
     terceiro membro do par e tem a MESMA invariância: --btn-gold-ink, agora
     declarado aqui com o valor do canônico em vez de repetido como literal
     #1c1917 em 7 sítios de 6 seletores (.skip-link, .nav-link.nav-entrar e os seus
     estados :hover/.active, a regra móvel de .nav-right .nav-entrar, .btn-primary —
     um deles operando de um color-mix de borda). Censo medido em 2026-09-09.
     No canônico o mesmo hex vivia copiado em 56 sítios antes de virar token —
     guard de lá: spec/tinta-do-rotulo-dourado-e-token.test.js. */
  --btn-gold-hi: #d8b86a;
  --btn-gold-lo: #a37f37;
  --btn-gold-ink: #1c1917;
  /* Borda de campo (A2 do canônico): declaração IDÊNTICA à de
     saas/shared/brand-tokens.css — deriva da tinta da própria superfície, logo flipa
     com o tema sem override. As medições e o limite estão na regra `input, textarea`,
     mais abaixo. */
  --field-border: color-mix(in srgb, var(--ink) 50%, transparent);
  --gold-soft: #a37f37;     /* ouro velho (era #b8902f) — AA 4.6:1 */
  --indigo: #8d89f5;
  /* --sky was collapsed onto --indigo here; realign to the shared source of
     truth (saas/shared/brand-tokens.css) so it stays a distinct blue. --ink /
     --ink-soft deliberately keep the off-white of decisão #85 (do NOT align). */
  --sky: #6f9fd8;
  /* literal canônico de saas/shared/brand-tokens.css (= color-mix(var(--gold) 28%) no escuro);
     o tema claro redefine abaixo. Literal mantém a cópia BR byte-comparável com a PT (#6853). */
  --rule: rgba(184, 146, 68, 0.28);
  --hair: rgba(255, 255, 255, 0.09);
  --card: rgba(255, 255, 255, 0.03);
  --card-strong: rgba(255, 255, 255, 0.055);
  /* Véus PRÓPRIOS da landing. NÃO são o `--scrim` da app, e a diferença é de
     PAPEL, não de cor. Duas razões independentes, as duas medidas em 2026-08-31:
     (1) ACOPLAMENTO — a app serve este mesmo RGB só como veneziana de modal
         (--scrim 0,55 / --scrim-strong 0,58). Estes dois são cromo de página e
         profundidade de vinheta, a 0,72 e a 0,97: apontá-los ao scrim faria um
         futuro ajuste da veneziana mexer, calado, na barra fixa do site.
     (2) ALCANCE — a landing não carrega `brand-tokens.css`. Das 71 páginas
         HTML de saas/landing, ZERO o alcançam por <link> ou @import (as folhas são
         styles.css, blog/blog.css, conceitos/conceitos.css e brand-faces.css, e
         nenhuma o importa). `var(--scrim)` aqui seria custom property indefinida
         SEM fallback — inválida no tempo do valor computado —, e num `background`
         não herdado isso rende `transparent`: a barra fixa ficaria sem fundo.
     Dois papéis, dois nomes, de propósito: um muda quando o cromo do cabeçalho
     muda, o outro quando a profundidade da vinheta muda, e não devem nunca
     mexer-se em conjunto só porque hoje partilham o RGB.

     ⚠️ AO EDITAR ESTA PROSA: o nome do token da app está citado acima SEM
     dois-pontos a seguir, e isso é deliberado. `tinta-de-direcao-nao-servida.test.js`
     varre as folhas da landing com /--scrim\s*:/ em LINHAS CRUAS — não remove
     comentários — para ficar vermelho no dia em que a landing declarar mesmo esse
     token. Escrever aqui o nome seguido de dois-pontos põe esse guard vermelho
     sobre prosa, alarme falso sobre uma folha correta. É o mesmo tropeço já
     medido e registado em `font-display-nao-se-chama-body.test.js`. */
  --header-veil: rgba(8, 11, 20, 0.72);
  /* ^ barra fixa do topo (.topbar), lida através do blur do backdrop-filter.
       Só o tema escuro: o claro sobrepõe na REGRA (`[data-theme='light'] .topbar`),
       não no token, e continua a vencer por especificidade. */
  --vignette-deep: rgba(8, 11, 20, 0.97);
  /* ^ parada FUNDA da vinheta da constelação de ontologia (.ontology-canvas e
       .onto-mobile). A parada PRÓXIMA do mesmo gradiente, rgba(14,20,36,0.92),
       continua literal de propósito: é outra cor, com dívida própria registada. */
  --err: #ef6f5c;
  --ok: #2bc48a;
  --maxw: 1200px;
  --gutter: clamp(20px, 5vw, 56px);
  /* Family palette : used by the donut + legend + family chips */
  --fam-superiores: #d97706;
  --fam-tjs: #8d89f5;
  --fam-trfs: #57a8e0;
  --fam-trts: #4fbf96;
  --fam-tres: #d98ad9;
  --fam-tcs: #a3c94f;  /* verde-folha — antes ocre #c98a3e, colidia com superiores no donut (sweep UX 2026-07-19) */
  --fam-administrativo: #e0cd50;  /* amarelo — antes violeta claro, colidia com tjs */
  --fam-turmas_recursais: #c04fd9;  /* magenta — antes azul claro, colidia com trfs */
  --fam-militar: #8a97a8;  /* aço/steel — justiça militar (STM, TJM-*) */
  --fam-default: #a8a29e;
  /* Esfera palette (legislação por esfera: barra empilhada + dots da legenda no
     painel Normativos). Antes REFERENCIADA (var(--esf-federal|estadual|municipal)
     em .esf-seg/.esf-dot/.embed-fill) mas NUNCA definida → segmentos e dots caíam
     no fallback vazio (transparent) e a barra de esferas renderizava um pill oco.
     Esse conserto usou ALIAS das famílias (--fam-superiores/-tjs/-trts), e a razão
     escrita para o desvio era «a landing não mostra legenda de família nestas
     páginas, logo os dois eixos não colidem».
     ⛔ MEDIDO EM 2026-09-09, e a razão era FALSA nesta árvore: o índice de órgãos
     pinta `--orgidx-*: var(--fam-*)` em 9 declarações (8 famílias + o default), no
     bloco .orgaos-index desta folha, e esse índice vive na MESMA página da barra de
     esferas — index.html tem os dois (`orgaos-index` 1 ocorrência, `esf-bar` 1).
     Em cobertura.html só existe a barra (`orgaos-index` 0), logo a colisão que
     refuta a razão antiga é a de index.html, e basta uma página para refutá-la.
     Com o alias, União saía exatamente na tinta de «superiores», estados na de
     «tjs» e municípios na de «trts» — as duas legendas a ler como a mesma
     codificação, que é precisamente o que o comentário de saas/shared/brand-tokens.css
     manda evitar («deliberately not reusing any --fam hue so the two legends never
     read as the same encoding»). Alinhado ao canônico: sky→gold→teal, cada um já
     auditado ≥3:1 como preenchimento gráfico (WCAG 1.4.11) sobre --bg-2/--bg-3 nos
     dois temas. Guard: spec/tokens-da-marca-nao-divergem-em-silencio.test.js. */
  --esf-federal: #5b93cf;
  --esf-estadual: #b89244;
  --esf-municipal: #4fa89a;
  /* Fluid type scale */
  --step-eyebrow: clamp(0.72rem, 0.68rem + 0.2vw, 0.82rem);
  --step-body: clamp(1.02rem, 0.97rem + 0.4vw, 1.22rem);
  --step-h2: clamp(1.9rem, 1.3rem + 2.6vw, 3.1rem);
  --step-h3: clamp(1.18rem, 1.05rem + 0.6vw, 1.4rem);
  /* Spacing token ladder: one shared rhythm so section head→content gaps stop
     jittering between hand-set values. --space-10 (40px) é o gap canônico
     head→content de todas as secções.
     ⛔ O ÍNDICE É O DE saas/shared/brand-tokens.css (auto-descritivo, N x 4px), e
     essa troca é a CORREÇÃO de uma armadilha medida, não um capricho de nome. Até
     2026-09-09 esta escada era um índice SEQUENCIAL (2,3,4,5,6,7 → 8,12,16,24,32,40):
     o mesmo `--space-6` valia 32px aqui e 24px lá, e `--space-5` valia 24px aqui e
     20px lá. Nada rebentava e nada avisava — um bloco de regras movido entre a
     landing e a app mudava de espaçamento em silêncio. O renomeado é PIXEL-IDÊNTICO
     (5→6, 6→8, 7→10, mesmos 24/32/40px em cada sítio); os 3 degraus que já batiam
     (--space-2/3/4 = 8/12/16px) ficam como estavam.
     ⭐ A coordenação que o guard dizia estar pendente com a linha PT foi MEDIDA e é
     vazia: `var(--space-` não aparece em ficheiro nenhum da landing fora desta folha
     (0 ocorrências em pt/, blog/, conceitos/ e nos .html). */
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-6: 24px;
  --space-8: 32px;
  --space-10: 40px;
  /* Letter-spacing tokens for the mono-uppercase label device. Two tiers:
     --track-eyebrow for the ~0.7-0.82rem eyebrows/kickers, --track-label for the
     sub-0.7rem caps micro-labels. Collapses ~6 ad-hoc tracking values. */
  --track-eyebrow: 0.2em;
  --track-label: 0.1em;
  /* Tokens antes fantasma (referenciados mas nunca definidos): --focus-ring
     tornava `outline: var(--focus-ring)` inválido no .nav-group-btn (anel de foco
     sumia); --radius-x e --font-x caíam no fallback e colapsavam a escada.
     NUNCA escrever asterisco+barra dentro de comentário CSS: a sequência de
     fechamento embutida (bug FB-BD 7067988f) encerrava este comentário no meio
     e ENGOLIA a declaração de --focus-ring abaixo — foco invisível em todo
     seletor `outline: var(--focus-ring)` (accordion de órgãos, WCAG 2.4.7). */
  --focus-ring: 2px solid var(--gold-bright);
  /* Escada de raio ALINHADA a saas/shared/brand-tokens.css (2026-09-09). Era
     10/14/18/22 — «2px mais redonda que a do app» — e essa diferença aparecia lado
     a lado para quem abre a landing e o app na mesma sessão. Move 17 sítios que
     consomem os tokens (sm 2, md 6, lg 9; xl e 2xl têm ZERO consumidores).
     ⚠️ NÃO fecha o eixo, e o número diz porquê: das 204 declarações `border-radius`
     desta folha só 24 passam por token; as outras 180 são LITERAIS e já misturavam
     as DUAS escadas — 35 na antiga (10px 14, 14px 13, 18px 7, 22px 1) contra 50 na
     partilhada (12px 20, 9px 12, 16px 11, 20px 7), mais 95 fora de qualquer uma
     (999px 28, 50% 18, 8px 11, 6px 8, 3px 8, 13px 5, e o resto). Tokenizá-las é
     decisão de vocabulário do dono do desenho (qual literal é qual degrau), e está
     no relatório desta lane.
     MÉTODO do censo (para ser refeito, não copiado): comentários removidos; conta
     por DECLARAÇÃO, incluindo as longhands de canto; classificada pelo PRIMEIRO
     valor em px. Medido em 2026-09-09 nesta árvore; 35 + 50 + 95 = 180. */
  --radius-sm: 9px;
  --radius-md: 12px;
  --radius-lg: 16px;
  --radius-xl: 20px;
  /* Escada de raio/sombra/foco completada (F-A, S3 2026-07-07): --radius-xs,
     --radius-pill, --shadow-*, --focus-ring-offset e --focus-halo já eram
     REFERENCIADOS por seletores reais (.tri-card, .corpus-tab, o corpus-switcher)
     mas NUNCA definidos — caíam em fallback e a sombra/anel do card sumia. Aqui
     eles ganham valor, alinhados ao vocabulário do app (saas/app brand-tokens). */
  --radius-xs: 6px;
  --radius-2xl: 26px;
  --radius-pill: 999px;
  --focus-ring-offset: 3px;
  --focus-halo: 0 0 0 4px color-mix(in srgb, var(--gold) 18%, transparent);
  --shadow-card: 0 18px 40px -28px rgba(0, 0, 0, 0.9);
  --shadow-raised: 0 22px 48px -14px color-mix(in srgb, var(--gold) 75%, transparent);
  --shadow-gold: 0 16px 38px -14px color-mix(in srgb, var(--gold) 65%, transparent);
  --btn-border: 1px solid var(--hair);
  --btn-border-hover: 1px solid var(--gold);
  /* Stacks IDÊNTICOS aos de saas/shared/brand-tokens.css (2026-09-09). A landing
     tinha a mesma face titular com a cauda mais curta ('Times New Roman' e
     'SFMono-Regular', Menlo em falta): invisível enquanto a webfont carrega — e é
     exatamente por ser invisível que divergia sem ninguém ver. O que muda é só o
     que se vê quando a webfont NÃO chega. As faces de fallback com métricas
     ajustadas ('Lora Fallback' / 'Public Sans Fallback') estão declaradas nesta
     folha, acima. */
  --font-display: 'Lora', 'Lora Fallback', Georgia, 'Times New Roman', serif;
  --font-mono: 'Fira Code', ui-monospace, 'SFMono-Regular', Menlo, monospace;
}

/* =============================================================================
   LIGHT THEME : papel creme, tinta navy, dourado escurecido p/ AA. Ativado por
   data-theme='light' no <html> (toggle no nav + bootstrap inline no <head>).
   Valores UNIFICADOS com saas/shared/brand-tokens.css e o app (saas/app). Escuro
   continua o default (operador: "deixando o escuro como default").
   ============================================================================= */
[data-theme='light'] {
  color-scheme: light;
  --bg: #faf8f2;
  --bg-2: #f3f0e7;
  --bg-3: #ebe7da;
  --ink: #1a1f2e;
  --ink-soft: #2c3242;
  /* contrast ladder (the --muted/--muted-2 aliases follow these automatically) */
  --text-primary: #2c3242;
  --text-secondary: #555b6b;
  --text-tertiary: #5f6573; /* AA on tinted surfaces (was #676d7c = 4.07); aligns canonical --muted-2 light */
  --gold: #765d16; /* AA as text on cream (was #8a6d1a = missed AA 3.6-4.3); aligns canonical brand-tokens light --gold */
  --gold-bright: #6f570f;
  --gold-soft: #a07f1c;
  --indigo: #4338ca;
  --sky: #2d5a96;
  --rule: rgba(138, 109, 26, 0.35);
  --hair: rgba(26, 31, 46, 0.12);
  --card: rgba(26, 31, 46, 0.035);
  --card-strong: rgba(26, 31, 46, 0.06);
  /* ⛔ ELEVACAO DO BOTAO PRIMARIO. Estes dois nasciam SO no :root escuro e
     derivavam de `var(--gold)`. No escuro --gold e' #b89244 (champanhe claro) e
     o resultado e' um BRILHO sobre fundo escuro — correto. No claro --gold foi
     escurecido para #765d16 (para cumprir AA como TEXTO sobre creme), e o mesmo
     token vira uma MANCHA CASTANHA-ESCURA projectada 16px PARA BAIXO, com 38px
     de blur, sobre o que estiver por baixo do botao. O que esta' por baixo do
     botao primario e', em tres paginas, a letra miuda .privacy; e na home, o
     #qc-help. Este e' exactamente o defeito que a propria regra `.btn-primary`
     ja' documenta para a SUPERFICIE do botao ("os --gold* do tema claro viram
     TEXTO escuro sobre creme") e que resolveu com --btn-gold-hi/lo, que NAO
     flipam: a sombra ficou para tras. (Ancora no SELETOR e nao em numero de
     linha: a linha muda sem avisar e a citacao envelhece calada.)
     Medido com o compositor de chapas (pior ponto) a 2026-08-21: matar SO esta
     sombra leva #qc-help de 4,423 -> 5,452 e o fundo composto sob o texto volta
     ao papel liso (#f9f7f1). A aurora, a quem o defeito tinha sido atribuido,
     vale 0,033 — foi um erro de atribuicao, e a sombra e' 100% da causa no
     #qc-help. Curva de falha da escolha (tinta ink, mesma geometria): alpha
     0,45 -> 4,42 REPROVA; 0,35 -> 4,64; 0,28 -> 4,80; 0,22 -> 4,95; 0,14 ->
     5,08. 0,22 nao e' argmin: e' o alpha de sombra que o tema claro JA' usa em
     `.topbar.scrolled` (rgba(26,31,46,.22), mais abaixo neste ficheiro), e deixa
     ~0,18 de alpha de folga antes sequer de tocar a barra de +0,25.
     Geometria inalterada de proposito: muda a TINTA, nao o desenho.
     Vigia: spec/sombra-do-botao-nao-escurece-a-letra-miuda.test.js */
  --shadow-gold:   0 16px 38px -14px rgba(26, 31, 46, 0.22);
  --shadow-raised: 0 22px 48px -14px rgba(26, 31, 46, 0.22);
  --err: #b91c1c;
  --ok: #166534;          /* green-800. Esta era a QUARTA copia de --ok (claro) que
                             ainda carregava o green-700 #15803d, depois de brand-tokens.css
                             (saas/shared + saas/app + saas/admin/app) ja terem sido
                             corrigidas para #166534 no commit 984f01044c — o guard de
                             paridade daquelas tres (brand-tokens-paridade.test.js) so
                             varre ficheiros chamados brand-tokens.css, e esta landing
                             carrega os tokens inline no proprio styles.css, entao nunca
                             foi alcancada. #15803d nascia ABAIXO de AA como TEXTO sobre
                             --bg-2 (4,40:1) e --bg-3 (4,05:1), as superficies de
                             .demo-check/.notify(.form-msg)/.plat-copy.ok. Re-medido nesta
                             arvore com o MESMO compositor do guard irmao (Chromium
                             compoe color-mix() como color(srgb ...), nao rgb() — esta
                             landing nao usa color-mix sobre --ok como texto, so como
                             borda decorativa de badge/botao, que 1.4.11 nao vincula
                             aqui: ja se identifica por texto+icone): com #166534, --bg-2
                             sobe para 6,26:1 e --bg-3 para 5,76:1. Guard:
                             spec/light-theme-token-aa-guard.test.js. */
  /* Family palette no tema claro: os matizes do escuro reprovam WCAG 1.4.11
     (objeto gráfico ≥3:1) sobre o creme (dots de legenda/donut/chips medem
     1,87-2,62:1). Valores escurecidos já auditados no canônico (saas/shared +
     vendored do app, auditoria 2026-06-29); COMPUTADO ≥3,01:1 sobre --bg-2
     #f3f0e7 aqui. Mudou o vendored/shared, atualizar este bloco no mesmo commit. */
  --fam-superiores: #92580a;
  --fam-tjs: #837fe3;
  --fam-trfs: #4a90c0;
  --fam-trts: #3f9a79;
  --fam-tres: #b673b6;
  --fam-tcs: #5e9426;
  --fam-administrativo: #8f7a12;
  --fam-turmas_recursais: #9638c4;
  --fam-militar: #5f6b82;  /* aço/steel — justiça militar (light-mode AA) */
  --fam-default: #8e8986;
  /* Esfera no tema claro: os três matizes do escuro caem abaixo de 3:1 (WCAG
     1.4.11) sobre o creme, tal como as famílias acima. Valores do canônico. Antes
     de 2026-09-09 estes tokens não existiam neste bloco porque eram ALIAS de
     --fam-* e herdavam o escurecimento pela indireção; agora que carregam matiz
     própria, o par claro tem de ser declarado — senão a barra de esferas pintaria
     no creme os hexes afinados para navy. */
  --esf-federal: #2f6ba8;
  --esf-estadual: #8a6d1a;
  --esf-municipal: #2f7d70;
  /* ⛔ SOMBRA DE CARD NO TEMA CLARO — ausência MEDIDA, não decisão. Até 2026-09-09
     esta folha declarava --shadow-card só no :root escuro (preto a 0,9 de alfa), e
     o tema claro herdava-o: os cards do site pintavam no papel creme a sombra
     desenhada para o navy, enquanto a app pinta a versão navy-suave do canônico na
     mesma superfície. É a MESMA classe de defeito que --shadow-gold/--shadow-raised
     já pagaram aqui (ver o bloco da elevação do botão primário, acima, e
     spec/sombra-do-botao-nao-escurece-a-letra-miuda.test.js): token de elevação que
     nasce só no escuro e ninguém repara que o claro o herda. Valor do canônico,
     idêntico ao que a app serve. */
  --shadow-card: 0 18px 40px -28px rgba(26, 31, 46, 0.35);
}

/* Light surface fixes for the few HARDCODED-dark literals (tokens already flip
   above; these rules carry their own dark values that need a light counterpart). */
[data-theme='light'] .topbar { background: rgba(250, 248, 242, 0.78); }
[data-theme='light'] .topbar.scrolled {
  background: rgba(250, 248, 242, 0.92);
  box-shadow: 0 18px 40px -28px rgba(26, 31, 46, 0.22);
}
/* "Sem fundo de cor que atrapalhe" (operador): on the light paper the aurora
   color blurs are dialled WAY down so the page reads clean, not tinted. */
[data-theme='light'] .aurora::before,
[data-theme='light'] .aurora::after { opacity: 0.1; }
[data-theme='light'] .grain { opacity: 0.025; }

/* Form fields + dashboard filters: the dark-tuned `rgba(0,0,0,0.32–0.48)` field
   fills are HARDCODED (the only theme literals these inputs carry — the tokens
   don't reach them). On cream paper that composites to a medium-grey box: the
   navy --ink typed text survives, but the --muted-2 placeholder drops to ~2.2:1
   (FAIL AA) and the grey box reads as "broken" against the light surface. Repaint
   to a white field on cream (mirrors saas/admin/index.html), so the placeholder
   clears AA (~5.8:1) and the field looks native to the light theme. color-scheme
   keeps the native focus chrome / date-picker light. */
[data-theme='light'] input,
[data-theme='light'] textarea,
[data-theme='light'] .filter-select,
[data-theme='light'] .filter-search,
[data-theme='light'] .explorer-search { background: #fff; color-scheme: light; }
[data-theme='light'] .tel-group { background: #fff; }
[data-theme='light'] input:focus:not(:focus-visible),
[data-theme='light'] textarea:focus:not(:focus-visible),
[data-theme='light'] .filter-select:focus:not(:focus-visible),
[data-theme='light'] .tel-group:focus-within { background: #fff; }
/* LH-06: os <select> do form /beta (#uf/#municipio/#perfil) também precisam do
   repaint claro — mas SÓ o background-color: o shorthand `background:#fff` das
   regras acima apagaria a seta (background-image) do select. */
[data-theme='light'] select { background-color: #fff; color-scheme: light; }
[data-theme='light'] select:focus:not(:focus-visible) { background-color: #fff; }

/* Appearance toggle injected into the nav by appearance.js (sun while dark = go
   light; moon while light = go dark). Token-driven; >=44px touch hit (WCAG 2.5.5). */
.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 38px;
  height: 38px;
  /* Slot próprio, separado do par Entrar/Como-usar? (ruling operador 2026-07-05:
     o toggle não pode disputar espaço visual com o CTA). 4px→14px: com "Entrar"
     agora um pill dourado sólido, dois preenchimentos colados liam como um só
     bloco confuso; a folga maior lê como dois controles distintos mesmo sem
     sobreposição literal (essa já foi corrigida em 2026-07-04 via placeholder
     estático + breakpoint do drawer, ver @media abaixo).
     ⛔ Os 14px NÃO cedem na banda compacta 1081-1329 (2026-09-01): a folga de
     largura veio da legenda da marca, do gutter do topbar e do corpo de letra —
     nenhuma delas revoga este ruling. Voltar aos 4px valia +10px e reabria
     exatamente o defeito visual que o ruling fechou. */
  margin-left: 14px;
  /* The static placeholder ships [hidden] so no-JS pages never show an empty pill;
     appearance.js drops [hidden] on hydration. inline-flex above would otherwise
     override the UA [hidden]{display:none}, so re-assert it here. */

  /* Visible at REST, not only on hover: a subtle filled pill + a clear --ink icon, so
     the dark->light switch is an obvious symbol up top instead of a faint grey glyph
     that blends into the dark header (operator 2026-06-26). */
  background: var(--card);
  border: 1px solid var(--hair);
  border-radius: 999px;
  color: var(--ink);
  cursor: pointer;
  transition: color 0.15s ease, background 0.15s ease, border-color 0.15s ease;
}
/* Re-assert UA [hidden] over the inline-flex above: the static placeholder stays
   invisible (and out of the flex flow) until appearance.js hydrates it. */
.theme-toggle[hidden] { display: none; }
.theme-toggle:hover {
  color: var(--gold);
  background: var(--card);
  border-color: var(--gold);
}
.theme-toggle svg {
  width: 18px;
  height: 18px;
  display: block;
}
@media (pointer: coarse) {
  .theme-toggle { width: 44px; height: 44px; }
}
@media (prefers-reduced-motion: reduce) {
  .theme-toggle { transition: none; }
}

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; scroll-padding-top: 88px;
  /* Reserva p/ overlay fixo de rodapé (ex.: card de cookies): --overlay-bottom-h é
     escrita em runtime por registerBottomOverlay() (app.js) enquanto há overlay
     visível e removida ao dispensar — resolve a 0px sem overlay (nenhum gap). Aqui,
     scroll-padding-bottom faz a rolagem ancorada (#hash / scrollIntoView) parar ACIMA
     do overlay; o body ganha o padding-bottom espelhado. */
  scroll-padding-bottom: var(--overlay-bottom-h, 0px); }
body {
  font-family: 'Public Sans', 'Public Sans Fallback', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  color: var(--ink);
  background: var(--bg);
  font-size: var(--step-body);
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
  /* Espelho do scroll-padding-bottom: reserva o espaço do overlay fixo de rodapé no
     FIM do documento, para que o último conteúdo (footer, form #notify) fique acima do
     card de cookies. 0px sem overlay (var não definida) — nenhum gap permanente. */
  padding-bottom: var(--overlay-bottom-h, 0px);
  /* Responsividade sem quebra de palavra: jamais hifenizar nem partir letra a
     letra. Overflow de prosa resolve por layout (min-width:0, clamp, wrap por
     palavra inteira). `break-word` parte um token longo demais só como último
     recurso, ao contrário de `anywhere`, que quebra gulosamente no meio. */
  hyphens: none;
  -webkit-hyphens: none;
  overflow-wrap: break-word;
}
::selection { background: color-mix(in srgb, var(--gold) 28%, transparent); color: var(--ink); }

/* ---- Brand primitives for native controls (both themes) ----
   Nothing renders in the OS-default look: checkboxes/radios/range adopt the gold
   accent, the scrollbar carries a discreet gold-tinted thumb, and every control
   inherits the brand font. accent-color / scrollbar-color / font are inherited, so
   seeding html cascades everywhere; both values resolve through the themed --gold. */
html {
  accent-color: var(--gold);
  scrollbar-color: color-mix(in srgb, var(--gold) 40%, transparent) transparent;
  scrollbar-width: thin;
}
button, input, select, textarea, optgroup { font-family: inherit; }

/* Guarda anti-quebra de TÍTULO/DISPLAY (programa front; espelha
   saas/landing/conceitos/conceitos.css): headers, eyebrows e números de display
   jamais hifenizam nem partem palavra/letra — overflow se resolve por LAYOUT
   (clamp de fonte, grid/min-width), nunca quebrando o token. A prosa do body
   mantém o break-word de último recurso definido acima. */
h1, h2, h3,
.eyebrow, .counter-eyebrow,
.counter-num, .acervo .stat .v, .fam-num {
  hyphens: none;
  -webkit-hyphens: none;
  overflow-wrap: normal;
  word-break: normal;
}
.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
/* WCAG 1.4.10 (Reflow) - SELETOR: table.visually-hidden. Medido em 2026-08-22 a
   320x900 em conceitos/o-corpus.html: scrollWidth 388 vs clientWidth 320, 68px de
   rolagem horizontal REAL (scrollTo(9999,0) levava scrollX de 0 a 68). Ausente a
   1280x900. A regra .visually-hidden acima ja declara width:1px, mas uma caixa de
   tabela sob table-layout:auto trata width como piso e nunca desce abaixo do
   min-content -- e o white-space:nowrap da propria regra faz min-content ==
   max-content, entao a tabela media 369,09px de largura. Deixar o conteudo quebrar
   e o unico eixo que encolhe a caixa: 369,09px -> 32,7px, delta 68 -> 0. Restrito a
   table.visually-hidden porque e 1 dos 137 usos da classe na landing (os outros 136
   sao span/p/h/label/div/caption, onde width:1px ja vincula e nada muda). Continua
   clipe visual, nunca display:none nem visibility:hidden: a tabela permanece na
   arvore de acessibilidade com caption, colunas e linhas. */
table.visually-hidden { white-space: normal; overflow-wrap: anywhere; }

/* ---- Accessibility: focus + skip link ---- */
/* `summary` entra no baseline global (review FB-BD 7067988f): todo <details>
   interativo ganha anel visível mesmo se a regra própria da classe sumir; as
   regras específicas (.orgidx-summary, .legis-disclose > summary, ...) seguem
   vencendo por especificidade. */
a:focus-visible, button:focus-visible, input:focus-visible, textarea:focus-visible,
select:focus-visible, summary:focus-visible {
  /* Anel de foco dourado via tokens (F-A / S3 2026-07-07): mesmos valores de antes,
     agora nomeados (--focus-ring / --focus-ring-offset / --focus-halo). */
  outline: var(--focus-ring);
  outline-offset: var(--focus-ring-offset);
  border-radius: var(--radius-xs);
  box-shadow: var(--focus-halo);
}
.skip-link {
  /* A1: mesma superfície theme-invariant do .btn-primary (var(--gold) flipava
     para #765d16 no claro → ~2,8:1 com a tinta #1c1917). --btn-gold-hi = 9,2:1. */
  position: absolute; left: 16px; top: -64px; z-index: 100;
  background: var(--btn-gold-hi); color: var(--btn-gold-ink); font-weight: 600;
  font-family: 'Fira Code', ui-monospace, monospace;
  padding: 11px 18px; border-radius: 10px; text-decoration: none;
  font-size: 0.85rem; transition: top .2s ease;
}
.skip-link:focus { top: 16px; }

/* ---- Atmosphere: aurora + parchment grain + ledger rules ---- */
.bg-layer { position: fixed; inset: 0; z-index: -1; pointer-events: none; }
.aurora { overflow: hidden; }
.aurora::before, .aurora::after {
  content: ""; position: absolute; border-radius: 50%;
  /* Suavizada 2026-07-19 (ordem operador, "expansão feia" no desktop): opacidade
     0.55→0.30 e saturação das bolas indigo 42%→26% / gold 30%→18% com blur
     130→150px. O halo vira ambiente sutil em vez de mancha visível. */
  filter: blur(150px); opacity: 0.30;
}
.aurora::before {
  width: 760px; height: 760px; top: -320px; left: -220px;
  background: radial-gradient(circle, color-mix(in srgb, var(--indigo) 26%, transparent), transparent 70%);
}
.aurora::after {
  width: 680px; height: 680px; bottom: -340px; right: -200px;
  background: radial-gradient(circle, color-mix(in srgb, var(--gold) 18%, transparent), transparent 70%);
}
/* Ledger column rules REMOVED 2026-07-21 (operador: linhas amarelas delimitando
   areas = horror estetico). DOM layer stays; no gold frame paint. */
.ledger {
  background-image: none;
  opacity: 0;
  visibility: hidden;
}
.grain {
  opacity: 0.045; mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

.wrap { max-width: var(--maxw); margin-inline: auto; padding-inline: var(--gutter); }
.inline-link { color: var(--gold); text-decoration: none; border-bottom: 1px solid var(--rule); white-space: nowrap; }
.inline-link:hover { border-bottom-color: var(--gold); }
.code-key {
  font-family: 'Fira Code', monospace; font-size: 0.92em;
  color: var(--gold-bright); background: color-mix(in srgb, var(--gold) 10%, transparent);
  border: 1px solid var(--rule); border-radius: 6px; padding: 2px 7px;
}

/* ---- Reveal: progressive enhancement only (html.js + motion ok) ---- */
.js .reveal { opacity: 0; transform: translateY(22px); }
.js .reveal.in {
  opacity: 1; transform: none;
  transition: opacity .8s cubic-bezier(.22,.61,.36,1), transform .8s cubic-bezier(.22,.61,.36,1);
}
.js .reveal.in[data-d="1"] { transition-delay: .08s; }
.js .reveal.in[data-d="2"] { transition-delay: .16s; }
.js .reveal.in[data-d="3"] { transition-delay: .24s; }
.js .reveal.in[data-d="4"] { transition-delay: .32s; }

/* WCAG 2.4.7 (Focus Visible) - SELETOR: .js .reveal. Medido em 2026-08-22: ao
   navegar por Tab, o browser rola o elemento focado para a vista, mas o
   IntersectionObserver so acrescenta .in um frame depois (e o rootMargin -6% pode
   nem disparar na rolagem minima do foco). O alvo fica focado e invisivel:
   checkVisibility({checkVisibilityCSS:true, checkOpacity:true}) === false, herdado
   de um ancestral .reveal em opacity:0 / translateY(22px). Reproduzido em 14 de 14
   combinacoes (7 paginas BR x 320px e 1280px) com o observer desarmado, e em 7 de 7
   paginas a 320px com o observer VIVO -- neste ultimo caso inclusive sobre blocos
   que ja tinham .in mas ainda estavam no meio da transicao de 0.8s, ou seja o
   defeito nao depende de o observer ter falhado. Revela no instante em que o foco
   entra, sem tocar em JS, seguindo o precedente de .gloss:focus-within e
   .cov-ressalva:focus-within nesta mesma folha. */
.js .reveal:focus-within { opacity: 1 !important; transform: none !important; }

/* =========================================================
   ANNOUNCE : faixa de pré-lançamento "IAJUS vem aí" (acima da nav,
   rola junto com a página , a nav continua sticky sozinha)
   ========================================================= */
.announce {
  /* Diluted gold wash; neutral bottom edge (operador 2026-07-21). */
  background: linear-gradient(90deg, color-mix(in srgb, var(--gold) 8%, transparent), color-mix(in srgb, var(--gold) 3%, transparent) 55%, color-mix(in srgb, var(--gold) 7%, transparent));
  border-bottom: 1px solid var(--hair);
}
.announce-inner {
  display: flex; align-items: center; justify-content: center; flex-wrap: wrap;
  gap: 6px 8px; padding: 9px 4px;
  font-size: 0.86rem; letter-spacing: 0.02em; line-height: 1.35;
  color: var(--ink, #f6f4ee); text-decoration: none;
}
.announce-inner strong { color: var(--gold-bright); font-weight: 700; white-space: nowrap; }
.announce-mark { color: var(--gold); }
.announce-sep { color: var(--gold-soft); }
.announce-cta {
  color: var(--gold); font-weight: 600; white-space: nowrap;
  border-bottom: 1px solid color-mix(in srgb, var(--gold) 45%, transparent); margin-left: 4px;
}
.announce-inner:hover .announce-cta { color: var(--gold-bright); border-bottom-color: var(--gold-bright); }
@media (max-width: 560px) {
  .announce-inner { font-size: 0.78rem; padding: 8px 2px; }
  /* Mobile: o CTA por extenso some, mas a faixa inteira continua sendo um link.
     Para não virar um link sem affordance, a frase ganha um sublinhado sutil e
     uma seta compacta (via ::after) que sinaliza que dá pra tocar. */
  .announce-cta { display: none; }
  .announce-text {
    border-bottom: 1px solid color-mix(in srgb, var(--gold) 45%, transparent);
    padding-bottom: 1px;
  }
  .announce-text::after {
    content: " →"; color: var(--gold); white-space: nowrap;
  }
  .announce-inner:hover .announce-text { border-bottom-color: var(--gold-bright); }
}

/* =========================================================
   NAV : sticky, with mobile toggle
   ========================================================= */
.topbar {
  position: sticky; top: 0; z-index: 30;
  border-bottom: 1px solid var(--hair);
  background: var(--header-veil);
  backdrop-filter: saturate(140%) blur(14px);
  -webkit-backdrop-filter: saturate(140%) blur(14px);
  transition: box-shadow .25s ease, background .25s ease;
}
.topbar.scrolled { box-shadow: 0 18px 40px -28px rgba(0,0,0,0.9); background: rgba(22, 27, 40, 0.9); }
/* A barra de topo pode ser um pouco MAIS LARGA que o wrap de conteúdo (--maxw 1200):
   com a marca + 6 links + o par "Como usar?"/"Entrar" + o toggle, o conteúdo do nav
   soma ~897px e estourava os 820px disponíveis dentro do wrap de 1200px por ~77px,
   fazendo o pill "Entrar" pintar por cima do toggle de tema (medido ao vivo em
   1440-1600px; o wrap capa o nav então alargar o viewport não resolvia). Dar ao
   wrap DO TOPBAR um teto de 1360px (só no header horizontal, acima do drawer) dá
   folga para os dois estados do pill: "Entrar" (~92px) e, logado, o menu do
   usuário — que no fallback "Minha conta" mede 137px (medido ao vivo 2026-07-20:
   com 1300px o pill transbordava 11px por cima do toggle; primeiro nome real é
   mais curto que o fallback). O conteúdo das seções segue em 1200px.
   ⭐ Este teto vale em TODA a barra horizontal, e por isso o `min-width` é o do
   drawer +1 (1081 desde 2026-09-01, era 1330). Abaixo de 1360px de viewport ele
   não morde — o wrap fica preso à viewport —, mas se ficasse em 1330 a faixa
   1081-1329 herdava o `--maxw` de 1200px das seções e perdia até 160px de
   largura útil exatamente onde ela é escassa. */
@media (min-width: 1081px) {
  .topbar .wrap { max-width: 1360px; }
}
nav {
  display: flex; align-items: center; justify-content: space-between;
  /* nowrap: marca + .nav-right + toggle ficam numa única linha no header horizontal.
     Sem isto, na banda apertada o toggle (último filho) podia cair para uma 2ª
     linha e sobrepor o CTA. Acima do drawer a barra é sempre uma linha só. */
  flex-wrap: nowrap;
  /* Header ~80px: 38px logo + 21px de respiro em cima e embaixo (decisão de
     design 2026-06-10). min-height trava a altura mesmo se o conteúdo encolher. */
  padding-block: 21px; gap: 16px; min-height: 80px;
}
.brand { display: inline-flex; align-items: center; gap: 13px; text-decoration: none; color: var(--ink); }
.brand svg { width: 38px; height: 38px; flex: none; }
/* Wordmark IAJUS : "IA" grotesco pesado + "JUS" Lora itálico ouro
   (colisão engenharia x lei , direção C, saas/brand/BOARD.md). */
.brand b {
  font-family: 'Public Sans', 'Public Sans Fallback', system-ui, sans-serif; font-weight: 700; font-size: 1.34rem;
  letter-spacing: 0.01em; line-height: 1;
}
.brand b span { color: var(--gold); font-family: 'Lora', 'Lora Fallback', Georgia, serif; font-style: italic; font-weight: 600; }
.brand small {
  display: block; font-family: 'Fira Code', monospace; font-size: 0.55rem;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted-2); margin-top: 3px;
  white-space: nowrap; /* legenda nunca quebra nem alarga a marca a ponto de invadir o nav */
}
/* FE-RESP-01 (320px): marca(216px) + hambúrguer(43) + theme-toggle(38) + gaps(32)
   somavam ~329px num nav de ~270px e empurravam o theme-toggle ~60px para fora da
   viewport (overflow-x na página inteira). Abaixo de 421px a legenda "Inteligência
   Jurídica" cede — o wordmark IAJUS + o símbolo continuam identificando a marca —
   e o header volta a caber com folga. */
@media (max-width: 420px) {
  .brand small { display: none; }
}
/* Links alinhados à ESQUERDA (logo-nav-esquerda, CTA-direita: padrão SaaS).
   center foi abandonado porque os 9 itens + a marca excedem o wrap de 1200px,
   e center derrama o overflow para a ESQUERDA, sobrepondo a legenda da logo a
   "O acervo". flex-start joga qualquer sobra para a direita (sob nada), e a CTA
   fica isolada à direita via margin-left:auto. A marca fica fora do .nav-right. */
/* gap fluido: 5 links + "Recursos" + CTA + Entrar cabem numa só linha acima do
   breakpoint do drawer (1080px desde 2026-09-01, ver @media abaixo); abaixo disso
   a barra vira drawer. O clamp foi apertado de 14-24px para 8-16px porque o conjunto cresceu
   (Sobre + Fale conosco + Recursos): 7 gaps a 24px somavam ~168px e estouravam
   a faixa de 830px do .wrap (--maxw 1200). */
.nav-right {
  display: flex; flex: 1; flex-wrap: nowrap; min-width: 0;
  align-items: center; justify-content: flex-start; gap: clamp(8px, 0.85vw, 12px);
  /* GARANTIA ESTRUTURAL do não-overlap com o toggle de tema (ordem operador
     2026-07-26). O box do .nav-right nunca invade o toggle — `flex: 1` com
     `min-width: 0` já cede o espaço dele, que é `flex: none`. O que sobrepunha era
     o CONTEÚDO: os itens são `white-space: nowrap`, logo não encolhem abaixo do
     min-content, transbordam a caixa e PINTAM por cima do vizinho. Esse é o
     mecanismo por trás das três correções anteriores (2026-07-04 placeholder
     estático, 2026-07-05 folga do toggle, bumps de breakpoint) — todas mexeram na
     LARGURA para o transbordo não acontecer, nenhuma tornou o transbordo inofensivo.
     `overflow-x: clip` torna: qualquer excedente é cortado na borda da caixa em vez
     de invadir o toggle. Precisa ser `clip` e não `hidden` — `hidden` num eixo força
     o outro a `auto` (vira scroll container) e decapitaria o dropdown "Como
     pesquisar", que é absolute e escapa para BAIXO; `clip` é a exceção da spec que
     permite manter o outro eixo `visible`. No drawer (<=1080px) o bloco do @media
     mais abaixo sobrescreve os dois eixos, então isto vale só na barra horizontal. */
  overflow-x: clip;
  overflow-y: visible;
}
/* Regras legadas do par SOLTO de pills (sem .nav-auth em volta), escopadas a FILHO
   DIRETO do .nav-right. Depois de 2026-07-26 nenhuma página servida cai mais aqui —
   as 12 do header canônico e as 4 do secundário (/conceitos/*, /chatgpt) agrupam as
   duas pills no .nav-auth, que é quem carrega o margin-left:auto agora. Ficam para os
   protótipos em _proto/ e para markup legado. O `>` é obrigatório: como seletor
   descendente, estas regras pegariam as pills DENTRO do .nav-auth e reabririam o
   espaçamento no meio do par (o auto-margin empurraria a segunda pill para longe da
   primeira, desmanchando o par). */
/* M-AO: respiro extra entre as duas pills soltas (operador: pills coladas no print). */
.nav-right > .nav-cta + .nav-entrar { margin-left: 4px; }
/* O par de pills fica isolado à direita. O auto-margin vai no primeiro do par para
   os dois andarem juntos; sem o pill dourado, recai sobre a CTA. */
.nav-right > .nav-entrar { margin-left: auto; }
.nav-right > .nav-cta:first-of-type { margin-left: auto; }
/* Bloco de autenticação: as duas pills viram UM alvo de layout (ordem operador
   2026-07-26). `flex: none` para nunca encolher e nunca ser espremido pelos links à
   esquerda — quem cede largura é a lista de links, não o par de ações. O
   margin-left:auto que antes vivia no pill agora vive aqui, então o par inteiro é
   que é empurrado para a direita, junto. */
.nav-auth { display: flex; align-items: center; gap: 8px; flex: none; margin-left: auto; }
/* "Entrar": AGORA o CTA forte da barra (ruling operador 2026-07-05 — antes era
   texto apagado, "Conecte seu assistente" dominava demais). Pill dourado sólido
   com o par tema-invariante --btn-gold-hi/lo (superfície de botão, não a tinta
   de texto --gold que já foi re-escurecida p/ AA em claro) + tinta escura fixa
   #1c1917, igual ao CTA original: garante AA nos dois temas sem depender do
   --gold que flipa. Hover clareia a superfície (hi→ainda mais claro via
   color-mix) mantendo a mesma tinta de texto. */
.nav-link.nav-entrar {
  color: var(--btn-gold-ink);
  background: linear-gradient(180deg, var(--btn-gold-hi), var(--btn-gold-lo));
  font-weight: 600; padding: 8px 16px; border-radius: 999px;
  /* Contorno definido (ordem operador 2026-07-19): filete escuro-ouro (62% do
     lo do gradiente + tinta) que tira a borda "barata" do pill + luz superior
     interna formando bisel sutil; funciona nos dois temas porque o par
     --btn-gold-hi/lo é tema-invariante. */
  border: 1px solid color-mix(in srgb, var(--btn-gold-lo) 62%, var(--btn-gold-ink));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.3), 0 1px 2px rgba(0, 0, 0, 0.28);
}
.nav-link.nav-entrar:hover {
  color: var(--btn-gold-ink);
  background: linear-gradient(180deg, color-mix(in srgb, var(--btn-gold-hi) 88%, white), var(--btn-gold-hi));
}
/* .active precisa reafirmar a tinta escura: `.nav-link.active { color: var(--gold) }`
   vem DEPOIS na cascata e tem a mesma especificidade, então sem isto um pill dourado
   marcado como ativo pintaria ouro sobre ouro (ilegível). É o mesmo motivo pelo qual
   .nav-cta já tinha o seu par :hover/.active. Hoje o prerender não assa .active neste
   pill (ele não leva data-route, de propósito — ver o comentário no HTML), então esta
   regra é o cinto de segurança de quem vier adicionar um. */
.nav-link.nav-entrar.active {
  color: var(--btn-gold-ink);
  background: linear-gradient(180deg, var(--btn-gold-hi), var(--btn-gold-lo));
}
/* Fonte do nav (decisão de design 2026-06-10, consultoria gemini-3.1-pro: o
   mono-caps anterior foi reprovado). Default provisório = Inter Medium, sentence
   case, self-hosted (subset latin+latin-ext, swap) , ver @font-face no topo e o
   token --font-nav em :root. Alternativas para o operador (Public Sans, Instrument
   Sans) já vivem no stack do corpo; trocar --font-nav aplica a escolha final. */
.nav-link {
  font-family: var(--font-nav); font-weight: 500;
  /* 0.95rem: com 4 links + CTA + Entrar a barra cabe folgada numa só linha. */
  font-size: 0.95rem; letter-spacing: 0.005em;
  color: var(--muted); text-decoration: none; transition: color .2s ease;
  white-space: nowrap; /* rótulos de 2 palavras ("Acesso ao BETA") nunca quebram */
  /* Alvo de ponteiro ~40px de altura (24px de texto + 16px de padding) —
     audit landing P2-1 2026-07-19: WCAG 2.2 SC 2.5.8 AA mínimo 24px já passava;
     o padrão do projeto é 44px e 40px é o compromisso que não infla o header
     sticky. Os pills (.nav-entrar/.nav-cta) já têm padding próprio 8px (40px). */
  padding-block: 8px;
}
.nav-link:hover, .nav-link.active { color: var(--gold); }
/* "Como usar?" (ex-"Conecte seu assistente" / ex-nav-cta dourado sólido): ÊNFASE
   MÉDIA de propósito (ruling operador 2026-07-05) — a barra deve ter no máximo
   1-2 CTAs fortes, e "Entrar" agora é o forte. Outline com a tinta --gold (já
   AA como texto nos dois temas) sobre fundo transparente, em vez de superfície
   sólida: continua lendo como ação, sem competir com o pill dourado de "Entrar". */
.nav-link.nav-cta {
  color: var(--gold); background: transparent; border: 1px solid var(--gold);
  font-weight: 600; padding: 8px 15px; border-radius: 999px;
}
.nav-link.nav-cta:hover, .nav-link.nav-cta.active {
  color: var(--bg); background: var(--gold); border-color: var(--gold);
}

/* ---- Nav dropdown ("Recursos": Conceitos + Atlas) ----------------------------
   Keeps the top bar to 5 text links + 1 trigger + CTA + Entrar so it never clips
   between 1081-1280px (a flat 7-link bar overflowed 57px at the breakpoint edge).
   Desktop: a hover/focus popup anchored to the trigger. Mobile (<=1080): the popup
   styling is reset in the drawer block so the items stack as a labelled section.
   ⛔ O 1080 desta linha NÃO é decoração: `app.js` (initNavGroup) tranca TODOS os
   handlers deste dropdown atrás de `matchMedia('(min-width: 1081px)')` — pointer,
   click, Enter/Space/ArrowDown/Escape, focusin/focusout e o click-outside. Medido a
   2026-09-01 com o breakpoint do CSS forçado a 1023 por CSSOM: em 1024/1060/1080 o
   foco no gatilho NÃO abre o menu (`aria-expanded` fica `false`, `checkVisibility()`
   do menu = false) e em 1081/1100/1280/1366 abre. Logo o drawer do CSS não pode
   descer abaixo de 1081 sem mover ESSE mesmo número em app.js: a barra apareceria
   com um `aria-haspopup` inoperável por teclado (WCAG 2.1.1 e 4.1.2). */
.nav-group { position: relative; display: inline-flex; }
.nav-group-btn {
  display: inline-flex; align-items: center; gap: 5px;
  background: transparent; border: 0; cursor: pointer;
  /* padding-block casa com o .nav-link (~40px de alvo, P2-1); inline 0 p/ não
     comer largura da barra. */
  padding: 8px 0;
}
.nav-caret {
  width: 7px; height: 7px; border-right: 1.6px solid currentColor;
  border-bottom: 1.6px solid currentColor; transform: translateY(-2px) rotate(45deg);
  transition: transform .2s ease; opacity: 0.8;
}
.nav-group-btn[aria-expanded="true"] .nav-caret { transform: translateY(1px) rotate(-135deg); }
.nav-group-menu {
  position: absolute; top: calc(100% + 12px); left: 50%; transform: translateX(-50%) translateY(-6px);
  display: flex; flex-direction: column; min-width: 168px; padding: 6px;
  background: var(--bg-2); border: 1px solid var(--rule); border-radius: 14px;
  box-shadow: 0 22px 48px -24px rgba(0,0,0,0.55);
  opacity: 0; visibility: hidden; pointer-events: none;
  /* Hover-intent close delay: when the pointer leaves, the menu FADES over ~200ms
     (pointer-events flips off at once — the visual grace softens the snap; the ::before
     bridge is what actually keeps the trigger->menu cross alive). The open direction
     (hover/expanded) zeroes the delay so it appears at once. */
  transition: opacity .18s ease .2s, transform .18s ease .2s, visibility .18s .2s;
  z-index: 60;
}
/* Hover bridge: an invisible slab spanning the 12px trigger->menu gap, so the pointer
   crossing from the trigger down to the menu never leaves the hoverable region and the
   menu stops vanishing mid-cross. It sits inside the (hoverable) menu box, above the
   trigger's top edge, and is only "live" while the menu is revealed (parent pointer-events
   are none when closed, so the bridge cannot block the links behind it). */
.nav-group-menu::before {
  content: ""; position: absolute; left: 0; right: 0; top: -14px; height: 14px;
}
/* Reveal on hover (desktop pointer, no-JS fallback) OR when the trigger reports
   expanded. With JS on, app.js owns aria-expanded through a hover-intent timer
   (open on pointerenter, close ~220ms after pointerleave) AND focus-within (open on
   focusin, close on focusout leaving the group). Keyboard/focus reveal is therefore
   JS-driven via aria-expanded, NOT a CSS :focus-within — a :focus-within reveal here
   would keep matching after Escape returns focus to the button, holding the menu open
   and breaking dismissability. */
.nav-group:hover .nav-group-menu,
.nav-group-btn[aria-expanded="true"] + .nav-group-menu {
  opacity: 1; visibility: visible; pointer-events: auto; transform: translateX(-50%) translateY(0);
  transition-delay: 0s;
}
/* Fallback SÓ sem JS (html.js nasce no head quando o script corre): com JS o
   :focus-within ficaria ligado depois do Escape devolver o foco ao botão e
   prenderia o menu aberto (razão do comentário acima); sem JS não há Escape
   nem aria-expanded — o teclado não abriria o grupo nunca. Os itens continuam
   alcançáveis no rodapé, mas aqui o menu cumpre o dever primário. */
html:not(.js) .nav-group:focus-within .nav-group-menu {
  opacity: 1; visibility: visible; pointer-events: auto; transform: translateX(-50%) translateY(0);
  transition-delay: 0s;
}
.nav-group-item {
  font-family: var(--font-nav); font-size: 0.92rem; color: var(--ink-soft);
  text-decoration: none; padding: 9px 12px; border-radius: 9px; white-space: nowrap;
  transition: background .15s ease, color .15s ease;
}
.nav-group-item:hover, .nav-group-item:focus-visible { background: var(--card); color: var(--gold); }
.nav-group-btn:focus-visible { outline: var(--focus-ring); outline-offset: 3px; border-radius: 6px; }

/* <button> como item de menu: zera o visual nativo de botão e herda
   o do <a class="nav-group-item"> (a classe fornece fonte, padding, hover). */
button.nav-group-item {
  appearance: none; background: transparent; border: 0; cursor: pointer;
  text-align: left; width: 100%;
}

.nav-toggle {
  display: none; flex-direction: column; gap: 5px; cursor: pointer;
  background: transparent; border: 1px solid var(--hair); border-radius: 10px;
  padding: 10px 11px; width: 44px; height: 44px;
}
.nav-toggle-bar { display: block; width: 20px; height: 2px; background: var(--ink-soft); border-radius: 2px; transition: transform .25s ease, opacity .2s ease; }
.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }
/* Botão de fechar DENTRO do dialog (#nav-menu), 2026-09-04: só existe no modo
   gaveta modal — fora dele o mesmo nó é a barra horizontal, nunca um dialog, e
   um botão de "fechar" ali não faz sentido nenhum. display:none aqui, revelado
   só dentro do @media do drawer abaixo (mesmo padrão do .nav-toggle acima). */
.nav-close { display: none; }

/* Drawer mobile: a barra horizontal (marca + links + CTA + Entrar) colapsa no
   hambúrguer até 1080px. Medido (axe/overflow sweep @1024): as páginas de nav mais
   larga estouram a CTA à direita entre ~901-1080px se ficarem em barra horizontal —
   escritorios/cobertura têm 6 links (+45/+23px) e as de conceito têm rótulos longos
   (+112px). O index (5 links) caberia, mas colapsa junto para um comportamento único.
   ⛔⛔ DE 1329 PARA 1080 (2026-09-01, defeito reportado pelo operador com print).
   O ponto tinha subido 1239→1319→1329 numa sequência que só sabia GASTAR largura
   (toggle de tema no header, folga do ruling 2026-07-05), e o resultado era um
   desktop de 1280 CSS px — 1920 físicos a 150% de escala, ou um portátil de
   1366/1280 — a receber o hambúrguer centrado numa barra vazia. Medido a
   2026-09-01, servindo esta árvore em 127.0.0.1 com Chromium (playwright 1.62.1,
   deviceScaleFactor 1): `display: flex` no `.nav-toggle` e `.nav-right` em
   `position: absolute` a 1024 e a 1280, nas 5 páginas do header canónico e do
   secundário. A conta antiga não estava errada; estava a responder à pergunta
   errada — perguntava "a barra ATUAL cabe?" quando a pergunta é "o que cede para
   ela caber?".
   ⭐ POR QUE 1080 E NÃO 1023. O piso é do `app.js`, não do desenho: `initNavGroup`
   tranca todos os handlers do dropdown "Como pesquisar" atrás de
   `matchMedia('(min-width: 1081px)')`. Com o CSS forçado a 1023 por CSSOM e o
   app.js intacto, o foco no gatilho NÃO abre o menu em 1024/1060/1080
   (`aria-expanded` fica `false`) e abre em 1081/1100/1280/1366 — 3 larguras mortas
   contra 4 vivas, com controlo positivo. Servir a barra abaixo de 1081 seria
   entregar um `aria-haspopup` inoperável por teclado (WCAG 2.1.1, 4.1.2). Descer
   até 1024 exige mover ESSE número em app.js, o que arrasta o cache-buster de
   `app.js?v=N` em todas as páginas e o `spec/app-js-cache-buster.lock.json`.
   ⭐ O QUE CEDE na banda 1081-1329 (bloco logo abaixo, com as medições): a legenda
   da marca, o gutter do topbar e o corpo de letra do nav. Medido no ponto mais
   apertado (1081px, index): folga de 32,3px com Inter e 18,1px no primeiro frame
   com 'Inter Fallback' — as duas MAIORES que os 20,0px / 16,4px que o desenho
   aceite hoje tem no seu próprio limite (1330px).
   ⚠️ O scrim segue este teto (min-width 1081). A banda do contador do hero
   (min-width:1081 / max-width:1329) DEIXOU de o seguir: ver a nota lá em baixo.
   As páginas de conceito também herdam este drawer genérico. */
@media (max-width: 1080px) {
  .nav-toggle { display: flex; }
  .nav-right {
    position: absolute; top: 100%; left: 0; right: 0;
    flex: none; flex-direction: column; align-items: stretch; justify-content: flex-start; gap: 0;
    /* Opaque fill so the bright hero headline never ghosts through the drawer.
       Pair with the full-viewport .nav-scrim (below) that darkens the rest of the
       page; together the open menu reads as a solid layer, not a translucent flap. */
    background: #0a0d16;
    backdrop-filter: saturate(140%) blur(18px); -webkit-backdrop-filter: saturate(140%) blur(18px);
    border-bottom: 1px solid var(--rule);
    box-shadow: 0 28px 60px -30px rgba(0,0,0,0.95);
    padding: 8px var(--gutter) 22px;
    max-height: 0; overflow-y: auto; overflow-x: hidden; opacity: 0; visibility: hidden;
    transition: max-height .3s ease, opacity .25s ease, visibility .25s;
  }
  .nav-right.open { max-height: calc(100vh - 100%); max-height: calc(100dvh - 100%); opacity: 1; visibility: visible; }
  /* Mesma receita de cor de .demo-modal-close (styles.css, ~L3846): --bg-3 de fundo,
     --text-secondary de tinta, --hair de borda, --gold-bright/--rule no hover. Medido
     nos DOIS temas sobre o fundo REAL da gaveta (não o do modal): #0a0d16 escuro dá
     9,03:1 (glifo) e 7,01:1 (glifo sobre o fundo do próprio botão); #f6f3ea claro dá
     6,11:1 e 5,48:1 — os dois folgados acima do piso AA de 4,5:1. align-self:flex-end
     porque a coluna do drawer é align-items:stretch (herdaria largura total senão). */
  .nav-close {
    display: inline-flex; align-items: center; justify-content: center;
    align-self: flex-end; flex: none; margin: 4px 0 10px;
    width: 44px; height: 44px; border-radius: 9px; border: 1px solid var(--hair);
    background: var(--bg-3); color: var(--text-secondary); font-size: 1.05rem; line-height: 1;
    cursor: pointer;
  }
  .nav-close:hover { color: var(--gold-bright); border-color: var(--rule); }
  .nav-close:focus-visible { outline: 2px solid var(--gold-bright); outline-offset: 2px; }
  .nav-link { padding-block: 14px; border-bottom: 1px solid var(--hair); font-size: 0.95rem; }
  /* No drawer o .nav-auth vira uma coluna esticada: as duas pills empilham em
     largura cheia, com a mesma silhueta e a mesma ordem do desktop (Entrar em cima,
     outline; Cadastre-se embaixo, dourado). O margin-left:auto do desktop morre aqui
     — em coluna ele empurraria a pill para fora do eixo. As regras de pill logo
     abaixo usam seletor DESCENDENTE de propósito, para valerem tanto dentro do
     .nav-auth (12 páginas do header canônico) quanto soltas (/conceitos, /chatgpt). */
  .nav-auth { display: flex; flex-direction: column; align-items: stretch; margin-left: 0; gap: 0; }
  /* Hierarquia espelha o desktop: o pill dourado sólido (.nav-entrar) é o forte, o
     outline (.nav-cta) é o secundário. Ambos centrados, mesma silhueta de pílula —
     nunca texto solto sem affordance. */
  .nav-right .nav-cta {
    margin-left: 0; margin-top: 10px; text-align: center; color: var(--gold);
    background: transparent; font-weight: 600; border: 1px solid var(--gold); border-radius: 12px; padding: 11px 18px;
  }
  .nav-right .nav-entrar {
    margin-left: 0; margin-top: 12px; text-align: center; color: var(--btn-gold-ink);
    background: linear-gradient(180deg, var(--btn-gold-hi), var(--btn-gold-lo));
    border: 1px solid transparent; border-radius: 12px; padding: 11px 18px;
  }
  /* In the drawer the "Recursos" dropdown flattens into a labelled, always-open
     section: the trigger becomes a non-interactive group heading and the items
     stack as ordinary drawer links (no popup, no hover state). */
  .nav-group { display: block; width: 100%; }
  .nav-group-btn {
    width: 100%; justify-content: flex-start; cursor: default;
    padding-block: 14px; border-bottom: 1px solid var(--hair);
    color: var(--muted-2); font-size: 0.78rem; letter-spacing: 0.08em; text-transform: uppercase;
  }
  .nav-group-btn .nav-caret { display: none; }
  /* ⛔ O `visibility: visible` daqui SAIU de proposito, e tirar era o conserto.
     Ele era incondicional, e por isso ganhava ao `visibility: hidden` que o
     `.nav-right` fechado impoe — `visibility` e herdada mas o descendente PODE
     desfaze-la, ao contrario de `inert`. Resultado medido a 2026-08-22, em 11 das
     14 rotas BR (todas as que trazem o menu "Como pesquisar"), a 1280 e a 375 px,
     nos dois temas: numa carga fria, sem ninguem abrir o hamburger, as tres
     primeiras paradas de Tab caiam em "Como usar?", "Conceitos" e "Atlas" — links
     focaveis com `checkVisibility()` a devolver false, porque o pai fechado os
     corta a altura zero com `max-height:0; overflow:hidden`. Quem navega por
     teclado ficava tres paradas sem ver foco nenhum, em todo o carregamento de
     pagina. WCAG 2.4.7 (AA).
     ⭐ A correcao nao e esconder o menu outra vez: e deixar de o REVELAR quando o
     pai esta fechado. Aberto, `.nav-right.open` ja e `visibility: visible` e o
     menu herda-o — nao ha regra a escrever para o caso bom. */
  .nav-group-menu {
    position: static; transform: none; opacity: 1; pointer-events: auto;
    min-width: 0; padding: 0; background: none; border: 0; box-shadow: none;
  }
  /* ⛔ E esta linha existe por causa de ESPECIFICIDADE, nao de ordem no ficheiro.
     A regra de revelacao do popup de desktop e `.nav-group-btn[aria-expanded="true"]
     + .nav-group-menu` (0,3,0) e traz `transform: translateX(-50%)`. O reset do
     drawer acima e so `.nav-group-menu` (0,1,0): esta DEPOIS no ficheiro e mesmo
     assim PERDE. Entre 1080 e 1328 px — faixa que inclui os 1280 px — o CSS achava
     que estava no drawer e o JS achava que estava no desktop, entao a regra do popup
     casava e empurrava a linha focada para fora do ecra. Medido: `getBoundingClientRect().x`
     entre -515 e -529, com so uma lasca do anel dourado visivel. A 375 px nao
     acontecia. Repetir o seletor com a mesma especificidade e o que devolve a
     ultima palavra a quem esta certo aqui.
     ⭐ Desde 2026-09-01 esta faixa de desacordo esta VAZIA: o drawer do CSS desceu
     para <=1080 e o desktop do app.js comeca em >=1081, ou seja os dois passaram a
     concordar no MESMO numero. A linha FICA, e de proposito: ela nao custa pixel
     nenhum e continua a ser o unico anteparo se algum dia o guarda do app.js
     mudar de valor sem que este bloco mude junto — apaga-la seria reabrir um
     defeito WCAG ja pago em troca de nada. */
  .nav-group-btn[aria-expanded="true"] + .nav-group-menu { transform: none; }
  /* ⚠️ E esta e a outra metade, sem a qual o conserto acima vira defeito novo: a
     regra BASE de `.nav-group-menu`, fora desta media query, impoe
     `visibility: hidden` para o popup de desktop. Ao tirar o `visible`
     incondicional la de cima, o submenu passaria a ficar escondido tambem com a
     gaveta ABERTA — trocando "tres paradas invisiveis" por "menu que nunca
     aparece". Aqui ele volta, mas so quando `.nav-right` esta mesmo aberto, que
     e a condicao que faltava desde o inicio. */
  .nav-right.open .nav-group-menu { visibility: visible; }
  /* The hover bridge only exists for the desktop popup; in the flattened drawer it would
     overlay a stray absolute slab, so remove it. */
  .nav-group-menu::before { display: none; }
  .nav-group-item { padding: 14px 12px; border-bottom: 1px solid var(--hair); font-size: 0.95rem; color: var(--ink-soft); }
  /* <button> item (Sair do menu do usuário): a mesma hairline do <a> no drawer. */
  button.nav-group-item { border-bottom: 1px solid var(--hair); }
  /* Tema claro no drawer: o painel tinha fundo navy hardcoded (#0a0d16) mas os
     links usam tokens que flipam para o claro — .nav-link (--muted) ~2,9:1
     sobre o painel escuro (FAIL AA, quase invisível). Servir um painel creme
     no claro devolve o contraste dos tokens. ".nav-entrar" (pill dourado
     tema-invariante --btn-gold-hi/lo + tinta fixa #1c1917) já é AA nos dois
     temas por construção — sem precisar de override aqui (a regra antiga que
     pintava --ink/--rule nele ficou órfã quando ele deixou de ser ghost-button
     e foi removida). ".nav-cta" (outline com --gold) também já é AA em claro. */
  [data-theme='light'] .nav-right {
    background: #f6f3ea;
    box-shadow: 0 28px 60px -30px rgba(26, 31, 46, 0.25);
    border-bottom-color: var(--rule);
  }
}

/* =========================================================
   BANDA COMPACTA DO HEADER : 1081-1329px  (2026-09-01)
   =========================================================
   O drawer desceu de 1329 para 1080 (ver a derivação no bloco acima). Isto é o
   que PAGA a descida: a barra horizontal não cabia nesta faixa por conta própria,
   e sem estas cinco declarações o resultado seria o `overflow-x: clip` do
   `.nav-right` a decapitar "Cadastre-se" em silêncio — que é PIOR do que o
   hambúrguer, porque o hambúrguer pelo menos se vê.

   MEDIDO (2026-09-01, esta árvore servida em 127.0.0.1, Chromium/playwright
   1.62.1, deviceScaleFactor 1, página `index` — a de nav mais larga). Sem nada
   disto, a 1081px: o conteúdo do `.nav-right` pede 912px e tem 654px. O buraco de
   258px fecha-se assim, e nenhuma linha aqui é enfeite:

     - legenda da marca fora .............. -133px de conteúdo (a marca cai 184→112)
     - gutter do topbar 5vw → 20px ........ +62px de caixa a 1081px
     - `nav { gap }` 16 → 12px ............ +8px
     - pills com padding-inline 12px ...... -14px de conteúdo
     - corpo do nav 15,2 → 13,6px no piso . -80px de conteúdo

   ⭐ POR QUE APERTAR O GUTTER DA BARRA NÃO É INVENÇÃO. Acima de 1330px o
   `.topbar .wrap` já tem teto de 1360px contra os 1200px das secções, ou seja o
   header JÁ não alinha com a coluna de conteúdo por decisão anterior. Medido a
   2026-09-01: a marca começa 65px (a 1330) a 80px (a 1440+) à esquerda de onde a
   coluna de texto começa. Esta banda estende para baixo a mesma ideia — e o gutter
   é FLUIDO (20px a 1081, 56px a 1329) precisamente para chegar a 1329 com os
   mesmos 56px que a regra base usa a 1330: medido, o desalinho fecha em 64,5px vs
   65,0px, portanto atravessar o limite não salta a barra na horizontal.

   Resultado no ponto MAIS APERTADO (1081px): folga de 32,3px com Inter e 18,1px
   no primeiro frame (com 'Inter Fallback', antes de o woff2 chegar). As duas são
   MAIORES que os 20,0px / 16,4px que o desenho já aceite tem no seu próprio
   limite, os 1330px — ou seja, esta banda não é mais frágil que o que ela estende.

   O QUE NÃO CEDEU, e porquê: o `margin-left: 14px` do toggle de tema (ruling do
   operador 2026-07-05, valia +10px e é exatamente o defeito visual que o ruling
   fechou); o `gap: 8px` do `.nav-auth` (o par Entrar/Cadastre-se tem de continuar
   a ler como UM bloco); o lockup da marca fora a legenda; e a IA da barra — dobrar
   dois links dentro de "Como pesquisar" valia ~148px e resolvia isto sozinho, mas
   é HTML e é decisão de arquitetura de informação, não de folha de estilo.

   ⭐ A legenda "Inteligência Jurídica" é `aria-hidden` e o nome acessível da marca
   é o `aria-label="IAJUS Inteligência Jurídica"`, que CONTÉM o rótulo visível que
   sobra ("IAJUS") — WCAG 2.5.3 continua satisfeito. O precedente é a regra de
   `max-width: 420px` mais acima nesta folha, que já cede a mesma legenda pelo mesmo
   motivo: o símbolo + o wordmark continuam a identificar a marca sozinhos.

   ⚠️ O corpo do nav é FLUIDO de propósito: 13,6px a 1081 e 15,2px a 1329, que é
   exatamente o `0.95rem` da regra base. Assim NÃO há salto de tipografia ao
   atravessar 1329→1330 — só a legenda reaparece. Se `--font-nav` ou os rótulos
   mudarem, o número a re-medir é a folga a 1081px, não este clamp. */
@media (min-width: 1081px) and (max-width: 1329px) {
  .topbar .brand small { display: none; }
  /* 20px (o piso do --gutter) a 1081 → 56px (o teto) a 1329, para encontrar a
     regra base exatamente no limite da banda. Derivação: 36px de subida em 248px
     de viewport = 14,516vw − 136,92px. */
  .topbar .wrap { padding-inline: clamp(20px, 14.516vw - 136.92px, 56px); }
  .topbar nav { gap: 12px; }
  .topbar .nav-link { font-size: clamp(0.85rem, 0.414rem + 0.645vw, 0.95rem); }
  .topbar .nav-link.nav-cta,
  .topbar .nav-link.nav-entrar { padding-inline: 12px; }
}

/* Scrim do drawer mobile: cobre toda a viewport por baixo do painel e acima do
   conteúdo, escurece o resto da página e fecha o menu ao toque. Inerte e invisível
   enquanto o menu está fechado (sem .open). z-index abaixo do .topbar (30) para o
   painel e o botão hambúrguer continuarem clicáveis por cima. */
.nav-scrim {
  position: fixed; inset: 0; z-index: 25;
  background: rgba(0, 0, 0, 0.55);
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity .25s ease, visibility .25s ease;
}
.nav-scrim.open { opacity: 1; visibility: visible; pointer-events: auto; }
/* Trava a rolagem do body enquanto o drawer está aberto (a classe vai no <html>). */
html.nav-open, html.nav-open body { overflow: hidden; }
/* overflow:hidden no <html> DESGRUDA a topbar position:sticky — ela volta ao fluxo,
   que fica fora da tela depois que a página rolou, e leva junto o drawer (absolute,
   top:100% da topbar) ancorado nela. Era a causa do "o menu não abre depois de
   rolar": ele abria, mas off-screen acima da viewport. Fixar a topbar à viewport
   enquanto o menu está aberto mantém header e drawer colados ao topo em qualquer
   posição de rolagem. Só atua com o menu aberto (hambúrguer = mobile/tablet). */
html.nav-open .topbar { position: fixed; top: 0; left: 0; right: 0; }
@media (min-width: 1081px) {
  /* Acima do breakpoint do drawer (1080 desde 2026-09-01) o scrim nunca aparece
     (nav horizontal). Este `min-width` é o par obrigatório do `max-width` do
     drawer: se ficasse em 1330 haveria uma faixa 1081-1329 com barra horizontal
     e um scrim ainda no DOM à espera de `.open` — o `display:none` é o que o
     mantém inerte fora do drawer. */
  .nav-scrim { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .nav-scrim { transition: none; }
}

/* NOTA: o bloco dedicado .concept-page do drawer (min-width:1081/max-width:1239)
   foi REMOVIDO — o drawer genérico (@media max-width:1239px acima) já cobre as
   páginas de conceito em toda a faixa e agora carrega o override de tema claro.
   O bloco antigo divergia (fundo translúcido 0.97 vs opaco, max-height 70vh vs
   full) e sobrepunha o canônico por especificidade. */

/* =========================================================
   HERO : asymmetric editorial split
   ========================================================= */
header { position: relative; z-index: 1; padding-block: clamp(48px, 7vw, 96px) clamp(36px, 5vw, 64px); }
.hero-grid {
  display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
  gap: clamp(28px, 5vw, 72px); align-items: start;
}
/* #108 H1 (auditoria 23/09): no hero de 2 colunas a 1440×900 o CTA primário «Continuar
   cadastro» terminava em y=1019 — o H1 a 5rem ocupava 5 linhas (417px). Em desktop baixo o
   H1 da home usa o MESMO teto do H1 das páginas internas (.page-head h1, 3.6rem) e o topo
   do hero fica no piso do seu próprio clamp (48px). Medido (2026-09-24, Chromium): o botão
   do CTA termina em y=776 a 1440×900, clicável com o aviso de cookies aberto. O limite de altura vem da geometria sem este bloco: o CTA
   termina em ~1019px, logo abaixo de 1050px ele não caberia. Largura e mobile inalterados. */
@media (min-width: 881px) and (max-height: 1050px) {
  #view-home header { padding-top: 48px; }
  #view-home header h1 { font-size: clamp(2.5rem, 1.4rem + 5.2vw, 3.6rem); }
}
.eyebrow {
  display: inline-flex; align-items: center; gap: 11px;
  font-family: 'Fira Code', monospace;
  font-size: var(--step-eyebrow); letter-spacing: var(--track-eyebrow); text-transform: uppercase;
  color: var(--gold); font-weight: 500; margin-bottom: 18px;
}
/* Eyebrow tick: quiet ink, not gold frame bar (operador 2026-07-21). */
.eyebrow::before { content: ""; width: 28px; height: 1px; background: color-mix(in srgb, var(--ink) 22%, transparent); }
/* h2.page-h1 (2026-07-19, audit landing P1): no master SPA só a home tem <h1>;
   as demais views usam <h2 class="page-h1"> com o MESMO visual (o prerender a
   promove a <h1> na página estática da rota — 1 h1 por URL). */
h1, h2.page-h1 {
  font-family: 'Lora', 'Lora Fallback', Georgia, serif; font-weight: 500;
  font-size: clamp(2.5rem, 1.4rem + 5.2vw, 5rem); line-height: 1.02;
  letter-spacing: -0.025em; text-wrap: balance; margin-bottom: 26px;
}
h1 .hl, h2.page-h1 .hl { color: var(--gold); font-style: italic; font-weight: 500; }
/* H1 highlight underline: quiet ink hairline, not gold frame bar (operador 2026-07-21). */
h1 .hl::after, h2.page-h1 .hl::after {
  content: ""; display: block; height: 1px; margin-top: 8px; max-width: 7ch;
  background: color-mix(in srgb, var(--ink) 18%, transparent);
  transform-origin: left; transform: scaleX(0);
}
.js h1 .hl::after, .js h2.page-h1 .hl::after { animation: underline 1.1s .5s cubic-bezier(.22,.61,.36,1) forwards; }
@keyframes underline { to { transform: scaleX(1); } }
.lede {
  font-size: clamp(1.08rem, 1rem + 0.5vw, 1.32rem); color: var(--ink-soft);
  max-width: 54ch; line-height: 1.68;
}
.lede strong { color: var(--ink); font-weight: 500; }
/* Abrangência: linha secundária abaixo do lede que declara a cobertura real
   (26 estados + DF, tribunais de contas, órgãos administrativos, municípios). */
.lede-abrangencia {
  font-size: clamp(0.98rem, 0.92rem + 0.35vw, 1.12rem); color: var(--ink-soft);
  max-width: 62ch; line-height: 1.62; margin-top: 12px;
}
.lede-abrangencia strong { color: var(--ink); font-weight: 500; }
.hero-cta { display: flex; gap: 14px; flex-wrap: wrap; margin-top: 36px; }
/* Ação secundária do hero: o link "Ver a demonstração" abaixo do form de e-mail.
   Discreto (não compete com a ação primária dourada), com underline animado. */
.hero-secondary { margin-top: 16px; }
.hero-demo-link {
  display: inline-flex; align-items: center; gap: 7px;
  font-family: var(--font-nav); font-weight: 500; font-size: 0.98rem;
  color: var(--muted); text-decoration: none; transition: color .2s ease;
}
.hero-demo-link:hover, .hero-demo-link:focus-visible { color: var(--gold); }

/* Faixa de canais do hero (.hero-canais) REMOVIDA 2026-07-18 (ruling operador via B
   seq2303): os chips de texto eram redundantes com a .plat-strip de logos logo abaixo.
   A fileira de logos (7 coins, com Email) ficou sendo o único sinal de canais no hero. */

/* Counter : the typographic monument */
.counter-card {
  position: relative;
  /* Optical nudge (two-column hero only) so the card aligns with the headline,
     not the eyebrow, now that the grid is top-aligned. Reset to 0 on one-column
     layouts in the <=880px block below, where there is no headline to align to. */
  margin-top: clamp(0px, 2vw, 28px);
  /* Neutral hair frame — never gold --rule (operador 2026-07-21 anti-linha-amarela). */
  border: 1px solid var(--hair); border-radius: 20px;
  padding: clamp(28px, 4vw, 40px) clamp(24px, 3vw, 34px);
  background:
    linear-gradient(165deg, rgba(255,255,255,0.04), transparent 55%),
    var(--bg-2);
  box-shadow: 0 40px 90px -50px rgba(0,0,0,0.9), inset 0 1px 0 rgba(255,255,255,0.04);
  overflow: hidden;
  /* Guarda anti-clip do monumento (operador 2026-07-23, print: último dígito cortado
     a ~1000px): o card vira container e o .counter-num ganha um teto em cqw — o número
     NUNCA excede o miolo, em qualquer banda. Mata a classe dos caps por banda (o de
     1081-1329 ficou; a banda 881-1080 estava SEM cap e clipava 60px medidos). */
  container-type: inline-size;
}
.counter-card::before {
  content: "N.º"; position: absolute; top: 16px; right: 20px;
  font-family: 'Fira Code', monospace; font-size: 0.7rem; letter-spacing: 0.2em;
  color: var(--muted-2);
}
.counter-eyebrow {
  font-family: 'Fira Code', monospace; font-size: 0.72rem; letter-spacing: var(--track-eyebrow);
  text-transform: uppercase; color: var(--muted); margin-bottom: 14px;
}
.counter-num {
  font-family: 'Lora', 'Lora Fallback', Georgia, serif; font-weight: 600;
  /* Lora numerals run ~6% wider than Fraunces: smaller cap + tighter tracking
     keep the 8-digit acervo count inside the card (was clipping at 4.4rem). */
  font-size: clamp(2.6rem, 1.5rem + 4.6vw, 4.05rem); line-height: 0.98;
  /* Teto por container (browsers sem cqw ignoram esta 2ª declaração e ficam com a de
     cima): 100cqw = CONTENT-box do card (padding já fora); orçamento de glifos do
     acervo de 10 chars em Lora tnum = 5,55em medidos → 5,9em com folga. */
  font-size: min(clamp(2.6rem, 1.5rem + 4.6vw, 4.05rem), calc(100cqw / 5.9));
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums; font-feature-settings: "tnum";
  background: linear-gradient(180deg, #fff7f3 18%, var(--gold) 125%);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: var(--gold);
}
/* Forced-colors / Windows High Contrast: the gradient is dropped and the
   transparent text-fill would otherwise hide the big stat numbers. Restore an
   opaque fill so .counter-num / .ah-num stay legible (content untouched). */
@media (forced-colors: active) {
  .counter-num, .ah-num {
    -webkit-text-fill-color: currentColor;
    color: CanvasText;
    background: none;
  }
}
/* Light mode: the dark-tuned gradient (#fff7f3 -> gold) starts near-white, so the
   top ~18% of each glyph vanishes on the cream surface (operator: "o número não
   aparece direito no modo claro"). Repaint legibly in light: a gold-bright -> ink
   ramp keeps the editorial character but every part of the numeral clears AA
   (gold-bright ~6.5:1, ink ~15:1 on #faf8f2). Dark mode keeps the original. */
[data-theme='light'] .counter-num,
[data-theme='light'] .ah-num {
  background: linear-gradient(180deg, var(--gold-bright) 0%, var(--ink) 115%);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: var(--ink);
}
.counter-label { color: var(--text-primary); font-size: 0.98rem; margin-top: 12px; line-height: 1.5; }
/* V3: sub-linhas do counter (normas + doutrina aberta) — o acervo não é só juris. */
.counter-subs { list-style: none; margin: 14px 0 0; padding: 0; display: flex; flex-direction: column; gap: 7px; }
.counter-subs li { display: flex; align-items: baseline; gap: 9px; color: var(--muted); font-size: 0.9rem; line-height: 1.4; }
.counter-subs .cs-val { font-family: 'Fira Code', monospace; font-weight: 600; font-size: 0.98rem;
  color: var(--ink-soft); font-variant-numeric: tabular-nums; }

/* ⛔ Estado LOCAL de indisponibilidade do cartão de contadores (2026-08-23).
   O cartão ficava com os rótulos ("decisões · órgãos · todas as Justiças") e SEM
   número nenhum quando `/api/stats/public` não responde — vazio sem sinal, no
   elemento mais proeminente da home. A frase honesta existia, mas só no
   `.stats-error` do painel `/cobertura`, que na home mede 0x0 dentro de `[hidden]`.
   ⭐ A regra prende-se à PRESENÇA REAL da frase, não a um atributo paralelo: quem a
   escreve é `stats.js::clearVisibleStats`, e é o mesmo texto que ele já punha no
   `.stats-error`. Assim o estado visual e o texto honesto não podem divergir — não há
   caminho em que os números desapareçam sem que a explicação esteja escrita ao lado.
   ⚠️ A direção da degradação foi escolhida, não sofrida: num motor sem `:has()` a
   regra cai inteira e o cartão fica com a FRASE mais os campos vazios. Fica feio;
   continua honesto. O contrário — esconder os números e perder a frase — seria voltar
   ao defeito, e por isso a frase NUNCA depende de `:has()` para aparecer.
   ⚠️ `.counter-spark` entra na lista de propósito: é uma sparkline ILUSTRATIVA de
   crescimento (`aria-hidden`), e uma curva a subir ao lado de "não medido" afirma
   com desenho o que o texto acabou de negar.
   ⛔ NUNCA pôr `display:none` no `.counter-unavailable`: ele é a região viva
   (`role="status"`), e uma região viva não-renderizada não é anunciada quando o texto
   entra. Vazio ele já não ocupa altura — um <p> sem conteúdo não gera linha —, por
   isso zera-se só a caixa e nunca a renderização. */
.counter-unavailable { margin: 0; padding: 0; border: 0; }
.counter-unavailable:not(:empty) {
  margin-top: 12px; color: var(--text-primary); font-size: 0.98rem; line-height: 1.5;
}
.counter-card:has(.counter-unavailable:not(:empty)) .counter-num,
.counter-card:has(.counter-unavailable:not(:empty)) .counter-label,
.counter-card:has(.counter-unavailable:not(:empty)) .counter-subs,
.counter-card:has(.counter-unavailable:not(:empty)) .counter-spark { display: none; }

/* V3: banda tri-famílias (jurisprudência · normativos · doutrina) logo sob o hero. */
.tri-familias {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px;
  margin-top: clamp(28px, 4vw, 46px);
}
/* Text inside a fading ancestor temporarily missed AA while the reveal opacity
   crossed intermediate values. Keep this information-bearing band opaque; the
   existing translateY transition still provides the entrance cue. */
.js .tri-familias.reveal { opacity: 1; }
@media (max-width: 820px) { .tri-familias { grid-template-columns: 1fr; } }

/* P2-6 (audit landing 2026-07-19; GO B seq2618): sumário de âncoras da home,
   SÓ mobile — em 390px a home passa de 14 telas de rolagem, então as fichas
   levam direto às seções-chave. Escondido no desktop (a jornada inteira já
   cabe em poucas telas e o nav global cobre as rotas).
   Desktop sem barra sticky (bug ao vivo operador 2026-07-20): a pill flutuante
   duplicava itens do nav global (Demonstração/Plataformas) e cobria o conteúdo
   ao rolar. Removida a variante >=861px; resta só a móvel abaixo. */
.home-toc { display: none; }
@media (max-width: 860px) {
  .home-toc {
    display: flex; gap: 8px; overflow-x: auto;
    margin-top: 20px; padding: 2px 2px 10px;
    scrollbar-width: none; /* trilho invisível; a rolagem continua disponível */
  }
  .home-toc::-webkit-scrollbar { display: none; }
  .home-toc a {
    flex: none; display: inline-flex; align-items: center; min-height: 44px;
    padding: 0 16px; border: 1px solid var(--hair); border-radius: 999px;
    color: var(--muted); text-decoration: none; font-size: 0.82rem; white-space: nowrap;
    transition: color .2s ease, border-color .2s ease;
  }
  .home-toc a:hover { color: var(--gold); border-color: var(--gold); }
}
.tri-card {
  display: flex; flex-direction: column; gap: 4px;
  padding: clamp(20px, 2.6vw, 28px); text-decoration: none;
  background: var(--bg-2); border: 1px solid var(--hair); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  transition: border-color .2s ease, transform .2s ease, box-shadow .2s ease;
}
/* WS-2 hover "card-strong": the whole card lifts, the gold edge warms and the
   rule + kicker + arrow all light up together, so the card reads as one clickable
   object (it is an <a>). Reduced-motion keeps the color cues, drops the lift. */
.tri-card:hover, .tri-card:focus-visible {
  border-color: var(--gold); transform: translateY(-4px);
  box-shadow: 0 26px 54px -30px rgba(0,0,0,0.6), 0 0 0 1px var(--gold) inset;
}
.tri-card:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-ring-offset); }
@media (prefers-reduced-motion: reduce) { .tri-card:hover, .tri-card:focus-visible { transform: none; } }
.tri-ic { color: var(--gold); margin-bottom: 8px; display: block; }
/* WS-2 kicker: mono family label above the name (mirrors the section .kicker idiom). */
.tri-kicker {
  font-family: 'Fira Code', ui-monospace, monospace; font-size: 0.72rem; font-weight: 600;
  letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-tertiary);
  transition: color .2s ease;
}
.tri-card:hover .tri-kicker, .tri-card:focus-visible .tri-kicker { color: var(--gold-bright); }
/* WS-2 golden rule: a hairline that grows from the left (scaleX 0→1) when the card
   reveals, and firms up on hover. Purely decorative (aria-hidden in the markup). */
.tri-rule {
  height: 2px; width: 44px; margin: 8px 0 4px; border-radius: 2px;
  background: linear-gradient(90deg, var(--gold), var(--gold-bright));
  transform: scaleX(0); transform-origin: left center;
  transition: transform .5s cubic-bezier(.16,.84,.44,1) calc(var(--tri-i, 0) * 90ms + 120ms),
              width .2s ease;
}
.tri-familias.in .tri-rule { transform: scaleX(1); }
.tri-card:hover .tri-rule, .tri-card:focus-visible .tri-rule { width: 60px; }
@media (prefers-reduced-motion: reduce) {
  .tri-rule { transform: scaleX(1); transition: none; }
}
.tri-name {
  font-family: 'Lora', 'Lora Fallback', Georgia, serif; font-weight: 600; font-size: 1.28rem; color: var(--ink);
}
.tri-sub { color: var(--text-secondary); font-size: 0.9rem; line-height: 1.45; margin-top: 6px; }
.tri-go {
  margin-top: 14px; font-family: 'Fira Code', monospace; font-size: 0.82rem; font-weight: 600;
  letter-spacing: 0.02em; color: var(--ink-soft);
  display: inline-flex; align-items: center; gap: 6px;
}
.tri-card:hover .tri-go { color: var(--gold-bright); }

.counter-live {
  display: inline-flex; align-items: center; gap: 9px; margin-top: 18px;
  font-family: 'Fira Code', monospace; font-size: 0.78rem; color: var(--gold);
  padding-top: 16px; border-top: 1px solid var(--hair); width: 100%;
}
.pulse { width: 8px; height: 8px; border-radius: 50%; background: var(--gold); position: relative; flex: none; }
.pulse::after {
  content: ""; position: absolute; inset: -5px; border-radius: 50%;
  border: 1px solid var(--gold); animation: pulse 2.4s ease-out infinite;
}
@keyframes pulse { 0% { transform: scale(0.5); opacity: 1; } 100% { transform: scale(2.4); opacity: 0; } }

@media (max-width: 880px) {
  .hero-grid { grid-template-columns: 1fr; }
  .counter-card { max-width: 520px; margin-top: 0; }
}
/* Mobile above-the-fold (addendum operador 2026-07-07 #3): o TÍTULO do hero (o que
   o produto é) + a faixa de canais + o CTA vêm PRIMEIRO; só depois o card de
   números. Antes o card subia (`order:-1`) e empurrava o título para baixo da
   dobra no celular. A ordem agora é a do DOM (hero-copy → counter-card), então
   não há regra de `order` aqui: o texto lidera. */
@media (max-width: 560px) {
  .counter-card { order: 0; margin-top: 4px; }
  /* A legenda da marca subia 8.8px (ilegível). No mobile ela só divide espaço com
     o hamburguer, então cresce p/ ~10.9px sem risco de invadir o nav. (Esta regra
     vem DEPOIS de `.brand small` base — senão a ordem de origem a sobrescreveria.) */
  .brand small { font-size: 0.68rem; }
}
/* ≤374px: o monumento de 10 dígitos precisa CABER — a fonte cede (clamp), o
   número jamais quebra (guarda anti-quebra global). Bug corrigido 2026-06-12:
   o piso de 2.6rem estourava o card a 320px e o break-word herdado do body
   partia o último dígito para a linha de baixo, sem hífen. */
@media (max-width: 374px) {
  .counter-num {
    font-size: clamp(1.7rem, 9.4vw, 2.5rem);
    font-size: min(clamp(1.7rem, 9.4vw, 2.5rem), calc(100cqw / 5.9));
  }
}
/* 1081-1329px (hero ainda 2-col): o card fica estreito e o clamp global
   (cap 4.05rem) estourava — a 1100px o número media 360px num box de 329px e o
   último dígito era CLIPADO (flagrado na revisão página-a-página 2026-07-02).
   Cap da banda: 3.5rem ≈ 309px de dígitos, folga nos dois extremos.
   ⚠️ Esta banda JÁ NÃO acompanha o breakpoint do drawer, e a coincidência dos
   números é acidental (2026-09-01): o drawer desceu para <=1080 e o que hoje
   ocupa 1081-1329 é a BANDA COMPACTA DO HEADER, que é outra coisa. A razão desta
   regra nunca foi o nav — é a largura do `.counter-card` na grelha de 2 colunas
   do hero, que não depende da barra de topo. Quem quiser mexer num dos dois
   números não arrasta o outro. */
@media (min-width: 1081px) and (max-width: 1329px) {
  .counter-num {
    font-size: clamp(2.6rem, 1rem + 3.6vw, 3.5rem);
    font-size: min(clamp(2.6rem, 1rem + 3.6vw, 3.5rem), calc(100cqw / 5.9));
  }
}

/* =========================================================
   ACERVO : family stats strip (juris ∪ legis ∪ doutrina ∪ qualificadas)
   ========================================================= */
.acervo { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px;
  border: 1px solid var(--hair); border-radius: 18px; overflow: hidden; background: var(--hair); }
.acervo .stat { background: var(--bg-2); padding: clamp(22px, 3vw, 32px); position: relative; }
.acervo .stat .ic { color: var(--gold); margin-bottom: 14px; display: block; }
.acervo .stat .v {
  font-family: 'Lora', 'Lora Fallback', Georgia, serif; font-weight: 600;
  /* max 2.05rem: "13.748.995" must fit one line in a 4-col cell at 1280px */
  font-size: clamp(1.55rem, 1rem + 1.7vw, 2.05rem); line-height: 1; letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums; font-feature-settings: "tnum"; color: var(--ink);
}
.acervo .stat .k { color: var(--muted); font-size: 0.95rem; margin-top: 8px; line-height: 1.45; }
.acervo .stat .sub { color: var(--muted-2); font-size: 0.82rem; margin-top: 4px;
  font-family: 'Fira Code', monospace; }
/* display:block (2026-07-19, audit landing P2-3): o span inline colava o timestamp
   ao fim da frase da lede ("...nada além disso. Acervo atualizado em..."), lendo
   como continuação da prosa. Em bloco ele vira a linha de fine-print que é. */
.stats-updated { display: block; margin-top: 14px; font-family: 'Fira Code', monospace;
  font-size: 0.74rem; letter-spacing: 0.04em; color: var(--muted-2); }
/* ⛔ Re-afirma o [hidden] do UA por cima do `display: block` da `.stats-updated` acima.
   O MECANISMO ja esta explicado em `.counter-foot--live[hidden]`, nesta mesma folha: o
   `[hidden]{display:none}` do UA e (0,1,0), uma regra de classe do autor tambem e (0,1,0), e
   em empate de especificidade o AUTOR vence o UA -- logo o `hidden` do HTML nao surte efeito.
   Esta e a mesma familia de defeito em mais quatro classes; as outras remetem para aqui.
   Os quatro `.stats-updated` nascem `hidden` no HTML e so o stats.js os revela quando a data
   chega (applyStampTo -> holder.hidden = false). Sem esta linha, com o dado em falta, a pessoa
   lia a frase de frescor partida -- "Numeros conferidos em ." -- data ausente e ponto final
   orfao, e a arvore de acessibilidade a anunciava como `paragraph`. Medido em 2026-08-22, com
   o stats.js sem dado: caixa de 1088x19 a 1280px e 280x58 a 320px, checkVisibility() = true. */
.stats-updated[hidden] { display: none; }
/* Prosa explicativa curta sob o acervo (funil de curadoria, doutrina aberta): a
   .stats-updated mono 0.74rem é o device de timestamp/fine-print — usá-la para
   frases importantes de honestidade as fazia parecer rodapé ilegível. Prosa de
   leitura de verdade, cap de medida. */
.stats-note { margin-top: 10px; font-size: 0.92rem; line-height: 1.55;
  color: var(--text-secondary); max-width: 62ch; }
@media (max-width: 980px) { .acervo { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px) { .acervo { grid-template-columns: 1fr; } }
/* A faixa-resumo da /cobertura tem 4 cards (V2: decisões / normas / qualificadas /
   doutrina aberta) — usa o grid default de 4 colunas, com step 2x2 no tablet e
   1-col no telefone (as regras genéricas .acervo @980/@520 já cobrem, mas o
   #view-cobertura precede a especificidade delas, então repõe os steps aqui). */
@media (max-width: 980px) { #view-cobertura .acervo { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px) { #view-cobertura .acervo { grid-template-columns: 1fr; } }
/* A faixa .acervo do /beta ('O que é o IAJUS') também tem só 3 .stat: sem esta
   regra herda o grid de 4 colunas e deixa uma 4ª célula-fantasma translúcida à
   direita. Mesmo fix da /cobertura, com o breakpoint 760 coerente. */
#view-beta .acervo { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 760px) { #view-beta .acervo { grid-template-columns: 1fr; } }
/* #623: o cartão «de série histórica» da home nasce `hidden` e só aparece com o intervalo
   medido. Omitido, a faixa fica com 3 .stat e herdaria a 4.ª célula-fantasma (e, no passo
   2x2, uma célula órfã): mesmo passo da faixa do /beta — 3 colunas, 1 abaixo de 760. */
.acervo:has(> .stat[hidden]) { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 760px) { .acervo:has(> .stat[hidden]) { grid-template-columns: 1fr; } }
/* #623: o intervalo «1988 a 2026» é mais largo que os números das células vizinhas; na grelha de
   4 colunas (>980px) ele quebrava em duas linhas a 1440 e descia a legenda abaixo das irmãs.
   Uma linha só, com corpo próprio só neste cartão e só nessa banda. */
@media (min-width: 981px) {
  .acervo .stat[data-serie-historica-cartao] .v {
    white-space: nowrap; font-size: clamp(1.4rem, 0.4rem + 1.5vw, 1.8rem);
  }
}
/* big numbers JAMAIS quebram (guarda anti-quebra de display no topo do arquivo);
   nota: break-word NÃO respeita pontos de milhar — partia dígito solto. Em célula
   estreita quem cede é a fonte (clamp acima), nunca a integridade do número. */

/* Instância split: três linhas (judicial, contas, administrativo) sob o acervo */
.instancia-split {
  list-style: none; display: flex; flex-wrap: wrap; gap: 10px 26px;
  margin-top: 16px; padding: 14px 18px;
  border: 1px solid var(--hair); border-radius: 14px; background: var(--bg-2);
}
.instancia-split li {
  display: flex; align-items: baseline; gap: 8px; min-width: 0;
  font-size: 0.92rem; color: var(--muted); line-height: 1.4;
}
.instancia-split .is-dot {
  width: 9px; height: 9px; border-radius: 3px; flex: none;
  align-self: center; transform: translateY(0.5px);
}
.instancia-split .is-judicial { background: var(--fam-tjs); }
.instancia-split .is-contas { background: var(--fam-tcs); }
.instancia-split .is-admin { background: var(--fam-administrativo); }
/* Legislação por esfera: swatches NEUTROS (contorno dourado) em vez de reusar os
   matizes de família (tjs/tcs/administrativo) — o mesmo roxo não pode significar
   'Justiça' numa lista e 'normas da União' na seguinte sem minar a semântica da
   paleta de famílias do donut logo abaixo. */
.instancia-split.is-esferas .is-dot {
  background: transparent; border: 1.5px solid var(--gold-soft);
}
/* Micro-rótulo do grupo (antes só em aria-label — usuário vidente via duas
   fileiras de números sem título). Mono caps, tom terciário. */
.split-label {
  font-family: 'Fira Code', ui-monospace, monospace; font-size: 0.7rem;
  letter-spacing: var(--track-label); text-transform: uppercase;
  color: var(--text-tertiary); margin: 16px 0 6px;
}
.instancia-split .is-val {
  font-family: 'Fira Code', monospace; font-weight: 600; color: var(--ink);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.instancia-split .is-k { color: var(--muted); min-width: 0; }
@media (max-width: 720px) { .instancia-split { flex-direction: column; gap: 9px; } }

/* Ontology graph container (the interactive canvas lives inside .tree-wrap) */
.tree-wrap { margin-top: 36px; display: grid; grid-template-columns: 1fr; gap: 16px; }

/* =========================================================
   BUTTONS
   ========================================================= */
.btn {
  display: inline-flex; align-items: center; gap: 9px;
  font-family: 'Fira Code', monospace; font-weight: 600; font-size: 0.92rem;
  letter-spacing: 0.02em; text-decoration: none;
  /* Raio "de ação" canônico via token (F-A / S3 2026-07-07): era 12px cru. */
  padding: 15px 26px; border-radius: var(--radius-md); cursor: pointer; border: 0;
  transition: transform .16s ease, box-shadow .24s ease, background .24s ease, border-color .24s ease, color .24s ease;
}
.btn .arrow { transition: transform .2s ease; }
.btn:hover .arrow { transform: translateX(4px); }
.btn-primary {
  /* A1 (design plan 2026-07-02): ouro-de-SUPERFÍCIE theme-invariant. Os --gold*
     do tema claro viram TEXTO escuro sobre creme e reprovam AA como superfície de
     botão; --btn-gold-hi/lo NÃO flipam. Tinta #1c1917 = 9,2:1 (topo) / 4,7:1 (base). */
  background: linear-gradient(180deg, var(--btn-gold-hi), var(--btn-gold-lo));
  color: var(--btn-gold-ink); box-shadow: var(--shadow-gold);
}
.btn-primary:hover { transform: translateY(-2px); box-shadow: var(--shadow-raised); }
.btn-ghost { background: rgba(255,255,255,0.02); color: var(--ink); border: var(--btn-border); }
.btn-ghost:hover {
  border-color: var(--gold); color: var(--gold);
  background: color-mix(in srgb, var(--gold) 6%, transparent);
  transform: translateY(-2px);
  box-shadow: 0 16px 38px -22px color-mix(in srgb, var(--gold) 40%, transparent);
}

/* =========================================================
   ÓRGÃOS ÍNDICE TIPOGRÁFICO (DI-L1, 2026-07-08): editorial colophon/index of every
   individual sigla, grouped by legal family. Replaces the WS-3 pill/dot marquee
   (anti-collision vs jusratio.com.br's coverage marquee — see
   docs/design/IAJUS_DESIGN_IDENTITY_2026-07-08.md §2/§6.4). No pill, no dot marker,
   no marquee.
   FB-D exploração progressiva (feedback ao vivo do operador 2026-07-10): cada família
   é um <details> nativo FECHADO por default. A primeira dobra mostra só o eyebrow da
   família + a contagem real de órgãos + chevron; as siglas aparecem ao expandir
   (clique/Enter/Espaço, semântica nativa de details/summary: teclado e estado
   anunciado sem JS; múltiplos grupos podem ficar abertos ao mesmo tempo). A transição
   de altura usa ::details-content + interpolate-size (progressive enhancement:
   navegador sem suporte faz toggle instantâneo, mesmo estado final) e morre sob
   prefers-reduced-motion: reduce.
   Baked from the órgão registry + corpus_stats.json::by_orgao by
   tools/build_orgaos_roster.py (do not hand-edit the markup between the
   ORGAOS_ROSTER markers in index.html).
   ========================================================= */
.orgaos-index {
  position: relative; z-index: 1; border-block: 1px solid var(--hair);
  padding-block: 28px;
  /* A seção vive FORA do .wrap (a borda full-bleed é intencional), mas o CONTEÚDO
     precisa alinhar à mesma coluna central de --maxw: sem isto, em monitores largos
     o eyebrow cola na borda esquerda e a contagem (margin-left:auto) na direita.
     padding % refere-se ao containing block (main, largura do viewport sem a barra
     de rolagem), então o cálculo centra sem overflow horizontal. */
  padding-inline: max(var(--gutter), calc((100% - var(--maxw)) / 2));
  /* Permite interpolar height: 0 -> auto na transição do ::details-content abaixo
     (propriedade herdada; navegadores sem suporte ignoram a declaração). */
  interpolate-size: allow-keywords;
  /* Text-safe family colors, local to the índice. The shared --fam-* tokens are tuned
     for WCAG 1.4.11 (>=3:1, graphical objects like dots/bars) and stay untouched for
     their other consumers (donut, instancia-split, atlas isles); AA body TEXT needs
     >=4.5:1, so the light theme below darkens each hue just enough to clear that bar
     (dark theme's --fam-* already clears >=4.5:1, so it is reused as-is). */
  --orgidx-superiores: var(--fam-superiores);
  --orgidx-tjs: var(--fam-tjs);
  --orgidx-trfs: var(--fam-trfs);
  --orgidx-trts: var(--fam-trts);
  --orgidx-tres: var(--fam-tres);
  --orgidx-tcs: var(--fam-tcs);
  --orgidx-administrativo: var(--fam-administrativo);
  --orgidx-militar: var(--fam-militar);
  --orgidx-default: var(--fam-default);
}
[data-theme="light"] .orgaos-index {
  --orgidx-tjs: #6762dd;
  --orgidx-trfs: #3978a3;
  --orgidx-trts: #337d62;
  --orgidx-tres: #a254a2;
  --orgidx-tcs: #95662e;
  --orgidx-administrativo: #8759bf;
  --orgidx-default: #74706d;
}
/* Lede de reconciliação (QA-UI "121 vs 137"): explica, com os números reais do
   registry + corpus_stats.json, por que o índice lista mais órgãos do que o contador
   "órgãos com acervo" da home. Mesma voz do .lede-abrangencia, em corpo menor por ser
   linha de apoio da seção (não o pitch principal). */
.orgidx-lede {
  margin: 0 0 18px; max-width: 68ch;
  font-size: 0.98rem; line-height: 1.6; color: var(--ink-soft);
}
.orgidx-lede strong { color: var(--ink); font-weight: 500; }
.orgidx-groups {
  /* Grid, não columns: com disclosure, expandir um grupo não pode re-balancear os
     grupos entre colunas no meio da interação (columns re-flui e o grupo "pula" de
     coluna; no grid cada grupo fica preso à sua célula e só a linha cresce). */
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: clamp(28px, 4vw, 56px); align-items: start;
}
.orgidx-group {
  margin: 0; min-width: 0;
  border-bottom: 1px solid var(--hair);
}
/* Linha-resumo do grupo (fechado por default): eyebrow + contagem + chevron.
   list-style/::marker matam o triângulo nativo do summary (o chevron abaixo é a
   affordance única, consistente nos dois temas). */
.orgidx-summary {
  display: flex; align-items: center; gap: 12px;
  padding-block: 14px; cursor: pointer; list-style: none;
  -webkit-tap-highlight-color: transparent;
}
.orgidx-summary::-webkit-details-marker { display: none; }
.orgidx-summary::marker { content: none; }
.orgidx-summary:focus-visible { outline: var(--focus-ring); outline-offset: 3px; border-radius: 4px; }
.orgidx-summary:hover .orgidx-eyebrow,
.orgidx-group[open] > .orgidx-summary .orgidx-eyebrow { color: var(--ink); }
.orgidx-eyebrow {
  display: flex; align-items: baseline; gap: 8px; margin: 0;
  font-family: 'Fira Code', ui-monospace, monospace; font-size: 0.74rem; font-weight: 600;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--muted-2);
  transition: color .15s ease;
}
.orgidx-star {
  color: var(--gold); font-weight: 600; font-size: 0.9em; line-height: 1;
}
.orgidx-count {
  margin-left: auto; flex: none;
  font-family: 'Fira Code', ui-monospace, monospace; font-size: 0.72rem; font-weight: 500;
  letter-spacing: 0.04em; color: var(--muted-2); white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.orgidx-chevron {
  flex: none; width: 8px; height: 8px; margin-right: 2px;
  border-right: 1.5px solid var(--muted-2); border-bottom: 1.5px solid var(--muted-2);
  transform: translateY(-2px) rotate(45deg);
  transition: transform .22s ease, border-color .15s ease;
}
.orgidx-summary:hover .orgidx-chevron,
.orgidx-group[open] > .orgidx-summary .orgidx-chevron { border-color: var(--gold); }
.orgidx-group[open] > .orgidx-summary .orgidx-chevron {
  transform: translateY(2px) rotate(-135deg);
}
/* Conteúdo do disclosure: altura anima 0 -> auto onde interpolate-size existe
   (Chromium atuais); nos demais a regra degrada para abrir/fechar instantâneo com o
   MESMO estado final. content-visibility em allow-discrete mantém as siglas visíveis
   durante o fechamento em vez de sumirem no primeiro frame. */
.orgidx-group::details-content {
  height: 0; overflow: clip;
  transition: height .3s ease, content-visibility .3s allow-discrete;
}
.orgidx-group[open]::details-content { height: auto; }
.orgidx-siglas {
  margin: 0; padding: 2px 0 16px; line-height: 2.1;
  /* Siglas are plain space-separated spans (real word-break opportunities); the
     middle-dot separator lives in ::before below so it can never be orphaned at a
     line start (it is always glued to the sigla that follows it). */
}
.orgidx-sigla {
  font-family: 'Fira Code', ui-monospace, monospace; font-weight: 500;
  color: var(--orgidx-default); text-decoration: none; cursor: default;
  text-underline-offset: 3px; text-decoration-thickness: 1px;
  transition: color .15s ease;
  /* Hyphenated siglas (TJ-RJ, TRE-AC) must never break at the hyphen: the sigla is
     one atomic label, only the space BETWEEN siglas is a valid wrap point. */
  white-space: nowrap;
}
.orgidx-siglas > .orgidx-sigla:not(:first-child)::before {
  content: "\00b7"; color: var(--muted-2); margin-right: 8px; font-weight: 400;
}
.orgidx-sigla:hover, .orgidx-sigla:focus-visible {
  text-decoration: underline; text-decoration-color: currentColor;
}
.orgidx-sigla:focus-visible { outline: var(--focus-ring); outline-offset: 2px; border-radius: 2px; }
/* Size tiers by real acórdão volume (corpus_stats.json::by_orgao); "base" = órgão has
   no count row yet (real coverage gap, not a fabricated zero — same single tier as
   the smallest measured órgãos). */
.orgidx-sigla.idx-base, .orgidx-sigla.idx-s { font-size: 0.8rem; }
.orgidx-sigla.idx-m { font-size: 0.92rem; }
.orgidx-sigla.idx-l { font-size: 1.08rem; font-weight: 600; }
/* Link para a via profunda (/cobertura) ao pé da grade de siglas: a contagem
   por órgão é extra no index e vive como texto visível só lá — o caminho até
   ela precisa ficar visível e focável junto do índice (decisão ARQ 95894). */
.orgidx-more { margin: 14px 0 0; }
.orgidx-group[data-familia="superiores"] .orgidx-sigla { color: var(--orgidx-superiores); }
.orgidx-group[data-familia="tjs"] .orgidx-sigla { color: var(--orgidx-tjs); }
.orgidx-group[data-familia="trfs"] .orgidx-sigla { color: var(--orgidx-trfs); }
.orgidx-group[data-familia="trts"] .orgidx-sigla { color: var(--orgidx-trts); }
.orgidx-group[data-familia="tres"] .orgidx-sigla { color: var(--orgidx-tres); }
.orgidx-group[data-familia="tcs"] .orgidx-sigla { color: var(--orgidx-tcs); }
.orgidx-group[data-familia="administrativo"] .orgidx-sigla { color: var(--orgidx-administrativo); }
.orgidx-group[data-familia="militar"] .orgidx-sigla { color: var(--orgidx-militar); }
@media (max-width: 900px) {
  .orgidx-groups { grid-template-columns: 1fr; }
}
@media (max-width: 560px) {
  .orgidx-eyebrow { font-size: 0.7rem; }
  .orgidx-count { font-size: 0.68rem; }
  .orgidx-sigla.idx-base, .orgidx-sigla.idx-s { font-size: 0.78rem; }
  .orgidx-sigla.idx-m { font-size: 0.88rem; }
  .orgidx-sigla.idx-l { font-size: 1rem; }
}
/* FB-D acessibilidade: sob reduced-motion o disclosure vira toggle instantâneo
   (nenhuma animação de altura/chevron/cor), mesmo conteúdo e estados. */
@media (prefers-reduced-motion: reduce) {
  .orgidx-group::details-content,
  .orgidx-chevron,
  .orgidx-eyebrow { transition: none; }
}

/* =========================================================
   SECTIONS
   ========================================================= */
/* Respiro vertical (decisão #85: py-20 desktop / py-10 mobile). Mais ar entre
   seções , o audit apontou espaçamento sufocado. ~44px mobile → ~104px desktop. */
section.block { padding-block: clamp(44px, 8vw, 104px); position: relative; z-index: 1; }
.sec-head { max-width: 64ch; }
.kicker {
  display: inline-flex; align-items: baseline; gap: 12px;
  font-family: 'Fira Code', monospace; color: var(--gold);
  font-size: 0.78rem; letter-spacing: var(--track-eyebrow); text-transform: uppercase;
  margin-bottom: 14px;
}
.kicker .idx { color: var(--muted-2); }
h2 {
  font-family: 'Lora', 'Lora Fallback', Georgia, serif; font-weight: 500; font-size: var(--step-h2);
  letter-spacing: -0.02em; line-height: 1.08; margin: 0 0 clamp(14px, 1.4vw, 22px); text-wrap: balance;
}
.intro { color: var(--text-primary); max-width: 62ch; font-size: 1.1rem; line-height: 1.66; }
.intro strong { color: var(--ink); font-weight: 500; }
/* Ressalva de período (TST/TRT/TRE = 2016-2026): asterisco que revela a nota
   no hover do mouse OU no foco (clique/teclado/toque), sem depender de JS. */
.cov-ressalva { position: static; display: inline; cursor: help; outline: none; }
/* Alvo de toque >=24px (WCAG 2.5.8) sem deslocar o glifo: inline-grid centrado +
   margens negativas que compensam o padding, então o '*' não empurra a linha. */
.cov-ressalva-mark { color: var(--gold); font-weight: 600;
  display: inline-grid; place-items: center; min-width: 24px; min-height: 24px;
  margin: -6px -7px; padding: 6px 7px; vertical-align: middle; }
/* The tip anchors to the whole PARAGRAPH (its positioned ancestor), never to the
   inline mark: a 280px box anchored at an arbitrary text-wrap position clips at a
   viewport edge (seen live at ~750px). Paragraph-anchored + clamped width cannot
   overflow; :has() scopes the positioning to paragraphs that carry a ressalva. */
.intro:has(.cov-ressalva), p:has(> .cov-ressalva) { position: relative; }
.cov-ressalva-tip {
  position: absolute; left: 0; top: calc(100% + 6px); z-index: 20; width: max-content;
  max-width: min(280px, calc(100vw - 2rem));
  background: var(--bg-2, #161616); color: var(--text-primary, #eee);
  border: 1px solid var(--hair, #333); border-radius: 8px; padding: 8px 11px;
  font-size: 0.82rem; line-height: 1.45; font-weight: 400; font-style: normal;
  box-shadow: 0 8px 24px rgba(0,0,0,0.4);
  opacity: 0; visibility: hidden; transform: translateY(-3px); transition: opacity .14s ease, transform .14s ease;
}
.cov-ressalva:hover .cov-ressalva-tip,
.cov-ressalva:focus .cov-ressalva-tip,
.cov-ressalva:focus-within .cov-ressalva-tip { opacity: 1; visibility: visible; transform: translateY(0); }
.cov-ressalva:focus-visible .cov-ressalva-mark { outline: 2px solid var(--gold); outline-offset: 2px; border-radius: 3px; }
/* (mobile right-anchor override removed: the paragraph-anchored tip above is
   already viewport-safe at every width) */

/* Glossário : termo de jargão com sublinhado pontilhado dourado que revela uma
   definição curta e sem jargão no hover / foco / toque. Mesmo mecanismo da
   .cov-ressalva (bolha ancorada ao CONTAINER posicionado, largura clampada = à
   prova de viewport, nunca ao meio da linha). glossary.js só acrescenta
   role=tooltip, aria-describedby (id único por instância) e o dispensar por Esc /
   toque; sem JS o termo continua legível, perde só a bolha (melhoria progressiva). */
.gloss {
  cursor: help; outline: none;
  text-decoration: underline dotted; text-decoration-color: var(--gold);
  text-decoration-thickness: 1px; text-underline-offset: 3px;
}
.gloss:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; border-radius: 3px; }
/* O container do termo vira a âncora do tip (mesma razão da .cov-ressalva: uma
   bolha ancorada num ponto arbitrário de quebra de linha corta na borda da tela). */
p:has(> .gloss), li:has(.gloss), td:has(.gloss), dd:has(.gloss),
h3:has(.gloss), h4:has(.gloss), summary:has(.gloss),
.intro:has(.gloss), figcaption:has(.gloss), .qual-line:has(.gloss) { position: relative; }
.gloss-tip {
  position: absolute; left: 0; top: calc(100% + 6px); z-index: 20; width: max-content;
  max-width: min(300px, calc(100vw - 2rem));
  background: var(--bg-2, #161616); color: var(--text-primary, #eee);
  border: 1px solid var(--hair, #333); border-radius: 8px; padding: 8px 11px;
  font-family: 'Inter', 'Inter Fallback', system-ui, sans-serif;
  font-size: 0.82rem; line-height: 1.45; font-weight: 400; font-style: normal;
  letter-spacing: normal; text-transform: none; text-decoration: none; white-space: normal;
  box-shadow: 0 8px 24px rgba(0,0,0,0.4);
  opacity: 0; visibility: hidden; transform: translateY(-3px); transition: opacity .14s ease, transform .14s ease;
}
.gloss:hover > .gloss-tip,
.gloss:focus > .gloss-tip,
.gloss:focus-within > .gloss-tip,
.gloss.gloss--open > .gloss-tip { opacity: 1; visibility: visible; transform: translateY(0); }
@media (prefers-reduced-motion: reduce) {
  .gloss-tip { transition: none; transform: none; }
}

/* Feature grid : index-numbered ledger entries */
.features { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1px; margin-top: var(--space-10);
  border: 1px solid var(--hair); border-radius: 20px; overflow: hidden; background: var(--hair); }
.feature {
  background: var(--bg-2); padding: clamp(26px, 3vw, 36px);
  position: relative; transition: background .25s ease, transform .2s ease, box-shadow .25s ease;
}
.feature:hover { background: var(--bg-3); transform: translateY(-3px); box-shadow: 0 26px 50px -34px rgba(0,0,0,0.7); }
.feature .num {
  font-family: 'Fira Code', monospace; font-size: 0.74rem; letter-spacing: var(--track-eyebrow);
  color: var(--muted-2); margin-bottom: 18px;
}
.feature .ic {
  width: 48px; height: 48px; border-radius: 13px; display: grid; place-items: center;
  background: color-mix(in srgb, var(--gold) 10%, transparent); color: var(--gold); margin-bottom: 18px;
  border: 1px solid var(--rule);
}
.feature h3 { font-family: 'Lora', 'Lora Fallback', Georgia, serif; font-weight: 600; font-size: var(--step-h3); margin-bottom: 10px; }
.feature p { color: var(--text-primary); font-size: 1rem; line-height: 1.6; }
@media (max-width: 760px) { .features { grid-template-columns: 1fr; } }

/* "What's coming" : numbered editorial list */
.roadmap { margin-top: var(--space-10); display: grid; gap: 1px; border-top: 1px solid var(--hair); }
.road-item {
  display: grid; grid-template-columns: auto 1fr; gap: clamp(18px, 3vw, 40px);
  align-items: start; padding-block: clamp(22px, 3vw, 34px);
  border-bottom: 1px solid var(--hair); transition: padding-left .25s ease;
}
.road-item:hover { padding-left: 8px; }
.road-item .step {
  font-family: 'Lora', 'Lora Fallback', Georgia, serif; font-style: italic; font-size: clamp(1.6rem, 3vw, 2.4rem);
  color: var(--gold); line-height: 1; min-width: 1.6ch;
}
.road-item h3 { font-family: 'Lora', 'Lora Fallback', Georgia, serif; font-weight: 600; font-size: var(--step-h3); margin-bottom: 7px; }
.road-item p { color: var(--text-primary); font-size: 1.02rem; max-width: 60ch; }

/* Coverage chips */
.chips { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 30px; list-style: none; }
/* WS4-i2: deep-links de discovery do app no bloco acervo-plus */
.acervo-deeplinks { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 18px; }
/* Sublinha honesta abaixo do CTA do Atlas: o mapa é aberto, abrir a fonte de cada
   ponto é que pede beta (ruling operador 2026-07-12: Atlas público). */
.sec-cta-sub { display: block; margin-top: 8px; font-size: 0.82rem; color: var(--muted-2); }

.chip {
  font-family: 'Fira Code', monospace; font-size: 0.84rem; color: var(--muted);
  border: 1px solid var(--hair); padding: 8px 15px; border-radius: 999px;
  background: rgba(255,255,255,0.018); transition: border-color .2s ease, color .2s ease;
}
.chip:hover { border-color: var(--rule); color: var(--ink); }
.chip strong { color: var(--ink); font-weight: 600; }

/* =========================================================
   STATS REGION : interactive corpus explorer
   ========================================================= */
.stats-region { margin-top: 40px; }
.stats-region[data-stats-state="loading"] .stats-error,
.stats-region[data-stats-state="loading"] .stats-content,
.stats-region[data-stats-state="error"] .stats-skeleton,
.stats-region[data-stats-state="error"] .stats-content,
.stats-region[data-stats-state="ready"] .stats-skeleton,
.stats-region[data-stats-state="ready"] .stats-error { display: none; }

/* Skeleton */
.stats-skeleton { display: grid; gap: 18px; }
.sk { border-radius: 16px; background:
  linear-gradient(100deg, var(--bg-2) 30%, var(--bg-3) 50%, var(--bg-2) 70%);
  background-size: 220% 100%; }
.js .sk { animation: shimmer 1.4s linear infinite; }
@keyframes shimmer { to { background-position: -220% 0; } }
.sk-bars { height: 220px; border: 1px solid var(--hair); }
.sk-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; }
.sk-card { height: 220px; border: 1px solid var(--hair); }
@media (max-width: 760px) { .sk-grid { grid-template-columns: 1fr; } }

/* Error */
.stats-error { border: 1px solid var(--hair); border-radius: 16px; background: var(--bg-2);
  padding: 32px; text-align: center; }
.stats-error p { color: var(--muted); margin-bottom: 18px; }

/* ── Aviso (`.notice`) e o estado FALHOU do acervo (PROP-LAND-COB-01) ──────────
   O componente `.notice`/`.notice--err` do kit de desenho não existia nesta folha —
   `docs/design/experiencia_iajus/telas/landing.md#land-cob` lista-o entre os
   reutilizados e a mockup LAND-COB-02 mostra-o, mas o `grep` na landing devolvia zero.
   Aqui entra só o que a mockup pinta, e nada mais: caixa, ícone, título, texto e ações.
   ⛔ A tinta vem de `var(--err)`, nunca de hex à mão: o vermelho literal desta folha já
   foi um valor de token de uma direção de marca NÃO SERVIDA colado como constante
   (spec/superficie-de-erro-da-landing-mantem-tinta-do-token.test.js conta a história).
   ⛔ `.notice[hidden]` não é cerimónia: `display:flex` é regra de autor e vence a folha
   do UA, portanto sem esta linha o `hidden` do markup fica INERTE e o aviso vazio
   aparece em todo carregamento. É o mesmo defeito, e o mesmo conserto, de
   `.stats-updated[hidden]`. */
.notice { display: flex; align-items: flex-start; gap: 12px;
  padding: clamp(14px, 2vw, 18px); border: 1px solid var(--hair); border-radius: 16px;
  background: var(--card); color: var(--text-primary); font-size: 0.95rem; line-height: 1.5; }
.notice[hidden] { display: none; }
.notice-ic { flex: none; margin-top: 2px; color: var(--gold); }
.notice-body { flex: 1 1 auto; min-width: 0; }
.notice-title { margin: 0; color: var(--ink); font-weight: 600; }
.notice-text { margin: 4px 0 0; color: var(--text-secondary); }
.notice-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 14px; }
.notice--err { border-color: color-mix(in srgb, var(--err) 45%, transparent);
  background: color-mix(in srgb, var(--err) 7%, transparent); }
.notice--err .notice-ic { color: var(--err); }
.stats-notice { margin-bottom: 24px; }
/* UMA ausência, UM cartão. `.stats-error` continua a servir os estados em que a leitura
   CHEGOU e a medição não existe; enquanto a raiz carrega FALHOU, quem fala é o aviso —
   dois cartões a explicar a mesma ausência com frases diferentes leem-se como dois
   problemas distintos. O atributo é o mesmo que `stats.js::clearVisibleStats` carimba,
   e não um segundo mecanismo de deteção. */
:root[data-iajus-stats-measurement="FALHOU"] .stats-error { display: none; }
/* «indisponível» de FALHA: itálico e tinta terciária, para se ler como ausência
   declarada e nunca como figura. O corte de tamanho vale só para os números de DISPLAY
   (`.counter-num`, `.acervo .stat .v`, `.fam-num`): a palavra no corpo de 4rem do herói
   gritaria a ausência, e nos slots de corpo (`.cs-val`, `.esf-val`) o tamanho já é o
   do texto à volta. */
.v--indisponivel { font-style: italic; font-weight: 400; color: var(--text-tertiary);
  font-variant-numeric: normal; letter-spacing: 0; }
.counter-num.v--indisponivel, .acervo .stat .v--indisponivel, .fam-num.v--indisponivel {
  font-size: clamp(1.05rem, 0.95rem + 0.4vw, 1.3rem); line-height: 1.35; }

/* Loaded grid */
.stats-content { display: grid; grid-template-columns: repeat(2, 1fr); gap: 18px; }
.chart-card {
  background: var(--bg-2); border: 1px solid var(--hair); border-radius: 18px;
  padding: clamp(22px, 3vw, 30px);
  min-width: 0; /* let 1fr tracks shrink below intrinsic content (charts) on mobile */
}
.chart-span { grid-column: 1 / -1; }
.chart-head { margin-bottom: 22px; }
.chart-head-row { display: flex; align-items: flex-end; justify-content: space-between; gap: 18px; flex-wrap: wrap; }
.chart-head h2 { font-family: 'Lora', 'Lora Fallback', Georgia, serif; font-weight: 600; font-size: 1.32rem; }
.chart-sub { color: var(--muted-2); font-size: 0.86rem; margin-top: 4px;
  font-family: 'Fira Code', monospace; letter-spacing: 0.02em; }
/* WS4 — passo a passo de plugins com prints (work order operador 2026-07-02) */
.plug-card {
  border: 1px solid var(--hair); border-radius: var(--radius-lg, 14px);
  background: var(--bg-2); padding: clamp(18px, 3vw, 30px); margin-top: 22px;
}
.plug-title { font-family: 'Lora', 'Lora Fallback', Georgia, serif; font-weight: 600; font-size: 1.18rem; margin: 0 0 14px; }
.plug-subtitle { font-family: 'Lora', 'Lora Fallback', Georgia, serif; font-weight: 600; font-size: 1.02rem; margin: 22px 0 8px; }
/* Colunas explícitas em vez de auto-fit: em ~1108px o auto-fit cabia 3 colunas e
   deixava o 4º passo órfão (3+1). 2x2 mantém as linhas internamente consistentes
   e alinha os prints pelo topo (as alturas dos pares divergem). */
.plug-steps {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: 1fr; gap: 18px 22px; align-items: start;
}
@media (min-width: 760px) { .plug-steps { grid-template-columns: repeat(2, 1fr); } }
.plug-steps-2 { grid-template-columns: repeat(2, 1fr); }
.plug-step p { margin: 0 0 10px; font-size: 0.95rem; line-height: 1.55; color: var(--ink-soft); }
.plug-step img {
  width: 100%; height: auto; display: block; border-radius: 10px;
  border: 1px solid var(--hair); background: #14181f; /* letterbox escuro atrás de screenshot — invariante nos dois temas */
}
.plug-note { margin: 16px 2px 0; font-size: 0.88rem; color: var(--muted); line-height: 1.55; max-width: 78ch; }
/* FE-RESP-01 (ordem operador via B, seq2443): JAMAIS quebra intra-palavra.
   O antigo word-break:break-all partia QUALQUER palavra no fim da linha —
   "Pesquisa Jurídica" renderizava "Jurídic/a" em 360px. overflow-wrap:anywhere
   só parte um token quando ele SOZINHO não cabe na linha, que é exatamente o
   caso das URLs/endereços longos de instalação (https://mcp.iajus.com.br/mcp,
   caminhos de repositório); palavras comuns descem inteiras. */
.plug-note code, .plug-step code { overflow-wrap: anywhere; }

/* Prints ampliaveis (lightbox SOTA, work order operador 2026-07-05): o <img> some
   dentro de um <button> real (foco/teclado nativos, Enter/Espaco ja funcionam sem
   JS extra) para que passar o mouse ou tocar sinalize "da pra ampliar" e o clique/tap
   abra o overlay #lightbox (hidratado por app.js::initLightbox). Sem JS, o botao
   ainda existe mas fica inerte - a imagem continua 100% visivel/legivel (progressive
   enhancement, mesmo padrao do resto da landing). */
.plug-shot {
  all: unset; position: relative; display: block; width: 100%; cursor: zoom-in;
  border-radius: 10px;
}
.plug-shot img {
  width: 100%; height: auto; display: block; border-radius: 10px;
  border: 1px solid var(--hair); background: #14181f; /* letterbox escuro atrás de screenshot — invariante nos dois temas */
  transition: transform 0.22s ease, filter 0.22s ease;
}
.plug-shot-hint {
  position: absolute; right: 10px; bottom: 10px; z-index: 1;
  display: flex; align-items: center; gap: 6px;
  padding: 6px 12px; border-radius: 999px;
  background: color-mix(in srgb, #0b0e14 78%, transparent);
  border: 1px solid rgba(255,255,255,0.14);
  color: #fff; font-family: var(--font-nav); font-size: 0.76rem; font-weight: 600;
  letter-spacing: 0.01em;
  opacity: 0; transform: translateY(4px);
  transition: opacity 0.18s ease, transform 0.18s ease;
}
.plug-shot-hint::before {
  content: ""; width: 13px; height: 13px; flex: none;
  background-color: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath fill-rule='evenodd' d='M9 3a6 6 0 1 0 3.76 10.68l3.78 3.78a1 1 0 0 0 1.42-1.42l-3.78-3.78A6 6 0 0 0 9 3Zm-4 6a4 4 0 1 1 8 0 4 4 0 0 1-8 0Z'/%3E%3Cpath d='M9 6.5a.75.75 0 0 1 .75.75V8.5H11a.75.75 0 0 1 0 1.5H9.75v1.25a.75.75 0 0 1-1.5 0V10H7a.75.75 0 0 1 0-1.5h1.25V7.25A.75.75 0 0 1 9 6.5Z'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath fill-rule='evenodd' d='M9 3a6 6 0 1 0 3.76 10.68l3.78 3.78a1 1 0 0 0 1.42-1.42l-3.78-3.78A6 6 0 0 0 9 3Zm-4 6a4 4 0 1 1 8 0 4 4 0 0 1-8 0Z'/%3E%3Cpath d='M9 6.5a.75.75 0 0 1 .75.75V8.5H11a.75.75 0 0 1 0 1.5H9.75v1.25a.75.75 0 0 1-1.5 0V10H7a.75.75 0 0 1 0-1.5h1.25V7.25A.75.75 0 0 1 9 6.5Z'/%3E%3C/svg%3E") center / contain no-repeat;
}
/* Affordance visivel: hover/focus no botao (desktop), sempre visivel ao toque
   (mobile nao tem :hover, entao o hint fica de leve presente via opacity base
   maior em telas sem ponteiro fino). */
.plug-shot:hover img, .plug-shot:focus-visible img { transform: scale(1.015); filter: brightness(1.04); }
.plug-shot:hover .plug-shot-hint, .plug-shot:focus-visible .plug-shot-hint { opacity: 1; transform: none; }
.plug-shot:focus-visible {
  outline: var(--focus-ring); outline-offset: 3px; border-radius: 10px;
}
@media (pointer: coarse) {
  .plug-shot-hint { opacity: 0.92; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .plug-shot img { transition: none; }
  .plug-shot:hover img, .plug-shot:focus-visible img { transform: none; }
}

/* =========================================================
   LIGHTBOX : overlay de ampliacao para os prints (.plug-shot)
   Mesmo contrato a11y/visual do .demo-modal/.beta-success: backdrop escuro,
   dialog centralizado, close no canto, foco preso (Tab trap em app.js),
   ESC/backdrop fecham, foco devolvido ao botao que abriu, animacao so com
   prefers-reduced-motion: no-preference.
   ========================================================= */
.lightbox[hidden] { display: none; }
.lightbox {
  position: fixed; inset: 0; z-index: 1000;
  display: flex; align-items: center; justify-content: center; padding: 4vh 3vw;
}
.lightbox-backdrop { position: absolute; inset: 0; background: rgba(0,0,0,0.82); cursor: zoom-out; }
.lightbox-dialog {
  position: relative; width: min(1100px, 100%); max-height: 92vh;
  display: flex; flex-direction: column; align-items: center;
}
.lightbox-img-wrap {
  width: 100%; display: flex; align-items: center; justify-content: center;
  min-height: 0;
}
.lightbox-img {
  max-width: 100%; max-height: 78vh; width: auto; height: auto;
  display: block; border-radius: 10px;
  border: 1px solid rgba(255,255,255,0.14); background: #14181f; /* letterbox escuro — vidro fixo nos dois temas */
  box-shadow: 0 24px 70px rgba(0,0,0,0.55);
}
.lightbox-caption {
  margin: 14px 2px 0; max-width: 78ch; text-align: center;
  font-size: 0.88rem; line-height: 1.5;
  color: #d8dbe2; /* legenda sobre vidro escuro — invariante por desenho */
}
.lightbox-caption:empty { display: none; }
.lightbox-close {
  position: absolute; top: -14px; right: -14px; z-index: 1;
  width: 44px; height: 44px; display: flex; align-items: center; justify-content: center;
  border-radius: 50%; border: 1px solid rgba(255,255,255,0.18);
  /* Lightbox é vidro escuro nos DOIS temas (overlay sobre página esmaecida):
     fundo/tinta fixos são o contrato, não hex solto — mesmo padrão dos tokens
     de overlay do atlas, a consolidar quando a família --overlay-* nascer. */
  background: #1b2130; color: #f2f0ec; cursor: pointer;
}
.lightbox-close:hover { color: var(--gold-bright); border-color: rgba(255,255,255,0.32); }
.lightbox-close:focus-visible { outline: 2px solid var(--gold-bright); outline-offset: 2px; }
@media (max-width: 640px) {
  .lightbox-close { top: 6px; right: 6px; }
}
body.lightbox-open { overflow: hidden; }
@media (prefers-reduced-motion: no-preference) {
  .lightbox-dialog { animation: demoModalIn 0.18s ease both; }
}

.chart-note {
  margin: 10px 2px 0; font-size: 0.8rem; line-height: 1.5; color: var(--muted);
  font-family: var(--font-nav);
}

@media (max-width: 760px) { .stats-content { grid-template-columns: 1fr; } }

/* Year histogram */
.histo { display: flex; align-items: flex-end; gap: clamp(4px, 1vw, 10px); height: 200px; }
.histo .bar-col { flex: 1 1 0; display: flex; flex-direction: column; align-items: center; gap: 8px; height: 100%; justify-content: flex-end; min-width: 0; }
.histo .bar-track { width: 100%; display: flex; align-items: flex-end; flex: 1; }
.histo .bar {
  width: 100%; border-radius: 6px 6px 2px 2px;
  background: linear-gradient(180deg, var(--gold-bright), var(--gold-soft));
  height: 0; transition: height .9s cubic-bezier(.22,.61,.36,1);
  min-height: 3px;
}
.histo .bar-col:hover .bar { filter: brightness(1.12); }
.histo .bar-val { font-family: 'Fira Code', monospace; font-size: 0.62rem; letter-spacing: -0.02em; color: var(--muted); white-space: nowrap; }
.histo .bar-yr { font-family: 'Fira Code', monospace; font-size: 0.66rem; color: var(--muted-2); white-space: nowrap; }
@media (max-width: 560px) {
  .histo .bar-val { display: none; }
  .histo {
    height: 168px; gap: 5px;
    /* keep year labels legible: give each bar a floor and let the row scroll
       horizontally if 14 bars cannot fit, instead of crushing the labels */
    overflow-x: auto; overflow-y: hidden; padding-bottom: 4px;
    scrollbar-width: thin;
  }
  .histo .bar-col { flex: 0 0 26px; }
}

/* Family donut */
.donut-wrap { display: grid; grid-template-columns: 168px 1fr; gap: 22px; align-items: center; }
.donut { width: 168px; height: 168px; transform: rotate(-90deg); }
.donut-hole { fill: none; stroke: var(--bg-3); stroke-width: 4.2; }
.donut .seg { fill: none; stroke-width: 4.2; stroke-linecap: butt;
  stroke-dasharray: 0 100; transition: stroke-dasharray 1s cubic-bezier(.22,.61,.36,1); }
.donut-center { transform: rotate(90deg); transform-origin: 21px 21px; }
.donut-center-num { font-family: 'Lora', 'Lora Fallback', serif; font-weight: 600; font-size: 5.4px; fill: var(--ink); text-anchor: middle; }
.donut-center-lbl { font-family: 'Fira Code', monospace; font-size: 2.1px; fill: var(--muted-2); text-anchor: middle; letter-spacing: 0.04em; }
.donut-legend { list-style: none; display: grid; gap: 6px; }
/* ⛔ Mesmo defeito e mesmo conserto de `.stats-updated[hidden]` (o mecanismo esta la).
   O stats.js esvazia e esconde `#family-legend` quando nao ha familia medida; sem esta linha
   a legenda seguia com caixa de grid e a arvore de acessibilidade anunciava uma `list` vazia. */
.donut-legend[hidden] { display: none; }
.donut-legend li { display: block; }
/* Legend item is a clickable filter button (família → órgãos drill-down). */
.donut-legend .lg-btn {
  width: 100%; display: flex; align-items: center; gap: 10px;
  font-size: 0.9rem; color: var(--ink-soft); text-align: left; cursor: pointer;
  background: transparent; border: 1px solid transparent; border-radius: 9px;
  padding: 6px 8px; font-family: inherit;
  transition: background .18s ease, border-color .18s ease;
}
.donut-legend .lg-btn:hover { background: var(--bg-3); border-color: var(--hair); }
.donut-legend .dot { width: 11px; height: 11px; border-radius: 3px; flex: none; }
.donut-legend .lg-name { flex: 1; }
.donut-legend .lg-val { font-family: 'Fira Code', monospace; font-size: 0.8rem; color: var(--muted); }
.donut-legend .lg-pct { font-family: 'Fira Code', monospace; font-size: 0.72rem; color: var(--muted-2); min-width: 3.4ch; text-align: right; }
@media (max-width: 480px) { .donut-wrap { grid-template-columns: 1fr; justify-items: center; } }

/* Órgão explorer */
.explorer-controls { display: flex; gap: 12px; flex-wrap: wrap; align-items: center; }
.explorer-search {
  width: clamp(180px, 40vw, 280px); padding: 10px 14px; border-radius: 10px;
  border: 1px solid var(--field-border); background: rgba(0,0,0,0.32); color: var(--ink);
  font-family: 'Fira Code', monospace; font-size: 0.82rem;
}
.explorer-search::placeholder { color: var(--muted-2); }
.explorer-search:focus:not(:focus-visible) { outline: none; border-color: var(--gold); box-shadow: 0 0 0 3px color-mix(in srgb, var(--gold) 18%, transparent); }
.explorer-sort { display: inline-flex; border: 1px solid var(--hair); border-radius: 10px; overflow: hidden; }
.sort-btn {
  background: transparent; border: 0; cursor: pointer; color: var(--muted);
  font-family: 'Fira Code', monospace; font-size: 0.74rem; letter-spacing: 0.04em;
  padding: 10px 14px; transition: background .2s ease, color .2s ease;
  /* >=44px touch target (Apple HIG / WCAG 2.5.5), content centered */
  min-height: 44px; display: inline-flex; align-items: center;
}
.sort-btn + .sort-btn { border-left: 1px solid var(--hair); }
.sort-btn.is-active { background: color-mix(in srgb, var(--gold) 12%, transparent); color: var(--gold); }
.orgao-list { list-style: none; display: grid; gap: 4px; max-height: 440px; overflow-y: auto; padding-right: 6px; }
.orgao-list li { display: block; }
/* Each row is a real button (clickable drill-down). */
.orgao-list .o-row {
  width: 100%; text-align: left; cursor: pointer;
  display: grid; grid-template-columns: minmax(96px, 130px) 1fr auto; align-items: center; gap: 14px;
  padding: 13px 8px; border-radius: 8px; border: 1px solid transparent; /* 9px rendia ~36px de alvo; 13px chega ao piso 44px */
  background: transparent; color: inherit; font: inherit;
  transition: background .18s ease, border-color .18s ease;
}
.orgao-list .o-row:hover { background: var(--bg-3); border-color: var(--hair); }
.orgao-list .o-row.is-active { background: var(--bg-3); border-color: var(--rule); }
.orgao-list .o-name { font-family: 'Fira Code', monospace; font-size: 0.82rem; color: var(--ink); min-width: 0; }
.orgao-list .o-fam { font-size: 0.66rem; color: var(--muted-2); display: block; letter-spacing: 0.04em;
  line-height: 1.25; }
@media (max-width: 420px) { .orgao-list .o-row { grid-template-columns: minmax(72px, 104px) 1fr auto; gap: 8px; } }
.orgao-list .o-bar { height: 8px; border-radius: 4px; background: var(--gold-soft); min-width: 4px;
  transition: width .8s cubic-bezier(.22,.61,.36,1); }
.orgao-list .o-val { font-family: 'Fira Code', monospace; font-size: 0.8rem; color: var(--muted); text-align: right; }
.orgao-empty { color: var(--muted-2); font-family: 'Fira Code', monospace; font-size: 0.84rem; padding: 12px 6px; }
.orgao-hint { color: var(--text-tertiary); font-family: 'Fira Code', monospace; font-size: 0.74rem; letter-spacing: 0.03em; margin-bottom: 10px; }

/* Órgão drill-down detail panel */
.orgao-detail {
  margin-top: 14px; padding: 16px 16px 14px; border-radius: 14px;
  border: 1px solid var(--rule);
  background: radial-gradient(120% 120% at 0% 0%, color-mix(in srgb, var(--gold) 8%, transparent), transparent 60%), var(--bg-3);
  animation: odIn .26s cubic-bezier(.22,.61,.36,1);
}
@keyframes odIn { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
.od-head { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.od-dot { flex: none; width: 11px; height: 11px; border-radius: 50%; }
.od-title { font-family: 'Lora', 'Lora Fallback', Georgia, serif; font-weight: 600; font-size: 1.12rem; flex: 1; }
.od-close {
  flex: none; width: 44px; height: 44px; /* era 30px — abaixo do piso 44px da casa */ border-radius: 9px; cursor: pointer;
  background: var(--bg-2); border: 1px solid var(--hair); color: var(--muted);
  font-size: 1.1rem; line-height: 1; transition: color .18s ease, border-color .18s ease;
}
.od-close:hover { color: var(--gold); border-color: var(--rule); }
.od-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 12px; }
.od-item { display: flex; flex-direction: column; gap: 3px; padding: 11px 12px; border-radius: 10px; background: var(--bg-2); border: 1px solid var(--hair); }
.od-item dt { font-family: 'Fira Code', monospace; font-size: 0.66rem; letter-spacing: var(--track-label); text-transform: uppercase; color: var(--text-tertiary); }
.od-item dd { font-family: 'Fira Code', monospace; font-size: 0.98rem; color: var(--ink); }
.od-note { margin-top: 12px; color: var(--text-secondary); font-size: 0.82rem; line-height: 1.5; }

/* Rank lists (relatores / turmas) */
.rank-list { list-style: none; display: grid; gap: 10px; }
.rank-list li { display: grid; grid-template-columns: auto 1fr auto; gap: 12px; align-items: center; }
.rank-list .r-idx { font-family: 'Fira Code', monospace; font-size: 0.74rem; color: var(--gold); min-width: 2ch; }
.rank-list .r-body { min-width: 0; }
/* Relator/órgão names must never be truncated with "…": they are source-citation
   data. Wrap to a second line instead of clipping. */
.rank-list .r-name { font-size: 0.96rem; color: var(--ink-soft); overflow-wrap: anywhere; }
.rank-list .r-meta { font-family: 'Fira Code', monospace; font-size: 0.68rem; color: var(--muted-2); }
.rank-list .r-track { height: 6px; border-radius: 3px; background: var(--bg-3); margin-top: 6px; overflow: hidden; }
.rank-list .r-fill { height: 100%; background: linear-gradient(90deg, var(--gold), var(--gold-soft)); width: 0; transition: width .8s cubic-bezier(.22,.61,.36,1); }
.rank-list .r-val { font-family: 'Fira Code', monospace; font-size: 0.82rem; color: var(--muted); }

/* Qualificadas chips */
.kind-grid { list-style: none; display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); gap: 12px; }
/* ⛔ Mesmo defeito e mesmo conserto de `.stats-updated[hidden]` (o mecanismo esta la).
   `#qualificadas-list` nasce `hidden` no HTML e o renderQualificadas() so o revela com itens
   medidos; sem esta linha ele seguia com caixa de grid (1026x0 a 1280px, 234x0 a 320px) e uma
   `list` vazia anunciada no lugar dos precedentes qualificados. */
.kind-grid[hidden] { display: none; }
.kind-grid li { border: 1px solid var(--hair); border-radius: 12px; padding: 14px 16px; background: var(--bg-3); }
.kind-grid .kd-val { font-family: 'Lora', 'Lora Fallback', serif; font-weight: 600; font-size: 1.4rem; color: var(--gold); font-variant-numeric: tabular-nums; }
.kind-grid .kd-name { font-size: 0.84rem; color: var(--muted); margin-top: 2px; }

/* =========================================================
   INTEGRATIONS
   ========================================================= */
.integrations { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; margin-top: var(--space-10); }
.intg-card {
  background: var(--bg-2); border: 1px solid var(--hair); border-radius: 16px;
  padding: 26px 24px; transition: transform .2s ease, border-color .25s ease, background .25s ease;
}
.intg-card:hover { transform: translateY(-3px); border-color: var(--rule); background: var(--bg-3); }
.intg-mark { width: 52px; height: 52px; border-radius: 13px; display: grid; place-items: center;
  background: rgba(255,255,255,0.04); color: var(--ink-soft); margin-bottom: 16px; border: 1px solid var(--hair); }
.intg-card h3 { font-family: 'Lora', 'Lora Fallback', Georgia, serif; font-weight: 600; font-size: 1.22rem; margin-bottom: 8px; }
.intg-card p { color: var(--text-primary); font-size: 0.94rem; line-height: 1.55; margin-bottom: 16px; }
.intg-badge {
  font-family: 'Fira Code', monospace; font-size: 0.66rem; letter-spacing: var(--track-label);
  text-transform: uppercase; color: var(--muted); border: 1px solid var(--hair);
  padding: 5px 11px; border-radius: 999px;
}
.intg-soon { border-style: dashed; border-color: var(--rule); }
.intg-soon .intg-mark { color: var(--gold); background: color-mix(in srgb, var(--gold) 6%, transparent); }
.intg-badge-soon { color: var(--gold); border-color: var(--rule); background: color-mix(in srgb, var(--gold) 6%, transparent); }
.intg-celeris { background: linear-gradient(165deg, color-mix(in srgb, var(--indigo) 10%, transparent), color-mix(in srgb, var(--gold) 4%, transparent)), var(--bg-2); border-color: var(--rule); }
.intg-celeris .intg-mark { color: var(--gold-bright); background: color-mix(in srgb, var(--gold) 10%, transparent); }
.intg-badge-celeris { color: var(--gold-bright); border-color: var(--rule); background: color-mix(in srgb, var(--gold) 8%, transparent); }
.integ-note { margin-top: 30px; color: var(--muted); font-size: 1rem; max-width: 70ch; }
.integ-note strong { color: var(--ink); }
@media (max-width: 980px) { .integrations { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px) { .integrations { grid-template-columns: 1fr; } }

.channel-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; margin-top: var(--space-10); }
.channel-card {
  display: flex; flex-direction: column; align-items: flex-start; min-width: 0; min-height: 230px;
  padding: 26px 24px; border: 1px solid var(--hair); border-radius: 16px; background: var(--bg-2);
}
.channel-card h3 { font-family: 'Lora', 'Lora Fallback', Georgia, serif; font-size: var(--step-h3); margin-bottom: 10px; }
.channel-card p { color: var(--text-primary); line-height: 1.6; margin-bottom: 20px; }
.channel-card .btn { margin-top: auto; min-height: 44px; }
@media (max-width: 900px) { .channel-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .channel-grid { grid-template-columns: 1fr; } .channel-card { min-height: 0; } }

/* INTEG-MM-01 Fatia 1: faixa de logos clicáveis (índice de marcas da página).
   Cada chip é um alvo >=44px (WCAG 2.5.5); grid 3x2 no mobile. */
.logo-strip { display: flex; flex-wrap: wrap; gap: 14px; margin-top: var(--space-8); }
.logo-chip {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  min-width: 64px; min-height: 64px; padding: 12px; border: 1px solid var(--hair);
  border-radius: 16px; background: var(--bg-2); text-decoration: none;
  transition: transform .18s ease, border-color .18s ease, box-shadow .18s ease;
}
.logo-chip img, .logo-chip svg { width: 34px; height: 34px; display: block; border-radius: 8px; }
.logo-chip:hover { transform: translateY(-2px); border-color: var(--accent, #8ab4ff); box-shadow: 0 8px 24px rgba(0,0,0,.28); }
.logo-chip:focus-visible { outline: 3px solid var(--accent, #8ab4ff); outline-offset: 2px; }
.logo-chip:active { transform: translateY(0); }
.logo-chip[hidden] { display: none; }
.logo-chip .logo-chip-label { font-size: .82rem; font-weight: 600; color: var(--text-primary); }
@media (max-width: 560px) {
  .logo-strip { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .logo-chip { min-width: 0; width: 100%; }
}

/* =========================================================
   PROVIDER SELECTOR + PANELS (/integracoes, reformulacao 2026-07-18,
   ordem operador via B mural seq2302/2303): seletor por provider com os
   7 canais agrupados por TIPO de conexao (Instale o plugin / Conector MCP /
   Canais diretos); a pagina mostra SO o painel do provider escolhido
   (initProviderPanels no app.js). Sem JS, todos os paineis ficam visiveis
   e os chips funcionam como ancora nativa.
   ========================================================= */
.provider-nav {
  display: flex; flex-wrap: wrap; align-items: flex-start;
  gap: 18px 34px; margin-top: var(--space-8);
}
.provider-nav-group { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.provider-nav-caption {
  font-family: var(--font-nav); font-size: 0.72rem; font-weight: 700;
  letter-spacing: 0.09em; text-transform: uppercase; color: var(--muted);
}
.provider-nav-chips { display: flex; flex-wrap: wrap; gap: 10px; }
.provider-chip {
  display: inline-flex; align-items: center; gap: 10px;
  min-height: 52px; padding: 10px 16px 10px 12px;
  border: 1px solid var(--hair); border-radius: 14px; background: var(--bg-2);
  color: var(--text-primary); text-decoration: none; font-size: 0.9rem; font-weight: 600;
  transition: transform .18s ease, border-color .18s ease, box-shadow .18s ease, background .18s ease;
}
.provider-chip img { width: 30px; height: 30px; display: block; border-radius: 8px; color-scheme: light; }
.provider-chip:hover { transform: translateY(-2px); border-color: var(--accent, #8ab4ff); box-shadow: 0 8px 24px rgba(0,0,0,.28); }
.provider-chip:focus-visible { outline: 3px solid var(--accent, #8ab4ff); outline-offset: 2px; }
.provider-chip:active { transform: translateY(0); }
.provider-chip.is-active {
  border-color: var(--gold); background: color-mix(in srgb, var(--gold) 8%, var(--bg-2));
  box-shadow: 0 0 0 1px var(--gold) inset;
}
.provider-chip.is-active:hover { transform: none; }

.provider-panels { margin-top: var(--space-8); }
.provider-panel {
  border: 1px solid var(--hair); border-radius: var(--radius-lg, 14px);
  background: var(--bg-2); padding: clamp(18px, 3vw, 30px);
  scroll-margin-top: 96px;
}
.provider-panel[hidden] { display: none; }
.provider-panels .provider-panel + .provider-panel { margin-top: 22px; }
.provider-head { display: flex; align-items: center; gap: 16px; }
.provider-coin {
  flex: none; width: 56px; height: 56px; border-radius: 15px;
  display: flex; align-items: center; justify-content: center;
  background: #fff; border: 1px solid var(--hair);
}
.provider-coin img { width: 32px; height: 32px; display: block; border-radius: 8px; color-scheme: light; }
.provider-coin-mcp { background: color-mix(in srgb, var(--indigo) 16%, var(--bg-2)); color: var(--accent, #8ab4ff); }
.provider-id { min-width: 0; }
.provider-id h2 {
  font-family: 'Lora', 'Lora Fallback', Georgia, serif; font-weight: 600;
  font-size: clamp(1.3rem, 2.4vw, 1.6rem); margin: 4px 0 0;
}
.provider-sub { color: var(--muted); font-size: 0.88rem; margin: 4px 0 0; }
.provider-group {
  display: inline-flex; align-items: center; min-height: 24px; padding: 2px 10px;
  border-radius: 999px; border: 1px solid var(--rule);
  font-family: var(--font-nav); font-size: 0.7rem; font-weight: 700;
  letter-spacing: 0.07em; text-transform: uppercase;
}
.provider-group-plugin { color: var(--gold-bright); background: color-mix(in srgb, var(--gold) 8%, transparent); }
.provider-group-mcp { color: var(--accent, #8ab4ff); background: color-mix(in srgb, var(--indigo) 12%, transparent); }
.provider-group-canal { color: #63d68b; background: color-mix(in srgb, #2f9e5b 14%, transparent); }
.provider-lede { margin-top: 16px; max-width: 82ch; }
.provider-panel .plug-steps { margin-top: 20px; }
.provider-panel .plug-subtitle:first-of-type { margin-top: 0; }
.provider-cta { margin: 20px 2px 0; }
.provider-cta .btn { min-height: 46px; }
@media (max-width: 640px) {
  .provider-nav { gap: 16px 20px; }
  /* chips full-width stack on narrow phones: keep 44px+ target, readable wrap */
  .provider-nav-chips { gap: 8px; }
  .provider-chip {
    min-height: 48px;
    flex: 1 1 calc(50% - 8px);
    justify-content: flex-start;
    padding: 10px 12px;
    font-size: 0.88rem;
  }
  .provider-head { align-items: flex-start; }
  .provider-coin { width: 48px; height: 48px; }
  .provider-coin img { width: 28px; height: 28px; }
  .provider-panel { scroll-margin-top: 72px; padding: 16px; }
}
@media (prefers-reduced-motion: reduce) {
  .provider-chip { transition: none; }
  .provider-chip:hover { transform: none; }
}

/* =========================================================
   BETA BANNER: faixa "ainda não faz parte do beta?" no topo da home
   (pedido do operador 2026-07-05, primeiro elemento visível antes do hero).
   Reaproveita os tokens do .notify (mesma superfície dourada/indigo) num
   formato de faixa horizontal full-bleed, não de cartão centrado. Sempre
   visível (não usa .reveal) porque precisa aparecer "de cara", sem esperar
   scroll. Link único para /beta#notify — nenhum endpoint novo. */
.beta-banner {
  position: relative; overflow: hidden;
  border-bottom: 1px solid var(--rule);
  background:
    radial-gradient(120% 200% at 8% 0%, color-mix(in srgb, var(--gold) 10%, transparent), transparent 60%),
    radial-gradient(120% 200% at 100% 100%, color-mix(in srgb, var(--indigo) 10%, transparent), transparent 60%),
    var(--bg-2);
}
.beta-banner-inner {
  display: flex; align-items: center; justify-content: center; flex-wrap: wrap;
  gap: var(--space-4) var(--space-8);
  padding-block: var(--space-4);
  text-align: center;
}
.beta-banner-text {
  margin: 0; color: var(--text-secondary);
  font-size: 0.95rem; line-height: 1.5;
}
.beta-banner-text strong { color: var(--ink); font-weight: 600; }
.beta-banner-btn {
  /* Versão compacta do .btn.btn-primary para caber numa faixa fina. */
  padding: 10px 20px; font-size: 0.85rem; flex: none;
}
@media (max-width: 640px) {
  .beta-banner-inner { flex-direction: column; gap: var(--space-3); padding-block: var(--space-4) var(--space-6); }
  .beta-banner-text { font-size: 0.9rem; }
}

/* =========================================================
   NOTIFY / forms
   ========================================================= */
.notify {
  margin-block: clamp(40px, 6vw, 72px) 0;
  position: relative; overflow: hidden;
  background:
    radial-gradient(120% 120% at 12% 0%, color-mix(in srgb, var(--indigo) 14%, transparent), transparent 55%),
    radial-gradient(120% 120% at 92% 100%, color-mix(in srgb, var(--gold) 10%, transparent), transparent 55%),
    var(--bg-2);
  border: 1px solid var(--rule); border-radius: 26px;
  padding: clamp(36px, 5vw, 64px) clamp(24px, 4vw, 56px); text-align: center;
}
.notify .seal {
  width: 52px; height: 52px; margin: 0 auto 22px; display: grid; place-items: center;
  border-radius: 50%; border: 1px solid var(--rule); color: var(--gold);
  background: color-mix(in srgb, var(--gold) 6%, transparent);
}
.notify h2 { margin-bottom: 12px; }
.notify .intro { margin-inline: auto; }
/* Espaçamento/cor das bandas de conversão amarrados aos tokens (antes eram
   style= inline com números mágicos fora da escala --space-*). O .kicker é
   inline-flex shrink-to-fit centrado pelo text-align:center do .notify — o antigo
   justify-content:center inline era no-op. */
.notify .sec-cta { margin-top: var(--space-8); }
.notify .privacy a { color: var(--gold); }
#remover { margin-top: var(--space-6); }
form { margin-top: 30px; }
.fields { display: flex; gap: 12px; max-width: 580px; margin-inline: auto; flex-wrap: wrap; text-align: left; }
.field { flex: 1; min-width: 200px; }
.field.email { flex: 1.35; }
label {
  display: block; font-family: 'Fira Code', monospace;
  font-size: 0.72rem; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--muted); margin-bottom: 8px; font-weight: 500;
}
label .opt { color: var(--muted-2); text-transform: none; letter-spacing: 0; }
/* ⛔ LIMITE DE CAMPO = --field-border, NUNCA --hair (2026-09-09). --hair é filete de
   divisor: como limite de campo mede 1,273:1 (contra o próprio campo) e 1,147:1
   (contra --bg-2) no escuro, e 1,270 / 1,115 no claro — muito abaixo do piso 3:1 de
   objeto de interface (WCAG 1.4.11), ou seja, o campo não tinha borda VISÍVEL, tinha
   uma insinuação. --field-border (o token que o canônico criou exatamente para isto,
   `color-mix(in srgb, var(--ink) 50%, transparent)`) mede no escuro 5,069:1 por dentro
   e 4,695 / 4,569 / 4,327 contra --bg / --bg-2 / --bg-3; no claro 3,233:1 por dentro
   (campo branco) e 3,044 / 2,837 / 2,613 por fora — passa a aresta de dentro em ambos
   os temas e melhora TODOS os pares. Medido nesta árvore em 2026-09-09 com composição
   alfa real (o campo é rgba(0,0,0,.32) sobre a superfície, nunca a superfície nua) e
   ANCORADO no pixel: em Chrome for Testing 153.0.8010.12, contato.html a 1280×900, a
   tira vertical no topo deste campo lê fora=rgb(32,37,57) borda=rgb(134,137,144)
   dentro=rgb(21,25,38) — 5,000:1 por dentro e 4,328:1 por fora, contra rgb(42,45,58)
   e 1,280 / 1,108 com --hair. A borda compõe-se sobre o CAMPO (background-clip
   border-box), não sobre a superfície: quem medir contra a superfície nua obtém outro
   número e conclui outra coisa.
   ⚠️ O que ainda NÃO passa: no tema claro, contra --bg-2/--bg-3 por FORA (2,84/2,61).
   Fechar esse par exige escurecer o token no canônico, que é decisão do dono do
   desenho e move a app e o admin no mesmo passe — está no relatório desta lane. */
input, textarea {
  width: 100%; padding: 15px 17px; border-radius: 12px;
  border: 1px solid var(--field-border); background: rgba(0,0,0,0.32); color: var(--ink);
  font-size: 1.02rem; font-family: 'Public Sans', 'Public Sans Fallback', system-ui, -apple-system, sans-serif;
  transition: border-color .18s ease, box-shadow .18s ease, background .18s ease;
}
textarea { resize: vertical; min-height: 96px; line-height: 1.55; }
input::placeholder, textarea::placeholder { color: var(--muted-2); }
input:focus:not(:focus-visible), textarea:focus:not(:focus-visible) { outline: none; border-color: var(--gold); background: rgba(0,0,0,0.42); box-shadow: 0 0 0 3px color-mix(in srgb, var(--gold) 18%, transparent); }
input[aria-invalid="true"], textarea[aria-invalid="true"] { border-color: var(--err); box-shadow: 0 0 0 3px color-mix(in srgb, var(--err) 15%, transparent); }

/* ---- International phone (DDI country selector + national number) --------- */
.tel-group {
  position: relative; display: flex; align-items: stretch;
  border: 1px solid var(--field-border); border-radius: 12px;
  background: rgba(0,0,0,0.32);
  transition: border-color .18s ease, box-shadow .18s ease, background .18s ease;
}
.tel-group:focus-within { border-color: var(--gold); background: rgba(0,0,0,0.42); box-shadow: 0 0 0 3px color-mix(in srgb, var(--gold) 18%, transparent); }
.tel-country {
  display: inline-flex; align-items: center; gap: 6px; flex-shrink: 0;
  background: none; border: none; border-right: 1px solid var(--hair);
  border-radius: 12px 0 0 12px; cursor: pointer; color: var(--ink);
  font-family: 'Fira Code', monospace; font-size: 0.95rem;
  padding: 0 13px; line-height: 1; min-width: 0;
}
.tel-country:hover { background: var(--card-strong); }
.tel-flag { font-size: 1.15rem; line-height: 1; }
.tel-code { color: var(--ink); font-variant-numeric: tabular-nums; }
.tel-caret { display: inline-flex; color: var(--muted-2); }
/* The number input inside the group: drop its own border/background; the group owns them. */
.tel-group input[type="tel"] {
  flex: 1 1 auto; min-width: 0; border: none; background: none;
  border-radius: 0 12px 12px 0; box-shadow: none;
}
.tel-group input[type="tel"]:focus:not(:focus-visible) { box-shadow: none; background: none; border: none; }
.tel-group[data-invalid="true"] { border-color: var(--err); box-shadow: 0 0 0 3px color-mix(in srgb, var(--err) 15%, transparent); }
.tel-popup {
  position: absolute; z-index: 40; top: calc(100% + 6px); left: 0; right: 0;
  background: var(--bg-2); border: 1px solid var(--rule, var(--hair));
  border-radius: 12px; box-shadow: 0 18px 40px -12px rgba(0,0,0,0.6); padding: 8px;
}
.tel-search { margin-bottom: 6px; padding: 10px 13px; font-size: 0.92rem; border-radius: 9px; }
.tel-listbox { list-style: none; margin: 0; padding: 0; max-height: 248px; overflow-y: auto; }
.tel-option {
  display: flex; align-items: center; gap: 12px; padding: 9px 11px;
  border-radius: 8px; cursor: pointer; color: var(--ink-soft); text-align: left;
}
.tel-option.active { background: color-mix(in srgb, var(--gold) 16%, transparent); color: var(--ink); }
.tel-option.selected .tel-option-name { color: var(--gold); }
.tel-option-flag { font-size: 1.2rem; line-height: 1; flex-shrink: 0; }
.tel-option-name { flex: 1 1 auto; font-family: 'Public Sans', 'Public Sans Fallback', system-ui, sans-serif; font-size: 0.95rem; min-width: 0; }
.tel-option-code { font-family: 'Fira Code', monospace; font-size: 0.8rem; color: var(--muted-2); font-variant-numeric: tabular-nums; flex-shrink: 0; }
.tel-empty { padding: 12px; font-size: 0.9rem; color: var(--muted-2); }
@media (prefers-reduced-motion: reduce) { .tel-group { transition: none; } }

.submit-row { margin-top: 20px; }
button[type="submit"] { min-width: 230px; justify-content: center; }
button[type="submit"][aria-busy="true"] { opacity: 0.85; cursor: progress; }
.spinner {
  width: 17px; height: 17px; border-radius: 50%;
  /* LH-07: tokens no lugar dos hex fixos (rgba(63,24,13,.35)/#fff1ec): o anel
     escuro deriva de --bg e o segmento claro de --ink, acompanhando o tema. */
  border: 2px solid color-mix(in srgb, var(--bg) 35%, transparent);
  border-top-color: color-mix(in srgb, var(--ink) 94%, var(--bg));
  animation: spin .7s linear infinite; display: none;
}
button[aria-busy="true"] .spinner { display: inline-block; }
button[aria-busy="true"] .btn-label { opacity: 0.85; }
@keyframes spin { to { transform: rotate(360deg); } }
.form-msg {
  margin-top: 20px; font-family: 'Fira Code', monospace; font-size: 0.92rem;
  font-weight: 500; min-height: 1.4em;
  display: none; align-items: center; justify-content: center; gap: 9px;
}
.form-msg.show { display: flex; }
.form-msg.ok { color: var(--ok); }
.form-msg.err { color: var(--err); }
/* E-mail typo advisory (GO operador 2026-07-14): "Você quis dizer nome@gmail.com?"
   reuses the same aria-live .form-msg region — neutral tone (not err/ok), with a
   clickable inline button for the one-click-accept suggestion. */
.form-msg.suggest { color: var(--ink-soft, var(--ink)); flex-wrap: wrap; }
.form-msg-suggest-btn {
  background: none; border: none; padding: 0; margin: 0;
  font: inherit; font-weight: 700; color: var(--gold-bright, var(--gold));
  text-decoration: underline; text-decoration-color: currentColor;
  text-underline-offset: 3px; cursor: pointer;
}
.form-msg-suggest-btn:hover { color: var(--gold); }
.form-msg-suggest-btn:focus-visible {
  outline: var(--focus-ring); outline-offset: var(--focus-ring-offset, 2px);
  border-radius: 4px;
}
.privacy { font-family: 'Fira Code', monospace; color: var(--muted-2); font-size: 0.78rem; margin: 18px auto 0; max-width: 48ch; line-height: 1.5; }
/* ⛔ Conformidade e' propriedade do PAR cor+fundo, nunca da cor sozinha. Sobre
   papel liso --muted-2 (#5f6573) mede 5,13:1 e esta' bem; mas as TRES .privacy
   que vivem no fundo do painel .notify (#cta-beta em index.html, #notify em
   beta.html, e a de contato.html) assentam no CANTO QUENTE do degrade' proprio
   do painel (`--gold 10%` ancorado a 92% 100%, i.e. em baixo a' direita — que e'
   exactamente onde a letra mais miuda da pagina fica). Medido a 2026-08-21 no
   pior ponto: 4,394 / 4,468 / 4,384 — as tres REPROVAM AA (piso 4,5; 12,48px,
   peso 400). Corrigir a sombra do botao (acima) sozinho nao chega: leva-as a
   4,765 / 4,721 / 4,674, ainda aquem da margem de +0,25 exigida, porque o tecto
   passa a ser o degrade' do painel.
   Sobe-se UM degrau da escada de contraste ja' existente (--text-tertiary ->
   --text-secondary): nenhum literal novo, nenhum token novo, e a hierarquia
   aguenta porque a letra miuda continua separada por TAMANHO (0,78rem) e por
   FAMILIA (Fira Code), nao so' por cor. Depois: 5,377 / 5,485 / 5,334, margem
   +0,83 a +0,99 nos tres sitios. So' no tema claro — o escuro ja' media 4,94 a
   5,13 e fica intocado (verificado: numeros identicos ao bit antes e depois).
   Vigia: spec/sombra-do-botao-nao-escurece-a-letra-miuda.test.js */
[data-theme='light'] .privacy { color: var(--text-secondary); }

/* ---- select (cascading UF/município + perfil) ---------------------------- */
select {
  width: 100%; padding: 15px 42px 15px 17px; border-radius: 12px;
  border: 1px solid var(--field-border); background-color: rgba(0,0,0,0.32); color: var(--ink);
  font-size: 1.02rem; font-family: 'Public Sans', 'Public Sans Fallback', system-ui, -apple-system, sans-serif; cursor: pointer;
  appearance: none; -webkit-appearance: none; -moz-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%2398a2bd' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 16px center;
  transition: border-color .18s ease, box-shadow .18s ease, background-color .18s ease, opacity .18s ease;
}
select:focus:not(:focus-visible) { outline: none; border-color: var(--gold); background-color: rgba(0,0,0,0.42); box-shadow: 0 0 0 3px color-mix(in srgb, var(--gold) 18%, transparent); }
select:disabled { opacity: 0.5; cursor: not-allowed; }
select[aria-invalid="true"] { border-color: var(--err); box-shadow: 0 0 0 3px color-mix(in srgb, var(--err) 15%, transparent); }
/* native option list renders in the OS theme; force readable text on dark UAs */
/* A lista nativa de <option> renderiza no tema do SO, não no da página: o par
   escuro-sobre-claro fica fixo de propósito para o texto não sumir em UA escura. */
select option { color: #0d1322; background: #f2f0e9; }
/* date input: calendar UI follows the active theme (dark glyph on navy, light on
   cream) instead of forcing a dark picker onto the light paper. */
input[type="date"] { color-scheme: dark; }
[data-theme='light'] input[type="date"] { color-scheme: light; }

/* ---- BETA progressive form ----------------------------------------------- */
.beta-form { text-align: left; max-width: 640px; margin-inline: auto; }
.beta-step { border: none; padding: 0; margin: 0 0 4px; }
.beta-step + .beta-step { margin-top: 26px; padding-top: 24px; border-top: 1px solid var(--hair); }
.beta-step .fields { max-width: 100%; margin-inline: 0; }
.beta-step .fields + .fields { margin-top: 14px; }
.beta-legend {
  font-family: 'Fira Code', monospace; font-size: 0.74rem; letter-spacing: var(--track-eyebrow);
  text-transform: uppercase; color: var(--gold); margin-bottom: 16px; padding: 0; font-weight: 500;
}
.beta-legend .opt { color: var(--muted-2); letter-spacing: 0; }
.field-hint { display: block; font-family: 'Fira Code', monospace; font-size: 0.74rem; color: var(--muted-2); margin-top: 7px; }
/* ⛔ Mesmo defeito e mesmo conserto de `.stats-updated[hidden]` (o mecanismo esta la).
   `#uf-hint` e `#municipio-hint` nascem `hidden` e o setHint() do app.js os liga e desliga
   conforme haja texto; sem esta linha o span vazio seguia em fluxo (314x0 a 1280px, 230x0 a
   320px) e o seu proprio `margin-top: 7px` virava espaco morto sob os selects de UF e de
   municipio. */
.field-hint[hidden] { display: none; }
.field-hint.err { color: var(--err); }
/* Erro inline do campo (QA-UI "erro longe do campo"): a mensagem específica vive ao
   lado do input que falhou, ligada por aria-describedby; o #notify-msg global fica só
   para status de envio, sucesso e erros de rede/limite. O [hidden] explícito garante
   precedência sobre o display:block acima. */
.field-error { display: block; margin-top: 6px; font-size: 0.86rem; line-height: 1.45; color: var(--err); }
.field-error[hidden] { display: none; }

.beta-choice { margin-top: 4px; }
.beta-choice-label { display: block; font-family: 'Fira Code', monospace; font-size: 0.72rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); margin-bottom: 10px; font-weight: 500; }
.beta-toggle { display: flex; gap: 10px; flex-wrap: wrap; }
.beta-pill {
  flex: 0 1 auto; display: inline-flex; align-items: center; gap: 8px; margin: 0;
  padding: 11px 18px; border-radius: 999px; border: 1px solid var(--hair);
  background: rgba(255,255,255,0.02); color: var(--ink-soft); cursor: pointer;
  font-family: 'Public Sans', 'Public Sans Fallback', system-ui, -apple-system, sans-serif; font-size: 0.98rem; text-transform: none; letter-spacing: 0;
  transition: border-color .18s ease, background .18s ease, color .18s ease;
}
.beta-pill input { position: absolute; opacity: 0; width: 1px; height: 1px; pointer-events: none; }
.beta-pill span::before {
  content: ""; display: inline-block; width: 14px; height: 14px; margin-right: 9px; vertical-align: -2px;
  border-radius: 50%; border: 1.5px solid var(--muted); transition: border-color .18s ease, box-shadow .18s ease, background .18s ease;
}
.beta-pill:hover { border-color: var(--rule); color: var(--ink); }
.beta-pill:has(input:checked) { border-color: var(--gold); background: color-mix(in srgb, var(--gold) 8%, transparent); color: var(--ink); }
.beta-pill:has(input:checked) span::before { border-color: var(--gold); background: var(--gold); box-shadow: inset 0 0 0 3px var(--bg-2); }
.beta-pill:has(input:focus-visible) { outline: 2px solid var(--gold-bright); outline-offset: 3px; }

.beta-reveal { margin-top: 20px; }
.beta-reveal[hidden] { display: none; }
.beta-reveal .field + .beta-reveal,
.beta-reveal .beta-choice { margin-top: 20px; }
@media (prefers-reduced-motion: no-preference) {
  .beta-reveal:not([hidden]) { animation: beta-reveal-in .28s ease both; }
  @keyframes beta-reveal-in { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: translateY(0); } }
}

@media (max-width: 620px) {
  .fields { flex-direction: column; }
  .field, .field.email { flex: 1 1 100%; }
  button[type="submit"] { width: 100%; }
  .hero-cta .btn { flex: 1 1 100%; justify-content: center; }
  .beta-toggle { flex-direction: column; }
  .beta-pill { width: 100%; }
}

/* =========================================================
   PRÉ-FOOTER : faixa de conversão (navy + 1 tom)
   ========================================================= */
.prefooter { position: relative; z-index: 1; margin-top: clamp(56px, 8vw, 96px); }
/* Home ends with the #cta-beta band (funnel to /beta) and /beta ends with the full
   cadastro form (#notify) + the LGPD #remover section. Both already close on a strong
   CTA, so suppress the generic global pre-footer BETA band on both to avoid a duplicate
   "acesso ao BETA" at the very end. */
body[data-route="/"] .prefooter,
body[data-route="/beta"] .prefooter { display: none; }

/* /beta = the Google-Ads cadastro landing (its own self-contained view-beta). The canonical
   #notify form physically LIVES in view-beta (moved out of view-home, so it exists once in the
   DOM). The default lead-in copy shows everywhere the form might render; the .notify-beta copy
   shows ONLY on /beta, swapped purely by this route attribute. (The form's #notify-titulo stays
   the labelledby target on both, so the accessible name is unaffected.) */
.notify-beta { display: none; }
body[data-route="/beta"] .notify-default { display: none; }
body[data-route="/beta"] .notify-beta[hidden] { display: revert; }
body[data-route="/beta"] span.notify-beta[hidden] { display: inline-flex; }

/* /beta hero: slightly tighten the top padding vs the home header (no marquee/eyebrow
   stack above it) and let the supporting blocks breathe. Reuses .hero-grid/.hero-copy. */
.beta-hero { padding-block: clamp(40px, 6vw, 80px) clamp(28px, 4vw, 52px); }
.prefooter .wrap { max-width: var(--maxw); }
.prefooter-inner {
  display: flex; align-items: center; justify-content: space-between; gap: clamp(20px, 4vw, 48px);
  flex-wrap: wrap;
  background: var(--bg-3); border: 1px solid var(--rule); border-radius: 20px;
  padding: clamp(28px, 4vw, 44px) clamp(24px, 4vw, 48px);
}
.prefooter-copy { min-width: 0; flex: 1 1 320px; }
.prefooter-copy h2 { font-size: clamp(1.5rem, 1.1rem + 1.6vw, 2.2rem); color: var(--ink); margin-bottom: 8px; line-height: 1.18; }
.prefooter-copy p { color: var(--text-secondary); font-size: 1.02rem; max-width: 52ch; }
.prefooter-cta { flex: 0 0 auto; }

/* =========================================================
   PROGRAMAS : selo de membro (NVIDIA Inception)
   Discreto, centrado, imediatamente antes do footer. O badge tem placa
   branca própria, então assenta direto no navy nos dois temas (sem chip).
   ========================================================= */
.programas { position: relative; z-index: 1; text-align: center; padding-block: clamp(28px, 4vw, 44px) 0; }
.programas .wrap { max-width: var(--maxw); }
.programas-h { font-family: var(--font-nav); font-size: 0.78rem; letter-spacing: 0.04em; color: var(--text-secondary); font-weight: 600; margin-bottom: 12px; }
.programas-copy { color: var(--text-secondary); font-size: 0.96rem; max-width: 52ch; margin: 0 auto; line-height: 1.55; }
.programas-badge { width: 160px; height: 69px; display: block; margin: 18px auto 0; }
.programas-legal { font-size: 0.72rem; color: var(--muted-2); max-width: 56ch; margin: 16px auto 0; line-height: 1.5; }

/* =========================================================
   FOOTER
   ========================================================= */
footer { border-top: 1px solid var(--hair); padding-block: 48px 64px; margin-top: clamp(40px, 6vw, 72px); color: var(--muted-2); position: relative; z-index: 1; }
footer .wrap { max-width: var(--maxw); }
/* 4 colunas (Marca · Produto · Institucional · Legal), max-width 1200 herdado do .wrap. */
.foot-grid { display: grid; grid-template-columns: 1.7fr 1fr 1fr 1fr; gap: clamp(24px, 4vw, 56px); padding-bottom: 32px; border-bottom: 1px solid var(--hair); }
.foot-brand { display: flex; align-items: center; gap: 12px; color: var(--muted); font-size: 0.96rem; }
.foot-brand svg { width: 30px; height: 30px; flex: none; }
.foot-brand strong { color: var(--ink-soft); font-weight: 500; }
.foot-tagline { color: var(--muted-2); font-size: 0.92rem; margin-top: 14px; max-width: 32ch; line-height: 1.55; }
.foot-links { display: flex; flex-direction: column; gap: 11px; }
.foot-links h3 { font-family: var(--font-nav); font-size: 0.78rem; letter-spacing: 0.04em; color: var(--text-secondary); margin-bottom: 5px; font-weight: 600; }
/* Subtítulo "Redes" abaixo dos links legais na mesma coluna: respiro acima para
   separar do bloco anterior sem virar uma coluna nova. */
.foot-links h3.foot-subhead { margin-top: 16px; }
.foot-links a { color: var(--muted); text-decoration: none; font-size: 0.92rem; transition: color .2s ease;
  /* Alvo de ponteiro ~40px em todas as larguras (P2-1 2026-07-19): 24px de texto
     + 16px de padding. Antes o padding só existia <=560px (6px). */ padding-block: 8px; }
.foot-links a:hover { color: var(--gold); }
.foot-row { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 12px; padding-top: 26px; }
footer small { font-family: 'Fira Code', monospace; color: var(--muted-2); font-size: 0.78rem; letter-spacing: 0.02em; }
/* Bloco "Siga nas redes sociais" na coluna da marca do rodapé. */
.foot-social { margin-top: 20px; display: flex; flex-wrap: wrap; gap: 14px 20px; align-items: center; }
.foot-social-label { display: block; flex: 0 0 100%; font-family: var(--font-nav); font-size: 0.78rem; letter-spacing: 0.04em; color: var(--text-secondary); font-weight: 600; margin-bottom: 10px; }
.foot-social-link { display: inline-flex; align-items: center; gap: 9px; color: var(--muted); text-decoration: none; font-size: 0.92rem; transition: color .2s ease; }
.foot-social-link:hover { color: var(--gold); }
.foot-social-link:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; border-radius: 5px; }
.foot-social-ic { width: 21px; height: 21px; flex: none; stroke: currentColor; stroke-width: 1.7; fill: none; }
.foot-social-dot { fill: currentColor; stroke: none; }
/* Quebra responsiva: 4→2 colunas (marca ocupa a linha inteira), depois 1. */
@media (max-width: 860px) { .foot-grid { grid-template-columns: 1fr 1fr; } .foot-brand-col { grid-column: 1 / -1; } }
@media (max-width: 560px) {
  .prefooter-inner { flex-direction: column; align-items: flex-start; }
  .prefooter-cta { width: 100%; justify-content: center; }
  /* Phone tap targets: give standalone footer/aside text links vertical hit-area
     without enlarging the visible type. Only standalone link lists — never
     in-sentence inline links. The existing column gap keeps rows from touching.
     (.foot-links a ganhou padding-block 8px no base em 2026-07-19 — P2-1.) */
  .foot-social-link { min-height: 44px; }
  .sec-aside .inline-link { display: inline-block; padding-block: 6px; }
}
@media (max-width: 480px) { .foot-grid { grid-template-columns: 1fr; } .foot-row { flex-direction: column; text-align: center; } }

/* =========================================================
   COBERTURA / INTEGRAÇÕES standalone-page header
   ========================================================= */
.page-head { padding-block: clamp(40px, 6vw, 72px) clamp(20px, 3vw, 36px); }
/* FB-A: páginas editoriais internas compartilham uma abertura mais composta e o
   mesmo ritmo vertical. Home e beta mantêm seus heróis próprios; páginas legais
   preservam a densidade deliberada. */
.spa-view.editorial-view .page-head {
  position: relative;
  padding-block: clamp(52px, 7vw, 88px) clamp(36px, 5vw, 60px);
  border-bottom: 1px solid var(--hair);
}
.spa-view.editorial-view .page-head::after {
  content: "";
  position: absolute;
  inset: auto 0 -1px;
  width: min(180px, 35vw);
  height: 1px;
  background: linear-gradient(90deg, var(--gold), transparent);
}
.spa-view.editorial-view .page-head h1,
.spa-view.editorial-view .page-head h2.page-h1 {
  max-width: 18ch;
  font-size: clamp(2.35rem, 1.45rem + 3.6vw, 4.25rem);
  margin-block: 20px 18px;
}
.spa-view.editorial-view section.block {
  padding-top: clamp(44px, 6vw, 76px) !important;
}
.spa-view.editorial-view section.block ~ section.block {
  border-top: 1px solid color-mix(in srgb, var(--hair) 72%, transparent);
}
.spa-view#view-cobertura .corpus-switch + section.block {
  border-top: 1px solid color-mix(in srgb, var(--hair) 72%, transparent);
}
.page-head .back {
  font-family: 'Fira Code', monospace; font-size: 0.76rem; color: var(--muted);
  text-decoration: none; letter-spacing: 0.04em;
  /* LC-07: área de toque >=44px sem deslocar o visual — o padding amplia o alvo
     e a margem negativa compensa a posição. */
  display: inline-block; padding: 16px 10px; margin: -16px -10px;
}
.page-head .back:hover { color: var(--gold); }
.page-head h1, .page-head h2.page-h1 { font-size: clamp(2.1rem, 1.4rem + 3vw, 3.6rem); margin: 18px 0 16px; }

/* =========================================================
   REDUCED MOTION : disable all non-essential motion
   ========================================================= */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important; animation-iteration-count: 1 !important;
    transition-duration: .001ms !important; transition-delay: 0s !important; scroll-behavior: auto !important;
  }
  .reveal { opacity: 1 !important; transform: none !important; }
  .marquee-track { animation: none !important; }
  h1 .hl::after, h2.page-h1 .hl::after { transform: scaleX(1) !important; }
}

/* View Transitions : gentle cross-fade between same-page anchors */
@media (prefers-reduced-motion: no-preference) {
  ::view-transition-old(root), ::view-transition-new(root) { animation-duration: .35s; }
}

/* =========================================================
   SPA VIEWS : client-side router shows/hides these
   ========================================================= */
.spa-view[hidden] { display: none !important; }
/* O container da view recebe foco PROGRAMÁTICO na troca de rota (app.js foca o
   container para o leitor de tela anunciar a navegação). Como o container é
   full-bleed, o anel default do UA pintava uma linha branca de 1px colada na
   borda esquerda da viewport ("borda infinita" flagrada pelo operador
   2026-07-19). Foco aqui é navegação, nunca alvo interativo: sem anel. */
.spa-view:focus, #app-view:focus { outline: none; }

/* =========================================================
   ONTOLOGY CANVAS : interactive node-link graph
   ========================================================= */
.onto-graph-wrap {
  position: relative; margin-top: 36px; text-align: center;
}
.onto-graph-header {
  font-family: 'Lora', 'Lora Fallback', Georgia, serif; font-weight: 500;
  font-size: clamp(1.6rem, 1rem + 2.2vw, 2.4rem); line-height: 1.1;
  letter-spacing: -0.02em; margin-bottom: 10px; text-wrap: balance;
}
.onto-graph-sub {
  color: var(--muted); font-size: 1.02rem; max-width: 58ch; margin-inline: auto;
  margin-bottom: 22px; line-height: 1.62;
}
.ontology-canvas {
  width: 100%; max-width: 1080px; height: auto; aspect-ratio: 1 / 0.60; display: block;
  margin-inline: auto; border-radius: 20px;
  /* Layered ground: a soft gold-tinted radial bloom behind the hub + a cool
     vignette, so the constellation sits in depth rather than on a flat slab. */
  background:
    radial-gradient(60% 75% at 40% 52%, color-mix(in srgb, var(--gold) 7%, transparent), transparent 70%),
    radial-gradient(120% 120% at 82% 18%, rgba(87,199,245,0.05), transparent 55%),
    linear-gradient(160deg, rgba(14,20,36,0.92), var(--vignette-deep));
  border: 1px solid var(--hair);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.04), 0 30px 70px -50px rgba(0,0,0,0.9);
  cursor: default;
}
/* JS hides the canvas on phones (sets [hidden]) and shows .onto-mobile instead.
   The attribute selector wins regardless of any display set elsewhere. */
.ontology-canvas[hidden] { display: none !important; }
.onto-hint {
  margin-top: 10px; font-family: 'Fira Code', monospace;
  font-size: 0.74rem; color: var(--muted-2); letter-spacing: 0.04em;
}
.onto-noscript {
  color: var(--muted); font-size: 0.9rem; margin-top: 12px;
  border: 1px dashed var(--hair); border-radius: 12px;
  padding: 18px 22px; max-width: 480px; margin-inline: auto;
}

/* =========================================================
   ONTOLOGY : mobile DOM constellation (phones only)
   A legible, touch-first replacement for the desktop canvas. Sources flow DOWN
   into the ontology hub, which fans out into the six ways to search. Real text
   (never clipped), real buttons (≥44px touch targets), CSS connector lines.
   ========================================================= */
.onto-mobile { display: none; }
.onto-mobile[hidden] { display: none !important; }
@media (max-width: 640px) {
  .onto-mobile:not([hidden]) { display: block; }
}
.onto-mobile {
  margin-inline: auto; max-width: 460px;
  padding: 22px 16px 20px; border-radius: 20px;
  background:
    radial-gradient(80% 55% at 50% 30%, color-mix(in srgb, var(--gold) 8%, transparent), transparent 70%),
    linear-gradient(160deg, rgba(14,20,36,0.92), var(--vignette-deep));
  border: 1px solid var(--hair);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.04), 0 24px 60px -46px rgba(0,0,0,0.9);
}

/* Tier 1 , the three sources */
.om-tier.om-sources {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 9px;
}
.om-src {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; gap: 3px; min-height: 66px;
  padding: 11px 7px; border-radius: 13px;
  background: var(--bg-2); border: 1px solid var(--hair);
  border-top: 2px solid var(--fam-default);
}
.om-src.fam-juris  { border-top-color: var(--gold); }
.om-src.fam-legis  { border-top-color: var(--sky); }
.om-src.fam-dout   { border-top-color: var(--fam-trts); }
.om-src-label {
  font-family: 'Lora', 'Lora Fallback', Georgia, serif; font-weight: 600;
  font-size: 0.86rem; line-height: 1.12; color: var(--ink);
}
.om-src.fam-juris .om-src-label { color: var(--gold-bright); }
.om-src.fam-legis .om-src-label { color: #8fdcff; }
.om-src.fam-dout  .om-src-label { color: #8fe6c4; }
.om-src-sub {
  font-family: 'Fira Code', monospace; font-size: 0.6rem;
  letter-spacing: 0.02em; color: var(--text-secondary); line-height: 1.2;
}

/* Connectors */
.om-link { position: relative; height: 26px; }
.om-link-down::before {
  content: ""; position: absolute; left: 50%; top: 0; bottom: 0; width: 2px;
  transform: translateX(-50%);
  background: linear-gradient(180deg, color-mix(in srgb, var(--gold) 55%, transparent), color-mix(in srgb, var(--gold) 18%, transparent));
}
.om-link-fan { height: 22px; }
.om-link-fan::before {
  content: ""; position: absolute; left: 50%; top: 0; height: 11px; width: 2px;
  transform: translateX(-50%);
  background: linear-gradient(180deg, color-mix(in srgb, var(--gold) 55%, transparent), color-mix(in srgb, var(--gold) 20%, transparent));
}
.om-link-fan::after {
  content: ""; position: absolute; left: 22%; right: 22%; top: 11px; height: 11px;
  border: 2px solid transparent;
  border-top: 2px solid color-mix(in srgb, var(--gold) 28%, transparent);
  border-radius: 60% 60% 0 0 / 100% 100% 0 0;
  border-bottom: none;
}

/* Tier 2 , the ontology hub */
.om-hub {
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  text-align: center; padding: 15px 18px; margin-inline: auto; max-width: 320px;
  border-radius: 16px;
  background: radial-gradient(120% 120% at 50% 0%, rgba(243,212,136,0.16), color-mix(in srgb, var(--gold) 5%, transparent));
  border: 1px solid var(--rule);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--gold) 6%, transparent), 0 14px 38px -22px color-mix(in srgb, var(--gold) 50%, transparent);
}
.om-hub-title {
  font-family: 'Lora', 'Lora Fallback', Georgia, serif; font-weight: 600; font-size: 1.16rem;
  letter-spacing: -0.01em; line-height: 1.1; color: var(--gold-bright);
}
.om-hub-sub {
  font-family: 'Fira Code', monospace; font-size: 0.66rem;
  letter-spacing: 0.04em; color: var(--ink-soft);
}

/* Tier 3 , the six search modes (interactive) */
.om-modes-cap {
  text-align: center; color: var(--text-secondary);
  font-size: 0.86rem; line-height: 1.45; margin: 4px auto 14px; max-width: 36ch;
}
.om-modes {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px;
}
.om-mode {
  position: relative; display: flex; flex-direction: column; gap: 3px;
  text-align: left; min-height: 64px; padding: 12px 13px;
  border-radius: 13px; cursor: pointer;
  background: var(--bg-2); border: 1px solid var(--hair); color: var(--ink);
  font-family: inherit;
  transition: border-color .2s ease, background .2s ease, transform .15s ease, box-shadow .2s ease;
}
.om-mode:hover { border-color: var(--rule); background: var(--bg-3); }
.om-mode:active { transform: scale(0.985); }
.om-mode.is-rec {
  border-color: color-mix(in srgb, var(--gold) 42%, transparent);
  background: linear-gradient(160deg, color-mix(in srgb, var(--gold) 8%, transparent), var(--bg-2));
}
.om-mode-flag {
  position: absolute; top: -8px; right: 10px;
  font-family: 'Fira Code', monospace; font-size: 0.54rem;
  letter-spacing: 0.1em; text-transform: uppercase; font-weight: 700; color: var(--btn-gold-ink) /* era #1a1303, quase-gêmeo literal de --btn-gold-ink */;
  background: linear-gradient(180deg, var(--gold-bright), var(--gold));
  padding: 3px 8px; border-radius: 999px;
}
.om-mode-label {
  font-family: 'Lora', 'Lora Fallback', Georgia, serif; font-weight: 600; font-size: 0.98rem;
  line-height: 1.12; color: var(--ink);
}
.om-mode-sub {
  font-family: 'Fira Code', monospace; font-size: 0.62rem;
  letter-spacing: 0.03em; color: var(--text-secondary); line-height: 1.2;
}

/* =========================================================
   SEARCH MODALITIES : 6-card grid (interactive, explained)
   ========================================================= */
.modalities-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 16px; margin-top: var(--space-10); align-items: start;
}
.modality-card {
  position: relative; display: flex; flex-direction: column;
  background: var(--bg-2); border: 1px solid var(--hair); border-radius: 16px;
  padding: 24px 22px; scroll-margin-top: 96px;
  transition: border-color .22s ease, background .22s ease, transform .2s ease, box-shadow .22s ease;
}
.modality-card:hover { border-color: var(--rule); background: var(--bg-3); transform: translateY(-3px); }
/* Flashed when its node is clicked in the ontology graph above (canvas → card bridge). */
.modality-card.is-focused {
  border-color: var(--gold); background: var(--bg-3);
  box-shadow: 0 0 0 1px var(--gold), 0 18px 50px -28px color-mix(in srgb, var(--gold) 55%, transparent);
}
.modality-card.is-recommended { border-color: color-mix(in srgb, var(--gold) 38%, transparent); }
.modality-rec {
  position: absolute; top: 14px; right: 14px;
  font-family: 'Fira Code', monospace; font-size: 0.6rem;
  letter-spacing: var(--track-label); text-transform: uppercase; color: var(--btn-gold-ink) /* era #1a1303, quase-gêmeo literal de --btn-gold-ink */; font-weight: 700;
  background: linear-gradient(180deg, var(--gold-bright), var(--gold));
  padding: 3px 9px; border-radius: 999px;
}
.modality-head { display: flex; align-items: center; gap: 13px; margin-bottom: 12px; }
.modality-icon {
  flex: none; width: 42px; height: 42px; border-radius: 12px; display: grid; place-items: center;
  background: color-mix(in srgb, var(--gold) 8%, transparent); color: var(--gold); border: 1px solid var(--rule);
}
.modality-card h3 {
  font-family: 'Lora', 'Lora Fallback', Georgia, serif; font-weight: 600; font-size: 1.16rem;
  line-height: 1.2; display: flex; flex-direction: column; gap: 2px;
}
.modality-kind {
  font-family: 'Fira Code', monospace; font-weight: 500;
  font-size: 0.62rem; letter-spacing: var(--track-label); text-transform: uppercase;
  color: var(--text-tertiary);
}
.modality-lead { color: var(--text-primary); font-size: 0.97rem; line-height: 1.58; }
.modality-fields {
  list-style: none; display: flex; flex-wrap: wrap; gap: 6px; margin: 14px 0 2px;
}
.modality-fields li {
  font-family: 'Fira Code', monospace; font-size: 0.68rem;
  color: var(--text-secondary); background: var(--card); border: 1px solid var(--hair);
  border-radius: 7px; padding: 4px 8px;
}
.modality-more { margin-top: 13px; }
.modality-more summary {
  cursor: pointer; list-style: none; width: max-content;
  font-family: 'Fira Code', monospace; font-size: 0.7rem;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--gold);
  display: inline-flex; align-items: center; gap: 6px; transition: color .18s ease;
}
.modality-more summary::-webkit-details-marker { display: none; }
.modality-more summary::after {
  content: '+'; font-size: 0.95rem; line-height: 1; color: var(--gold); transition: transform .2s ease;
}
.modality-more[open] summary::after { content: '\2013'; }
.modality-more summary:hover { color: var(--gold-bright); }
.modality-more > p {
  color: var(--text-secondary); font-size: 0.9rem; line-height: 1.6;
  margin-top: 11px; padding-top: 11px; border-top: 1px solid var(--hair);
}
.modality-eg {
  display: flex; flex-direction: column; gap: 5px;
  border-top: none !important; padding-top: 9px !important;
}
.modality-eg span {
  font-family: 'Fira Code', monospace; font-size: 0.6rem;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--text-tertiary);
}
.modality-eg code {
  font-family: 'Fira Code', monospace; font-size: 0.78rem; line-height: 1.5;
  color: var(--ink-soft); background: var(--bg); border: 1px solid var(--hair);
  border-radius: 8px; padding: 8px 10px; word-break: break-word;
}
.modality-tool {
  margin-top: auto; padding-top: 16px;
  font-family: 'Fira Code', monospace; font-size: 0.66rem;
  letter-spacing: 0.04em; color: var(--text-tertiary); word-break: break-word;
}

/* =========================================================
   LEGISLATION SECTION : progressive-disclosure cards
   Each card leads with a headline stat, then a scannable lede, then a native
   <details> reveal for the full breakdown. No chip-wall at rest; the detail is
   one keystroke / tap away and works with JS disabled.
   ========================================================= */
.legis-cards {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: 16px; margin-top: var(--space-10); align-items: start;
}
/* Colapsa alinhado ao ritmo das dobras irmãs (.busca-tipos/.features colapsam em
   760): em 768px a fileira não fica 1-col enquanto a vizinha já está 2-up. Banda
   760-979 fica 2-up para os 3 cards ricos não espremerem antes do 3-up em 980. */
@media (min-width: 760px) and (max-width: 979px) { .legis-cards { grid-template-columns: repeat(2, 1fr); max-width: 720px; margin-inline: auto; } }
@media (max-width: 759px) { .legis-cards { grid-template-columns: 1fr; max-width: 640px; margin-inline: auto; } }

/* Sub-bloco "Além da jurisprudência" (fusão das antigas seções 04 Cobertura + 07
   Legislação & Doutrina, ordem do operador 2026-07-22): separa a legislação e a
   doutrina das métricas de jurisprudência acima com um filete, sem abrir uma seção
   nova. O rótulo é um eyebrow NAO-heading, então a hierarquia da seção segue h2 (o
   título da Cobertura) -> h3 (os cards). */
.acervo-plus-block { margin-top: clamp(30px, 4.5vw, 52px); padding-top: clamp(26px, 3.5vw, 40px); border-top: 1px solid var(--hair); }
.acervo-plus-eyebrow {
  font-family: 'Fira Code', 'Fira Code Fallback', monospace; font-size: 0.78rem;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--gold);
  margin-bottom: clamp(16px, 2vw, 22px);
}

.legis-card {
  background:
    linear-gradient(168deg, rgba(255,255,255,0.035), transparent 60%),
    var(--bg-2);
  border: 1px solid var(--hair); border-radius: 18px;
  padding: clamp(22px, 2.6vw, 30px);
  min-width: 0;
  transition: border-color .25s ease, transform .2s ease, box-shadow .25s ease;
}
.legis-card:hover {
  border-color: var(--rule); transform: translateY(-3px);
  box-shadow: 0 26px 60px -44px rgba(0,0,0,0.95);
}
.legis-card-head { display: flex; align-items: center; gap: 14px; margin-bottom: 16px; }
.legis-card-icon {
  width: 46px; height: 46px; flex: none; border-radius: 13px; display: grid; place-items: center;
  background: color-mix(in srgb, var(--gold) 10%, transparent); color: var(--gold); border: 1px solid var(--rule);
}
.legis-card-figure { display: flex; flex-direction: column; line-height: 1.05; }
.legis-card-num {
  font-family: 'Lora', 'Lora Fallback', Georgia, serif; font-weight: 600;
  font-size: clamp(1.7rem, 1.2rem + 1.6vw, 2.2rem); letter-spacing: -0.02em;
  color: var(--ink); font-variant-numeric: tabular-nums; font-feature-settings: "tnum";
}
/* Glifo no lugar do número quando a métrica é secreta (doutrina nunca divulga
   quantidade nem composição , regra de copy público do operador). */
.legis-card-icon-lg {
  font-family: 'Lora', 'Lora Fallback', Georgia, serif; font-weight: 600;
  font-size: clamp(1.9rem, 1.2rem + 2vw, 2.4rem); line-height: 1;
  color: var(--gold); letter-spacing: -0.02em;
}
.legis-card-unit {
  font-family: 'Fira Code', monospace; font-size: 0.72rem; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--text-tertiary); margin-top: 4px;
}
.legis-card-title {
  font-family: 'Lora', 'Lora Fallback', Georgia, serif; font-weight: 600; font-size: 1.2rem;
  margin-bottom: 8px; line-height: 1.25; color: var(--ink);
}
.legis-card-lede { color: var(--text-primary); font-size: 0.96rem; line-height: 1.6; }
.legis-card-lede strong { color: var(--gold-bright); font-weight: 500; }

/* Disclosure */
.legis-disclose { margin-top: 16px; border-top: 1px solid var(--hair); }
.legis-disclose > summary {
  list-style: none; cursor: pointer; user-select: none;
  display: flex; align-items: center; gap: 8px;
  padding: 13px 2px 4px; margin-top: 8px;
  font-family: 'Fira Code', monospace; font-size: 0.76rem; letter-spacing: 0.03em;
  color: var(--gold); transition: color .18s ease;
}
.legis-disclose > summary::-webkit-details-marker { display: none; }
.legis-disclose > summary::after {
  content: ""; width: 8px; height: 8px; margin-left: 2px;
  border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg); transition: transform .22s ease;
}
.legis-disclose[open] > summary::after { transform: rotate(-135deg); }
.legis-disclose > summary:hover { color: var(--gold-bright); }
.legis-disclose > summary:focus-visible { outline: 2px solid var(--gold-bright); outline-offset: 3px; border-radius: 6px; }
.legis-disclose[open] > summary { color: var(--text-tertiary); }
/* gentle reveal of the disclosed body (motion-safe) */
.js .legis-disclose[open] > :not(summary) { animation: legisReveal .32s cubic-bezier(.22,.61,.36,1) both; }
@keyframes legisReveal { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }

.legis-list {
  list-style: none; display: grid; gap: 9px; font-size: 0.92rem; color: var(--text-primary);
  margin-top: 6px;
}
.legis-list li { display: flex; align-items: flex-start; gap: 9px; line-height: 1.5; }
.legis-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--gold); flex: none; margin-top: 0.55em; }
.legis-dot-premium { width: 6px; height: 6px; border-radius: 50%; background: var(--indigo); flex: none; margin-top: 0.55em; }

.legis-sub-title {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-family: 'Fira Code', monospace; font-size: 0.7rem; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--text-tertiary); font-weight: 500;
  margin: 16px 0 7px;
}
.legis-count {
  font-size: 0.7rem; letter-spacing: 0.04em; color: var(--gold);
  background: color-mix(in srgb, var(--gold) 10%, transparent); border: 1px solid var(--rule);
  border-radius: 999px; padding: 2px 8px;
}
.legis-uf-row {
  font-family: 'Fira Code', monospace; font-size: 0.82rem; line-height: 1.7;
  color: var(--ink-soft); letter-spacing: 0.02em;
}

.legis-tools { list-style: none; display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; }
.legis-tools li { min-width: 0; }
.tool-name {
  font-family: 'Fira Code', monospace; font-size: 0.74rem;
  color: var(--gold-bright); background: color-mix(in srgb, var(--gold) 7%, transparent);
  border: 1px solid var(--rule); border-radius: 7px; padding: 4px 9px;
  display: inline-block; max-width: 100%;
  overflow-wrap: anywhere; word-break: break-word;
  transition: background .18s ease, border-color .18s ease;
}
.legis-tools li:hover .tool-name { background: color-mix(in srgb, var(--gold) 13%, transparent); border-color: var(--gold-soft); }
.legis-tier-note { font-size: 0.8rem; color: var(--text-secondary); margin-top: 12px; line-height: 1.45; }
.legis-tier-note .tool-name { font-size: 0.72rem; }

/* Quiet bridge from the lawyer-facing legislation flow to the developer surface. */
.legis-dev-bridge {
  margin-top: 26px; text-align: center; color: var(--text-secondary);
  font-size: 0.96rem; line-height: 1.5;
  max-width: 56ch; margin-inline: auto;
}

/* =========================================================
   DIFFERENTIATOR : raw-mess → clean-base visual explainer
   ========================================================= */
.transform {
  margin-top: 40px; display: grid;
  grid-template-columns: 1fr auto 1fr; gap: clamp(12px, 2vw, 22px);
  align-items: stretch;
}
.transform-panel {
  border: 1px solid var(--hair); border-radius: 18px;
  padding: 20px 18px; background: var(--bg-2); min-width: 0;
}
.transform-before {
  background: linear-gradient(160deg, color-mix(in srgb, var(--err) 5%, transparent), var(--bg-2));
  border-color: color-mix(in srgb, var(--err) 20%, transparent);
}
.transform-after {
  background: linear-gradient(160deg, color-mix(in srgb, var(--gold) 7%, transparent), var(--bg-2));
  border-color: var(--rule);
}
.transform-tag {
  display: inline-block; font-family: 'Fira Code', monospace;
  font-size: 0.62rem; letter-spacing: 0.12em; text-transform: uppercase;
  padding: 4px 10px; border-radius: 999px; margin-bottom: 14px;
}
.transform-tag-raw { color: var(--err); background: color-mix(in srgb, var(--err) 10%, transparent); border: 1px solid color-mix(in srgb, var(--err) 28%, transparent); }
.transform-tag-clean { color: var(--btn-gold-ink) /* era #1a1303, quase-gêmeo literal de --btn-gold-ink */; background: linear-gradient(180deg, var(--gold-bright), var(--gold)); font-weight: 700; }
.transform-lines { list-style: none; display: flex; flex-direction: column; gap: 11px; }
.transform-lines li { display: flex; gap: 9px; align-items: flex-start; font-size: 0.86rem; line-height: 1.4; }
.transform-lines code {
  font-family: 'Fira Code', monospace; font-size: 0.78rem;
  color: var(--text-secondary); overflow-wrap: anywhere; word-break: break-word;
}
.tl-bad {
  flex: none; width: 18px; height: 18px; border-radius: 50%;
  display: grid; place-items: center; font-family: 'Fira Code', monospace;
  font-size: 0.7rem; font-weight: 700; color: var(--err);
  background: color-mix(in srgb, var(--err) 12%, transparent); border: 1px solid color-mix(in srgb, var(--err) 40%, transparent);
}
.transform-fields { list-style: none; display: flex; flex-direction: column; gap: 9px; }
.transform-fields li {
  display: flex; flex-direction: column; gap: 2px;
  padding-bottom: 9px; border-bottom: 1px solid var(--hair);
}
.transform-fields li:last-child { border-bottom: none; padding-bottom: 0; }
.tf-k {
  font-family: 'Fira Code', monospace; font-size: 0.6rem;
  letter-spacing: var(--track-label); text-transform: uppercase; color: var(--text-tertiary);
}
.tf-v { font-size: 0.94rem; color: var(--ink); line-height: 1.3; overflow-wrap: anywhere; }
.transform-arrow {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 8px; color: var(--gold); text-align: center;
}
.transform-arrow-label {
  font-family: 'Fira Code', monospace; font-size: 0.58rem;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-secondary);
  max-width: 9ch; line-height: 1.25;
}
.transform-note {
  margin-top: 22px; text-align: center; color: var(--text-secondary);
  font-size: 0.98rem; line-height: 1.55; max-width: 60ch; margin-inline: auto;
}
@media (max-width: 720px) {
  .transform { grid-template-columns: 1fr; }
  .transform-arrow { flex-direction: row; padding-block: 4px; }
  .transform-arrow svg { transform: rotate(90deg); }
  .transform-arrow-label { max-width: none; }
}

/* =========================================================
   AUTHOR / "QUEM CONSTRUIU" page
   ========================================================= */
/* Card do sócio: empilhado (foto centralizada acima do texto) por padrão em
   TODAS as larguras — é o único layout que não deixa a foto pequena "flutuando"
   ao lado de uma bio longa. O par lado-a-lado entra no mesmo breakpoint largo
   dedicado (>=900px) em que o .founders-grid vira 2 colunas (4 sócios, 2x2):
   cada coluna de 2 já tem espaço real de sobra, então o retrato pode ir para
   o lado do texto sem precisar empilhar de novo. */
.author-card {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: clamp(18px, 3vw, 26px); padding: clamp(24px, 3vw, 34px);
  border: 1px solid var(--rule); border-radius: 22px;
  background: linear-gradient(160deg, rgba(255,255,255,0.04), color-mix(in srgb, var(--gold) 4%, transparent)), var(--bg-2);
}
.author-portrait {
  flex: none; width: min(220px, 60%); aspect-ratio: 3 / 4; border-radius: 20px;
  display: grid; place-items: center; overflow: hidden; position: relative; margin: 0;
  background: radial-gradient(120% 120% at 30% 20%, rgba(243,212,136,0.22), color-mix(in srgb, var(--gold) 6%, transparent));
  border: 1px solid var(--rule);
}
.author-portrait img { width: 100%; height: 100%; object-fit: cover; object-position: center 20%; }
/* Photo credit: tiny caption pinned to the portrait's lower edge. */
.author-photo-credit {
  position: absolute; left: 0; right: 0; bottom: 0; padding: 3px 6px;
  font-size: 0.68rem; letter-spacing: 0.02em; text-align: center; color: rgba(255,255,255,0.78);
  background: linear-gradient(0deg, rgba(0,0,0,0.55), rgba(0,0,0,0));
}
.author-body { width: 100%; }
.author-monogram {
  font-family: 'Lora', 'Lora Fallback', Georgia, serif; font-weight: 600;
  font-size: clamp(1.8rem, 6vw, 2.8rem); color: var(--gold-bright); letter-spacing: -0.02em;
}
/* Placeholder portrait (no photo yet): neutral initial-circle, never a broken <img>. */
.author-portrait-placeholder { place-items: center; }
/* "Bio em breve." marker until the real bio is dropped in. */
.bio-pending { color: var(--text-secondary); font-style: italic; }
.author-name { font-family: 'Lora', 'Lora Fallback', Georgia, serif; font-weight: 600; font-size: 1.3rem; margin-bottom: 6px; }
.author-role {
  font-family: 'Fira Code', monospace; font-size: 0.78rem;
  letter-spacing: 0.04em; color: var(--gold); text-transform: uppercase; margin-bottom: 16px;
}
.author-bio { color: var(--text-primary); font-size: 1.02rem; line-height: 1.62; margin-bottom: 18px; text-align: left; }
.author-creds { list-style: none; display: flex; flex-direction: column; gap: 9px; text-align: left; }
.author-creds li { display: flex; gap: 10px; align-items: flex-start; color: var(--text-secondary); font-size: 0.94rem; line-height: 1.4; }
.cred-dot { flex: none; width: 8px; height: 8px; margin-top: 7px; border-radius: 50%; background: var(--gold); }

/* >=900px: card ganha espaço real de sobra (1 ou 2 colunas no .founders-grid),
   então o retrato vai para o lado do texto. Fica fixo (não cresce com vw) para
   nunca mais desalinhar a bio comprida. */
@media (min-width: 900px) {
  .author-card {
    flex-direction: row; align-items: flex-start; text-align: left;
    gap: clamp(24px, 3vw, 40px);
  }
  .author-portrait { width: 168px; }
  .author-role { text-align: left; }
}

/* Founders: 1 coluna até 899px (empilhado, retrato acima do texto) e 2 colunas
   fixas a partir de 900px (4 sócios: 2x2, sem card órfão em nenhuma largura).
   Cada coluna de 2 tem espaço real de sobra, então o card usa o layout
   lado-a-lado geral do >=900px (retrato ao lado da bio) em vez de empilhar
   de novo como a antiga grade de 3 colunas precisava. */
.founders-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(16px, 2.5vw, 26px);
  align-items: stretch;
}
@media (min-width: 900px) {
  .founders-grid { grid-template-columns: repeat(2, 1fr); }
}
.founders-grid .author-card { height: 100%; }

.author-highlight {
  margin-top: 24px; display: grid; grid-template-columns: auto 1fr;
  gap: clamp(18px, 3vw, 32px); align-items: center;
  padding: clamp(22px, 3vw, 32px); border-radius: 20px;
  border: 1px solid var(--rule);
  background: radial-gradient(120% 140% at 0% 0%, color-mix(in srgb, var(--gold) 10%, transparent), transparent 60%), var(--bg-2);
}
.ah-figure { display: flex; flex-direction: column; align-items: center; line-height: 1; }
.ah-num {
  font-family: 'Lora', 'Lora Fallback', Georgia, serif; font-weight: 600;
  font-size: clamp(2.6rem, 9vw, 4rem); letter-spacing: -0.02em;
  background: linear-gradient(180deg, #fffdf6 18%, var(--gold) 125%);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: var(--gold);
}
.ah-unit { font-family: 'Fira Code', monospace; font-size: 0.8rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--gold); margin-top: 4px; }
.ah-text h3 { font-family: 'Lora', 'Lora Fallback', Georgia, serif; font-weight: 600; font-size: 1.18rem; margin-bottom: 8px; }
.ah-text p { color: var(--text-secondary); font-size: 0.96rem; line-height: 1.55; }
@media (max-width: 560px) {
  .author-highlight { grid-template-columns: 1fr; text-align: center; }
  .ah-text h3, .ah-text p { text-align: center; }
}

.works-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 16px; margin-top: var(--space-10); align-items: start;
}
.work-card {
  position: relative; display: flex; flex-direction: column; gap: 8px;
  padding: 22px 20px; border-radius: 16px;
  background: var(--bg-2); border: 1px solid var(--hair);
  transition: border-color .22s ease, background .22s ease, transform .2s ease;
}
.work-card:hover { border-color: var(--rule); background: var(--bg-3); transform: translateY(-3px); }
.work-tag {
  /* Piso de legibilidade 0.7rem (~11px): mono-caps a 9px + tracking viram textura
     ilegível; a hierarquia se mantém por cor gold + borda pill. */
  align-self: flex-start; font-family: 'Fira Code', monospace;
  font-size: 0.7rem; letter-spacing: var(--track-label); text-transform: uppercase;
  color: var(--gold); border: 1px solid var(--rule); background: color-mix(in srgb, var(--gold) 5%, transparent);
  padding: 4px 9px; border-radius: 999px;
}
.work-card h3 { font-family: 'Lora', 'Lora Fallback', Georgia, serif; font-weight: 600; font-size: 1.14rem; }
.work-card p { color: var(--text-secondary); font-size: 0.92rem; line-height: 1.55; }
.work-card-placeholder { border-style: dashed; opacity: 0.8; }
.work-card-placeholder em { color: var(--text-tertiary); font-style: italic; }

/* =========================================================
   EXPLORER FILTERS : family/year/órgão filter bar (POR-2)
   ========================================================= */
.explorer-filters {
  display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-end;
  padding: 16px 22px; background: var(--bg-3); border-radius: 12px;
  border: 1px solid var(--hair); margin-bottom: 18px;
}
.filter-group {
  display: flex; flex-direction: column; gap: 5px; flex: 1 1 140px; min-width: 120px;
}
.filter-group-search {
  flex: 2 1 200px; min-width: 160px;
}
.filter-label {
  font-family: 'Fira Code', monospace; font-size: 0.66rem;
  letter-spacing: var(--track-eyebrow); text-transform: uppercase; color: var(--muted-2); font-weight: 500;
}
.filter-select {
  padding: 9px 12px; border-radius: 9px; border: 1px solid var(--field-border);
  background: rgba(0,0,0,0.36); color: var(--ink);
  font-family: 'Fira Code', monospace; font-size: 0.82rem;
  appearance: none; -webkit-appearance: none; cursor: pointer;
  transition: border-color .18s ease, background .18s ease;
  /* FL-10: >=44px touch target, alinhado ao .sort-btn do mesmo painel */
  min-height: 44px;
}
.filter-select:focus:not(:focus-visible) { outline: none; border-color: var(--gold); background: rgba(0,0,0,0.48); }
.filter-search {
  padding: 9px 12px; border-radius: 9px; border: 1px solid var(--field-border);
  background: rgba(0,0,0,0.36); color: var(--ink);
  font-family: 'Fira Code', monospace; font-size: 0.82rem;
  width: 100%; transition: border-color .18s ease;
  /* FL-10: >=44px touch target, alinhado ao .sort-btn do mesmo painel */
  min-height: 44px;
}
.filter-search::placeholder { color: var(--muted-2); }
.filter-search:focus:not(:focus-visible) { outline: none; border-color: var(--gold); }
.filter-clear {
  padding: 9px 16px; border-radius: 9px; border: 1px solid var(--hair);
  background: transparent; color: var(--muted); cursor: pointer;
  font-family: 'Fira Code', monospace; font-size: 0.76rem;
  letter-spacing: 0.04em; align-self: flex-end;
  transition: border-color .18s ease, color .18s ease;
  /* FL-10: >=44px touch target, alinhado ao .sort-btn do mesmo painel */
  min-height: 44px;
}
.filter-clear:hover { border-color: var(--rule); color: var(--gold); }
@media (max-width: 640px) {
  .explorer-filters { flex-direction: column; align-items: stretch; }
  .filter-clear { align-self: flex-start; }
}

/* "Filtro não se aplica" chip (QA sweep B seq2703): honest inline note in the head
   of the sections that do NOT react to the explorer filter (relatores, órgãos
   julgadores, precedentes por tipo). Baked [hidden] in the HTML; app.js reveals it
   while a filter is active. Hairline + muted keeps it discreet; --muted is AA on
   --bg-3 in both themes. The [hidden] re-assert beats the inline-flex above. */
.filter-na {
  display: inline-flex; align-items: center; gap: 7px;
  margin: 10px 0 0; padding: 5px 12px;
  font-family: var(--font-nav); font-size: 0.76rem; line-height: 1.45;
  color: var(--muted);
  background: var(--bg-3); border: 1px solid var(--hair); border-radius: var(--radius-pill);
}
.filter-na .filter-na-ic { flex: 0 0 auto; color: var(--muted-2); }
.filter-na[hidden] { display: none; }

/* ════════════════════════════════════════════════════════════════════════════
   V2 "O Acervo" : corpus-switcher (Jurisprudência | Normativos | Doutrina) +
   painéis Normativos e Doutrina. Sem JS os painéis empilham (cada um com <h2>);
   com JS o app.js liga o tablist ARIA e esconde os inativos.
   ════════════════════════════════════════════════════════════════════════════ */
.corpus-switch { margin-top: clamp(28px, 4vw, 44px); }

/* Barra de abas — mesma linguagem visual do #demo (.demo-tabs): sublinhado dourado,
   scroll horizontal em telas estreitas. Vira role=tablist via app.js. */
.corpus-tabs {
  display: flex; justify-content: flex-start; gap: 6px; overflow-x: auto;
  scrollbar-width: none; scroll-snap-type: x proximity;
  border-bottom: 1px solid var(--hair); margin-bottom: clamp(20px, 3vw, 30px);
}
.corpus-tabs::-webkit-scrollbar { display: none; }
.corpus-tab {
  scroll-snap-align: start; white-space: nowrap; min-height: 44px;
  display: inline-flex; align-items: center; padding: 10px 18px;
  font-family: 'Public Sans', system-ui, sans-serif; font-size: 0.98rem; font-weight: 600;
  color: var(--muted); text-decoration: none; cursor: pointer;
  background: none; border: 0; border-bottom: 2px solid transparent;
  transition: color .18s ease, border-color .18s ease;
}
.corpus-tab:hover { color: var(--ink); }
.corpus-tab.is-active { color: var(--gold-bright); border-bottom-color: var(--gold); }
.corpus-tab:focus-visible { outline: var(--focus-ring); outline-offset: -2px; border-radius: var(--radius-xs); }

/* Cada painel: sem JS o .corpus-switch NÃO recebe .switch-js → todos visíveis e
   empilhados (o [hidden] é neutralizado). Com JS, só o .is-active aparece. */
.corpus-switch:not(.switch-js) .corpus-panel[hidden] { display: block; }
.corpus-switch:not(.switch-js) .corpus-panel + .corpus-panel {
  margin-top: clamp(32px, 5vw, 52px); padding-top: clamp(24px, 4vw, 40px);
  border-top: 1px solid var(--hair);
}
.corpus-switch:not(.switch-js) .corpus-tabs { display: none; } /* âncoras redundantes sem JS */
.corpus-panel-h {
  font-family: 'Lora', Georgia, serif; font-weight: 600;
  font-size: var(--step-h2); line-height: 1.12; margin: 0; text-wrap: balance;
  scroll-margin-top: 84px; position: relative;
}
.corpus-panel-h > span[id] { position: absolute; top: -84px; } /* âncora de deep-link sem deslocar o texto */
.corpus-panel-lede {
  color: var(--muted); font-size: var(--step-body); line-height: 1.5;
  margin: 10px 0 clamp(20px, 3vw, 30px); max-width: 62ch;
}

/* ---- Painel Normativos ---- */
.norm-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 18px; }
.norm-grid .chart-span { grid-column: 1 / -1; }
@media (max-width: 720px) { .norm-grid { grid-template-columns: 1fr; } }

/* Barra empilhada por esfera */
.esf-bar {
  display: flex; width: 100%; height: 34px; border-radius: var(--radius-pill);
  overflow: hidden; background: var(--bg-3); border: 1px solid var(--hair);
}
/* ⛔ Mesmo defeito e mesmo conserto de `.stats-updated[hidden]` (o mecanismo esta la).
   `#esf-bar` nasce `hidden` e o renderEsferaBar() so o revela com total > 0; sem esta linha a
   barra vazia seguia ocupando os seus 34px de altura (1026x34 a 1280px, 234x34 a 320px) e a
   arvore de acessibilidade anunciava `img "Distribuicao por esfera indisponivel."` -- exatamente
   o que o `hidden` existia para calar. */
.esf-bar[hidden] { display: none; }
.esf-seg { display: block; height: 100%; min-width: 3px; transition: width .5s cubic-bezier(.22,1,.36,1); }
.esf-seg.esf-federal { background: var(--esf-federal); }
.esf-seg.esf-estadual { background: var(--esf-estadual); }
.esf-seg.esf-municipal { background: var(--esf-municipal); }
.esf-legend {
  list-style: none; display: flex; flex-wrap: wrap; gap: 8px 22px; margin: 16px 0 0; padding: 0;
}
.esf-legend li { display: flex; align-items: baseline; gap: 8px; }
.esf-dot { width: 11px; height: 11px; border-radius: 3px; flex: none; transform: translateY(1px); }
.esf-dot.esf-federal { background: var(--esf-federal); }
.esf-dot.esf-estadual { background: var(--esf-estadual); }
.esf-dot.esf-municipal { background: var(--esf-municipal); }
.esf-val { font-family: 'Fira Code', monospace; font-weight: 600; font-size: 1.02rem;
  color: var(--ink); font-variant-numeric: tabular-nums; }
.esf-k { color: var(--muted); font-size: 0.9rem; }

/* Funil de curadoria */
.funnel { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 14px; }
.funnel-step { position: relative; display: grid; grid-template-columns: 1fr auto; align-items: center;
  gap: 4px 12px; padding: 12px 14px; border-radius: var(--radius-md);
  background: var(--bg-3); border: 1px solid var(--hair); overflow: hidden; }
.funnel-bar { position: absolute; inset: 0 auto 0 0; height: 100%; z-index: 0;
  background: color-mix(in srgb, var(--gold) 16%, transparent); border-right: 2px solid var(--gold-soft);
  transition: width .5s cubic-bezier(.22,1,.36,1); }
.funnel-step.is-out .funnel-bar { background: color-mix(in srgb, var(--gold) 26%, transparent); }
.funnel-lbl { position: relative; z-index: 1; color: var(--ink-soft); font-size: 0.92rem; font-weight: 600; }
.funnel-num { position: relative; z-index: 1; font-family: 'Fira Code', monospace; font-weight: 600;
  font-size: 1.06rem; color: var(--gold-bright); font-variant-numeric: tabular-nums; }
.funnel-note { color: var(--muted-2); font-size: 0.82rem; line-height: 1.45; margin: 14px 0 0; }

/* Federal ao vivo */
.fed-stat { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 14px; }
.fed-stat li { display: flex; align-items: baseline; gap: 10px; }
.fed-val { font-family: 'Fira Code', monospace; font-weight: 600; font-size: 1.5rem;
  color: var(--gold); font-variant-numeric: tabular-nums; }
.fed-k { color: var(--muted); font-size: 0.9rem; }

/* Chips de UF (mapa de estados no MCP — highlight estático fase Z) */
.uf-chips { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px; }
.uf-chip {
  font-family: 'Fira Code', monospace; font-size: 0.8rem; font-weight: 600; letter-spacing: 0.04em;
  color: var(--gold-bright); background: color-mix(in srgb, var(--gold) 12%, transparent);
  border: 1px solid var(--rule); border-radius: var(--radius-sm); padding: 7px 11px;
}

/* Medidor de cobertura de embeddings (feature-detect) */
.embed-meter { display: flex; flex-direction: column; gap: 8px; }
.embed-track { height: 12px; border-radius: var(--radius-pill); background: var(--bg-3);
  border: 1px solid var(--hair); overflow: hidden; }
.embed-fill { height: 100%; background: var(--esf-federal); transition: width .5s cubic-bezier(.22,1,.36,1); }
.embed-cap { display: flex; justify-content: space-between; gap: 12px;
  font-family: 'Fira Code', monospace; font-size: 0.82rem; color: var(--muted); }
.embed-cap .embed-pct { color: var(--gold-bright); font-weight: 600; font-variant-numeric: tabular-nums; }

/* Filtros gated de normativos (inseridos por app.js) — mesmo shell dos .filter-* */
.norm-gated-filters {
  display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-end;
  padding: 16px 22px; background: var(--bg-3); border-radius: 12px;
  border: 1px solid var(--hair); margin-bottom: 18px;
}
/* O container nasce [hidden] e só é revelado quando o payload traz uma chave gated
   (UF/situação/tipo/ano). Sem este guard a declaração `display:flex` acima vence o
   `[hidden]{display:none}` da UA e deixa um pill VAZIO no topo do painel Normativos
   (defeito visto na varredura 2026-07-12). Restaura o contrato feature-detect. */
.norm-gated-filters[hidden] { display: none; }

/* ---- Painel Doutrina aberta ---- */
.dout-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 18px; }
@media (max-width: 520px) { .dout-grid { grid-template-columns: 1fr; } }
.dout-fig { background: var(--bg-2); border: 1px solid var(--hair); border-radius: 18px;
  padding: clamp(22px, 3vw, 30px); }
.dout-num { font-family: 'Lora', Georgia, serif; font-weight: 600;
  font-size: clamp(2rem, 1.4rem + 2.4vw, 3rem); color: var(--gold);
  line-height: 1; font-variant-numeric: tabular-nums; }
.dout-k { color: var(--muted); font-size: 0.98rem; margin-top: 10px; }
.dout-source { display: flex; align-items: flex-start; gap: 16px; margin-top: 22px;
  padding: 18px 20px; background: var(--card); border: 1px solid var(--hair); border-radius: var(--radius-lg); }
.dout-badge { flex: none; font-family: 'Fira Code', monospace; font-weight: 700; font-size: 0.82rem;
  letter-spacing: 0.06em; color: var(--gold-bright); background: color-mix(in srgb, var(--gold) 14%, transparent);
  border: 1px solid var(--rule); border-radius: var(--radius-sm); padding: 8px 12px; }
.dout-source p { color: var(--muted); font-size: 0.95rem; line-height: 1.5; margin: 0; }

/* Realce breve ao saltar de um select categórico "jump" para o gráfico alvo. */
.jump-flash { animation: jumpFlash 1.4s ease; border-radius: var(--radius-md); }
@keyframes jumpFlash {
  0%, 100% { box-shadow: 0 0 0 0 transparent; }
  20%, 60% { box-shadow: 0 0 0 3px var(--rule); }
}
@media (prefers-reduced-motion: reduce) { .jump-flash { animation: none; } }

/* ════════════════════════════════════════════════════════════════════════════
   Task #67 , landing rebuild components (mobile-first; spec S1-S9 + /integracoes)
   ════════════════════════════════════════════════════════════════════════════ */

/* ---- Hero: quick-capture + counter microcopy ---- */
.quick-capture { display: flex; flex-direction: column; gap: 10px; margin-top: 22px; max-width: 460px; }
/* BOARD-08: help de passo 2 fica sob a fileira e-mail+botão (não entre eles no desktop). */
.quick-capture .qc-help {
  margin: 0;
  font-size: 0.85rem;
  line-height: 1.35;
  color: var(--text-tertiary, var(--ink-soft));
  max-width: 32rem;
}
.quick-capture input {
  width: 100%; min-height: 48px; padding: 12px 16px; border-radius: 12px;
  border: 1px solid var(--field-border); background: var(--card); color: var(--ink);
  font: inherit; font-size: 0.98rem;
}
.quick-capture input::placeholder { color: var(--text-tertiary); }
.quick-capture .qc-btn { min-height: 48px; justify-content: center; }
@media (min-width: 621px) {
  .quick-capture { flex-direction: row; flex-wrap: wrap; align-items: stretch; }
  .quick-capture input { flex: 1 1 auto; min-width: 12rem; }
  .quick-capture .qc-btn { flex: 0 0 auto; }
  .quick-capture .qc-help { flex: 1 0 100%; }
}
.counter-foot {
  margin-top: 14px; font-size: 0.78rem; line-height: 1.5; color: var(--text-tertiary);
  border-top: 1px solid var(--hair); padding-top: 12px;
}
/* Live variant: the pulse dot sits inline with "Atualizado em <data>" (the date
   already conveys freshness, so the old separate "atualizado continuamente" badge
   was dropped as redundant). */
.counter-foot--live { display: inline-flex; align-items: center; gap: 9px; width: 100%; }
/* ⛔ Re-afirmar o [hidden] do UA por cima do inline-flex acima. Esta folha JA resolveu
   exatamente isto para a .theme-toggle (procure `.theme-toggle[hidden]` mais acima, com o
   comentario que explica o mecanismo) e esta segunda ocorrencia ficou por fazer -- mesmo
   ficheiro, mesmo defeito, uma instancia consertada e outra nao.
   O mecanismo: `[hidden]{display:none}` da folha do UA e (0,1,0), e a regra de classe acima
   tambem e (0,1,0) -- mas regra de AUTOR vence regra de UA em igualdade de especificidade.
   Logo o `hidden` do HTML nao surtia efeito nenhum.
   O que isso mostrava: index.html traz este <p> com `hidden` de proposito, porque o <time>
   nasce VAZIO e so o stats.js o preenche e tira o atributo. Sem esta linha, quem carrega a
   pagina antes de o JS correr -- ou com o JS a falhar -- le "Atualizado em .", uma frase de
   frescor partida ao lado de um ponto pulsante que anuncia estar "ao vivo". E, por o
   elemento continuar a ter caixa, ele permanece na arvore de acessibilidade e e anunciado.
   Achado por auditoria de movimento, ao notar que o getComputedStyle devolvia inline-flex
   para um elemento marcado hidden. */
.counter-foot--live[hidden] { display: none; }

/* ---- §01 Demo ---- */
.demo-grid { display: grid; gap: 26px; }
.demo-grid > * { min-width: 0; }
/* Desktop (2-col): a janela de chat leva a fatia flexível e larga; o rail de apoio
   é uma coluna FIXA e proporcional (era 1fr, que em telas largas virava ~440px de
   vão morto ao lado dos 3 chips soltos — bug reportado na task #63). Assim a coluna
   direita tem exatamente a largura do painel de garantias, sem void. */
@media (min-width: 981px) {
  .demo-grid { grid-template-columns: minmax(0, 1fr) minmax(288px, 340px); align-items: start; column-gap: clamp(26px, 3vw, 40px); }
}
.demo-chat {
  position: relative; background: var(--bg-2); border: 1px solid var(--hair);
  border-radius: 18px; padding: clamp(14px, 2.5vw, 22px);
  box-shadow: 0 24px 60px -30px rgba(0, 0, 0, 0.55);
}
/* Branded chat-window header: avatar + product name "IAJUS Pesquisa Jurídica" +
   a discreet "ao vivo" badge, so the demo reads as a real assistant window. */
.demo-window-head {
  display: flex; align-items: center; gap: 11px;
  margin-bottom: 14px; padding-bottom: 13px; border-bottom: 1px solid var(--hair);
}
.demo-avatar {
  flex: none; width: 38px; height: 38px; border-radius: 10px;
  display: inline-flex; align-items: center; justify-content: center;
  background: linear-gradient(135deg, var(--gold), var(--gold-bright));
  /* The brand asterisk (inline SVG) draws in the surface color over the gold tile,
     so the mark reads as a cut-out — the same figure/ground the topbar .brand uses. */
  color: var(--bg);
}
.demo-avatar svg { display: block; }
.demo-window-title { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.demo-window-title b { font-family: var(--font-nav); font-weight: 600; font-size: 0.94rem; color: var(--text-primary); }
.demo-window-title small { font-size: 0.76rem; color: var(--text-tertiary); }
.demo-window-badge {
  flex: none; margin-left: auto; display: inline-flex; align-items: center; gap: 6px;
  font-size: 0.72rem; font-weight: 600; color: var(--gold-bright);
  padding: 3px 9px; border: 1px solid var(--gold); border-radius: 999px;
  white-space: nowrap;
}
.demo-window-badge::before {
  content: ""; width: 6px; height: 6px; border-radius: 50%;
  background: var(--gold-bright); flex: none;
}
html.js .demo-window-badge::before { animation: demo-live-pulse 2s ease-in-out infinite; }
@keyframes demo-live-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }
@media (prefers-reduced-motion: reduce) {
  html.js .demo-window-badge::before { animation: none; }
}
.demo-tabs {
  /* justify-content: a generic `nav` rule sets space-between , pin to start */
  display: flex; justify-content: flex-start; gap: 6px; margin-bottom: 14px; overflow-x: auto;
  scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch;
  border-bottom: 1px solid var(--hair); padding-bottom: 2px;
}
.demo-tab {
  scroll-snap-align: start; white-space: nowrap; min-height: 44px;
  display: inline-flex; align-items: center; padding: 8px 16px;
  font-family: 'Fira Code', ui-monospace, monospace; font-size: 0.82rem;
  color: var(--text-secondary); text-decoration: none; border-radius: 10px 10px 0 0;
  border-bottom: 2px solid transparent;
}
.demo-tab:hover { color: var(--ink); }
.demo-tab.is-active { color: var(--gold-bright); border-bottom-color: var(--gold); }
/* Sem JS: painéis empilhados (abas viram âncoras). Com JS: só o ativo. */
.demo-chat:not(.demo-js) .demo-panel + .demo-panel { margin-top: 22px; border-top: 1px solid var(--hair); padding-top: 18px; }
.demo-js .demo-panel { display: none; }
.demo-js .demo-panel.is-active { display: block; }
.demo-query {
  display: flex; gap: 10px; align-items: baseline; margin-bottom: 12px;
}
.demo-role {
  flex: 0 0 auto; font-family: 'Fira Code', ui-monospace, monospace;
  font-size: 0.72rem; color: var(--text-tertiary); text-transform: uppercase; letter-spacing: 0.08em;
}
.demo-query p { font-family: 'Lora', 'Lora Fallback', Georgia, serif; font-style: italic; color: var(--ink-soft); font-size: 0.98rem; }
/* Indicador de busca (substitui o antigo "dump mono" de log no redesign #85):
   passo do stepper entre a pergunta e a resposta, em linguagem humana, NÃO em
   fonte de código. "Procurando no acervo…" → "✓ N acórdãos encontrados". */
.demo-tool {
  display: flex; flex-wrap: wrap; gap: 6px 12px; align-items: center;
  font-size: 0.86rem; color: var(--text-secondary);
  margin-bottom: 14px;
}
.demo-tool-doing { color: var(--text-tertiary); }
.demo-tool-state { display: inline-flex; align-items: center; gap: 5px; }
.demo-tool-state b { color: var(--ink); font-weight: 600; }
.demo-check { color: var(--ok); }
/* O .demo-rag é a 1 menção acessível à arquitetura (autoridade técnica sem jargão). */
.demo-rag {
  font-size: clamp(0.88rem, 0.84rem + 0.2vw, 0.92rem); color: var(--text-secondary); line-height: 1.55;
  border-left: 2px solid var(--rule); padding: 2px 0 2px 12px; margin: 14px 0 4px;
  max-width: 60ch;
}
.demo-prose { color: var(--text-primary); font-size: clamp(0.95rem, 0.92rem + 0.2vw, 1rem); margin-bottom: 12px; }
.demo-prose b { color: var(--ink); }
.demo-cites { list-style: none; display: grid; gap: clamp(12px, 2.5vw, 16px); margin-bottom: 12px; }
/* Card do acórdão: identificação (link) + ementa + botão "Ver no tribunal". */
.demo-card {
  background: color-mix(in srgb, var(--gold) 5%, transparent); border: 1px solid var(--rule);
  border-radius: 12px; padding: clamp(13px, 3vw, 16px) clamp(14px, 3.5vw, 18px);
  transition: border-color .18s ease, background .18s ease;
}
html.js .demo-card:hover { border-color: var(--gold); background: color-mix(in srgb, var(--gold) 8%, transparent); }
.demo-cite {
  display: inline-flex; flex-wrap: wrap; gap: 2px 6px; align-items: center;
  font-size: clamp(0.86rem, 0.8rem + 0.3vw, 0.9rem); line-height: 1.5; font-weight: 600;
  color: var(--gold-bright); text-decoration: none; overflow-wrap: break-word;
}
.demo-cite:hover { color: var(--gold); text-decoration: underline; text-underline-offset: 3px; }
/* Botão explícito que o leigo reconhece: abre o inteiro teor no site do tribunal. */
.demo-card-cta {
  /* LH-08: >=44px touch target (cobre também .demo-card-cta-alt, que acompanha esta classe) */
  display: inline-flex; align-items: center; gap: 6px; min-height: 44px; margin-top: 8px;
  font-family: var(--font-nav); font-weight: 600; font-size: 0.84rem;
  color: var(--bg); background: var(--gold); border-radius: 9px;
  padding: 7px 14px; text-decoration: none; transition: background .18s ease;
}
.demo-card-cta:hover { background: var(--gold-bright); }
.demo-card-cta .arrow, .demo-card-cta span { transition: transform .2s ease; }
.demo-card:hover .demo-card-cta span { transform: translateX(3px); }
/* Quando a fonte traz um inteiro teor distinto, o card mostra dois botões:
   o primário (site do tribunal) e o secundário em contorno (PDF da íntegra). */
.demo-card-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.demo-card-cta-alt {
  color: var(--gold-bright); background: transparent;
  border: 1px solid var(--gold); border-radius: 9px;
}
.demo-card-cta-alt:hover { background: color-mix(in srgb, var(--gold) 10%, transparent); color: var(--gold-bright); }
/* Trecho = botão: contexto (texto antes + <mark> realçado + texto depois) que
   abre o popup com a ementa completa. Sem JS, continua legível como bloco de texto. */
.demo-excerpt {
  display: block; width: 100%; text-align: left; margin-top: 6px;
  font: inherit; font-size: clamp(0.88rem, 0.82rem + 0.3vw, 0.92rem); line-height: 1.55; color: var(--text-secondary);
  background: transparent; border: 0; padding: 2px 0; cursor: pointer;
}
html:not(.js) .demo-excerpt { cursor: default; }
.demo-excerpt-text { display: inline; }
.demo-hl {
  background: color-mix(in srgb, var(--gold) 22%, transparent); color: var(--ink);
  border-radius: 3px; padding: 0 2px;
  box-decoration-break: clone; -webkit-box-decoration-break: clone;
}
.demo-excerpt-more {
  display: inline-flex; align-items: center; gap: 4px; margin-left: 6px;
  font-family: var(--font-nav); font-size: 0.74rem; font-weight: 600;
  color: var(--gold-bright); white-space: nowrap;
}
.demo-excerpt-more::before { content: "\2197"; font-weight: 400; }
html.js .demo-excerpt:hover .demo-excerpt-more { text-decoration: underline; text-underline-offset: 2px; }
.demo-excerpt:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; border-radius: 6px; }
.demo-fulltext { display: none; }
/* Popup (ementa completa, com o trecho realçado) — acessível, fecha em ESC/backdrop. */
.demo-modal[hidden] { display: none; }
.demo-modal {
  position: fixed; inset: 0; z-index: 1000;
  display: flex; align-items: center; justify-content: center; padding: 4vh 16px;
}
.demo-modal-backdrop { position: absolute; inset: 0; background: rgba(0,0,0,0.66); }
.demo-modal-dialog {
  position: relative; width: min(760px, 100%); max-height: 92vh;
  display: flex; flex-direction: column;
  background: var(--bg-2); border: 1px solid var(--rule); border-radius: 14px;
  box-shadow: 0 24px 60px rgba(0,0,0,0.5); padding: 20px clamp(16px, 3vw, 28px);
}
.demo-modal-close {
  position: absolute; top: 10px; right: 10px; width: 44px; height: 44px;
  border-radius: 9px; border: 1px solid var(--hair); background: var(--bg-3);
  color: var(--text-secondary); font-size: 1.05rem; line-height: 1; cursor: pointer;
}
.demo-modal-close:hover { color: var(--gold-bright); border-color: var(--rule); }
.demo-modal-title {
  font-family: 'Fira Code', ui-monospace, monospace; font-size: 0.82rem; font-weight: 600;
  color: var(--gold-bright); margin: 0 44px 0 0; line-height: 1.4;
}
.demo-modal-body {
  margin-top: 12px; padding: 14px 6px 0 0; overflow-y: auto;
  font-size: 0.92rem; line-height: 1.62; color: var(--text-primary);
  /* FE-RESP-01: texto corrido (transcrições da demo) usa break-word — um token
     só parte se SOZINHO não couber na linha; prosa comum nunca quebra no meio. */
  overflow-wrap: break-word; border-top: 1px solid var(--hair);
}
.demo-modal-body mark.demo-hl { background: color-mix(in srgb, var(--gold) 30%, transparent); }
.demo-modal-foot { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--hair); }
body.demo-modal-open { overflow: hidden; }
@media (prefers-reduced-motion: no-preference) {
  .demo-modal-dialog { animation: demoModalIn .18s ease both; }
  @keyframes demoModalIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
}

/* =========================================================
   BETA SUCCESS : modal de confirmação do cadastro (POST /beta ok)
   Mesmos tokens/padrão do .demo-modal; centrado, sóbrio, dourado.
   ========================================================= */
.beta-success[hidden] { display: none; }
.beta-success {
  position: fixed; inset: 0; z-index: 1000;
  display: flex; align-items: center; justify-content: center; padding: 4vh 16px;
}
.beta-success-backdrop { position: absolute; inset: 0; background: rgba(0,0,0,0.66); }
.beta-success-dialog {
  position: relative; width: min(480px, 100%); max-height: 92vh;
  display: flex; flex-direction: column; text-align: center;
  background: var(--bg-2); border: 1px solid var(--rule); border-radius: 14px;
  box-shadow: 0 24px 60px rgba(0,0,0,0.5); padding: clamp(24px, 4vw, 34px) clamp(20px, 4vw, 32px);
}
.beta-success-close {
  position: absolute; top: 10px; right: 10px; width: 44px; height: 44px;
  border-radius: 9px; border: 1px solid var(--hair); background: var(--bg-3);
  color: var(--text-secondary); font-size: 1.05rem; line-height: 1; cursor: pointer;
}
.beta-success-close:hover { color: var(--gold-bright); border-color: var(--rule); }
.beta-success-close:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.beta-success-seal {
  width: 62px; height: 62px; margin: 4px auto 14px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  color: var(--gold-bright); background: color-mix(in srgb, var(--gold) 14%, transparent);
  border: 1px solid var(--rule);
}
.beta-success-title {
  font-family: 'Lora', Georgia, serif; font-size: clamp(1.3rem, 3.4vw, 1.55rem);
  font-weight: 600; color: var(--ink); margin: 0 0 12px; line-height: 1.25;
}
.beta-success-body { margin: 0; }
.beta-success-body p {
  font-size: 0.96rem; line-height: 1.62; color: var(--text-primary); margin: 0 0 12px;
}
.beta-success-body p:last-child { margin-bottom: 0; }
.beta-success-body strong { color: var(--ink); }
/* (M8, 2026-07-25) O bloco .beta-success-set-password foi REMOVIDO junto com a âncora que
   ele estilizava. O modal do /beta não exibe link de definir senha: esse link é uma
   credencial e só viaja no e-mail. Não reintroduzir o estilo sem antes ler a docstring de
   BetaRequestOut em saas/api/interest/main.py. */
.beta-success-foot { margin-top: 22px; }
.beta-success-ok { min-width: 180px; justify-content: center; }
body.beta-success-open { overflow: hidden; }
@media (prefers-reduced-motion: no-preference) {
  .beta-success-dialog { animation: demoModalIn .18s ease both; }
}

.demo-limits { margin-top: 4px; font-size: 0.84rem; }
.demo-limits summary {
  cursor: pointer; min-height: 44px; display: flex; align-items: center;
  color: var(--text-tertiary); font-family: 'Fira Code', ui-monospace, monospace; font-size: 0.76rem;
}
.demo-limits summary:hover { color: var(--text-secondary); }
.demo-limits p { color: var(--text-secondary); padding: 4px 0 8px; }
.demo-foot {
  margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--hair);
  font-size: 0.78rem; color: var(--text-tertiary);
}
.demo-replay {
  position: absolute; top: 12px; right: 12px; width: 44px; height: 44px;
  border-radius: 50%; border: 1px solid var(--hair); background: var(--bg-3);
  color: var(--text-secondary); font-size: 1.05rem; cursor: pointer;
}
.demo-replay:hover { color: var(--gold-bright); border-color: var(--rule); }
@media (max-width: 640px) {
  /* O replay (44px, absolute top-right) sobrepõe o fim da linha de abas em
     telas estreitas , reservar o vão e apertar o padding das abas. */
  .demo-tabs { padding-right: 52px; }
  .demo-tab { padding: 8px 10px; }
}
@media (max-width: 480px) {
  /* ≤480px nem o vão basta (3 abas ≈ 277px > espaço útil): replay desce
     para o pé do card, ao lado do .demo-foot (que reserva o canto). */
  .demo-tabs { padding-right: 0; }
  .demo-replay { top: auto; bottom: 12px; }
  .demo-foot { padding-right: 56px; }
}
.demo-side { display: grid; gap: 18px; align-content: start; }
.demo-side-card {
  display: grid; gap: 18px; min-width: 0;
  padding: clamp(20px, 2.6vw, 28px);
  background: linear-gradient(145deg, color-mix(in srgb, var(--gold) 7%, var(--card)), var(--card) 52%);
  border: 1px solid var(--rule); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
}
.demo-side-eyebrow {
  margin: 0; color: var(--gold-bright);
  font-family: 'Fira Code', ui-monospace, monospace;
  font-size: 0.75rem; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase;
}
.demo-side-list { display: grid; gap: 15px; margin: 0; padding: 0; list-style: none; }
.demo-side-list li {
  display: grid; grid-template-columns: 24px minmax(0, 1fr); gap: 11px; align-items: start;
  color: var(--text-primary); font-size: 0.92rem; line-height: 1.55;
}
.demo-side-list b { color: var(--ink); font-weight: 650; }
.demo-side-check {
  display: inline-grid; place-items: center; width: 24px; height: 24px;
  border: 1px solid var(--rule); border-radius: 50%;
  background: color-mix(in srgb, var(--gold) 10%, transparent);
  color: var(--gold-bright); font-size: 0.78rem; font-weight: 700;
}
.demo-side-card .demo-cta { width: 100%; min-height: 44px; justify-content: center; text-align: center; }
.demo-side-note { margin: 0; padding-inline: 4px; line-height: 1.6; }
@media (max-width: 480px) {
  .demo-side-card { gap: 16px; padding: 18px 16px; }
  .demo-side-list li { grid-template-columns: 22px minmax(0, 1fr); gap: 9px; }
  .demo-side-check { width: 22px; height: 22px; }
}
/* Desktop (grid de 2 colunas): a coluna de apoio é bem mais curta que a lista de
   acórdãos à esquerda. Fica sticky para acompanhar a rolagem em vez de deixar um
   grande vazio à direita. Desliga abaixo de 981px, onde o aside já empilha embaixo. */
@media (min-width: 981px) {
  .demo-side { position: sticky; top: 100px; }
}
.demo-points { list-style: none; counter-reset: dp; display: grid; gap: 16px; }
.demo-points li { counter-increment: dp; padding-left: 44px; position: relative; }
.demo-points li::before {
  content: counter(dp, decimal-leading-zero); position: absolute; left: 0; top: 2px;
  font-family: 'Fira Code', ui-monospace, monospace; font-size: 0.8rem; color: var(--gold);
}
.demo-points h3 { font-size: 1.02rem; margin-bottom: 4px; color: var(--ink); }
.demo-points p { font-size: 0.92rem; color: var(--text-secondary); }
.demo-cta { align-self: start; }

/* Animação (só quando JS adiciona .anim; reduced-motion nunca chega aqui) */
.demo-panel.anim .demo-query,
.demo-panel.anim .demo-tool,
.demo-panel.anim .demo-answer { opacity: 0; transform: translateY(6px); }
.demo-panel.anim.q-in .demo-query,
.demo-panel.anim.tool-loading .demo-tool,
.demo-panel.anim.tool-done .demo-tool,
.demo-panel.anim.ans-in .demo-answer {
  opacity: 1; transform: none; transition: opacity .3s ease, transform .3s ease;
}
.demo-panel.anim .demo-tool-state { visibility: hidden; }
.demo-panel.anim.tool-done .demo-tool-state { visibility: visible; }
/* Reticências animadas no "Procurando no acervo" enquanto o passo de busca roda. */
.demo-panel.anim.tool-loading .demo-tool-doing::after {
  content: '·'; display: inline-block; margin-left: 1px; color: var(--gold);
  animation: demo-blink 0.9s steps(3, end) infinite;
}
@keyframes demo-blink {
  0% { content: '·'; } 33% { content: '··'; } 66% { content: '···'; }
}
.demo-panel.anim .demo-cites li { opacity: 0; transform: translateY(8px); }
.demo-panel.anim .demo-cites li.cite-in {
  opacity: 1; transform: none; transition: opacity .32s ease, transform .32s ease;
}
/* Typewriter caret on the question while JS types it (JS-only via .typing). */
.demo-panel.typing .demo-query p::after {
  content: ""; display: inline-block; width: 2px; height: 1.05em;
  margin-left: 2px; vertical-align: -0.16em; background: var(--gold);
  animation: demo-caret 0.85s steps(2, start) infinite;
}
@keyframes demo-caret { 50% { opacity: 0; } }
/* WS-4: gold caret trailing the answer prose while it streams word-by-word (JS adds
   .streaming on .demo-prose during the stream, removes it when the sentence lands). */
.demo-prose.streaming::after {
  content: ""; display: inline-block; width: 2px; height: 1.05em;
  margin-left: 2px; vertical-align: -0.16em; background: var(--gold);
  animation: demo-caret 0.85s steps(2, start) infinite;
}
/* Keep the question box from collapsing to zero height while it's empty mid-type. */
.demo-panel.anim .demo-query p { min-height: 1.5em; }
/* Keep the prose from collapsing while it is mid-stream (empty innerHTML). */
.demo-panel.anim .demo-prose { min-height: 1.5em; }
@media (prefers-reduced-motion: reduce) {
  .demo-replay { display: none; }
  .demo-panel.typing .demo-query p::after { display: none; }
  .demo-prose.streaming::after { display: none; }
  .demo-panel.anim .demo-query, .demo-panel.anim .demo-tool,
  .demo-panel.anim .demo-answer, .demo-panel.anim .demo-cites li {
    opacity: 1 !important; transform: none !important;
  }
}

/* ---- §02 Cobertura: grid por família ---- */
.fam-grid { display: grid; gap: 14px; margin-top: var(--space-10); grid-template-columns: 1fr; }
@media (min-width: 481px) { .fam-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 760px) { .fam-grid { grid-template-columns: repeat(4, 1fr); } }
.fam-card {
  background: var(--card); border: 1px solid var(--hair); border-radius: 14px;
  padding: 18px 16px; transition: transform .18s ease, border-color .18s ease;
}
html.js .fam-card:hover { transform: translateY(-3px); border-color: var(--rule); }
.fam-card h3 { font-size: 0.86rem; font-weight: 600; color: var(--text-secondary); margin-bottom: 8px; }
.fam-num {
  font-family: 'Lora', 'Lora Fallback', Georgia, serif; font-variant-numeric: tabular-nums;
  /* sem break-word: número de display jamais parte dígito (guarda anti-quebra) */
  font-size: clamp(1.4rem, 3vw, 1.8rem); color: var(--ink);
}
.fam-sub { font-size: 0.76rem; color: var(--text-tertiary); margin-top: 6px; font-family: 'Fira Code', ui-monospace, monospace; }
.fam-rule { margin-top: 22px; font-size: 0.92rem; color: var(--text-secondary); }
.sec-cta { margin-top: 24px; }
/* "Saiba mais" aside: muted microcopy under a section CTA pointing to a concept
   page. The concept links can be long, so they wrap by whole words here (the
   global .inline-link uses nowrap, fine for short links but it would overflow
   narrow screens with these longer labels). */
.sec-aside { margin-top: 12px; font-size: 0.92rem; color: var(--text-secondary); }
/* Long inline-link phrases must wrap, not overflow, on narrow screens. The base
   .inline-link uses nowrap so a lone "→" never drops to its own line; re-enable
   wrapping wherever the link text is a full sentence. */
.sec-aside .inline-link,
.plat-note .inline-link,
.plat-prereq .inline-link,
.plat-golden .inline-link,
.stats-updated .inline-link, /* /cobertura 320px: "De onde vêm os dados e o que está no acervo →" estourava a página em 41px (FE-RESP-01 sweep) */
.intro .inline-link, /* /integracoes 320px sob o espaçamento de texto da WCAG 1.4.12: "Conheça os tipos de busca do IAJUS" estourava 92px */
.work-card .inline-link, /* /quem-construiu, mesma condição, 83px: o link do repositório da UnB vive num <p> nu dentro de <article class="work-card">.
                            ⚠️ A 1ª versão desta linha dizia `.prose .inline-link` e era CÓDIGO MORTO: quem-construiu.html não usa `.prose` em lado nenhum
                            (grep devolve zero). O A/B mediu a rota DEPOIS do "conserto" e deu 393/310 — o MESMO número de antes. Escrever o seletor que
                            explicaria o defeito não é o mesmo que escrever o seletor que o ALCANÇA. */
.legal-prose .inline-link { white-space: normal; }

/* ---- Tipos de busca na home: 4 cards simples, linguagem do leigo ----
   Mirrors the .integ-step card aesthetic (palette tokens, gold accents).
   hyphens:none + overflow-wrap:break-word keep prose readable on 320px
   without ever splitting a word letter-by-letter. 1 col on phones,
   2x2 on tablets, 4-up on wide desktop (same rhythm as the .acervo stats). */
.busca-tipos {
  list-style: none; display: grid; gap: 16px; grid-template-columns: 1fr;
  margin-top: var(--space-10);
}
@media (min-width: 760px) { .busca-tipos { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1100px) { .busca-tipos { grid-template-columns: repeat(4, 1fr); } }
.busca-tipo {
  position: relative; background: var(--card); border: 1px solid var(--hair);
  border-radius: 16px; padding: 22px 20px 20px;
  hyphens: none; overflow-wrap: break-word;
}
.busca-tipo-tag {
  display: inline-block; margin-bottom: 12px;
  font-family: 'Fira Code', ui-monospace, monospace; font-size: 0.72rem;
  /* ⛔ Era `color: var(--gold)`. O token declara "AA 5.9:1 sobre navy" e a
     alegacao e verdadeira -- sobre navy SOLIDO. Mas 2 destas 6 tags vivem
     dentro de `.busca-eixo-estrutura`, que empilha um tinte de creme a 8% por
     cima do navy. O fundo que o olho recebe ali e #353537, e nenhum CSS deste
     repo contem esse valor: ele so existe composto em runtime. Medido com axe
     a 2026-08-20: 4.20:1 no escuro e 4.43:1 no claro, serious.
     Conformidade e propriedade do PAR cor+fundo, nunca da cor sozinha.
     --gold-bright cumpre nos QUATRO casos (dentro/fora x escuro/claro), com
     4.87:1 no mais apertado. O fundo do chip fica em --gold: e decoracao, nao
     texto. A mesma declaracao existe em `.integ-step .integ-tag` e NAO se
     mexe -- essa foi medida e passa, porque nao vive sob o tinte. */
  color: var(--gold-bright); background: color-mix(in srgb, var(--gold) 7%, transparent);
  border: 1px solid var(--rule); border-radius: 8px; padding: 4px 9px;
  white-space: nowrap;
}
.busca-tipo h3 { font-size: 1.06rem; color: var(--ink); margin-bottom: 7px; }
.busca-tipo p { font-size: 0.92rem; color: var(--text-secondary); line-height: 1.55; }
.js .busca-tipo { transition: transform .18s ease, border-color .18s ease; }
.js .busca-tipo:hover { transform: translateY(-3px); border-color: var(--rule); }

/* Dois eixos de busca (operador #65 2026-07-13): a seção deixa de ser 4 caixas
   iguais e vira dois grupos rotulados, "pelo texto" e "pela estrutura". O eixo
   de estrutura ganha a faixa de diferencial (borda dourada esquerda, mesmo
   padrão do .sov-block) porque a busca pela árvore do CNJ e pelas citações é o
   que quase nenhum tribunal oferece. Tokens do tema, AA em dark e light; ritmo
   de grid 760/1100 herdado de .busca-tipos, sem breakpoint novo. */
.busca-eixo { margin-top: var(--space-10); }
.busca-eixo-titulo {
  font-family: 'Fira Code', ui-monospace, monospace; font-size: 0.78rem;
  letter-spacing: 0.04em; text-transform: uppercase; color: var(--gold-bright);
  margin-bottom: 14px;
}
.busca-eixo .busca-tipos { margin-top: 0; }
.busca-eixo-estrutura {
  padding: clamp(18px, 3vw, 26px); margin-top: 28px;
  border: 1px solid var(--hair); border-left: 3px solid var(--gold);
  border-radius: var(--radius-lg);
  background: color-mix(in srgb, var(--gold) 5%, var(--card));
}
.busca-eixo-nota {
  font-size: 0.92rem; color: var(--text-secondary); line-height: 1.55;
  margin-bottom: 16px; max-width: 62ch;
}
/* As duas formas estruturais são 1 col no phone, 2-up a partir de 760 (não 4-up:
   são só duas e ganham respiro). */
.busca-tipos-estrutura { grid-template-columns: 1fr; }
@media (min-width: 760px) { .busca-tipos-estrutura { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1100px) { .busca-tipos-estrutura { grid-template-columns: repeat(2, 1fr); } }
.busca-tipo h4 { font-size: 1.06rem; color: var(--ink); margin-bottom: 7px; }
/* híbrida = padrão: selo discreto no canto, borda dourada sutil no card. */
.busca-tipo-padrao { border-color: color-mix(in srgb, var(--gold) 40%, var(--hair)); }
.busca-tipo-selo {
  position: absolute; top: 14px; right: 14px;
  font-family: 'Fira Code', ui-monospace, monospace; font-size: 0.64rem;
  letter-spacing: 0.03em; text-transform: uppercase; color: var(--gold-bright);
  background: color-mix(in srgb, var(--gold) 12%, transparent);
  border: 1px solid var(--rule); border-radius: 6px; padding: 2px 7px;
}

/* ---- §03 Confiabilidade: proof-cards + arquitetura ---- */
.proof-grid { display: grid; gap: 16px; grid-template-columns: 1fr; }
/* Escala de breakpoint unificada 560/760/980/1240: o gate 769 excluía o próprio
   768 (iPad retrato), deixando 'Quatro jeitos de procurar' em 2 colunas enquanto
   'Confiabilidade' irmã seguia 1 coluna. 760 alinha ao ritmo de grid das dobras. */
@media (min-width: 760px) { .proof-grid { grid-template-columns: repeat(2, 1fr); } }
.proof-card {
  background: var(--card); border: 1px solid var(--hair); border-radius: var(--radius-lg);
  padding: clamp(16px, 2.5vw, 24px); display: flex; flex-direction: column; gap: 10px;
  min-width: 0;
}
.proof-card h3 { font-size: 1.08rem; color: var(--ink); }
.proof-card p { font-size: 0.93rem; color: var(--text-primary); }
/* Frase-resumo em linguagem simples que fecha cada proof-card (F-A 2026-07-07):
   substituiu os antigos blocos <pre class="proof-term"> de código, que expunham
   jargão de banco/engenharia ao advogado. Empurrada para a base do card. */
.proof-plain {
  margin-top: auto; padding-top: 12px; border-top: 1px solid var(--hair);
  font-size: 0.9rem; font-weight: 500; color: var(--gold-bright);
}

/* SOBERANIA DE DADOS (operador 2026-07-08): faixa dentro de "Por que confiar".
   Faixa distinta dos proof-cards (borda dourada esquerda + fundo sutil) para
   marcar o diferencial de jurisdição BR sem competir com a grade de prova.
   Mobile-first: 1 coluna, sobe para 2 a partir de 760 (mesmo ritmo do proof-grid).
   Tokens do tema; AA em dark e light (herda --ink/--text-primary/--gold-bright). */
.sov-block {
  margin-top: 28px; padding: clamp(18px, 3vw, 28px);
  border: 1px solid var(--hair); border-left: 3px solid var(--gold);
  border-radius: var(--radius-lg);
  background: color-mix(in srgb, var(--gold) 5%, var(--card));
}
.sov-head { display: flex; align-items: center; gap: 12px; margin-bottom: 6px; }
.sov-kicker {
  flex: 0 0 auto; display: inline-flex; color: var(--gold-bright);
}
.sov-title { font-size: clamp(1.12rem, 2.4vw, 1.28rem); color: var(--ink); line-height: 1.2; }
.sov-grid { display: grid; gap: 16px; grid-template-columns: 1fr; margin-top: 16px; }
@media (min-width: 760px) { .sov-grid { grid-template-columns: repeat(2, 1fr); } }
.sov-card {
  background: var(--card); border: 1px solid var(--hair); border-radius: var(--radius-lg);
  padding: clamp(14px, 2.2vw, 20px); display: flex; flex-direction: column; gap: 8px;
  min-width: 0;
}
/* h3 E h4 no MESMO seletor de propósito: o componente .sov-card é reutilizado sob
   pais de nível diferente — sob o <h2> das "Plataformas" os cartões são h3, sob o
   <h3 class="sov-title"> da soberania são h4. O nível segue o PAI (senão a
   hierarquia salta, WCAG 1.3.1); os pixels seguem esta regra e não mexem. */
.sov-card h3, .sov-card h4 { font-size: 1.02rem; color: var(--ink); line-height: 1.25; }
.sov-card p { font-size: 0.93rem; color: var(--text-primary); line-height: 1.6; }
.arch-block { margin-top: 34px; }
.arch-intro { font-size: 1rem; color: var(--text-primary); max-width: 70ch; margin-bottom: 18px; }
.arch-list { list-style: none; display: grid; gap: 16px; grid-template-columns: 1fr; }
@media (min-width: 760px) { .arch-list { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1100px) { .arch-list { grid-template-columns: repeat(4, 1fr); } }
.arch-list li { border-left: 2px solid var(--rule); padding-left: 14px; }
.arch-list h3 { font-size: 0.98rem; color: var(--gold-bright); margin-bottom: 4px; }
.arch-list p { font-size: 0.88rem; color: var(--text-secondary); }

/* Pontos de valor do teaser de escritórios (F-A / S1 #3, 2026-07-07): a seção
   antes tinha só título + link; agora ganha 3 marcadores curtos. Sem cota/limite. */
.escr-points {
  list-style: none; margin: 18px 0 0; padding: 0;
  display: grid; gap: 10px; max-width: 62ch;
}
.escr-points li {
  position: relative; padding-left: 22px;
  font-size: 0.98rem; color: var(--text-primary); line-height: 1.5;
}
.escr-points li::before {
  content: ""; position: absolute; left: 0; top: 0.55em;
  width: 7px; height: 7px; border-radius: var(--radius-pill);
  background: var(--gold);
}

/* ---- §04 Acervo além: linha de qualificadas ---- */
.qual-line { margin-top: 22px; font-size: 0.98rem; color: var(--text-primary); max-width: 66ch; }

/* Fileira compacta de plataformas logo abaixo da .qual-line: coins CLAROS com os
   assets oficiais, e a fileira inteira e UM link SPA -> /integracoes. Distinta do
   .logo-strip de /integracoes (coins menores ~34px, icone ~20px, fundo claro fixo).
   O fundo e branco FIXO (nao tokenizado de proposito): os logos oficiais escuros
   (ChatGPT preto, Grok #050505) sumiriam sobre o navy do hero; e color-scheme:light
   forca o chatgpt.svg -- que e adaptativo via @media(prefers-color-scheme) -- ao seu
   traco PRETO mesmo quando o sistema operacional esta em dark mode. */
.plat-strip {
  display: inline-flex; flex-wrap: wrap; align-items: center; gap: 10px;
  margin-top: 20px; text-decoration: none; max-width: 100%;
}
.plat-strip-chip {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; flex: 0 0 auto; border-radius: 50%;
  background: #fff; color-scheme: light;
  border: 1px solid color-mix(in srgb, var(--gold) 30%, rgba(0, 0, 0, 0.14));
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.22);
  transition: border-color .18s ease, box-shadow .18s ease, transform .18s ease;
}
.plat-strip-chip img { width: 20px; height: 20px; display: block; color-scheme: light; }
.plat-strip:hover .plat-strip-chip,
.plat-strip:focus-visible .plat-strip-chip {
  border-color: var(--gold); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.30); transform: translateY(-1px);
}
.plat-strip:focus-visible { outline: 3px solid var(--gold-bright); outline-offset: 4px; border-radius: 18px; }
.plat-strip-more {
  display: inline-flex; align-items: center; gap: 6px; margin-inline-start: 6px;
  font-size: .84rem; font-weight: 600; color: var(--gold-bright); white-space: nowrap;
}
.plat-strip:hover .plat-strip-more { text-decoration: underline; text-underline-offset: 3px; }
@media (max-width: 430px) {
  .plat-strip { gap: 8px; }
  .plat-strip-chip { width: 30px; height: 30px; }
  .plat-strip-chip img { width: 18px; height: 18px; }
  .plat-strip-more { width: 100%; margin-inline-start: 0; margin-top: 4px; }
}
@media (prefers-reduced-motion: reduce) {
  .plat-strip-chip { transition: none; }
  .plat-strip:hover .plat-strip-chip,
  .plat-strip:focus-visible .plat-strip-chip { transform: none; }
}

/* ---- §05 Plataformas (home) ---- */
.plat-home { display: grid; gap: 22px; }
.plat-home > * { min-width: 0; }
@media (min-width: 861px) { .plat-home { grid-template-columns: 1fr minmax(0, 480px); align-items: start; } }
.plat-chips { list-style: none; display: flex; flex-wrap: wrap; gap: 10px; }
.plat-chip {
  display: inline-flex; align-items: center; min-height: 44px; padding: 8px 16px;
  border: 1px solid var(--hair); border-radius: 999px; text-decoration: none;
  color: var(--text-primary); font-size: 0.9rem; background: var(--card);
  /* "Claude Desktop · claude.ai": the middle dot is not a break opportunity, so
     allow the label to wrap rather than push the chip past a 320px viewport. */
  overflow-wrap: anywhere; word-break: break-word; text-align: center;
}
.plat-chip:hover { border-color: var(--gold); color: var(--gold-bright); }
.plat-code-card { background: var(--bg-2); border: 1px solid var(--hair); border-radius: 14px; padding: 16px; min-width: 0; overflow-x: auto; }
.plat-code-label { font-size: 0.8rem; color: var(--text-tertiary); margin-bottom: 10px; font-family: 'Fira Code', ui-monospace, monospace; }
.plat-code-note { font-size: 0.82rem; color: var(--text-secondary); margin-top: 10px; }

/* ---- §06 Credibilidade ---- */
.cred-body { max-width: 75ch; display: grid; gap: 14px; }
.cred-body p { font-size: 1.02rem; color: var(--text-primary); line-height: 1.7; }
.cred-cards { list-style: none; display: grid; gap: 14px; margin-top: var(--space-10); grid-template-columns: 1fr; }
@media (min-width: 641px) { .cred-cards { grid-template-columns: repeat(3, 1fr); } }
.cred-cards li {
  background: var(--card); border: 1px solid var(--hair); border-radius: 14px; padding: 16px;
}
.cred-cards b {
  display: block; font-family: 'Fira Code', ui-monospace, monospace;
  font-size: clamp(1.1rem, 2.4vw, 1.4rem); color: var(--gold-bright); margin-bottom: 6px;
  overflow-wrap: break-word;
}
.cred-cards span { font-size: 0.84rem; color: var(--text-secondary); }

/* ---- §07 FAQ ---- */
.faq-list { display: grid; gap: 10px; max-width: 860px; }
.faq-item {
  background: var(--card); border: 1px solid var(--hair); border-radius: 12px;
  padding: 0 18px;
}
.faq-item summary {
  cursor: pointer; min-height: 52px; display: flex; align-items: center; gap: 12px;
  font-weight: 600; color: var(--ink); font-size: 0.98rem; padding: 12px 0;
  list-style: none;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::before {
  content: '+'; flex: 0 0 auto; color: var(--gold); font-family: 'Fira Code', ui-monospace, monospace;
  font-size: 1.1rem; width: 18px;
}
.faq-item[open] summary::before { content: '−'; }
.faq-item p { padding: 0 0 16px 30px; font-size: 0.93rem; color: var(--text-secondary); max-width: 70ch; }

/* ---- §07b Preços (/precos, PROP-LAND-PRECOS-01, iajus#108) ----
   Bloco ÚNICO (P-06/17 + AGENTS.md "nunca CSS inline, nunca ficheiro próprio"):
   .pricing é a grade, .price-card cada plano, .price-card--destaque o cartão
   realçado. O critério visual da tela (landing.md#land-precos) é EXPLÍCITO:
   destaque NUNCA só por cor — aqui é borda dourada + sombra elevada + o único
   botão .btn-primary da grade; um mutante que apague border/box-shadow abaixo
   mantendo só a cor tem de reprovar o teste de M3 (ver RELATORIO da lane). */
.pricing { display: grid; gap: var(--space-6); grid-template-columns: 1fr; }
@media (min-width: 760px) { .pricing { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1081px) { .pricing { grid-template-columns: repeat(4, 1fr); } }
.price-card {
  display: flex; flex-direction: column; gap: var(--space-3);
  background: var(--card); border: 1px solid var(--hair); border-radius: var(--radius-lg);
  padding: var(--space-6);
}
.price-card--destaque {
  /* 390 (coluna única): destaque primeiro, por ordem visual — DOM não muda,
     então a leitura por teclado/leitor de tela segue a ordem dos cartões. */
  order: -1;
  border: 1px solid var(--gold);
  box-shadow: var(--shadow-raised);
}
@media (min-width: 760px) {
  /* 2×2/4 colunas: a grade já tem largura para mostrar a ordem natural dos
     planos (Beta · Plus · Pro · Escritórios); só a coluna única de 390 precisa
     do destaque primeiro. */
  .price-card--destaque { order: 0; }
}
.price-card-name {
  margin: 0; font-family: var(--font-display); color: var(--ink);
  font-size: var(--step-h3);
}
.price-card-price { margin: 0; font-size: 1.05rem; font-weight: 600; color: var(--gold-bright); }
.price-card-label {
  margin: var(--space-2) 0 0; font-size: 0.78rem; font-weight: 600; color: var(--text-tertiary);
  text-transform: uppercase; letter-spacing: var(--track-label);
}
.price-card-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.price-card-list li {
  position: relative; padding-left: 22px; font-size: 0.92rem; line-height: 1.55;
  color: var(--text-secondary);
}
.price-card-list--sim li::before {
  content: '✓'; position: absolute; left: 0; top: 0; color: var(--gold); font-weight: 700;
}
.price-card-list--nao li {
  color: var(--text-tertiary);
}
.price-card-list--nao li::before {
  content: '–'; position: absolute; left: 0; top: 0; color: var(--text-tertiary); font-weight: 700;
}
.price-card-cta { margin: var(--space-2) 0 0; }
.price-card-cta .btn { width: 100%; justify-content: center; }
/* Selo neutro (kit) reaproveitado aqui para um facto verificável — "Por convite" —
   nunca para um superlativo de marketing (test_landing_no_marketing_superlatives). */
.selo {
  display: inline-flex; align-items: center; padding: 4px 12px; border-radius: var(--radius-pill);
  font-size: 0.76rem; font-weight: 700; text-transform: uppercase; letter-spacing: var(--track-label);
  width: fit-content;
}
.selo--neutral { background: var(--bg-3); color: var(--text-secondary); border: 1px solid var(--hair); }

/* ---- Footer badge ---- */
.foot-badge {
  display: inline-block; padding: 2px 8px; margin-right: 8px; border-radius: 6px;
  border: 1px solid var(--rule); color: var(--gold); font-family: 'Fira Code', ui-monospace, monospace;
  font-size: 0.68rem; letter-spacing: 0.06em;
}

/* ---- /integracoes: prereq + accordion/tablist + códigos + copiar ---- */
.plat-prereq { margin-top: 18px; font-size: 0.95rem; color: var(--text-primary); max-width: 78ch; }
.plat-tabs-bar {
  display: flex; flex-wrap: wrap; gap: 6px; border-bottom: 1px solid var(--hair);
  margin-bottom: 18px; position: sticky; top: 72px; z-index: 5;
  background: color-mix(in srgb, var(--bg) 92%, transparent); backdrop-filter: blur(8px);
  padding: 8px 0;
}
.plat-tab-btn {
  min-height: 44px; padding: 8px 16px; border: 0; background: transparent; cursor: pointer;
  font-family: 'Fira Code', ui-monospace, monospace; font-size: 0.8rem;
  color: var(--text-secondary); border-bottom: 2px solid transparent;
}
.plat-tab-btn:hover { color: var(--ink); }
.plat-tab-btn.is-active { color: var(--gold-bright); border-bottom-color: var(--gold); }
.plat-list { display: grid; gap: 12px; }
/* min-width:0 , sem isso o min-content dos <pre> propaga e alarga o grid item
   inteiro além do viewport (overflow-x da página) em vez de rolar dentro do bloco */
.plat-list > .plat-acc { min-width: 0; }
.plat-acc { background: var(--card); border: 1px solid var(--hair); border-radius: 14px; }
.plat-acc summary {
  cursor: pointer; min-height: 56px; display: flex; align-items: center; gap: 12px;
  flex-wrap: wrap; padding: 12px 18px; list-style: none;
}
.plat-acc summary::-webkit-details-marker { display: none; }
/* Affordance de expansão (device do FAQ '+' → '−'): fechado, cada linha parecia
   item estático de lista. O modo tablist >=861px esconde os summaries (custo zero
   no desktop). */
.plat-acc summary::after {
  content: '+'; margin-left: 10px; flex: none; color: var(--gold);
  font-family: 'Fira Code', ui-monospace, monospace; font-size: 1.05rem; line-height: 1;
}
.plat-acc[open] summary::after { content: '−'; }
.plat-acc summary:hover { background: var(--bg-3); border-radius: 14px 14px 0 0; }
.plat-name { font-weight: 600; color: var(--ink); font-size: 1rem; }
.plat-badge {
  margin-left: auto; font-family: 'Fira Code', ui-monospace, monospace; font-size: 0.7rem;
  padding: 4px 10px; border-radius: 999px; border: 1px solid var(--hair); color: var(--text-secondary);
}
/* FL-9: tokenizado sobre --ok (o rgba fixo era o --ok escuro hardcoded; assim a
   borda acompanha o tema, como o texto já fazia). */
.plat-ok { border-color: color-mix(in srgb, var(--ok) 40%, transparent); color: var(--ok); }
/* SVG checkmark (replaced the ✅ emoji: color-consistent with the badge text in both
   themes, same stroke language as the product icons; emoji rendered platform-dependent
   and off-brand). currentColor inherits the theme-corrected green above. */
.plat-ok-ico { vertical-align: -1px; margin-right: 1px; }
/* a11y: on the light cream badge bg (#f2f0eb) the light --ok (#15803d) lands at 4.4:1
   on this 11.2px mono text, just under WCAG AA 4.5:1 (axe serious). Deepen the green
   ONLY on the light plat-ok badge to 5.3:1 (dark theme's --ok #2bc48a is 7.2:1, fine).
   Scoped to the badge so the global --ok token is untouched. */
[data-theme='light'] .plat-ok { color: #127233; }
.plat-mid { border-color: var(--rule); color: var(--gold-bright); }
/* min-width:0 / overflow-x:hidden na cadeia: sem isso o min-content dos blocos
   <pre> (white-space:pre) propaga e estoura a página no 320px (a barra horizontal
   só sai quando o ancestral pode encolher e o scroll do <pre> assume). */
.plat-panel { padding: 4px 18px 18px; min-width: 0; overflow-x: hidden; }
.plat-steps { margin-left: 20px; display: grid; gap: 10px; min-width: 0;
  font-size: 0.93rem; color: var(--text-primary); max-width: 78ch; }
.plat-steps li { min-width: 0; }
/* <code> INLINE (não os blocos <pre>) pode quebrar nas fronteiras naturais em
   telas estreitas, sem partir a palavra no meio , evita estouro horizontal do
   passo a passo no 320px. Os blocos <pre class="plat-code"> seguem com scroll. */
.plat-steps li code, .plat-note code { overflow-wrap: break-word; }
/* Teto de medida (60-80ch): sem cap, a prosa de instalação corre ~140-160ch no
   desktop no modo tablist/accordion. Os <pre class="plat-code"> seguem full-width. */
.plat-note { font-size: 0.9rem; color: var(--text-secondary); margin-top: 10px; max-width: 78ch; }
.plat-note strong { color: var(--text-primary); }
.plat-sec { color: var(--gold-bright); }
.plat-more { margin-top: 10px; }
.plat-more summary {
  cursor: pointer; min-height: 44px; display: flex; align-items: center;
  font-size: 0.84rem; color: var(--text-tertiary);
}
.plat-code {
  position: relative; background: var(--bg-3); border: 1px solid var(--hair);
  border-radius: 10px; padding: 13px 15px; margin-top: 10px;
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  /* nunca crescer além do container: o snippet rola DENTRO da própria caixa */
  max-width: 100%; min-width: 0;
}
.plat-code code {
  font-family: 'Fira Code', ui-monospace, monospace; font-size: clamp(0.78rem, 1.5vw, 0.86rem);
  color: var(--ink-soft); white-space: pre; line-height: 1.65;
}
.plat-copy {
  position: absolute; top: 8px; right: 8px; min-width: 44px; min-height: 32px;
  padding: 4px 10px; border-radius: 8px; border: 1px solid var(--hair);
  background: var(--bg-2); color: var(--text-secondary); cursor: pointer;
  font-family: 'Fira Code', ui-monospace, monospace; font-size: 0.7rem;
}
/* FL-5: no toque, o botão sobe a >=44px (WCAG 2.5.5 / HIG) e o bloco de código
   ganha respiro no topo para o código nunca ficar sob o botão (8px + 44px). */
@media (pointer: coarse) {
  .plat-copy { min-height: 44px; }
  .plat-code { padding-top: 56px; }
}
.plat-copy:hover { color: var(--gold-bright); border-color: var(--rule); }
.plat-copy.ok { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 40%, transparent); }
html:not(.js) .plat-copy { display: none; }
.plat-golden {
  margin-top: 26px; padding: 16px 18px; border-left: 3px solid var(--gold);
  background: color-mix(in srgb, var(--gold) 6%, transparent); border-radius: 0 12px 12px 0;
  font-size: 0.93rem; color: var(--text-primary);
}
.plat-avail { display: grid; gap: 22px; grid-template-columns: 1fr; }
@media (min-width: 769px) { .plat-avail { grid-template-columns: 1fr 1fr; } }
.avail-col h3 { font-size: 0.98rem; color: var(--ink); margin-bottom: 10px; }
.avail-list { list-style: none; display: grid; gap: 8px; font-size: 0.88rem; color: var(--text-secondary); }
.avail-list code { color: var(--gold-bright); font-family: 'Fira Code', ui-monospace, monospace; font-size: 0.82rem; }
/* F7: rótulo PT-BR é o título do item; o nome técnico da tool vira detalhe secundário menor ao lado. */
.avail-list .avail-label { color: var(--text-primary); }
.avail-list code.avail-tool { margin-left: 6px; font-size: 0.72rem; color: var(--gold); }
.avail-flag {
  display: inline-block; margin-left: 4px;
  font-size: 0.74rem; font-style: italic; color: var(--text-secondary);
}

/* Tablist mode (≥861px com JS): esconder summaries, mostrar só painel atual */
.plat-tabs-mode .plat-acc { border: 0; background: transparent; }
.plat-tabs-mode .plat-acc summary { display: none; }
.plat-tabs-mode .plat-acc:not([open]) { display: none; }

/* ---- Autor: monograma com asterisco ---- */
.author-ast { color: var(--gold); }

/* =========================================================
   DINAMISMO (task #85) : motion layer added on top of the static
   document. Every effect here is CSS-first and dies under the global
   prefers-reduced-motion block above (animations/transitions zeroed),
   plus the explicit fallbacks at the end of this block. JS only adds
   the .in / .lit hooks via IntersectionObserver , never required for
   readability.
   ========================================================= */

/* ---- Hero counter card: gold sweep + growth sparkline ---- */
.counter-sweep {
  position: absolute; inset: 0; pointer-events: none; border-radius: inherit;
  background: linear-gradient(115deg, transparent 30%, color-mix(in srgb, var(--gold-bright) 10%, transparent) 48%, transparent 66%);
  background-size: 250% 100%; background-position: 180% 0;
}
.js .counter-card.in .counter-sweep { animation: counter-sweep 5.5s ease-in-out 0.6s infinite; }
@keyframes counter-sweep { 0% { background-position: 180% 0; } 55%, 100% { background-position: -80% 0; } }

.counter-spark {
  display: flex; align-items: flex-end; gap: 4px; height: 38px;
  margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--hair);
}
.counter-spark span {
  flex: 1 1 0; min-width: 0; height: var(--h); border-radius: 3px 3px 0 0;
  background: linear-gradient(180deg, var(--gold-bright), color-mix(in srgb, var(--gold-soft) 35%, transparent));
  transform-origin: bottom; transform: scaleY(0.06); opacity: 0.5;
}
.js .counter-card.in .counter-spark span {
  animation: spark-rise 0.6s cubic-bezier(.22,.61,.36,1) forwards;
}
.counter-card.in .counter-spark span:nth-child(1)  { animation-delay: .50s; }
.counter-card.in .counter-spark span:nth-child(2)  { animation-delay: .56s; }
.counter-card.in .counter-spark span:nth-child(3)  { animation-delay: .62s; }
.counter-card.in .counter-spark span:nth-child(4)  { animation-delay: .68s; }
.counter-card.in .counter-spark span:nth-child(5)  { animation-delay: .74s; }
.counter-card.in .counter-spark span:nth-child(6)  { animation-delay: .80s; }
.counter-card.in .counter-spark span:nth-child(7)  { animation-delay: .86s; }
.counter-card.in .counter-spark span:nth-child(8)  { animation-delay: .92s; }
.counter-card.in .counter-spark span:nth-child(9)  { animation-delay: .98s; }
.counter-card.in .counter-spark span:nth-child(10) { animation-delay: 1.04s; }
.counter-card.in .counter-spark span:nth-child(11) { animation-delay: 1.10s; }
.counter-card.in .counter-spark span:nth-child(12) { animation-delay: 1.16s; }
.counter-card.in .counter-spark span:last-child { opacity: 1; }
@keyframes spark-rise { to { transform: scaleY(1); opacity: 0.85; } }

/* ---- Hero atmosphere: a slow vertical scan sweeping the aurora ---- */
.js .aurora::after { animation: aurora-drift 22s ease-in-out infinite alternate; }
@keyframes aurora-drift {
  from { transform: translate3d(0,0,0) scale(1); opacity: 0.30; }
  to   { transform: translate3d(-26px,-30px,0) scale(1.08); opacity: 0.40; }
}

/* ---- Scroll-reveal variants: opt-in directional entrances ---- */
.js .reveal[data-rv="left"]  { transform: translateX(-26px); }
.js .reveal[data-rv="right"] { transform: translateX(26px); }
.js .reveal[data-rv="scale"] { transform: scale(0.965); }
.js .reveal[data-rv].in { transform: none; }

/* ---- Card micro-interactions: shared lift + gold edge on hover ---- */
.js .proof-card, .js .legis-card, .js .work-card, .js .plat-chip,
.js .integ-step, .js .demo-points li {
  transition: transform .2s cubic-bezier(.22,.61,.36,1), border-color .2s ease, box-shadow .2s ease;
}
.js .proof-card:hover, .js .legis-card:hover, .js .work-card:hover {
  transform: translateY(-4px); border-color: var(--rule);
  box-shadow: 0 26px 50px -34px rgba(0,0,0,0.7);
}

/* =========================================================
   INTEGRAÇÕES VISUAIS : "como conectar em 3 passos" , linguagem
   acessível para advogado não-técnico (cards + ícones + passo-a-passo).
   ========================================================= */
.integ-how { margin-top: 8px; }
.integ-steps {
  list-style: none; display: grid; gap: 16px; counter-reset: ist;
  grid-template-columns: 1fr;
}
@media (min-width: 760px) { .integ-steps { grid-template-columns: repeat(3, 1fr); } }
.integ-step {
  counter-increment: ist; position: relative; overflow: hidden;
  background: var(--card); border: 1px solid var(--hair); border-radius: 16px;
  padding: 22px 20px 20px;
}
.integ-step::before {
  content: counter(ist, decimal-leading-zero);
  position: absolute; top: 14px; right: 16px;
  font-family: 'Fira Code', ui-monospace, monospace; font-size: 0.78rem;
  color: var(--gold); opacity: 0.6;
}
.integ-step-ic {
  width: 46px; height: 46px; border-radius: 12px; display: grid; place-items: center;
  color: var(--gold-bright); background: color-mix(in srgb, var(--gold) 10%, transparent);
  border: 1px solid var(--rule); margin-bottom: 14px;
}
.integ-step h3 { font-size: 1.04rem; color: var(--ink); margin-bottom: 6px; }
.integ-step p { font-size: 0.92rem; color: var(--text-secondary); line-height: 1.55; }
.integ-step .integ-tag {
  display: inline-block; margin-top: 12px;
  font-family: 'Fira Code', ui-monospace, monospace; font-size: 0.74rem;
  color: var(--gold); background: color-mix(in srgb, var(--gold) 7%, transparent);
  border: 1px solid var(--rule); border-radius: 8px; padding: 4px 9px;
}
/* connective arrow between steps (desktop only, decorative) */
@media (min-width: 760px) {
  .integ-step:not(:last-child)::after {
    content: "→"; position: absolute; top: 50%; right: -12px; transform: translateY(-50%);
    color: var(--gold-soft); font-size: 1.1rem; z-index: 1;
  }
}
.js .integ-step:hover { transform: translateY(-4px); border-color: var(--rule); }

/* "O que dá pra perguntar" , chips de exemplo, ilustram uso acessível */
.integ-ask { margin-top: 28px; }
.integ-ask-list { list-style: none; display: flex; flex-wrap: wrap; gap: 10px; margin-top: 14px; }
.integ-ask-list li {
  font-family: 'Lora', 'Lora Fallback', Georgia, serif; font-style: italic;
  font-size: 0.9rem; color: var(--ink-soft);
  background: var(--bg-2); border: 1px solid var(--hair);
  border-radius: 999px; padding: 9px 16px; line-height: 1.4;
}
.js .integ-ask-list li { transition: border-color .18s ease, color .18s ease; }
.js .integ-ask-list li:hover { border-color: var(--rule); color: var(--ink); }

@media (prefers-reduced-motion: reduce) {
  .counter-sweep { display: none; }
  .counter-spark span { transform: none !important; opacity: 0.7 !important; animation: none !important; }
  .aurora::after { animation: none !important; }
}

/* ===================== Sobre os dados (PUBLIC-09) ===================== */
.dados-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 12px; }
.dados-list li {
  font-size: 0.95rem; color: var(--text-secondary); line-height: 1.6;
  padding-left: 18px; position: relative;
}
.dados-list li::before {
  content: ""; position: absolute; left: 0; top: 0.62em;
  width: 6px; height: 6px; border-radius: 50%; background: var(--gold);
}
.dados-list li strong { color: var(--ink); }
.dados-table-wrap { overflow-x: auto; border: 1px solid var(--hair); border-radius: var(--radius-md, 14px); }
/* LC-02: indicador de foco do wrapper rolável (espelha .subproc-wrap) */
.dados-table-wrap:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.dados-table { width: 100%; border-collapse: collapse; font-size: 0.9rem; min-width: 520px; }
.dados-table th, .dados-table td { text-align: left; padding: 12px 16px; border-bottom: 1px solid var(--hair); vertical-align: top; }
.dados-table thead th {
  font-family: var(--font-nav, ui-sans-serif); font-size: 0.74rem; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--muted); background: var(--bg-2); font-weight: 600;
}
.dados-table tbody th[scope="row"] { color: var(--ink); font-weight: 600; white-space: normal; }
.dados-table tbody td { color: var(--text-secondary); }
.dados-table tbody tr:last-child th, .dados-table tbody tr:last-child td { border-bottom: 0; }
.dados-note { display: block; margin-top: 4px; font-size: 0.8rem; color: var(--muted); }
/* Inline abbreviations (ADI/ADC/ADPF/ADO): dotted underline + help cursor, theme-aware. */
.dados-note abbr[title] { text-decoration: underline dotted; text-underline-offset: 2px; cursor: help; }

/* ===================== Por relator / volume (PUBLIC-03) ===================== */
.rel-disclaimer {
  margin: 18px 0 6px; padding: 14px 18px; border-radius: var(--radius-md, 14px);
  border: 1px solid var(--hair); background: var(--bg-2);
  font-size: 0.88rem; color: var(--text-secondary); line-height: 1.55;
}
.rel-disclaimer strong { color: var(--ink); }
.rel-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 10px; }
.rel-item {
  padding: 14px 16px; border: 1px solid var(--hair); border-radius: var(--radius-md, 14px);
  background: var(--card);
}
.rel-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.rel-name { font-family: var(--font-display, Georgia, serif); font-size: 1rem; color: var(--ink); }
.rel-count { font-family: var(--font-mono, ui-monospace, monospace); font-size: 0.84rem; color: var(--gold); white-space: nowrap; flex-shrink: 0; }
.rel-orgaos { margin: 6px 0 0; font-size: 0.82rem; color: var(--muted); }
/* Career timeline is opt-in (progressive disclosure — not always-on profiling). */
.rel-trajetoria { margin: 8px 0 0; }
.rel-trajetoria > summary {
  cursor: pointer; font-size: 0.78rem; color: var(--text-secondary, var(--muted));
  list-style-position: inside; width: max-content; border-radius: 6px;
}
.rel-trajetoria > summary:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }
.rel-trajetoria[open] > summary { margin-bottom: 6px; }
.rel-trajetoria ul { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: 4px 14px; }
.rel-trajetoria li { font-size: 0.8rem; color: var(--muted); font-family: var(--font-mono, ui-monospace, monospace); }
.rel-empty { color: var(--muted); font-size: 0.9rem; padding: 12px 0; list-style: none; }

/* ============================ Páginas legais (LGPD) ============================
   Coluna de leitura para Privacidade / Termos / Cookies. Usa só tokens do tema
   (nenhum hex novo) e a escala de tipo --step-*. Medida de leitura ~70ch. */
.legal-prose { max-width: 72ch; padding-bottom: clamp(48px, 8vw, 96px); }
.legal-meta { font-family: 'Fira Code', monospace; font-size: 0.78rem; color: var(--text-tertiary); margin-top: 6px; }
.legal-prose section { margin-top: clamp(28px, 4vw, 44px); }
.legal-prose section:first-child { margin-top: clamp(12px, 2vw, 20px); }
.legal-prose h2 {
  font-size: var(--step-h3); line-height: 1.25; color: var(--ink);
  margin: 0 0 12px; padding-left: 14px; border-left: 2px solid var(--gold);
}
.legal-prose h3 { font-size: 1.05rem; color: var(--ink-soft); margin: 20px 0 8px; }
.legal-prose p { color: var(--text-primary); font-size: 1.02rem; line-height: 1.7; margin: 0 0 12px; }
.legal-prose ul { margin: 0 0 12px; padding-left: 1.25em; }
.legal-prose li { color: var(--text-primary); font-size: 1.02rem; line-height: 1.66; margin-bottom: 8px; }
.legal-prose li::marker { color: var(--gold-soft); }
.legal-prose strong { color: var(--ink); font-weight: 600; }
.legal-prose a { color: var(--gold); text-decoration: underline; text-underline-offset: 2px; }
.legal-prose a:hover { color: var(--gold-bright); }
.legal-prose code {
  font-family: 'Fira Code', monospace; font-size: 0.86em;
  background: var(--bg-3); border: 1px solid var(--hair);
  border-radius: 5px; padding: 1px 6px; color: var(--ink-soft);
}

/* Tabela de sub-processadores / cookies — rolável no mobile */
.subproc-wrap { overflow-x: auto; margin: 14px 0 16px; border: 1px solid var(--hair); border-radius: 10px; }
.subproc-wrap:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.subproc-table { width: 100%; border-collapse: collapse; min-width: 520px; font-size: 0.95rem; }
.subproc-table th, .subproc-table td { text-align: left; padding: 12px 16px; vertical-align: top; border-bottom: 1px solid var(--hair); }
.subproc-table thead th {
  font-family: 'Inter', 'Inter Fallback', 'Public Sans', sans-serif; font-size: 0.74rem; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--text-tertiary); background: var(--bg-2); font-weight: 600;
}
.subproc-table tbody tr:last-child td { border-bottom: 0; }
.subproc-table td:first-child { color: var(--ink-soft); font-weight: 500; white-space: nowrap; }
.subproc-table code { white-space: nowrap; }

/* Botão que parece link (ex.: "rever preferências de cookies") */
.link-button {
  background: none; border: 0; padding: 0; font: inherit; cursor: pointer;
  color: var(--gold); text-decoration: underline; text-underline-offset: 2px;
  /* inline ~20px de alvo — piso 44px sem sair do fluxo (botão-texto) */
  min-height: 44px; min-width: 44px;
}
.link-button:hover { color: var(--gold-bright); }
.link-button:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; border-radius: 2px; }

@media (max-width: 560px) {
  .subproc-table td:first-child { white-space: normal; }
}

/* ============================ Consentimento de cookies (LGPD) ============================ */
.consent-row { display: flex; align-items: flex-start; gap: 10px; margin: 6px 0 2px; text-align: left; }
.consent-row input[type="checkbox"] { margin-top: 3px; width: 16px; height: 16px; accent-color: var(--gold); flex-shrink: 0; }
/* The base `label` is mono + UPPERCASE for short field labels ("NOME COMPLETO").
   The consent label is a full sentence, so reset it to the body sans, sentence case,
   for a readable, consistent identity (it was inheriting uppercase monospace). */
.consent-row label {
  font-family: 'Public Sans', 'Public Sans Fallback', system-ui, -apple-system, sans-serif;
  font-size: 0.88rem; color: var(--text-secondary); line-height: 1.45;
  text-transform: none; letter-spacing: 0; font-weight: 400;
}
.consent-row a { color: var(--gold); text-decoration: underline; text-underline-offset: 2px; }
.consent-row input[aria-invalid="true"] { outline: 2px solid var(--err); outline-offset: 2px; }

/* Aviso de cookies (LGPD): CARD COMPACTO flutuante no canto inferior-DIREITO.
   Era uma barra full-width fixa (left:0;right:0;bottom:0) que, enquanto visível,
   comia TODO clique na banda inferior da viewport — o hero CTA "Pedir acesso ao
   beta", o submit do #notify e o checkbox de consentimento em telas curtas (achado
   do funil beta 2026-07-21). Card de canto ANCORADO À DIREITA (decisão do design
   owner B 2026-07-21, OPÇÃO 2): o hero CTA é left-aligned no desktop, então o canto
   direito não o cobre. NO MOBILE o hero CTA é full-width (.hero-cta .btn = flex 1 1
   100%; medido: centro do CTA = 256 = centro da viewport @512), então a largura é
   capada em calc(50vw - 24px) para a borda ESQUERDA do card ficar sempre à direita do
   centro da viewport — o centro do CTA continua clicável em qualquer largura; 400px
   preservado no desktop (>=848px, onde o hero é 2-col e o CTA já está à esquerda).
   A reserva de espaço em runtime
   (registerBottomOverlay em app.js -> --overlay-bottom-h -> padding-bottom +
   scroll-padding-bottom) garante que o fim do scroll fica ACIMA do card. Conformidade
   LGPD INALTERADA: mesmos botões Aceitar/Recusar (igual proeminência), mesmo texto,
   mesmo link da política, mesmos handlers/cookies de consentimento — só a geometria
   mudou. Radius/sombra/superfícies/gold seguem os tokens do design system. */
.cookie-banner {
  position: fixed;
  right: 16px;
  right: calc(16px + env(safe-area-inset-right, 0px));
  left: auto;
  bottom: 16px;
  bottom: calc(16px + env(safe-area-inset-bottom, 0px));
  z-index: 200;
  width: min(360px, calc(100vw - 32px));
  max-width: 360px;
  background: var(--bg-3);
  border: 1px solid var(--rule);
  border-radius: 14px;
  box-shadow: 0 16px 44px rgba(0, 0, 0, 0.45), 0 3px 10px rgba(0, 0, 0, 0.30);
}
.cookie-banner[hidden] { display: none; }
/* Desktop = cartão de canto ENCOLHIDO (título + ~2 linhas de texto + botões inline).
   Antes era um cartaz que subia ~354-464px e cobria o hero CTA; agora a caixa fica
   baixa (top bem abaixo do CTA @carga) e o auto-colapso (app.js) tira o resto. */
.cookie-banner-inner {
  padding: 13px 15px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
/* Título "Cookies" = nome acessível do diálogo (aria-labelledby="cookie-banner-title"),
   mantido sr-only: sai da vista sem sair da árvore de acessibilidade (o leitor de tela
   ainda anuncia "Cookies"; a copy visível é só o parágrafo, conforme ruling do operador). */
.cookie-banner-text strong {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}
.cookie-banner-text p { color: var(--text-secondary); font-size: 0.86rem; line-height: 1.5; margin: 0; }
.cookie-banner-text a { color: var(--gold); text-decoration: underline; text-underline-offset: 2px; }
.cookie-banner-text a:hover { color: var(--gold-bright); }
.cookie-banner-text a:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; border-radius: 4px; }
.cookie-banner-actions { display: flex; gap: 8px; flex-wrap: wrap; }
/* Botões discretos: SEM flex-grow (não esticam full-width), inline no card/barra.
   L-09 / BOARD Wave1: alvos ≥44px (WCAG 2.5.5 / touch) em Aceitar e Recusar. */
.cookie-banner-actions button { flex: 0 1 auto; min-height: 44px; min-width: 44px; }
.cookie-banner button { font: inherit; font-size: 0.82rem; font-weight: 600; padding: 7px 14px;
  min-height: 44px; border-radius: 999px; cursor: pointer; border: 1px solid transparent; transition: background .15s ease, border-color .15s ease, color .15s ease; }
.cookie-accept { background: var(--gold); color: var(--bg); border-color: var(--gold); }
.cookie-accept:hover { background: var(--gold-bright); border-color: var(--gold-bright); }
.cookie-reject { background: transparent; color: var(--ink-soft); border-color: var(--rule); }
.cookie-reject:hover { border-color: var(--gold); color: var(--ink); }
.cookie-banner button:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

/* MOBILE (<=880px, onde o .hero-grid é 1-coluna) = aviso IN-FLOW no TOPO do documento.
   V2 do fix do funil (ruling B/Q 2026-07-23): a barra/pill FIXED de rodapé é uma CLASSE
   MORTA no mobile — em viewport baixo (@390x667/512x667 o hero CTA termina ~11px do rodapé)
   e na home o #quick-capture .qc-btn qualquer overlay fixo de rodapé cobre o CTA; encurtar
   copy não resolve a classe. Aqui o aviso é `position: static`: ocupa espaço no fluxo
   (empurra o conteúdo pra baixo, acima do topbar sticky) e ROLA junto com a página — por
   CONSTRUÇÃO não há rect flutuante para interceptar clique de nenhum CTA. Invariante
   ESTRUTURAL travado em spec/cookie-banner-cta-overlap.test.js: dentro deste @media a
   .cookie-banner NÃO é fixed e o .cookie-pill é display:none (nenhum overlay fixo de cookie
   pré-decisão no mobile). Desktop (>880px, hero 2-col) mantém o card de canto + pill. */
@media (max-width: 880px) {
  .cookie-banner {
    position: static;
    left: auto;
    right: auto;
    bottom: auto;
    width: auto;
    max-width: none;
    max-height: none;
    overflow: visible;
    margin: 0;
    border-radius: 0;
    border-width: 0 0 1px 0;
    box-shadow: none;
  }
  .cookie-banner-inner {
    padding: 10px 16px;
    padding-top: max(10px, env(safe-area-inset-top, 0px));
    gap: 8px;
  }
  .cookie-banner-text p { font-size: 0.8rem; line-height: 1.4; }
  /* Links tocáveis (~40px de área prática) sem inflar as linhas. */
  .cookie-banner-text a { display: inline-block; padding: 9px 4px; margin: -5px 0; }
  .cookie-banner-actions { gap: 8px; }
  /* Botões compactos: sem flex-grow, 40px de toque efetivo garantido por min-height. */
  .cookie-banner-actions button { flex: 0 1 auto; padding: 7px 16px; font-size: 0.82rem; min-height: 44px; }

  /* Nenhum pill fixo no mobile pré-decisão (ele também sobreporia o CTA em viewport baixo).
     Re-acesso no mobile = footer "rever preferências" / página /cookies. */
  .cookie-pill { display: none; }

  /* Invocação EXPLÍCITA no mobile (data-cookie-prefs, ex. footer): aí sim um CARD FIXED
     TEMPORÁRIO — o usuário pediu e pode fechar (botão × criado em JS). */
  .cookie-banner.cookie-invoked {
    position: fixed;
    left: 12px;
    right: 12px;
    bottom: calc(12px + env(safe-area-inset-bottom, 0px));
    width: auto;
    max-height: 80vh;
    overflow-y: auto;
    border: 1px solid var(--rule);
    border-radius: 14px;
    box-shadow: 0 16px 44px rgba(0, 0, 0, 0.45), 0 3px 10px rgba(0, 0, 0, 0.30);
    z-index: 200;
  }
  .cookie-banner.cookie-invoked .cookie-banner-inner {
    padding-bottom: max(10px, env(safe-area-inset-bottom, 0px));
  }
}

/* Botão × do card invocado (mobile): oculto por padrão, visível só no card invocado. */
.cookie-close {
  display: none;
  position: absolute;
  top: 8px;
  right: 8px;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--ink-soft);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
}
.cookie-banner.cookie-invoked .cookie-close { display: inline-flex; align-items: center; justify-content: center; }
.cookie-close:hover { color: var(--ink); }
.cookie-close:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

/* PILL colapsado (DESKTOP) — canto inferior ESQUERDO, longe dos CTAs primários.
   O aviso colapsa para cá no primeiro scroll sem decisão (app.js, desktop-only); tap/click
   reabre. Consentimento LGPD inalterado (só a apresentação muda). Alvo <=48x120. */
.cookie-pill {
  position: fixed;
  /* Canto inferior DIREITO (2026-07-23, V2): co-locado com o card encolhido (que some ao
     colapsar), LONGE dos CTAs do funil no desktop, que ficam à esquerda/centro (hero /beta
     x>=96, #quick-capture, #notify-form). Bottom-esquerdo roçava a borda esquerda do hero
     /beta em certas rolagens; à direita fica x-disjunto de TODOS os CTAs em qualquer scroll. */
  right: 16px;
  right: calc(16px + env(safe-area-inset-right, 0px));
  bottom: 16px;
  bottom: calc(16px + env(safe-area-inset-bottom, 0px));
  z-index: 200;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 40px;
  max-width: 120px;
  padding: 0 14px;
  border-radius: 999px;
  background: var(--bg-3);
  color: var(--ink);
  border: 1px solid var(--rule);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.35);
  font: inherit; font-size: 0.85rem; font-weight: 600; line-height: 1;
  cursor: pointer;
  white-space: nowrap;
}
.cookie-pill[hidden] { display: none; }
.cookie-pill:hover { border-color: var(--gold); }
.cookie-pill:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.cookie-pill svg { width: 15px; height: 15px; flex: 0 0 auto; color: var(--gold); }

/* Movimento gated por prefers-reduced-motion: sem animação quando o usuário pede
   redução (barra e pill apenas aparecem). */
@media (prefers-reduced-motion: no-preference) {
  .cookie-banner:not([hidden]) { animation: cookie-rise .22s ease both; }
  .cookie-pill:not([hidden]) { animation: cookie-rise .18s ease both; }
}
@keyframes cookie-rise { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* =========================================================================
   VISUAL-COMPONENT KIT (additive : ONE shared visual language)
   -------------------------------------------------------------------------
   Reusable "show-don't-tell" primitives for every landing screen and the
   conceitos/*.html pages (which also load this file). All classes below are
   NEW : nothing here restyles an existing selector. Brand vocabulary only :
   mono = 'Fira Code'; serif = 'Lora'; accent = var(--gold)/--gold-bright;
   surfaces = var(--card)/--bg-3/--hair/--rule; success = var(--ok). Pill
   radius is the project's literal 999px. No travessão in any rendered copy.

   Usage contract (one line each) :
     .stat-tile        big mono gold number + muted label : <div class="stat-tile"><span class="stat-tile__num">312</span><span class="stat-tile__label">sub-áreas</span></div>
     .coverage-bar     labelled progress meter, fill driven by --pct (0-100), fill color overridable via --bar-fill : <div class="coverage-bar" role="meter" aria-valuenow="82" aria-valuemin="0" aria-valuemax="100" aria-label="STJ 82%" style="--pct:82"><span class="coverage-bar__head"><span class="coverage-bar__name">STJ</span><span class="coverage-bar__val">82%</span></span><span class="coverage-bar__track"><span class="coverage-bar__fill"></span></span></div>
     .compare-table    2-col comparison : mono gold first column, serif second : <table class="compare-table"><tbody><tr><th scope="row">CNJ</th><td>classificação oficial</td></tr></tbody></table>
     .chip-row         flex pill container; wraps .chip-row__chip and .platform-chip
     .chip-row__chip   neutral pill (hair border) for tags/labels inside .chip-row (KIT-scoped : does NOT touch the legacy bare .chip)
     .platform-chip    interactive platform pill (link/button), gold on hover : <a class="platform-chip" href="…"><svg class="kit-icon">…</svg>Claude Desktop</a>
     .proof-card--pass modifier on .proof-card : adds left var(--ok) stripe for zero-violation / passed proof cards : <article class="proof-card proof-card--pass">…</article>
     .kit-icon         inline-SVG icon convention : 16-20px, stroke var(--gold), no fill (decorative SVGs also need aria-hidden="true")
   ========================================================================= */

/* ---- stat-tile : one headline number + its label ---- */
.stat-tile {
  display: flex; flex-direction: column; gap: 4px; min-width: 0;
}
.stat-tile__num {
  font-family: 'Fira Code', ui-monospace, monospace; font-weight: 600;
  color: var(--gold); line-height: 1;
  font-size: clamp(1.8rem, 1.2rem + 2.4vw, 2.8rem);
  letter-spacing: -0.01em; font-variant-numeric: tabular-nums;
}
.stat-tile__label {
  font-family: 'Fira Code', ui-monospace, monospace;
  font-size: 0.74rem; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--muted); line-height: 1.35;
}
/* optional: lay out several tiles on one row */
.stat-tile-row {
  display: grid; gap: clamp(18px, 3vw, 32px);
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
}

/* ---- coverage-bar : labelled progress meter (role="meter") ----
   Drive the fill width with the --pct custom property (a unitless 0-100
   number, e.g. style="--pct:82"). Authors MUST also set the real ARIA
   semantics on the element: role="meter" + aria-valuenow/min/max + an
   aria-label, since CSS width is presentational only. Fill color defaults
   to gold but is overridable per instance via --bar-fill (used by the
   conceitos semantic palette : lexical/semantic/hybrid). */
.coverage-bar { --pct: 0; --bar-fill: var(--gold); display: block; min-width: 0; }
.coverage-bar__head {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 12px; margin-bottom: 7px;
}
.coverage-bar__name {
  font-family: 'Fira Code', ui-monospace, monospace; font-size: 0.82rem;
  color: var(--ink); min-width: 0;
}
.coverage-bar__val {
  font-family: 'Fira Code', ui-monospace, monospace; font-size: 0.78rem;
  color: var(--muted); white-space: nowrap; font-variant-numeric: tabular-nums;
}
.coverage-bar__track {
  display: block; height: 8px; border-radius: 999px;
  background: var(--bg-3); border: 1px solid var(--hair); overflow: hidden;
}
.coverage-bar__fill {
  display: block; height: 100%; border-radius: 999px;
  width: clamp(0%, calc(var(--pct) * 1%), 100%);
  background: var(--bar-fill);
  transition: width .6s cubic-bezier(.22, 1, .36, 1);
}
@media (prefers-reduced-motion: reduce) {
  .coverage-bar__fill { transition: none; }
}

/* ---- compare-table : mono gold first column, serif second ---- */
.compare-table {
  width: 100%; border-collapse: collapse;
  font-size: 0.94rem; line-height: 1.55;
}
.compare-table th,
.compare-table td {
  text-align: left; vertical-align: top;
  padding: 11px 16px; border-bottom: 1px solid var(--hair);
}
.compare-table tr:last-child th,
.compare-table tr:last-child td { border-bottom: 0; }
.compare-table th[scope="row"],
.compare-table td:first-child {
  font-family: 'Fira Code', ui-monospace, monospace; font-weight: 600;
  color: var(--gold); white-space: nowrap;
}
.compare-table td:nth-child(2),
.compare-table th[scope="row"] + td {
  font-family: 'Lora', 'Lora Fallback', Georgia, serif; color: var(--text-primary);
}
.compare-table thead th {
  font-family: 'Fira Code', ui-monospace, monospace; font-weight: 600;
  font-size: 0.72rem; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--text-tertiary); border-bottom-color: var(--rule);
}

/* ---- chip-row + chips ----
   .chip-row is the flex container; .chip-row__chip is a neutral tag pill
   (kept off the legacy bare .chip selector to avoid restyling it).
   .platform-chip is an interactive (link/button) platform pill. */
.chip-row {
  display: flex; flex-wrap: wrap; gap: 10px; list-style: none;
  padding: 0; margin: 0;
}
.chip-row__chip {
  display: inline-flex; align-items: center; gap: 7px;
  font-family: 'Fira Code', ui-monospace, monospace; font-size: 0.82rem;
  color: var(--muted); border: 1px solid var(--hair); border-radius: 999px;
  padding: 7px 14px; background: rgba(255, 255, 255, 0.018);
}
.chip-row__chip strong { color: var(--ink); font-weight: 600; }
.platform-chip {
  display: inline-flex; align-items: center; gap: 8px;
  min-height: 44px; padding: 8px 16px;
  border: 1px solid var(--hair); border-radius: 999px;
  background: var(--card); color: var(--text-primary);
  font-size: 0.9rem; text-decoration: none;
  transition: border-color .2s ease, color .2s ease;
  overflow-wrap: anywhere; word-break: break-word; text-align: center;
}
.platform-chip:hover { border-color: var(--gold); color: var(--gold-bright); }
.platform-chip:hover .kit-icon { stroke: var(--gold-bright); }

/* ---- proof-card--pass : zero-violation proof card (left ok stripe) ----
   Additive modifier on the existing .proof-card; only paints the left edge. */
.proof-card--pass { border-left: 3px solid var(--ok); }

/* ---- kit-icon : inline-SVG icon convention (16-20px, stroke gold) ----
   Pair with <svg class="kit-icon" width="18" height="18" viewBox="0 0 24 24"
   fill="none" aria-hidden="true"> … strokes inherit var(--gold). Add a
   visible label next to it, or role/aria-label when the icon stands alone. */
.kit-icon {
  width: 18px; height: 18px; flex: none;
  stroke: var(--gold); stroke-width: 1.75; fill: none;
  stroke-linecap: round; stroke-linejoin: round;
  transition: stroke .2s ease;
}

/* =========================================================
   CROSS-DOCUMENT VIEW TRANSITIONS (WS2 pre-render MPA, W1)
   Opt both the SPA shell and the generated per-route documents
   into same-origin cross-document View Transitions, so a native
   navigation between pre-rendered docs cross-fades like the SPA
   (duration reuses the ::view-transition rule above). Progressive
   enhancement: browsers without @view-transition parse-skip the
   rule and keep the plain hard navigation. Disabled under
   reduced motion.
   ========================================================= */
@view-transition { navigation: auto; }
@media (prefers-reduced-motion: reduce) {
  @view-transition { navigation: none; }
}

/* =========================================================
   ATLAS TEASER (home, seção #atlas-home) — mapa semântico
   ilustrativo em SVG puro (o Atlas real, deck.gl/WebGL, vive
   no app em /atlas). Tudo token-driven (tema claro herda dos
   overrides de [data-theme='light']); movimento é CSS-only e
   morre sob prefers-reduced-motion.
   ========================================================= */
.atlas-teaser {
  display: grid;
  grid-template-columns: minmax(0, 1.7fr) minmax(240px, 1fr);
  gap: clamp(18px, 3vw, 34px);
  align-items: stretch;
  margin-top: 8px;
}

/* O palco: um "recorte" do mapa. É um LINK inteiro para o app. */
.atlas-stage {
  position: relative;
  display: block;
  min-height: 320px;
  border-radius: 16px;
  overflow: hidden;
  border: 1px solid var(--hair);
  background:
    radial-gradient(120% 90% at 22% 30%, color-mix(in srgb, var(--gold) 7%, transparent), transparent 55%),
    radial-gradient(110% 100% at 78% 72%, color-mix(in srgb, var(--indigo) 8%, transparent), transparent 60%),
    var(--bg-2);
  text-decoration: none;
  transition: border-color .25s ease, box-shadow .25s ease, transform .25s ease;
}
.atlas-stage:hover,
.atlas-stage:focus-visible {
  border-color: color-mix(in srgb, var(--gold) 45%, var(--hair));
  box-shadow: 0 24px 60px -30px rgba(0, 0, 0, 0.55);
  transform: translateY(-2px);
}
.atlas-stage:focus-visible {
  outline: 2px solid var(--gold-bright);
  outline-offset: 3px;
}
.atlas-field { position: absolute; inset: 0; width: 100%; height: 100%; }

/* Mar de fundo: dispositivos "distantes", neutros. */
.at-sea circle { fill: var(--muted-2); }

/* Ilhas temáticas: cada grupo herda um matiz da paleta de famílias/ramos. */
.at-isle circle { fill: var(--isle, var(--fam-default)); }
.at-isle--trabalhista { --isle: var(--fam-trts); }
.at-isle--tributario { --isle: var(--sky); }
.at-isle--penal { --isle: var(--err); }
.at-isle--civil { --isle: var(--indigo); }
.at-isle--administrativo { --isle: var(--gold); }
.at-isle--ambiental { --isle: var(--ok); }

/* Deriva lenta de cada ilha + pulso do ponto em destaque — só com motion OK. */
@media (prefers-reduced-motion: no-preference) {
  .at-isle { animation: at-drift 30s ease-in-out infinite alternate; }
  .at-isle--tributario { animation-duration: 34s; animation-delay: -6s; }
  .at-isle--penal { animation-duration: 27s; animation-delay: -14s; }
  .at-isle--civil { animation-duration: 32s; animation-delay: -3s; }
  .at-isle--administrativo { animation-duration: 26s; animation-delay: -18s; }
  .at-isle--ambiental { animation-duration: 29s; animation-delay: -10s; }
  @keyframes at-drift {
    from { transform: translate(0, 0); }
    to { transform: translate(9px, -6px); }
  }
  .at-focus-ring { animation: at-pulse 3.2s ease-out infinite; }
  @keyframes at-pulse {
    0% { r: 5; opacity: 0.75; }
    70% { r: 16; opacity: 0; }
    100% { r: 16; opacity: 0; }
  }
}
.at-focus-dot { fill: var(--gold-bright); }
.at-focus-ring { fill: none; stroke: var(--gold-bright); stroke-width: 1.5; opacity: 0.4; }

/* Rótulos flutuantes dos temas (decorativos, aria-hidden). */
.at-label {
  position: absolute;
  transform: translate(-50%, -50%);
  font-family: 'Fira Code', ui-monospace, monospace;
  font-size: 0.68rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-soft);
  background: color-mix(in srgb, var(--bg) 62%, transparent);
  border: 1px solid var(--hair);
  border-radius: 999px;
  padding: 3px 9px;
  pointer-events: none;
  backdrop-filter: blur(3px);
}

/* Cartão de exemplo: o que um clique abre no Atlas de verdade. */
.at-card {
  position: absolute;
  left: 24%;
  top: 42%;
  max-width: 240px;
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 11px 14px;
  border-radius: 12px;
  border: 1px solid color-mix(in srgb, var(--gold) 40%, var(--hair));
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  box-shadow: 0 18px 44px -22px rgba(0, 0, 0, 0.6);
  pointer-events: none;
  backdrop-filter: blur(4px);
}
.at-card-kicker {
  font-family: 'Fira Code', ui-monospace, monospace;
  font-size: 0.62rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--gold-bright);
}
.at-card-title {
  font-family: Lora, Georgia, serif;
  font-size: 1.02rem;
  font-weight: 600;
  color: var(--ink);
}
.at-card-sub { font-size: 0.74rem; line-height: 1.45; color: var(--muted); }

/* Convite fixo no canto do palco. */
.at-open {
  position: absolute;
  right: 14px;
  bottom: 12px;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: 'Fira Code', ui-monospace, monospace;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--gold-bright);
  padding: 8px 15px;
  border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--gold) 55%, transparent);
  background: color-mix(in srgb, var(--bg) 66%, transparent);
  transition: background .2s ease, color .2s ease, border-color .2s ease;
}
.atlas-stage:hover .at-open,
.atlas-stage:focus-visible .at-open {
  background: var(--gold);
  border-color: var(--gold);
  color: var(--bg);
}

/* Rótulo "Ilustração" no canto do palco do Atlas (F-A / S1 #4, 2026-07-07): deixa
   claro que o teaser é uma ilustração, não uma captura do produto real. Discreto,
   canto superior esquerdo, sem competir com o cartão de exemplo. */
.at-ilustra {
  position: absolute; left: 12px; top: 12px;
  font-family: var(--font-nav); font-size: 0.68rem; font-weight: 600;
  letter-spacing: var(--track-label); text-transform: uppercase;
  color: var(--text-secondary); background: color-mix(in srgb, var(--bg) 66%, transparent);
  border: var(--btn-border); border-radius: var(--radius-pill);
  padding: 4px 10px; pointer-events: none;
}

/* Onboarding em 3 passos, ao lado do palco. */
.atlas-steps {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: clamp(14px, 2.2vh, 22px);
}
.atlas-step { display: flex; gap: 13px; align-items: flex-start; }
.atlas-step-num {
  flex: 0 0 auto;
  width: 28px;
  height: 28px;
  display: grid;
  place-items: center;
  border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--gold) 55%, transparent);
  color: var(--gold-bright);
  font-family: 'Fira Code', ui-monospace, monospace;
  font-size: 0.78rem;
  font-weight: 600;
}
.atlas-step h3 {
  margin: 3px 0 4px;
  font-family: Lora, Georgia, serif;
  font-size: 1.02rem;
  font-weight: 600;
  color: var(--ink);
}
.atlas-step p { margin: 0; font-size: 0.86rem; line-height: 1.55; color: var(--muted); }

@media (max-width: 900px) {
  .atlas-teaser { grid-template-columns: 1fr; }
  .atlas-stage { min-height: 260px; }
}
@media (max-width: 560px) {
  .atlas-stage { min-height: 220px; }
  /* No celular o cartão de exemplo vira ruído sobre um palco pequeno. */
  .at-card { display: none; }
  .at-label { font-size: 0.6rem; }
}

/* Sem movimento: mapa 100% estático (as ilhas e o anel ficam parados). */
@media (prefers-reduced-motion: reduce) {
  .at-isle, .at-focus-ring { animation: none; }
  .atlas-stage, .at-open { transition: none; }
  .atlas-stage:hover, .atlas-stage:focus-visible { transform: none; }
}


/* WS-5 v1 — 4 verbal titles only (8 formas gated) */
.ws5-buscas { padding: 3rem 0 2rem; }
.ws5-list {
  list-style: none;
  margin: 1.25rem 0 0;
  padding: 0;
  display: grid;
  gap: 0.85rem;
}
.ws5-list li {
  padding: 0.9rem 1.1rem;
  border: 1px solid var(--hair, rgba(255,255,255,0.08));
  border-radius: 12px;
  background: var(--bg-2, transparent);
  line-height: 1.45;
}
.ws5-list strong { color: var(--gold, #b89244); font-weight: 600; }
