/* ==========================================================================
   NEXUS theme-final / 02-base.css
   Reset, tipografia, utilitários estruturais, foco e camada de fundo.
   Só consome tokens de 01-tokens.css. Nenhum hex, nenhum raio em px,
   nenhuma família de fonte literal aqui.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Reset enxuto
   -------------------------------------------------------------------------- */

*,
*::before,
*::after {
  box-sizing: border-box;
}

* {
  margin: 0;
}

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  -moz-tab-size: 2;
  tab-size: 2;
  background-color: hsl(var(--background));
  scrollbar-color: hsl(var(--border)) transparent;
  scroll-padding-block-start: calc(var(--header-h) + var(--space-4));

  /* Realce nativo de toque desligado na CAMADA COMPARTILHADA (item novo da
     rodada de 06/08/2026: "brilho de toque quadrado" — captura do dono, um
     retângulo azulado ao tocar um cartão do portfólio no celular, ignorando
     o raio do componente). É o `-webkit-tap-highlight-color` de fábrica do
     WebKit/Blink: pinta um retângulo semitransparente sobre a CAIXA de
     qualquer elemento "tocável" no toque, sem respeitar `border-radius`
     nenhum — não é bug de um cartão específico, é o comportamento padrão do
     motor para QUALQUER superfície clicável do site. Zerar aqui, em `html`,
     cobre todo mundo de uma vez (a propriedade não é herdada pela spec
     formal, mas os dois motores que a implementam resolvem o valor efetivo
     de cada elemento subindo até encontrar uma declaração, exatamente como
     herança) — nenhuma folha de seção precisa repetir isto.

     Sumir com o retângulo não pode significar sumir com o retorno de toque
     (o pedido explícito do dono): o substituto — um `:active` de verdade,
     que respeita o raio do PRÓPRIO componente porque é pintura da própria
     caixa dele, nunca um retângulo por cima — mora logo abaixo, em "4. Foco
     e acessibilidade": `.btn`, `.chip` e `.badge` já tinham `:active`
     autônomo (não dependia de `:hover` primeiro, então já funcionava em
     toque); só `.card--interactive` tinha um `:active` que SÓ desfazia o
     `:hover` (sem efeito nenhum em toque puro, onde `:hover` nunca dispara)
     — ganhou complemento; `.card` genérico (a classe-base que
     `.portfolio__card` também carrega, ver `#portfolio .portfolio__card`
     fora do território desta folha) ganhou um `:active` novo, para
     qualquer cartão clicável que ainda não tivesse o próprio. */
  -webkit-tap-highlight-color: transparent;
}

/* Rolagem suave só para quem não pediu menos movimento */
@media (prefers-reduced-motion: no-preference) {
  html {
    scroll-behavior: smooth;
  }
}

body {
  min-height: 100svh;
  background-color: transparent;
  color: hsl(var(--foreground));
  font-family: var(--font-body);
  font-size: var(--fs-base);
  line-height: var(--lh-body);
  font-weight: 400;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

/* Mídia é bloco e nunca estoura o container */
img,
picture,
video,
canvas,
svg,
iframe {
  display: block;
  max-width: 100%;
}

img,
video {
  height: auto;
}

/* Formulários herdam a tipografia do documento */
input,
button,
textarea,
select {
  font: inherit;
  color: inherit;
}

button {
  background: none;
  border: 0;
  cursor: pointer;
}

a {
  color: inherit;
  text-decoration-thickness: max(1px, 0.06em);
  text-underline-offset: 0.22em;
}

ul[role="list"],
ol[role="list"] {
  list-style: none;
  padding: 0;
}

hr {
  border: 0;
  border-block-start: var(--hairline) solid hsl(var(--border));
}

::selection {
  background-color: hsl(var(--primary) / 0.3);
  color: hsl(var(--foreground));
}

/* --------------------------------------------------------------------------
   2. Tipografia
   Display no cabeçalho, corpo no texto, mono só em rótulo e dado tabular.
   -------------------------------------------------------------------------- */

h1,
h2,
h3,
h4,
h5,
h6 {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: var(--lh-tight);
  letter-spacing: var(--tracking-display);
  text-wrap: balance;
  color: hsl(var(--foreground));
}

h1 {
  font-size: var(--fs-h1);
  line-height: var(--lh-display);
  font-weight: 700;
}

h2 {
  font-size: var(--fs-h2);
  line-height: var(--lh-display);
  font-weight: 650;
}

h3 {
  font-size: var(--fs-h3);
}

h4 {
  font-size: var(--fs-lead);
  letter-spacing: -0.015em;
}

h5 {
  font-size: var(--fs-base);
  letter-spacing: -0.01em;
}

h6 {
  font-size: var(--fs-sm);
  letter-spacing: 0;
}

p {
  font-size: var(--fs-base);
  line-height: var(--lh-body);
  text-wrap: pretty;
}

small {
  font-size: var(--fs-sm);
  line-height: 1.5;
}

strong,
b {
  font-weight: 650;
}

code,
kbd,
samp,
pre {
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
}

/* Bloco de código e tabela rolam dentro do próprio container */
pre {
  overflow-x: auto;
  max-width: 100%;
}

/* --------------------------------------------------------------------------
   3. Responsividade de base
   O <body> nunca rola na horizontal; texto longo quebra em vez de estourar.
   -------------------------------------------------------------------------- */

html,
body {
  overflow-x: clip;   /* clip em vez de hidden: não quebra position: fixed */
  max-width: 100%;
}

p,
li,
dd,
dt,
figcaption,
blockquote,
h1,
h2,
h3,
h4,
h5,
h6 {
  overflow-wrap: break-word;
  /* 13ª rodada, pedido do dono: nenhuma palavra quebra com hífen no meio
     ("em-presas" no lead do hero foi a gota). `manual` preserva hífens
     ortográficos (terça-feira) e mata a hifenização automática em todo o
     site; o overflow-wrap acima continua de rede para token gigante. */
  hyphens: manual;
}

/* Palavra técnica longa, URL e identificador não devem hifenizar */
code,
kbd,
samp,
pre,
a[href^="http"],
a[href^="mailto"] {
  hyphens: none;
  overflow-wrap: anywhere;
}

table {
  width: 100%;
  border-collapse: collapse;
}

.table-scroll {
  overflow-x: auto;
  max-width: 100%;
  -webkit-overflow-scrolling: touch;
}

/* Alvo de toque mínimo em dispositivo sem cursor fino */
@media (pointer: coarse) {
  button,
  summary,
  [role="button"],
  input[type="checkbox"],
  input[type="radio"] {
    min-block-size: var(--tap-min);
    min-inline-size: var(--tap-min);
  }
}

/* --------------------------------------------------------------------------
   4. Foco e acessibilidade
   -------------------------------------------------------------------------- */

/* O contorno acompanha sozinho o border-radius do elemento; não forçamos
   raio aqui para o foco continuar correto com --radius: 0. */
:focus-visible {
  outline: 2px solid hsl(var(--ring));
  outline-offset: 2px;
}

/* Anula o anel padrão só quando já existe substituto acima */
:focus:not(:focus-visible) {
  outline: none;
}

.sr-only,
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: fixed;
  inset-block-start: var(--space-4);
  inset-inline-start: var(--space-4);
  z-index: 999;
  padding: var(--space-3) var(--space-5);
  background-color: hsl(var(--primary));
  color: hsl(var(--primary-foreground));
  border-radius: var(--radius-md);
  border: var(--hairline) solid hsl(var(--primary));
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: var(--tracking-mono);
  text-transform: uppercase;
  text-decoration: none;
  box-shadow: var(--shadow-md);
  transform: translateY(-250%);
  transition: transform calc(var(--dur-fast) * var(--motion)) var(--ease-out);
}

.skip-link:focus-visible {
  transform: translateY(0);
}

/* --------------------------------------------------------------------------
   5. Utilitários de layout
   -------------------------------------------------------------------------- */

.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.container--wide {
  max-width: var(--container-wide);
}

/* §7.3, rampa de largura. Regra transversal: mora aqui e em nenhum partial.

   O container não salta de 1240px para 1600px de uma vez. Ele sobe em dois
   degraus em direção a --container-wide, porque a faixa que doía de verdade
   era 1560px a 1900px, onde 1240px de conteúdo ocupavam 72% da tela e o
   site parecia uma coluna estreita no meio do monitor.

   Degrau 1 (>= 1560px): meio caminho entre --container e --container-wide,
   1420px, expresso como interpolação dos dois tokens e não como número
   solto, para o estúdio continuar podendo mexer nos tokens sem quebrar a
   rampa.
   Degrau 2 (>= 1900px): --container-wide cheio, 1600px, que é o teto final
   exigido pelo parágrafo. Em 1920x1080 isso dá 83% da largura da tela,
   contra 65% de antes. Daí para cima quem cresce é --scale, nunca a
   largura.

   .container--wide continua sendo a exceção reservada às seções de grade
   densa (portfólio, govtech, cases e a barra do header), que precisam de
   mais trilhas antes de o container comum alcançá-las. Acima de 1900px as
   duas convergem em --container-wide, e é isso que mantém a navegação do
   header alinhada com o conteúdo das seções. */
@media (min-width: 1560px) {
  .container {
    max-width: calc(var(--container) + (var(--container-wide) - var(--container)) * 0.5);
  }

  /* .container--wide também é .container: sem esta redeclaração a regra
     acima, por estar dentro de media query e vir depois na folha, rebaixava
     o container largo de 1600px para 1420px justamente na faixa em que ele
     mais importa. Medido: o header e o portfólio saíam com 1420px em
     1728x1117. A modificadora tem que reafirmar o teto em cada degrau. */
  .container--wide {
    max-width: var(--container-wide);
  }
}

@media (min-width: 1900px) {
  .container,
  .container--wide {
    max-width: var(--container-wide);
  }
}

/* Largura de container e medida de leitura são coisas diferentes. Dentro de
   .container--wide o texto corrido continua travado em --measure (68ch, §3):
   o que ganha largura é a grade, nunca a linha de texto. Os blocos de texto
   das seções já declaram --measure por conta própria; esta é a rede de
   segurança para qualquer filho direto de um container largo.

   `.container--wide > .section__head` SAIU desta lista (06/08/2026, item
   "título de seção apertado"): a especificidade daqui (duas classes) vencia
   a de `.section__head` sozinho (uma classe, `min(100%, 44rem)` desde a
   mesma rodada, mais abaixo) E a de `.section__head--split{max-width:none}`
   (04-sections.css, também uma classe) — cancelando os dois de graça, só
   para quem mora direto num `.container--wide` (achado medindo #portfolio:
   508px em vez dos 704px que a regra de baixo já pedia; #govtech escapava
   por acaso, porque ali `.section__head` não é filho DIRETO de
   `.container--wide`, tem um `.govtech__panel` no meio). `.section__head`
   não é texto corrido — é a GRADE que empacota eyebrow/h2/lead — e já tem
   o próprio teto, que É a correção deste item; manter esta entrada aqui
   era repetir a política antiga por cima da nova, não uma proteção a mais.
   `p`, `.lead` e `.prose` continuam na lista: são texto corrido de verdade,
   e é exatamente para eles que esta rede de segurança existe. */
.container--wide > p,
.container--wide > .lead,
.container--wide > .prose {
  max-width: var(--measure);
}

.container--flush {
  padding-inline: 0;
}

/* --------------------------------------------------------------------------
   Ritmo vertical entre seções.

   DEFEITO CORRIGIDO NA RODADA DE AGOSTO DE 2026, e a correção é de camada,
   não de seção. `--section-y` é o respiro de UMA seção, mas duas seções
   vizinhas somam o respiro DUAS VEZES na junção entre elas: a base de uma
   mais o topo da outra. Medido em index2.html (pele de vidro, --density
   1.14), 1440x900, do último pixel pintado de uma seção ao primeiro da
   seguinte:

     provas -> tese            311px
     tese -> capacidades       402px
     capacidades -> metodo     401px
     metodo -> modelos         401px
     modelos -> portfolio      415px
     portfolio -> cases        402px      (e assim por diante, 11 junções)

   Ou seja: em 1440 o vazio entre duas seções valia mais que um terço da
   altura útil da tela, em TODA a página, e não só depois da régua de provas.
   Corrigir seção a seção (o que `sections/govtech.css` já tinha feito por
   conta própria, com um `padding-block` local de 0.38) troca o defeito por
   um ritmo irregular, porque o vizinho continua pagando o respiro inteiro.

   A correção: o respiro passa a ser propriedade da JUNÇÃO, não da seção.
   Quem tem vizinho paga metade daquele lado; a primeira e a última seção da
   página continuam com o respiro cheio contra o header e contra o rodapé.
   A junção passa a valer um `--section-y`, exatamente metade do que valia,
   e continua sendo o mesmo token do §4: nada de número novo, nada de
   `margin` negativa, nada de seção conhecendo a vizinha por nome.

   Os fatores são custom properties porque `--section-y` também é multiplicado
   por `--density` (o estúdio move os dois) e por `.section--tight`: escrever
   `padding-block` de novo em cada regra de junção desfaria a variante tight.
   Com fatores, tight continua tight, e metade de tight continua metade.

   `:has()` é progressive enhancement: onde ele não existir, o lado de baixo
   volta a pagar o respiro cheio e o site fica com o ritmo antigo, que é
   folgado, nunca quebrado.
   -------------------------------------------------------------------------- */

.section {
  --section-y-scale: 1;   /* variante da seção  (tight = 0.55) */
  --section-y-start: 1;   /* fator do lado de cima  (0.5 se há seção antes) */
  --section-y-end: 1;     /* fator do lado de baixo (0.5 se há seção depois) */
  position: relative;
  padding-block:
    calc(var(--section-y) * var(--section-y-scale) * var(--section-y-start))
    calc(var(--section-y) * var(--section-y-scale) * var(--section-y-end));
}

.section--tight {
  --section-y-scale: 0.55;
}

.section + .section {
  --section-y-start: 0.5;
}

.section:has(+ .section) {
  --section-y-end: 0.5;
}

/* --------------------------------------------------------------------------
   A junção do rodapé, que o seletor de irmão não alcança.

   DEFEITO 4 DO VEREDITO. As duas regras acima resolvem a junção por
   IRMANDADE, e existe exatamente uma junção da página em que os dois lados
   não são irmãos: `#contato -> #footer`. `core/render.js` promove o
   `<footer>` para fora de `<main>` depois da escrita única, para o landmark
   `contentinfo` não ficar dentro de `main` (mapeamento HTML -> ARIA). Depois
   da promoção, `#contato` é o último filho de `<main>` e não tem
   `+ .section` nenhum, e o rodapé é irmão de `<main>` e não tem `.section`
   antes dele: os dois ficam com fator 1, e a emenda soma o dobro.

   Medido antes da correção, do último pixel pintado de `#contato` ao
   primeiro do rodapé: 402px em index2 a 1440x900 contra 201px de toda junção
   de ritmo cheio, 220 contra 109 em 390x844, 269 contra 134 em index.html,
   141 contra 70 em index3.html. Era a única junção da página fora do ritmo.

   A promoção NÃO é desfeita: ela é conquista de acessibilidade. O que muda é
   o seletor, que passa a enxergar a forma promovida do documento. Continua
   sem número novo, sem `margin` negativa e sem seção conhecendo a vizinha
   pelo nome: quem sabe do rodapé é a tag `footer`, e ela é o landmark.

   As duas regras cobrem as DUAS formas do documento. Com o rodapé promovido,
   a primeira paga a metade de cima do lado de `#contato` e a segunda a
   metade de baixo do lado do rodapé. Sem JS, ou se `promoverRodape` não
   rodar, o rodapé continua dentro de `main`, `.section + .section` já dá a
   metade de cima e `footer.section` repete o mesmo 0.5: o valor é o mesmo
   pelos dois caminhos, então nenhuma das duas formas paga a emenda dobrada.
   -------------------------------------------------------------------------- */

main:has(+ footer.section) > .section:last-child {
  --section-y-end: 0.5;
}

footer.section {
  --section-y-start: 0.5;
}

/* Medida máxima aumentada (06/08/2026, item novo da rodada: "título de
   seção apertado" — captura do dono, "Um produto, quatro caminhos de
   mercado." quebrando em três linhas curtas com metade da tela vazia à
   direita, "pode aumentar um pouco mais a possibilidade de escrita desses
   títulos... tá muito apertado à esquerda"). MESMO DEFEITO do item do hero
   (sections/hero.css, .hero__copy), agora na camada dos cabeçalhos de
   seção: `var(--measure)` (52ch de fábrica) é medida de PARÁGRAFO — boa
   para o `.lead` que mora dentro deste bloco, curta demais para um `<h2>`
   de display que só tem duas ou três dezenas de caracteres.

   A correção NÃO larga `.lead`: ele já carrega o próprio `max-width: var(
   --measure)` (regra própria, logo abaixo de `.eyebrow`) — trocar o teto
   AQUI só afeta o quanto o `<h2>`/`.eyebrow` (que não têm medida própria)
   podem esticar; o parágrafo continua com a largura de leitura de sempre,
   dado por regra dele mesmo, não por herdar o teto do pai.

   `min(100%, 44rem)` em vez de um valor fixo: nunca estoura em tela
   estreita (100% do container já governa lá) e dá ao título quase o dobro
   de largura útil em telas médias/largas — medido (getClientRects do nó de
   texto) em "Um produto, quatro caminhos de mercado." (41 caracteres): 3
   linhas em 1280/1440/1920px antes, 1 linha depois, nas três larguras.
   `.section__head--split > *` (04-sections.css) já tinha o próprio teto
   independente e não muda. */
.section__head {
  display: grid;
  gap: var(--space-4);
  max-width: min(100%, 44rem);
  margin-block-end: var(--space-10);
}

.section__head--center {
  margin-inline: auto;
  text-align: center;
  justify-items: center;
}

/* Rótulo de seção: mono, caixa alta, curto */
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  font-weight: 500;
  line-height: 1;
  letter-spacing: var(--tracking-mono);
  text-transform: uppercase;
  color: hsl(var(--muted-foreground));
}

/* Traço/filete ANTES do rótulo removido por pedido do dono (item 4, rodada
   06/08/2026: "sem o traço, em TODAS as seções e nas 5 peles" — o `.eyebrow`
   vinha com um `::before` desenhando uma régua de 24px, hoje sem `content`
   nenhum, então nenhuma regra o desenha mais). Correção na CAMADA
   COMPARTILHADA cobre as 5 peles de uma vez só: `09-skin-cult.css` e
   `10-skin-smooth.css` só REDIMENSIONAM/RECOLOREM esse `::before` (viram um
   traço curto ou uma bolinha) sem nunca declarar `content` por conta
   própria — sem `content` aqui não sobra pseudo-elemento nenhum para elas
   dimensionarem, então as duas ficam sem marcador também, de graça, sem
   precisar editar aquelas folhas (fora do território deste agente).
   `08-skin-surface.css` (bolinha) segue a mesma lógica. `06-skin-glass.css`
   já declarava `content: none` por conta própria (cápsula translúcida no
   lugar do traço) — já estava correta, nada mudou lá.

   `.eyebrow--bare` (modificador que só existia para pedir `content: none`
   num `.eyebrow` específico) SAIU: virou política local sem propósito
   agora que o padrão inteiro já nasce sem traço — a classe pode continuar
   no HTML de quem já a usa (partials/cases.js, contato.js, govtech.js;
   fora do território deste agente) sem quebrar nada, só deixou de ter
   qualquer efeito visual, exatamente como o padrão ao redor dela. */

.lead {
  font-size: var(--fs-lead);
  line-height: 1.55;
  color: hsl(var(--muted-foreground));
  max-width: var(--measure);
}

.measure {
  max-width: var(--measure);
}

.measure--narrow {
  max-width: 46ch;
}

/* Grade fluida: nunca contagem fixa de colunas */
.grid-auto {
  display: grid;
  gap: var(--space-6);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--grid-min)), 1fr));
}

.grid-auto--sm {
  --grid-min: 200px;
}

.grid-auto--lg {
  --grid-min: 360px;
}

/* Pilha vertical com ritmo único */
.stack {
  display: grid;
  gap: var(--stack-gap, var(--space-4));
  align-content: start;
}

.stack--sm {
  --stack-gap: var(--space-2);
}

.stack--lg {
  --stack-gap: var(--space-8);
}

/* Fila que quebra sozinha */
.cluster {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--cluster-gap, var(--space-3));
}

.cluster--between {
  justify-content: space-between;
}

/* --------------------------------------------------------------------------
   6. Camada de fundo (--pattern)
   Pseudo-elemento fixo atrás do conteúdo. O pacote de variáveis vem de
   01-tokens.css; aqui só é aplicado. Com --pattern: none a camada some.
   -------------------------------------------------------------------------- */

body::before {
  content: "";
  position: fixed;
  inset: -12%;
  z-index: -1;
  pointer-events: none;
  background-image: var(--pattern-image);
  background-size: var(--pattern-size);
  background-position: var(--pattern-position);
  background-repeat: var(--pattern-repeat);
  opacity: calc(var(--pattern-opacity) * var(--pattern-boost));
  mix-blend-mode: var(--pattern-blend);
  -webkit-mask-image: var(--pattern-mask);
  mask-image: var(--pattern-mask);
  will-change: transform;

  /* Deriva lenta da aurora e do mesh: só transform, e a duração é gated
     por --motion. Com --motion: 0 a duração vira 0s e nada se move. */
  animation-name: var(--pattern-anim);
  animation-duration: calc(var(--motion) * 26s);
  animation-timing-function: var(--ease-io);
  animation-iteration-count: infinite;
  animation-direction: alternate;
}

@keyframes nx-drift {
  from {
    transform: translate3d(-1.5%, -1%, 0) scale(1.04);
  }
  to {
    transform: translate3d(1.5%, 1.5%, 0) scale(1.12);
  }
}

/* --------------------------------------------------------------------------
   7. Menos movimento: desliga tudo, sem exceção
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* --------------------------------------------------------------------------
   8. Impressão
   -------------------------------------------------------------------------- */

@media print {
  body::before {
    display: none;
  }

  .skip-link {
    display: none;
  }

  .section {
    padding-block: var(--space-8);
    break-inside: avoid;
  }
}
