/* ==========================================================================
   FPR DESIGN — estilos
   Tokens sincronizados com as variáveis do Figma (arquivo FPR_SITE, coleções
   Primary / Color Token — modo Dark — e Fontes). Ver docs/design-system.md.
   ========================================================================== */

/* Archivo (Omnibus-Type, licença OFL — livre pra uso comercial) — fonte
   variável com eixos de peso (400–900) e largura (100–125%): serve de fonte de
   título (font-stretch: --display-stretch) e do rodapé (largura normal). Arquivo
   em assets/fonts/ (recorte latino, 90 KB), sem depender do Google em produção. */
@font-face {
  font-family: "Archivo";
  src: url("../fonts/Archivo-latin-variable.woff2") format("woff2");
  font-weight: 400 900;
  font-stretch: 100% 125%;
  font-style: normal;
  font-display: swap;
}

:root {
  /* Cores — Color Token / modo Dark (Primary: neutral·green·acid) */
  --c-bg: #151717;           /* bg/main */
  --c-bg-subtle: #202222;    /* bg/subtle */
  --c-bg-overlay: #383d3d;   /* bg/overlay */
  --c-border: #4f5555;       /* border/main */
  --c-text-main: #fcffea;    /* text/main */
  --c-text-subtle: #9ea19a;  /* text/subtle */
  --c-text-disable: #777b78; /* text/disable */
  --c-text-highlight: #e5f961; /* text/highlight (acid/500) */
  --c-shape-med: #51685d;      /* shapes/med */
  --c-shape-text: #415149;     /* Color/shaped_fill_text_color — texto sobre fills acid */
  --c-acid: #e5f961;           /* Acid_Green (badges/shapes sólidos) */
  --c-acid-subtle: #f2ff9f;    /* bg/subtle (variante clara do acid, footer/pills) */

  /* Tipografia — Fontes: fontes/display (Archivo, no lugar da Neue Machina) + fontes/text
     (Owners Text via Adobe Fonts — kit pnq4oqg, pesos 300/400/700 + itálicos;
     Inter fica como fallback caso o kit não carregue) */
  --font-text: "owners-text", "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-display: "Archivo", var(--font-text);
  /* Largura da Archivo nos títulos (eixo wdth, 100–125%). 100% = mesma largura
     da Neue Machina (todo o layout foi calibrado nela); 125% (expandida) deixa
     os títulos ~30% mais largos e quebra linha — só subir junto com reajuste
     dos tamanhos. */
  --display-stretch: 100%;
  --font-archia: "Archivo", var(--font-text); /* rodapé (MULTIDESIGN etc.) — largura normal */

  /* Espaçamento */
  --space-1: 0.5rem;
  --space-2: 1rem;
  --space-3: 2rem;
  --space-4: 4rem;
  --space-5: 8rem;

  /* Layout — sem teto de largura: a grade preenche a tela inteira em
     qualquer resolução (só a margem/--edge-pad e o nº de colunas mudam
     por breakpoint). --container-max fica disponível só pra limitar a
     largura de TEXTO longo no futuro (legibilidade), não o shell/grade. */
  --container-max: 1440px;
  --header-h: 107px;

  /* Grid (Figma: node 132-711, style "Grid") — 12 colunas, gutter 0, margem
     30px em 1440px (1440 - 2×30 = 1380 / 12 = 115px/coluna exatas).
     RESPONSIVO: --grid-cols e --edge-pad mudam nos breakpoints abaixo (não
     existe ainda spec de Tablet/Mobile no Figma — valores por convenção,
     recalibrar quando essas páginas chegarem). .container/.grid/.debug-grid
     e os componentes já construídos (header, hero) consomem essas variáveis,
     então respondem sozinhos ao redimensionar. */
  --grid-cols: 12;
  --grid-gutter: 0px;
  --edge-pad: clamp(24px, 2.4vw, 30px); /* desktop: ≥1024px */
}

@media (max-width: 1023px) {
  /* tablet — sem spec do Figma ainda; 8 colunas por convenção */
  :root {
    --grid-cols: 8;
    --edge-pad: clamp(20px, 3vw, 24px);
  }
}

@media (max-width: 639px) {
  /* mobile — sem spec do Figma ainda; 4 colunas por convenção */
  :root {
    --grid-cols: 4;
    --edge-pad: clamp(16px, 5vw, 20px);
  }
}

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: var(--header-h);
}

body {
  margin: 0;
  background: var(--c-bg);
  color: var(--c-text-main);
  font-family: var(--font-text);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

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

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

.container {
  width: 100%;
  padding-inline: var(--edge-pad);
}

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

/* ==========================================================================
   Grid (Figma: 12 colunas, gutter 0, margem 30px — node 132-711)
   Combine com .container: <div class="container grid"> ... </div>
   Filhos usam .col-1 … .col-12 (grid-column: span N) e, se precisar
   deslocar, .col-start-1 … .col-start-13.
   ========================================================================== */

.grid {
  display: grid;
  grid-template-columns: repeat(var(--grid-cols), 1fr);
  column-gap: var(--grid-gutter);
}

.col-1  { grid-column: span 1; }
.col-2  { grid-column: span 2; }
.col-3  { grid-column: span 3; }
.col-4  { grid-column: span 4; }
.col-5  { grid-column: span 5; }
.col-6  { grid-column: span 6; }
.col-7  { grid-column: span 7; }
.col-8  { grid-column: span 8; }
.col-9  { grid-column: span 9; }
.col-10 { grid-column: span 10; }
.col-11 { grid-column: span 11; }
.col-12 { grid-column: span 12; }

.col-start-1  { grid-column-start: 1; }
.col-start-2  { grid-column-start: 2; }
.col-start-3  { grid-column-start: 3; }
.col-start-4  { grid-column-start: 4; }
.col-start-5  { grid-column-start: 5; }
.col-start-6  { grid-column-start: 6; }
.col-start-7  { grid-column-start: 7; }
.col-start-8  { grid-column-start: 8; }
.col-start-9  { grid-column-start: 9; }
.col-start-10 { grid-column-start: 10; }
.col-start-11 { grid-column-start: 11; }
.col-start-12 { grid-column-start: 12; }
.col-start-13 { grid-column-start: 13; }

/* Spans por breakpoint — use quando um item precisa ocupar uma proporção
   diferente da grade reduzida (8 colunas no tablet, 4 no mobile) em vez de
   herdar o span de .col-N. Ex.: <div class="col-4 col-md-4 col-sm-4">
   (metade no desktop-12, metade no tablet-8, largura total no mobile-4). */
@media (max-width: 1023px) {
  .col-md-1 { grid-column: span 1; }
  .col-md-2 { grid-column: span 2; }
  .col-md-3 { grid-column: span 3; }
  .col-md-4 { grid-column: span 4; }
  .col-md-5 { grid-column: span 5; }
  .col-md-6 { grid-column: span 6; }
  .col-md-7 { grid-column: span 7; }
  .col-md-8 { grid-column: span 8; }
}

@media (max-width: 639px) {
  .col-sm-1 { grid-column: span 1; }
  .col-sm-2 { grid-column: span 2; }
  .col-sm-3 { grid-column: span 3; }
  .col-sm-4 { grid-column: span 4; }
}

/* Overlay de debug do grid — tecla G alterna (ver assets/js/main.js).
   Reproduz a grade do Figma: 12 colunas, vermelho 10%, margem = --edge-pad. */
.debug-grid {
  position: fixed;
  inset: 0;
  z-index: 999;
  pointer-events: none;
  display: none;
  padding-inline: var(--edge-pad);
}
.debug-grid.is-visible {
  display: grid;
  grid-template-columns: repeat(var(--grid-cols), 1fr);
  column-gap: var(--grid-gutter);
}
.debug-grid span {
  background: rgba(255, 0, 0, 0.1);
  outline: 1px solid rgba(255, 0, 0, 0.25);
}

/* ==========================================================================
   Hover padrão — glitch de pixel
   Troca Default -> Hover em blocos, não em fade suave: um degradê duro de
   2 cores recortado no texto, deslizando por steps(). Padrão do site para
   qualquer link ou botão de texto (nav, lang-switch, CTAs futuros etc).

   Uso: adicionar a classe .hover-glitch ao elemento. Por padrão troca
   text/main -> text/highlight; para outra combinação, sobrescrever
   --glitch-from / --glitch-to no seletor do componente.
   ========================================================================== */

.hover-glitch {
  --glitch-from: var(--c-text-main);
  --glitch-to: var(--c-text-highlight);

  background-image: linear-gradient(90deg, var(--glitch-to) 50%, var(--glitch-from) 50%);
  background-size: 200% 100%;
  background-position: 100% 0; /* mostra a metade "from" (default) */
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
  transition: background-position 0.28s steps(5, jump-end);
}

.hover-glitch:hover,
.hover-glitch:focus-visible {
  background-position: 0% 0; /* mostra a metade "to" */
}

/* ==========================================================================
   Header
   ========================================================================== */

.site-header {
  /* Não é mais fixo — rola junto com o Hero. A barra compacta (.sticky-bar,
     mais abaixo) assume o posto fixo quando este header sai de cena. */
  position: absolute;
  inset-inline: 0;
  top: 0;
  z-index: 50;
  padding-block-start: 31px;
}

.header-inner {
  width: 100%;
  padding-inline: var(--edge-pad);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 32px;
}

.logo {
  display: flex;
  align-items: center;
  flex-shrink: 0;
}

.logo img {
  width: 152px;
  height: auto;
}

.nav-wrapper {
  display: flex;
  align-items: center;
  gap: clamp(24px, 3vw, 56px);
  min-width: 0;
}

.nav-menu {
  display: flex;
  align-items: center;
  gap: clamp(16px, 5vw, 72px); /* 72px = valor do Figma no frame de 1440px */
  list-style: none;
  margin: 0;
  padding: 0;
}

.nav-link {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  font-family: var(--font-text);
  font-weight: 400;
  font-size: 20px;
  line-height: 24px;
  letter-spacing: -1px;
  white-space: nowrap;
}

.nav-link .slash {
  width: 15px;
  height: 24px;
  flex-shrink: 0;
}

.lang-switch {
  display: flex;
  align-items: center;
  gap: 2px;
  font-size: 12px;
  line-height: 14px;
  letter-spacing: 0.3px;
  flex-shrink: 0;
}

.lang-switch button {
  --glitch-from: var(--c-text-disable);
  --glitch-to: var(--c-text-highlight);

  font: inherit;
  font-family: var(--font-text);
  background-color: transparent; /* não usar o shorthand "background": zeraria o gradiente do .hover-glitch */
  border: 0;
  padding: 0;
  cursor: pointer;
}

.lang-switch button.is-active {
  background-position: 0% 0; /* trava na cor de destaque, sem depender de hover */
}

.lang-switch .sep {
  color: var(--c-text-subtle);
}

/* ==========================================================================
   Barra fixa (Figma node 154:531) — assume o posto do header quando ele sai
   de cena ao rolar. Entrada SEM glitch (fade + rise-up suave, cubic-bezier,
   igual ao .reveal do resto do site) — cada bloco (logo/menu/whats/lang)
   entra em cascata, um de cada vez, em vez do bloco inteiro entrar junto.
   Via `transition` (não `@keyframes`/`.reveal`) porque pode entrar e sair
   várias vezes conforme o usuário rola pra cima/baixo, e uma animação
   `forwards` de uma vez só não reverte de forma limpa. Toggle em main.js.
   ========================================================================== */

.sticky-bar {
  position: fixed;
  top: 15px;
  left: 50%;
  z-index: 60;
  display: flex;
  gap: 3px;
  transform: translateX(-50%);
  pointer-events: none;
}

.sticky-bar.is-visible {
  pointer-events: auto;
}

.sticky-box {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 60px;
  padding: 15px;
  background-color: var(--c-bg-subtle);
  flex-shrink: 0;
  text-decoration: none;
  /* opacity/transform: entrada sem glitch, cada box em cascata (delay por
     classe abaixo) — background-color continua em steps() só pro hover. */
  opacity: 0;
  transform: translateY(28px);
  transition: background-color 0.2s steps(4, jump-end), opacity 0.5s cubic-bezier(0.16, 1, 0.3, 1), transform 0.5s cubic-bezier(0.16, 1, 0.3, 1);
}

.sticky-bar.is-visible .sticky-box {
  opacity: 1;
  transform: translateY(0);
}

.sticky-bar.is-visible .sticky-logo     { transition-delay: 0s, 0s, 0s; }
.sticky-bar.is-visible .sticky-menu     { transition-delay: 0s, 0.08s, 0.08s; }
.sticky-bar.is-visible .sticky-whatsapp { transition-delay: 0s, 0.16s, 0.16s; }
.sticky-bar.is-visible .sticky-lang     { transition-delay: 0s, 0.24s, 0.24s; }

@media (prefers-reduced-motion: reduce) {
  .sticky-box {
    transform: none;
    transition: background-color 0.2s steps(4, jump-end), opacity 0.3s ease;
  }
  .sticky-bar.is-visible .sticky-logo,
  .sticky-bar.is-visible .sticky-menu,
  .sticky-bar.is-visible .sticky-whatsapp,
  .sticky-bar.is-visible .sticky-lang {
    transition-delay: 0s;
  }
}

/* Hover padrão dos boxes da barra fixa (Figma node 153:209): bg/subtle ->
   bg/overlay em blocos, mesma linguagem "sem fade suave" do .hover-glitch,
   aqui em preenchimento sólido. Vale pra todos os boxes (logo/menu/whats/lang). */
.sticky-box:hover,
.sticky-box:focus-visible {
  background-color: var(--c-bg-overlay);
}

.sticky-logo img {
  width: 94px;
  height: auto;
  display: block;
}

.sticky-menu-wrap {
  position: relative;
}

.sticky-menu {
  justify-content: space-between;
  gap: 60px;
  border: 0;
  font: inherit;
  cursor: pointer;
}

/* Rótulo "Menu" (Figma node 154:531, atualizado pelo Felipe): Body/Nav
   agora — era Large Caption (12px/14px/0.3px, igual ao EN/PT). Só o
   `:first-child` (o texto), não o ícone hambúrguer (também um <span>
   dentro do mesmo botão, mas com sua própria regra de tamanho). */
.sticky-menu > span:first-child {
  font-family: var(--font-text);
  font-weight: 400;
  font-size: 20px;
  line-height: 24px;
  letter-spacing: -1px;
  color: var(--c-text-main);
  white-space: nowrap;
}

.sticky-menu-icon {
  position: relative;
  width: 32px;
  height: 32px;
  flex-shrink: 0;
}

.sticky-menu-icon img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  transition: opacity 0.15s steps(4, jump-end);
}

.sticky-menu-icon .is-open {
  opacity: 0;
}

/* Menu aberto: fica na cor de hover mesmo sem o mouse em cima, e troca o
   ícone hambúrguer pelo X (mesma técnica de crossfade por opacidade usada
   no botão "Entre em contato"). */
.sticky-menu[aria-expanded="true"] {
  background-color: var(--c-bg-overlay);
}

.sticky-menu[aria-expanded="true"] .is-closed {
  opacity: 0;
}

.sticky-menu[aria-expanded="true"] .is-open {
  opacity: 1;
}

.sticky-whatsapp img {
  width: 24px;
  height: 24px;
  display: block;
}

/* Submenu do Menu (Figma node 153:492) — entrada SEM glitch (fade + rise-up
   suave, cubic-bezier, igual ao .sticky-box e ao .reveal do resto do site),
   cada item em cascata (delay crescente), disparada por .is-open em main.js. */
.sticky-submenu {
  position: absolute;
  top: calc(100% + 5px);
  left: 0;
  width: 100%;
  display: flex;
  flex-direction: column;
  pointer-events: none;
}

.sticky-submenu.is-open {
  pointer-events: auto;
}

.sticky-submenu-item {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 10px;
  background-color: var(--c-bg-subtle);
  color: var(--c-text-main);
  font-family: var(--font-text);
  font-weight: 400;
  font-size: 10pt; /* era 10px, depois 14pt, 12pt — pedido do Felipe */
  line-height: normal;
  text-transform: uppercase; /* pedido do Felipe */
  white-space: nowrap;
  text-decoration: none;
  opacity: 0;
  transform: translateY(20px);
  transition: background-color 0.2s steps(4, jump-end), opacity 0.5s cubic-bezier(0.16, 1, 0.3, 1), transform 0.5s cubic-bezier(0.16, 1, 0.3, 1);
}

/* Espaço entre os itens em margin-top (não `gap` no flex pai) — o Felipe
   reportou o último item aparecendo separado do bloco; não reproduzi
   (posição final medida sem transição = colada, sem gap), mas `gap` do
   flexbox combinado com `transform`/`transition` por item é um combo com
   histórico de bugs de repintura em alguns navegadores. Margem é mais
   simples/robusta — remove essa variável sem depender de entender a causa exata. */
.sticky-submenu-item + .sticky-submenu-item {
  margin-top: 1px;
}

.sticky-submenu-item:hover,
.sticky-submenu-item:focus-visible {
  background-color: var(--c-bg-overlay);
}

.sticky-submenu.is-open .sticky-submenu-item {
  opacity: 1;
  transform: translateY(0);
}

.sticky-submenu.is-open .sticky-submenu-item:nth-child(1) { transition-delay: 0s, 0s, 0s; }
.sticky-submenu.is-open .sticky-submenu-item:nth-child(2) { transition-delay: 0s, 0.08s, 0.08s; }
.sticky-submenu.is-open .sticky-submenu-item:nth-child(3) { transition-delay: 0s, 0.16s, 0.16s; }

@media (prefers-reduced-motion: reduce) {
  .sticky-submenu-item {
    transform: none;
    transition: background-color 0.2s steps(4, jump-end), opacity 0.2s ease;
  }
  .sticky-submenu.is-open .sticky-submenu-item:nth-child(1),
  .sticky-submenu.is-open .sticky-submenu-item:nth-child(2),
  .sticky-submenu.is-open .sticky-submenu-item:nth-child(3) {
    transition-delay: 0s;
  }
}

/* ==========================================================================
   Hero
   ========================================================================== */

.hero {
  position: relative;
  min-height: 100svh;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  overflow: hidden;
  isolation: isolate;
  padding-bottom: clamp(24px, 4vh, 32px);
  background: var(--c-bg) url("../img/hero.jpg") center / cover no-repeat;
}

.hero-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  will-change: transform; /* parallax no scroll, ver main.js */
}

.hero-title {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  color: var(--c-text-main);
  text-transform: uppercase;
  padding-inline: 20px;
  margin-bottom: clamp(28px, 6.5vh, 67px);
}

.hero-title-sub {
  margin: 0 0 -0.475em;
  font-family: var(--font-display);
  font-stretch: var(--display-stretch);
  font-weight: 400;
  font-size: clamp(24px, 2.9vw, 40px);
  line-height: 1.1;
  letter-spacing: -0.075em;
}

.hero-title-main {
  margin: 0;
  font-family: var(--font-display);
  font-stretch: var(--display-stretch);
  font-weight: 900;
  font-size: clamp(42px, 5.9vw, 80px);
  line-height: 1.16;
  letter-spacing: -0.0375em;
}

.hero-signature {
  position: relative;
  z-index: 1;
  width: 100%;
  padding-inline: var(--edge-pad);
}

.hero-signature img {
  width: 100%;
  height: auto;
}

/* Botão "Entre em contato" (Figma node 139:726, componente Frame 41,
   property1 Default/Hover) — simplificado pelo Felipe: virou um retângulo
   de texto (60px, padding 30) + um quadrado de 20px que pula do topo
   (Default) pro fundo (Hover) do retângulo + a seta, que não muda mais
   de posição, só troca de ícone (2 SVGs, giram 180°/trocam de cor entre
   si — trocados por opacidade em vez de recriados via CSS). O pulo do
   quadrado anima com `transform: translateY(40px)` (delta fixo: 0-20 no
   Default vira 40-60 no Hover). Cores invertem em blocos (steps), sem
   fade suave — mesma linguagem do padrão .hover-glitch, aqui aplicada a
   preenchimento sólido em vez de recorte de texto. */
.hero-contact {
  --tab-bg: var(--c-text-highlight);
  --tab-fg: var(--c-bg);

  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: flex-start;
  align-self: flex-start;
  /* Figma: x=145 no frame 1440 = margem(30) + 1 coluna(115) — desloca 1
     coluna a partir da margem em vez de ficar rente a ela como o logo. */
  margin-inline-start: calc(var(--edge-pad) + (100% - 2 * var(--edge-pad)) / var(--grid-cols));
  margin-bottom: clamp(32px, 8vh, 96px);
  text-decoration: none;
}

.hero-contact-label {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 90px;
  padding: 36px;
  flex-shrink: 0;
  font-family: var(--font-text);
  font-weight: 400;
  font-size: 24px;
  line-height: 29px;
  letter-spacing: 0;
  white-space: nowrap;
  background-color: var(--tab-bg);
  color: var(--tab-fg);
  transition: background-color 0.15s steps(4, jump-end), color 0.15s steps(4, jump-end);
}

.hero-contact-mid {
  width: 24px;
  height: 24px;
  flex-shrink: 0;
  background-color: var(--tab-bg);
  transition: background-color 0.15s steps(4, jump-end), transform 0.15s steps(6, jump-end);
}

.hero-contact-arrow {
  position: relative;
  width: 24px;
  height: 24px;
  margin-top: 24px;
  flex-shrink: 0;
}

.hero-contact-arrow img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  transition: opacity 0.15s steps(4, jump-end);
}

.hero-contact-arrow .is-hover {
  opacity: 0;
}

.hero-contact:hover,
.hero-contact:focus-visible {
  --tab-bg: var(--c-bg-subtle); /* bg/subtle (Dark) */
  --tab-fg: var(--c-text-main); /* text/main (Dark) */
}

.hero-contact:hover .hero-contact-mid,
.hero-contact:focus-visible .hero-contact-mid {
  transform: translateY(48px); /* Big (Figma 139:726): topo 0-24 -> 48-72 */
}

.hero-contact:hover .is-default,
.hero-contact:focus-visible .is-default {
  opacity: 0;
}

.hero-contact:hover .is-hover,
.hero-contact:focus-visible .is-hover {
  opacity: 1;
}

/* Animação de entrada do header + hero — posição Y suave + offset de tempo
   entre os elementos (referência: raviklaassens.com). 100% CSS (keyframes +
   delay), roda sozinha ao carregar, sem depender de JS. Ordem da cascata:
   logo -> nav (4 links) -> idioma -> subtítulo -> título -> assinatura. */
@media (prefers-reduced-motion: no-preference) {
  .reveal {
    opacity: 0;
    transform: translateY(28px);
    animation: reveal-up 1.1s cubic-bezier(0.16, 1, 0.3, 1) forwards;
  }
  .reveal.d1 { animation-delay: 0s; }     /* logo */
  .reveal.d2 { animation-delay: 0.08s; }  /* nav: Trabalhos */
  .reveal.d3 { animation-delay: 0.16s; }  /* nav: Capacidades */
  .reveal.d4 { animation-delay: 0.24s; }  /* nav: Sobre mim */
  .reveal.d5 { animation-delay: 0.32s; }  /* nav: Contato */
  .reveal.d6 { animation-delay: 0.4s; }   /* EN / PT */
  .reveal.d7 { animation-delay: 0.5s; }   /* hero: Entre em contato */
  .reveal.d8 { animation-delay: 0.6s; }   /* hero: Design & Creativity */
  .reveal.d9 { animation-delay: 0.85s; }  /* hero: FOR ALL PURPOSES */
  .reveal.d10 { animation-delay: 1.1s; }  /* hero: assinatura */
}

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

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

/* Versão da animação de entrada acima (mesma distância/easing/duração de
   .reveal) só que disparada ao ROLAR até a seção entrar em vista, em vez de
   ao carregar a página — usada em toda seção abaixo da dobra (Intro,
   Galeria...). Usa `transition` (não `@keyframes`/`animation-delay`) porque
   o gatilho é uma classe adicionada via IntersectionObserver (main.js), não
   o carregamento da página. As classes .d1-.d10 são compartilhadas entre
   seções — cada seção tem seu próprio IntersectionObserver, então a
   cascata de cada uma começa a contar a partir do momento em que ELA
   entra em vista, não do carregamento da página. */
@media (prefers-reduced-motion: no-preference) {
  .reveal-scroll {
    opacity: 0;
    transform: translateY(28px);
    transition: opacity 1.1s cubic-bezier(0.16, 1, 0.3, 1), transform 1.1s cubic-bezier(0.16, 1, 0.3, 1);
  }
  .reveal-scroll.is-inview {
    opacity: 1;
    transform: translateY(0);
  }
  /* footer: deslocamento maior (60px) pra a entrada ser bem perceptível */
  .site-footer .reveal-scroll {
    transform: translateY(60px);
  }
  .site-footer .reveal-scroll.is-inview {
    transform: translateY(0);
  }
  .reveal-scroll.d1 { transition-delay: 0s; }
  .reveal-scroll.d2 { transition-delay: 0.15s; }
  .reveal-scroll.d3 { transition-delay: 0.27s; }
  .reveal-scroll.d4 { transition-delay: 0.42s; }
  .reveal-scroll.d5 { transition-delay: 0.54s; }
  .reveal-scroll.d6 { transition-delay: 0.66s; }
  .reveal-scroll.d7 { transition-delay: 0.78s; }
  .reveal-scroll.d8 { transition-delay: 0.9s; }
  .reveal-scroll.d9 { transition-delay: 1.02s; }
  .reveal-scroll.d10 { transition-delay: 1.14s; }
}

/* ==========================================================================
   Intro — "//:movido pelo design" (Figma: node 69-311, frame "INTRO")
   ========================================================================== */

.intro {
  position: relative;
  background: var(--c-bg);
  padding-block: clamp(56px, 9vw, 128px) clamp(64px, 10vw, 148px);
}

/* Wrapper "fantasma" cobrindo a seção inteira (top:0 a bottom:15px), só pra
   dar ao eyebrow uma área de containing block alta o bastante pro
   position:sticky ter onde "andar" — não afeta o fluxo do resto do conteúdo
   (.container.grid continua em fluxo normal, sem saber que isso existe). */
.intro-eyebrow-wrap {
  position: absolute;
  inset: 0 0 15px 0;
  padding-inline: var(--edge-pad);
  padding-top: 15px; /* posição de repouso (antes do scroll ativar o sticky) já com a margem de 15px */
  z-index: 1;
  pointer-events: none;
}

.intro-eyebrow {
  position: sticky;
  top: 15px;
  margin: 0;
  font-family: var(--font-text);
  font-weight: 400;
  font-size: 12px;
  line-height: 14px;
  letter-spacing: 0.3px;
  color: var(--c-text-highlight);
}

.intro-statement {
  grid-column: 3 / span 8;
  grid-row: 2;
  max-width: 920px;
  justify-self: center;
  margin-top: clamp(40px, 10vw, 130px);
  color: var(--c-text-main);
  font-family: var(--font-text);
  font-weight: 300;
  font-size: clamp(20px, 2.2vw, 32px);
  line-height: 1.3125; /* 42/32 */
}

.intro-statement p {
  margin: 0 0 20px;
}

.intro-statement p:last-child {
  margin-bottom: 0;
}

.intro-icon {
  grid-column: 11 / span 1;
  grid-row: 2;
  align-self: center;
  justify-self: end;
  width: 79px;
  height: auto;
}

.intro-badge {
  grid-column: 1 / -1;
  grid-row: 3;
  justify-self: center;
  margin-top: clamp(48px, 9vw, 120px);
  position: relative;
  width: 226px;
  aspect-ratio: 2 / 1;
}

/* 5 variantes do grafismo "MULTIDESIGN" (texto já embutido no SVG de cada
   uma — Figma FPR_DESIGN_IDV node 2085:53) empilhadas na mesma caixa,
   trocando uma de cada vez conforme o scroll (ver main.js), sem transição —
   troca seca, instantânea. object-fit evita qualquer salto de tamanho entre
   variantes com proporções levemente diferentes. */
.intro-badge img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  opacity: 0;
}

.intro-badge img.is-active {
  opacity: 1;
}

@media (max-width: 1023px) {
  .intro-statement,
  .intro-badge {
    grid-column: 1 / -1;
  }
  .intro-icon {
    display: none; /* decorativo — sem spec de tablet/mobile do Figma ainda */
  }
}

/* ==========================================================================
   Gallery — "Works that say and feel" (Figma: node 101-276, frame "Gallery";
   info card: node 97-178, componente "Frame23")
   ========================================================================== */

.gallery {
  background: var(--c-bg);
  padding-block: clamp(56px, 9vw, 128px) clamp(96px, 12vw, 180px);
}

/* .grid (utilitário) já dá display:grid + as 12/8/4 colunas responsivas —
   aqui só o alinhamento vertical e o espaçamento entre as duas metades. */
.gallery-header {
  align-items: end;
  row-gap: 32px;
  margin-bottom: 30px;
}

.gallery-heading {
  grid-column: 1 / 9;
  display: flex;
  flex-direction: column;
}

.gallery-heading-slash {
  width: 30px;
  height: 48px;
  margin-bottom: -6px; /* mesmo recuo visual do slash no logo/nav */
}

.gallery-heading p {
  margin: 0;
  font-family: var(--font-text);
  font-weight: 400;
  font-size: 24px;
  line-height: 29px;
  color: var(--c-text-main);
}

.gallery-filters {
  grid-column: 9 / -1;
  display: flex;
  align-items: center;
  gap: clamp(24px, 4vw, 63px); /* 63px no Figma (node 92:89) */
}

@media (max-width: 1023px) {
  .gallery-heading,
  .gallery-filters {
    grid-column: 1 / -1;
  }
}

.gallery-mark {
  width: 52px;
  height: 32px;
  flex-shrink: 0;
}

.gallery-filter-list {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 5px;
}

.gallery-filter {
  border: 0;
  padding: 10px;
  font: inherit;
  font-family: var(--font-text);
  font-weight: 400;
  font-size: 12px;
  line-height: 14px;
  white-space: nowrap;
  color: var(--c-text-disable);
  background-color: var(--c-bg-subtle);
  cursor: pointer;
  transition: background-color 0.2s steps(4, jump-end), color 0.2s steps(4, jump-end);
}

.gallery-filter:hover,
.gallery-filter:focus-visible {
  color: var(--c-text-main);
  background-color: var(--c-bg-overlay);
}

.gallery-filter.is-active {
  color: var(--c-bg); /* text/inverse do Figma = mesmo valor de bg/main */
  background-color: var(--c-text-highlight);
  letter-spacing: 0.3px; /* só o estado ativo tem tracking no Figma */
}

.gallery-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr); /* 4 colunas x 2 linhas — 8 itens no HTML (era 3x3/9) */
  column-gap: 30px;
  row-gap: 100px;
  align-items: start;
}

.gallery-item {
  display: flex;
  flex-direction: column;
  gap: 15px;
  text-decoration: none; /* o item vira <a> quando o projeto já tem página própria */
}

.gallery-item-media {
  position: relative;
  width: 100%;
  aspect-ratio: 1 / 1;
  overflow: hidden;
  background: var(--c-bg-subtle);
  /* molduras quadradas em todo breakpoint (pedido do Felipe) — era altura
     aleatória por JS (efeito "masonry" do Figma), removida. */
}

/* Cursor do sistema continua com o formato de seta ao passar sobre a
   moldura, só que preta sólida (pedido do Felipe — 1ª tentativa foi um
   círculo, trocado por uma seta de verdade) — SVG embutido como cursor
   customizado (não dá pra só "pintar" o cursor nativo via CSS puro).
   Hotspot em 0,0 (ponta superior-esquerda da seta), igual ao cursor padrão
   do sistema. Só com mouse de verdade; convive com o botão "Veja mais"
   (.gallery-item-follow), que continua por cima. */
@media (hover: hover) and (pointer: fine) {
  .gallery-item-media {
    cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='22' height='22'%3E%3Cpath d='M0 0 L0 16 L4.5 12.3 L7.2 18.6 L9.7 17.5 L7 11.2 L12.5 11.2 Z' fill='%23000000'/%3E%3C/svg%3E") 0 0, pointer;
  }
}

/* Imagem 50% mais alta que a caixa (25% de sobra em cima/embaixo) pra ter
   margem de sobra pro parallax (main.js) deslocar sem nunca revelar borda
   vazia — a caixa em si (.gallery-item-media) que corta o excesso via
   overflow:hidden. Esse valor tem que bater com GALLERY_PARALLAX_OVERSCAN
   no JS (intensidade do efeito). */
.gallery-item-media img {
  position: absolute;
  top: -25%;
  left: 0;
  width: 100%;
  height: 150%;
  display: block;
  object-fit: cover;
  will-change: transform;
}

/* Botão "Veja mais" que segue o cursor sobre a moldura (pedido do Felipe).
   Posição em `transform: translate3d(...)` escrita via JS a cada
   mousemove — a MESMA propriedade `transform` tem uma transition curta,
   então o botão "persegue" o cursor com um leve atraso suave em vez de
   colar exatamente nele (efeito comum em portfólio, aqui com easing igual
   ao `.reveal-scroll` do resto do site). Opacidade/escala em transition
   própria (entrada/saída), acionadas via `.is-active` no mouseenter/leave
   (ver main.js — a 1ª posição, no mouseenter, pula sem transition pra não
   atravessar animando a moldura inteira vindo do canto). */
.gallery-item-follow {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 110px;
  height: 60px;
  background-color: var(--c-text-highlight); /* acid green */
  color: var(--c-bg);
  font-family: var(--font-text);
  font-weight: 400;
  font-size: 14px;
  line-height: 1.2;
  letter-spacing: 0.3px;
  text-align: center;
  text-transform: uppercase;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  scale: 0.6;
  transition: transform 0.2s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.3s cubic-bezier(0.16, 1, 0.3, 1), scale 0.3s cubic-bezier(0.16, 1, 0.3, 1);
  will-change: transform;
}

.gallery-item-follow.is-active {
  opacity: 1;
  scale: 1;
}

@media (prefers-reduced-motion: reduce), (hover: none), (pointer: coarse) {
  .gallery-item-follow {
    display: none;
  }
}

.gallery-item-info {
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.gallery-item-info h3 {
  margin: 0;
  font-family: var(--font-text);
  font-weight: 400;
  font-size: 32px;
  line-height: 32px;
  color: var(--c-text-main);
}

.gallery-item-tags {
  margin: 0;
  font-family: var(--font-text);
  font-weight: 400;
  font-size: 12px;
  line-height: 14px;
  letter-spacing: 0.3px;
  color: var(--c-text-highlight);
}

.gallery-item-year {
  margin: 0;
  font-family: var(--font-text);
  font-weight: 400;
  font-size: 12px;
  line-height: 14px;
  letter-spacing: 0.3px;
  color: var(--c-text-main);
}

@media (max-width: 1023px) {
  .gallery-grid {
    grid-template-columns: repeat(2, 1fr);
    row-gap: 56px;
  }
}

@media (max-width: 639px) {
  .gallery-grid {
    grid-template-columns: 1fr;
  }
  /* menos imagens no mobile (scroll mais curto): só os 4 primeiros itens */
  .gallery-item:nth-child(n + 5) {
    display: none;
  }
  .gallery-filters {
    width: 100%;
    justify-content: space-between;
  }
}

/* ==========================================================================
   Capacidades — "Art Direction" (Figma: node 103-297, "Frame 32")
   ========================================================================== */

/* Trilho de scroll: alto o bastante pra segurar o "palco" (.capabilities)
   travado na tela por um tempo de leitura enquanto o usuário rola, antes de
   soltar e seguir o scroll normal — 100% via `position:sticky`, sem
   interceptar o scroll nem chamar scrollTo() (a técnica de JS que travou
   o site antes NUNCA MAIS — ver memória do projeto). O ciclo de texto
   (main.js) só LÊ a posição via getBoundingClientRect, mesmo padrão seguro
   do parallax/badge/sticky-bar. 450vh de trilho = 100vh/150vh/200vh por
   palavra (Art Direction / Branding / 3D & Motion — Branding ganhou um
   pouco mais, 3D & Motion fica com o dobro do tempo de Art Direction,
   porque a seção "Sobre mim" sobe cobrindo Capacidades logo depois —
   ver CAPABILITIES_SEGMENTS_VH em main.js, os dois têm que somar o mesmo
   total se mudar). */
.capabilities-pin {
  position: relative;
  height: calc(min(1250px, 100vh) + 450vh);
}

.capabilities {
  position: sticky;
  top: 0;
  height: min(1250px, 100vh);
  background-color: var(--c-bg);
  overflow: clip;
  /* sem padding-block: título e case agora são position:absolute com
     top em %, não dependem mais do fluxo/padding pra se posicionar. */
}

/* Padrão de pontos do Figma (node 174:588) — fill nativo do Figma, sem
   asset exportável; recriado em CSS puro (radial-gradient repetido) em vez
   de baixar como imagem. Elemento PRÓPRIO (não é mais background direto de
   .capabilities) pra poder ter animação de entrada e parallax de mouse
   independentes do resto — desloca via `background-position` no lugar de
   `transform` (transform moveria o retângulo inteiro incluindo a borda,
   background-position desliza só o padrão dentro dele, sem revelar bordas).
   Nunca usar o shorthand `background` aqui: zeraria esse background-image
   (mesma armadilha já documentada com .lang-switch button). */
.capabilities-dots {
  position: absolute;
  inset: -20px; /* folga pro parallax nunca revelar borda sem padrão */
  pointer-events: none;
  background-image: radial-gradient(circle, rgba(255, 255, 255, 0.12) 2px, transparent 2px);
  background-size: 28px 28px;
}

/* Fotos/quadrado decorativos flutuando atrás do título — posição em % do
   frame Figma (1440px de referência), sem spec de tablet/mobile ainda
   (escondidos em telas pequenas, mesma convenção do .intro-icon). */
.capabilities-decor {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.capabilities-decor-01,
.capabilities-decor-02,
.capabilities-decor-dot {
  /* left/top: transição suave ao trocar de palavra (data-cap-index em
     .capabilities, ver main.js). O parallax de mouse usa `transform` à
     parte (via JS, sem transition — precisa reagir na hora), então os
     dois efeitos não brigam entre si. */
  transition: left 0.6s cubic-bezier(0.16, 1, 0.3, 1), top 0.6s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.28s ease;
}

/* Fade da troca de imagem a cada título (main.js, capSwapImages). */
.capabilities-decor-01.is-swapping,
.capabilities-decor-02.is-swapping,
.capabilities-case-media img.is-swapping {
  opacity: 0;
}
.capabilities-case-media img {
  transition: opacity 0.28s ease;
}

.capabilities-decor-01 {
  position: absolute;
  left: 49.93%;
  top: clamp(90px, 17.36vw, 250px);
  width: clamp(160px, 24.31vw, 350px);
  aspect-ratio: 350 / 232;
  object-fit: cover;
}

.capabilities-decor-02 {
  position: absolute;
  left: 69.93%;
  top: clamp(60px, 13.06vw, 188px);
  width: clamp(64px, 8.61vw, 124px);
  aspect-ratio: 1 / 1;
  object-fit: cover;
}

.capabilities-decor-dot {
  position: absolute;
  left: 12.64%;
  top: clamp(120px, 24.79vw, 357px);
  width: clamp(12px, 1.74vw, 25px);
  aspect-ratio: 1 / 1;
  background: var(--c-text-highlight);
}

/* Posições alternativas dos 3 decorativos por palavra do ciclo (0=Art
   Direction, o padrão acima; 1=Branding; 2=3D & Motion) — sem spec do
   Figma pras palavras 2 e 3 (só "Art Direction" foi desenhada até agora),
   valores estimados pra dar variedade visual a cada troca. Ajustar se/quando
   o Felipe mandar posições reais. */
.capabilities[data-cap-index="1"] .capabilities-decor-01 {
  left: 14%;
  top: clamp(70px, 15vw, 220px);
}
.capabilities[data-cap-index="1"] .capabilities-decor-02 {
  left: 82%;
  top: clamp(150px, 21vw, 300px);
}
.capabilities[data-cap-index="1"] .capabilities-decor-dot {
  left: 58%;
  top: clamp(50px, 10vw, 150px);
}

.capabilities[data-cap-index="2"] .capabilities-decor-01 {
  left: 74%;
  top: clamp(150px, 22vw, 320px);
}
.capabilities[data-cap-index="2"] .capabilities-decor-02 {
  left: 16%;
  top: clamp(50px, 9vw, 140px);
}
.capabilities[data-cap-index="2"] .capabilities-decor-dot {
  left: 42%;
  top: clamp(210px, 29vw, 390px);
}

.capabilities-heading {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 100%;
  transform: translate(-50%, -50%);
  z-index: 1;
  text-align: center;
}

/* .reveal-scroll sozinho usa só translateY(28px) — aqui teria que "brigar"
   com o translate(-50%,-50%) de centralização acima (transform não é
   propriedade que soma entre duas regras, só uma vence). Junta os dois
   numa declaração só, por cima da regra genérica (2 classes = mais
   específico), mantendo a centralização E adicionando o rise-up. */
.capabilities-heading.reveal-scroll {
  transform: translate(-50%, calc(-50% + 28px));
}
.capabilities-heading.reveal-scroll.is-inview {
  transform: translate(-50%, -50%);
}

/* Título único — o ciclo (Art Direction / Branding / 3D & Motion) troca o
   textContent direto via JS, letra por letra, tipo "scramble" (ver
   scrambleText em main.js). Sem empilhamento/crossfade — mais simples. */
.capabilities-title {
  margin: 0;
  font-family: var(--font-display);
  font-stretch: var(--display-stretch);
  font-weight: 400;
  font-size: clamp(36px, 12.5vw, 180px); /* piso 36 (era 48): "ART DIRECTION" estourava telas de ~340px */
  line-height: 0.644; /* 116/180 do Figma */
  letter-spacing: -0.017em; /* -3px/180px */
  text-transform: uppercase;
  color: var(--c-text-main);
  font-variant-numeric: tabular-nums; /* números com largura fixa — some com o "tremor" de largura do scramble */
}

/* "DIREÇÃO DE ARTE" tem ~8,6em de largura (vs ~7,7em de "ART DIRECTION"): com
   12.5vw ela passaria de 100vw e quebraria em 2 linhas. Em português o corpo
   escala com 10.4vw (≈90vw de largura) — no teto de 180px (≥1731px) é o mesmo
   tamanho de antes. */
html[lang="pt-BR"] .capabilities-title {
  font-size: clamp(36px, 10.4vw, 180px);
}

@media (prefers-reduced-motion: reduce) {
  .capabilities-pin {
    height: auto;
  }
  .capabilities {
    position: static;
    height: auto;
    min-height: min(1250px, 100vh);
  }
  /* Sem Capacidades travada (acima virou position:static), o margin-top
     negativo de #sobre (ver style.css, seção Sobre mim) sobreporia o fim
     do conteúdo ESTÁTICO dela de verdade, escondendo conteúdo de forma
     permanente — não só durante uma transição de scroll. Desativado aqui. */
  .sobre {
    margin-top: 0;
  }
}

.capabilities-tag {
  position: absolute;
  left: 26.04%;
  top: 34%;
  padding: clamp(10px, 1.39vw, 20px);
  background-color: var(--c-text-highlight);
  color: var(--c-bg);
  font-family: var(--font-text);
  font-weight: 400;
  font-size: clamp(14px, 1.67vw, 24px);
  line-height: 1.21;
  white-space: nowrap;
}

.capabilities-case {
  position: absolute;
  left: 0;
  right: 0;
  /* 835/1257 do Figma — não depende mais do fluxo do heading. min(): em telas
     baixas (ex.: 768px de altura) o parágrafo mais longo (Branding, ~300px
     de bloco) passava do fim da seção e era cortado; aí o bloco sobe o
     suficiente pra caber, com ~40px de respiro embaixo. */
  top: min(66.43%, calc(100% - 344px));
  z-index: 1;
}

/* Livre pela seção INTEIRA (não mais um item de flex preso perto da borda
   esquerda) — posicionado com left/top em % relativas a .capabilities, igual
   aos decorativos, pra poder "viajar" pra qualquer parte do palco a cada
   troca de palavra (pedido do Felipe: "use a div inteira de sessão
   capacidade como área"). left/top mudam DIRETO, sem transition de
   propósito (pedido anterior: "não precisa ter a interpolação... pode ser
   direto") — ver regras data-cap-index abaixo. */
.capabilities-case-media {
  position: absolute;
  left: 8%;
  top: 64%;
  width: clamp(280px, 32vw, 464px);
  aspect-ratio: 464 / 261;
  overflow: hidden;
  z-index: 1;
}

/* Sem spec do Figma pras palavras 2/3 (só "Art Direction" foi desenhada) --
   valores estimados, espalhados pela seção pra dar variedade real. */
.capabilities[data-cap-index="1"] .capabilities-case-media {
  left: 54%;
  top: 12%;
}
.capabilities[data-cap-index="2"] .capabilities-case-media {
  left: 30%;
  top: 74%;
}

/* A img fica 20px maior que a caixa em todo lado (overscan) porque o
   parallax de mouse (main.js) translada ela até ~18px — sem essa folga,
   o deslocamento revelaria borda vazia. Mesmo padrão já usado no
   parallax do Hero/Galeria. Esse `transform` é só do parallax de mouse —
   não tem nada a ver com o left/top de reposicionamento por palavra acima
   (são propriedades diferentes, num elemento diferente do wrapper), então
   os dois efeitos não brigam. */
.capabilities-case-media img {
  display: block;
  position: absolute;
  inset: -20px;
  width: calc(100% + 40px);
  height: calc(100% + 40px);
  object-fit: cover;
}

/* "não muda de lugar": ao contrário da foto do case (que passeia pela
   seção, ver .capabilities-case-media), esse texto fica fixo — não tem
   nenhuma regra data-cap-index pra ele. Encaixado na grade de 12 colunas
   do site (.capabilities-case ganhou a classe .grid), começando na 9ª
   coluna até a borda direita. Em telas menores (--grid-cols vira 8/4) a
   coluna 9 não existe mais, então volta pra ocupar a largura toda. */
.capabilities-case-info {
  grid-column: 9 / -1;
  max-width: 351px;
  display: flex;
  flex-direction: column;
  gap: 20px;
  color: var(--c-text-main);
}

@media (max-width: 1023px) {
  .capabilities-case-info {
    grid-column: 1 / -1;
  }
}

.capabilities-case-title {
  margin: 0;
  font-family: var(--font-text);
  font-weight: 400;
  font-size: 32px;
  line-height: 1;
}

.capabilities-case-text {
  margin: 0;
  font-family: var(--font-text);
  font-weight: 300; /* era 400 — pedido do Felipe (Body/Small mais leve em todo o site) */
  font-size: 20px;
  line-height: 1.2;
  letter-spacing: 0.5px;
}

/* Reentrada do subtítulo/parágrafo quando a palavra do ciclo troca
   (main.js adiciona .is-changing) — fade + subida curta, mesma curva do
   resto do site. */
.capabilities-case-title.is-changing,
.capabilities-case-text.is-changing {
  animation: capCaseIn 0.6s cubic-bezier(0.16, 1, 0.3, 1) both;
}
.capabilities-case-text.is-changing {
  animation-delay: 0.08s;
}
@keyframes capCaseIn {
  from { opacity: 0; transform: translateY(14px); }
  to { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .capabilities-case-title.is-changing,
  .capabilities-case-text.is-changing { animation: none; }
}

@media (max-width: 767px) {
  .capabilities-decor {
    display: none; /* decorativo — sem spec de mobile ainda */
  }
  .capabilities-tag {
    position: static;
    display: inline-block;
    margin-top: 16px;
  }
  /* O "passeio" livre pela seção (left/top variando por palavra) é coisa de
     tela larga — em mobile trava numa posição central segura, mesma pra
     qualquer palavra, pra não sobrepor o heading nem estourar a largura
     estreita (sem spec de mobile pra esse comportamento ainda). */
  .capabilities-case-media,
  .capabilities[data-cap-index="1"] .capabilities-case-media,
  .capabilities[data-cap-index="2"] .capabilities-case-media {
    left: 50%;
    top: 64%;
    transform: translate(-50%, 0);
    width: min(80%, 350px);
  }
}

/* ==========================================================================
   Sobre mim (Figma: node 123-324, "Frame 37")
   ========================================================================== */

/* "Ao fazer scroll essa sessão vai sobrepor a de capacidade": sticky+z-index
   maior que o resto da página. TESTADO com scroll simulado e MEDIDO com
   getBoundingClientRect a cada passo: a 1ª versão (só sticky+z-index, sem
   margin-top negativo) NÃO criava sobreposição de verdade — o bottom de
   `.capabilities` e o top de `#sobre` ficavam sempre EXATAMENTE colados
   (nunca sobrepostos), porque o "empurrão" nativo do sticky (que nunca
   deixa um elemento sticky passar do fundo do próprio container) fazia
   Capacidades DESLIZAR pra fora rolando normalmente ENQUANTO Sobre também
   ainda não tinha travado (só travava depois que Capacidades já tinha
   saído inteira da tela) — era uma transição comum de scroll, sem
   cobrir nada.
   CORRIGIDO com `margin-top` NEGATIVO igual à altura travada de
   Capacidades (`min(1250px,100vh)`, mesma fórmula usada lá) — puxa a
   posição "natural" de #sobre pra cima, fazendo ela travar no topo
   EXATAMENTE no instante em que Capacidades começaria a deslizar (ainda
   travada, não rolando) — nesse momento Sobre (z-index maior, fundo
   opaco) cobre Capacidades por cima, em vez de esperar ela sair rolando
   primeiro. Sem essa margem, a técnica de "só sticky" não basta pra criar
   sobreposição visível — é um resultado matemático do jeito que
   position:sticky calcula onde travar, não um detalhe estético.
   CONFIRMADO pelo Felipe (comparando com o protótipo): essa seção usa
   mesmo o fundo CLARO do Figma (bg/main #d4d4d4 = modo "Light" da coleção
   Color Token) — não o Dark do resto do site, de propósito (contraste
   proposital). --sobre-bg/--sobre-text são LOCAIS (só existem dentro de
   .sobre), não mexem nos tokens globais --c-bg/--c-text-main usados no
   resto do site. */
.sobre {
  --sobre-bg: #d4d4d4;
  --sobre-text: #151717;
  position: sticky;
  top: 0;
  z-index: 2;
  /* puxa a posição de trava pra cima em 1 "altura travada" de Capacidades —
     ver explicação grande acima. Mesma fórmula de .capabilities (style.css). */
  margin-top: calc(-1 * min(1250px, 100vh));
  background-color: var(--sobre-bg);
  /* padding-top: max(...) garante um mínimo de 100px mesmo em telas onde o
     clamp(56px,9vw,128px) resolveria pra menos — a barra fixa (.sticky-bar)
     é position:fixed, top:15px, height:60px (termina em 75px), com
     z-index:60 (bem acima do z-index:2 dessa seção). Como .sobre gruda no
     topo (top:0) assim que chega, sem esse piso o eyebrow (1º conteúdo,
     logo depois do padding) ficava ESCONDIDO atrás da barra fixa em telas
     onde o clamp resolvia abaixo de ~75px — não estava quebrado, só
     coberto (confirmado comparando com o protótipo do Figma). */
  padding-top: max(clamp(56px, 9vw, 128px), 100px);
  padding-bottom: clamp(96px, 12vw, 180px);
}

.sobre-eyebrow {
  display: flex;
  flex-direction: column;
  margin-bottom: clamp(32px, 5vw, 64px);
}

.sobre-eyebrow-slash {
  width: 30px;
  height: 48px;
  margin-bottom: -6px; /* mesmo recuo visual do slash no logo/nav/galeria */
}

.sobre-eyebrow p {
  margin: 0;
  font-family: var(--font-text);
  font-weight: 400;
  font-size: 24px;
  line-height: 29px;
  color: var(--sobre-text);
}

.sobre-content {
  align-items: start;
  row-gap: 40px;
}

/* Foto: grid-column 1/6 = 5 colunas ~ 575px em 1440 (Figma: box 576x576,
   left:30 = margem, bate quase exato). overflow:visible de propósito — o
   quadrado do shader (abaixo) sai um pouco da borda direita/inferior da
   foto no Figma (não fica contido), então quem recorta é o FRAME interno
   (.sobre-photo-frame), não esse wrapper. */
.sobre-photo {
  grid-column: 1 / 6;
  position: relative;
  aspect-ratio: 1 / 1;
  overflow: visible;
}

.sobre-photo-frame {
  position: absolute;
  inset: 0;
  overflow: hidden;
}

/* CORRIGIDO: a versão anterior usava width/height do Figma como duas
   porcentagens INDEPENDENTES (188.12%/125.43%) sem `object-fit` — isso só
   funciona sem distorcer se a imagem local tiver EXATAMENTE a proporção
   que o Figma pressupôs ao calcular esses números (a partir do asset
   interno DELE). A foto que o Felipe colocou na pasta é 16:9 (1920x1080),
   proporção DIFERENTE — esticava a imagem (achatada/puxada). `object-fit:
   cover` com uma única imagem preenche a caixa quadrada sem NUNCA
   distorcer, seja qual for a proporção real do arquivo. */
/* inset:-16px/overscan: a foto principal agora também tem um parallax de
   mouse SUTIL (pedido do Felipe) — sem essa folga, `object-fit:cover`
   preenche a caixa exatamente, sem sobra, e qualquer deslocamento
   revelaria borda vazia. 120px > mouse (8px) + parallax de scroll (±100px,
   via a propriedade `translate`, independente do `transform` do mouse). */
.sobre-photo-frame img {
  display: block;
  position: absolute;
  inset: -120px;
  width: calc(100% + 240px);
  height: calc(100% + 240px);
  max-width: none; /* o reset global img{max-width:100%} capava a largura e deixava um vazio à direita da foto */
  object-fit: cover;
  object-position: 50% 22%;
}

/* Quadrado menor com a foto processada (Figma tinha um shader WebGPU de
   "gradient map" mapeando a luminância da foto pra um degradê amarelo —
   recurso só de preview do Figma, precisa de WebGPU, não dá pra portar pra
   um site estático de verdade; o Felipe já mandou o resultado do shader
   PRÉ-RENDERIZADO como imagem (sobre-photo-shader.jpg), então só recorto
   ele igual à foto principal). Posição em % relativa ao PRÓPRIO .sobre-photo
   (576×576 no Figma): left 453/576=78.65%, top 434/576=75.35%,
   tamanho 223/576=38.72%. */
.sobre-photo-shader {
  position: absolute;
  left: 78.65%;
  top: 75.35%;
  width: 38.72%;
  aspect-ratio: 1 / 1;
  overflow: hidden;
  z-index: 1;
}

/* Mesma correção do frame principal (object-fit em vez de width/height %
   independentes) — o zoom extra (bem mais fechado que a foto grande, só
   olho/nariz/boca no Figma) vem de um `transform:scale()` UNIFORME por
   cima do cover, que nunca distorce (escala X e Y igualmente). */
.sobre-photo-shader img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 15%;
  transform: scale(2.6);
  transform-origin: 50% 20%;
}

/* Texto: grid-column 9/-1 (pedido do Felipe — mesma coluna usada no texto
   do case/Capacidades e no filtro da Galeria, pra alinhar as 3 seções) até
   a borda — max-width replica os 455px do Figma sem travar num número
   exato de colunas. */
.sobre-text {
  grid-column: 9 / -1;
  max-width: 455px;
  /* precisa ficar ACIMA da faixa de palavras-chave (.sobre-marquee,
     z-index:1) — ela cruza por cima da foto de propósito (decorativo,
     como no Figma) mas não pode tampar o texto de baixo dela (o botão
     "Baixa CV" saiu daqui, ver .sobre-cv — precisava da MESMA referência
     de posição do carrossel pra nunca se sobrepor em nenhuma largura). */
  position: relative;
  z-index: 2;
}

.sobre-title {
  margin: 0 0 20px;
  font-family: var(--font-display);
  font-stretch: var(--display-stretch);
  font-weight: 400;
  font-size: clamp(28px, 2.9vw, 40px);
  line-height: 1.1;
  letter-spacing: -0.075em;
  text-transform: uppercase;
  color: var(--sobre-text);
}

.sobre-bio {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.sobre-bio p {
  margin: 0;
  font-family: var(--font-text);
  font-weight: 300; /* era 400 — pedido do Felipe (Body/Small mais leve em todo o site) */
  font-size: 20px;
  line-height: 1.2;
  letter-spacing: 0.5px;
  color: var(--sobre-text);
}

/* Botão "Baixa CV" (Figma node 195:635) — MESMA instância de componente do
   .hero-contact (os data-node-id internos batem: I195:635;139:714 etc. são
   o mesmo "Frame 41" do botão "Entre em contato"), só texto/ícone
   diferentes — reaproveita a estrutura e as cores EXATAS (--c-text-highlight
   / --c-bg são tokens globais, não os --sobre-* locais, porque o botão do
   Figma já resolve pro mesmo verde-ácido/escuro do resto do site
   independente da seção). O ícone que o Figma exportou pra esse botão era
   BYTE-IDÊNTICO ao contact-arrow-default.svg do Hero (confirmado com
   `diff`) — então o hover reaproveita os MESMOS 2 arquivos do Hero
   (contact-arrow-default/-hover.svg) com a MESMA técnica de crossfade por
   opacidade, garantindo comportamento idêntico (pedido do Felipe, ver
   .sobre-cv-icon abaixo).
   Falta o PDF de verdade em assets/docs/ — o href é só um caminho
   esperado, ainda não existe o arquivo; avisar o Felipe. */
/* Posicionado com a MESMA referência de coordenadas do carrossel
   (.sobre-marquee, filho direto de .sobre) — não mais "margin-top depois
   da bio". Motivo (bug real reportado pelo Felipe com screenshot): com
   `margin-top` fixo, o botão só limpava a faixa na largura em que eu
   testei (1440px) — em telas mais largas a faixa desce mais (seu
   `top:67.5%` é relativo à altura de .sobre, que cresce com a largura,
   já que a foto quadrada fica maior), mas a margem fixa do botão não
   acompanhava, e eles voltavam a se sobrepor. Corrigido saindo de dentro
   de .sobre-text e virando filho direto de .sobre, com `left`/`top`
   calculados a partir da MESMA base % — os dois agora escalam juntos em
   qualquer largura. left replica "começa na 9ª coluna" (mesma fórmula já
   usada no botão "Entre em contato" do Hero, só com índice 8 em vez de 1
   coluna). top = 67.5% (igual ao carrossel) + 70px (folga: a faixa tem no
   máximo ~44px de altura, clamp(28px,2.9vw,40px)*1.1 de line-height, então
   70px sempre sobra). */
.sobre-cv {
  --tab-bg: var(--c-text-highlight);
  --tab-fg: var(--c-bg);

  position: absolute;
  left: calc(var(--edge-pad) + (100% - 2 * var(--edge-pad)) * 8 / var(--grid-cols));
  top: calc(67.5% + 90px); /* acompanha a faixa (+20px) em ≥1536px */
  z-index: 2;
  display: inline-flex;
  align-items: flex-start;
  text-decoration: none;
}

.sobre-cv-label {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 90px;
  padding: 36px;
  flex-shrink: 0;
  font-family: var(--font-text);
  font-weight: 400;
  font-size: 24px;
  line-height: 29px;
  letter-spacing: 0;
  white-space: nowrap;
  background-color: var(--tab-bg);
  color: var(--tab-fg);
  transition: background-color 0.15s steps(4, jump-end), color 0.15s steps(4, jump-end);
}

.sobre-cv-mid {
  width: 24px;
  height: 24px;
  flex-shrink: 0;
  background-color: var(--tab-bg);
  transition: background-color 0.15s steps(4, jump-end), transform 0.15s steps(6, jump-end);
}

/* Ícone: DUPLICADO do componente do Hero de propósito, pra garantir
   consistência 1:1 (pedido do Felipe) — em vez de aproximar o efeito só
   com CSS (scaleX, tentativa anterior), reaproveita os MESMOS 2 arquivos
   do .hero-contact-arrow (contact-arrow-default.svg/-hover.svg — o
   download-arrow.svg que eu tinha baixado do Figma pro "Baixa CV" era
   BYTE-IDÊNTICO ao contact-arrow-default.svg, confirmado com `diff`,
   então nem precisou criar asset novo) com a MESMA técnica de crossfade
   por opacidade, não um transform CSS aproximando o resultado. */
.sobre-cv-icon {
  position: relative;
  width: 24px;
  height: 24px;
  margin-top: 24px;
  flex-shrink: 0;
}

.sobre-cv-icon img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  transition: opacity 0.15s steps(4, jump-end);
}

.sobre-cv-icon .is-hover {
  opacity: 0;
}

.sobre-cv:hover,
.sobre-cv:focus-visible {
  --tab-bg: var(--c-bg-subtle); /* bg/subtle (Dark) */
  --tab-fg: var(--c-text-main); /* text/main (Dark) */
}

.sobre-cv:hover .sobre-cv-mid,
.sobre-cv:focus-visible .sobre-cv-mid {
  transform: translateY(48px); /* Big (Figma 139:726): topo 0-24 -> 48-72 */
}

.sobre-cv:hover .is-default,
.sobre-cv:focus-visible .is-default {
  opacity: 0;
}

.sobre-cv:hover .is-hover,
.sobre-cv:focus-visible .is-hover {
  opacity: 1;
}

/* Faixa de palavras-chave rolando sem parar (Figma node 195:620) —
   full-bleed (ignora o padding do .container, sai da margem lateral dos
   dois lados) sobrepondo a parte de baixo da foto, mesma posição do
   Figma (~67.5% da altura da foto). Conteúdo duplicado 2x no HTML pra
   loop contínuo sem "salto": anima só a 1ª metade (translateX(-50%)),
   quando a 2ª metade (idêntica) chega no lugar da 1ª, reinicia sem
   ninguém notar. */
.sobre-marquee {
  position: absolute;
  left: 0;
  right: 0;
  /* Era 67.5% - 50px (subiu 50px, pedido do Felipe). Com a bio nova, mais
     longa, a faixa cruzava o texto em ≥1536px: agora 67.5% + 20px (só vale
     ≥1536px — abaixo disso os blocos @media mais embaixo sobrescrevem). */
  top: calc(67.5% + 20px);
  overflow: hidden;
  pointer-events: none;
  z-index: 1;
}

.sobre-marquee-track {
  display: flex;
  align-items: center;
  gap: 32px;
  width: max-content;
  animation: sobre-marquee-scroll 32s linear infinite;
}

.sobre-marquee-item {
  font-family: var(--font-display);
  font-stretch: var(--display-stretch);
  font-weight: 400;
  font-size: clamp(28px, 2.9vw, 40px);
  line-height: 1.1;
  letter-spacing: -0.075em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--c-text-subtle); /* neutral/400 #9ea19a, mesmo em cima do fundo claro */
}

.sobre-marquee-dot {
  width: 6px;
  height: 6px;
  flex-shrink: 0;
  background-color: var(--c-text-main); /* --white #fcffea no Figma */
}

@keyframes sobre-marquee-scroll {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(-50%);
  }
}

@media (prefers-reduced-motion: reduce) {
  .sobre-marquee-track {
    animation: none;
  }
}

@media (max-width: 1023px) {
  .sobre-photo,
  .sobre-text {
    grid-column: 1 / -1;
  }
  .sobre-text {
    max-width: none;
  }
  /* No desktop a foto tem espaço sobrando à direita (fica ao lado do
     texto), então o quadrado do shader pode sobrar 17% pra fora da caixa
     sem problema (overflow:visible acima). Aqui a foto passa a ocupar a
     largura TODA — sem sobra nenhuma — então esse mesmo overflow estourava
     a viewport. Trava (overflow:hidden), o quadrado só fica cortado na
     borda da foto. */
  .sobre-photo {
    overflow: hidden;
  }
  /* O posicionamento em % relativo a .sobre (pra acompanhar a faixa em
     qualquer largura, ver .sobre-cv acima) só faz sentido decorativo
     cruzando a foto — em mobile a faixa já cai numa posição bem mais baixa
     (a seção fica mais alta, empilhada) e não vale a pena replicar a
     mesma matemática. Volta a ser um elemento normal de fluxo, com a
     mesma margem lateral do .container (não está mais dentro dele). */
  .sobre-cv {
    position: static;
    margin: 32px var(--edge-pad) 0;
  }
}

/* ==========================================================================
   Footer — node 126:380 (Figma). Frame de referência 1440x1121: todo
   elemento fica posicionado em % desse frame (aspect-ratio trava a
   proporção) pra escalar igual em qualquer largura — mesma técnica do
   .sobre-marquee (top em %). CTA "Vamos trabalhar juntos" reaproveita o
   padrão simplificado do .hero-contact/.sobre-cv (label + quadrado +
   ícone com crossfade de opacidade) em vez da estrutura aninhada mais
   complexa do Figma (quadrados decorativos extras que, na prática, se
   confundem com o fundo verde) — mesma linguagem visual, menos DOM.
   Ícones próprios (footer-cta-arrow-*.svg) com fundo escuro no default e
   verde no hover — invertido em relação ao hero, já que aqui o fundo da
   seção inteira já é verde ácido. Fonte Archia (MULTIDESIGN, BSB/WORLD,
   DESIGN & CREATIVITY etc.) ainda não licenciada — cai no fallback de
   Archivo (largura normal).
   "Instagram" no Figma está com erro de digitação ("instragram") —
   corrigido aqui. Links sociais e do CTA são placeholders (href="#" /
   "#contato") até termos os destinos reais. */
.site-footer {
  /* O footer usa o modo "ACID" da coleção Color Token do Figma — um
     token com o MESMO NOME do modo Dark usado no resto do site pode
     resolver pra um valor DIFERENTE (conferido via get_variable_defs
     por nó, node 126:380): bg/main e text/highlight batem com o mesmo
     verde #e5f961 nos dois modos, mas text/subtle vira #51685d (não
     #9ea19a) e shapes/med vira #5c7468 (não #51685d) — variáveis
     LOCAIS aqui pra não confundir com os tokens globais (Dark). */
  --footer-text-subtle: #51685d; /* text/subtle (Acid) — assinatura + linha MULTIDESIGN/BSB/DESIGN&CREATIVITY */
  --footer-shape-med: #5c7468;   /* shapes/med (Acid) — diamante central */

  position: relative;
  aspect-ratio: 1440 / 760;
  background-color: var(--c-acid);
  color: var(--c-bg); /* text/main (Acid) = #151717, mesmo valor do --c-bg global */
  overflow: hidden;
}

.footer-cta {
  --tab-bg: var(--c-bg); /* shapes/high (Acid) = #151717, mesmo valor do --c-bg global */
  --tab-fg: #ffffff; /* text/inverse (Acid) — NÃO é --c-text-main (#fcffea), token diferente */

  position: absolute;
  /* mesma fórmula do .hero-contact: margem + 1 coluna a partir da borda */
  left: calc(var(--edge-pad) + (100% - 2 * var(--edge-pad)) / var(--grid-cols));
  top: var(--footer-cta-top, 23.9%);
  z-index: 1;
  display: inline-flex;
  align-items: flex-start;
  text-decoration: none;
}

.footer-cta-label {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 90px;
  padding: 36px;
  flex-shrink: 0;
  font-family: var(--font-text);
  font-weight: 400;
  font-size: 24px;
  line-height: 29px;
  letter-spacing: 0;
  white-space: nowrap;
  background-color: var(--tab-bg);
  color: var(--tab-fg);
  transition: background-color 0.15s steps(4, jump-end), color 0.15s steps(4, jump-end);
}

.footer-cta-mid {
  width: 24px;
  height: 24px;
  flex-shrink: 0;
  background-color: var(--tab-bg);
  transition: background-color 0.15s steps(4, jump-end), transform 0.15s steps(6, jump-end);
}

.footer-cta-icon {
  position: relative;
  width: 24px;
  height: 24px;
  margin-top: 24px;
  flex-shrink: 0;
}

.footer-cta-icon img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  transition: opacity 0.15s steps(4, jump-end);
}

.footer-cta-icon .is-hover {
  opacity: 0;
}

.footer-cta:hover,
.footer-cta:focus-visible {
  --tab-bg: var(--c-acid-subtle); /* bg/subtle (Acid) */
  --tab-fg: var(--c-bg); /* text/main (Acid) */
}

.footer-cta:hover .footer-cta-mid,
.footer-cta:focus-visible .footer-cta-mid {
  transform: translateY(48px); /* Big (Figma 139:726): topo 0-24 -> 48-72 */
}

.footer-cta:hover .is-default,
.footer-cta:focus-visible .is-default {
  opacity: 0;
}

.footer-cta:hover .is-hover,
.footer-cta:focus-visible .is-hover {
  opacity: 1;
}

.footer-info {
  position: absolute;
  /* coluna 9 (mesma fórmula do .sobre-cv): margem + 8 colunas */
  left: calc(var(--edge-pad) + (100% - 2 * var(--edge-pad)) * 8 / var(--grid-cols));
  top: var(--footer-info-top, 23.9%);
  width: 460px; /* pedido do Felipe (= 4 colunas em 1440) */
}

.footer-bio {
  margin: 0;
  font-family: var(--font-text);
  font-weight: 400;
  font-size: 24px;
  line-height: 29px;
  letter-spacing: 0;
}

.footer-social {
  display: flex;
  flex-wrap: wrap;
  gap: 39px;
  margin-top: 32px;
}

/* E-mail em texto, abaixo dos ícones de redes (abre o app de e-mail). */
.footer-email {
  display: inline-block;
  margin-top: 28px;
  font-family: var(--font-text);
  font-weight: 400;
  font-size: 20px;
  line-height: 24px;
  color: inherit;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 5px;
  overflow-wrap: anywhere;
}

.footer-email:hover,
.footer-email:focus-visible {
  text-decoration-thickness: 2px;
}

/* Links de redes sociais (Figma nodes 246:786 componente / 246:699 estados):
   5 ícones em caixas de 48px (ícone de 32px no canto superior-esquerdo),
   gap 39px. Cor via máscara (currentColor) — 1 SVG por rede, sem versão
   hover separada. Modo Acid: padrão shapes/med #5c7468, hover shapes/high
   #151717 (o frame de estados do Figma está no modo Dark, onde o hover
   é #e5f961 — não serve sobre o fundo verde do footer). Troca em blocos
   (steps), mesma linguagem do resto do site. */
.footer-social-icon {
  display: block;
  width: 48px;
  height: 48px;
  color: var(--footer-shape-med);
  transition: color 0.15s steps(4, jump-end);
}

.footer-social-icon span {
  display: block;
  width: 32px;
  height: 32px;
  background-color: currentColor;
  -webkit-mask: var(--icon) center / contain no-repeat;
  mask: var(--icon) center / contain no-repeat;
}

.footer-social-icon.is-whatsapp span {
  --icon: url(../icons/social-whatsapp.svg);
}

.footer-social-icon.is-instagram span {
  --icon: url(../icons/social-instagram.svg);
}

.footer-social-icon.is-linkedin span {
  --icon: url(../icons/social-linkedin.svg);
}

.footer-social-icon.is-behance span {
  --icon: url(../icons/social-behance.svg);
}

.footer-social-icon.is-spotify span {
  --icon: url(../icons/social-spotify.svg);
}

.footer-social-icon:hover,
.footer-social-icon:focus-visible {
  color: var(--c-bg);
}

.footer-meta {
  position: absolute;
  left: 2.292%;
  /* acompanha o logo: base da linha = topo do logo - 30px (pedido do Felipe) */
  bottom: calc(100% - var(--footer-logo-top, 63.6%) + 30px);
  width: 95.625%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
}

.footer-meta-col {
  display: flex;
  flex-direction: column;
  gap: 7px;
}

.footer-meta-col-right {
  align-items: flex-end;
  text-align: right;
}

.footer-meta-label {
  margin: 0;
  font-family: var(--font-archia);
  font-stretch: 100%;
  font-weight: 700;
  font-size: 18px;
  line-height: 1;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--footer-text-subtle);
}

.footer-meta-sub {
  margin: 0;
  display: flex;
  align-items: center;
  gap: 5px;
  font-family: var(--font-archia);
  font-stretch: 100%;
  font-weight: 500;
  font-size: 18px;
  line-height: 1;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--footer-text-subtle);
}

.footer-meta-diamond {
  flex-shrink: 0;
}

.footer-logo-mark {
  /* Versão SEM o glifo ® (Figma node 223:268). SANGRA nas bordas
     (pedido do Felipe): 106% da largura, centralizado (left:-3%), e a
     base passa do fim do frame — `.site-footer{overflow:hidden}` corta
     esquerda, direita e embaixo, como se tivesse sido recortado. Frame
     de referência 1440×880. */
  position: absolute;
  left: -3%;
  top: var(--footer-logo-top, 63.6%);
  width: 106%;
  max-width: none; /* o reset global img{max-width:100%} travaria em 100% */
  height: auto;
  display: block;
  pointer-events: none;
}

@media (max-width: 1023px) {
  .site-footer {
    aspect-ratio: auto;
    padding: 48px var(--edge-pad) 64px;
    overflow: visible;
  }

  .footer-cta,
  .footer-info,
  .footer-meta,
  .footer-logo-mark {
    position: static;
    left: auto;
    top: auto;
    bottom: auto;
    width: auto;
  }

  .footer-cta {
    margin-bottom: 48px;
  }

  .footer-info {
    margin-bottom: 56px;
  }

  .footer-meta {
    flex-direction: column;
    align-items: flex-start;
    gap: 24px;
  }

  .footer-meta-col-right {
    align-items: flex-start;
    text-align: left;
  }

  .footer-meta-diamond {
    display: none;
  }

  .footer-logo-mark {
    margin-top: 48px;
  }
}

/* Painel de ajuste (dev) do logo do footer — tecla L / ?logo. Remover
   antes do lançamento junto com o bloco correspondente em main.js. */
.logo-panel {
  position: fixed;
  right: 16px;
  bottom: 16px;
  z-index: 200;
  width: 260px;
  padding: 12px;
  background: var(--c-bg);
  color: var(--c-text-main);
  border: 1px solid var(--c-border);
  font-family: var(--font-text);
  font-size: 12px;
  line-height: 14px;
}
.logo-panel[hidden] { display: none; }
.logo-panel-title { margin-bottom: 10px; color: var(--c-text-highlight); }
.logo-panel input[type="range"] { width: 100%; margin: 0 0 10px; }
.logo-panel-row { display: flex; align-items: center; gap: 8px; }
.logo-panel-value { flex: 1; }
.logo-panel button {
  padding: 4px 8px;
  border: 1px solid var(--c-border);
  background: var(--c-bg-subtle);
  color: var(--c-text-main);
  font: inherit;
  cursor: pointer;
}

.logo-panel-field { display: block; margin-bottom: 10px; }
.logo-panel-field > span:first-child { display: block; margin-bottom: 4px; }
.logo-panel-field .logo-panel-value { display: block; margin-top: 2px; color: var(--c-text-subtle); }
.logo-panel-field input[type="range"] { margin-bottom: 0; }

/* Breakpoint 1280–1535px: ajustes específicos (pedido do Felipe).
   - Carrossel do Sobre desce 50px (volta pra 67.5%) pra ficar ENTRE o
     texto da bio e o botão "Baixa CV" em vez de cruzar o texto.
   - Botão CTA e bio do footer sobem pra 14.3% (o painel de dev, se
     mexido, continua sobrescrevendo via variável). */
@media (min-width: 1280px) and (max-width: 1535px) {
  /* Bio nova (3 parágrafos, mais longa — pedido do Felipe) passava por cima
     da faixa de palavras: quanto mais estreita a tela, mais a bio quebra
     em linhas e mais desce. Empurra faixa + "Baixa CV" pra baixo na mesma
     proporção (0 em 1536px; ~48px em 1440; ~140px em 1280). */
  .sobre {
    --sobre-shift: max(0px, calc((1536px - 100vw) * 0.45));
    /* + altura na base (mesma proporção): sem isso o "Baixa CV", empurrado
       pra baixo, passava do fim da seção em ~1280px. */
    padding-bottom: calc(clamp(96px, 12vw, 180px) + max(0px, calc((1536px - 100vw) * 0.4)));
  }

  .sobre-marquee {
    top: calc(67.5% + var(--sobre-shift));
  }

  .sobre-cv {
    top: calc(67.5% + 70px + var(--sobre-shift));
  }

  .footer-cta {
    top: var(--footer-cta-top, 14.3%);
  }

  .footer-info {
    top: var(--footer-info-top, 14.3%);
  }
}

/* ==========================================================================
   Breakpoint 1024–1279px (pedido do Felipe). Grid mantido em 12 colunas
   (margem 24px): em ≥1024 ainda há largura pra 12 col; 8 col só abaixo de
   1024 (tablet) e 4 col abaixo de 640 (mobile) — ver docs/design-system.md.
   Escala tipográfica reduzida nesta faixa:
   - Body/Nav 20→18px | Body/Large 32→28px (intro) | Body/Large Tight 32→28px
     (título dos itens da galeria) | Body/Small 20→18px
   - Todos os botões (hero, Baixa CV, CTA do footer) no tamanho Med
   - Galeria em 3 colunas, filtros numa linha só (sem empilhar)
   - Foto do Sobre mim mais larga (colunas 1–6)
   ========================================================================== */
@media (min-width: 1024px) and (max-width: 1279px) {
  .nav-link {
    font-size: 18px;
    line-height: 22px;
  }

  .intro-statement {
    font-size: 28px;
    line-height: 36px;
  }

  .gallery-heading {
    grid-column: 1 / 6;
  }

  .gallery-filters {
    grid-column: 6 / -1;
    gap: 24px;
  }

  .gallery-filter-list {
    flex-wrap: nowrap;
  }

  .gallery-grid {
    grid-template-columns: repeat(3, 1fr);
  }

  .gallery-item-info h3 {
    font-size: 28px;
    line-height: 28px;
  }

  .capabilities-case-text,
  .sobre-bio p {
    font-size: 18px;
  }

  .sobre-photo {
    grid-column: 1 / 7;
  }

  /* Botões: tamanho Med (Figma 139:726) */
  .hero-contact-label,
  .sobre-cv-label,
  .footer-cta-label {
    height: 60px;
    padding: 30px;
    font-size: 20px;
    line-height: 24px;
    letter-spacing: -1px;
  }

  .hero-contact-mid,
  .sobre-cv-mid,
  .footer-cta-mid {
    width: 20px;
    height: 20px;
  }

  .hero-contact-arrow,
  .sobre-cv-icon,
  .footer-cta-icon {
    width: 20px;
    height: 20px;
    margin-top: 20px;
  }

  .hero-contact:hover .hero-contact-mid,
  .hero-contact:focus-visible .hero-contact-mid,
  .sobre-cv:hover .sobre-cv-mid,
  .sobre-cv:focus-visible .sobre-cv-mid,
  .footer-cta:hover .footer-cta-mid,
  .footer-cta:focus-visible .footer-cta-mid {
    transform: translateY(40px);
  }
}

/* 1024–1279px: textos que ficavam na coluna 9 passam pra coluna 7 e
   ganham largura de 6 colunas (7 → borda direita). A foto do Sobre volta
   pra colunas 1–5: com o texto na coluna 7 e o quadrado do shader saindo
   17% da foto pra fora, a foto em 1–6 encostaria/sobreporia o texto. */
@media (min-width: 1024px) and (max-width: 1279px) {
  .capabilities-case-info {
    grid-column: 7 / -1;
    max-width: none;
  }

  .sobre-photo {
    grid-column: 1 / 6;
  }

  .sobre-text {
    grid-column: 7 / -1;
    max-width: none;
  }

  .sobre-cv {
    left: calc(var(--edge-pad) + (100% - 2 * var(--edge-pad)) * 6 / var(--grid-cols));
  }

  .footer-info {
    left: calc(var(--edge-pad) + (100% - 2 * var(--edge-pad)) * 6 / var(--grid-cols));
    width: calc((100% - 2 * var(--edge-pad)) * 6 / var(--grid-cols));
  }
}

/* 1024–1279px: textos da coluna 7 com 5 colunas de largura (7 → 11); foto
   principal e quadrado do shader ficam POR CIMA do carrossel de palavras
   (que vira fundo da seção, atrás das fotos). */
@media (min-width: 1024px) and (max-width: 1279px) {
  .capabilities-case-info,
  .sobre-text {
    grid-column: 7 / span 5;
  }

  .footer-info {
    width: calc((100% - 2 * var(--edge-pad)) * 5 / var(--grid-cols));
  }

  .sobre-photo {
    z-index: 2;
  }
}

/* 1024–1279px: carrossel de palavras no FUNDO da seção (abaixo da foto,
   centralizado na faixa do padding-bottom do .sobre), atrás de tudo. */
@media (min-width: 1024px) and (max-width: 1279px) {
  .sobre-marquee {
    top: auto;
    bottom: calc(clamp(96px, 12vw, 180px) / 2 - 17px);
  }
}

/* 1024–1279px: o quadrado do shader sobrepõe 80% da própria largura sobre a
   foto principal (largura 38.72% da foto → 80% = 30.98% dentro → left
   = 100% − 30.98% = 69.02%). */
@media (min-width: 1024px) and (max-width: 1279px) {
  .sobre-photo-shader {
    left: 69.02%;
  }
}

/* 1024–1279px: organização da seção Sobre mim sem sobreposição (exceto as
   duas fotos). O botão "Baixa CV" sai do posicionamento absoluto (que
   cruzava o fim do texto) e entra no fluxo, logo abaixo do conteúdo,
   alinhado à coluna 7; o carrossel fica na faixa do padding-bottom, depois
   do botão. */
@media (min-width: 1024px) and (max-width: 1279px) {
  .sobre-cv {
    position: static;
    margin: 32px 0 0 calc(var(--edge-pad) + (100% - 2 * var(--edge-pad)) * 6 / var(--grid-cols));
  }
}

/* CORREÇÃO: o .sobre puxa `margin-top: -min(1250px,100vh)` pra cobrir
   Capacidades enquanto ela ainda está grudada. Se o .sobre for MAIS BAIXO
   que essa distância (ex.: 837px numa viewport de 870px), sua base termina
   antes do fim do trilho de Capacidades e, ao rolar pro rodapé, uma faixa do
   palco de Capacidades aparece embaixo do Sobre. min-height igual à mesma
   fórmula garante que o Sobre sempre cobre o palco por inteiro. */
@media (prefers-reduced-motion: no-preference) {
  .sobre {
    min-height: min(1250px, 100vh);
  }
}

/* 1024–1279px: Body/Medium 24px → 20px (linha 24px): eyebrows das seções
   (Galeria e Sobre mim) e bio do footer. Os botões já estão em 20px (Med). */
@media (min-width: 1024px) and (max-width: 1279px) {
  .gallery-heading p,
  .sobre-eyebrow p,
  .footer-bio {
    font-size: 20px;
    line-height: 24px;
  }
}

/* 1024–1279px: rodapé com altura mínima em px. O frame é proporcional
   (aspect-ratio), então em 1024px ele encolhia pra ~540px enquanto o
   conteúdo (tamanhos fixos em px) precisa de ~600px — bio, redes sociais e
   linha MULTIDESIGN se sobrepunham. min-height convive com o aspect-ratio
   (vale o maior dos dois); botão e bio sobem pra 14.3% pra deixar espaço
   pra linha de texto acima do logo. */
@media (min-width: 1024px) and (max-width: 1279px) {
  /* NÃO usar min-height junto do aspect-ratio: o navegador propaga o
     min-height pela proporção e ALARGA o footer (700px × 1440/760 = 1326px,
     estourando a viewport e cortando a caixa de texto na margem). Altura
     explícita: o maior entre 700px e a altura proporcional (52.78vw). */
  .site-footer {
    aspect-ratio: auto;
    height: max(700px, 52.78vw);
  }

  .footer-cta {
    top: var(--footer-cta-top, 14.3%);
  }

  .footer-info {
    top: var(--footer-info-top, 14.3%);
  }
}

/* 1280–1439px: a caixa de texto do footer (460px fixos a partir da coluna 9)
   estourava a margem direita em larguras < 1440px. Agora coluna 7 com
   largura de 5 colunas (mesmo padrão da faixa 1024–1279). Até 1439 pra não
   mexer no layout de 1440 (referência do Figma). */
@media (min-width: 1280px) and (max-width: 1439px) {
  .footer-info {
    left: calc(var(--edge-pad) + (100% - 2 * var(--edge-pad)) * 6 / var(--grid-cols));
    width: calc((100% - 2 * var(--edge-pad)) * 5 / var(--grid-cols));
  }
}

/* 1024–1279px: ícones de rede social em 26px (caixa e gap na mesma
   proporção do componente: caixa = 1.5 × ícone = 39px, gap 39 × 26/32 ≈ 32px). */
@media (min-width: 1024px) and (max-width: 1279px) {
  .footer-social {
    gap: 32px;
  }

  .footer-social-icon {
    width: 39px;
    height: 39px;
  }

  .footer-social-icon span {
    width: 26px;
    height: 26px;
  }
}

/* 768–1023px (tablet): sem o menu principal (.site-header: logo + nav +
   EN/PT) — fica só a barra fixa (.sticky-bar, Figma 154:531), centralizada,
   sempre visível. Com o header em display:none o getBoundingClientRect()
   dele vira zeros, e a lógica de main.js (header saiu de cena => barra
   visível) já a mantém ligada sem depender do scroll. */
@media (max-width: 1023px) {
  .site-header {
    display: none;
  }
}

/* ≤1023px: o logo do footer (max-width:none, usado pra sangrar no desktop)
   estourava a largura da viewport (1460px naturais) quando o footer vira
   fluxo normal. Volta a caber na largura disponível. */
@media (max-width: 1023px) {
  .footer-logo-mark {
    width: 100%;
    max-width: 100%;
  }
}

/* 768–1023px (tablet): sem o botão "Entre em contato" no hero. (A
   centralização vertical do título foi desfeita a pedido do Felipe — o
   título volta à posição Y original, ancorado embaixo.) */
@media (max-width: 1023px) {
  .hero-contact {
    display: none;
  }

  /* Altura do hero no tablet: 100vh deixava o hero enorme em retrato
     (768×1024 → 1024px de altura, título pequeno num mar de vazio). Agora
     ~90% da altura da tela, entre 640px e 960px. */
  .hero {
    min-height: 0;
    height: clamp(640px, 90svh, 960px);
  }
}

/* Assinatura da base do hero: nunca encolher nem ser espremida pelo flex
   column (com altura fixa no hero, o flex-shrink padrão cortaria a imagem). */
.hero-signature {
  flex-shrink: 0;
  max-width: 100%;
}


/* Grid do tablet (768–1023px): 6 colunas (desktop 12, mobile 4). Todo o
   conteúdo do tablet já está em 1 / -1 (empilhado), então nada precisa ser
   remapeado. De 640 a 767px continua 8 colunas até esse breakpoint ser
   trabalhado. */
@media (min-width: 481px) and (max-width: 1023px) {
  :root {
    --grid-cols: 6;
  }
}

/* Overlay de debug (tecla G): tem 12 <span>; com menos colunas os extras
   quebravam numa 2ª linha e pareciam colunas a mais (ex.: "8 colunas" +
   4 numa segunda fileira). Esconde os spans além do nº de colunas. */
@media (min-width: 481px) and (max-width: 1023px) {
  .debug-grid span:nth-child(n+7) { display: none; }
}
@media (max-width: 480px) {
  .debug-grid span:nth-child(n+5) { display: none; }
}

/* Assinatura do hero: <picture> com versão de 800px de largura no tablet
   (Figma node 69:322, mesma altura de letra 12.63px em menos largura — as
   palavras ficam mais legíveis em 768–1023px). display:contents mantém o
   <img> como item direto do flex column do hero. */
.hero-signature-picture {
  display: contents;
}

/* 768–1023px: Intro — caixa de texto centralizada com 4 colunas de largura
   (grid de 6: colunas 2–5) e Body/Large em 24px. */
@media (max-width: 1023px) {
  .intro-statement {
    grid-column: 2 / span 4;
    max-width: none;
    font-size: 24px;
    line-height: 1.3125;
  }
}

/* 768–1023px: texto do case de Capacidades começa na 4ª coluna (grid de 6
   → colunas 4–6). */
@media (max-width: 1023px) {
  .capabilities-case-info {
    grid-column: 4 / -1;
  }
}

/* 768–1023px: Sobre mim — moldura da foto principal mais baixa (4:3 em vez
   de quadrada: a foto ocupa a largura toda e ficava altíssima) e o quadrado
   do shader sobreposto mais pro centro da foto (antes colado no canto
   inferior direito e cortado pela borda). */
@media (max-width: 1023px) {
  .sobre-photo {
    aspect-ratio: 4 / 3;
  }

  .sobre-photo-shader {
    left: 52%;
    top: 45%;
  }
}

/* 768–1023px: o carrossel de palavras cruza a FOTO principal (na frente
   dela), em vez de cair em cima do título "Olá, sou Felipe Rocha". O
   carrossel é irmão do .container (não filho da foto), então a posição é
   calculada: topo da foto (~240px) + altura da foto (4:3 → 0.75 × largura
   útil) − 90px, ou seja, ~90px acima da base da foto. */
@media (max-width: 1023px) {
  .sobre-marquee {
    top: calc(240px + 0.75 * (100vw - 2 * var(--edge-pad)) - 90px);
    bottom: auto;
  }
}

/* 768–1023px: título "Olá, sou Felipe Rocha" numa linha só (o <br> some) e
   Display/Medium em 40px. */
@media (max-width: 1023px) {
  .sobre-title {
    font-size: 40px;
    line-height: 44px;
    white-space: nowrap;
  }

  .sobre-title br {
    display: none;
  }
}

/* ==========================================================================
   Footer no tablet (768–1023px) — protótipo Figma node 252:807 (frame
   768×781). Volta ao layout proporcional (aspect-ratio + posições em % do
   frame, como no desktop) com as coordenadas do protótipo: assinatura
   "FELIPE PINHEIRO ROCHA" no topo, bio à esquerda, redes sociais em COLUNA à
   direita (ícones de 24px, passo de 49px), botão (tamanho Med), linha
   MULTIDESIGN colada no logo (18.5px acima) e logo sangrando esquerda/
   direita (103.65% da largura), base do logo = base do rodapé. Textos da
   linha MULTIDESIGN escalam com a largura (15.303px em 768px = 1.993vw).
   ========================================================================== */
.footer-name {
  display: none;
}

@media (min-width: 481px) and (max-width: 1023px) {
  .site-footer {
    aspect-ratio: 768 / 781;
    padding: 0;
    overflow: hidden;
  }

  .footer-name,
  .footer-cta,
  .footer-info,
  .footer-meta,
  .footer-logo-mark {
    position: absolute;
    margin: 0;
  }

  .footer-name {
    display: block;
    left: 4.036%;
    top: 4.225%;
    width: 92.057%;
  }

  .footer-name img {
    display: block;
    width: 100%;
    height: auto;
  }

  /* botão (Med) — mesmas medidas do bloco Med de 1024–1279 */
  .footer-cta {
    left: 3.516%;
    top: var(--footer-cta-top, 38.284%);
    z-index: 1;
  }

  .footer-cta-label {
    height: 60px;
    padding: 30px;
    font-size: 20px;
    line-height: 24px;
    letter-spacing: -1px;
  }

  .footer-cta-mid {
    width: 20px;
    height: 20px;
  }

  .footer-cta-icon {
    width: 20px;
    height: 20px;
    margin-top: 20px;
  }

  .footer-cta:hover .footer-cta-mid,
  .footer-cta:focus-visible .footer-cta-mid {
    transform: translateY(40px);
  }

  /* bio + redes: o wrapper cobre o frame inteiro (sem interceptar cliques) e
     cada filho é posicionado em % do frame */
  .footer-info {
    inset: 0;
    width: auto;
    height: auto;
    pointer-events: none;
  }

  .footer-bio {
    position: absolute;
    left: 3.906%;
    top: var(--footer-info-top, 15.493%);
    width: 61.458%;
    pointer-events: auto;
  }

  .footer-social {
    position: absolute;
    left: 80.859%;
    top: var(--footer-info-top, 18.054%);
    flex-direction: column;
    flex-wrap: nowrap;
    gap: 25px;
    margin: 0;
    pointer-events: auto;
  }

  /* e-mail sob a bio (a bio tem até 4 linhas em EN; o CTA começa em ~48%) */
  .footer-email {
    position: absolute;
    left: 3.906%;
    top: 34%;
    margin: 0;
    pointer-events: auto;
  }

  .footer-social-icon {
    width: 24px;
    height: 24px;
  }

  .footer-social-icon span {
    width: 24px;
    height: 24px;
  }

  /* linha MULTIDESIGN: base 18.53px (2.413vw) acima do topo do logo */
  .footer-meta {
    left: 1.009%;
    width: 97.721%;
    top: auto;
    bottom: calc(100% - var(--footer-logo-top, 69.05%) + 2.413vw);
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: 0;
  }

  .footer-meta-col-right {
    align-items: flex-end;
    text-align: right;
  }

  .footer-meta-col {
    gap: 0.646vw;
  }

  .footer-meta-label,
  .footer-meta-sub {
    font-size: 1.993vw;
    letter-spacing: 0;
  }

  .footer-meta-sub {
    gap: 0.554vw;
  }

  .footer-meta-sub img {
    width: 1.993vw;
    height: auto;
  }

  /* diamante fixo em 44.17% da linha (331.45 / 750.46 no protótipo) — não
     depende da largura das colunas de texto (a fonte de fallback no lugar da
     Archia muda essas larguras e deslocava o diamante com space-between) */
  .footer-meta-diamond {
    display: block;
    position: absolute;
    left: 44.166%;
    top: 0;
    width: 6.64vw;
    height: auto;
  }

  .footer-logo-mark {
    left: -1.953%;
    top: var(--footer-logo-top, 69.05%);
    width: 103.646%;
    max-width: none;
  }
}

/* ==========================================================================
   Mobile grande (481–767px) e mobile (≤480px): mesmas mudanças do tablet
   (blocos acima agora valem a partir de 481px) + ajustes de escala.
   Grid: 6 colunas em 481–1023px, 4 em ≤480px.
   ========================================================================== */
@media (min-width: 481px) and (max-width: 767px) {
  /* footer: mesmo layout proporcional do protótipo do tablet (frame 768) —
     o corpo da bio escala com a largura (24px em 768 = 3.125vw) */
  .footer-bio {
    font-size: 3.125vw;
    line-height: 3.776vw;
  }
}

/* Mobile (≤480px): grid de 4 colunas — posições que usavam colunas do grid de
   6 voltam a largura total, e o título do Sobre mim (nowrap 40px = 417px)
   encolhe pra caber numa linha só. O footer mantém o layout empilhado de
   mobile (o protótipo proporcional do tablet só vale a partir de 481px). */
@media (max-width: 480px) {
  .intro-statement {
    grid-column: 1 / -1;
  }

  .capabilities-case-info {
    grid-column: 1 / -1;
  }

  .sobre-title {
    font-size: clamp(24px, 7.5vw, 32px);
    line-height: 1.1;
  }
}

/* Barra fixa: `left:50%` + shrink-to-fit limitava a barra a 50% da viewport e
   os boxes vazavam pra direita (fora do centro) em larguras < ~840px.
   width:max-content solta o limite (a barra fica centralizada de verdade). */
.sticky-bar {
  width: max-content;
}

/* ≤480px: a barra completa (~410px) não cabe — compacta: logo menor, sem o
   rótulo "Menu" (fica só o ícone), padding menor. */
@media (max-width: 480px) {
  .sticky-box {
    padding: 10px;
  }

  .sticky-logo img {
    width: 64px;
  }

  .sticky-menu > span:first-child {
    display: none;
  }
}

/* ≤480px: título do hero — "Design & Creativity" 20px e "For all purposes"
   36px (antes clamp mínimo de 24px e 42px). */
@media (max-width: 480px) {
  .hero-title-sub {
    font-size: 20px;
  }

  .hero-title-main {
    font-size: min(36px, 9.5vw); /* 36px a partir de ~380px; encolhe em telas menores pra "OS PROPÓSITOS" caber numa linha */
    /* entrelinha menor entre "PARA TODOS" e "OS PROPÓSITOS" (pedido do Felipe);
       o margin-top devolve o que o line-height tirou de cima, pra primeira
       linha ficar onde estava em relação a "Design & Criatividade". */
    line-height: 0.95;
    margin-top: 0.105em;
  }
}

/* Quebra de linha só no celular: "PARA TODOS" / "OS PROPÓSITOS" (no desktop
   o título fica numa linha só). */
.br-m {
  display: none;
}

@media (max-width: 767px) {
  .br-m {
    display: inline;
  }
}

/* ≤480px: a barra fixa ocupa TODAS as colunas (da margem esquerda à direita
   do grid) em vez de ficar do tamanho do conteúdo; os 4 blocos dividem a
   largura igualmente (gap de 3px mantido). */
@media (max-width: 480px) {
  .sticky-bar {
    left: var(--edge-pad);
    right: var(--edge-pad);
    width: auto;
    transform: none;
  }

  .sticky-bar > .sticky-box,
  .sticky-bar > .sticky-menu-wrap {
    flex: 1 1 0;
    min-width: 0;
  }

  .sticky-menu-wrap > .sticky-menu {
    width: 100%;
    justify-content: center;
  }

  /* Submenu na largura inteira da barra (pedido do Felipe): o wrapper do menu
     deixa de ser o "pai posicionado", então o submenu se ancora na própria
     barra (fixa) e ocupa de ponta a ponta, em vez de ficar do tamanho do
     botão Menu (o texto "CAPABILITIES" vazava da caixa). */
  .sticky-menu-wrap {
    position: static;
  }

  .sticky-submenu {
    left: 0;
    right: 0;
    width: auto;
  }

  .sticky-submenu-item {
    padding: 16px 10px;
  }

  /* Página de projeto: a barra fica em fluxo normal (static) até fixar —
     precisa ser "posicionada" pro submenu se ancorar nela. */
  body .project-header-row .sticky-bar {
    position: relative;
    right: auto; /* o right:20px herdado deslocaria a barra (relative) pra esquerda */
  }
}

/* ==========================================================================
   Botão (componente Figma 139:726, tamanho MED) — versão genérica .btn-med,
   mesma estrutura/cores do .hero-contact (modo Dark: verde-ácido → hover
   #202222 / #fcffea): rótulo 60px (padding 30, 20/24, tracking -1px),
   quadrado 20px no topo que desce 40px no hover, seta 20px com crossfade
   entre os 2 SVGs. Usado no "Veja mais" da galeria (mobile).
   ========================================================================== */
.btn-med {
  --tab-bg: var(--c-text-highlight);
  --tab-fg: var(--c-bg);

  display: inline-flex;
  align-items: flex-start;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-decoration: none;
  cursor: pointer;
}

.btn-med-label {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 60px;
  padding: 30px;
  flex-shrink: 0;
  font-family: var(--font-text);
  font-weight: 400;
  font-size: 20px;
  line-height: 24px;
  letter-spacing: -1px;
  white-space: nowrap;
  background-color: var(--tab-bg);
  color: var(--tab-fg);
  transition: background-color 0.15s steps(4, jump-end), color 0.15s steps(4, jump-end);
}

.btn-med-mid {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
  background-color: var(--tab-bg);
  transition: background-color 0.15s steps(4, jump-end), transform 0.15s steps(6, jump-end);
}

.btn-med-icon {
  position: relative;
  width: 20px;
  height: 20px;
  margin-top: 20px;
  flex-shrink: 0;
}

.btn-med-icon img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  transition: opacity 0.15s steps(4, jump-end);
}

.btn-med-icon .is-hover {
  opacity: 0;
}

.btn-med:hover,
.btn-med:focus-visible {
  --tab-bg: var(--c-bg-subtle);
  --tab-fg: var(--c-text-main);
}

.btn-med:hover .btn-med-mid,
.btn-med:focus-visible .btn-med-mid {
  transform: translateY(40px);
}

.btn-med:hover .is-default,
.btn-med:focus-visible .is-default {
  opacity: 0;
}

.btn-med:hover .is-hover,
.btn-med:focus-visible .is-hover {
  opacity: 1;
}

/* "Veja mais" da galeria: só no mobile (≤639px), onde só 4 dos 8 itens
   aparecem; o clique (main.js) mostra todos e some com o botão. */
.gallery-more-wrap {
  display: none;
}

@media (max-width: 639px) {
  .gallery-more-wrap {
    display: flex;
    justify-content: center;
    margin-top: 96px;
  }

  .gallery-more-wrap.is-hidden {
    display: none;
  }

  .gallery-grid.is-expanded .gallery-item:nth-child(n + 5) {
    display: flex;
  }
}

/* ==========================================================================
   Capacidades no mobile (≤480px) — protótipo Figma node 257:1165 (iPhone,
   frame 401×874). Fotos e "Meu trabalho como" NO TOPO; título ao centro; texto
   do case embaixo. Larguras/lefts/tops das fotos escalam com a largura
   (vw / % de 401px); y do título/tag/texto seguem o protótipo (50% + offsets,
   70.7%). As fotos continuam MUDANDO DE POSIÇÃO a cada keyword (index 0 = o
   protótipo; 1 e 2 = posições estimadas dentro da mesma faixa do topo).
   O quadradinho verde (dot) do protótipo fica fora da tela — escondido.
   ========================================================================== */
@media (max-width: 480px) {
  .capabilities-decor {
    display: block;
  }

  .capabilities-decor-dot {
    display: none;
  }

  /* Fotos ~30% menores que no protótipo (pedido do Felipe: 87→61vw, 31→22vw,
     72→51vw) e reposicionadas na faixa de cima (0–90vw), acima da tag/título.
     Cada palavra (data-cap-index) tem a sua composição. */
  .capabilities-decor-01 {
    left: 4%;
    top: 12vw;
    width: 61vw;
  }

  .capabilities-decor-02 {
    left: 70%;
    top: 20vw;
    width: 22vw;
  }

  .capabilities-case-media,
  .capabilities[data-cap-index="1"] .capabilities-case-media,
  .capabilities[data-cap-index="2"] .capabilities-case-media {
    transform: none;
    width: 51vw;
    aspect-ratio: 290 / 163;
  }

  .capabilities-case-media {
    left: 38%;
    top: 50vw;
  }

  .capabilities[data-cap-index="1"] .capabilities-decor-01 { left: 38%; top: 12vw; }
  .capabilities[data-cap-index="1"] .capabilities-decor-02 { left: 8%; top: 22vw; }
  .capabilities[data-cap-index="1"] .capabilities-case-media { left: 6%; top: 50vw; }

  .capabilities[data-cap-index="2"] .capabilities-decor-01 { left: 2%; top: 48vw; }
  .capabilities[data-cap-index="2"] .capabilities-decor-02 { left: 18%; top: 12vw; }
  .capabilities[data-cap-index="2"] .capabilities-case-media { left: 46%; top: 14vw; }

  /* Trava mais curta no celular (pedido do Felipe): o trilho alto que prende a
     seção cai de +450vh pra +225vh (metade da rolagem "presa"). Os tempos de
     cada palavra em main.js (CAPABILITIES_SEGMENTS_VH_MOBILE) somam o mesmo
     225vh — se mudar um, mudar o outro junto. */
  .capabilities-pin {
    height: calc(min(1250px, 100vh) + 225vh);
  }

  /* título: centro em 50% + 84px (521px no frame de 874); tag acima dele */
  .capabilities-heading {
    top: calc(50% + 84px);
  }

  .capabilities-tag {
    position: absolute;
    left: 23.69%;
    top: -68.5px;
    margin: 0;
    padding: 20px;
    font-size: 16px;
    line-height: 4px;
    text-transform: uppercase;
  }

  /* 64% (era 70.7%) + parágrafo 18/22 (era 20/24): o texto novo mais longo
     (Branding) passava ~57px do fim da seção num celular de 844px de altura. */
  .capabilities-case {
    top: 64%;
  }

  .capabilities-case-info {
    max-width: 351px;
    width: 87.53vw;
    margin-left: calc(7.23vw - var(--edge-pad));
    gap: 20px;
  }

  .capabilities-case-title {
    font-size: 28px;
    line-height: 32px;
  }

  .capabilities-case-text {
    font-weight: 300;
    font-size: 18px;
    line-height: 22px;
  }
}

/* ≤480px: fotos atrás do texto central (tag + título) — o heading sobe pra
   z-index 3 (a foto do case tem z-index 1 e ficava por cima da tag). */
@media (max-width: 480px) {
  .capabilities-heading {
    z-index: 3;
  }

  .capabilities-case {
    z-index: 3;
  }
}

/* ≤480px: todos os botões no tamanho MED (Figma 139:726): rótulo 60px
   (padding 30, 20/24, tracking -1px), quadrado e seta de 20px (seta 20px
   abaixo do topo), hover do quadrado desce 40px. Vale pro "Baixa CV", pro CTA
   do footer e pro "Entre em contato" (escondido no mobile, mas mantido
   coerente). O "Veja mais" (.btn-med) já é Med. */
@media (max-width: 480px) {
  .hero-contact-label,
  .sobre-cv-label,
  .footer-cta-label {
    height: 60px;
    padding: 30px;
    font-size: 20px;
    line-height: 24px;
    letter-spacing: -1px;
  }

  .hero-contact-mid,
  .sobre-cv-mid,
  .footer-cta-mid {
    width: 20px;
    height: 20px;
  }

  .hero-contact-arrow,
  .sobre-cv-icon,
  .footer-cta-icon {
    width: 20px;
    height: 20px;
    margin-top: 20px;
  }

  .hero-contact:hover .hero-contact-mid,
  .hero-contact:focus-visible .hero-contact-mid,
  .sobre-cv:hover .sobre-cv-mid,
  .sobre-cv:focus-visible .sobre-cv-mid,
  .footer-cta:hover .footer-cta-mid,
  .footer-cta:focus-visible .footer-cta-mid {
    transform: translateY(40px);
  }
}

/* ≤480px: botões centralizados na largura (Baixa CV, CTA do footer; o "Veja
   mais" já é centralizado por flex). */
@media (max-width: 480px) {
  .sobre-cv,
  .footer-cta {
    display: flex;
    width: max-content;
    margin-inline: auto;
  }
}

/* ==========================================================================
   Footer no mobile (≤480px) — protótipo Figma node 258:1166 (frame 402×874).
   Mesma técnica do tablet: aspect-ratio + posições em % do frame. Assinatura
   no topo (341px), botão Med, bio 24/29, redes em LINHA (ícones 24px, passo
   49px), linha MULTIDESIGN (fontes 12.243px = 3.046vw) 18.53px (4.61vw)
   acima do logo, logo de 648px (161.19% da largura) centralizado, sangrando
   ~123px de cada lado, base = base do rodapé. Tamanhos de texto escalam com a
   largura (vw); botão e ícones ficam em px.
   ========================================================================== */
@media (max-width: 480px) {
  .site-footer {
    aspect-ratio: 402 / 874;
    padding: 0;
    overflow: hidden;
  }

  .footer-name,
  .footer-cta,
  .footer-info,
  .footer-meta,
  .footer-logo-mark {
    position: absolute;
    margin: 0;
  }

  .footer-name {
    display: block;
    left: 7.711%;
    top: 3.776%;
    width: 84.826%;
  }

  .footer-name img {
    display: block;
    width: 100%;
    height: auto;
  }

  .footer-cta {
    left: 4.726%;
    top: var(--footer-cta-top, 18.421%);
    z-index: 1;
    width: max-content;
  }

  .footer-info {
    inset: 0;
    width: auto;
    height: auto;
    pointer-events: none;
  }

  .footer-bio {
    position: absolute;
    left: 7.214%;
    top: var(--footer-info-top, 31.006%);
    width: 86.318%;
    font-size: 5.97vw;
    line-height: 7.214vw;
    pointer-events: auto;
  }

  .footer-social {
    position: absolute;
    left: 7.711%;
    top: var(--footer-info-top-social, 54.577%);
    flex-direction: row;
    flex-wrap: nowrap;
    gap: 25px;
    margin: 0;
    pointer-events: auto;
  }

  /* e-mail logo abaixo da linha de ícones (24px de ícone + 20px de respiro) */
  .footer-email {
    position: absolute;
    left: 7.711%;
    top: calc(var(--footer-info-top-social, 54.577%) + 44px);
    margin: 0;
    font-size: 18px;
    pointer-events: auto;
  }

  .footer-social-icon,
  .footer-social-icon span {
    width: 24px;
    height: 24px;
  }

  .footer-meta {
    left: 8.204%;
    width: 83.582%;
    top: auto;
    bottom: calc(100% - var(--footer-logo-top, 76.808%) + 4.61vw);
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: 0;
  }

  .footer-meta-col {
    gap: 0.987vw;
  }

  .footer-meta-col-right {
    align-items: flex-start;
    text-align: left;
  }

  .footer-meta-label,
  .footer-meta-sub {
    font-size: 3.046vw;
    letter-spacing: 0;
  }

  .footer-meta-sub {
    gap: 0.846vw;
  }

  .footer-meta-sub img {
    width: 3.046vw;
    height: auto;
  }

  .footer-meta-diamond {
    display: block;
    position: absolute;
    left: 34.64%;
    top: 0;
    width: 12.69vw;
    height: auto;
  }

  .footer-logo-mark {
    left: -30.597%;
    top: var(--footer-logo-top, 76.808%);
    width: 161.194%;
    max-width: none;
  }
}

/* ≤480px: barra fixa — menu, WhatsApp e EN/PT ficam QUADRADOS (60×60) e só o
   bloco do logo expande (ocupa o resto da largura), com o logo maior. */
@media (max-width: 480px) {
  .sticky-bar > .sticky-menu-wrap,
  .sticky-bar > .sticky-whatsapp,
  .sticky-bar > .sticky-lang {
    flex: 0 0 60px;
    width: 60px;
  }

  .sticky-bar > .sticky-logo {
    flex: 1 1 auto;
    min-width: 0;
  }

  .sticky-logo img {
    width: min(100%, 120px);
  }

  .sticky-bar > .sticky-lang {
    padding: 0;
  }

  .sticky-menu-wrap > .sticky-menu {
    width: 60px;
    padding: 0;
  }
}


/* ==========================================================================
   Página interna de projeto (Figma node 273-347, "Home — Desktop / 1441")
   — modelo base pra todas as páginas de projeto da galeria. Header vira a
   barra fixa (.sticky-bar) permanente (sem o header original nem o toggle
   por scroll — pedido do Felipe: "o menu original é substituído pelo
   menu/barra fixa"); eyebrow ("//Works that say and feel", reaproveita
   .gallery-heading) e o ícone decorativo à direita NÃO são fixos, rolam com
   a página. Título (Display/Large) na coluna 2, ano rente à margem direita;
   texto introdutório + imagem 16:9 na coluna 5; lista de capacidades na
   coluna 1-3, à esquerda da imagem (mesma linha de grid, ancorada embaixo).
   Blocos de caso (imagem cheia OU duas com 15px de gutter + legenda)
   repetem quantas vezes o projeto precisar. Footer = .site-footer, igual
   à Home (ver decisão abaixo).
   ========================================================================== */

.project-hero {
  /* topo = mesma medida da margem lateral (--edge-pad), pedido do Felipe —
     antes o conteúdo começava colado no topo (0px) enquanto a lateral já
     tinha --edge-pad. A barra fixa (.sticky-bar) fica centralizada, fora
     da faixa horizontal do eyebrow/ícone, então não tampa nada aqui. */
  padding-top: var(--edge-pad);
}

.project-header-row {
  position: relative;
  align-items: center;
  /* os 3 itens (eyebrow, barra, ícone) dividem a MESMA linha da grade —
     sem isso, a barra (grid-column:1/-1) empurraria os outros dois pra
     uma 2ª linha, já que ocupa a largura toda. */
  grid-template-rows: 1fr;
  /* minmax(0,…): sem isso as trilhas crescem até o conteúdo mínimo da barra
     (≈361px) e estouram a largura de celulares de 375px ou menos. */
  grid-template-columns: repeat(var(--grid-cols), minmax(0, 1fr));
}

.project-header-row .project-eyebrow,
.project-header-row .project-mark {
  grid-row: 1;
}

/* Barra de navegação — SÓ nesta página: entra no fluxo normal (respeita a
   mesma margem do topo que o resto do conteúdo, pedido do Felipe) e só
   fica fixa ("gruda" no topo) ao rolar — muda o comportamento herdado de
   `.sticky-bar` (Home: sempre `fixed`, escondida até o header original
   sair de cena).
   NOTA: `position:sticky` puro NÃO funciona aqui — o "containing block"
   de um item de grid é a própria LINHA da grade (~77px de altura, a
   altura do eyebrow), então a barra perdia onde "grudar" assim que essa
   linha rolava pra fora da tela, a poucos px do topo (testado: parava de
   seguir e scrollava embora já em scrollY~100). Por isso o JS mede a
   posição natural (`.project-header-row .sticky-bar`, main.js) e alterna
   pra `position:fixed` manualmente ao passar do ponto onde ela ficaria a
   15px do topo — mesmo raciocínio do `.sticky-bar` da Home, só que
   medindo a própria barra em vez de um header separado. */
.project-header-row .sticky-bar {
  grid-row: 1;
  grid-column: 1 / -1;
  position: static;
  left: auto;
  width: max-content;
  /* Em celular estreito (375px) o conteúdo da barra passa do container
     (380px): limita à largura disponível e o bloco do logo (min-width:0)
     absorve a diferença, sem criar rolagem horizontal. */
  max-width: 100%;
  min-width: 0;
  margin-inline: auto;
  /* Reseta o `transform:translateX(-50%)` herdado da regra base do
     `.sticky-bar` (pensada pro estado sempre-fixo da Home): aqui a
     centralização em fluxo normal já vem do `margin-inline:auto` — manter
     o transform causava um deslocamento duplo, e a barra "pulava" de
     posição no instante em que virava fixa (bug reportado pelo Felipe). */
  transform: none;
  pointer-events: auto;
}

.project-header-row .sticky-bar .sticky-box {
  opacity: 1;
  transform: none;
}

.project-header-row .sticky-bar.is-pinned {
  position: fixed;
  top: 15px;
  left: 50%;
  margin-inline: 0;
  max-width: calc(100vw - 2 * var(--edge-pad));
  transform: translateX(-50%);
}

.project-eyebrow {
  grid-column: 1 / 7;
}

.project-mark {
  grid-column: 12 / -1;
  justify-self: end;
  width: 79px;
  height: auto;
}

.project-hero-row {
  grid-column: 2 / -1;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
}

.project-title {
  margin: 0;
  font-family: var(--font-display);
  font-stretch: var(--display-stretch);
  font-weight: 400;
  font-size: clamp(48px, 7.5vw, 112px); /* Display/Large — 112px em 1440 */
  line-height: 1.036; /* 116/112 do Figma */
  letter-spacing: -0.027em; /* -3px/112px */
  text-transform: uppercase;
  color: var(--c-text-main);
}

/* Telas ≤360px: o piso de 48px estourava a palavra mais longa ("MARCENARIA"). */
@media (max-width: 360px) {
  .project-title {
    font-size: 42px;
  }
}

.project-year {
  margin: 0;
  flex-shrink: 0;
  font-family: var(--font-text);
  font-weight: 400;
  font-size: 24px;
  line-height: 29px;
  color: var(--c-text-main);
}

.project-intro {
  grid-column: 5 / 11; /* 6 colunas de largura */
  margin: 0;
  font-family: var(--font-text);
  font-weight: 300;
  font-style: normal;
  font-size: 32px;
  line-height: 42px;
  color: var(--c-text-main);
}

/* Texto com mais de 1 parágrafo (main.js/gerar-projetos.js: cada quebra de
   linha do JSON vira um <p> próprio, não <br><br> — <br><br> dava um
   espaço de 2 linhas cheias entre parágrafos, exagerado). Reset de margem
   nos <p> + um respiro pequeno (16px) só entre um parágrafo e o próximo. */
.project-intro p,
.project-case-caption-text p {
  margin: 0;
}
.project-intro p + p,
.project-case-caption-text p + p {
  margin-top: 16px;
}

.project-hero-media-row {
  align-items: end;
}

.project-capabilities {
  grid-column: 1 / 4;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.project-capabilities-label {
  margin: 0;
  padding-block: 10px;
  font-family: var(--font-text);
  font-weight: 300;
  font-size: 20px;
  line-height: 24px;
  letter-spacing: 0.5px;
  color: var(--c-text-subtle);
}

.project-capabilities-list {
  display: flex;
  flex-direction: column;
}

.project-capabilities-list li {
  padding-block: 10px;
  border-bottom: 1px solid var(--c-border);
  font-family: var(--font-text);
  font-weight: 300;
  font-size: 20px;
  line-height: 24px;
  letter-spacing: 0.5px;
  color: var(--c-text-main);
}

.project-hero-media {
  grid-column: 5 / -1;
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  background: var(--c-bg-subtle);
}

/* Imagem 50% mais alta que a caixa (25% de sobra em cima/embaixo) pro
   parallax de scroll (main.js) — mesmo padrão de overscan do
   .gallery-item-media img, valor tem que bater com
   GALLERY_PARALLAX_OVERSCAN no JS. */
.project-hero-media img {
  position: absolute;
  top: -25%;
  left: 0;
  width: 100%;
  height: 150%;
  display: block;
  object-fit: cover;
  will-change: transform;
}

/* Vídeo no hero (autoplay mudo em loop) — mesmo critério do vídeo nos
   blocos de caso: sem overscan/parallax de scroll (já se move sozinho). */
.project-hero-media video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
}

/* Blocos de caso — repetem: imagem cheia OU duas com 15px de gutter, cada
   um seguido de uma legenda (rótulo coluna 1-3 + texto Body/Large coluna 5).
   .project-case + ~ .project-case dá o espaço entre blocos (100px). */
.project-case {
  margin-top: 100px; /* só o 1º bloco (espaço vindo do Hero) — os seguintes usam a regra abaixo */
}

/* Espaço vertical ENTRE os blocos de imagem do portfólio (pedido do
   Felipe, testando 170px — era 100px, igual ao espaço vindo do Hero por
   causa da regra acima; agora as duas distâncias são independentes). */
.project-case + .project-case {
  margin-top: 170px;
}

/* Quando o bloco ANTERIOR não tem legenda (sem "legendaLabel"/
   "legendaTexto" no dados.json — ver .project-case-caption, é opcional),
   a distância até o próximo vira só 15px — pedido do Felipe: sem texto
   pedindo respiro embaixo da imagem, os blocos podem ficar colados, mesmo
   gutter de 15px já usado entre as 2 imagens de um bloco "split". */
.project-case:not(:has(.project-case-caption)) + .project-case {
  margin-top: 15px;
}

.project-case-media {
  position: relative;
  width: 100%;
  aspect-ratio: 1382 / 834; /* proporção do bloco cheio no Figma (1440) */
  overflow: hidden;
  background: var(--c-bg-subtle);
}

.project-case-media img {
  position: absolute;
  top: -25%;
  left: 0;
  width: 100%;
  height: 150%;
  display: block;
  object-fit: cover;
  will-change: transform;
}

/* Vídeo nos blocos de caso (autoplay mudo em loop, pedido do Felipe): sem
   o overscan/parallax de scroll das imagens (`top:-25%;height:150%`) — um
   vídeo já se move sozinho, então fica só um cover simples e estático,
   sem `will-change:transform` (nada escreve `transform` nele). */
.project-case-media video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
}

/* Bloco "manterProporcao" (dados.json): em vez de cortar a imagem/vídeo
   pra preencher a caixa (cover, 1382:834 padrão), a caixa se ajusta à
   proporção NATURAL do arquivo — sem overscan/parallax (não tem sobra de
   imagem pra deslocar sem revelar borda, já que não tem crop nenhum). Só
   pros blocos "imagem"/"video" (não "split" — ali as 2 metades dividem
   uma linha só, então cada imagem manter a própria proporção quebraria o
   alinhamento entre as duas). */
.project-case-media.is-natural {
  aspect-ratio: auto;
}
.project-case-media.is-natural img,
.project-case-media.is-natural video {
  position: static;
  top: auto;
  left: auto;
  width: 100%;
  height: auto;
  transform: none;
}

.project-case-media.is-split {
  display: flex;
  gap: 15px;
  aspect-ratio: auto;
}

/* Bloco split: cada metade precisa da própria caixa de recorte
   (`.project-media-crop`, position:relative;overflow:hidden) pro parallax
   de scroll da imagem lá dentro não vazar por cima da outra metade — antes
   o `<img>` era direto o item do flex, sem caixa própria pra cortar a
   sobra de 25% do overscan. */
.project-case-media.is-split > .project-media-crop {
  position: relative;
  overflow: hidden;
  flex: 1 1 0;
  min-width: 0;
  aspect-ratio: 683.5 / 834; /* cada metade, já descontado o gutter de 15px */
}

/* Figma node 274:760 (revisão do componente de legenda): antes era um flex
   com larguras fixas (345px + gap 116px) que só batiam com a coluna 5 na
   largura de 1440px — virou item de grid de verdade (`.grid` na própria
   `.project-case-caption`, mesmo padrão de `.project-hero-media-row`) pra
   alinhar com a coluna 5 em qualquer largura, igual ao `.project-intro`. */
.project-case-caption {
  align-items: start;
  margin-top: 35px;
}

.project-case-caption-label {
  grid-column: 1 / 5;
  margin: 0;
  padding-block: 10px;
  font-family: var(--font-text);
  font-weight: 300;
  font-size: 20px;
  line-height: 24px;
  letter-spacing: 0.5px;
  color: var(--c-text-subtle);
}

.project-case-caption-text {
  grid-column: 5 / 11; /* 6 colunas de largura (era 5/-1 + max-width:688px fixo) */
  margin: 0;
  font-family: var(--font-text);
  font-weight: 300; /* era 400 (Regular) — pedido do Felipe, mais leve */
  font-size: 24px;
  line-height: 31.9px; /* era 29px, +10% pedido do Felipe */
  color: var(--c-text-main);
}

/* "Próximo projeto" — imagem de fundo baixa opacidade (mesma linguagem do
   Figma: um teaser discreto, não uma foto cheia), botão no canto
   superior-direito (variante SEM quadrado do meio — só rótulo + seta 40px,
   diferente do padrão .hero-contact/.btn-med de 3 partes) e título+tags do
   próximo projeto embaixo. */
/* .project-next-wrap: caixa que soma a altura de .project-next + .site-
   footer, pra .project-next-media (imagem de fundo compartilhada pelas
   duas) poder crescer de escala ao rolar sem cortar feio bem na costura
   entre as duas seções — ver comentário no HTML (projeto.html) e o
   parallax de scale em main.js. */
.project-next-wrap {
  position: relative;
  overflow: hidden;
}

.project-next {
  position: relative;
  z-index: 1;
  margin-top: 740px; /* era 540px — mais distância pedida do Felipe (sem valor exato, escolhi +200px) */
  padding-top: 90px;
  padding-bottom: 40px;
}

.project-next-media {
  position: absolute;
  inset: 0;
  z-index: 0;
  will-change: transform;
}

.project-next-media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0.3;
  filter: grayscale(1);
  transform-origin: center;
}

/* Coluna 10 + centralizado na vertical do screenshot de fundo (pedido do
   Felipe) — antes era `float:right` (extremo direito, sem relação com a
   grade). Mesma fórmula de posicionamento por coluna do `.hero-contact`/
   `.footer-cta` (não dá pra usar `.grid`+`grid-column` aqui porque o botão
   não compartilha linha de grid com nada — só ele sozinho). "Centro
   horizontal do screenshot" = meio da altura do `.project-next` (posição
   relativa), única extensão vertical que faz sentido medir, já que a
   imagem de fundo cobre a seção inteira. */
.project-next-cta {
  position: absolute;
  top: 25%; /* era 50% (centro) — pedido do Felipe pra ficar mais alto */
  left: calc(var(--edge-pad) + (100% - 2 * var(--edge-pad)) * 9 / var(--grid-cols));
  transform: translateY(-50%);
  z-index: 1;
  display: inline-flex;
  align-items: flex-start;
  text-decoration: none;
}

/* `transform` não soma entre regras — o `.reveal-scroll` genérico (subida
   de 28px) ia SUBSTITUIR o translateY(-50%) de centralização acima em vez
   de somar. Junta os dois numa declaração só, por cima da regra genérica
   (2 classes = mais específico), mesmo padrão do `.capabilities-heading`. */
.project-next-cta.reveal-scroll {
  transform: translateY(calc(-50% + 28px));
}
.project-next-cta.reveal-scroll.is-inview {
  transform: translateY(-50%);
}

.project-next-cta-label {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 60px;
  padding: 30px;
  flex-shrink: 0;
  font-family: var(--font-text);
  font-weight: 400;
  font-size: 20px;
  line-height: 24px;
  letter-spacing: -1px;
  white-space: nowrap;
  background-color: var(--c-text-highlight);
  color: var(--c-bg);
  transition: background-color 0.15s steps(4, jump-end), color 0.15s steps(4, jump-end);
}

.project-next-cta-icon {
  position: relative;
  width: 40px;
  height: 40px;
  margin-top: 20px;
  flex-shrink: 0;
}

.project-next-cta-icon img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  transition: opacity 0.15s steps(4, jump-end);
}

.project-next-cta-icon .is-hover {
  opacity: 0;
}

.project-next-cta:hover .project-next-cta-label,
.project-next-cta:focus-visible .project-next-cta-label {
  background-color: var(--c-bg-subtle);
  color: var(--c-text-main);
}

.project-next-cta:hover .is-default,
.project-next-cta:focus-visible .is-default {
  opacity: 0;
}

.project-next-cta:hover .is-hover,
.project-next-cta:focus-visible .is-hover {
  opacity: 1;
}

.project-next-info {
  position: relative;
  z-index: 1;
  /* `clear:both` saiu junto com o `float:right` do `.project-next-cta`
     (agora `position:absolute`, não ocupa mais espaço no fluxo) — o
     margin-top sozinho preserva a mesma posição visual de antes (182px
     do topo do `.project-next`, conferido no navegador). */
  margin-top: 60px;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 16px;
}

.project-next-title {
  margin: 0;
  font-family: var(--font-display);
  font-stretch: var(--display-stretch);
  font-weight: 400;
  font-size: clamp(28px, 3.5vw, 40px); /* Display/Small — 40px em 1440 */
  line-height: 1.1;
  letter-spacing: -0.075em;
  text-transform: uppercase;
  color: var(--c-text-main);
}

/* 1024–1279px: MESMA escala tipográfica reduzida que a Home já usa nessa
   faixa (ver o bloco "Breakpoint 1024–1279px (pedido do Felipe)" acima,
   perto de .nav-link/.intro-statement) — Body/Large 32→28px (`.project-
   intro`, equivalente ao `.intro-statement` da Home) e Body/Small 20→18px
   (`.project-capabilities-label`/`-list li`/`.project-case-caption-label`,
   equivalente ao `.capabilities-case-text`/`.sobre-bio p`). Faltava esse
   degrau na página de projeto — ela pulava direto do tamanho cheio (≥1280)
   pro empilhado de tablet (≤1023), sem o intermediário que a Home tem.
   `.project-case-caption-text` (Body/Medium, 24px) ficou de fora: não tem
   equivalente na Home que reduza nessa faixa (o único Body/Medium da Home,
   `.footer-bio`, usa escala em vw contínua, não esse sistema de px por
   breakpoint — não dava pra inventar um valor sem uma referência real). */
@media (min-width: 1024px) and (max-width: 1279px) {
  .project-intro {
    font-size: 28px;
    line-height: 36px;
  }

  .project-capabilities-label,
  .project-capabilities-list li,
  .project-case-caption-label {
    font-size: 18px;
    line-height: 21.6px; /* mesma razão 1.2 já usada na base (20px/24px) */
  }
}

@media (max-width: 1023px) {
  /* Cabeçalho da página de projeto: sem o texto à esquerda (.project-eyebrow)
     nem o ícone à direita (.project-mark) no tablet E no mobile — pedido
     do Felipe, valia só pro mobile a princípio, depois estendido pro iPad
     (mesmo breakpoint ≤1023px usado pro resto do tablet nessa página). */
  .project-eyebrow { display: none; }
  .project-mark { display: none; }
  .project-hero-row,
  .project-intro,
  .project-hero-media { grid-column: 1 / -1; }
  .project-capabilities { grid-column: 1 / -1; margin-top: 24px; }
  .project-hero-media-row { row-gap: 24px; }
  .project-case-caption { row-gap: 24px; }
  .project-case-caption-label,
  .project-case-caption-text { grid-column: 1 / -1; }
  /* Coluna 10 + centro vertical é fórmula de 12 colunas (desktop) — em
     8/4 colunas o cálculo N/--grid-cols estouraria a largura, então
     ≤1023px volta pro posicionamento antigo (float:right + clear:both no
     .project-next-info, como era antes da mudança pro absolute). */
  .project-next-cta {
    position: relative;
    top: auto;
    left: auto;
    transform: none;
    float: right;
  }
  .project-next-info { clear: both; margin-top: 140px; }
}

@media (max-width: 639px) {
  .project-case-media.is-split { flex-direction: column; }
  /* Em coluna, o eixo principal do flex vira a altura — `flex:1 1 0` (base
     0px) some com a altura da caixa, já que o `.project-case-media` pai
     não tem altura própria pra distribuir (bug pré-existente, só ficou
     visível ao medir a caixa de recorte pro parallax). `flex:0 1 auto`
     devolve a altura pro `aspect-ratio` decidir, como nas outras larguras. */
  .project-case-media.is-split > .project-media-crop {
    flex: 0 1 auto;
    aspect-ratio: 4 / 3;
  }
  .project-next-cta { float: none; }
  .project-next-info { margin-top: 32px; }
}

/* ==========================================================================
   Tela de carregamento (Home) — assets/js/splash.js
   Cobre a página até hero, fontes e capas da galeria carregarem. As versões do
   logo (Figma "Logos", node 9:150) trocam em loop (corte seco, sem fade — mesma
   linguagem "em blocos" do resto do site) até a versão principal. `is-loading`
   (posta por um script inline no <head>) trava o scroll e PAUSA a animação de
   entrada do hero; ao terminar a classe sai (o hero entra) e a cortina sobe
   (.is-leaving). Sem JS a classe nunca existe e a tela não aparece.
   ========================================================================== */
.splash {
  --splash-w: clamp(150px, 14vw, 240px); /* largura do logo principal; as outras versões escalam por --k */
  display: none;
  position: fixed;
  inset: 0;
  z-index: 1000;
  align-items: center;
  justify-content: center;
  background: var(--c-bg);
  color: var(--c-text-highlight);
}

html.is-loading .splash,
.splash.is-leaving {
  display: flex;
}

html.is-loading {
  overflow: hidden;
}

html.is-loading .reveal {
  animation-play-state: paused; /* o hero só entra depois da cortina */
}

/* todas as versões empilhadas no mesmo ponto; só a .is-on aparece */
.splash-logos {
  display: grid;
  place-items: center;
}

.splash-logo {
  grid-area: 1 / 1;
  display: block;
  width: calc(var(--splash-w) * var(--k, 1));
  height: auto;
  opacity: 0;
}

.splash-logo.is-on {
  opacity: 1;
}

.splash-label {
  position: absolute;
  left: 0;
  right: 0;
  bottom: clamp(24px, 4vw, 48px);
  text-align: center;
  font-family: var(--font-text);
  font-weight: 400;
  font-size: 14px;
  line-height: 1;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--c-text-subtle);
}

/* Saída: logo e rótulo somem rápido e a cortina sobe. */
.splash.is-leaving {
  pointer-events: none;
  animation: splash-out 0.9s cubic-bezier(0.76, 0, 0.24, 1) 0.15s forwards;
}

.splash.is-leaving .splash-logos,
.splash.is-leaving .splash-label {
  opacity: 0;
  transition: opacity 0.2s ease;
}

@keyframes splash-out {
  to {
    transform: translateY(-100%);
  }
}

@media (prefers-reduced-motion: reduce) {
  .splash.is-leaving {
    animation: splash-fade 0.3s ease forwards;
  }

  @keyframes splash-fade {
    to {
      opacity: 0;
    }
  }
}
