/* base.css — reset enxuto, tipografia de base, foco e a coluna de leitura.
   Nada aqui conhece componente. Só elemento e layout de página. */

/* ---------------------------------------------------------------
   1. RESET
   --------------------------------------------------------------- */
*,
*::before,
*::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  scroll-behavior: smooth;
}

body,
h1, h2, h3, h4,
p, figure, blockquote, dl, dd { margin: 0; }

/* :where() zera a especificidade do reset. Sem ele, ul[role="list"]
   (0,1,1) vence a classe de um componente (0,1,0) e apaga o padding
   que o componente definiu — foi o que derrubou o recuo lateral da
   c-scroll-strip por três fases sem ninguém ver. */
:where(ul[role="list"], ol[role="list"]) { list-style: none; padding: 0; margin: 0; }

img,
picture,
svg { display: block; max-width: 100%; }

button,
input,
textarea,
select { font: inherit; color: inherit; }

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

/* ---------------------------------------------------------------
   2. BASE
   --------------------------------------------------------------- */
body {
  background: var(--color-bg);
  color: var(--color-text-body);
  font-family: var(--font-sans);
  font-size: var(--type-body-size);
  line-height: var(--type-body-lh);
  font-weight: 400;
  /* trava o vazamento de 1px que o truque de sangria por 100vw pode
     abrir em navegadores com barra de rolagem clássica (não-overlay).
     `clip`, não `hidden`: a spec força overflow-y para `auto` quando um
     eixo é `visible` e o outro não — isso faria do body um contêiner de
     scroll e quebraria o position:sticky do case-toc. `clip` nos dois
     eixos evita essa regra por completo. */
  overflow-x: clip;
}

h1, h2, h3, h4 {
  font-size: inherit;
  font-weight: inherit;
  line-height: inherit;
  color: var(--color-text);
}

strong, b {
  font-weight: 700;
  color: inherit;
}

/* ---------------------------------------------------------------
   3. LINKS
   O site de produção não tem hover nenhum, o que deixa link sem sinal
   de que é clicável. Aqui o sublinhado aparece na interação.

   COR. Verde (--color-link) é o padrão de LINK DE TEXTO: footer, prosa
   e os dois CTAs. O padrão mora aqui, no elemento, e não numa classe,
   porque assim um <a> escrito dentro de um parágrafo amanhã já nasce
   certo sem ninguém lembrar de nada.

   O preço disso é que o padrão também alcança <a> que NÃO é link de
   texto: pill de nav, card que embrulha um bloco inteiro, rótulo de
   seção. Esses três voltam ao escuro, cada um no seu próprio
   componente (components.css §1b, §2, §7 e §8) — a lista de exceções
   é curta e fechada, e está anotada em cada um.

   HOVER. Mesmo verde, mais sublinhado: o link não troca de cor ao
   passar o mouse, só ganha o traço. Quem quer outro comportamento
   sobrepõe no componente, como o c-link-arrow faz (§20 em
   components.css) trocando o sublinhado pelo deslize da seta.
   --------------------------------------------------------------- */
a {
  color: var(--color-link);
  text-decoration: none;
  text-underline-offset: 0.25em;
  text-decoration-thickness: 1px;
  transition: text-decoration-color var(--duration-ui) var(--ease);
}

a:hover { text-decoration: underline; }

/* Depois que o verde virou o padrão de `a`, esta classe passou a repetir
   o que o elemento já faz. Fica de propósito, por dois motivos: os dois
   CTAs a declaram no HTML, então ela é o marcador explícito de "isto é
   um call to action" para quem lê a marcação; e ela é a rede se o padrão
   de `a` mudar. Aponta para --color-link direto, não para o apelido. */
.link-accent { color: var(--color-link); }

/* ---------------------------------------------------------------
   4. FOCO
   Ausente na produção inteira. É o requisito de acessibilidade mais
   barato e o mais visível para quem navega por teclado.
   --------------------------------------------------------------- */
:focus { outline: none; }

:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 3px;
  border-radius: 2px;
}

/* ---------------------------------------------------------------
   5. SKIP LINK
   --------------------------------------------------------------- */
.skip-link {
  position: absolute;
  top: var(--space-2);
  left: var(--space-2);
  z-index: 100;
  padding: var(--space-2) var(--space-4);
  background: var(--color-text);
  color: var(--color-bg);
  border-radius: var(--radius-sm);
  transform: translateY(calc(-100% - var(--space-4)));
  transition: transform var(--duration-ui) var(--ease);
}

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

/* ---------------------------------------------------------------
   6. COLUNA DE LEITURA
   Uma coluna manda. Só imagem tem licença para sangrar, e faz isso
   com .bleed, que quebra a grade sem sair do fluxo.
   --------------------------------------------------------------- */
.page {
  display: grid;
  grid-template-columns:
    [full-start] minmax(var(--gutter), 1fr)
    [content-start] min(var(--measure), 100% - var(--gutter) * 2) [content-end]
    minmax(var(--gutter), 1fr) [full-end];
  /* O respiro de baixo era --space-6 (24px), o mesmo valor de tudo
     quanto é gap pequeno no site — a página terminava justa demais
     depois do rodapé de contato. Subiu para --space-9 (56px), mais que
     o dobro, mantendo a assimetria com o topo (--space-10, 72px) de
     propósito: o respiro do topo empurra o conteúdo pra baixo da faixa
     morta do navegador, o de baixo só precisa parecer que a página
     "descansa" antes de acabar — não precisa ser tão grande quanto. Uma
     regra só, porque .page envolve toda página igual; nenhum ajuste por
     página foi necessário. */
  padding-block: var(--space-10) var(--space-9);
  row-gap: var(--rhythm);
}

/* <main> fica display:contents: continua sendo o único landmark <main>
   da página, mas some da árvore de layout, então cada <section> dentro
   dele vira item direto da grade — inclusive os que precisam de .bleed. */
.page > main { display: contents; }

.page > *,
.page > main > * { grid-column: content; }

.page > .bleed,
.page > main > .bleed { grid-column: full; }

.stack {
  display: flex;
  flex-direction: column;
  gap: var(--rhythm);
}

/* modificadores de gap — nomeados pelo papel, não pelo valor, para não
   precisar de renome se o token mudar de pixel.
   rótulo já tem seu próprio respiro (§ components.css .c-label);
   estes três só valem para o que vem depois dele. */
.stack--tight { gap: var(--space-4); }  /* prosa e link dentro de uma seção */
.stack--roomy { gap: var(--space-8); }  /* lista de blocos longos, ex. Work Experience */
.stack--cozy  { gap: var(--space-5); }  /* lista compacta, ex. Education */

/* linha com dois blocos nas pontas, ex. subtítulo + CTA no Quick stories */
.row-between {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-4);
  flex-wrap: wrap;
}

/* duas colunas iguais que viram uma abaixo do breakpoint,
   ex. Initiatives / What we move no case */
.grid-two {
  display: grid;
  gap: var(--space-8);
}

@media (min-width: 700px) {
  .grid-two { grid-template-columns: 1fr 1fr; }
}

/* Modificador — pedido do Breno pro par Initiatives / What we move em
   /case-prepaid: fica em DUAS colunas mesmo abaixo do breakpoint em vez
   de colapsar pra uma, com um gap menor no mobile (--space-4 em vez de
   --space-8) pra caber sem espremer o texto mais longo das duas listas
   ("Support deflection rate"). Único uso de `.grid-two` hoje, então o
   comportamento padrão de colapsar continua livre pra um próximo par
   que precise dele. */
.grid-two--always {
  grid-template-columns: 1fr 1fr;
  gap: var(--space-4);
}

@media (min-width: 700px) {
  .grid-two--always { gap: var(--space-8); }
}

/* ---------------------------------------------------------------
   7. UTILITÁRIOS
   --------------------------------------------------------------- */
/* lista que mantém a semântica mas dispensa o marcador visual */
.list-plain {
  list-style: none;
  margin: 0;
  padding: 0;
}

/* MARCA-TEXTO — a varredura de caneta marca-texto. Utilitário, não
   componente: vale em qualquer <span>/<mark> de texto corrido, e não
   conhece nenhuma seção do site.

   A cor vem de background-image e não de background-color porque o que
   anima é `background-size`: o gradiente de duas paradas iguais é uma
   faixa chapada que dá para redimensionar. `0 85%` ancora a faixa na
   linha de base do texto (não embaixo dele), e `45%` de altura deixa
   ela cobrindo só a metade inferior da letra, que é o que uma caneta
   de verdade faz.

   `box-decoration-break: clone` é o que impede o marcador de ser
   desenhado uma vez só para a caixa inteira quando o trecho quebra em
   duas linhas — sem isso, o preenchimento some da segunda linha.

   A classe `.is-marked` é escrita pelo IntersectionObserver do main.js.
   Sem JS o trecho fica sem marcador, e o texto continua legível: o
   marcador nunca carrega informação, só ênfase. */
.highlight {
  background-image: linear-gradient(120deg, var(--color-marker), var(--color-marker));
  background-repeat: no-repeat;
  background-position: 0 85%;
  background-size: 0% 45%;
  padding: 0 0.1em;
  transition: background-size var(--duration-marker) ease-in-out;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}

.highlight.is-marked { background-size: 100% 45%; }

.visually-hidden:not(:focus):not(:active) {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---------------------------------------------------------------
   8. MOVIMENTO
   O reveal só existe quando o JS liga .js no html. Sem JS, ou com
   reduced-motion, o conteúdo já nasce visível.
   --------------------------------------------------------------- */
.js .reveal {
  opacity: 0;
  transition: opacity var(--duration-reveal) var(--ease);
}

.js .reveal.is-visible { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  .js .reveal {
    opacity: 1;
    transition: none;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }

  /* A regra acima esmaga a DURAÇÃO, não o ATRASO — e o escalonamento do
     marca-texto é `transition-delay` inline, escrito pelo JS. Sem isto o
     marcador ainda apareceria em cascata, só que em saltos secos. O JS
     já não escreve o atraso quando a preferência está ligada; esta é a
     rede para quando ela muda com a página aberta, mesmo padrão do
     c-gallery-marquee. */
  .highlight { transition-delay: 0s !important; }
}

/* ---------------------------------------------------------------
   9. TRANSIÇÃO DE PÁGINA (View Transitions entre documentos)

   Cada navegação interna faz cross-fade: a página velha some, a nova
   aparece. A float bar é a única coisa que NÃO participa — ela fica
   parada enquanto o resto troca.

   POR QUE VIEW TRANSITIONS E NÃO OPACIDADE NO DOM VIVO. O fade acontece
   numa camada de SNAPSHOT que o browser monta por cima da página
   (a árvore `::view-transition`), não no `<body>` nem em nenhum
   ancestral real. Isso importa muito aqui: baixar a opacidade de um
   ancestral da float bar a transformaria em containing block do
   `position: fixed` e prenderia a barra — é o bug de 25/08 registrado
   no MEMORY.md. Com snapshot, o DOM vivo nunca recebe opacidade < 1,
   então aquele bug não tem como voltar por este caminho.

   ESCOPO. `navigation: auto` só vale para navegações same-origin de
   documento. Link externo com `target="_blank"` (Linkedin) abre outro
   contexto e nunca dispara; `mailto:` não é navegação de documento.
   Não precisa de exceção escrita para nenhum dos dois.

   DEGRADAÇÃO. Browser sem suporte ignora a at-rule inteira e navega
   normalmente — nunca fica preso numa página invisível, porque não há
   estado inicial escondido esperando JS para aparecer. Voltar pelo
   bfcache também é seguro: o DOM volta com as classes que tinha
   (`.reveal.is-visible` inclusive), então nada renasce em opacity 0.
   --------------------------------------------------------------- */
@view-transition { navigation: auto; }

/* Curto de propósito: a navegação não pode PARECER mais lenta por causa
   do enfeite. Fica no mesmo espírito do fade de rolagem. */
::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: var(--duration-page-transition);
  animation-timing-function: var(--ease);
}

/* A FLOAT BAR PERSISTE. Com nome próprio ela vira um grupo separado da
   raiz: sai do cross-fade geral e deixa de ser desenhada duas vezes
   (uma no snapshot da página velha, outra no da nova), que é o
   piscar/duplicar clássico de nav em transição de página.

   O GRUPO ainda anima; o PAR DE IMAGENS não. A distinção é o miolo
   desta regra e vale explicar.

   A barra tem duas posições possíveis: parada dentro do header (página
   no topo) e fixa a --floatbar-top da viewport (página rolada). Saindo
   de uma página rolada para uma página nova, que sempre começa no topo,
   as duas geometrias não batem. Duas saídas ruins e uma boa:

   · deixar tudo no padrão: a barra cross-fadeia consigo mesma. Como as
     duas fotos são quase idênticas, o `mix-blend-mode: plus-lighter`
     que a UA aplica ao par clareia o pill no meio do caminho, um flash
     branco justo no elemento que deveria ser o ponto fixo da tela.
   · zerar também o grupo: a barra TELEPORTA para a posição nova no
     primeiro quadro. Some o flash, entra um salto.
   · manter o grupo animando e matar só o par, que é o escrito abaixo:
     a barra DESLIZA da posição antiga para a nova, sólida, sem nunca
     perder opacidade. Quando as duas posições já coincidem (o caso
     comum, clicar na nav com a página no topo) a animação do grupo é
     um no-op e a barra fica perfeitamente parada.

   `opacity: 1` fixo no `-new` é o que garante o "sólida": sem ele o
   pseudo herdaria o fade-in padrão da UA. */
/* `[data-floatbar]` e nao `.c-floatbar`: nome de view transition tem de
   ser UNICO no documento, e nome repetido nao degrada — aborta a
   transicao inteira. O `_components-test.html` tem SEIS `.c-floatbar`
   (demos de estado) e nenhum `data-floatbar`; o atributo so existe na
   barra de verdade, uma por pagina. */
[data-floatbar] { view-transition-name: floatbar; }

::view-transition-group(floatbar) {
  animation-duration: var(--duration-page-transition);
  animation-timing-function: var(--ease);
}

::view-transition-old(floatbar) { animation: none; opacity: 0; }
::view-transition-new(floatbar) { animation: none; opacity: 1; }

/* Reduced motion. A regra global de §8 mira `*`, que NÃO alcança os
   pseudo-elementos de view transition (eles vivem numa árvore à parte),
   então o corte precisa ser escrito aqui. Fica em 1ms em vez de
   `animation: none` de propósito: zerar a animação da raiz deixaria o
   snapshot velho e o novo empilhados no mesmo quadro, com o
   `mix-blend-mode: plus-lighter` que a UA aplica ao par — clarão branco
   no lugar de uma troca limpa. Com 1ms a semântica da animação fica de
   pé e a troca vira instantânea. */
@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) {
    animation-duration: 1ms !important;
  }
}

/* Quebra de linha que só existe em tela larga. Serve para travar o
   desenho de uma frase (hoje a headline da Home) sem impor a mesma
   quebra no mobile, onde a coluna é estreita demais para ela fazer
   sentido. `<br>` é substituível: `display: none` o desliga de verdade,
   o texto volta a fluir como se ele não estivesse lá. */
.u-br-wide { display: none; }

@media (min-width: 700px) {
  .u-br-wide { display: inline; }
}
