/* ==============================================================
   BASE — reset do navegador, tokens de design, tipografia global
   e o sistema de reveal-on-scroll (usado em todas as páginas).
   ============================================================== */

:root {
  --gray-01: #f0f0f0;
  --gray-02: #f2f2f3;
  --gray-03: #cbcbcb;
  --gray-04: #c4c4c4;
  --gray-05: #8a8a8a;
  --gray-06: #606060;
  --gray-07: #232428;
  --orange: #e37c4c;
  --orange-accent: #f18858;
  --white: #ffffff;

  --font-heading: 'Anybody', sans-serif;
  --font-body: 'Exo 2', sans-serif;

  --container-width: 1552px;
  --section-gap: 130px;
  --header-height: 80px;
}

/* ===== Reset ===== */
* { box-sizing: border-box; margin: 0; padding: 0; }

html { scroll-behavior: smooth; }

body {
  font-family: var(--font-body);
  color: var(--gray-07);
  background: var(--white);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

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

::selection {
  background: var(--orange-accent);
  color: var(--white);
}

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

ul { list-style: none; }

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

h1 {
  font-family: 'Anybody';
  font-weight: 700;
  font-size: 60px;
  color: var(--gray-07);
}

h2 {
  font-family: 'Anybody';
  font-weight: 700;
  font-size: 40px;
  color: var(--gray-07);
}

h3 {
  font-family: 'Anybody';
  font-weight: 600;
  font-variation-settings: "wdth" 100;
  color: var(--gray-07);
}

p {
  font-family: 'Exo 2';
  font-weight: 500;
  font-size: 20px;
  color: var(--gray-07);
}

/* ===== Reveal on scroll ===== */
.reveal {
  opacity: 0;
  transform: translateY(32px);
  transition: opacity 0.8s cubic-bezier(0.16, 1, 0.3, 1), transform 0.8s cubic-bezier(0.16, 1, 0.3, 1);
}

.reveal.is-visible {
  opacity: 1;
  transform: translateY(0);
}

/* Mesmo visual de .reveal, mas via @keyframes em vez de transition — pra
   disparar no carregamento da página (sem depender do IntersectionObserver
   detectar scroll), .reveal-instant precisa poder ganhar a própria classe
   e .is-visible juntos, na mesma chamada síncrona (ver script.js: bloco
   do vídeo "Sobre"). Com transition isso não funcionaria: as duas classes
   aplicadas no mesmo instante nunca chegam a pintar o estado "escondido",
   então o navegador não teria de onde animar. Uma @keyframes sempre toca
   sua timeline 0%-100% inteira no momento em que é atribuída, não importa
   quando isso aconteça (mesmo raciocínio do wipe-rise acima). */
.reveal-instant {
  opacity: 0;
  transform: translateY(32px);
}

@keyframes reveal-instant-in {
  to { opacity: 1; transform: translateY(0); }
}

.reveal-instant.is-visible {
  animation: reveal-instant-in 0.8s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}

/* Title wipe: a single static mask around the whole title (all lines
   together), with the text itself — one rigid block, <br>s included —
   rising up from below it. Because the mask's bottom edge is the one doing
   the work, the last line's bottom (its descenders) is the last thing to
   clear it, reading as a cut through the final line. Inspired by the title
   treatment on insany.com.br/quem-somos.
   The mask lives on the inner .wipe-text span, not the observed h1 itself:
   an at-rest state that resolves to a zero-height/fully-clipped box makes
   some browsers report the *observed* element as never intersecting, so
   is-visible would never get added. Keeping the h1's own box unaffected
   avoids that trap. */
.reveal-wipe .wipe-text {
  display: block;
  overflow: hidden;
}

.reveal-wipe .wipe-inner {
  display: block;
  transform: translateY(100%);
}

/* A keyframe animation instead of a transition: "reveal-wipe" (resting,
   hidden) and "is-visible" (revealed) both get added by the same JS
   IntersectionObserver callback, often a frame or two apart — too close
   together for a transition, which only animates a change from whatever
   the *previous rendered frame* showed. A keyframe animation has no such
   dependency: it always plays its own 0%-to-100% timeline in full the
   moment it's assigned, regardless of when that happens. */
@keyframes wipe-rise {
  to { transform: translateY(0); }
}

.reveal-wipe.is-visible .wipe-inner {
  animation: wipe-rise 0.9s cubic-bezier(0.65, 0, 0.35, 1) forwards;
}

/* Hero info block (heading + intro paragraph): the same up-from-below
   rise as the title, applied to the whole block — but unmasked, just a
   plain translate — plus the paragraph's last few words individually
   fade in mid-flight, each .word-fade with its own inline animation-delay,
   staggering them like insany.com.br's intro text. */
.reveal-rise .rise-inner {
  display: flex;
  flex-direction: column;
  gap: 10px;
  transform: translateY(100%);
}

.reveal-rise.is-visible .rise-inner {
  animation: wipe-rise 0.9s cubic-bezier(0.65, 0, 0.35, 1) forwards;
}

.word-fade {
  opacity: 0;
}

@keyframes word-fade-in {
  to { opacity: 1; }
}

.reveal-rise.is-visible .word-fade {
  animation: word-fade-in 0.5s ease-out forwards;
}

.client-logo:nth-child(2) { transition-delay: 0.05s; }
.client-logo:nth-child(3) { transition-delay: 0.1s; }
.client-logo:nth-child(4) { transition-delay: 0.15s; }
.client-logo:nth-child(5) { transition-delay: 0.2s; }
.client-logo:nth-child(6) { transition-delay: 0.25s; }
.client-logo:nth-child(7) { transition-delay: 0.3s; }

/* Conteúdos page: filter tabs reveal one after another instead of together.
   A keyframe animation instead of a transition — like .reveal-wipe above,
   the tabs are already in the initial viewport, so "tab-reveal" (resting)
   and "is-visible" (revealed) get added close enough together that a
   transition could get interrupted before ever painting the hidden state. */
.tab-reveal { opacity: 0; }

@keyframes tab-in {
  from { opacity: 0; transform: translateY(16px); }
  to { opacity: 1; transform: translateY(0); }
}

/* Starts at 0.9s, right after the title finishes settling, then eases in
   more gradually (longer duration, wider spacing, softer curve) than a
   quick pop. */
.tab-reveal.is-visible {
  animation: tab-in 0.6s cubic-bezier(0.16, 1, 0.3, 1) 0.9s forwards;
}

#news-tabs .tab:nth-child(2).is-visible { animation-delay: 1.02s; }
#news-tabs .tab:nth-child(3).is-visible { animation-delay: 1.14s; }
#news-tabs .tab:nth-child(4).is-visible { animation-delay: 1.26s; }
#news-tabs .tab:nth-child(5).is-visible { animation-delay: 1.38s; }
#news-tabs .tab:nth-child(6).is-visible { animation-delay: 1.5s; }

/* Page-load cascade: hero-level content (title, then supporting text/media)
   is already in view when the page loads, so the same reveal-on-scroll
   system fires almost immediately — staggered so it reads top-to-bottom
   instead of popping in all at once, similar to insany.com.br/contato. */
.article-toc,
.article-side,
.contact-lead { transition-delay: 0.1s; }

.page-hero-info.reveal-rise.is-visible .rise-inner { animation-delay: 0.1s; }

.contact-benefits { transition-delay: 0.2s; }
.contact-form-card { transition-delay: 0.15s; }
.contact-direct { transition-delay: 0.3s; }

.about-structure-card:nth-child(2) { transition-delay: 0.05s; }
.about-structure-card:nth-child(3) { transition-delay: 0.1s; }
.about-structure-card:nth-child(4) { transition-delay: 0.15s; }
.about-structure-card:nth-child(5) { transition-delay: 0.2s; }
.about-structure-card:nth-child(6) { transition-delay: 0.25s; }
.about-structure-card:nth-child(7) { transition-delay: 0.3s; }
.about-structure-card:nth-child(8) { transition-delay: 0.35s; }

@media (prefers-reduced-motion: reduce) {
  .reveal, .reveal.is-visible {
    opacity: 1;
    transform: none;
    transition: none;
  }

  .reveal-wipe .wipe-inner {
    transform: none;
  }

  .reveal-wipe.is-visible .wipe-inner {
    animation: none;
    transform: none;
  }

  .reveal-rise .rise-inner {
    transform: none;
  }

  .reveal-rise.is-visible .rise-inner,
  .word-fade {
    animation: none;
    transform: none;
    opacity: 1;
  }

  .tab-reveal, .tab-reveal.is-visible {
    opacity: 1;
    animation: none;
    transform: none;
  }

  .projects-table-row.row-cascade {
    opacity: 1;
    animation: none;
    transform: none;
  }

  .project-tile.tile-cascade {
    opacity: 1;
    animation: none;
    transform: none;
  }

  .project-lightbox,
  .project-lightbox-figure {
    transition: none;
  }
}

/* ===== Reusable pieces ===== */
.eyebrow {
  text-transform: uppercase;
  font-size: 16px;
  color: var(--gray-06);
  border-top: 2px solid var(--gray-06);
  padding-top: 10px;
  padding-bottom: 10px;
  margin-bottom: 32px;
  letter-spacing: 0.02em;
}

