/* ==========================================================================
   MA.ZACHARIAS — portfólio
   HTML + CSS puro + JS vanilla. Sem build, sem dependências externas.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Fontes
   -------------------------------------------------------------------------- */

@font-face {
  font-family: "Inter Tight";
  src: url("../assets/fonts/InterTight-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Inter Tight";
  src: url("../assets/fonts/InterTight-Bold.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

/* --------------------------------------------------------------------------
   2. Tokens
   -------------------------------------------------------------------------- */

:root {
  /* Página branca, texto em crimson e cinza.
     Nem branco puro no fundo nem preto puro em lugar nenhum — o contraste
     levemente rebaixado é o que dá o acabamento. O cinza tem uma pitada de
     vermelho, para não brigar com o crimson. */
  --bg:       #FAFAFA;  /* fundo global */
  --bg-elev:  #E6E4E5;  /* placeholder de mídia antes do load */
  --ink:      #C8102E;  /* crimson — display, títulos, ênfase, ativo */
  --ink-60:   #545454;  /* cinza — leitura e texto secundário */
  --ink-30:   #A8A8A8;  /* cinza claro — numeração, estados desativados */

  /* espaçamento — múltiplos de 8 */
  --s1:  8px;
  --s2:  16px;
  --s3:  24px;
  --s4:  40px;
  --s5:  64px;
  --s6:  96px;
  --s7:  160px;

  --gutter: clamp(1.25rem, 3.5vw, 3rem);
  --header-h: 60px;
  --maxw: 1600px;

  --font: "Inter Tight", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --ease: cubic-bezier(0.16, 1, 0.3, 1);

  color-scheme: light;
}

/* --------------------------------------------------------------------------
   3. Reset
   -------------------------------------------------------------------------- */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* o conteúdo entra por JS: sem reservar a calha, a barra de rolagem
     aparece depois e desloca o header centralizado */
  scrollbar-gutter: stable;
}

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

ul, ol { list-style: none; }

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

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  cursor: pointer;
}

a { color: inherit; text-decoration: none; }

::selection {
  background: var(--ink);
  color: var(--bg);
}

/* --------------------------------------------------------------------------
   4. Base
   -------------------------------------------------------------------------- */

body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font);
  font-size: 0.9375rem;
  font-weight: 400;
  line-height: 1.7;
  letter-spacing: -0.005em;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  padding-top: var(--header-h);
  overflow-x: hidden;
}

:focus-visible {
  outline: 1px solid var(--ink);
  outline-offset: 3px;
}

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

.skip-link {
  position: absolute;
  left: var(--gutter);
  top: 0;
  z-index: 100;
  padding: var(--s1) var(--s2);
  background: var(--ink);
  color: var(--bg);
  font-size: 0.75rem;
  transform: translateY(-150%);
}

.skip-link:focus {
  transform: translateY(calc(var(--header-h) + 8px));
}

.visually-hidden {
  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;
}

/* --------------------------------------------------------------------------
   5. Tipografia
   -------------------------------------------------------------------------- */

.headline {
  font-size: clamp(2.75rem, 7.5vw, 6.5rem);
  font-weight: 700;
  letter-spacing: -0.035em;
  line-height: 0.98;
  text-wrap: balance;
}

/* Cada linha mascarada é um bloco próprio: quebra sozinha no mobile (sem <br>
   para esconder) e sobe com 90ms de atraso em relação à anterior.
   A máscara mora sempre num span interno — se ficasse no próprio h1, o
   padding/margem de compensação sobrescreveria a margem de layout do título. */
.mask { display: block; }

.title-project {
  font-size: clamp(2rem, 5vw, 3.5rem);
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: 1.05;
}

.label {
  font-size: 0.6875rem;
  font-weight: 400;
  letter-spacing: 0.18em;
  line-height: 1;
  text-transform: uppercase;
  color: var(--ink-60);
}

.meta {
  font-size: 0.75rem;
  letter-spacing: 0;
  line-height: 1.6;
}

.body-text {
  max-width: 34em;
}

.body-text + .body-text { margin-top: var(--s3); }

/* Sem sublinhado em lugar nenhum: o afeto do link é a cor. Secundário vai
   para crimson no hover; o que já é crimson recua para o cinza. */
.link {
  transition: color 300ms var(--ease);
}

.link:hover,
.link:focus-visible { color: var(--ink); }

.link-static {
  color: var(--ink);
  transition: color 300ms var(--ease);
}

.link-static:hover,
.link-static:focus-visible { color: var(--ink-60); }

/* --------------------------------------------------------------------------
   6. Header / nav
   -------------------------------------------------------------------------- */

.site-header {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 50;
  height: var(--header-h);
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}

@supports not (background: color-mix(in srgb, red 50%, blue)) {
  .site-header { background: var(--bg); }
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
  height: 100%;
}

.logo,
.nav a {
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1;
}

.nav {
  display: flex;
  align-items: center;
  gap: var(--s3);
}

.nav a {
  color: var(--ink-60);
  transition: color 300ms var(--ease);
}

.nav a:hover,
.nav a:focus-visible,
.nav a[aria-current="page"] { color: var(--ink); }

.nav__social {
  display: flex;
  align-items: center;
  color: var(--ink-60);
  transition: color 300ms var(--ease);
}

.nav__social:hover,
.nav__social:focus-visible { color: var(--ink); }

/* --------------------------------------------------------------------------
   7. Footer
   -------------------------------------------------------------------------- */

.site-footer {
  margin-top: var(--s7);
}

.site-footer__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
  padding-block: var(--s3);
  font-size: 0.75rem;
  line-height: 1.6;
  color: var(--ink-60);
}

.site-footer a { color: var(--ink-60); }

.site-footer a:hover,
.site-footer a:focus-visible { color: var(--ink); }

/* --------------------------------------------------------------------------
   8. Home — headline + grid de trabalhos
   -------------------------------------------------------------------------- */

.hero {
  padding-top: clamp(56px, 9vw, 96px);
  padding-bottom: clamp(64px, 11vw, 120px);
}

.work-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s2);
}

.work-item a,
.lab-item button {
  display: block;
  transition: opacity 500ms var(--ease);
}

/* o cursor isola um trabalho: os outros recuam.
   Sem :has(), nada acontece — o grid só não escurece. */
@media (hover: hover) {
  .work-grid:has(a:hover) a:not(:hover),
  .lab-grid:has(button:hover) button:not(:hover) { opacity: 0.32; }
}

.work-grid:has(a:focus-visible) a:not(:focus-visible),
.lab-grid:has(button:focus-visible) button:not(:focus-visible) { opacity: 0.32; }

.thumb {
  position: relative;
  overflow: hidden;
  background: var(--bg-elev);
  aspect-ratio: 1 / 1;
}

/* camada do parallax: 6% mais alta que o recorte, para sobrar margem
   nas duas pontas do deslocamento */
.thumb__media {
  position: absolute;
  inset: -6% 0;
  transform: translate3d(0, var(--py, 0px), 0);
  will-change: transform;
}

.thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 700ms var(--ease);
}

.work-item a:hover .thumb img,
.work-item a:focus-visible .thumb img { transform: scale(1.03); }

.caption {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s2);
  margin-top: 12px;
}

.caption__title {
  font-size: 0.9375rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.4;
  color: var(--ink-60);
  transition: color 300ms var(--ease);
}

.work-item a:hover .caption__title,
.work-item a:focus-visible .caption__title { color: var(--ink); }

.caption__year {
  font-size: 0.75rem;
  line-height: 1.6;
  color: var(--ink-60);
  font-variant-numeric: tabular-nums;
}

/* Linha de cabeçalho de seção: rótulo à esquerda, contagem à direita.
   É o que dá ao grid um começo declarado em vez de só aparecer. */
.section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s3);
  margin-bottom: var(--s3);
}

.section-head__count { font-variant-numeric: tabular-nums; }

/* Mensagem de erro / estado vazio */
.notice {
  padding-block: var(--s5);
  color: var(--ink-60);
  font-size: 0.9375rem;
}

.notice button {
  color: var(--ink);
  font-weight: 700;
  transition: color 300ms var(--ease);
}

.notice button:hover,
.notice button:focus-visible { color: var(--ink-60); }

/* --------------------------------------------------------------------------
   9. Página de projeto
   -------------------------------------------------------------------------- */

.project {
  padding-top: var(--s5);
}

.back {
  display: inline-block;
  font-size: 0.75rem;
  color: var(--ink-60);
  transition: color 300ms var(--ease);
}

.back:hover,
.back:focus-visible { color: var(--ink); }

.project__head { margin-top: var(--s4); }

.project__title { margin-bottom: var(--s3); }

.project__description {
  max-width: 34em;
  color: var(--ink-60);
}

/* O espaço faz o que a régua fazia: separar a descrição dos créditos. */
.credits {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s3) var(--s5);
  max-width: 52em;
  margin-top: var(--s5);
}

.credit {
  font-size: 0.75rem;
  line-height: 1.6;
}

.credit__role { color: var(--ink-60); }

.credit__name { font-weight: 700; }

.media {
  display: grid;
  gap: var(--s2);
  margin-top: var(--s5);
}

/* O quadro herda a proporção da imagem (o JS preenche --ratio ao carregar).
   O 16:9 é só o espaço reservado enquanto ela não chega. */
.media__frame {
  position: relative;
  background: var(--bg-elev);
  aspect-ratio: var(--ratio, 16 / 9);
  overflow: hidden;
}

/* Enquanto não se sabe se o slot tem arquivo, não pinta o placeholder: um
   slot vazio viraria um retângulo cinza que aparece e some. */
.media__frame.is-loading { background: none; }

.media__frame img,
.media__frame iframe {
  width: 100%;
  height: 100%;
  object-fit: contain;
  border: 0;
}

.media__frame iframe { object-fit: fill; }

/* a mídia entra com um resto de escala, que assenta ao aparecer */
.js .media__frame.reveal img { transform: scale(1.06); }

.js .media__frame.reveal.is-in img {
  transform: none;
  transition: transform 1200ms var(--ease) var(--reveal-delay, 0ms);
}

.project-next {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s3);
  margin-top: var(--s6);
  color: var(--ink-60);
  transition: color 300ms var(--ease);
}

.project-next:hover,
.project-next:focus-visible { color: var(--ink); }

.project-next__title {
  font-size: clamp(1.25rem, 2.5vw, 1.75rem);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.2;
  text-align: right;
}

/* --------------------------------------------------------------------------
   10. About
   -------------------------------------------------------------------------- */

.about {
  max-width: 640px;
  padding-top: var(--s5);
}

.about__section + .about__section { margin-top: var(--s5); }

.about__section > .label { display: block; margin-bottom: var(--s3); }

.about__bilingual + .about__bilingual { margin-top: var(--s4); }

/* Texto corrido fica no cinza: crimson em parágrafo longo cansa a leitura e
   cai para 4,8:1 de contraste. O crimson manda no display e nas ênfases. */
.about__bilingual p { color: var(--ink-60); }

.about__lang {
  display: block;
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  line-height: 1;
  text-transform: uppercase;
  color: var(--ink-60);
  margin-bottom: 12px;
}

/* Lista tabular: os anos alinham numa coluna própria. Sem régua — quem separa
   as linhas é o espaço. */
.table li {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s3);
  padding-block: 10px;
}

.table li:first-child { padding-top: 0; }
.table li:last-child { padding-bottom: 0; }

.table__meta {
  flex: none;
  font-size: 0.75rem;
  line-height: 1.6;
  color: var(--ink-60);
  font-variant-numeric: tabular-nums;
}

.awards li { color: var(--ink-60); }

.school__course {
  font-weight: 700;
  line-height: 1.5;
}

.school__place {
  font-size: 0.75rem;
  line-height: 1.6;
  color: var(--ink-60);
}

.contact li + li { margin-top: var(--s1); }

/* --------------------------------------------------------------------------
   11. Lab
   -------------------------------------------------------------------------- */

.lab-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--s2);
}

.lab-item button {
  display: block;
  width: 100%;
  padding: 0;
  text-align: left;
}

.lab-item .thumb img { transition: transform 700ms var(--ease); }

.lab-item button:hover .thumb img,
.lab-item button:focus-visible .thumb img { transform: scale(1.03); }

.lab-item button:hover .caption__title,
.lab-item button:focus-visible .caption__title { color: var(--ink); }

/* Lightbox */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--gutter);
  background: var(--bg);
  opacity: 0;
  transition: opacity 320ms var(--ease);
}

.lightbox[hidden] { display: none; }

.lightbox.is-open { opacity: 1; }

.lightbox img { transform: scale(0.97); }

.lightbox.is-open img { transform: none; }

.lightbox img {
  transition: transform 620ms var(--ease);
  max-width: min(100%, 1200px);
  max-height: calc(100vh - var(--s6));
  width: auto;
  height: auto;
  object-fit: contain;
}

.lightbox__close {
  position: absolute;
  top: 0;
  right: 0;
  padding: var(--s3) var(--gutter);
  font-size: 0.75rem;
  color: var(--ink-60);
  transition: color 300ms var(--ease);
}

.lightbox__close:hover,
.lightbox__close:focus-visible { color: var(--ink); }

.lightbox__caption {
  position: absolute;
  left: var(--gutter);
  bottom: var(--s3);
  font-size: 0.75rem;
  color: var(--ink-60);
}

body.is-locked { overflow: hidden; }

/* --------------------------------------------------------------------------
   12. 404
   -------------------------------------------------------------------------- */

/* mesmo ritmo vertical da .hero — o 404 não pode ter alinhamento próprio.
   O min-height só empurra o rodapé para baixo em telas altas. */
.error-page {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  min-height: calc(100vh - var(--header-h) - 280px);
  padding-top: clamp(56px, 9vw, 96px);
  padding-bottom: clamp(64px, 11vw, 120px);
}

.error-page p {
  max-width: 34em;
  margin-top: var(--s3);
  color: var(--ink-60);
}

.error-page .link { margin-top: var(--s4); align-self: flex-start; color: var(--ink); }

/* --------------------------------------------------------------------------
   13. Movimento
   -------------------------------------------------------------------------- */


.js .reveal {
  opacity: 0;
  transform: translateY(18px);
}

.js .reveal.is-in {
  opacity: 1;
  transform: none;
  transition:
    opacity 800ms var(--ease) var(--reveal-delay, 0ms),
    transform 800ms var(--ease) var(--reveal-delay, 0ms);
}

/* A headline abre subindo por trás de uma máscara. O padding compensa o
   recorte dos descendentes (o "g" de Design) sem mudar o espaçamento. */
.js .mask {
  overflow: hidden;
  padding-bottom: 0.14em;
  margin-bottom: -0.14em;
}

.js .mask__line {
  display: block;
  transform: translateY(105%);
}

.js .mask.is-in .mask__line {
  transform: none;
  transition: transform 1100ms var(--ease) var(--reveal-delay, 0ms);
}

/* Seta que anda no hover */
.arrow {
  display: inline-block;
  transition: transform 400ms var(--ease);
}

a:hover .arrow,
a:focus-visible .arrow { transform: translateX(4px); }

.back:hover .arrow,
.back:focus-visible .arrow { transform: translateX(-4px); }

/* --------------------------------------------------------------------------
   14. Responsivo
   -------------------------------------------------------------------------- */

@media (max-width: 1024px) {
  .work-grid { grid-template-columns: repeat(2, 1fr); }
  .lab-grid  { grid-template-columns: repeat(3, 1fr); }
}

@media (max-width: 640px) {
  :root { --s7: 96px; }

  .nav { gap: 20px; }
  .nav a { font-size: 0.75rem; }

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

  .credits { grid-template-columns: 1fr; gap: var(--s3); }

  .site-footer__inner {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--s1);
  }

  .project-next { flex-direction: column; gap: var(--s2); }
  .project-next__title { text-align: left; }
}

@media (max-width: 380px) {
  .nav { gap: 14px; }
  .site-header__inner { gap: var(--s2); }
}

@media (min-width: 1921px) {
  .work-grid, .lab-grid { gap: var(--s3); }
}

/* --------------------------------------------------------------------------
   15. Movimento reduzido
   -------------------------------------------------------------------------- */

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

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    transition-delay: 0ms !important;
    scroll-behavior: auto !important;
  }

  .js .reveal,
  .js .reveal.is-in,
  .js .mask__line,
  .js .mask.is-in .mask__line {
    opacity: 1;
    transform: none;
  }

  .js .mask {
    overflow: visible;
    padding-bottom: 0;
    margin-bottom: 0;
  }

  .thumb__media { transform: none; }

  .js .media__frame.reveal img,
  .js .media__frame.reveal.is-in img,
  .work-item a:hover .thumb img,
  .work-item a:focus-visible .thumb img,
  .lab-item button:hover .thumb img,
  .lab-item button:focus-visible .thumb img { transform: none; }

  a:hover .arrow,
  a:focus-visible .arrow,
  .back:hover .arrow,
  .back:focus-visible .arrow { transform: none; }

}

/* --------------------------------------------------------------------------
   16. Impressão
   -------------------------------------------------------------------------- */

@media print {
  body { background: #fff; color: #000; padding-top: 0; }
  .site-header, .site-footer, .project-next { display: none; }

  /* nada pode ficar invisível por causa de animação que não rodou */
  .js .reveal,
  .js .mask__line,
  .js .media__frame.reveal img {
    opacity: 1 !important;
    transform: none !important;
  }

  .js .mask { overflow: visible; }
}
