/* ==============================================================
   CONTEÚDO — hub de conteúdos (conteudos.html) e o template usado
   por todos os artigos (conteudos/<categoria>/*.html). Qualquer estilo
   novo aqui vale automaticamente para os próximos artigos publicados.
   ============================================================== */

.news-page { background: #f5f5f5; }
.article-page { background: #f5f5f5; }

/* Hero override for the Conteúdos hub (Figma node 2293:157) — .page-hero
   itself is shared with Projetos/Serviços (see componentes.css), so only
   this page's values are tweaked here instead of touching the shared
   rule: 48px gap (was 45) and pb-80 (was 160), plus the old 8-col-era
   80px extra indent on the title/info removed (the 180px grid margin
   from .container already provides the correct left/right edge). */
.news-page .page-hero {
  gap: 48px;
  padding-bottom: 160px;
}

.news-page .page-hero-title,
.news-page .page-hero-info {
  padding: 0;
}

@media (max-width: 900px) {
  .news-page .page-hero {
    gap: 24px;
    padding-bottom: 56px;
  }
}

/* Sequência de entrada orquestrada (mesmo padrão de projetos.css, ver
   initHeroIntroSequence em script.js): título nasce alinhado com
   .news-filter, wipe-mask, escorrega pra posição atual, depois libera
   hero-info e só então .news-filter/.news-posts sobem com fade. */
.news-page .page-hero-title {
  transform: translateY(var(--intro-offset, 0px));
  transition: transform 1.2s cubic-bezier(0.65, 0, 0.35, 1);
}

.news-page .page-hero-info {
  opacity: 0;
}

.news-page .page-hero-info.is-intro-visible {
  opacity: 1;
  transition: opacity 0.4s ease;
}

.news-page .news-filter,
.news-page .news-posts {
  opacity: 0;
  transform: translateY(100px);
}

.news-page .news-filter.is-intro-visible,
.news-page .news-posts.is-intro-visible {
  opacity: 1;
  transform: translateY(0);
  transition: opacity 1.6s cubic-bezier(0.16, 1, 0.3, 1), transform 1.6s cubic-bezier(0.16, 1, 0.3, 1);
}

/* ===== Filtro (categoria) =====
   Own section, no vertical padding of its own — per Figma the only
   whitespace above it is the hero's own pb-80, and the tab row's own
   padding is what gives it height. */
.news-filter { background: #f5f5f5; }

.news-posts { padding: 80px 0; }

.tabs-list {
  display: flex;
  gap: 24px;
  align-items: flex-end;
  flex-wrap: wrap;
}

/* Same text formatting + line technique as .filter-select-trigger/
   .filter-select-option (projetos.css): Exo 2/400/20px, gray-07 by
   default, hover lightens to gray-06 (active or not), and a 1px line
   (not a border — an absolutely-positioned ::after, so it never affects
   the box's height) reveals via scaleX. */
.tab {
  position: relative;
  font-family: var(--font-body);
  font-size: 20px;
  font-weight: 400;
  color: var(--gray-07);
  transition: color 0.2s ease;
}

.tab::after {
  content: "";
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: right;
  transition: transform 0.35s ease;
}

.tab:hover {
  color: var(--gray-06);
}

.tab:hover::after,
.tab.is-active::after {
  transform: scaleX(1);
  transform-origin: left;
}

/* row-gap 80/column-gap 48, same recipe as .home-projects-grid (see
   modulos/home.css) — reused here for the same 2-per-row card pattern. */
.news-grid {
  display: grid;
  grid-template-columns: repeat(var(--grid-columns), 1fr);
  column-gap: var(--grid-gutter);
  row-gap: 80px;
}

/* Reserves roughly the space a loaded page of cards will take up before
   data/content.json has actually been fetched — otherwise the grid is
   briefly empty, the page is shorter than the viewport, and the footer
   flashes into view at the bottom of the screen before the fetched
   content pushes it back below the fold. */
#news-grid {
  min-height: 60vh;
}

.news-card-image {
  position: relative;
  height: 194px;
  overflow: hidden;
  margin-bottom: 24px;
}

.news-card-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 1.2s cubic-bezier(0.16, 1, 0.3, 1), filter 1.2s cubic-bezier(0.16, 1, 0.3, 1);
}

.news-card-content {
  position: relative;
  padding-top: 8px;
}

/* The divider is a single pseudo-element line (not a border + an extra
   overlay), always visible at rest in its normal color. On hover it
   vanishes with the erased edge sweeping left to right (anchored on the
   right via transform-origin, shrinking away from the left). */
.news-card-content::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 3px;
  background: var(--gray-07);
  transform: scaleX(1);
  transform-origin: left;
  transition: transform 0.35s ease;
}

/* transform-origin snaps (it isn't in the transition list) the instant
   hover toggles, so each direction gets its own anchor: vanishing on
   enter is anchored right (erasing sweeps left-to-right), reappearing on
   leave is anchored left (growth sweeps left-to-right too). .content-row
   (home preview, see modulos/home.css) shares these same inner classes. */
.content-row:hover .news-card-content::after,
.content-row:focus-visible .news-card-content::after {
  transform: scaleX(0);
  transform-origin: right;
}

.news-card-category {
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: 14px;
  color: var(--gray-07);
}

.news-card-title {
  margin-bottom: 8px;
  overflow: hidden;
}

.news-card-title h3 {
  font-size: 24px;
}

.news-card-content p {
  font-weight: 300;
  font-size: 20px;
  color: var(--gray-07);
}

/* ===== Postagem card (grid da página de Conteúdos, Figma node 2293:157) =====
   Own outer class (.content-card), reused as-is by each article's
   .article-related-grid (#article-related-grid, built via JS) so both
   grids share the exact same card. Structure/spacing mirrors
   .home-project-card (modulos/home.css): image with margin-bottom, block
   content below, hover scale+blur on the image. */
.content-card {
  grid-column: span 6;
  display: block;
  position: relative;
}

/* Teste: superfície branca atrás do card no hover. Pseudo-elemento em vez
   de background direto em .content-card — a imagem e o texto encostam nas
   bordas do card (sem padding lateral), então um background ali só
   apareceria em tiras finas nos gaps verticais. O ::before soma um halo de
   24px ao redor (position:absolute + inset negativo), sem mudar o layout
   em repouso, e fica atrás do conteúdo via z-index:-1. */
.content-card::before {
  content: "";
  position: absolute;
  inset: -24px;
  z-index: -1;
  background: transparent;
  border-radius: 8px;
  box-shadow: 0 8px 16px rgba(0, 0, 0, 0);
  transition: background-color 0.4s cubic-bezier(0.16, 1, 0.3, 1),
    box-shadow 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}

.content-card:hover::before {
  background: var(--white);
  box-shadow: 0 8px 16px rgba(0, 0, 0, 0.08);
}

.content-card .news-card-image {
  height: auto;
  aspect-ratio: 622 / 320;
  margin-bottom: 40px;
}

/* .news-card-image img's transition is already declared unscoped further
   up — .content-card just needs its own hover/focus trigger, same as
   .news-card and .content-row (home.css). */
.content-card:hover .news-card-image img,
.content-card:focus-visible .news-card-image img {
  transform: scale(1.04);
  filter: blur(5px);
}

.content-card .news-card-content { padding-top: 0; }
.content-card .news-card-content::after { display: none; }

/* Categoria colada no título (margin-bottom:0) e título com 16px antes do
   resumo — mesmo espaçamento de .content-row (home.css), por pedido
   explícito de manter os dois iguais. */
.content-card .news-card-category {
  font-family: 'Exo 2';
  margin-bottom: 0;
  font-weight: 400;
  font-size: 18px;
  color: var(--gray-06);
}

.content-card .news-card-title {
  margin: 8px 0;
}

.content-card .news-card-title h3 {
  font-size: 32px;
  color: var(--gray-07);
}

.content-card .news-card-excerpt {
  margin-bottom: 32px;
  font-weight: 300;
  font-size: 18px;
  color: var(--gray-07);
}

/* Publicado em/tempo de leitura: mesma estrutura e estilo do rodapé do
   card de "Últimos conteúdos" da home (.content-row-foot, modulos/home.css)
   — só o nome da classe muda, pra não colidir com aquele escopo. */
.content-card-foot {
  display: flex;
  align-items: center;
  gap: 10px;
  font-weight: 400;
  font-size: 16px;
  color: var(--gray-06);
}

/* Teste: cursor customizado sobre os cards de conteúdo. O cursor nativo
   some (só com mouse de verdade — "pointer: fine" — telas touch não têm
   hover real) e essa box passa a seguir o ponteiro. Split em dois níveis
   porque o JS (script.js) já escreve `transform: translate(Xpx, Ypx)`
   inline no .cursor-tag pra seguir o mouse a cada frame — se o scale/
   centralização do hover morasse na mesma propriedade, um dos dois
   sobrescreveria o outro. O .cursor-tag-inner fica livre pra animar seu
   próprio transform (centralizar + crescer no .is-visible) via CSS. */
.cursor-tag {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 200;
  pointer-events: none;
}

.cursor-tag-inner {
  display: flex;
  align-items: center;
  padding: 12px 24px;
  border-radius: 4px;
  background: var(--gray-07);
  color: var(--gray-01);
  font-family: var(--font-heading);
  font-weight: 500;
  font-size: 16px;
  white-space: nowrap;
  opacity: 0;
  transform: translate(-50%, -50%) scale(0.8);
  transition: opacity 0.3s cubic-bezier(0.16, 1, 0.3, 1), transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}

.cursor-tag.is-visible .cursor-tag-inner {
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
}

@media (pointer: fine) {
  .content-card { cursor: none; }
}

.news-empty {
  font-size: 16px;
  color: var(--gray-06);
  margin-bottom: 40px;
}

/* Infinite scroll: an invisible 1px marker right after the grid — once it
   scrolls into view, JS (createScrollSentinel) grows the visible slice. */
.scroll-sentinel {
  height: 1px;
}

/* ===== Article (content page, Figma node 2293:277) =====
   Substitui o layout antigo (aside .article-meta + .article-layout em
   flex) por uma página em seções empilhadas — filtro, título/subtítulo,
   hero, grid de 3 colunas (índice/corpo/lateral) e relacionados — batendo
   com a nova referência do Figma. */

/* ===== Filtro (topo do artigo) =====
   Mesmas classes .tabs-list/.tab do hub (conteudos.html), mas aqui são
   links pra conteudos.html?categoria=X em vez de botões de filtro — a
   página de artigo não tem grade própria pra filtrar. .site-header já é
   sticky e ocupa seu próprio espaço no fluxo normal (não é overlay como no
   frame do Figma), então só falta um respiro de 40px até a linha de tabs. */
.article-filter {
  padding-top: 40px;
}

/* ===== Título, subtítulo e metadados =====
   Grid de 12 colunas só pra limitar título+intro a 9 (o byline abaixo
   continua largura cheia, span 12) — mesma lógica de subgrid local já
   usada em .axis-intro (servicos.css) pra travar uma largura específica
   sem depender de px fixo. padding-top:230px (140 + 90) iguala a altura
   em que o título wipe começa na tela à de .page-hero (conteudos.html/
   projetos.html/servicos.html): aqui o offset extra até o h1 vem de
   .article-filter (40px + altura da linha de tabs, ~30px) somado a este
   padding — medido via CDP pra fechar em 380px do topo da viewport,
   igual às outras páginas. */
.article-intro-block {
  padding: 230px 0 80px;
  display: grid;
  grid-template-columns: repeat(var(--grid-columns), 1fr);
  column-gap: var(--grid-gutter);
  row-gap: 16px;
}

.article-title-block {
  grid-column: span 9;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.article-title-block h1 {
  font-size: 60px;
  line-height: 1.03;
}

.article-intro p {
  font-weight: 400;
  font-size: 24px;
  line-height: 1.4;
  color: var(--gray-06);
}

.article-byline {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px;
  margin-top: 8px;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 18px;
  color: var(--gray-06);
}

.article-byline-author {
  color: var(--gray-07);
}


.article-hero-image {
  position: relative;
  aspect-ratio: 1560 / 638;
}

/* Recorte da foto isolado num wrapper próprio (em vez de overflow:hidden
   direto no .article-hero-image) pra seta (.article-hero-arrow, mais
   abaixo) poder passar um pouco da borda quando o cursor chega perto,
   sem ficar cortada — ela é irmã desse wrapper, não fica presa no clip. */
.article-hero-photo {
  position: absolute;
  inset: 0;
  overflow: hidden;
}

.article-hero-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Seta da marca em cima da capa do artigo, sempre apontando pra direita
   — mesmo mecanismo da foto de "Quem lidera" (.about-lead-arrow em
   quem-somos.css), via JS (script.js: initLocalArrow). z-index simples
   (sem stacking context): nada mais na frente aqui disputa camada. */
.article-hero-arrow {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 2;
  pointer-events: none;
  transition: transform .3s ease-out;
  will-change: transform;
}

.article-hero-arrow-inner {
  transform: translate(-50%, -50%) rotate(-45deg) scale(0);
  color: var(--orange-accent);
  opacity: 0;
  will-change: transform, opacity;
}

.article-hero-arrow-icon {
  display: block;
  width: clamp(60px, 10vw, 190px);
  height: auto;
}

.article-hero-arrow.is-active .article-hero-arrow-inner {
  animation: local-arrow-appear .6s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

.article-hero-arrow.is-leaving .article-hero-arrow-inner {
  animation: local-arrow-disappear .5s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

@media (pointer: fine) {
  .article-hero-image { cursor: none; }
}

/* Espaço entre a imagem de capa e o grid (índice/corpo/lateral) que vem
   logo depois: padding-top na .container que envolve .article-section-grid,
   não na seção da imagem. */
.article-hero-image-section + .container {
  padding-top: 80px;
}

/* ===== Grid de 3 colunas: índice / corpo / lateral =====
   Spans 3/6/3 batem exatamente com o frame do Figma (1920px, margem 180,
   gutter 48): cada coluna do frame vale 86px, e 354/756/354px (índice/
   corpo/lateral) equivalem a 3/6/3 colunas do grid de 12 do site. */
.article-section-grid {
  display: grid;
  grid-template-columns: repeat(var(--grid-columns), 1fr);
  column-gap: var(--grid-gutter);
  align-items: start;
}

/* ===== Índice (TOC) =====
   Construído via JS a partir dos <h2> reais de .article-body (ver
   js/script.js) — nunca uma lista fixa, cada artigo tem um número
   diferente de capítulos. O ícone (mesma seta usada em .article-share/
   .nav-cta) só aparece no item ativo; nos demais, o espaço reservado pra
   ele vira a indentação (pl-24) do texto. */
/* Sticky: mesma receita/offset já usada em .project-toc (projetos.css) —
   acompanha o scroll do corpo do artigo e some sozinha quando a linha da
   grid (article-body, bem mais alta) termina. */
.article-toc {
  grid-column: span 3;
  display: flex;
  flex-direction: column;
  gap: 0px;
  padding: 0px 0 15px;
  position: sticky;
  top: calc(var(--header-height) + 40px);
}

.article-toc-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 0 4px 24px;
  font-family: var(--font-body);
  font-size: 16px;
  font-weight: 400;
  color: var(--gray-06);
  transition: color 0.2s ease;
}

.article-toc-item img {
  display: none;
  flex: none;
  width: 14px;
  height: auto;
}

.article-toc-item:hover {
  color: var(--orange);
}

.article-toc-item.is-active {
  padding-left: 0;
  font-weight: 600;
  color: var(--gray-07);
}

.article-toc-item.is-active img {
  display: block;
}

/* ===== Corpo do artigo ===== */
.article-body {
  grid-column: span 6;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 40px;
}

.article-image {
  overflow: hidden;
  aspect-ratio: 978 / 451;
}

.article-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* scroll-margin-top: sem isso, clicar num item do sumário rola o capítulo
   até encostar no topo real da viewport — onde o .site-header sticky (80px)
   cobre o título por cima, dando a impressão de que "nada aconteceu". Mesma
   receita/offset já usada para esse problema em projetos.css. */
.article-copy h2 {
  font-size: 32px;
  margin-bottom: 8px;
  scroll-margin-top: calc(var(--header-height) + 24px);
}

.article-copy p {
  font-weight: 300;
  font-size: 20px;
  line-height: 1.5;
  color: var(--gray-07);
  margin-bottom: 16px;
}

.article-copy p:last-child { margin-bottom: 0; }

.article-copy ul {
  list-style: disc;
  padding-left: 24px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.article-copy li {
  font-weight: 300;
  font-size: 20px;
  line-height: 1.5;
  color: var(--gray-07);
}

/* ===== Lateral: card "Sobre a Setta" + card "Compartilhar" =====
   .article-share é um <div> (não mais o <button> que envolvia o card
   inteiro na primeira versão) — agora carrega uma fileira de botões reais,
   um por rede (.article-share-icons), então o card em si não pode mais ser
   um único elemento clicável (button dentro de button é HTML inválido). */
/* Sticky na coluna inteira (não só em .article-share) — mesma receita/
   offset de .article-toc, pra grudar exatamente no mesmo instante do
   scroll que o sumário. Colar o sticky só no card "Compartilhar" (como
   era antes) faz ele nascer mais abaixo, porque sua posição estática de
   partida já vem empurrada pela altura de "Sobre a Setta" acima — dava um
   efeito de atraso, os dois só alinhavam depois de rolar bastante. Com o
   sticky na coluna toda, os dois topos (índice e lateral) partem do mesmo
   ponto da grid e prendem juntos. */
/* align-self:stretch força esta coluna a ocupar a altura cheia da linha
   (a mesma de .article-body, bem mais alto) — é esse espaço vazio abaixo
   do conteúdo real que dá "percurso" pro sticky de .article-share
   (abaixo) grudar e acompanhar o scroll em vez de já nascer parado.
   Sem gap geral aqui: a imagem cinza e o card "Sobre a Setta" continuam
   encostados (igual ao Figma) — o respiro de 40px antes de "Compartilhar"
   vem de margin-top nele mesmo (ver .article-share), não de um gap que
   afetaria os três filhos por igual. */
.article-side {
  grid-column: span 3;
  align-self: stretch;
  display: flex;
  flex-direction: column;
  padding-left: 86px;
}

.article-side-media {
  height: 137px;
  background: var(--gray-04);
}

.article-side-card {
  padding: 40px 28px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.article-about-card {
  background: var(--white);
}

.article-side-title {
  font-family: var(--font-heading);
  font-weight: 600;
  font-variation-settings: "wdth" 100;
  font-size: 18px;
  color: var(--gray-07);
}

.article-about-card p:not(.article-side-title) {
  font-family: var(--font-body);
  font-size: 16px;
  color: var(--gray-07);
}

/* .link-more (componentes.css, compartilhado com a home) não tem traçado
   embaixo do texto — escopado aqui em vez de mexer no componente
   compartilhado (ver [[feedback_page_scoping]]). Traçado FIXO (não
   reveal-on-hover), mesma receita de .home-talk-whatsapp/.section-more-link
   (home.css): border-bottom sempre visível, só a cor escurece no hover —
   pedido explícito do usuário pra bater com esse padrão já usado no site.

   width:fit-content é a peça que faltava: .article-side-card (pai flex-
   column) usa align-items padrão (stretch), então mesmo sendo inline-flex
   .link-more esticava pra largura cheia do card — e mesmo com o traçado
   escopado só no span do texto, o LINK inteiro (área clicável) continuava
   ocupando a linha toda. .home-talk-whatsapp/.section-more-link já
   declaram width:fit-content por causa exatamente disso. */
.article-about-card .link-more {
  width: fit-content;
}

.article-about-card .link-more-text {
  padding-bottom: 4px;
  border-bottom: 2px solid var(--gray-04);
  transition: border-color 0.3s ease;
}

.article-about-card .link-more:hover .link-more-text,
.article-about-card .link-more:focus-visible .link-more-text {
  border-color: var(--gray-07);
}

/* padding-top:0 (sobrescreve o padding:40px 28px herdado de
   .article-side-card) + margin-top:40px no lugar dele: sem isso, os 40px
   ficavam DENTRO da caixa sticky, entre o topo dela (onde o offset gruda)
   e o texto "Compartilhe este conteúdo" — o texto sempre nascia 40px mais
   baixo que o item ativo do sumário, mesmo com os dois topos alinhados.
   Com o respiro fora da caixa sticky (margem, não padding), o topo da
   caixa já É o texto, e passa a grudar exatamente na mesma altura do
   sumário (mesmo top). */
.article-share {
  padding-top: 0;
  margin-top: 40px;
  align-items: center;
  text-align: center;
  position: sticky;
  top: calc(var(--header-height) + 40px);
}

.article-share .article-side-title {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 16px;
}

/* Botões de compartilhamento — mesma referência de layout indicada pelo
   usuário (clay.global/blog/buttons-web-design): fileira de ícones simples
   abaixo do texto. Estilo desenhado pra bater com o resto do site (círculo
   com borda fina, ícone monoline, hover sólido laranja — igual ao padrão
   já usado em .tab/.link-more/.nav-cta) em vez das cores de marca de cada
   rede, pra não introduzir 4 cores novas na página. */
.article-share-icons {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
  margin-top: 4px;
}

.article-share-icon {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  border: none;
  background: var(--white);
  color: var(--gray-07);
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 14px;
  cursor: pointer;
  transition: box-shadow 0.2s ease, background-color 0.2s ease, color 0.2s ease;
}

.article-share-icon svg {
  width: 22px;
  height: 22px;
}

/* O path do WhatsApp deixa bem mais respiro dentro do viewBox 24x24 que os
   outros dois ícones, então no mesmo tamanho ele parecia menor — sobe só
   este pra igualar o peso visual. */
.article-share-icon[data-network="whatsapp"] svg {
  width: 30px;
  height: 30px;
}

.article-share-icon:hover,
.article-share-icon:focus-visible {
  background: var(--gray-07);
  color: var(--gray-01);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

/* Tooltip via ::after em todo ícone de compartilhamento (não troca o
   ícone, que é pequeno demais pra caber texto): aparece no hover/foco de
   qualquer um deles (WhatsApp/LinkedIn mostram o label, "copiar link"
   mostra "Copiar link"), mesma caixa cinza-07/texto cinza-01 em Exo 2. O
   botão "copiar" reaproveita o mesmo ::after pro feedback pós-clique — só
   troca o texto (via data-tooltip, atualizado em script.js) e força
   opacity:1 com .is-copied, sem precisar de hover nesse momento. */
.article-share-icon::after {
  content: attr(data-tooltip);
  position: absolute;
  bottom: calc(100% + 10px);
  left: 50%;
  transform: translateX(-50%) translateY(4px);
  white-space: nowrap;
  background: var(--gray-07);
  color: var(--gray-01);
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 16px;
  padding: 4px 8px;
  border-radius: 4px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease, transform 0.2s ease;
}

.article-share-icon:hover::after,
.article-share-icon:focus-visible::after,
.article-share-icon.is-copied::after {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

/* ===== Conteúdos Relacionados =====
   Reaproveita .content-card (mesmo cartão do hub) num grid de 3 colunas
   próprio — a lista em si é montada via JS a partir de data/content.json,
   nunca hardcoded (ver js/script.js, #article-related-grid). */
.article-related {
  padding: 80px 0;
}

.article-related-inner {
  display: flex;
  flex-direction: column;
  gap: 80px;
}

.article-related-heading {
  font-family: var(--font-heading);
  font-weight: 700;
  font-variation-settings: "wdth" 100;
  font-size: 40px;
  color: var(--gray-07);
}

.article-related-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--grid-gutter);
}

.article-related-grid .content-card { grid-column: auto; }

@media (max-width: 1440px) {
  .news-grid { grid-template-columns: repeat(6, 1fr); }
  .content-card { grid-column: span 3; }
}

@media (max-width: 900px) {
  .article-intro-block { padding: 56px 0 40px; }
  .article-title-block { grid-column: 1 / -1; }
  .article-hero-image-section { padding: 40px 0; }

  .article-section-grid { grid-template-columns: 1fr; row-gap: 40px; }
  .article-toc,
  .article-body,
  .article-side { grid-column: 1 / -1; }
  .article-side { padding-left: 0; align-self: auto; }

  /* Empilhado em 1 coluna não faz sentido flutuar nada — cada bloco fica
     no lugar em que aparece no fluxo normal. */
  .article-toc,
  .article-share { position: static; top: auto; }

  .article-related-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 640px) {
  .tabs-list { gap: 20px; }
  .tab { font-size: 18px; }

  .article-title-block h1 { font-size: 34px; }
  .article-intro p { font-size: 20px; }
  .article-related-heading { font-size: 30px; }
  .article-related-grid { grid-template-columns: 1fr; }

  .news-grid { grid-template-columns: 1fr; row-gap: 56px; }
  .content-card { grid-column: span 1; }
  .content-card .news-card-title h3 { font-size: 24px; }
  .content-card .news-card-excerpt { font-size: 16px; }
}

/* ===== Newsletter ===== */
.content-newsletter {
  background: var(--gray-07);
}

/* Split 6/6, mesma receita de grid de 12 colunas usada em .home-talk-grid
   e demais seções da home (modulos/home.css) — aqui as duas colunas do
   Figma são exatamente iguais (flex-[1_0_0] nos dois lados). */
.content-newsletter-grid {
  display: grid;
  grid-template-columns: repeat(var(--grid-columns), 1fr);
  gap: var(--grid-gutter);
  align-items: flex-start;
  padding: 80px 0;
  border-bottom: 1px solid var(--gray-06);
}

.content-newsletter-copy {
  grid-column: span 6;
  min-width: 0;
  max-width: 673px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.content-newsletter-copy h2 {
  font-size: 40px;
  line-height: 1.1;
  color: var(--gray-01);
}

.content-newsletter-copy p {
  font-size: 20px;
  font-weight: 500;
  line-height: 1.4;
  color: var(--gray-05);
}

.content-newsletter-form {
  grid-column: span 6;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 24px;
}

.content-newsletter-fields {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.content-newsletter-label {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 20px;
  color: var(--gray-01);
}

.content-newsletter-row {
  display: flex;
  gap: 16px;
  align-items: stretch;
}

/* Reaproveita .form-field (modulos/componentes.css) sem overrides de
   altura/padding — mesmo tamanho de campo dos outros formulários do site,
   só remove a margem padrão do componente (não há outro campo abaixo
   aqui) e cede a largura pro botão ao lado via flex. */
.content-newsletter-input {
  flex: 1 0 0;
  min-width: 0;
  margin-bottom: 0;
}

/* Só nesse botão: largura no tamanho do texto (só padding lateral, sem
   width fixo como antes) — a altura continua os 45px padrão de
   .form-submit, batendo com o input ao lado. */
.content-newsletter-submit {
  flex: none;
  width: auto;
  height: 45px;
  padding: 0 40px;
  margin-top: 0;
}

.content-newsletter-consent {
  display: flex;
  align-items: center;
  gap: 16px;
  font-size: 16px;
  color: var(--gray-01);
  cursor: pointer;
}

/* Input nativo continua clicável/focável (position:absolute + opacity:0,
   não display:none) pra manter navegação por teclado — só o desenho visual
   migra pro SVG ao lado. */
.content-newsletter-consent input[type="checkbox"] {
  position: absolute;
  width: 20px;
  height: 20px;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.content-newsletter-consent-svg {
  flex: none;
  overflow: visible;
}

.content-newsletter-consent-box {
  fill: transparent;
  stroke: var(--gray-01);
  stroke-width: 1.5;
  transition: fill 0.2s ease, stroke 0.2s ease;
}

.content-newsletter-consent input:checked ~ .content-newsletter-consent-svg .content-newsletter-consent-box {
  fill: var(--orange);
  stroke: var(--orange);
}

.content-newsletter-consent input:focus-visible ~ .content-newsletter-consent-svg {
  outline: 2px solid var(--orange);
  outline-offset: 2px;
  border-radius: 4px;
}

/* Check "desenha" ao marcar (mesma técnica do componente do Uiverse por
   SelfMadeSystem: stroke-dashoffset anima de "totalmente escondido" pra
   "totalmente visível"). pathLength=100 normaliza o traço num valor fixo
   e redondo, em vez de depender do comprimento geométrico real do path. */
.content-newsletter-consent-check {
  fill: none;
  stroke: var(--white);
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
  transition: stroke-dashoffset 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}

.content-newsletter-consent input:checked ~ .content-newsletter-consent-svg .content-newsletter-consent-check {
  stroke-dashoffset: 0;
}

.content-newsletter-form .form-feedback { margin-top: 0; text-align: left; color: var(--gray-04); }
.content-newsletter-form .form-feedback.is-success { color: var(--orange); }

/* Bug pré-existente encontrado ao testar o mobile desta página (achado
   nesta sessão, não causado por ela — o mesmo bug já afetava conteudos.html
   antes de qualquer mudança daqui): estas duas media queries viviam ANTES
   da declaração base de .content-newsletter-grid/-row acima, então a base
   (sem @media, mesma especificidade) sempre vencia a cascata e o override
   mobile nunca era aplicado — o formulário ficava espremido, cortado à
   direita da viewport. Movidas pra depois da base pra realmente vencer. */
@media (max-width: 900px) {
  .content-newsletter-grid { grid-template-columns: 1fr; gap: 40px; padding: 80px 0; }
  .content-newsletter-copy,
  .content-newsletter-form { grid-column: 1 / -1; }
}

@media (max-width: 640px) {
  .content-newsletter-row { flex-direction: column; align-items: stretch; }
  .content-newsletter-submit { width: 100%; }
}
