/* ============================================================
   KAND™ — site.css
   Tokens no topo: cor, tipo e espaçamento saem daqui e de lugar
   nenhum mais. Reskin do site inteiro = editar este bloco.
   ============================================================ */

/* Light (300): só a frase grande de abertura do The Team (68). Medido no
   frame 13: haste de 7px a 2x, igual à da Light e longe da Regular (11).
   Os cinco pesos são reduzidos ao MESMO conjunto de 180 caracteres —
   o de antes mais ← e ↓, que faltavam: o "[←] Back to campaigns" caía
   numa fonte do sistema justo na seta. */
@font-face {
  font-family: "IBM Plex Mono";
  src: url("../fonts/IBMPlexMono-Light.woff2") format("woff2");
  font-weight: 300; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("../fonts/IBMPlexMono-Regular.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("../fonts/IBMPlexMono-Medium.woff2") format("woff2");
  font-weight: 500; font-style: normal; font-display: swap;
}
/* SemiBold (600): o item ativo do menu e os rótulos do novo desenho.
   Veio da dupla em TTF completo (930 caracteres); foi convertido para
   woff2 e reduzido ao MESMO conjunto dos outros pesos —
   7,5 KB em vez de ~100 KB, e nenhum caractere que exista num peso e
   falte no outro. Métricas idênticas às do Medium (ascendente 1025,
   descendente 275, maiúscula 698), então o alinhamento pela maiúscula
   do cabeçalho e do rodapé vale igual. */
@font-face {
  font-family: "IBM Plex Mono";
  src: url("../fonts/IBMPlexMono-SemiBold.woff2") format("woff2");
  font-weight: 600; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("../fonts/IBMPlexMono-Bold.woff2") format("woff2");
  font-weight: 700; font-style: normal; font-display: swap;
}

:root {
  /* --- cor ------------------------------------------------
     Do direcional de 11/10: fundo #f0f0f0, texto #4b4b4b, secundário
     #9b9b9b. A linha divisória medida nos frames é #dfdfdf — escrita
     aqui como o próprio texto a 12%, para continuar certa no tema
     escuro sem uma segunda conta. */
  --paper:    #f0f0f0;
  --ink:      #4b4b4b;
  --ink-mid:  #9b9b9b;
  --rule:     rgba(75, 75, 75, .12);
  --frame:    rgba(75, 75, 75, .06);   /* moldura de imagem que falhou */

  /* --- ESCALA ---------------------------------------------
     A página inteira é desenhada numa janela de 1710×900 (MacBook Air
     13 em "More Space", área do navegador) e, em qualquer outra largura,
     ela ESCALA: mesmas coisas, mesmos lugares, tamanhos proporcionais.
     Decisão da dupla, sem tamanho mínimo.

     --u é "um pixel do desenho". Todo tamanho do layout é N × --u —
     fonte, margem, grid, vão. Numa tela de 1710, --u = 1px; numa de
     1440, 0,842px; numa de 2560, 1,497px.

     Os frames são imagens de 3420×1800 (retina), e os números do grid
     foram passados nessa escala: 120 / 35 / 10. Em CSS caem pela metade.
     Conferido nas linhas vermelhas do ComGrid: margem 60, topo/base 17,5,
     12 colunas de 127,92 com vão de 5, 10 linhas de 82. Já as fontes do
     mapa de tamanhos estão na escala de 1710 — o texto do PDF é real, e
     os tamanhos lidos dele são 11, 14, 16, 18, 26, 36,6 e 68.

     Abaixo de 1024px a escala desliga (bloco no fim desta seção): num
     telefone, 14px escalados dariam 3px. */
  --u:      calc(100vw / 1710);
  --m-x:    calc(60   * var(--u));     /* margem esquerda e direita */
  --m-y:    calc(17.5 * var(--u));     /* margem de cima e de baixo */
  --gutter: calc(5    * var(--u));     /* vão entre colunas, entre linhas, entre imagens */
  --row:    calc(82   * var(--u));     /* altura de uma das 10 linhas do grid */

  --t-11: calc(11   * var(--u));       /* menu, rodapé, rótulos */
  --t-14: calc(14   * var(--u));       /* rótulos de seção, listas, numeração */
  --t-16: calc(16   * var(--u));       /* título no card da home */
  --t-18: calc(18   * var(--u));       /* texto corrido */
  --t-26: calc(26   * var(--u));       /* descrição do projeto */
  --t-36: calc(36.6 * var(--u));       /* nome na lista de Branding */
  --t-68: calc(68   * var(--u));       /* título do projeto, abertura do The Team */

  /* --- tipo -----------------------------------------------
     ESCALA DO SITE. Sete degraus, cada um com um uso declarado.
     Qualquer tamanho novo sai daqui — nada de número solto numa
     regra, senão a pasta volta a não ter padrão.

     Em mono toda letra ocupa 0,6em, então um corpo que funciona
     numa sans parece pequeno aqui: por isso o piso é mais alto
     do que pareceria necessário. */
  --mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  /* Os nomes antigos da escala continuam valendo e passam a apontar para
     a régua nova. É isso que faz o site inteiro mudar de uma vez na
     fase 1: cada regra que já usava --t-body passa a escalar com a
     página, sem ninguém reescrever regra por regra. As fases 2 e 3 vão
     trocando os nomes antigos pelos novos, página a página. */
  --t-micro: var(--t-11);                 /* nav, rodapé, rótulos, numerais */
  --t-small: var(--t-14);                 /* listas: clientes, prêmios, créditos */
  --t-body:  var(--t-18);                 /* texto corrido */
  --t-sect:  var(--t-14);                 /* títulos de seção: SEMIBOLD 14 no desenho */
  --t-lead:  var(--t-26);                 /* descrição do projeto, no topo */
  --t-group: var(--t-36);                 /* nomes da lista de Branding */
  --t-title: var(--t-68);                 /* título do projeto */

  /* O corpo desceu de 1,45vw para 1,28vw (20,9px → 18,4px numa tela de
     1440, que é o MacBook 13" da dupla). Mono ocupa 0,6em por letra, então
     20,9px aqui pesava como uns 26px de uma sans — a queixa veio de duas
     páginas diferentes no mesmo documento, o que é sinal de régua errada e
     não de página errada. Por isso o ajuste é no token, não por página.
     Efeito medido na coluna de 652px do The Team: 52 → 59 caracteres por
     linha. O título de tópico do Branding desceu junto, de 37,4px para
     28px: ele precisa caber uma frase inteira, não só uma palavra. */

  /* Tracking ZERO. Medido nos frames: "CAMPAIGNS" a 11px ocupa 58px —
     exatamente os 0,6em por letra da Plex Mono, sem espaço a mais. O
     .06em antigo abria a palavra em ~6px e tirava o menu do lugar. */
  --track-micro: 0;

  /* --- escala do The Team ----------------------------------
     Medida no site que a dupla trouxe como referência
     (simonholm.studio/about), numa janela de 1440:

       rótulo de seção   12,06px · peso 500 · tracking 0,028em · lh 1,2
       prosa             14,40px · peso 400 · entrelinha 1,6
       linha de lista    12,06px · peso 400 · tracking 0,044em

     Em vw isso é 0,837vw e 1,0vw. O PISO não é enfeite: 0,837vw num
     telefone de 390px daria 3,3px. O teto existe porque num monitor de
     2560 a fórmula passaria de 21px e a página deixaria de ser densa,
     que é justamente o ponto da referência.

     Estes tokens valem só dentro de [data-page="team"]. O resto do site
     continua na escala de sempre: uma página de projeto não tem lista
     nenhuma para adensar, e encolher o texto de um projeto seria
     resolver um problema que ele não tem. */
  --t-rotulo: var(--t-14);
  --t-prosa:  var(--t-14);
  --track-ref:    0;
  --track-rotulo: 0;
  /* O respiro entre as três faixas do The Team. Menor que o da grade
     antiga de duas colunas: com três faixas, 72px de vão comiam 144px de
     largura útil e espremiam a medida do texto. */
  --gut-team: clamp(20px, 3vw, 56px);

  /* --- espaço --------------------------------------------- */
  /* Margem lateral da página. Era clamp(14px, 2.2vw, 36px) — 31,7px numa
     tela de 1440, que é margem que quase não se vê. O cliente pediu mais
     respiro e escolheu ~100px a 1440: 7vw, sem teto, para que a margem
     continue proporcional em telas largas em vez de travar e deixar o
     conteúdo esticar sozinho.

     Um valor só governa a página inteira — header, rodapé, blocos,
     The Team, Contact — porque todos já leem daqui. O conteúdo não é
     redesenhado: ele encolhe junto, e as proporções se mantêm porque
     saem de tokens e de aspect-ratio, não de pixels escritos à mão.

     7vw (≈101px a 1440) foi longe demais no olho da dupla. 4,5vw cai
     quase no meio exato entre os 31,7px de antes e os 100,8px daquela
     versão: ≈65px a 1440.

     O piso de 14px é o mesmo de sempre e só entra abaixo de ~311px de
     largura. Acima disso quem manda é o vw — e a 375px isso dá 17px,
     praticamente a margem que o telefone já tinha. */
  /* Agora sai do grid do direcional: 60 de 1710, escalando junto. Os
     4,5vw anteriores davam 77px a 1710; os 60 do desenho são 3,51vw. */
  --gut: var(--m-x);                 /* margem lateral da página */

  /* --- movimento ------------------------------------------ */
  --ease:  cubic-bezier(.65, 0, .35, 1);  /* ease-in-out simétrico */
  --dur:   .58s;   /* thumb e metadados */
  --dur-link: .4s; /* links: mesmo gesto, percurso de uma linha em vez de
                      uma thumb inteira — a 0,58s um item de 11px arrasta */
}

/* ABAIXO DE 1024 A ESCALA DESLIGA.
   Decisão da dupla: celular e tablet em retrato ficam com o layout
   empilhado, no visual novo, até chegarem frames próprios. --u volta a
   ser 1px — os tamanhos do desenho valem em pixel de verdade — e só os
   que não cabem numa tela estreita são reduzidos: um título de 68px
   ocuparia a largura inteira de um telefone com duas palavras. */
@media (max-width: 1023px) {
  :root {
    --u:    1px;
    --m-x:  clamp(20px, 4vw, 40px);
    --t-68: 40px;
    --t-36: 26px;
    --t-26: 20px;
  }
}

/* O tema escuro de Branding/Projects saiu em 11/10: a dupla pediu o
   mesmo fundo claro e texto escuro em todas as páginas. */

/* memory.md: [hidden] é seletor de atributo e perde para qualquer
   regra de classe que defina display. Restaurado no dia 1. */
[hidden] { display: none !important; }

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

/* Os atributos width/height do <img> entram como dica de apresentação —
   height="1125" vira height: 1125px. Uma regra que define só a largura
   deixa essa altura de pé, e aspect-ratio não corrige: ele só calcula a
   dimensão que estiver em auto. O retrato do The Team saiu 340x1125 em
   vez de 340x425 exatamente por isso.
   height: auto neutraliza a dica; quem precisa de altura fixa (as
   imagens do grid, do bento e a espiada do More projects) declara a
   sua depois, com mais especificidade. */
img { height: auto; }

html { background: var(--paper); color-scheme: light; }

body {
  margin: 0;
  min-height: 100svh;
  background: var(--paper);
  color: var(--ink);
  font: 400 var(--t-micro)/1.45 var(--mono);
  letter-spacing: var(--track-micro);
  text-transform: uppercase;
  -webkit-font-smoothing: antialiased;
  display: grid;
  grid-template-rows: auto 1fr auto;
}

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

/* ============================================================
   HEADER / FOOTER
   Grid de 12 colunas. As posições da nav saem do mock: os três
   itens centrais ficam em passo regular (col 3, 5, 7), não
   distribuídos até a borda — CONTACT é que vai pra margem.
   ============================================================ */

/* O GRID DO DIRECIONAL: 12 colunas, vão de 5, margem de 60 dos lados e
   17,5 em cima e embaixo. Cabeçalho e rodapé são as duas faixas onde ele
   aparece inteiro, e por isso as duas o declaram aqui, uma vez só.

   ALINHAMENTO PELA MAIÚSCULA. No desenho o TOPO DAS LETRAS do menu e o
   topo do logo estão na mesma linha, a 17,5 da borda — medido no frame,
   os dois começam em y = 17,5. Uma caixa de texto não começa no topo da
   letra: na Plex Mono, com entrelinha 1, a maiúscula começa 0,177em
   abaixo da caixa e a linha de base fica 0,125em acima do fim dela
   (ascendente 1,025 − meia entrelinha negativa 0,15 − altura de
   maiúscula 0,698). As compensações abaixo saem dessa conta. */
:root { --cap-top: .177em; --base-bot: .125em; }

.bar {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
  align-items: start;
  padding: var(--m-y) var(--m-x);
  font-size: var(--t-11);
  font-weight: 500;
  line-height: 1;
}
/* Todo item explicitamente na linha 1: sem isso, um item posto numa coluna
   ANTERIOR à do item de antes (o ano na 1, depois do nome na 9) seria
   empurrado pelo posicionamento automático para uma segunda linha. */
.bar > * { grid-row: 1; }

/* Header sempre visível. O vidro é um overlay do próprio offwhite com o
   fundo desfocado por trás — o overlay é o que garante o contraste do
   texto; o blur só suaviza o que passa embaixo do separador.

   O memory.md registra que backdrop-filter em elemento fixo destrói o
   scroll. O custo é proporcional à ÁREA borrada, e aqui a área é uma
   faixa de ~52px de altura, não uma camada de tela cheia. Se aparecer
   engasgo em máquina fraca, apagar as duas linhas de backdrop-filter
   resolve sem perder o contraste — o overlay continua de pé. */
/* Cabeçalho SEM linha e SEM fundo: nos frames das faixas de imagem
   (pág. 8 a 10 do direcional) o logo e o menu passam direto por cima da
   foto. O vidro fosco e a linha de antes saem; o cabeçalho continua
   preso no topo durante a rolagem. */
.bar--top {
  position: sticky;
  top: 0;
  z-index: 10;
}

/* Rodapé: linha em cima e 17,5 de respiro dos DOIS lados do texto —
   da linha até o topo das letras, e da linha de base até a borda da
   janela. É o que a dupla marcou (35 + 35 no print retina). */
.bar--bot {
  border-top: 1px solid var(--rule);
  color: var(--ink-mid);
  padding-top:    calc(var(--m-y) - var(--cap-top));
  padding-bottom: calc(var(--m-y) - var(--base-bot));
}
/* Rodapé FIXO na parte de baixo da tela — só na home (Campaigns) e na
   página Projects (a lista), pedido da dupla em 11/10. Nas outras ele
   fica no fim da página, como sempre.
   `sticky` e não `fixed`: ele continua ocupando o próprio lugar no fim do
   documento (nada fica escondido atrás dele e não é preciso reservar
   altura à mão — que no telefone, com o rodapé em três linhas, seria
   outra) e, enquanto a página rola, fica preso à borda de baixo. O fundo
   é o do papel: o conteúdo passa por baixo dele, não através. */
body[data-page="home"] .bar--bot,
body[data-page="branding"] .bar--bot {
  position: sticky;
  bottom: 0;
  z-index: 10;
  background: var(--paper);
}

/* Logo: 93 × 15,6 de 1710, medido no frame. O SVG mantém a proporção
   (5,961) sozinho; só a largura é declarada. */
.logo { grid-column: 1 / span 2; justify-self: start; display: block; line-height: 0; }
.logo svg { display: block; width: calc(93 * var(--u)); height: auto; fill: currentColor; }

/* justify-self: start encolhe o item ao tamanho do texto. Sem isso o
   grid o estica pela coluna inteira e a área clicável — e o gatilho da
   roleta — passa a ser a faixa toda, com o mouse longe da palavra. */
.nav-a { grid-column: 3;  justify-self: start; }
.nav-b { grid-column: 5;  justify-self: start; }
.nav-c { grid-column: 7;  justify-self: start; }
.nav-z { grid-column: 12; justify-self: end; }

/* Menu: Medium 11 em #9b9b9b; a página em que se está, SemiBold 11 em
   #4b4b4b. É o inverso do que era — antes o item atual APAGAVA. */
.bar--top .rl { color: var(--ink-mid); }
.bar--top a[aria-current="page"] { color: var(--ink); font-weight: 600; }
/* Entrelinha 1 só no menu: a janela da roleta passa a ter a altura da
   letra, e o topo da maiúscula vai para a margem pela compensação. Em
   caixa-alta não há descendente para a janela cortar. */
.bar .rl { line-height: 1; margin-top: calc(-1 * var(--cap-top)); white-space: nowrap; }
/* nowrap: num tablet de 820 a coluna 12 tem ~50px e "> CONTACT" tem 59 —
   o item quebrava no espaço e virava duas linhas. Medido no navegador. */

/* --- roleta dos links ---------------------------------------
   Mesmo gesto da thumb, mecanismo diferente: aqui não é texto
   surgindo do vazio, é uma cópia idêntica tomando o lugar da
   original. A original sobe e sai pela borda de cima da janela
   enquanto a cópia, que esperava logo abaixo, sobe para a linha.

   A cópia é um ::after com attr(data-label): não duplica texto
   no HTML e não é lida duas vezes por leitor de tela.
   ------------------------------------------------------------ */
.rl {
  display: inline-block;
  overflow: hidden;          /* a janela: corta a cópia que espera embaixo */
  vertical-align: bottom;    /* sem isso o inline-block cria um vão de baseline */
  line-height: 1.6;
}
.rl > span {
  display: block;
  position: relative;
  transition: transform var(--dur-link) var(--ease);
}
.rl > span::after {
  content: attr(data-label);
  position: absolute;
  left: 0;
  top: 100%;                 /* a cópia aguarda exatamente uma linha abaixo */
  white-space: pre;          /* preserva espaços do rótulo, ex. "The Team" */
}
/* só onde existe ponteiro de verdade — em touch o :hover gruda
   depois do toque e o link ficaria com a cópia no lugar */
@media (hover: hover) and (pointer: fine) {
  .rl:hover > span { transform: translateY(-100%); }
}
.rl:focus-visible > span { transform: translateY(-100%); }

/* Negrito no item sob o cursor. Em mono todo glifo tem a mesma largura,
   então trocar o peso não empurra os vizinhos — numa fonte proporcional
   isso faria a barra inteira dançar a cada hover. */
@media (hover: hover) and (pointer: fine) {
  .bar--top .rl:hover { font-weight: 600; color: var(--ink); }
}
.bar--top .rl:focus-visible { font-weight: 600; color: var(--ink); }
a:focus-visible { outline: 1px solid var(--ink); outline-offset: 3px; }

/* Rodapé: o ano à esquerda, o nome da dupla à direita. No HTML a ordem
   é nome, ano — a posição sai daqui, com linha fixa (ver .bar > *). */
.foot-b { grid-column: 1 / span 4; justify-self: start; }
.foot-a { grid-column: 9 / span 4; justify-self: end; }
/* A frase inteira é o link. white-space: nowrap porque a janela da
   roleta tem uma linha de altura: se a frase quebrasse em duas, a cópia
   passaria a esperar duas linhas abaixo e o gesto sairia torto.
   Cabe folgado — 33 caracteres a 0,6em de 11px dão ~218px. */
.foot-c { grid-column: 5 / span 4; justify-self: center; white-space: nowrap; }

/* ============================================================
   FILEIRA DE PROJETOS  (Home — Campaigns) — redesenho em grid
   ------------------------------------------------------------
   Frame 3: oito cards de 194,4 × 260 (3:4), vão de 5, ocupando a faixa
   útil de 1590 de margem a margem, centrados na altura da janela.

   Frame 4 (fase 3): o card ativo cresce para QUATRO colunas × 343
   (526,67 × 343) no próprio lugar, em volta do próprio centro, e empurra
   os vizinhos para os dois lados; os outros mantêm o tamanho, a 5 de
   distância, e a faixa sangra pelas bordas. Nas pontas o card encosta na
   margem e cresce só para dentro. Número (Medium 14) em cima, título (Medium
   16) embaixo e, na linha seguinte, cliente e agência a 2 e 3 colunas
   do início do card.
   Isso vale com mouse, em janela de 1024 para cima — o render.js liga a
   classe .row--scrub só nessa condição. Sem ela (toque, tablet), a
   fileira continua rolando na horizontal e o hover só revela o texto.
   ============================================================ */

.row-wrap {
  overflow-x: auto;
  overflow-y: hidden;
  padding-inline: var(--gut);
  scrollbar-width: none;
}
.row-wrap::-webkit-scrollbar { display: none; }

.row {
  --tw:    calc(194.375 * var(--u));     /* (1590 − 7 × 5) / 8 */
  --th:    calc(260 * var(--u));
  --tw-on: calc(526.667 * var(--u));     /* quatro colunas e três vãos */
  --th-on: calc(343 * var(--u));
  --tg:    var(--gutter);
  /* espaço do número e do texto, IGUAL em cima e embaixo — é o que
     mantém os cards no centro da altura, como no frame */
  --by:    calc(100 * var(--u));

  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: var(--tw);
  column-gap: var(--tg);
  align-items: center;
  /* a altura já reserva o card ativo: crescer não empurra a página */
  min-height: var(--th-on);
  padding-block: var(--by);

  width: max-content;
  margin-inline: auto;   /* centraliza quando cabe; não trava o scroll quando não cabe */
  /* O frame centra os cards na JANELA (450 de 900), não no espaço entre
     cabeçalho (50,6) e rodapé (43,7) — o centro desse espaço fica 3,46
     abaixo. Com o item centrado no grid, uma margem negativa de 6,92 em
     cima sobe a caixa exatamente 3,46. Medido: cards a 323,46 → 320. */
  margin-top: calc(-6.92 * var(--u));
}

/* Cada projeto é só a caixa da thumb. Número e texto saem do fluxo
   (position:absolute), então um título longo não empurra nada. */
.proj {
  position: relative;
  height: var(--th);
  z-index: 1;
}

/* Medidas do frame 4, com entrelinha 1,25 (a janela da roleta precisa
   de folga para a descendente): número com a caixa 37,93 acima do card;
   título 35 abaixo; cliente e agência 17 abaixo do título, a 265,83 e
   398,75 do início do card (no frame, colunas 7 e 8). */
.num, .meta {
  position: absolute;
  left: 0;
  pointer-events: none;
  color: var(--ink);
}
.num  { bottom: calc(100% + 37.93 * var(--u)); font: 500 var(--t-14)/1.25 var(--mono); }
.meta {
  top: calc(100% + 35 * var(--u));
  width: var(--tw-on);
  display: grid;
  grid-template-columns: calc(265.83 * var(--u)) calc(132.92 * var(--u)) auto;
  row-gap: calc(17 * var(--u));
}

/* --- roleta -------------------------------------------------
   Cada linha é uma janela que corta (.ln), com um rolo dentro
   (.ln > span) que sobe de fora para o lugar. Sem overflow no
   pai, o texto apareceria deslizando por cima da imagem em vez
   de surgir de dentro da própria linha.
   ------------------------------------------------------------ */
.ln, .num { overflow: hidden; white-space: nowrap; }
.ln       { display: block; }

.ln > span, .num > span {
  display: block;
  transform: translateY(115%);
  opacity: 0;
  /* mesma curva da imagem: o texto acompanha o gesto da thumb */
  transition: transform var(--dur) var(--ease),
              opacity   var(--dur) var(--ease);
}

.proj:hover .ln > span,  .proj:focus-visible .ln > span,
.proj:hover .num > span, .proj:focus-visible .num > span,
.proj.is-on .ln > span,  .proj.is-on .num > span {
  transform: translateY(0);
  opacity: 1;
}

/* Escalonamento da roleta. Os atrasos vivem SÓ na regra de entrada:
   ao sair a regra base assume, sem atraso, e o texto sai junto em vez
   de ficar pendurado. Cada linha tem atraso + duração somando --dur,
   então todas chegam no mesmo instante em que o card termina de crescer. */
.proj:hover .ln.t > span, .proj:focus-visible .ln.t > span, .proj.is-on .ln.t > span {
  transition-delay: .07s; transition-duration: calc(var(--dur) - .07s);
}
.proj:hover .ln.c > span, .proj:focus-visible .ln.c > span, .proj.is-on .ln.c > span {
  transition-delay: .14s; transition-duration: calc(var(--dur) - .14s);
}
.proj:hover .ln.a > span, .proj:focus-visible .ln.a > span, .proj.is-on .ln.a > span {
  transition-delay: .21s; transition-duration: calc(var(--dur) - .21s);
}

.ln.t { grid-column: 1 / -1; font: 500 var(--t-16)/1.25 var(--mono); }
.ln.c { grid-column: 2; font: 400 var(--t-14)/1.25 var(--mono); }
.ln.a { grid-column: 3; font: 400 var(--t-14)/1.25 var(--mono); }

.shot { display: block; height: 100%; }
.shot img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  background: rgba(10, 10, 10, .05);  /* moldura visível se a imagem falhar */
}

.proj:focus-visible { outline: none; }
.proj:focus-visible .shot { outline: 1px solid var(--ink); outline-offset: 6px; }
.proj:hover, .proj:focus-visible, .proj.is-on { z-index: 2; }

/* --- o card que cresce (frame 4) -----------------------------------
   Flex em vez de grid: no grid as colunas têm a mesma largura, e aqui
   uma delas muda. A faixa é deslocada por --x, que o render.js calcula
   para o card ativo crescer em volta do centro que tinha em repouso (ou
   a faixa inteira centrada, sem card ativo). Largura e altura do card, e o deslocamento,
   andam na mesma curva e no mesmo tempo. */
.row-wrap.is-scrub { overflow: hidden; padding-inline: 0; }
.row--scrub {
  display: flex;
  align-items: center;
  column-gap: var(--tg);
  margin-inline: 0;
  --x: 0px;                         /* o render.js escreve no style do elemento */
  transform: translateX(var(--x));
  transition: transform var(--dur) var(--ease);
}
.row--scrub .proj {
  flex: none;
  width: var(--tw);
  transition: width var(--dur) var(--ease), height var(--dur) var(--ease);
}
.row--scrub .proj.is-on { width: var(--tw-on); height: var(--th-on); }
/* Enquanto os cards andam, o cursor pode passar um instante por cima de
   um vizinho: o texto acende só no ativo, nunca por hover num vizinho. */
.row--scrub .proj:not(.is-on):hover .ln > span,
.row--scrub .proj:not(.is-on):hover .num > span {
  transform: translateY(115%);
  opacity: 0;
}

main { display: grid; align-items: center; min-height: 0; }

/* ============================================================
   TABLET (768–1023) — fileiras de 4.
   ============================================================ */
@media (max-width: 1023px) and (min-width: 768px) {
  .row {
    /* quatro por linha, ocupando a faixa útil do tablet */
    --tw: calc((100vw - 2 * var(--m-x) - 3 * var(--gutter)) / 4);
    --th: calc(var(--tw) * 4 / 3);
    --by: 40px;
    grid-auto-flow: row;
    grid-template-columns: repeat(4, var(--tw));
    grid-auto-columns: auto;
    margin-top: 0;
    row-gap: 7em;
  }
  .row-wrap { overflow-x: visible; }
  /* o texto cabe no próprio card: uma linha embaixo da outra */
  .meta { width: 100%; grid-template-columns: minmax(0, 1fr); row-gap: 4px; }
  .ln.c, .ln.a { grid-column: 1; }
  main { padding-block: 24px; }
}

/* ============================================================
   MOBILE — sem hover. Lista vertical, uma thumb por linha,
   numeral e metadados sempre visíveis.
   ============================================================ */
@media (max-width: 767px) {
  .row-wrap { overflow-x: visible; }
  .row {
    display: block;
    width: auto;
    padding: 4px 0;   /* sem recuo de hover: aqui não há hover */
    margin-top: 0;
  }
  /* volta tudo para o fluxo normal: sem ampliação, a posição absoluta
     não tem mais função e atrapalharia a lista vertical */
  .proj {
    display: grid;
    grid-template-rows: auto auto auto;
    row-gap: 10px;
    height: auto;
    padding-block: 18px;
    border-bottom: 1px solid var(--rule);
  }
  .proj:last-child { border-bottom: 0; }
  .num, .meta {
    position: static;
    left: auto; width: auto;
  }
  .meta { grid-template-columns: minmax(0, 1fr); row-gap: 4px; }
  .ln.c, .ln.a { grid-column: 1; }
  /* sem hover não há roleta: o texto já nasce no lugar e visível */
  .ln, .num { overflow: visible; }
  .ln > span, .num > span {
    transform: none;
    opacity: 1;
    transition: none;
  }
  .shot { height: auto; aspect-ratio: 3 / 4; }
  .shot img { transform: none !important; aspect-ratio: 3 / 4; }

  .bar { grid-template-columns: repeat(6, 1fr); row-gap: 10px; }
  .logo  { grid-column: 1 / span 3; }
  .nav-a { grid-column: 1 / span 2; grid-row: 2; }
  .nav-b { grid-column: 3 / span 2; grid-row: 2; }
  .nav-c { grid-column: 5 / span 2; grid-row: 2; }
  .nav-z { grid-column: 4 / span 3; grid-row: 1; justify-self: end; }
  /* No telefone o rodapé empilha: nome, ano, crédito. A linha de cada um
     é explícita porque, no desktop, todo filho da barra está preso à
     linha 1 — sem isto os três cairiam um em cima do outro. */
  .bar--bot { row-gap: 8px; }
  .foot-a { grid-column: 1 / span 6; grid-row: 1; justify-self: start; }
  .foot-b { grid-column: 1 / span 6; grid-row: 2; justify-self: start; }
  .foot-c { grid-column: 1 / span 6; grid-row: 3; justify-self: start; }
}

/* ============================================================
   ACESSIBILIDADE
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  /* nada anima: a thumb troca de tamanho e o texto aparece direto,
     sem roleta e sem fade */
  .shot img, .ln > span, .num > span,
  .row--scrub, .row--scrub .proj, .acc > summary { transition: none; }
  .ln > span, .num > span { transform: none; }
  .proj:hover .ln > span,  .proj:focus-visible .ln > span,
  .proj:hover .num > span, .proj:focus-visible .num > span { transform: none; }
  .ln, .num { overflow: visible; }

  /* links: sem roleta. A cópia sai de cena e sobra só o realce
     de opacidade, que comunica o hover sem movimento. */
  .rl > span { transition: none; }
  .rl > span::after { content: none; }
  .rl:hover > span, .rl:focus-visible > span { transform: none; opacity: .5; }
}

/* ============================================================
   PÁGINA DE PROJETO — estágio 2 (revisado)
   ============================================================ */

:root {
  /* Alargado de 56vw para 64vw (806 → 921px numa tela de 1440) para os
     créditos caberem em duas colunas de verdade: cargo de um lado, nome
     do outro, sem quebra no meio do nome. */
  --panel-w: min(64vw, 1000px);
  /* Altura do cabeçalho: margem de cima + logo (15,6) + margem de baixo. */
  --hdr:     calc(2 * var(--m-y) + 15.6 * var(--u));
  /* O vão entre imagens agora é o vão do grid do direcional: 5 de 1710.
     Antes saía da especificação antiga (20 num quadro de 2400) e era o
     que fazia duas células pequenas de 665 + 20 somarem exatamente a
     alta de 1350. Com o vão novo essa soma deixa de fechar — ver a
     proporção das células pequenas nos formatos verticais, mais abaixo. */
  --bgap:    var(--gutter);   /* vão entre imagens = vão do grid: 5 */
}

html { scrollbar-gutter: stable; }

/* O shell é tudo que o painel empurra. Não declara transform nenhum
   quando fechado: qualquer transform, inclusive translateX(0), faria
   dele o bloco contentor dos filhos position:fixed. */
.shell {
  display: grid;
  grid-template-rows: auto 1fr auto;
  min-height: 100svh;
  transition: transform var(--dur) var(--ease);
}
#km:checked ~ .shell { transform: translateX(calc(-1 * var(--panel-w))); }
/* :has() só para o scroll-lock — é conforto. Abrir o painel nunca pode
   depender de suporte a seletor. */
body:has(#km:checked) { overflow: hidden; }

/* --- primeiro fold (redesenho em grid) ----------------------
   Posições tiradas do frame 5 do direcional, a 1710×900. Cada número
   abaixo sai de uma âncora medida no raster e das métricas da Plex Mono
   (ascendente 1,025 · descendente 0,275 · maiúscula 0,698 · parêntese e
   colchete 0,76 acima da base) — a conta está no HANDOFF.

     (01)                topo do parêntese     107,5
     título, 1ª linha    topo da maiúscula     150,5  · entrelinha 74
     descrição, 1ª linha topo da maiúscula     179    · entrelinha 37
     CLIENT:             topo da maiúscula     207,5  · entrelinha 21
     [+] KNOW MORE       topo do colchete      258,5
     [+] sozinho         topo do colchete      261    · termina na margem
     linha divisória     y = 360, de borda a borda
     primeira imagem     y = 446

   O título e a descrição se alinham PELO TOPO (as primeiras linhas de
   base batem); os créditos e o [+] se alinham PELO FIM do título. Assim,
   com um título de uma linha ou de três, o KNOW MORE continua colado na
   última linha dele, que é a relação que o desenho mostra. */
.phead {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  grid-template-rows: auto auto;
  column-gap: var(--gutter);
  padding: calc(55.29 * var(--u)) var(--m-x) calc(76.54 * var(--u));
  border-bottom: 1px solid var(--rule);
}
.phead .pnum {
  grid-area: 1 / 1 / 2 / 5;
  font-size: var(--t-14); font-weight: 500; line-height: 1;
}
.phead .ptitle {
  grid-area: 2 / 1 / 3 / 5; align-self: start;
  margin: calc(15.57 * var(--u)) 0 0;
  font-size: var(--t-68); font-weight: 500;
  line-height: calc(74 / 68);
  letter-spacing: 0;          /* medido: o avanço é o 0,6em natural da mono */
  text-transform: uppercase;
}
.phead .pidea {
  grid-area: 2 / 5 / 3 / 9; align-self: start;
  margin: calc(49.01 * var(--u)) 0 0;
  font-size: var(--t-26); line-height: calc(37 / 26);
  letter-spacing: 0; text-transform: none;
}
.phead .pmeta {
  grid-area: 2 / 10 / 3 / 13; align-self: end;
  margin-bottom: calc(12.57 * var(--u));
  /* coluna flex: o KNOW MORE vira bloco. Como inline-block ele ganhava a
     folga da linha de texto do pai embaixo de si — medido: 4,7px acima
     do lugar, e os créditos 2,4 acima junto. */
  display: flex; flex-direction: column; align-items: flex-start;
}
/* Rótulo e valor na MESMA linha; o grid de duas colunas mantém os valores
   alinhados entre si com rótulos de larguras diferentes. */
.phead .pcred {
  display: grid; grid-template-columns: max-content 1fr;
  column-gap: 1ch;
  font-size: var(--t-14); line-height: calc(21 / 14);
}
.phead .pcred span { font-weight: 600; }
.phead .pcred b { font-weight: 400; }

/* --- [+] Know more e o [+] sozinho ----------------------------
   Os dois abrem o mesmo painel (decisão da dupla). Alternância só com
   CSS: o painel abre sem JavaScript, então o conteúdo continua
   alcançável se um script quebrar. */
#km { position: absolute; opacity: 0; pointer-events: none; }
.km-open {
  display: inline-block;
  margin-top: calc(13.37 * var(--u));
  font-size: var(--t-14); line-height: 1;
  cursor: pointer;
}
.km-plus {
  grid-area: 2 / 12 / 3 / 13; align-self: end; justify-self: end;
  margin-bottom: calc(10.07 * var(--u));
  font-size: var(--t-14); line-height: 1;
  cursor: pointer;
}

/* O que vier logo depois do cabeçalho começa 85 abaixo da linha. Um
   bloco de texto ali não repete a linha — a do cabeçalho já separa. */
.phead + * { margin-top: calc(85 * var(--u)); }
.phead + .tblock { border-top: 0; margin-top: 0; padding-top: calc(76.81 * var(--u)); }

/* --- blocos de conteúdo -------------------------------------
   O PADRÃO DE GRID, e por que ele é assim.

   Quatro formatos, todos desenhados dentro do mesmo quadro de
   2400×1350 com 20px de respiro:

     Full              1 × 2400×1350
     Split vertical    2 × 1190×1350
     Vertical direita  2 × 1190×665 empilhadas + 1 × 1190×1350 à direita
     Vertical esquerda o espelho

   As contas fecham sozinhas: 1190 + 20 + 1190 = 2400, e
   665 + 20 + 665 = 1350. Toda faixa é 16:9 no total.

   O QUE ISTO CONSERTA. Antes, a altura de uma faixa saía da proporção
   natural do arquivo que subissem: nenhuma célula declarava proporção,
   e `height: 100%` numa linha de altura automática vira a altura
   intrínseca da imagem. Medido: um retrato mandado para o lugar de uma
   16:9 levou uma faixa de 890px para 3.926px — 4,4× — e esticou as
   outras duas imagens da mesma faixa junto, virando uma delas numa
   torre de 783×1958. Com `aspect-ratio` declarada por célula, a altura
   passa a sair do desenho e não do upload: mandar o arquivo errado
   agora custa um corte, nunca a página inteira. */
.blocks { padding-inline: var(--gut); display: grid; gap: var(--bgap); }
.brow   { display: grid; gap: var(--bgap); }

.brow img {
  width: 100%;
  object-fit: cover;                   /* corta, nunca deforma */
  display: block;
  background: var(--frame);            /* moldura visível se a imagem falhar */
}

/* Full — uma imagem, a faixa inteira. */
.brow--full { grid-template-columns: 1fr; }
.brow--full img { aspect-ratio: 2400 / 1350; }

/* Split vertical — duas verticais lado a lado. */
.brow--split { grid-template-columns: 1fr 1fr; }
.brow--split img { aspect-ratio: 1190 / 1350; }

/* Os dois formatos com uma vertical e duas pequenas.
   A ordem das imagens segue a leitura do formato: em "vertical direita"
   vêm primeiro as duas pequenas (que ficam à esquerda) e depois a alta;
   em "vertical esquerda", a alta primeiro.

   TODAS AS TRÊS CÉLULAS DECLARAM PROPORÇÃO, inclusive a que atravessa as
   duas linhas. Eu tinha escrito aqui que a alta não precisava — que a
   altura dela sairia da soma das duas pequenas — e estava errado: numa
   faixa de linhas automáticas, um item que atravessa as duas empurra as
   duas com a altura natural do arquivo. Medido no navegador: um retrato
   de 1200×3000 na célula alta levava a faixa de 774px para 1706px, nos
   dois formatos. Com a proporção declarada, a faixa mede 774px com
   qualquer arquivo, em qualquer largura.
   O `height: auto` é o que desarma o esticamento padrão do grid, que
   ganharia da proporção. */
.brow--vright,
.brow--vleft { grid-template-columns: 1fr 1fr; grid-template-rows: auto auto; }

/* AS DUAS PEQUENAS PRECISAM SOMAR A ALTA. A alta mantém 1190/1350; as
   pequenas saem da conta, não de uma medida de exportação:

     largura da célula  (1590 − 5) / 2           = 792,5
     altura da alta     792,5 × 1350 / 1190      = 899,05
     altura da pequena  (899,05 − 5) / 2         = 447,03
     proporção          792,5 / 447,03           = 1,77282

   Com o vão antigo (20 em 2400) isso era 1190/665 exato. Com 1190/665 e
   o vão novo, as pequenas somariam 891 contra 899 da alta — 8px de
   desencontro na base da faixa, visível em toda vertical. Como tudo
   escala junto (--u), a proporção é constante em qualquer largura. Uma
   imagem exportada em 1190×665 perde 0,9% num corte, dentro da
   tolerância que o painel já aceita sem avisar. */
:root { --r-pequena: 1.77282; }
.brow--vright > :nth-child(1) { grid-area: 1 / 1; aspect-ratio: var(--r-pequena); }
.brow--vright > :nth-child(2) { grid-area: 2 / 1; aspect-ratio: var(--r-pequena); }
.brow--vright > :nth-child(3) { grid-area: 1 / 2 / 3 / 3;
                                height: auto; aspect-ratio: 1190 / 1350; }

.brow--vleft  > :nth-child(1) { grid-area: 1 / 1 / 3 / 2;
                                height: auto; aspect-ratio: 1190 / 1350; }
.brow--vleft  > :nth-child(2) { grid-area: 1 / 2; aspect-ratio: var(--r-pequena); }
.brow--vleft  > :nth-child(3) { grid-area: 2 / 2; aspect-ratio: var(--r-pequena); }

/* --- vídeo dentro da célula ------------------------------------
   A célula de vídeo é uma célula como outra qualquer: nos formatos de
   três células ela já recebe a proporção pelo `:nth-child`; no Full e no
   Split a regra de proporção era escrita para `img`, então ganha aqui o
   par dela.

   O RECORTE. Um iframe não tem `object-fit`, e o player desenharia o
   vídeo inteiro com barras pretas quando a proporção do vídeo não bate
   com a da célula. Então o iframe é dimensionado na proporção DO VÍDEO
   (`--vr`, largura ÷ altura, medida pelo painel), grande o bastante para
   cobrir a célula nos dois eixos, centrado — e a célula corta o resto.
   É o `cover` de uma imagem, feito à mão:

     largura = o maior entre a largura da célula e altura × proporção
     altura  = o maior entre a altura da célula e largura ÷ proporção

   `cqw`/`cqh` são a largura e a altura da PRÓPRIA célula, que é o
   contêiner. Sem unidades de contêiner esta conta precisaria de
   JavaScript medindo cada célula a cada redimensionamento. */
.brow > .vcell {
  position: relative;
  overflow: hidden;
  width: 100%;
  background: var(--frame);
  container-type: size;
}
.brow--full  > .vcell { aspect-ratio: 2400 / 1350; }
.brow--split > .vcell { aspect-ratio: 1190 / 1350; }

.vcell iframe {
  position: absolute; left: 50%; top: 50%;
  width:  max(100cqw, calc(100cqh * var(--vr, 1.7778)));
  height: max(100cqh, calc(100cqw / var(--vr, 1.7778)));
  transform: translate(-50%, -50%);
  border: 0;
  /* Imagem que se mexe, não player: o clique passa para a página. Sem
     isto, um toque no celular sobre o vídeo podia pausá-lo. */
  pointer-events: none;
}
/* O link do HTML servido, que só aparece se o script não rodar. */
.vcell > a {
  position: absolute; left: 12px; bottom: 10px;
  font-size: var(--t-rotulo); color: var(--ink-mid);
}

/* --- bloco de texto -----------------------------------------
   Dois alinhamentos, escolhidos por bloco no painel:

     (padrão)  rótulo pequeno à esquerda, texto na metade direita
     --center  coluna no meio da página, cada linha centrada no eixo

   O título é opcional nos dois: vazio, ele some e não deixa uma linha
   morta ocupando a coluna da esquerda. */
.tblock {
  /* Frame 6: a linha nasce 37 depois da imagem de cima e corre de borda a
     borda; o texto começa 34,5 abaixo dela (topo da maiúscula), na
     coluna 7, em 18 com entrelinha 28; a próxima faixa de imagem vem
     150 depois da última linha de base. Não há linha embaixo: quem
     separa é o espaço. */
  display: grid; grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
  margin-top: calc(37 * var(--u));
  border-top: 1px solid var(--rule);
  padding: calc(26.31 * var(--u)) var(--m-x) calc(142.75 * var(--u));
}
/* Dois blocos de texto seguidos: a linha separa, o espaço não dobra. */
.tblock + .tblock { margin-top: 0; }
.tblock h2 {
  grid-column: 1 / span 4; grid-row: 1; margin: 0;
  font-size: var(--t-14); font-weight: 600; line-height: 1;
  /* a linha de base do rótulo na mesma altura da 1ª linha do texto */
  margin-top: calc((20.75 - 12.25) * var(--u));
}
.tblock h2:empty { display: none; }
.tblock .body {
  grid-column: 7 / span 6; grid-row: 1; margin: 0;
  font-size: var(--t-18); line-height: calc(28 / 18);
  text-transform: none; letter-spacing: 0;
}
.tblock .body p { margin: 0 0 calc(28 * var(--u)); }
.tblock .body p:last-child { margin-bottom: 0; }

.tblock--center h2     { grid-column: 1 / span 12; text-align: center; }
.tblock--center .body  { grid-column: 4 / span 6; text-align: center; }

/* ============================================================
   MORE PROJECTS
   ============================================================ */
/* O respiro ANTES da divisória: 37 depois de uma imagem, a mesma regra
   do bloco de texto. Depois de um bloco de TEXTO, nada — ele já traz o
   próprio espaço embaixo, e somar os dois abriria um buraco. */
.blocks + .more { margin-top: calc(37 * var(--u)); }

/* Frame 7. Linha de borda a borda; "OTHER PROJECTS" (SemiBold 14) com a
   linha de base exatamente sobre a linha de cima da lista; a lista na
   coluna 7, com as linhas sangrando até a borda direita da janela; cada
   item com 54 de altura e só a linha de cima; número (Medium 14) e nome
   (Regular 14) a 71 de distância; a prévia da capa nas colunas 4–5,
   alinhada ao topo da lista. */
.more {
  position: relative;
  overflow: hidden;
  border-top: 1px solid var(--rule);
  padding: 0 var(--m-x) calc(52.33 * var(--u));
  display: grid; grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
}
.more > h2 {
  grid-column: 1 / span 3; grid-row: 1; align-self: start;
  margin: calc(74.02 * var(--u)) 0 0;
  font-size: var(--t-14); font-weight: 600; line-height: 1;
}
.more > ol {
  grid-column: 7 / span 6; grid-row: 1;
  /* a margem negativa à direita é o que faz as linhas sangrarem */
  margin: calc(86.5 * var(--u)) calc(-1 * var(--m-x)) 0 0;
  padding: 0; list-style: none;
}
/* Nenhum <a> cria contexto de empilhamento próprio: thumbs e textos
   vivem no MESMO contexto, o da .more, e um z-index decide de fato quem
   fica na frente. */
.more li a {
  display: grid; grid-template-columns: calc(71 * var(--u)) 1fr; align-items: start;
  padding: calc(21.02 * var(--u)) 0 calc(17.98 * var(--u));
  border-top: 1px solid var(--rule);
  font-size: var(--t-14); line-height: 1;
}
.more li a .n,
.more li a .ttl { position: relative; z-index: 2; }
.more li a .n   { font-weight: 500; }
.more li a .ttl { font-weight: 400; transition: opacity var(--dur-link) var(--ease); }
@media (hover: hover) and (pointer: fine) {
  .more ol:hover li a .ttl       { opacity: .3; }
  .more ol:hover li a:hover .ttl { opacity: 1; }
}

/* A prévia: 265,8 × 256, alinhada ao
   topo da lista. Aparece com o mouse sobre o item. */
.more .peek {
  position: absolute;
  /* A coluna sai da largura da própria seção (100% = borda a borda), e
     não de 127,92 × --u: abaixo de 1024 a margem deixa de ser 60 e uma
     coluna escrita em --u cairia fora do lugar. */
  --col: calc((100% - 2 * var(--m-x) - 11 * var(--gutter)) / 12);
  left: calc(var(--m-x) + 3 * (var(--col) + var(--gutter)));
  top: calc(86.5 * var(--u));
  /* do início da coluna 4 ao início da 6 — inclui o vão depois da 5;
     medido no frame: 266 de largura, não os 260,8 de duas colunas */
  width:  calc(2 * (var(--col) + var(--gutter)));
  height: calc(256 * var(--u));
  object-fit: cover;
  opacity: 0; pointer-events: none;
  z-index: 0;
  transition: opacity var(--dur) var(--ease);
}
@media (hover: hover) and (pointer: fine) {
  .more li a:hover .peek { opacity: 1; }
}

/* ============================================================
   PAINEL KNOW MORE
   Fora do .shell: dentro, o transform que empurra a página o
   arrastaria junto e ele nunca entraria em cena.
   ============================================================ */
.panel {
  position: fixed; inset: 0 0 0 auto;
  width: var(--panel-w);
  background: var(--paper);
  border-left: 1px solid var(--rule);
  transform: translateX(100%);
  transition: transform var(--dur) var(--ease);
  overflow-y: auto;
  z-index: 20;
  padding: 0 clamp(20px, 2.6vw, 52px) 96px;
}
#km:checked ~ .panel { transform: translateX(0); }

/* Camada invisível que cobre a página: clicar fora fecha. É um <label>
   apontando para o mesmo checkbox, então funciona sem JavaScript. */
.km-scrim {
  position: fixed; inset: 0; z-index: 19;
  opacity: 0; pointer-events: none;
}
#km:checked ~ .km-scrim { pointer-events: auto; }

.panel-top {
  position: sticky; top: 0; z-index: 2;
  display: flex; justify-content: space-between; align-items: center;
  padding: 18px 0;
  background: var(--paper);
  border-bottom: 1px solid var(--rule);
}
.panel-top .pt-num { color: var(--ink-mid); }

/* O lead: a descrição em corpo grande, como na referência do Simon. */
.panel .lead {
  margin: 0; padding: clamp(30px, 5vh, 62px) 0 clamp(26px, 4vh, 52px);
  font-size: var(--t-lead);
  line-height: 1.18; letter-spacing: -.035em;
  text-transform: none; font-weight: 400;
  max-width: 22em;
}

/* A linha da referência: rótulo pequeno à esquerda, conteúdo à direita,
   separador fino no topo de cada linha. */
/* A coluna do rótulo era 4/13 da linha — 216px para um texto de 13px que
   nunca passa de 80. O que sobrava era dividido de novo em duas colunas
   de créditos, e "Creative Director › Kauê Barbosa" (307px) não cabia nos
   230px que restavam. Agora o rótulo leva 2,4/11,4 e o conteúdo fica com
   o resto. A proporção continua fixa de propósito: com `max-content` cada
   linha teria um rótulo de largura diferente e a coluna da direita
   começaria num lugar diferente a cada linha. */
.prow {
  display: grid;
  grid-template-columns: minmax(110px, 2.4fr) 9fr;
  gap: 8px clamp(16px, 2.4vw, 44px);
  padding: clamp(15px, 2.1vh, 26px) 0;
  border-top: 1px solid var(--rule);
  align-items: start;
}
.prow > h3 { margin: 0; font-size: var(--t-micro); font-weight: 400;
             color: var(--ink-mid); letter-spacing: var(--track-micro); }
.prow > .val { text-transform: none; letter-spacing: -.01em; }
.prow > .val.mono-up { text-transform: uppercase; letter-spacing: var(--track-micro); }
.prow p { margin: 0 0 .9em; font-size: var(--t-body); line-height: 1.45; }
.prow p:last-child { margin-bottom: 0; }

.prow .kpi { font-size: var(--t-sect); font-weight: 500;
             line-height: 1.45; letter-spacing: -.03em; text-transform: none; }
.prow ul { margin: 0; padding: 0; list-style: none;
           font-size: var(--t-small); line-height: 1.9; }
.prow .src { color: var(--ink-mid); }

/* CRÉDITOS — cargo numa coluna, nome na outra.
   Antes eram duas colunas de grupo (Agency | Partners) lado a lado, com
   cargo e nome espremidos dentro de cada uma; o nome quebrava no meio.
   Agora os grupos empilham e as duas colunas servem a cargo e nome.
   Uma grade só para TODOS os grupos, não uma por grupo: é o que faz o
   cargo de "Partners" começar na mesma vertical que o de "Agency". Com
   uma grade por grupo, cada uma mediria o próprio max-content e as
   colunas sairiam desencontradas. */
.prow .cred {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: .3em clamp(18px, 2vw, 40px);
  font-size: var(--t-small); line-height: 1.75;
}
.prow .cred h4 {
  grid-column: 1 / -1;
  margin: 1.5em 0 .25em;
  font-size: var(--t-micro); font-weight: 400;
  color: var(--ink-mid); letter-spacing: var(--track-micro);
}
.prow .cred h4:first-child { margin-top: 0; }
.prow .cred .role { color: var(--ink-mid); }

/* ============================================================
   LOADER

   A placa opaca é um pseudo-elemento da RAIZ, não um elemento no HTML.
   Duas razões, e as duas são sobre não estragar o site:

   · SEM PISCA. A classe .loading é posta por um script de uma linha no
     <head>, antes da primeira pintura. Um elemento criado por um script
     com defer chegaria depois de o conteúdo já ter aparecido, e o pisca
     seria pior do que não ter loader nenhum.
   · SEM TELA BRANCA ETERNA. Um loader que precisa de JavaScript para
     SAIR deixa o cliente olhando para o nada quando o script morre. Aqui
     não: se o loader.js não carregar, a placa some sozinha pelo prazo
     abaixo; e se o JavaScript estiver desligado, a classe nunca entra e o
     site aparece direto.

   O fundo sai de var(--paper), então a placa é clara nas páginas claras e
   preta no Branding e nos projetos de Branding, sem uma regra a mais.
   ============================================================ */
html.loading::before {
  content: "";
  position: fixed; inset: 0;
  z-index: 90;
  background: var(--paper);
  /* O PRAZO. Uma animação de duração zero com 8s de atraso: até lá nada
     acontece e as transições abaixo funcionam normalmente; passados os
     8s, o `forwards` fixa o estado final e a placa sai. É o que garante
     que nenhum defeito meu prenda o visitante numa tela vazia. O caminho
     normal termina bem antes — o teto do loader.js é 7s. */
  animation: ld-prazo 0s linear 8s forwards;
}
@keyframes ld-prazo { to { opacity: 0; visibility: hidden; } }
html.loading.ld-saindo::before { opacity: 0; transition: opacity .46s linear; }

/* O DESENHO (frames 1 e 2, medidos a 1710 × 900). Tudo na altura do
   centro da janela: o nome (790 de largura) centrado; "(84%)" começando
   em 280,1 e "[ LOADING ... ]" em 1386,4, os dois em 14 com o centro das
   maiúsculas na linha do meio. O KAND final (406,5 de largura) fica um
   pouco acima do nome — base em 473,5 contra 468,5 —, como no frame 2. */
#loader {
  position: fixed; inset: 0;
  z-index: 91;
  color: var(--ink);
  pointer-events: none;
}
html.ld-saindo #loader { opacity: 0; transition: opacity .46s linear; }

.ld-pct, .ld-estado {
  position: absolute;
  top: calc(50% - 7.36 * var(--u));      /* 0,526 × 14: o centro da maiúscula */
  font: 400 var(--t-14)/1 var(--mono);
  letter-spacing: 0;
  white-space: pre;
  font-variant-numeric: tabular-nums;
}
.ld-pct    { left: calc(280.13 * var(--u)); }
.ld-estado { left: calc(1386.35 * var(--u)); }

/* A caixa tem a proporção do NOME mesmo quando ele não existe (tela
   compacta): é ela que dá a régua em porcentagem para o KAND. */
.ld-marca {
  position: absolute; left: 50%; top: 50%;
  width: calc(790 * var(--u));
  aspect-ratio: 1464.49 / 69.48;
  transform: translate(-50%, -50%);
}
.ld-marca svg { display: block; overflow: visible; fill: currentColor; }
.ld-nome { width: 100%; height: 100%; }
/* 406,5 / 790 da largura; topo 25,95 acima do nome = −69,24% da altura dele. */
.ld-kand {
  position: absolute;
  left: 50%; top: -69.24%;
  width: 51.456%;
  height: auto;
  aspect-ratio: 998.34 / 167.47;
  transform: translateX(-50%);
  opacity: 0;
}
#loader[data-forma="kand"] .ld-kand { opacity: 1; }

/* SEM ANIMAÇÃO DE ENTRADA: o nome está na tela no primeiro quadro. */

/* A contração: cada letra que fica anda e cresce até a caixa da letra
   correspondente no KAND (o loader.js mede e escreve o transform em cada
   <path>); as outras apagam. Só transform e opacity — o compositor
   resolve sozinho, sem refazer layout. */
.ld-nome path {
  transform-box: fill-box;
  transform-origin: 0 0;
}
/* A transição mora na regra BASE: o loader.js escreve o transform e, se
   ela dependesse da classe que entra junto, o primeiro quadro já seria o
   final — as letras pulariam em vez de andar. */
.ld-nome .ld-fica { transition: transform .78s var(--ease); }
#loader.ld-junta .ld-cai  { opacity: 0; transition: opacity .3s linear; }
/* E o logo de verdade entra no lugar das quatro letras. */
#loader.ld-kand-on .ld-kand { opacity: 1; transition: opacity .22s linear; }
#loader.ld-kand-on .ld-nome { opacity: 0; transition: opacity .22s linear; }

/* Abaixo de 1024 a escala desliga: o nome ocupa a largura útil e os dois
   textos descem para baixo dele, um em cada margem. */
@media (max-width: 1023px) {
  .ld-marca { width: calc(100vw - 2 * var(--m-x)); }
  .ld-pct, .ld-estado { top: calc(50% + 56px); }
  .ld-pct    { left: var(--m-x); }
  .ld-estado { left: auto; right: var(--m-x); }
}

/* Quem pediu menos movimento continua tendo o loader — ele informa — mas
   sem a contração: o KAND entra direto. */
@media (prefers-reduced-motion: reduce) {
  .ld-nome .ld-fica,
  #loader.ld-junta .ld-cai,
  #loader.ld-kand-on .ld-kand,
  #loader.ld-kand-on .ld-nome { transition: none; }
}

/* ============================================================
   CURSOR
   Um quadrado branco com mix-blend-mode: difference. A mistura
   "difference" devolve 255 menos o fundo: sobre o offwhite ele
   aparece quase preto, sobre uma foto escura aparece claro. O
   contraste é calculado pelo compositor a cada frame, sem
   JavaScript lendo pixel nenhum.
   ============================================================ */
@media (hover: hover) and (pointer: fine) {
  body.cur-on,
  body.cur-on * { cursor: none; }

  #cur {
    position: fixed; left: 0; top: 0; z-index: 999;
    display: flex; align-items: center;
    pointer-events: none;
    mix-blend-mode: difference;
    color: #fff;                       /* branco = invertido contra o fundo */
    will-change: transform;
    opacity: 0;
    transition: opacity .25s ease;
  }
  body.cur-on #cur { opacity: 1; }

  /* Quadrado no repouso, triângulo em modo de ação. Os dois são o mesmo
     clip-path de 4 pontos — no triângulo, dois deles coincidem no meio
     da direita. Mesma contagem de pontos é o que permite ao navegador
     interpolar a forma em vez de trocar de uma para outra. */
  /* Um detalhe, não um elemento. O rótulo em colchetes saiu: ele
     repetia a palavra que já estava embaixo do cursor. */
  #cur .dot {
    width: 7px; height: 7px;
    background: #fff;
    flex: 0 0 auto;
    clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%);
    transition: clip-path var(--dur-link) var(--ease);
  }
  #cur.is-link .dot {
    clip-path: polygon(0% 0%, 100% 50%, 100% 50%, 0% 100%);
  }


}

/* ============================================================
   RESPONSIVO DA PÁGINA DE PROJETO
   ============================================================ */
@media (max-width: 1080px) {
  :root { --panel-w: min(74vw, 700px); }
}

/* ABAIXO DE 1024: EMPILHADO, VISUAL NOVO (decisão da dupla, até virem
   frames de celular). Cabeçalho do projeto em uma coluna — número,
   título, descrição, créditos e KNOW MORE — e o [+] sozinho sai, porque
   sem a borda direita do desktop ele vira um sinal solto no meio da
   tela; o KNOW MORE continua abrindo o painel. Textos e lista do Other
   projects ocupam a largura toda. As faixas de imagem continuam lado a
   lado no tablet e só empilham no telefone, logo abaixo. */
@media (max-width: 1023px) {
  .phead { padding-block: 36px 40px; row-gap: 0; }
  .phead .pnum   { grid-area: auto / 1 / auto / -1; }
  .phead .ptitle { grid-area: auto / 1 / auto / -1; margin-top: 18px; }
  .phead .pidea  { grid-area: auto / 1 / auto / -1; margin-top: 22px; max-width: 34em; }
  .phead .pmeta  { grid-area: auto / 1 / auto / -1; margin: 26px 0 0; align-self: start; }
  .km-plus { display: none; }
  .phead + * { margin-top: 40px; }
  .phead + .tblock { padding-top: 40px; }

  .tblock { margin-top: 32px; padding-block: 28px 64px; }
  .tblock h2, .tblock .body,
  .tblock--center h2, .tblock--center .body { grid-column: 1 / -1; grid-row: auto; }
  .tblock h2 + .body { margin-top: 18px; }
  .blocks + .more { margin-top: 32px; }
  .more > h2, .more > ol { grid-column: 1 / -1; grid-row: auto; }
  .more > h2 { margin-top: 40px; }
  .more > ol { margin-top: 24px; }
  .more .peek { display: none; }    /* sem a coluna vazia, a prévia cobriria a lista */
}

@media (max-width: 767px) {
  :root { --panel-w: 100vw; }   /* empurrar 56% numa tela de 390px não sobra nada */
  /* No telefone tudo empilha numa coluna, uma imagem depois da outra.
     Cada célula mantém a PRÓPRIA proporção — a alta continua alta, as
     pequenas continuam deitadas — então a página lida em vertical tem o
     mesmo ritmo do desenho.

     `:nth-child(n)` em vez de `*`, e não é preciosismo: `*` pesa (0,1,0)
     e perde para o `.brow--vright > :nth-child(1)` lá de cima, que pesa
     (0,2,0). Com a colocação explícita sobrevivendo dentro do media
     query, a célula alta continuava pedindo a coluna 2, o grid criava uma
     coluna implícita para atender, e ela saía com a largura natural do
     arquivo — 40px numa tela de 375. Medido: `grid-template-columns`
     resolvia para "301px 40px" em vez de uma coluna só, e a terceira
     imagem sumia numa tira na borda. `:nth-child(n)` casa com todo filho
     e pesa igual, então ganha por vir depois. */
  .brow--split, .brow--vright, .brow--vleft {
    grid-template-columns: 1fr; grid-template-rows: none;
  }
  .brow--vright > :nth-child(n),
  .brow--vleft  > :nth-child(n) { grid-area: auto; }
  .prow { grid-template-columns: 1fr; }
  /* No telefone o cargo e o nome empilham: duas colunas num painel de
     390px deixariam o nome com 150px, que é onde ele quebrava antes. */
  .prow .cred { grid-template-columns: 1fr; gap: 0 0; }
  .prow .cred .role { margin-top: .7em; }
}

/* ============================================================
   ACESSIBILIDADE — complemento do estágio 2
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  .shell, .panel, .more .peek, #cur, #cur .dot, #cur .tag { transition: none; }
}

/* ============================================================
   BRANDING — a lista (frames 11 e 12)
   ============================================================ */

/* Uma lista só, centrada no grid: começa na coluna 5 (591,7 de 1710) e
   o topo da primeira linha fica a 191,5 da janela — 140,9 abaixo do fim
   do cabeçalho. Medido no frame 11. */
.blist {
  margin: 0;
  padding: calc(140.9 * var(--u)) var(--m-x) calc(140.9 * var(--u));
  list-style: none;
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
}
.blist > li { grid-column: 5 / -1; }

/* Cada linha tem 87 de passo. O nome (36,6, Medium, entrelinha 1) tem a
   linha de base 81,55 abaixo do topo da linha: 49,52 de respiro em cima
   + 0,875 do corpo até a base. */
.blist a {
  display: flex;
  align-items: flex-start;
  padding: calc(49.52 * var(--u)) 0 calc(0.88 * var(--u));
  letter-spacing: 0;
  transition: opacity var(--dur) var(--ease);
}
/* Número e tópico (14) centrados na ALTURA DAS MAIÚSCULAS do nome, não
   na linha de base: o centro da caixa-alta fica a 0,526 do corpo abaixo
   do topo da caixa em entrelinha 1. 0,526 × (36,6 − 14) = 11,89. */
.blist .n,
.blist .cat {
  font: 500 var(--t-14)/1 var(--mono);
  margin-top: calc(11.89 * var(--u));
  flex: none;
}
/* O nome começa 77,5 depois do início do número — largura fixa, para
   todos os nomes alinharem na mesma vertical. */
.blist .n   { width: calc(77.5 * var(--u)); }
.blist .ttl { font: 500 var(--t-36)/1 var(--mono); }
.blist .cat { font-weight: 400; margin-left: calc(44 * var(--u)); }
.blist .vazio { padding-top: calc(49.52 * var(--u)); font-size: var(--t-14); }

/* Frame 12: sob o cursor a linha fica, as outras somem para 10% — o
   #dfdfdf medido no frame é o texto a 10% sobre o fundo. As imagens que
   se espalham em volta entram na fase 3. */
@media (hover: hover) and (pointer: fine) {
  .blist:has(a:hover) a:not(:hover) { opacity: .1; }
}
.blist:has(a:focus-visible) a:not(:focus-visible) { opacity: .1; }

/* As imagens do projeto sob o cursor (frame 12): quatro lugares fixos do
   grid, medidos no frame. Em cima: colunas 2–3 a 104,5 do topo (261 ×
   256) e coluna 9 a 109,5 (128 × 75). Embaixo, a 104,5 da borda — a mesma
   distância de cima: colunas 10–12 (394 × 430) e 1–2 (266 × 169). Presas
   à janela, atrás da lista; o tamanho é do lugar, a imagem se recorta. */
.bscatter { position: fixed; inset: 0; z-index: 0; pointer-events: none; }
.blist { position: relative; z-index: 1; }
.bscatter img {
  position: absolute;
  object-fit: cover;
  opacity: 0;
  transition: opacity .35s var(--ease);
}
.bscatter.is-on img[src]:not(.is-load) { opacity: 1; }
.bs-1 { left: calc(192.92 * var(--u));  top: calc(104.5 * var(--u));    width: calc(260.83 * var(--u)); height: calc(256 * var(--u)); }
.bs-2 { left: calc(1123.33 * var(--u)); top: calc(109.5 * var(--u));    width: calc(127.92 * var(--u)); height: calc(75 * var(--u)); }
.bs-3 { left: calc(1256.25 * var(--u)); bottom: calc(104.5 * var(--u)); width: calc(393.75 * var(--u)); height: calc(430 * var(--u)); }
.bs-4 { left: calc(60 * var(--u));      bottom: calc(104.5 * var(--u)); width: calc(265.83 * var(--u)); height: calc(169 * var(--u)); }

/* Abaixo de 1024 a lista ocupa a largura toda, começa mais perto do
   cabeçalho e o tópico desce para baixo do nome quando não cabe. */
@media (max-width: 1023px) {
  .bscatter { display: none; }
  .blist { padding-block: 56px 72px; }
  .blist > li { grid-column: 1 / -1; }
  .blist a { flex-wrap: wrap; padding-top: 28px; }
  .blist .n { width: 56px; }
  .blist .ttl { flex: 1 1 0; min-width: 0; }
  .blist .cat { margin-left: 0; flex-basis: 100%; padding-left: 56px; margin-top: 8px; }
}

/* ============================================================
   THE TEAM — redesenho em grid (frames 13 a 16)
   Medido a 1710 × 900; todo número é um pixel do desenho (u).
   ============================================================ */

/* Topo: a frase grande (Light 68, entrelinha 74) nas colunas 1–6, o
   complemento (26/37) a partir da coluna 7. As duas primeiras linhas de
   base batem na mesma altura (198,5 da janela): a caixa da frase começa
   85,4 abaixo do cabeçalho e a do complemento 34,25 abaixo dela. */
.tm-top {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
  align-items: start;
  padding: calc(85.41 * var(--u)) var(--m-x) calc(82 * var(--u));
  text-transform: none;
}
.tm-headline {
  grid-column: 1 / 7;
  margin: 0;
  font: 300 var(--t-68)/calc(74 / 68) var(--mono);
  letter-spacing: 0;
}
.tm-lead { grid-column: 7 / -1; position: relative; margin-top: calc(34.25 * var(--u)); }
.tm-lead p {
  margin: 0;
  padding-right: calc(40 * var(--u));      /* o [↓] mora no canto */
  font: 400 var(--t-26)/calc(37 / 26) var(--mono);
  letter-spacing: 0;
  white-space: pre-line;                    /* a quebra digitada vale */
}
/* [↓] na margem direita, na linha de base da última linha do complemento. */
.tm-down {
  position: absolute; right: 0; bottom: calc(7 * var(--u));
  font: 400 var(--t-14)/1 var(--mono);
}

/* Foto na largura do grid (60 → 1650), na proporção do próprio arquivo. */
.tm-photo { margin: 0; padding: 0 var(--m-x); }
.tm-photo img { display: block; width: 100%; height: auto; background: var(--frame); }

/* A afirmação e o texto corrido. A linha nasce 37 depois da foto (a
   mesma regra da página de projeto) e corre de borda a borda. A
   afirmação (26) e o texto (Medium 14, entrelinha 28) se alinham pelo
   CENTRO DAS MAIÚSCULAS da primeira linha: 277,5 nos dois. */
.tm-about {
  margin-top: calc(37 * var(--u));
  border-top: 1px solid var(--rule);
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
  align-items: start;
  padding: calc(118.15 * var(--u)) var(--m-x) calc(81.5 * var(--u));
  text-transform: none;
}
.tm-statement {
  grid-column: 1 / 7;
  margin: 0;
  font: 400 var(--t-26)/calc(37 / 26) var(--mono);
  white-space: pre-line;
}
.tm-body { grid-column: 7 / 12; margin-top: calc(4.62 * var(--u)); }
/* UM TEXTO SÓ À DIREITA. O corpo da abertura, o texto de cada seção e a
   frase antes dos prêmios são a MESMA regra: Medium 14, entrelinha 28,
   colunas 7–11. Antes as seções usavam 18 (lido do frame 16) e a página
   tinha dois tamanhos de texto corrido na mesma coluna — a dupla pediu
   para padronizar pelo de cima. Uma regra só é o que impede os dois de
   se separarem de novo. */
.tm-body p,
.acc-text p,
.awd-intro {
  margin: 0;
  font: 500 var(--t-14)/2 var(--mono);
  white-space: pre-line;
}
/* Parágrafos separados por uma linha em branco, como no desenho. */
.tm-body p + p,
.acc-text p + p { margin-top: calc(28 * var(--u)); }

/* --- as seções que abrem e fecham (frames 15 e 16) ---------------------
   Cada uma é uma linha de 86,75 com a divisória de borda a borda; o
   nome (SemiBold 14) na coluna 1 e o [ + ] na 7, com a maiúscula 25,5
   abaixo da linha. A primeira divisória é a de baixo do texto corrido. */
.acc { border-top: 1px solid var(--rule); }
.acc > summary {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
  padding: calc(22.02 * var(--u)) var(--m-x) calc(49.73 * var(--u));
  list-style: none;
  cursor: pointer;
}
.acc > summary::-webkit-details-marker { display: none; }
.acc > summary h2 { grid-column: 1 / 7; margin: 0; font: 600 var(--t-14)/1 var(--mono); }
.acc .tog { grid-column: 7 / -1; font: 400 var(--t-14)/1 var(--mono); white-space: pre; }
.acc .tog::before { content: "[ + ]"; }
.acc[open] .tog::before { content: "[ - ]"; }
/* Aberta, o conteúdo começa 72,5 abaixo da linha. */
.acc[open] > summary { padding-bottom: calc(35.48 * var(--u)); }
/* Fechando (o render.js anima a altura): o sinal e o respiro voltam aos
   da linha fechada logo no começo, andando junto com a altura. */
.acc > summary { transition: padding-bottom .45s var(--ease); }
.acc[open].is-fechando > summary { padding-bottom: calc(49.73 * var(--u)); }
.acc.is-fechando .tog::before { content: "[ + ]"; }

.acc-body {
  overflow: hidden;          /* a altura anima; a linha que sangra fica dentro do padding */
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
  padding: 0 var(--m-x) calc(30 * var(--u));
  text-transform: none;
}
.acc-body > * { grid-column: 7 / -1; }
.acc-text, .awd-intro { grid-column: 7 / 12; }   /* o tamanho é o do .tm-body p, acima */

/* As linhas (prêmios e listas): 60 de passo, divisória da coluna 7 até
   a borda DA JANELA — a margem negativa é o que faz sangrar. O detalhe
   começa na coluna 9. */
.acc-rows { list-style: none; margin: 0 calc(-1 * var(--m-x)) 0 0; padding: 0; }
.awd-intro + .acc-rows { margin-top: calc(66 * var(--u)); }
.acc-rows li {
  display: grid;
  grid-template-columns: calc(265.83 * var(--u)) 1fr;
  border-top: 1px solid var(--rule);
  padding: calc(22.02 * var(--u)) 0 calc(22.98 * var(--u));
  font: 400 var(--t-14)/1 var(--mono);
}
.acc-rows b { font-weight: 500; text-transform: uppercase; }

/* ============================================================
   CONTACT — redesenho em grid (frame 17)
   ============================================================ */

/* A frase (18/26,5) na coluna 1, o P.S. na 7, com a mesma linha de base. */
.ct-top {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
  align-items: start;
  padding: calc(62.4 * var(--u)) var(--m-x) calc(85 * var(--u));
  text-transform: none;
}
.ct-intro, .ct-ps {
  margin: 0;
  font: 400 var(--t-18)/calc(26.5 / 18) var(--mono);
  white-space: pre-line;
}
.ct-intro { grid-column: 1 / 7; }
.ct-ps    { grid-column: 7 / -1; }

/* Um cartão por pessoa, em metades do grid: foto quadrada de duas
   colunas e o texto 331,67 depois do início dela. */
.ct-people {
  border-top: 1px solid var(--rule);
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
  row-gap: calc(82 * var(--u));
  padding: calc(82 * var(--u)) var(--m-x) calc(91.25 * var(--u));
}
.ct-card { grid-column: span 6; display: flex; align-items: flex-start; }
.ct-photo {
  flex: none;
  width: calc(260.83 * var(--u));
  aspect-ratio: 1;
  overflow: hidden;
  border-radius: calc(4.5 * var(--u));
  background: var(--frame);
}
.ct-photo img { display: block; width: 100%; height: 100%; object-fit: cover; }
.ct-info { margin: calc(15.25 * var(--u)) 0 0 calc(70.84 * var(--u)); min-width: 0; }
.ct-info h2   { margin: 0; font: 600 var(--t-18)/1 var(--mono); }
.ct-info .role { margin: calc(12.5 * var(--u)) 0 0; font: 500 var(--t-14)/1 var(--mono); }

/* As linhas de contato: rótulo (Medium) e valor (Regular) a uma coluna
   de distância; a divisória tem a largura do conteúdo, como no desenho
   (318 com os emails da dupla). */
.ct-list {
  margin: calc(33.25 * var(--u)) 0 0;
  display: grid;
  width: max-content;
  min-width: calc(318 * var(--u));
  max-width: 100%;
}
.ct-list > div {
  display: grid;
  grid-template-columns: calc(133.33 * var(--u)) auto;
  border-top: 1px solid var(--rule);
  padding: calc(21.52 * var(--u)) 0 calc(23.48 * var(--u));
  font: 400 var(--t-14)/1 var(--mono);
}
.ct-list dt { font-weight: 500; }
.ct-list dd { margin: 0; white-space: nowrap; }
/* A roleta (.rl) tem janela de 1,6em por padrão — aqui ela engordava
   cada linha de 60 para 68,4 (medido). Entrelinha 1, presa no topo. */
.ct-list .rl, .ct-general .rl { line-height: 1; vertical-align: top; }

/* Os contatos gerais: um por linha, a partir da coluna 7, com o email
   na mesma vertical do texto do cartão da direita. */
.ct-general {
  border-top: 1px solid var(--rule);
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
  padding: calc(73.77 * var(--u)) var(--m-x) calc(55.25 * var(--u));
}
.ct-general > div {
  grid-column: 7 / -1;
  display: flex;
  font: 400 var(--t-14)/1 var(--mono);
}
.ct-general > div + div { margin-top: calc(14 * var(--u)); }
.ct-general .q { flex: none; width: calc(331.67 * var(--u)); font-weight: 500; }

/* ABAIXO DE 1024: empilhado (decisão da dupla). Os números em u viram
   pixels; aqui só o que muda de lugar. */
@media (max-width: 1023px) {
  .tm-top, .tm-about, .ct-top { padding-top: 48px; padding-bottom: 48px; row-gap: 24px; }
  .tm-headline, .tm-lead, .tm-statement, .tm-body,
  .ct-intro, .ct-ps { grid-column: 1 / -1; margin-top: 0; }
  .tm-about { margin-top: 24px; }
  .acc > summary h2 { grid-column: 1 / 9; }
  .acc .tog { grid-column: 9 / -1; justify-self: end; }
  .acc-body > *, .acc-text, .acc-text p, .awd-intro { grid-column: 1 / -1; }
  .awd-intro + .acc-rows { margin-top: 32px; }
  .acc-rows li { grid-template-columns: minmax(0, 2fr) minmax(0, 3fr); column-gap: 12px; padding-right: var(--m-x); }
  .ct-people { padding-top: 48px; padding-bottom: 48px; row-gap: 48px; }
  .ct-card { grid-column: 1 / -1; }
  .ct-general { padding-top: 40px; padding-bottom: 40px; }
  .ct-general > div { grid-column: 1 / -1; flex-wrap: wrap; row-gap: 8px; }
  .ct-general .q { width: 50%; }
}
@media (max-width: 767px) {
  .acc-rows li { grid-template-columns: 1fr; row-gap: 8px; }
  .ct-card { flex-direction: column; }
  .ct-photo { width: 160px; }
  .ct-info { margin: 20px 0 0; width: 100%; }
  .ct-list { width: 100%; min-width: 0; }
  .ct-list > div { grid-template-columns: 110px minmax(0, 1fr); }
  .ct-list dd { white-space: normal; overflow-wrap: anywhere; }
  .ct-general .q { width: 100%; }
}

/* ============================================================
   VÍDEO — sempre embed, nunca hospedado
   O contêiner segura a proporção antes do iframe carregar, então a
   página não pula quando o player entra.
   ============================================================ */
.vrow { margin-top: var(--bgap); }
.vframe {
  position: relative;
  aspect-ratio: var(--vr, 16 / 9);
  background: var(--frame);
  max-width: 100%;
  margin-inline: auto;
}
/* O TETO DE ALTURA VALE SÓ PARA AS PROPORÇÕES ALTAS.
   Com `aspect-ratio` travada, limitar a altura encolhe a LARGURA junto —
   e era isso que deixava o player estreito: medido a 1440×800, a imagem
   Full saía 1377px e o vídeo 16:9 saía 1203px, 174px mais magro. Num 16"
   passava de 200px. No scroll, alternar imagem e vídeo fazia a página
   respirar de um lado para o outro sem motivo visível.

   Um vídeo 16:9 é a mesma caixa da imagem Full (2400/1350 é 16:9), então
   sem teto ele casa exatamente. Já 1:1 e 9:16 em largura total ficariam
   altos demais — um vertical de 1240px de largura pediria 2.204px de
   altura, quase três telas — e para esses o teto continua, com a moldura
   centrada, que é como uma peça vertical aparece de fato. */
.vframe--alto { max-height: calc(100svh - var(--hdr) - 6 * var(--bgap)); }
.vframe iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

/* ============================================================
   RODAPÉ — posições
   Do direcional de 11/10: o ano à esquerda e o nome da dupla à direita,
   em TODAS as páginas (as regras ficam junto do cabeçalho, lá em cima).
   O crédito do desenvolvimento, que só existe no The Team, ocupa o
   centro — o lugar que sobra sem disputar com nenhum dos dois.
   ============================================================ */
