/* ==========================================================================
   Duarte.dev — landing brutalista
   Portado de "Portfolio Landing.dc.html" (Claude Design)
   ========================================================================== */

:root {
  --paper: #F4F2ED;
  --ink: #141414;
  --accent: #B5654A;
  --muted: #8A8A85;

  --rule: 1px solid var(--ink);

  --font-display: 'Archivo', 'Arial Black', sans-serif;
  --font-body: 'Inter', system-ui, -apple-system, sans-serif;
  --font-mono: 'JetBrains Mono', ui-monospace, 'SFMono-Regular', monospace;

  --pad-x: 32px;
  --shell: 1280px;
}

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

html {
  scroll-behavior: smooth;
  background: var(--paper);
}

body {
  margin: 0;
  padding: 0;
  min-width: 320px;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

a { color: var(--ink); }
a:hover { color: var(--accent); }

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

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

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

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { transition: none !important; }
}

/* --- primitivas ---------------------------------------------------------- */

.shell {
  max-width: var(--shell);
  margin: 0 auto;
}

.display {
  font-family: var(--font-display);
  font-stretch: 125%;
  text-transform: uppercase;
}

.mono {
  font-family: var(--font-mono);
}

/* Cabeçalho de seção: régua com numeral monoespaçado. */
.section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  padding: 24px var(--pad-x);
  border-bottom: var(--rule);
}

.section-title {
  font-family: var(--font-display);
  font-stretch: 125%;
  font-weight: 800;
  font-size: 32px;
  text-transform: uppercase;
  letter-spacing: -0.01em;
  margin: 0;
}

.section-title .num {
  font-family: var(--font-mono);
  font-weight: 400;
  font-size: 14px;
  color: var(--muted);
  margin-right: 16px;
}

/* Ocupa o lado direito do .section-head, que já era space-between. Mesmos
   valores da intro do "Incluso", para as duas lerem igual. */
.section-note {
  font-size: 15px;
  line-height: 1.55;
  color: var(--muted);
  max-width: 420px;
  margin: 0;
}

/* Botão-bloco: sem raio, contorno preto, inverte para tinta no hover. */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  background: var(--accent);
  color: var(--paper);
  text-decoration: none;
  font-family: var(--font-display);
  font-stretch: 125%;
  font-weight: 700;
  font-size: 16px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 20px 36px;
  border: var(--rule);
  transition: background-color .12s linear, color .12s linear;
}

.btn:hover,
.btn:focus-visible {
  background: var(--ink);
  color: var(--paper);
}

.btn .arrow {
  font-family: var(--font-mono);
  font-weight: 400;
}

.btn--lg {
  font-size: 18px;
  padding: 24px 44px;
}

/* Marcador quadrado das listas. */
.tick {
  font-family: var(--font-mono);
  color: var(--accent);
  flex: none;
}

/* --- topbar -------------------------------------------------------------- */

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  padding: 16px var(--pad-x);
  border-bottom: var(--rule);
}

.brand {
  font-family: var(--font-display);
  font-stretch: 125%;
  font-weight: 900;
  font-size: 16px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.brand a { text-decoration: none; }

.topnav {
  display: flex;
  gap: 24px;
  font-family: var(--font-mono);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.topnav a { text-decoration: none; }

.status {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--muted);
}

.status .dot {
  width: 8px;
  height: 8px;
  background: var(--accent);
  display: inline-block;
  flex: none;
}

.status--waitlist .dot { background: var(--muted); }

/* --- 1. hero ------------------------------------------------------------- */

/* Tela cheia com o conteúdo centrado na vertical. O container para em
   1600px para o texto não se esticar em ultrawide. */
.hero {
  /* Sobreposição no scroll: a hero fica presa no topo e a .page-flow desliza
     por cima dela. CSS puro, sem JS.
     Substitui o position: relative que vinha do bloco de divisórias no fim do
     arquivo — lá o .hero foi removido da lista, senão ele venceria a cascata
     por vir depois. Sticky também é bloco containing dos absolutos internos,
     que era o papel do relative. */
  position: sticky;
  top: 0;
  z-index: 1;
  border-bottom: var(--rule);
  min-height: 100vh;
  display: flex;
  /* stretch, nao center: o .hero__inner precisa preencher a altura para as
     duas linhas do grid conceitual existirem. */
  align-items: stretch;
  /* Base da pilha, declarada aqui e não herdada do body. A ordem completa
     está documentada logo abaixo, em .hero__grid. */
  background: var(--paper);
  /* O respiro acompanha a altura da tela: em telas baixas ele encolhe em
     vez de espremer o conteúdo para fora dos 100vh. */
  padding: clamp(56px, 8vh, 96px) var(--pad-x);
}

/* Bloco que agrupa tudo depois da hero. Passa por cima dela no scroll.
   O fundo opaco é o que esconde a hero presa atrás — sem ele os dois se
   sobrepõem visualmente. */
.page-flow {
  position: relative;
  z-index: 2;
  background: var(--paper);
}

/* Empilhamento do hero, de baixo para cima:
   papel (fundo do .hero) → grade (0) → halo (1) → esfera (2) → grão (3) → texto (4).

   Tudo em índices não negativos de propósito. Agora o .hero abre contexto de
   empilhamento próprio (position sticky + z-index 1), então esses cinco
   índices só competem entre si — nada aqui dentro alcança a .page-flow, e a
   hero inteira é comparada com ela por um número só, o z-index 1.
   Ainda assim, nada de índice negativo: uma camada negativa seria pintada
   antes do fundo papel do próprio .hero e sumiria. */

/* O passo da grade é o --pad-x, o mesmo recuo lateral de toda seção da
   página — as linhas caem alinhadas às margens do conteúdo. Ele cai para
   20px abaixo de 640px, então a grade adensa junto com o resto do layout. */
.hero__grid {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image:
    linear-gradient(to right,  rgba(20, 20, 20, .05) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(20, 20, 20, .05) 1px, transparent 1px);
  background-size: var(--pad-x) var(--pad-x);
}

/* Halo atrás da esfera. radial-gradient e não box-shadow/filter: gradiente
   é rasterizado uma vez e composto — não recalcula por quadro.

   O diâmetro segue o regime que dimensiona a esfera no hero-sphere.js:
   - desktop: o raio projetado é ~0.674 × altura do hero, então
     1.6 × 0.674 ≈ 108% da altura;
   - telas estreitas (≤900px): o piso de largura trava a esfera em 84% da
     largura, então 1.6 × 0.84 ≈ 134% da largura. */
.hero__halo {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  overflow: hidden;   /* o círculo excede o hero de propósito; recorta aqui */
}

.hero__halo::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  height: 108%;
  aspect-ratio: 1;
  background: radial-gradient(closest-side,
    rgba(181, 101, 74, 0.38),
    rgba(181, 101, 74, 0) 100%);
}

.hero__grain {
  position: absolute;
  inset: 0;
  z-index: 3;
  width: 100%;
  height: 100%;
  opacity: 0.16;
  pointer-events: none;
}

/* Este wrapper tem a largura toda do container e fica no topo da pilha,
   então cobre a faixa da esfera inteira. Fundo transparente não tira nada do
   hit-test: ele engolia todo evento de mouse destinado ao canvas atrás. Por
   isso o pointer-events: none aqui — e não só na coluna de texto. */
/* Grade conceitual 2x2. Colunas assimetricas de proposito: a esquerda
   recebe 1.35fr para a headline caber em duas linhas — com 1fr ela ficaria
   mais estreita que os 55% de antes e quebraria mais, nao menos.

   Linha 1 e auto (so as etiquetas), linha 2 leva o resto e alinha ao fim,
   o que joga texto e CTA para a metade inferior.

   padding-right reserva a faixa do indicador role, que fica na lateral
   direita e passaria por baixo das etiquetas e do CTA. */
.hero__inner {
  position: relative;
  z-index: 4;
  width: 100%;
  max-width: 1600px;
  margin: 0 auto;
  padding-right: 52px;
  pointer-events: none;

  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
  grid-template-rows: auto 1fr;
  column-gap: 48px;
  align-items: end;
}

.hero__stack {
  /* Atravessa as duas colunas em vez de morar so na segunda. Visualmente ela
     continua no quadrante superior direito por causa do justify-self, mas
     assim a linha de etiquetas para de ditar a largura minima da coluna do
     CTA — e a coluna esquerda pode crescer o quanto a headline precisa. */
  grid-column: 1 / -1;
  grid-row: 1;
  justify-self: end;
  align-self: start;
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  align-items: center;
  gap: 14px;
  margin: 0;
  padding: 0;
  list-style: none;
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--muted);
}

/* Divisor entre etiquetas: régua de 1px, no lugar de um caractere. */
.hero__stack li {
  display: flex;
  align-items: center;
  gap: 14px;
}

.hero__stack li + li::before {
  content: "";
  width: 1px;
  height: 9px;
  background: currentColor;
  opacity: 0.45;
}

.hero__text {
  grid-column: 1;
  grid-row: 2;
}

.hero__cta {
  grid-column: 2;
  grid-row: 2;
  justify-self: end;
}

/* Sem max-width proprio: a largura vem da coluna 1 do grid. */
.hero__text {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  background: transparent;
  pointer-events: none;
}

/* Único elemento interativo do bloco: volta a receber evento. O foco por
   teclado nunca dependeu disto — pointer-events não afeta tabulação. */
.hero__cta {
  pointer-events: auto;
}

/* Camada do canvas: cobre o hero inteiro, não é mais uma coluna.

   O multiplicador de canvas do hero-sphere.js foi para 1 junto com esta
   mudança, então o canvas mede exatamente o container e não há mais o que
   recortar — o overflow: hidden que existia aqui saiu com ele.

   pointer-events fica em auto: sem isso o cursor, o drag e o clique da
   esfera não recebem evento nenhum. Quem se protege disso é o bloco de
   texto, que tem pointer-events: none com auto só no CTA. */
.hero__art {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 2;        /* acima do halo, abaixo do grão e do texto */
}

.hero__eyebrow {
  font-family: var(--font-mono);
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
  margin: 0 0 clamp(16px, 3.5vh, 32px);
}

/* Elemento dominante da tela — ~6× o corpo do subtítulo.
   Dois limites, e vale o menor:
     8.8vw  cabe na coluna de 55% (o teto de 148px é o que "VENDER", a
            palavra mais longa, comporta nos 880px da coluna saturada);
     12vh   cabe na altura da tela. Sem esse termo, uma janela larga e
            baixa quebra a headline em quatro linhas que estouram os
            100vh e empurram o CTA para fora. */
.hero__title {
  font-family: var(--font-display);
  font-stretch: 125%;
  font-weight: 900;
  /* Dimensionada para que "Sites feitos / para vender" caiba em duas linhas
     dentro da coluna esquerda do grid 2x2. A linha mais larga da quebra pede
     ~9.2x o font-size, e a coluna esquerda vale ~0.53 da viewport — dai o
     teto de 5.3vw. O 8.6vh cobre as telas largas e baixas, onde a altura e
     que aperta. */
  font-size: clamp(46px, min(5.3vw, 8.6vh), 96px);
  line-height: 0.92;
  letter-spacing: -0.025em;
  text-transform: uppercase;
  text-wrap: balance;
  margin: 0 0 clamp(20px, 4.4vh, 40px);
}

/* 560px a 19px dá ~62 caracteres por linha, dentro da faixa legível. */
/* margin-bottom zerado de proposito. Ele existia para separar o subtitulo do
   CTA, que morava logo abaixo dentro deste mesmo bloco; com o CTA promovido a
   celula propria do grid, essa margem virou vao morto no rodape da caixa de
   texto — e como as duas celulas se alinham pelo fim da linha, era ela que
   deixava o botao flutuando acima da base do subtitulo. */
.hero__lede {
  font-size: 17px;
  line-height: 1.55;
  max-width: 560px;
  margin: 0;
}

/* Indicador de scroll, no rodapé da seção. Ancorado à esquerda para não
   colidir com o rótulo da divisória, que fica à direita. */
/* Lateral direita, na vertical. Com a esfera centralizada o flanco direito
   ficou vazio, e o rotulo da divisoria ja ocupa o canto inferior — empilhar
   os dois ali amontoaria. writing-mode gira o texto sem transform, entao a
   caixa continua participando do layout normalmente. */
.hero__scroll {
  position: absolute;
  z-index: 4;   /* acima do grão, como o resto do conteúdo */
  right: var(--pad-x);
  top: 50%;
  transform: translateY(-50%);
  writing-mode: vertical-rl;
  display: flex;
  align-items: center;
  gap: 12px;
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--muted);
  text-decoration: none;
}

.hero__scroll:hover { color: var(--accent); }

.hero__scroll-line {
  display: block;
  width: 1px;      /* eixos trocados: no writing-mode vertical a regua desce */
  height: 56px;
  background: currentColor;
}

/* --- 2. cases ------------------------------------------------------------ */

.cases { border-bottom: var(--rule); }

.case {
  border-bottom: var(--rule);
  padding: 88px var(--pad-x);
}

.case__grid {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  gap: 56px;
  align-items: flex-start;
}

/* Alternância par/ímpar — desligada no mobile (imagem sempre acima). */
.case--flip .case__grid { flex-direction: row-reverse; }

/* Moldura de navegador. */
.browser {
  flex: 3 1 520px;
  min-width: 320px;
  border: var(--rule);
}

.browser__bar {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 12px;
  border-bottom: var(--rule);
}

.browser__dots {
  display: flex;
  gap: 5px;
  flex: none;
}

.browser__dots span {
  width: 7px;
  height: 7px;
  border: var(--rule);
  display: block;
}

.browser__url {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Proporção fixa em vez de altura fixa: o recorte é o mesmo em qualquer
   largura de tela. 5/3 é a proporção que o frame já tinha no desktop. */
.shot {
  aspect-ratio: 5 / 3;
  position: relative;
  overflow: hidden;
  background: rgba(127, 127, 127, .08);
}

/* Screenshots de página inteira: ancoradas no topo, como no canvas. */
.shot img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
}

/* Slot vazio — mesmo tratamento do <image-slot> sem imagem. */
.shot--empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  text-align: center;
  padding: 12px;
}

.shot--empty::after {
  content: "";
  position: absolute;
  inset: 0;
  border: 1.5px dashed currentColor;
  opacity: .35;
  pointer-events: none;
}

.shot--empty svg { opacity: .45; }

.shot__cap {
  max-width: 90%;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: .01em;
  opacity: .75;
}

.case__body {
  flex: 2 1 320px;
  min-width: 280px;
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.tag {
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  border: var(--rule);
  padding: 4px 10px;
  align-self: flex-start;
}

.case__title {
  font-family: var(--font-display);
  font-stretch: 125%;
  font-weight: 900;
  font-size: clamp(28px, 3vw, 44px);
  line-height: 1;
  text-transform: uppercase;
  letter-spacing: -0.01em;
  margin: 0;
}

.case__desc {
  font-size: 16px;
  line-height: 1.6;
  margin: 0;
}

.case__bullets {
  margin: 8px 0 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  border-top: var(--rule);
}

.case__bullets li {
  display: flex;
  align-items: baseline;
  gap: 14px;
  padding: 12px 0;
  border-bottom: var(--rule);
  font-size: 14px;
  line-height: 1.5;
}

.case__bullets .tick { font-size: 10px; }

/* --- 3. processo --------------------------------------------------------- */

.process { border-bottom: var(--rule); }

/* Grade selada: a sobreposição de -1px funde as bordas adjacentes numa só. */
.grid-sealed {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  overflow: hidden;
}

.grid-sealed > * {
  background: var(--paper);
  border-right: var(--rule);
  border-bottom: var(--rule);
  margin-right: -1px;
  margin-bottom: -1px;
}

.step {
  padding: 32px 24px 48px;
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.step__num {
  font-family: var(--font-display);
  font-stretch: 125%;
  font-weight: 900;
  font-size: 64px;
  line-height: 1;
  color: var(--paper);
  -webkit-text-stroke: 1px var(--ink);
}

.step__title {
  font-family: var(--font-display);
  font-stretch: 125%;
  font-weight: 800;
  font-size: 18px;
  text-transform: uppercase;
  margin: 0;
}

.step p {
  font-size: 14px;
  line-height: 1.55;
  margin: 0;
}

/* --- 4. incluso ---------------------------------------------------------- */

.included {
  border-bottom: var(--rule);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
  overflow: hidden;
}

.included > * {
  background: var(--paper);
  border-right: var(--rule);
  border-bottom: var(--rule);
  margin-right: -1px;
  margin-bottom: -1px;
}

.included__intro { padding: 32px; }

.included__intro .section-title { margin: 0 0 16px; }

.included__intro p {
  font-size: 15px;
  line-height: 1.55;
  color: var(--muted);
  max-width: 400px;
  margin: 0;
}

.included__list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
}

.included__list li {
  display: flex;
  align-items: baseline;
  gap: 16px;
  padding: 14px var(--pad-x);
  border-bottom: var(--rule);
  font-size: 15px;
}

.included__list .tick { font-size: 12px; }

/* --- 5. sobre ------------------------------------------------------------ */

.about {
  border-bottom: var(--rule);
  padding: 72px var(--pad-x);
}

.about__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 48px;
}

.about__text {
  display: flex;
  flex-direction: column;
  gap: 20px;
  max-width: 640px;
}

.about__text p {
  font-size: 16px;
  line-height: 1.6;
  margin: 0;
}

.about__text p.about__lab {
  font-family: var(--font-mono);
  font-size: 12px;
  margin: 8px 0 0;
}

.about__lab a {
  color: var(--muted);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* --- 6. cta final -------------------------------------------------------- */

.cta {
  padding: 96px var(--pad-x);
  border-bottom: var(--rule);
}

.cta__inner {
  display: flex;
  flex-direction: column;
  gap: 40px;
  align-items: flex-start;
}

.cta__title {
  font-family: var(--font-display);
  font-stretch: 125%;
  font-weight: 900;
  font-size: clamp(40px, 6vw, 96px);
  line-height: 0.98;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  text-wrap: balance;
  margin: 0;
}

.cta p {
  font-size: 17px;
  line-height: 1.55;
  color: var(--muted);
  max-width: 520px;
  margin: 0;
}

/* --- rodapé -------------------------------------------------------------- */

.footer {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  padding: 20px var(--pad-x);
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

/* --- responsivo ---------------------------------------------------------- */

/* Tablet: a alternância dos cases cai — imagem acima, texto abaixo, sempre. */
@media (max-width: 900px) {
  .case__grid,
  .case--flip .case__grid {
    flex-direction: column;
    gap: 32px;
  }

  .browser,
  .case__body {
    flex: 1 1 auto;
    width: 100%;
    min-width: 0;
  }

  .case { padding: 56px var(--pad-x); }

  /* --- hero mobile ------------------------------------------------------
     svh e não vh: o vh do iOS conta a barra de endereço retraída, então a
     seção nasceria mais alta que a tela e empurraria o CTA para fora. */
  .hero {
    min-height: 88svh;   /* 80svh + 10% */
    align-items: flex-end;
    padding: 0 var(--pad-x) 32px;

    /* Sobreposição desligada aqui, mesma linha de corte do scroll imersivo.
       O motivo é o canvas: a esfera agenda requestAnimationFrame sem parar
       (rotationSpeed vem de speed: 8, é const e nunca chega a zero), então
       com sticky ela continuaria dentro da viewport, viva e composta, durante
       a página inteira em vez de sair de vista depois do hero. Em GPU de
       celular isso é candidato a engasgo no scroll.
       Continua relative: as camadas internas absolutas dependem disso.
       Para reativar no mobile, basta apagar esta linha. */
    position: relative;
  }

  /* O indicador de scroll é pedido só no desktop, e no mobile ele custaria
     56px de altura justamente onde o orçamento é mais apertado. */
  .hero__scroll { display: none; }

  /* Sem faixa de 55%: o canvas cobre o hero inteiro aqui também, e o texto
     passa a ficar por cima dele em vez de abaixo. */

  /* Tela estreita: a esfera é travada em 84% da largura pelo piso do
     hero-sphere.js, então o halo troca de eixo junto. */
  .hero__halo::before {
    height: auto;
    width: 134%;
    aspect-ratio: 1;
  }

  /* Desfaz a grade 2x2: abaixo de 900px o hero volta a empilhar em bloco,
     na mesma ordem de antes. */
  .hero__inner {
    display: block;
    max-width: none;
    padding-right: 0;
  }

  /* As etiquetas sao exclusivas do quadrante superior direito. Mostra-las
     aqui mudaria a estrutura do mobile, que era para ficar como estava. */
  .hero__stack { display: none; }

  .hero__text {
    max-width: none;
    width: 100%;
  }

  .hero__eyebrow { font-size: 11px; margin: 0 0 clamp(12px, 2vh, 20px); }

  /* Segue dominando a área de texto, mas quem manda é a largura: a proporção
     exata do desktop (~6,8× o corpo) daria 109px, e "VENDER" a 109px não cabe
     nos 335px de coluna de um telefone.

     Exatamente duas linhas: "SITES FEITOS / PARA VENDER".
     Medido na Archivo 900 com font-stretch 125% e letter-spacing -0.025em,
     em multiplos do font-size:
       "PARA VENDER" (a linha larga da quebra)  9.202x
       o titulo inteiro numa linha so           18.152x
     A coluna vale a largura da tela menos 2x --pad-x. Duas linhas pedem
     font-size acima de colW/18.152 (abaixo disso cabe tudo em uma) e nao
     mais que colW/9.202 (acima disso nasce a terceira). Em fracao da
     viewport o teto mais apertado da faixa e 0.0951, aos 320px; o piso mais
     alto e 0.0517, aos 899px. 9.2vw fica dentro dos dois com folga em toda a
     faixa de 320 a 899px.

     Sem o termo em vh que havia aqui: a quebra de linha depende da largura,
     nao da altura, e um vh curto derrubava o corpo abaixo do piso de uma
     linha so. O teto de 76px e o mesmo de antes e nao chega a produzir uma
     linha unica — precisaria de uma coluna de 1379px, e aqui ela nao passa
     de 835px. */
  .hero__title {
    font-size: min(9.2vw, 76px);
    margin: 0 0 clamp(14px, 1.9vh, 24px);
  }

  /* Reduzido para diminuir as quebras de linha. 15px fica abaixo do piso
     de 16px que evita o zoom automatico do iOS — vale para campos de
     formulario, nao para texto corrido, entao aqui e seguro. */
  .hero__lede {
    font-size: 14px;
    max-width: none;
    /* Repoe a margem que o desktop zera: aqui o empilhamento e em bloco e o
       CTA continua vindo logo abaixo, entao a separacao ainda e necessaria. */
    margin: 0 0 clamp(16px, 2.5vh, 28px);
  }

  /* Especificidade 0,2,0 para vencer o .btn do bloco de 640px, que vem
     depois no arquivo e reporia 15px. */
  .hero__inner .hero__cta {
    width: 100%;
    justify-content: space-between;
    font-size: 13px;
    padding: 16px 22px;
  }
}

@media (max-width: 640px) {
  :root { --pad-x: 20px; }

  .topbar {
    align-items: flex-start;
    gap: 12px;
  }

  .topnav {
    order: 3;
    width: 100%;
    gap: 16px;
    flex-wrap: wrap;
  }

  .btn,
  .btn--lg {
    font-size: 15px;
    padding: 18px 28px;
    width: 100%;
    justify-content: space-between;
  }

  .section-title { font-size: 26px; }
  .section-title .num { margin-right: 12px; }

  .about { padding: 56px var(--pad-x); }
  .cta { padding: 72px var(--pad-x); }
  .footer { gap: 8px; }
}

@media print {
  .topnav, .btn { display: none; }
}

/* ==========================================================================
   CAMADA DE SISTEMA VISUAL
   Marcação estrutural sobreposta ao layout — não participa do fluxo.
   Tudo aqui é aditivo: remover este bloco (e as classes correspondentes no
   HTML) devolve a página ao estado anterior.
   ========================================================================== */

:root {
  /* Cruzeta de registro, 9×9, na cor de acento. Fica em background-image
     para marcar os 4 cantos sem exigir 4 elementos no DOM. */
  --mark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='9' height='9' fill='none' stroke='%23B5654A' stroke-width='1'%3E%3Cpath d='M4.5 .5v8M.5 4.5h8'/%3E%3C/svg%3E");
}

/* --- 1. eyebrow labels --------------------------------------------------- */

.eyebrow {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--accent);
  margin: 0 0 10px;
}

/* Agrupadores: existem só para o eyebrow e o título contarem como um item
   no flex/grid do pai, preservando a contagem de colunas original. */
.cta__head {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.cta__head .eyebrow { margin: 0; }

/* --- 2. numeração de série ----------------------------------------------- */

.case__grid { position: relative; }

/* Fica inteiramente acima da linha de conteúdo (bottom: 100%), dentro do
   respiro que o .case já tinha — por isso não desloca nada. */
.case__index {
  position: absolute;
  bottom: 100%;
  right: 0;
  margin-bottom: -0.1em;
  font-family: var(--font-display);
  font-stretch: 125%;
  font-weight: 900;
  font-size: clamp(40px, 5.5vw, 80px);
  line-height: 1;
  letter-spacing: -0.02em;
  color: rgba(20, 20, 20, .10);
  pointer-events: none;
  user-select: none;
}

/* --- 3. marcadores de grid ----------------------------------------------- */

.marks { position: relative; }

.marks::after {
  content: "";
  position: absolute;
  inset: 5px;
  background-image: var(--mark), var(--mark), var(--mark), var(--mark);
  background-position: left top, right top, left bottom, right bottom;
  background-repeat: no-repeat;
  pointer-events: none;
}

/* Variante externa: a cruzeta monta em cima do canto, em vez de recuar para
   dentro. Só serve onde nenhum ancestral tem overflow: hidden — nas células
   das grades seladas ela seria cortada, e lá vale a versão interna. */
.marks--out::after { inset: -5px; }

/* --- 4. divisórias com label --------------------------------------------- */

/* A .hero ficou de fora desta lista de propósito: ela recebe position: sticky
   lá em cima e este bloco, por vir depois com a mesma especificidade, venceria
   a cascata e devolveria relative — matando a sobreposição no scroll. Sticky
   também estabelece bloco containing para os absolutos, então a .rule-label
   dela continua ancorada igual. */
.cases,
.process,
.about { position: relative; }

/* Senta em cima da régua de 1px que já separa as seções, abrindo um vão no
   traço com o fundo do papel. */
.rule-label {
  position: absolute;
  z-index: 4;   /* no hero, precisa passar por cima do grão */
  right: var(--pad-x);
  bottom: 0;
  transform: translateY(50%);
  background: var(--paper);
  padding: 0 10px;
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--muted);
  white-space: nowrap;
  pointer-events: none;
}

/* A fronteira #incluso|#sobre é rotulada a partir de baixo: .included tem
   overflow: hidden e cortaria o label pela metade. */
.rule-label--top {
  bottom: auto;
  top: 0;
  transform: translateY(-50%);
}

@media (max-width: 640px) {
  .eyebrow { font-size: 10px; letter-spacing: 0.14em; }
  .case__index { font-size: 40px; }
  .rule-label { font-size: 9px; padding: 0 8px; }
}

/* ==========================================================================
   VISUALIZAÇÃO COMPLETA
   Overlay que mostra o screenshot fullpage inteiro, na largura de um
   navegador desktop, com rolagem interna.
   ========================================================================== */

/* Gatilho — mesma linguagem da .tag, com área de clique de botão. */
.case__expand {
  align-self: flex-start;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--ink);
  background: transparent;
  border: var(--rule);
  border-radius: 0;
  padding: 9px 14px;
  cursor: pointer;
  transition: background-color .12s linear, color .12s linear;
}

.case__expand:hover,
.case__expand:focus-visible {
  background: var(--ink);
  color: var(--paper);
}

/* O display: flex abaixo venceria o [hidden] do user-agent por
   especificidade — o estado fechado precisa ser declarado aqui. */
.viewer[hidden] { display: none; }

.viewer {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 56px 24px 24px;
  background: rgba(20, 20, 20, .88);
}

/* A moldura repete o frame do case: fundo papel, régua de 1px, canto vivo. */
.viewer__stage {
  display: flex;
  flex-direction: column;
  width: min(1280px, 100%);
  max-height: 100%;
  background: var(--paper);
  border: var(--rule);
}

/* Igual à .browser__bar; fica fixa enquanto a página rola por baixo. */
.viewer__bar {
  flex: none;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 12px;
  border-bottom: var(--rule);
}

.viewer__url {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.viewer__scroll {
  overflow-y: auto;
  overscroll-behavior: contain;   /* a rolagem não vaza para o fundo travado */
  -webkit-overflow-scrolling: touch;
}

.viewer__img {
  display: block;
  width: 100%;
  height: auto;
}

/* X no canto superior direito, sobre o fundo escuro: inverte as cores da
   régua, mesma mecânica de hover do .btn. */
.viewer__close {
  position: absolute;
  top: 12px;
  right: 16px;
  width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-size: 18px;
  line-height: 1;
  color: var(--paper);
  background: transparent;
  border: 1px solid var(--paper);
  border-radius: 0;
  cursor: pointer;
  transition: background-color .12s linear, color .12s linear;
}

.viewer__close:hover,
.viewer__close:focus-visible {
  background: var(--paper);
  color: var(--ink);
}

@media (max-width: 640px) {
  .viewer { padding: 52px 12px 12px; }
  .viewer__close { top: 8px; right: 12px; }
}

/* ==========================================================================
   SCROLL IMERSIVO — CASE 001 (GSAP + ScrollTrigger)
   Nada aqui depende de media query: quem decide se o efeito existe é o
   gsap.matchMedia() do script.js, que adiciona .is-immersive ao trilho.
   Fonte única de verdade — sem .is-immersive (tela estreita,
   prefers-reduced-motion, ou CDN fora do ar) o case 001 fica idêntico aos
   outros, com o botão de overlay visível.
   ========================================================================== */

/* Sem o pin do ScrollTrigger o trilho não tem altura própria: ele é só o
   elemento de gatilho. A distância de scroll vem do end: "+=600%". */

/* Com o efeito ativo o botão de overlay é redundante. */
.case-track.is-immersive .case__expand { display: none; }

/* O translateY da fase 2 precisa da altura natural da captura para ter
   curso. Visualmente idêntico ao cover ancorado no topo, porque a captura
   é mais alta que a moldura — o crop em repouso não muda. */
.case-track.is-immersive .shot img { height: auto; }

/* Empilhamento durante o efeito: a moldura fica acima da camada de
   desfoque, que por sua vez fica acima do texto e da numeração. É isso que
   faz o blur pegar só o fundo. */
.case-track.is-immersive .browser { z-index: 2; }

/* A divisória entre os cases é o border-bottom do próprio .case — e o .case
   é o elemento pinado, então a linha viaja com ele e fica parada no meio da
   animação enquanto todo o resto sai. Não dá para animá-la pela opacidade do
   .case (levaria a moldura junto), então a borda vira transparente e a linha
   passa a ser desenhada por um pseudo-elemento com opacidade própria.
   A largura da borda não muda: zero deslocamento de layout. */
.case-track.is-immersive .case {
  position: relative;
  border-bottom-color: transparent;
  --rule-op: 1;   /* precisa estar declarado — ver a nota em .marks */
}

.case-track.is-immersive .case::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;   /* a faixa exata que a borda ocupa */
  height: 1px;
  background: var(--ink);
  opacity: var(--rule-op);
  pointer-events: none;
}

.case__defocus {
  position: absolute;
  /* Sangra só na vertical. Com -64px nos quatro lados a camada passava da
     borda da viewport e criava scroll horizontal — o .case__grid já encosta
     no padding da seção, então não há folga lateral para sangrar. */
  inset: -64px 0;
  z-index: 1;
  opacity: 0;
  pointer-events: none;
  /* Valor FIXO. Só a opacidade acima é animada — o blur nunca interpola. */
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
}

/* As cruzetas de canto precisam de um alvo animável: o pseudo-elemento não
   é acessível ao GSAP, então a opacidade dele vem de uma custom property.
   O valor 1 precisa estar DECLARADO, não só no fallback do var(): o GSAP lê
   o computed style para descobrir de onde partir, e uma property não
   declarada resolve como vazio — a moldura começaria com as cruzetas
   apagadas. Os cases 002–006 seguem com opacidade 1, como sempre. */
.marks { --mark-op: 1; }
.marks::after { opacity: var(--mark-op); }
