/* ============================================================================
   DESIGN SYSTEM GABRIEL AMARAL · BASE
   Reset, tipografia e fundacoes. Depende de tokens.css.
   ========================================================================= */

/* --- FONTE ---------------------------------------------------------------
   Um arquivo variavel cobre toda a faixa de pesos. subset latin, 34 KB.
   swap: o texto aparece na hora em Helvetica/Arial e troca quando carregar.
   ------------------------------------------------------------------------ */
@font-face{
  font-family:"Archivo";
  src:url("../assets/fonts/archivo-var.woff2") format("woff2");
  font-weight:100 900;
  font-style:normal;
  font-display:swap;
}

/* --- RESET --------------------------------------------------------------- */
*,*::before,*::after{ box-sizing:border-box; }
html{ -webkit-text-size-adjust:100%; scroll-behavior:smooth; }
body,h1,h2,h3,h4,h5,p,figure,blockquote,dl,dd{ margin:0; }
ul[class],ol[class]{ margin:0; padding:0; list-style:none; }
img,picture,svg,video{ display:block; max-width:100%; }
img{ height:auto; }
button,input,select,textarea{ font:inherit; color:inherit; }
a{ color:inherit; }

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

/* --- CORPO --------------------------------------------------------------- */
body{
  font-family:var(--font);
  font-size:var(--t-body);
  line-height:var(--lh-body);
  color:var(--ink);
  background:var(--paper);
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
  font-synthesis-weight:none;
}

::selection{ background:var(--marca); color:var(--anchor); }

/* --- TIPOGRAFIA ---------------------------------------------------------- */
h1,h2,h3,h4{
  font-weight:700;
  line-height:var(--lh-tight);
  letter-spacing:var(--tr-tight);
  text-wrap:balance;
}
h1{ font-size:var(--t-h1); }
h2{ font-size:var(--t-h2); }
h3{ font-size:var(--t-h3); line-height:var(--lh-snug); }
p{ text-wrap:pretty; }

/* Nunca partir palavra ao meio: portugues quebrado atrapalha a leitura. */
h1,h2,h3,h4,p,li,dt,dd,td,th,figcaption{ hyphens:none; overflow-wrap:break-word; }

.lead{ font-size:var(--t-lead); line-height:1.45; color:var(--ink-muted); text-wrap:pretty; }
.small{ font-size:var(--t-small); }
.muted{ color:var(--ink-muted); }
.faint{ color:var(--ink-faint); }
.measure{ max-width:var(--measure); }

code{
  font-family:ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,monospace;
  font-size:.9em;
  padding:1px 5px;
  border-radius:var(--r-sm);
  background:color-mix(in srgb, var(--ink) 8%, transparent);
  white-space:nowrap;
}

/* Rotulo em caixa alta com tracking: padrao dos dois diagramas autorais. */
.label{
  font-size:var(--t-label);
  font-weight:700;
  letter-spacing:var(--tr-label);
  text-transform:uppercase;
  line-height:1.2;
}

/* Numero de resultado. tabular-nums para as colunas nao dancarem. */
.stat{
  font-size:var(--t-stat);
  font-weight:700;
  line-height:1;
  letter-spacing:var(--tr-tight);
  font-variant-numeric:tabular-nums;
}
.num{ font-variant-numeric:tabular-nums; }

/* --- SOLIDO vs OUTLINE ---------------------------------------------------
   O recurso autoral do lockup em Asset 2@8x.png: "Product" em peso solido
   contra "DESIGNER" vazado. E o que da personalidade ao titulo sem precisar
   de ornamento.

   -webkit-text-stroke tem suporte amplo mas nao universal, e onde falha o
   texto sumiria (cor transparente sem contorno). O @supports garante que a
   versao vazada so existe onde ha contorno para desenhar; fora dali o texto
   continua solido e legivel.
   ------------------------------------------------------------------------ */
.type-outline{ color:inherit; }

@supports (-webkit-text-stroke: 1px currentColor){
  .type-outline{
    /* NAO usar color:transparent aqui. currentColor resolve para o valor
       computado de color, entao zerar color zeraria tambem o contorno e o
       texto sumiria. -webkit-text-fill-color zera so o preenchimento e
       deixa color intacto para o contorno herdar. */
    -webkit-text-fill-color:transparent;
    -webkit-text-stroke:1.5px currentColor;
    paint-order:stroke fill;
  }
  @media (max-width:640px){
    /* em corpo pequeno o contorno fino some: engrossa proporcionalmente */
    .type-outline{ -webkit-text-stroke-width:1px; }
  }
}

/* --- FOCO ----------------------------------------------------------------
   Anel de foco sempre visivel, inclusive dentro da ancora escura.
   ------------------------------------------------------------------------ */
:focus-visible{
  outline:3px solid var(--ink);
  outline-offset:3px;
  border-radius:2px;
}
.anchor :focus-visible{ outline-color:var(--marca); }

/* --- LAYOUT --------------------------------------------------------------- */
.container{
  width:100%;
  max-width:var(--container);
  margin-inline:auto;
  padding-inline:clamp(20px, 5vw, 40px);
}

.section{ padding-block:var(--section-y); }

/* O topo e sticky, entao um link de ancora pararia com o titulo da secao
   escondido atras dele. scroll-margin desloca o ponto de parada. */
[id]{ scroll-margin-top:88px; }

/* WCAG 2.2 AA 2.4.11 · Focus Not Obscured.
   scroll-margin acima resolve so o clique em link de ancora. A navegacao por
   Tab e outro caminho: o browser rola o elemento focado para dentro da tela
   por conta propria, e o topo sticky cobriria o foco. scroll-padding no
   container de rolagem protege TODO scroll-into-view, inclusive o do foco. */
html{ scroll-padding-top:88px; }

/* Ancora escura. Reescreve os tokens de texto para o contexto invertido,
   entao qualquer componente dentro dela funciona sem saber onde esta. */
.anchor{
  background:var(--anchor);
  --ink:var(--on-anchor);
  --ink-muted:var(--on-anchor-muted);
  --ink-faint:var(--on-anchor-muted);
  --rule:var(--on-anchor-rule);
  --rule-strong:var(--on-anchor-muted);
  --card:#2E2E2E;
  color:var(--on-anchor);
}

/* --- ACESSIBILIDADE ------------------------------------------------------- */
.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;
}

.skip-link{
  /* fixed e nao absolute: com absolute o link fica ancorado no topo do
     DOCUMENTO, entao dar Tab depois de rolar mandaria o foco para fora da
     tela. z-index acima do topo sticky para nao ser coberto por ele. */
  position:fixed; top:0; left:0; z-index:999;
  transform:translateY(-120%);
  /* Amarelo da marca sobre tinta: 10,39:1. Com a cor da ancora o link ficava
     escuro sobre o topo escuro e sumia dentro dele. */
  background:var(--marca); color:var(--anchor);
  padding:var(--s-3) var(--s-5);
  font-weight:700; text-decoration:none;
  border-bottom-right-radius:var(--r-md);
  box-shadow:0 4px 16px rgba(0,0,0,.35);
}
.skip-link:focus{ transform:translateY(0); }


/* --- O MOMENTO AUTORAL ----------------------------------------------------
   Um momento so, e nao a mesma entrada repetida em toda secao. A tese deste
   portfolio e que design vira numero, entao o unico movimento da pagina e a
   chegada dos numeros, um apos o outro.

   Ease-out exponencial a partir de um estado ja visivel: o estado escondido
   so passa a existir depois que o JS marca .js-reveal na raiz. Sem JS, ou se
   o script falhar, os numeros ja estao la.
   ------------------------------------------------------------------------ */
.js-reveal .reveal-num > *{
  opacity:0;
  transform:translateY(14px);
  transition:opacity 620ms var(--ease-entra),
             transform 620ms var(--ease-entra);
}
.js-reveal .reveal-num.is-in > *{ opacity:1; transform:none; }
.js-reveal .reveal-num.is-in > :nth-child(2){ transition-delay:90ms; }
.js-reveal .reveal-num.is-in > :nth-child(3){ transition-delay:180ms; }
.js-reveal .reveal-num.is-in > :nth-child(4){ transition-delay:270ms; }

/* Na faixa de prova da home o observado é a seção inteira, para o rótulo e os
   números aparecerem juntos: com o observer só no <dl>, o título ficava
   visível sozinho na borda da dobra com um vazio embaixo. */
.js-reveal .reveal-num--faixa > *{ opacity:0; transform:translateY(14px); }
.js-reveal .reveal-num--faixa .prova__item{
  opacity:0; transform:translateY(14px);
  transition:opacity 620ms var(--ease-entra),
             transform 620ms var(--ease-entra);
}
.js-reveal .reveal-num--faixa.is-in > *,
.js-reveal .reveal-num--faixa.is-in .prova__item{ opacity:1; transform:none; }
.js-reveal .reveal-num--faixa.is-in .prova__item:nth-child(2){ transition-delay:90ms; }
.js-reveal .reveal-num--faixa.is-in .prova__item:nth-child(3){ transition-delay:180ms; }
.js-reveal .reveal-num--faixa.is-in .prova__item:nth-child(4){ transition-delay:270ms; }

@media (prefers-reduced-motion: reduce){
  /* nao basta zerar a duracao: sem isto os numeros nasceriam invisiveis e
     dependeriam do observer para aparecer. Aqui ja nascem no estado final. */
  .js-reveal .reveal-num > *,
  .js-reveal .reveal-num--faixa > *,
  .js-reveal .reveal-num--faixa .prova__item{ opacity:1; transform:none; transition:none; }
}

/* --- SUPERFICIES DO NAVEGADOR ---------------------------------------------
   As partes que eu nao desenhei tambem carregam o design. Barra de rolagem,
   sublinhado e cursor de texto vem com o default do navegador, que nao
   pertence a nenhum sistema. Tirar isso do default e o sinal mais barato de
   que a pagina foi construida e nao montada.
   ------------------------------------------------------------------------ */
html{ scrollbar-color:var(--rule-strong) var(--paper); scrollbar-width:thin; }
.anchor{ scrollbar-color:var(--on-anchor-rule) var(--anchor); }

::-webkit-scrollbar{ width:11px; height:11px; }
::-webkit-scrollbar-track{ background:var(--paper); }
::-webkit-scrollbar-thumb{
  background:var(--rule-strong);
  border:3px solid var(--paper);
  border-radius:var(--r-full);
}
::-webkit-scrollbar-thumb:hover{ background:var(--ink-faint); }

/* Sublinhado do sistema, nao o do navegador: afastado da linha de base e
   com espessura propria, para nao cortar as descidas de g, p e q. */
a:not([class]){
  text-decoration-thickness:1px;
  text-underline-offset:.22em;
  text-decoration-color:var(--rule-strong);
  transition:text-decoration-color var(--d-fast) var(--ease);
}
a:not([class]):hover{ text-decoration-color:currentColor; }

html{ caret-color:var(--ink); }

/* --- ENTRADA DO HERO ------------------------------------------------------
   Esta é a parte mais importante da página: se ela não segurar, ninguém rola
   para ver o resto. Três decisões, e cada uma tem um porquê.

   1. A ORDEM É DE IMPORTÂNCIA, NÃO DE POSIÇÃO.
      A frase que carrega a mensagem chega primeiro e sozinha; o resto se monta
      em volta dela. Antes a sequência era de cima para baixo, então o rótulo
      das disciplinas entrava na frente do próprio título.

   2. O RITMO É LENTO O BASTANTE PARA SE LER COMO SEQUÊNCIA.
      Com 65ms entre as peças tudo chegava praticamente junto e a coreografia
      não existia. 130ms é o intervalo em que o olho percebe a ordem.

   3. A CURVA NÃO TEM ARRANQUE.
      Saiu o ease exponencial, que dispara e freia, e entrou uma curva suave.
      Deslocamento de 7px em vez de 10px: o suficiente para haver movimento,
      pouco o bastante para não chamar atenção para si.

   Só opacity e translate: nada que mude o espaço ocupado, senão a página
   salta enquanto carrega. O estado escondido só existe sob .js-reveal, então
   sem JS o hero nasce pronto.

   Por que @keyframes e não transition: a transition depende de o navegador ter
   pintado o estado inicial antes de a classe mudar, e medindo frame a frame a
   opacidade saltava de 0 para 1 no mesmo frame em que .hero-in entrava.
   ------------------------------------------------------------------------ */
@keyframes ha-entra{
  from{ opacity:0; transform:translateY(7px); }
  to  { opacity:1; transform:none; }
}

.js-reveal .ha{ opacity:0; }
.js-reveal .hero-in .ha{
  animation:ha-entra 820ms var(--ease-entra)
            calc(var(--base, 0ms) + var(--i, 0) * 130ms) both;
}

/* Vindo da abertura em vídeo, o texto começa a entrar ANTES de o vídeo sumir:
   os dois se cruzam no meio. Sem essa espera a troca era seca, um sai e o
   outro entra, e era exatamente o que fazia a transição parecer dura. */
.js-reveal .hero.fim-abertura{ --base:360ms; }

@media (prefers-reduced-motion: reduce){
  .js-reveal .ha{ opacity:1; }
  .js-reveal .hero-in .ha{ animation:none; }
}
