/* ─── Tipografia ─────────────────────────────────────────────────────────────
   Display, texto e UI: Sora (variável, 100–800), servida localmente de
   assets/fonts/. Auto-hospedada de propósito — sem requisição ao Google,
   sem FOUT distante, e funciona offline.

   Sora é geométrica e de contrações retas: os pesos baixos carregam a
   manchete, os médios o corpo, e os altos o que precisa de peso (nav, pills).
────────────────────────────────────────────────────────────────────────────*/

@font-face {
  font-family: 'Sora';
  src: url('../assets/fonts/Sora-VariableFont_wght.ttf') format('truetype-variations'),
       url('../assets/fonts/Sora-VariableFont_wght.ttf') format('truetype');
  font-weight: 100 800;
  font-style: normal;
  font-display: swap;
}

:root {
  --font-display: 'Sora', system-ui, -apple-system, sans-serif;
  --font-ui: 'Sora', system-ui, -apple-system, sans-serif;
  --font-accent: 'Sora', system-ui, -apple-system, sans-serif;

  /* ── Cores ──────────────────────────────────────────────────────────────
     O vinho da marca (#8C281E, amostrado do arquivo do logo) tomou o lugar
     do verde. Os nomes das variáveis foram mantidos para não reescrever as
     ~20 regras que os usam: --color-green* agora aponta para o vinho. */
  --color-cream: #F4F2EC;
  --color-paper: #FBF9F4;
  --color-ink: #1B1A17;
  --color-ink-soft: #4A4741;
  --color-ink-faint: #8B877D;

  /* Vinho da marca. base = logo; deep = repouso/estado escuro;
     light = tinta clara para fundos e realces. */
  --color-green: #8C281E;
  --color-green-deep: #6B1B14;
  --color-green-light: #F0DDD9;

  --color-coral: #C4482F;
  --color-coral-light: #F5DAD3;
  --color-sand: #DCCFB8;
  --color-white: #FFFFFF;
  --color-charcoal: #24231F;

  /* Nome próprio da marca, para código novo não precisar falar "green". */
  --color-brand: var(--color-green);
  --color-brand-deep: var(--color-green-deep);
  --color-brand-light: var(--color-green-light);

  /* ── Tipo fluido ──────────────────────────────────────────────────────── */
  --text-meta: clamp(0.75rem, 0.85vw, 0.875rem);
  --text-ui: clamp(0.875rem, 0.95vw, 1rem);
  --text-body: clamp(1rem, 1.1vw, 1.125rem);
  --text-section: clamp(1.75rem, 2vw, 2rem);
  --text-hero: clamp(2rem, 4.4vw, 4rem);
  --text-display: clamp(2rem, 4.4vw, 4rem);

  --page-margin: 7vw;
  --radius: 10px;
  --radius-lg: 18px;
  --radius-round: 999px;

  --card-shadow:
    0 1px 2px color-mix(in srgb, var(--color-ink) 6%, transparent),
    0 10px 30px -10px color-mix(in srgb, var(--color-ink) 16%, transparent);
  --card-shadow-hover:
    0 2px 4px color-mix(in srgb, var(--color-ink) 8%, transparent),
    0 20px 48px -14px color-mix(in srgb, var(--color-ink) 22%, transparent);

  --dot-tile: 18px;
  --dot-dot: 1px;
  --dot-opacity: 0.28;

  --noise-opacity: 0.3;
  --noise-size: 180px;

  --nav-shadow-depth: 78%;
  --nav-shadow-alpha: 39%;
}

/* ─── Reset ───────────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

html {
  overflow-x: hidden;
  scroll-behavior: auto;
}
.lenis.lenis-smooth { scroll-behavior: auto !important; }

body {
  min-height: 100%;
  font-family: var(--font-ui);
  font-weight: 400;
  line-height: 1.45;
  background-color: var(--color-cream);
  color: var(--color-ink);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  transition: background-color 0.6s ease, color 0.6s ease;
}

/* Quebras consistentes no conteúdo editorial em todas as páginas.
   `pretty` evita linhas finais muito curtas em parágrafos; `balance` distribui
   títulos em linhas mais próximas sem interferir nos elementos com nowrap. */
:where(p, li, dd, blockquote) { text-wrap: pretty; }
:where(h1, h2, h3, h4) { text-wrap: balance; }

img, svg, video { display: block; max-width: 100%; }
button { font: inherit; color: inherit; background: none; border: none; cursor: pointer; }
a { color: inherit; }
::selection { background: var(--color-coral-light); color: var(--color-ink); }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ─── Grão ──────────────────────────────────────────────────────────────
   Camada fixa de filme, abaixo do cursor e dos overlays, acima do fundo.
   Para desligar: --noise-opacity: 0 */
body::after {
  content: '';
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 10;
  opacity: var(--noise-opacity);
  transition: opacity 0.5s ease;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.75' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-repeat: repeat;
  background-size: var(--noise-size);
}
body[data-bg="hero"]::after { opacity: 0; }

/* ─── Estados de fundo ────────────────────────────────────────────────────
   --nav-fg / --nav-bg viajam com o estado, então a barra se repinta sozinha. */
body[data-bg="hero"] {
  background-color: var(--color-cream);
  color: var(--color-ink);
  --nav-fg: var(--color-ink);
  --nav-bg: var(--color-cream);
  --nav-shadow-depth: 78%;
  --nav-shadow-alpha: 39%;
}
body[data-bg="green"] {
  background-color: var(--color-green);
  color: var(--color-cream);
  --nav-fg: var(--color-cream);
  --nav-bg: var(--color-green);
}
body[data-bg="dark"] {
  background-color: var(--color-ink);
  color: var(--color-white);
  --nav-fg: var(--color-cream);
  --nav-bg: var(--color-ink);
}

/* ─── Nav ─────────────────────────────────────────────────────────────── */
.nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 12px var(--page-margin);
  color: var(--nav-fg);
  background-color: var(--nav-bg);
  border-bottom: 1px solid color-mix(in srgb, var(--nav-fg) 20%, transparent);
  --nav-shadow: color-mix(in srgb, var(--nav-bg) var(--nav-shadow-depth), #000);
  box-shadow: 0 4px 12px -4px color-mix(in srgb, var(--nav-shadow) var(--nav-shadow-alpha), transparent);
  opacity: 0;
  transform: translateY(-100%);
  pointer-events: none;
  transition: transform 0.42s cubic-bezier(0.4, 0, 0.2, 1),
              opacity 0.28s ease,
              background-color 0.6s ease,
              box-shadow 0.6s ease,
              color 0.6s ease;
}
.nav.nav-visible { opacity: 1; transform: translateY(0); pointer-events: auto; }

.nav-links { display: flex; align-items: center; gap: 8px; }

.nav-logo,
.nav-link {
  display: inline-grid;
  grid-template-areas: "label";
  align-items: center;
  justify-items: center;
  min-height: 44px;
  font-family: var(--font-display);
  font-size: var(--text-ui);
  line-height: 1;
  letter-spacing: -0.01em;
  color: inherit;
  text-decoration: none;
  white-space: nowrap;
  border-radius: var(--radius);
  padding: 12px 16px;
}
.nav-link > span { grid-area: label; }
.nav-logo { font-weight: 600; margin-left: -16px; }
.nav-link { font-weight: 400; }
.nav-links .nav-link:last-child { margin-right: -16px; }

/* ── Logo: símbolo S + nome ──
   O logo é um símbolo de traço e um nome, lado a lado. O símbolo é SVG
   inline (index.html) e herda a cor do contexto via currentColor, então
   acompanha o vinho sobre fundo claro e o creme sobre o vinho — sem
   precisar de duas versões do arquivo. */
.nav-logo {
  display: flex;
  align-items: center;
  gap: 10px;
}
/* O símbolo é mais alto que largo (razão 0,847 medida no path). Uma caixa
   quadrada o esticaria; aqui a altura manda e a largura sai dela. */
.nav-mark { display: block; height: 26px; width: 22px; flex: 0 0 auto; }
.nav-mark svg { display: block; width: 100%; height: 100%; overflow: visible; }
.nav-name { display: inline-flex; align-items: baseline; }

.nav-link::after {
  content: attr(data-label);
  grid-area: label;
  font-weight: 600;
  visibility: hidden;
  pointer-events: none;
}
.nav-link:hover > span,
.nav-link:focus-visible > span { font-weight: 600; }

/* O brilho no hover vale só para o nome: o símbolo é um traço e vira
   invisível sob background-clip: text. */
.nav-name {
  background-image: linear-gradient(100deg,
    var(--nav-fg) 42%,
    color-mix(in srgb, var(--nav-fg) 50%, var(--nav-bg)) 50%,
    var(--nav-fg) 58%);
  background-size: 300% 100%;
  background-repeat: no-repeat;
  background-position: 100% 0;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}
.nav-logo:hover .nav-name,
.nav-logo:focus-visible .nav-name { animation: nav-shimmer 900ms ease-out; }
@keyframes nav-shimmer {
  from { background-position: 100% 0; }
  to   { background-position: 0% 0; }
}

.nav-logo:focus-visible,
.nav-link:focus-visible { outline: 2px solid var(--nav-fg); outline-offset: 4px; }

/* Nav em telas estreitas. O problema medido: logo (173px com o nome
   completo) + quatro links (378px) = 551px numa viewport de 390px. Cada
   faixa abaixo remove uma peça, na ordem que menos custa ao visitante. */
@media (max-width: 760px) {
  .nav { gap: 12px; padding-inline: 16px; }
  .nav-logo, .nav-link { padding-inline: 10px; font-size: 0.9375rem; }
  .nav-logo { margin-left: -10px; }
  .nav-links { gap: 2px; }
  .nav-links .nav-link:last-child { margin-right: -10px; }
}
@media (max-width: 560px) {
  /* O sobrenome sai: 173px de logo viram 74px. */
  .nav { padding-inline: 12px; }
  .nav-logo { margin-left: -8px; }
  .nav-surname { display: none; }
  .nav-logo, .nav-link { padding-inline: 8px; font-size: 0.9375rem; }
  .nav-links { gap: 0; }
  .nav-links .nav-link:last-child { margin-right: -8px; }
}
@media (max-width: 479px) {
  /* Nem o primeiro nome cabe: 74px de logo + 372px de links passam de
     470px. O logo sai (display:none também o tira da tabulação) e a nav
     fica só com os destinos. O nome segue na manchete do hero, e o botão
     de voltar ao topo faz o que o logo fazia. */
  .nav { padding-inline: 8px; }
  .nav-logo { display: none; }
  .nav-links { gap: 0; width: 100%; justify-content: space-between; }
  .nav-link { padding-inline: 6px; font-size: 0.875rem; }
  .nav-links .nav-link:last-child { margin-right: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .nav { transition: opacity 0.2s ease; transform: none; }
  .nav.nav-visible { transform: none; }
  .nav-logo:hover .nav-name, .nav-logo:focus-visible .nav-name { animation: none; }
}

/* ─── Conteúdo sem JavaScript ───────────────────────────────────────────
   O <noscript> desenha a lista de projetos e o contato quando o JS está
   desligado. Sem estilo ele apareceria como uma lista com marcadores solta
   dentro de uma seção centralizada, então aqui ele recebe a mesma
   tipografia do resto. */
.pro-fallback {
  width: 100%;
  max-width: 60ch;
  margin: 0 auto;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.pro-fallback li {
  font-size: 1rem;
  line-height: 1.5;
  color: var(--color-ink-soft);
  padding-bottom: 14px;
  border-bottom: 1px solid color-mix(in srgb, var(--color-ink) 14%, transparent);
}
.pro-fallback strong { color: var(--color-ink); font-weight: 600; }
#contato .pro-fallback li { border-color: color-mix(in srgb, var(--color-cream) 30%, transparent); }
#contato .pro-fallback a { color: var(--color-cream); text-underline-offset: 4px; }
#contato .pro-fallback a:focus-visible { outline: 2px solid var(--color-cream); outline-offset: 4px; }

/* Quando o JS funciona, o painel é <dialog> e o <noscript> nunca é
   renderizado — não há conflito entre os dois. */

/* ─── Seções ──────────────────────────────────────────────────────────── */
.section {
  height: 100svh;
  padding: 6vw var(--page-margin);
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  z-index: 1;
}
#trabalho.section,
#contato.section {
  height: auto;
  padding-top: max(6rem, 11vw);
  min-height: 100svh;
}
#introducao.section { height: auto; min-height: 100svh; }
#trabalho.section { padding-bottom: max(6rem, 14vw); }

.section-inner { width: 100%; }

.section-title {
  font-family: var(--font-display);
  font-size: var(--text-section);
  line-height: 1.06;
  letter-spacing: -0.03em;
  font-weight: 400;
  max-width: 60%;
  margin-bottom: clamp(1.5rem, 3vw, 3rem);
}

/* ─── Botão ───────────────────────────────────────────────────────────────
   O único botão do site, com todos os consumidores lendo daqui. */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 16px;
  padding: 16px 24px;
  border-radius: var(--radius-round);
  background: var(--color-ink);
  color: var(--color-cream);
  font-family: var(--font-ui);
  font-weight: 400;
  font-size: var(--text-ui);
  line-height: 1;
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
}
.btn svg { flex: 0 0 auto; }
.btn--icon { padding: 12px 24px; border-radius: var(--radius); }

/* ─── Hero ────────────────────────────────────────────────────────────────
   Três linhas de manchete, um carrossel curvo de pills e um card 3D que vira
   uma face por pill. Cada face tem mídia, uma camada que flutua a 24px e um
   título a 64px, para o tipo paralaxar sobre a imagem quando o card vira. */
#introducao.g-hero {
  min-height: 100svh;
  padding: 96px 0 48px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  overflow: hidden;
}

.g-eyebrow {
  margin: 0 0 16px;
  font-family: var(--font-accent);
  font-weight: 400;
  font-size: clamp(1.25rem, 1.8vw, 2rem);
  line-height: 1.1;
  color: color-mix(in srgb, var(--color-ink) 62%, var(--color-white));
}

.g-head-wrap { width: min(100% - 12vw, 1040px); container-type: inline-size; }
.g-head {
  margin: 0;
  font-family: var(--font-display);
  font-size: min(var(--text-hero), 100cqi / 12.4);
  line-height: 1.04;
  letter-spacing: -0.035em;
  font-weight: 300;
  color: var(--color-ink);
}
/* Cada .g-line é um BLOCK, não um inline: as três linhas da manchete existem
   para quebrar o texto em pontos escolhidos, e com display:inline elas
   corriam todas na mesma linha. Em tela larga isso estourava o .g-head-wrap
   (1844px de conteúdo em 1040px de caixa) e o texto vazava para a direita,
   deixando o h1 visivelmente fora de centro. Como bloco, cada linha é
   centralizada dentro da wrap por text-align: center do .g-head. */
.g-line { display: block; white-space: nowrap; }
.g-word { display: inline-block; white-space: nowrap; }

.g-char { display: inline-block; position: relative; }
.g-glyph { display: inline-block; transition: opacity .12s ease, transform .12s ease; }
.g-char.is-swapped .g-glyph { opacity: 0; transform: scale(.6); }
.g-head.is-entering .g-glyph { transition: none; }
.g-obj {
  position: absolute; left: 50%; top: 50%;
  font-size: .58em; line-height: 1;
  color: var(--color-coral);
  pointer-events: none;
  translate: -50% -46%;
}

/* ── Carrossel curvo ──
   As pills ficam sobre um cilindro de eixo vertical. O script posiciona cada
   uma pela distância de arco até o centro: ela gira para o lado, recua e fica
   de perfil perto das pontas, sumindo depois de ~80°. */
.g-strip {
  position: relative;
  width: min(680px, 100%);
  height: 124px;
  margin: 30px 0 -16px;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 20%, #000 80%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 20%, #000 80%, transparent);
  perspective: 1800px;
  transform-style: preserve-3d;
  touch-action: pan-y;
  cursor: grab;
  user-select: none;
  -webkit-user-select: none;
}
.g-strip.is-dragging { cursor: grabbing; }
.g-strip:focus { outline: none; }
.g-strip:focus-visible .g-pill.is-active { outline: 2px solid var(--color-ink); outline-offset: 2px; }

.g-pill {
  position: absolute;
  left: 50%; top: 50%;
  display: inline-flex;
  align-items: center;
  gap: 12px;
  height: 60px;
  margin-top: -30px;
  padding: 0 22px 0 10px;
  border-radius: var(--radius-round);
  background: transparent;
  color: color-mix(in srgb, var(--color-ink) 52%, transparent);
  font-family: var(--font-ui);
  font-weight: 500;
  font-size: clamp(16px, 1.35vw, 21px);
  letter-spacing: -0.03em;
  white-space: nowrap;
  cursor: inherit;
  backface-visibility: hidden;
  overflow: hidden;
  isolation: isolate;
  transition: background-color .3s ease, color .3s ease, box-shadow .3s ease;
}
.g-pill img, .g-pill .g-thumb {
  flex: 0 0 auto;
  width: 40px; height: 40px;
  border-radius: var(--radius-round);
  object-fit: cover;
  -webkit-user-drag: none;
}
/* A marca na pill: o S é mais alto que largo e desenhado em traço escuro.
   Com `cover` ele seria cortado nas laterais; com `contain` sobre um disco
   claro ele aparece inteiro e não some contra o fundo da pill. */
.g-pill img.is-mark {
  object-fit: contain;
  padding: 8px;
  background: var(--color-white);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--color-ink) 12%, transparent);
}
.g-pill .g-emoji {
  flex: 0 0 auto; width: 40px; text-align: center;
  font-size: 24px; line-height: 1; letter-spacing: 0;
}
.g-pill::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: color-mix(in srgb, var(--color-ink) 6%, var(--color-white));
  transform: scaleX(0);
  transform-origin: 0 50%;
}
.g-pill.is-timing::before { animation: g-fill 3s linear forwards; }
.g-hero.is-paused .g-pill.is-timing::before { animation-play-state: paused; }
@keyframes g-fill { to { transform: scaleX(1); } }

.g-pill.is-active {
  background: var(--color-paper);
  color: var(--color-ink);
  box-shadow: 0 2px 4px color-mix(in srgb, var(--color-ink) 6%, transparent),
              0 16px 40px -12px color-mix(in srgb, var(--color-ink) 22%, transparent);
}

/* ── Card 3D ──
   Cada face é um grupo 3D, não uma figura plana. Só a camada de mídia recorta;
   o conteúdo flutua à frente. Nada com preserve-3d recebe overflow: hidden,
   que é o que faz o Safari achatar um grupo 3D. */
.g-stage {
  margin-top: 14px;
  perspective: 1000px;
  -webkit-box-reflect: below 4px linear-gradient(transparent 80%, rgba(0, 0, 0, .16));
}
.g-card {
  position: relative;
  width: clamp(200px, 17vw, 252px);
  aspect-ratio: 280 / 400;
  transform-style: preserve-3d;
  cursor: pointer;
}
.g-card-shadow {
  position: absolute; inset: 6% 4% -2%;
  border-radius: 18px;
  background: rgba(0, 0, 0, .3);
  filter: blur(20px);
  opacity: .4;
  transform: translateZ(-1px);
}
.g-face { position: absolute; inset: 0; transform-style: preserve-3d; }
.g-face--b { transform: rotateY(180deg); }
.g-media, .g-layer {
  position: absolute; inset: 0;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}
.g-media {
  border-radius: 18px;
  overflow: hidden;
  background: var(--color-charcoal);
}
.g-media > img { width: 100%; height: 100%; object-fit: cover; -webkit-user-drag: none; }
.g-field {
  position: absolute; inset: 0;
  background-image: radial-gradient(circle, color-mix(in srgb, var(--color-cream) 22%, transparent) 1px, transparent 1px);
  background-size: 16px 16px;
  background-position: 8px 8px;
}
.g-shade { position: absolute; inset: 0; background: #000; opacity: 0; pointer-events: none; }
.g-layer { pointer-events: none; transform-style: preserve-3d; }
.g-layer--mid { transform: translateZ(24px); }
.g-layer--title { transform: translateZ(64px); }
.g-title {
  position: absolute; left: 2px; right: 2px;
  top: 87%;
  transform: translateY(-50%);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(12px, 0.98vw, 15.5px);
  line-height: 1.1;
  letter-spacing: 0;
  white-space: nowrap;
  text-align: center;
  color: var(--color-cream);
  text-shadow: 0 1px 2px rgba(0, 0, 0, .45);
}

.g-brick {
  position: absolute;
  left: 0; top: 0;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 42px;
  padding: 0 16px;
  border-radius: var(--radius-round);
  background: color-mix(in srgb, var(--color-charcoal) 70%, var(--color-cream));
  color: var(--color-ink);
  font-family: var(--font-ui);
  font-weight: 500;
  font-size: 15px;
  letter-spacing: -0.02em;
  white-space: nowrap;
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--color-cream) 40%, transparent),
              0 1px 1px rgba(0, 0, 0, .18), 0 14px 28px -10px rgba(0, 0, 0, .45);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  transform-origin: 50% 100%;
  opacity: 0;
}
.g-brick--accent { background: var(--color-coral); color: var(--color-white); }
.g-brick--green { background: var(--color-green); color: var(--color-cream); }

@media (max-width: 640px) {
  #introducao.g-hero { padding-top: 132px; }
  .g-line { white-space: normal; }
  .g-title { font-size: clamp(11px, 3vw, 12px); }
}
@media (prefers-reduced-motion: reduce) { .g-char { transition: none; } }

/* ── Scroll cue ── */
.scroll-cue {
  position: absolute;
  left: 50%; bottom: 22px;
  translate: -50% 0;
  width: 44px; height: 44px;
  display: grid; place-items: center;
  border-radius: var(--radius-round);
  transition: opacity .3s ease;
}
.scroll-cue.is-gone { opacity: 0; pointer-events: none; }
.scroll-cue-dot {
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--color-ink);
  opacity: .8;
}

/* ── Campo de pontos ──
   Uma grade só atrás de about, trabalho, visual e depoimentos. Cada seção
   alinha as próprias linhas por --dot-shift, medido pelo app.js, para os
   pontos atravessarem as emendas sem degrau. */
.dots-layer,
#trabalho::before,
#visual::before,
#depoimentos::before,
.more-overlay {
  background-image: radial-gradient(circle, var(--dot-ink, var(--color-ink)) var(--dot-dot), transparent var(--dot-dot));
  background-size: var(--dot-tile) var(--dot-tile);
  background-position: calc(var(--dot-tile) / 2) calc(var(--dot-tile) / 2);
}
#trabalho::before,
#visual::before,
#depoimentos::before {
  content: '';
  position: absolute;
  inset: 0 var(--page-margin);
  z-index: -1;
  opacity: var(--dot-opacity);
  pointer-events: none;
  background-position: calc(var(--dot-tile) / 2) calc(var(--dot-tile) / 2 + var(--dot-shift, 0px));
}
.dots-layer {
  position: absolute;
  top: var(--dots-top, calc(85.7svh - 8px));
  left: var(--page-margin);
  right: var(--page-margin);
  height: var(--dots-h, calc(114.3svh + 8px));
  z-index: 0;
  opacity: var(--dot-opacity);
  pointer-events: none;
}

/* ─── About ─────────────────────────────────────────────────────────────
   Uma frase, centrada ópticamente, que entra palavra por palavra. */
#sobre .section-inner {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: min(100%, 1180px);
  text-align: center;
}
.about-text {
  font-family: var(--font-display);
  font-size: clamp(1.75rem, 4vw, 4.25rem);
  line-height: 1.14;
  letter-spacing: -0.03em;
  font-weight: 400;
  color: var(--color-cream);
  text-wrap: balance;
}
.experience-bar {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(1.25rem, 3vw, 2.75rem);
  margin: clamp(1.5rem, 3vw, 2.5rem) auto 0;
  color: color-mix(in srgb, var(--color-cream) 68%, transparent);
}
.experience-bar__label {
  margin: 0;
  font-family: var(--font-ui);
  font-size: clamp(.75rem, .95vw, .9rem);
  line-height: 1.35;
  text-align: right;
  white-space: nowrap;
}
.experience-bar__logos {
  display: block;
  flex: 0 1 auto;
  width: min(38vw, 391px);
  height: auto;
}
.about-bold {
  font-weight: 700;
  white-space: nowrap;
}
.about-cta {
  margin-top: clamp(2rem, 4vw, 3.5rem);
  background: var(--color-cream);
  color: var(--color-ink);
  opacity: 1;
  transition: background-color .3s ease, color .3s ease;
}
.about-cta:hover { background: var(--color-ink); color: var(--color-cream); }
#sobre { cursor: none; }

@media (max-width: 640px) {
  .experience-bar { flex-direction: column; gap: 14px; }
  .experience-bar__label { text-align: center; }
  .experience-bar__logos { width: min(100%, 391px); }
}

/* Palavras do reveal */
.word-wrap { display: inline-block; overflow: hidden; vertical-align: bottom; }
.word { display: inline-block; }

/* ─── Cursor customizado ───────────────────────────────────────────────── */
.cursor-label {
  position: fixed;
  left: 0; top: 0;
  z-index: 900;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 16px;
  border-radius: var(--radius-round);
  background: var(--cursor-bg, var(--color-ink));
  color: var(--cursor-fg, var(--color-cream));
  font-family: var(--font-ui);
  font-size: 14px;
  font-weight: 500;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  translate: 12px 12px;
  transition: opacity .18s ease;
}
.cursor-label.visible { opacity: 1; }
.cursor-label svg { flex: 0 0 auto; }
.cursor-label .icon-copy,
.cursor-label .icon-arrow-up-right,
.cursor-label .icon-clock { display: none; }
.cursor-label.contact-email .icon-arrow { display: none; }
.cursor-label.contact-email .icon-copy { display: block; }
.cursor-label.contact-link .icon-arrow { display: none; }
.cursor-label.contact-link .icon-arrow-up-right { display: block; }
.cursor-label.contact-copied .icon-arrow,
.cursor-label.contact-copied .icon-copy { display: none; }
.cursor-label.work-soon .icon-arrow { display: none; }
.cursor-label.work-soon .icon-clock { display: block; }

/* ─── Toast ────────────────────────────────────────────────────────────── */
.copy-toast {
  position: fixed;
  left: 50%; bottom: 32px;
  translate: -50% 20px;
  z-index: 950;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 12px 20px;
  border-radius: var(--radius-round);
  background: var(--color-ink);
  color: var(--color-cream);
  font-size: 14px;
  font-weight: 500;
  opacity: 0;
  pointer-events: none;
  transition: opacity .25s ease, translate .25s ease;
}
.copy-toast.visible { opacity: 1; translate: -50% 0; }
/* O texto chega por JS. Sem ele o toast não deve aparecer como uma pílula
   vazia carregando só o visto. */
.copy-toast:not(.visible) { visibility: hidden; }

/* ─── Elevador ────────────────────────────────────────────────────────── */
.elevator-btn {
  position: fixed;
  right: var(--page-margin); bottom: 28px;
  z-index: 80;
  width: 52px; height: 52px;
  display: grid; place-items: center;
  border-radius: var(--radius-round);
  background: var(--color-ink);
  color: var(--color-cream);
  opacity: 0;
  translate: 0 12px;
  pointer-events: none;
  transition: opacity .3s ease, translate .3s ease, background-color .3s ease;
}
.elevator-btn.visible { opacity: 1; translate: 0 0; pointer-events: auto; }
.elevator-btn:hover { background: var(--color-coral); }

/* ─── Trabalho: cards ─────────────────────────────────────────────────── */
.pro-section {
  width: min(100%, 1180px);
  margin: 0 auto;
}
.pro-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: flex-start;
  margin-bottom: clamp(1.5rem, 3vw, 2.5rem);
}
.pro-filter {
  /* min-height 44px: alvo de toque confortável no dedo. Com 38px o botão
     ficava abaixo do mínimo recomendado em todas as larguras. */
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  padding: 10px 20px;
  border-radius: var(--radius-round);
  border: 1px solid color-mix(in srgb, var(--color-ink) 18%, transparent);
  background: transparent;
  color: var(--color-ink-soft);
  font-size: var(--text-meta);
  font-weight: 500;
  letter-spacing: -0.01em;
  transition: background-color .25s ease, color .25s ease, border-color .25s ease;
}
.pro-filter:hover { border-color: var(--color-ink); color: var(--color-ink); }
.pro-filter.is-active {
  background: var(--color-ink);
  border-color: var(--color-ink);
  color: var(--color-cream);
}
.pro-filter:focus-visible { outline: 2px solid var(--color-ink); outline-offset: 3px; }

.pro-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(16px, 2vw, 26px);
}
/* O card pode ser <a>, <button> (com case) ou <article> (em breve). Os
   padrões de botão são desfeitos para os três ficarem idênticos: sem borda,
   fundo próprio nem a fonte do sistema, e com o texto alinhado à esquerda. */
.pro-card {
  display: flex;
  flex-direction: column;
  background: var(--color-paper);
  border: 0;
  border-radius: var(--radius-lg);
  padding: 14px;
  color: inherit;
  font: inherit;
  text-align: left;
  text-decoration: none;
  box-shadow: var(--card-shadow);
  transition: box-shadow .35s ease, transform .35s ease;
}
.pro-card:is(a, button) { cursor: none; }
.pro-card:hover { box-shadow: var(--card-shadow-hover); transform: translateY(-3px); }
/* Foco de teclado no card que é controle. O contorno fica por fora do raio
   para não brigar com a sombra do cartão. */
.pro-card:is(a, button):focus-visible {
  outline: 2px solid var(--color-ink);
  outline-offset: 4px;
}
/* [hidden] é a folha do navegador, e o `display: flex` acima a vence — o
   filtro marcava o card como hidden e ele continuava na tela. Esta regra
   devolve o efeito do atributo, e !important porque ela precisa valer
   contra o display declarado na mesma especificidade. */
.pro-card[hidden] { display: none !important; }
.pro-media {
  position: relative;
  aspect-ratio: 16 / 10;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--color-cream2, #EDEAE1);
}
.pro-media img,
.pro-media video {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform .6s cubic-bezier(.2, .8, .2, 1);
}
.pro-card:hover .pro-media img { transform: scale(1.03); }
.pro-card--media-contain .pro-media img { object-fit: contain; }
.pro-card--media-contain:hover .pro-media img { transform: none; }
.pro-media-empty {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  font-size: var(--text-meta);
  color: var(--color-ink-faint);
}
.pro-eyebrow {
  margin-top: 18px;
  font-size: var(--text-meta);
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--color-green);
}
.pro-eyebrow span { color: var(--color-ink-faint); margin: 0 2px; }
.pro-title {
  margin-top: 10px;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(1.35rem, 1.75vw, 1.85rem);
  line-height: 1.12;
  letter-spacing: -0.02em;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.pro-summary {
  margin-top: 8px;
  font-size: var(--text-meta);
  line-height: 1.45;
  color: var(--color-ink-soft);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.pro-card .pro-cta {
  margin-top: 20px;
  align-self: flex-start;
  background: var(--color-ink);
  color: var(--color-cream);
  transition: background-color .25s ease;
}
.pro-card:hover .pro-cta { background: var(--color-coral); }

/* Placa de "em breve": no lugar da seta, para os cards sem link. */
.pro-sign {
  position: relative;
  margin-top: 18px;
  align-self: flex-start;
  padding: 6px 14px 12px;
  border-radius: 6px;
  background: var(--color-sand);
  color: var(--color-ink);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  box-shadow: 0 1px 2px rgba(0, 0, 0, .12);
  transform-origin: 50% 0;
  transition: background-color .25s ease;
}
.pro-sign::before {
  content: '';
  position: absolute;
  inset: 4px 4px auto 4px;
  height: 4px;
  background: repeating-linear-gradient(-45deg,
    var(--color-coral) 0 6px,
    var(--color-ink) 6px 12px);
  opacity: .85;
  border-radius: 2px;
}
.pro-sign-text { position: relative; display: block; padding-top: 4px; }
.pro-sign-bug { display: none; }
.pro-card:hover .pro-sign { transform: rotate(-1.2deg); }

@media (max-width: 800px) {
  .pro-grid { grid-template-columns: 1fr; }
  .section-title { max-width: 100%; }
}

/* ─── Testemunhos: marquee ──────────────────────────────────────────────── */
#depoimentos { overflow: hidden; }
.tm-viewport {
  margin: 0 calc(var(--page-margin) * -1);
  padding: 16px var(--page-margin) 32px;
  overflow: hidden;
}
.tm-track {
  display: flex;
  flex-wrap: nowrap;
  gap: 20px;
  width: max-content;
  will-change: transform;
}
.tm-card {
  flex: 0 0 auto;
  width: clamp(280px, 30vw, 420px);
  padding: clamp(22px, 2vw, 30px);
  border-radius: var(--radius-lg);
  background: var(--color-paper);
  box-shadow: var(--card-shadow);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 24px;
}
.tm-quote {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.05rem, 1.35vw, 1.4rem);
  line-height: 1.35;
  letter-spacing: -0.015em;
}
.tm-quote::before { content: '\201C'; }
.tm-quote::after  { content: '\201D'; }
.tm-attrib { display: flex; align-items: center; gap: 12px; }
.tm-avatar {
  flex: 0 0 auto;
  width: 42px; height: 42px;
  border-radius: 50%;
  object-fit: cover;
}
.tm-avatar--empty {
  display: grid; place-items: center;
  background: var(--color-green-light);
  color: var(--color-green-deep);
  font-weight: 600;
  font-size: 16px;
}
.tm-who { display: flex; flex-direction: column; gap: 2px; }
.tm-name { font-weight: 600; font-size: var(--text-meta); }
.tm-role { font-size: var(--text-meta); color: var(--color-ink-faint); }

.tm-viewport.is-swipe { overflow-x: auto; scrollbar-width: none; }
.tm-viewport.is-swipe::-webkit-scrollbar { display: none; }

/* ─── Contato ──────────────────────────────────────────────────────────── */
#contato { cursor: none; }
.contact-table {
  width: 100%;
  display: flex;
  flex-direction: column;
  border-top: 1px solid color-mix(in srgb, var(--color-cream) 34%, transparent);
}
/* A linha é um <button> (e-mail) ou um <a> (redes). Para o desenho não
   mudar, os padrões de cada um é que são desfeitos: fundo, borda, sublinhado
   e a caixa de texto do botão. Altura vem do padding e do tamanho do texto,
   então a área de toque fica bem acima de 44px nas duas pontas. */
.contact-row {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  width: 100%;
  padding: clamp(16px, 2vw, 28px) 0;
  border: 0;
  border-bottom: 1px solid color-mix(in srgb, var(--color-cream) 34%, transparent);
  background: none;
  color: inherit;
  text-align: left;
  text-decoration: none;
  font: inherit;
  cursor: none;
  transition: padding-left .3s cubic-bezier(.2, .8, .2, 1);
}
.contact-row:hover { padding-left: clamp(12px, 1.5vw, 28px); }
/* Foco de teclado: o mesmo recuo do hover e um contorno que não depende da
   cor do ícone. Fica dentro da seção, sem sair da largura da coluna. */
.contact-row:focus-visible {
  padding-left: clamp(12px, 1.5vw, 28px);
  outline: 2px solid var(--color-cream);
  outline-offset: 4px;
  border-radius: 4px;
}
.contact-row:focus-visible .contact-row-icon {
  background: var(--color-cream);
  color: var(--color-green);
  border-color: var(--color-cream);
}
.contact-row-text {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: var(--text-display);
  line-height: 1.04;
  letter-spacing: -0.035em;
  color: var(--color-cream);
}
.contact-row-text strong { font-weight: 700; }
.contact-row-icon {
  flex: 0 0 auto;
  display: grid; place-items: center;
  width: 52px; height: 52px;
  border-radius: var(--radius-round);
  border: 1px solid color-mix(in srgb, var(--color-cream) 40%, transparent);
  transition: background-color .3s ease, color .3s ease, border-color .3s ease;
}
.contact-row:hover .contact-row-icon {
  background: var(--color-cream);
  color: var(--color-green);
  border-color: var(--color-cream);
}

/* ─── Overlay: Sobre mim ──────────────────────────────────────────────── */
/* Os dois painéis são <dialog> nativos. Aberto, o diálogo já está no top
   layer e o fundo é inerte; o CSS abaixo só desfaz a moldura padrão do
   elemento (que tem borda, padding e centralização próprios) para ele
   voltar a ocupar a tela inteira como antes.

   Fechado, `display: none` é do navegador — por isso nenhum controle
   interno entra na ordem de foco. Não reponha `display` aqui. */
.more-overlay,
.case-overlay {
  position: fixed;
  inset: 0;
  width: 100%;
  max-width: none;
  height: 100%;
  max-height: none;
  margin: 0;
  padding: 0;
  border: 0;
  z-index: 700;
  overflow-y: auto;
  overscroll-behavior: contain;
  /* Branco puro no painel: o creme da página atrás dele puxava o case para
     o bege e competia com as telas, que já são claras. O case é uma
     superfície de leitura, e uma superfície de leitura clara é branca. */
  background-color: #fff;
  opacity: 0;
  transition: opacity .35s ease;
}
.more-overlay { --dot-ink: color-mix(in srgb, var(--color-ink) 16%, transparent); }
.more-overlay[open],
.case-overlay[open] { display: block; }
.more-overlay.visible,
.case-overlay.visible { opacity: 1; }
/* O diálogo recebe o foco inicial (tabindex="-1"), mas ele não é um controle:
   o anel de foco apareceria em volta da tela inteira. O foco continua
   visível onde importa — no botão de fechar e nos links, pelos seus próprios
   :focus-visible. */
.more-overlay:focus,
.case-overlay:focus { outline: none; }
/* O fundo do diálogo é a própria página rolável; o scrim do navegador
   escureceria o creme do painel. */
.more-overlay::backdrop,
.case-overlay::backdrop { background: transparent; }

.more-close,
.case-close {
  position: fixed;
  z-index: 720;
  top: 20px; left: var(--page-margin);
  width: 52px; height: 52px;
  display: grid; place-items: center;
  border-radius: var(--radius-round);
  background: var(--color-ink);
  color: var(--color-cream);
  opacity: .85;
  transition: background-color .25s ease, opacity .25s ease;
}
.more-close:hover,
.case-close:hover { background: var(--color-coral); opacity: 1; }

/* No case o botão sobe para o canto direito e se ancora na borda do
   conteúdo: à esquerda ele flutuava por cima do começo dos títulos. Sólido
   e com anel claro porque agora pode cair sobre uma tela clara. */
.case-close {
  top: 16px;
  left: auto;
  right: max(16px, calc(var(--page-margin) - 8px));
  background: #fff;
  color: var(--color-ink);
  opacity: 1;
  box-shadow: 0 2px 14px rgba(20, 20, 20, .14), inset 0 0 0 1px rgba(20, 20, 20, .12);
}
.case-close:hover { background: var(--color-ink); color: #fff; }
.case-close:focus-visible {
  outline: 2px solid var(--color-green);
  outline-offset: 3px;
}

.more-block {
  width: min(100% - 2 * var(--page-margin), 1180px);
  margin: 0 auto;
}

.more-title {
  font-family: var(--font-display);
  font-size: clamp(1.6rem, 3.1vw, 3.1rem);
  line-height: 1.16;
  letter-spacing: -0.03em;
  font-weight: 400;
  text-align: center;
  max-width: 900px;
  margin: 0 auto clamp(24px, 4vw, 48px);
  text-wrap: balance;
}

/* Perfil em três colunas: texto / foto / texto */
.more-fold--profile {
  padding: clamp(64px, 10vh, 140px) 0 clamp(64px, 10vh, 120px);
}
.more-block--profile {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(260px, 400px) minmax(0, 1fr);
  gap: clamp(24px, 3vw, 48px);
  align-items: center;
}
.more-bio {
  font-size: clamp(1rem, 1.15vw, 1.2rem);
  line-height: 1.55;
  color: var(--color-ink-soft);
}
.more-bio--lead { text-align: right; }
.more-bio--tail { text-align: left; }
.more-profile-img img {
  width: 100%;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  border-radius: var(--radius-lg);
}
@media (max-width: 860px) {
  .more-block--profile { grid-template-columns: 1fr; }
  .more-bio--lead, .more-bio--tail { text-align: left; }
}

/* ─── Prism folder ────────────────────────────────────────────────────── */
#visual { overflow: hidden; overflow: clip; }
.prism-folder { width: 100%; height: clamp(520px, 82vh, 860px); }
.pf-stage {
  position: relative;
  width: 100%; height: 100%;
}
.pf-anchor {
  position: absolute;
  left: 50%; top: 50%;
  translate: -50% -50%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  z-index: 5;
}
.pf-folder {
  position: relative;
  width: clamp(190px, 17vw, 260px);
  aspect-ratio: 1 / 0.76;
  background: none;
  border: none;
  cursor: pointer;
  transform-style: preserve-3d;
  transition: filter .3s ease;
}
.pf-folder:hover { filter: brightness(1.04); }
.pf-tab {
  position: absolute;
  left: 8%; top: -7%;
  width: 40%; height: 14%;
  background: var(--pf-color, var(--color-green));
  border-radius: 8px 8px 0 0;
  filter: brightness(.94);
}
.pf-back {
  position: absolute;
  inset: 0;
  background: var(--pf-color, var(--color-green));
  border-radius: 10px;
  box-shadow: 0 18px 40px -12px rgba(0, 0, 0, .35);
  filter: brightness(.92);
}
.pf-peek { position: absolute; inset: 0; pointer-events: none; }
.pf-peek-item {
  position: absolute;
  left: var(--x, 0); top: var(--y, 0);
  width: var(--w, 40px); height: var(--h, 50px);
  object-fit: cover;
  border-radius: 3px;
  rotate: var(--r, 0deg);
  box-shadow: 0 2px 8px rgba(0, 0, 0, .22);
}
.pf-flap {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 62%;
  border-radius: 0 0 10px 10px;
  background: color-mix(in srgb, var(--pf-color, var(--color-green)) 66%, var(--color-white));
  overflow: hidden;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .35),
              0 -1px 0 rgba(0, 0, 0, .06);
}
.pf-flap::after {
  content: '';
  position: absolute;
  inset: 0;
  backdrop-filter: blur(10px) saturate(1.15);
  -webkit-backdrop-filter: blur(10px) saturate(1.15);
  background: linear-gradient(160deg, rgba(255, 255, 255, .22), rgba(0, 0, 0, .06));
}
.pf-gl {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  z-index: 1;
  opacity: 0;
  transition: opacity .35s ease;
}
.has-gl .pf-gl { opacity: 1; }
.pf-label {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: var(--text-meta);
  color: var(--color-ink-soft);
  transition: opacity .3s ease;
}
.pf-title { font-weight: 500; }
.pf-count { color: var(--color-ink-faint); }
.pf-windows { position: absolute; inset: 0; pointer-events: none; }
.pf-win {
  position: absolute;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--pf-window, var(--color-white));
  box-shadow: 0 12px 36px -10px rgba(0, 0, 0, .3);
  cursor: grab;
  pointer-events: auto;
  will-change: transform;
}
.pf-win.is-dragging { cursor: grabbing; }
.pf-media {
  width: var(--pf-img-w, 160px);
  height: var(--pf-img-h, 160px);
  object-fit: cover;
  -webkit-user-drag: none;
  pointer-events: none;
}
.pf-hint {
  position: absolute;
  left: 50%;
  translate: -50% 0;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--text-meta);
  color: var(--color-ink-faint);
  opacity: 0;
  transition: opacity .4s ease;
  pointer-events: none;
}
/* Sem imagem ainda: a peça vira um retângulo tingido da proporção certa,
   com o nome dentro, para o layout ficar de pé antes das fotos. */
.pf-ph {
  display: grid;
  place-items: center;
  width: var(--w, 100%);
  height: var(--h, auto);
  aspect-ratio: var(--ar, 1);
  border-radius: 3px;
  background: color-mix(in srgb, var(--pf-color, var(--color-green)) 22%, var(--color-cream));
  color: color-mix(in srgb, var(--color-ink) 60%, transparent);
  font-size: 11px;
  line-height: 1.2;
  text-align: center;
  padding: 6px;
  overflow: hidden;
}
.pf-win .pf-ph { width: var(--pf-img-w, 100%); height: var(--pf-img-h, 100%); border-radius: 0; }
.pf-hint.is-on { opacity: 1; }
.pf-anchor.is-hidden { opacity: 0; }

/* No telefone não há espaço ao lado da pasta: as peças tomam o palco, a
   seção cresce para caber todas, e a pasta recua quando elas estão fora
   (um toque em qualquer lugar as devolve). O palco guarda uma altura
   mínima porque aqui a seção é auto: sem ela, um palco de altura zero não
   teria onde pôr nem a pasta. */
@media (max-width: 700px) {
  #visual { height: auto; min-height: 100svh; overflow-x: clip; }
  .prism-folder { height: auto; }
  .pf-stage { min-height: 62svh; }
  .pf-anchor { transition: opacity .3s ease; }
  .prism-folder.is-open .pf-anchor { opacity: 0; pointer-events: none; }
}

/* ─── Site footer ────────────────────────────────────────────────────────
   Uma assinatura, centrada, no verde do site: a frase, quatro tiles de
   ícone, e uma linha de assinatura sobre um fio. A laje tem cantos
   arredondados e sobe de baixo do quadro numa mola, uma vez, quando aparece.
   Os estados de entrada só existem sob .sf-armed, que o site-footer.js põe
   depois de conferir que movimento é bem-vindo, e tira quando terminou.
   Sem o script, ou com movimento reduzido, o footer nasce pronto. */
.site-footer {
  position: relative;
  overflow: hidden;
  background: var(--color-green);
  color: var(--color-cream);
  --sf-ease: cubic-bezier(.22, 1, .36, 1);
  --sf-gutter: 12px;
}
.sf-slab {
  position: relative;
  padding: clamp(56px, 9vh, 104px) var(--page-margin) clamp(36px, 6vh, 64px);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  background: var(--color-green);
}
.sf-inner {
  max-width: 900px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  container-type: inline-size;
}
.sf-head {
  font-family: var(--font-display);
  font-size: min(clamp(1.9rem, 4.4vw, 4.4rem), 100cqi / 16);
  line-height: 1.08;
  letter-spacing: -0.03em;
  font-weight: 400;
  text-wrap: balance;
}
.sf-em {
  position: relative;
  font-weight: 700;
  color: var(--color-coral-light);
}
.sf-icons {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  margin-top: clamp(32px, 5vw, 52px);
}
/* Um tile: um quadrado creme com um disco escuro e o glifo, o disco um pouco
   fora de um disco de acento atrás, que aparece no hover. */
.sf-icon {
  position: relative;
  display: inline-grid;
  place-items: center;
  width: 64px; height: 64px;
  padding: 0;
  border-radius: 16px;
  background: var(--color-cream);
  color: var(--color-cream);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5),
              0 8px 20px -8px rgba(0, 0, 0, .4);
  transition: transform .3s cubic-bezier(.34, 1.56, .64, 1), box-shadow .3s ease;
}
.sf-disc {
  position: relative;
  display: grid;
  place-items: center;
  width: 40px; height: 40px;
  border-radius: 999px;
  background: var(--color-charcoal);
  box-shadow: 2px 2px 0 var(--color-coral);
  transition: box-shadow .3s ease, background-color .3s ease;
}
.sf-glyph { grid-area: 1 / 1; display: inline-flex; transition: opacity .2s ease, transform .2s ease; }
.sf-glyph--done { color: var(--color-green); opacity: 0; transform: scale(.6); }
.sf-icon.is-copied .sf-glyph:not(.sf-glyph--done) { opacity: 0; transform: scale(.6); }
.sf-icon.is-copied .sf-glyph--done { opacity: 1; transform: none; }

.sf-icon:hover,
.sf-icon:focus-visible {
  transform: translateY(-4px);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5),
              0 16px 28px -10px rgba(0, 0, 0, .5);
}
.sf-icon:hover .sf-disc,
.sf-icon:focus-visible .sf-disc { box-shadow: 3px 3px 0 var(--color-coral); }
.sf-icon:active { transform: translateY(-1px) scale(.97); }

/* O rótulo: sobre o tile no hover, então os ícones ficam sem palavra em
   repouso. */
.sf-tip {
  position: absolute;
  bottom: calc(100% + 12px);
  left: 50%;
  translate: -50% 4px;
  padding: 5px 9px;
  border-radius: 6px;
  background: var(--color-charcoal);
  color: var(--color-cream);
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 400;
  line-height: 1.4;
  letter-spacing: 0;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity .2s ease, translate .2s ease;
}
.sf-icon:hover .sf-tip,
.sf-icon:focus-visible .sf-tip,
.sf-icon.is-copied .sf-tip { opacity: 1; translate: -50% 0; }
.sf-icon.is-copied .sf-tip { color: var(--color-green-light); }

/* A assinatura: a marca oficial e uma linha pequena sobre um fio, fechando
   a página. A marca herdou o creme do rodapé por currentColor. */
.sf-sign {
  align-self: stretch;
  margin: clamp(40px, 7vw, 72px) 0 0;
  padding-top: 22px;
  border-top: 1px solid color-mix(in srgb, var(--color-cream) 22%, transparent);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 18px 28px;
  font-size: var(--text-meta);
  line-height: 1.5;
  color: color-mix(in srgb, var(--color-cream) 62%, transparent);
}
/* A marca é desenhada para 1000x1000 com o desenho no miolo; o viewBox do
   SVG recorta essa área, então 132px de largura já dá um logo legível.
   `height` fixo e `width: auto` deixam a largura seguir a proporção do
   viewBox — é o que mantém o S redondo em vez de esticado. */
.sf-logo { height: 62px; width: auto; flex: 0 0 auto; color: var(--color-cream); }
.sf-sign-text { text-align: right; }
.sf-icon:focus-visible { outline: 2px solid var(--color-cream); outline-offset: 4px; }
.sf-live {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

/* Entrada: a laje sobe de baixo do quadro na mola, a frase desliza para
   fora da própria linha de base (máscara, não fade), depois os tiles um a
   um e a assinatura. Cada atraso é um --sf-d posto por elemento no
   site-footer.js. */
.sf-line {
  display: inline-block;
  vertical-align: top;
  padding-bottom: .16em;
  margin-bottom: -.16em;
}
.sf-line > span { display: inline-block; }
.sf-armed .sf-slab { transform: translateY(calc(100% + var(--sf-gutter))); }
.sf-armed .sf-line { overflow: hidden; }
.sf-armed .sf-line > span { transform: translateY(110%); }
.sf-armed .sf-icon,
.sf-armed .sf-sign { opacity: 0; transform: translateY(12px); }
.sf-armed.sf-in .sf-slab {
  transform: none;
  transition: transform var(--sf-rise-dur, 1.1s)
              var(--sf-rise-ease, cubic-bezier(.34, 1.3, .64, 1));
}
.sf-armed.sf-in .sf-line > span {
  transform: none;
  transition: transform 1s var(--sf-ease) var(--sf-d, 0ms);
}
.sf-armed.sf-in .sf-icon,
.sf-armed.sf-in .sf-sign {
  opacity: 1;
  transform: none;
  transition: opacity .6s ease var(--sf-d, 0ms),
              transform .9s var(--sf-ease) var(--sf-d, 0ms);
}
@media (prefers-reduced-motion: reduce) {
  .sf-icon, .sf-disc, .sf-glyph, .sf-tip { transition: none; }
  .sf-icon:hover, .sf-icon:focus-visible { transform: none; }
}
@media (max-width: 640px) {
  .sf-slab { padding: 48px 24px 28px; }
  .sf-head { white-space: normal; }
  .sf-icons { gap: 12px; }
}

/* ─── Peek ───────────────────────────────────────────────────────────────
   O ícone de currículo do footer abre aqui em vez de sair do site: uma
   janela flutua sobre a página, num scrim tingido e desfocado. Botões
   redondos ficam logo fora do canto superior direito dela: fechar e abrir
   em outra aba.
   Um <dialog> aberto com showModal(), pelo foco preso, pelo Esc e pela
   página inerte atrás. O ::backdrop dele não é usado: o scrim é um elemento
   de verdade para poder ser clicado e animado junto com a janela. O
   movimento vive no site-footer.js. */
.peek {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  max-height: none;
  margin: 0;
  padding: 0;
  border: none;
  background: transparent;
  overflow: hidden;
}
.peek[open] { display: grid; place-items: center; }
.peek::backdrop { background: transparent; }
.peek-scrim {
  position: absolute;
  inset: 0;
  background: color-mix(in srgb, var(--color-charcoal) 56%, transparent);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.peek-frame { position: relative; transform-origin: 50% 50%; }
.peek-window {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius);
  background: var(--color-white);
  color: var(--color-ink);
  box-shadow: 0 2px 4px rgba(0, 0, 0, .1), 0 32px 80px -16px rgba(0, 0, 0, .48);
}
.peek--doc .peek-window {
  width: min(1024px, 100vw - 160px);
  height: calc(100dvh - 48px);
}
.peek-doc { display: block; width: 100%; height: 100%; border: 0; }
.peek-actions {
  position: absolute;
  top: 0;
  left: calc(100% + 12px);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.peek-btn {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border-radius: 999px;
  background: var(--color-charcoal);
  color: var(--color-cream);
  box-shadow: 0 6px 16px -6px rgba(0, 0, 0, .5);
  transition: background-color .2s ease, transform .15s ease;
}
.peek-btn:hover { background: color-mix(in srgb, var(--color-cream) 14%, var(--color-charcoal)); }
.peek-btn:active { transform: scale(.92); }
.peek-btn:focus-visible { outline: 2px solid var(--color-cream); outline-offset: 3px; }
@media (max-width: 760px) {
  .peek--doc .peek-window { width: 100vw; height: 100dvh; border-radius: 0; }
  .peek-actions { top: 10px; left: auto; right: 10px; flex-direction: row; }
}

/* ─── Case overlay ────────────────────────────────────────────────────── */
/* A caixa do .case-overlay está junto à do .more-overlay, acima. Aqui fica
   só o que é do case. */
/* Um case: uma imagem de topo, título e corpo à esquerda, números à
   direita. O conteúdo vem de project.case em content.js. */
/* Hero: o pôster de mockups já vem recortado no conteúdo (sem a sobra
   preta do artboard) e com o fundo convertido para branco. Por isso ele
   encosta no branco do painel sem moldura nem barra de cor. */
.case-hero {
  width: 100%;
  background: #fff;
}
/* O pôster é quase quadrado (1800×1993) e mostra uma composição de
   notebooks e celulares. `cover` numa faixa larga cortaria dispositivos
   inteiros, então a imagem aparece inteira: largura livre, limitada por
   `max-height` e centralizada. Assim nada é esticado nem cortado, e a
   proporção é sempre a do arquivo. */
.case-hero img {
  display: block;
  width: auto;
  max-width: min(100%, 760px);
  height: auto;
  max-height: 58vh;
  margin: 0 auto;
  object-fit: contain;
}

/* ─── Grade de telas do case ──────────────────────────────────────────── */
/* Grade, não fita. A fita horizontal cortava a última tela na borda e
   pedia arraste sem indicar que havia mais — quem não arrastasse nunca via
   as telas finais. A grade mostra todas de uma vez e quebra sozinha em
   menos colunas no telefone. Cada tela é um botão que amplia. */
.case-screens {
  width: min(100% - 2 * var(--page-margin), 1180px);
  margin: 0 auto;
  padding: clamp(32px, 5vh, 64px) 0 0;
}
.case-screens-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: clamp(16px, 2.2vw, 28px);
  list-style: none;
  margin: 0;
  padding: 0;
}
.case-screen { min-width: 0; }
.case-screen-btn {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: zoom-in;
  border-radius: 16px;
  transition: transform .25s ease, box-shadow .25s ease;
}
/* A proporção vem da imagem (540×1200), não de um aspect-ratio fixo: assim
   nenhuma tela é esticada nem cortada. */
.case-screen img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 16px;
  background: #f6f6f6;
  box-shadow: 0 1px 2px rgba(20, 20, 20, .06), 0 8px 24px -14px rgba(20, 20, 20, .28);
}
.case-screen-btn:hover img {
  box-shadow: 0 2px 4px rgba(20, 20, 20, .08), 0 16px 36px -16px rgba(20, 20, 20, .34);
}
.case-screen-btn:hover { transform: translateY(-2px); }
.case-screen-btn:focus-visible {
  outline: 2px solid var(--color-green);
  outline-offset: 4px;
}
/* Legenda curta e visível: na grade a tela não tem o contexto da fita, e
   sem uma linha embaixo ela não se identifica sozinha. */
.case-screen-cap {
  margin: 10px 2px 0;
  font-size: var(--text-meta);
  line-height: 1.4;
  color: var(--color-ink-faint);
  text-wrap: pretty;
}
.case-screens-caption {
  margin: clamp(20px, 3vw, 28px) 0 0;
  font-family: var(--font-display);
  font-size: clamp(12px, 1.1vw, 14px);
  letter-spacing: .04em;
  color: color-mix(in srgb, var(--color-ink) 58%, transparent);
}
@media (prefers-reduced-motion: reduce) {
  .case-screen-btn { transition: none; }
  .case-screen-btn:hover { transform: none; }
}

/* ─── Índice do case ──────────────────────────────────────────────────── */
/* Âncoras para as seções. Fica numa faixa própria entre a grade de telas e
   o texto: dentro do texto competiria com o título do case. */
.case-toc {
  width: min(100% - 2 * var(--page-margin), 1180px);
  margin: 0 auto;
  padding: clamp(24px, 3vw, 40px) 0 0;
  border-top: 1px solid rgba(20, 20, 20, .1);
}
.case-toc-list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 10px;
  list-style: none;
  margin: 0;
  padding: 0;
}
.case-toc-link {
  display: inline-block;
  padding: 6px 12px;
  border-radius: var(--radius-round);
  font-size: var(--text-meta);
  color: var(--color-ink-soft);
  background: #f4f4f4;
  text-decoration: none;
  transition: background-color .2s ease, color .2s ease;
}
.case-toc-link:hover { background: var(--color-ink); color: #fff; }
.case-toc-link:focus-visible {
  outline: 2px solid var(--color-green);
  outline-offset: 2px;
}

/* ─── Abertura do case ────────────────────────────────────────────────── */
/* Em telas largas o pôster fica ao lado do título: sozinho e centralizado,
   uma imagem quase quadrada deixa duas faixas brancas mortas dos lados e
   come a primeira dobra inteira. A partir daqui é texto de leitura, e a
   medida fica em torno de 60 caracteres por linha. */
.case-lead {
  width: min(100% - 2 * var(--page-margin), 820px);
  margin: 0 auto;
  padding: clamp(32px, 5vh, 64px) 0 0;
}
@media (min-width: 1000px) {
  .case-lead--split {
    width: min(100% - 2 * var(--page-margin), 1180px);
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(320px, 440px);
    gap: clamp(32px, 4vw, 64px);
    align-items: center;
  }
  .case-lead--split .case-hero { order: 2; }
  .case-lead-text { min-width: 0; }
}
.case-main {
  width: min(100% - 2 * var(--page-margin), 1180px);
  margin: 0 auto;
  padding: clamp(40px, 6vh, 72px) 0 clamp(96px, 14vh, 180px);
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(240px, 300px);
  gap: clamp(32px, 5vw, 72px);
  align-items: start;
}
.case-title {
  font-family: var(--font-display);
  font-size: clamp(2rem, 4.4vw, 4rem);
  line-height: 1.08;
  letter-spacing: -0.03em;
  font-weight: 400;
  text-wrap: balance;
  margin-bottom: clamp(20px, 3vw, 32px);
}
.case-body p,
.case-summary,
.case-section p {
  font-size: var(--text-body);
  line-height: 1.5;
  width: 100%;
  max-width: 100%;
  color: var(--color-ink-soft);
}
.case-body p + p { margin-top: 1em; }
.case-summary {
  font-size: clamp(1.15rem, 1.5vw, 1.45rem);
  line-height: 1.45;
  color: var(--color-ink);
  margin-bottom: clamp(24px, 3vw, 36px);
  text-wrap: pretty;
}

/* Ficha do projeto: função, período, equipe, tipo de entrega. Duas colunas
   no desktop, empilhada no telefone. */
.case-facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 16px 24px;
  margin: 0 0 clamp(32px, 4vw, 48px);
  padding: 20px 0;
  border-top: 1px solid color-mix(in srgb, var(--color-ink) 16%, transparent);
  border-bottom: 1px solid color-mix(in srgb, var(--color-ink) 16%, transparent);
}
.case-facts dt {
  font-size: var(--text-meta);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--color-ink-faint);
  margin-bottom: 4px;
}
.case-facts dd { margin: 0; font-size: .95rem; color: var(--color-ink); }

/* Seções do case: cada uma com um título que funciona como cabeçalho de
   leitura. O espaçamento entre elas é o que separa os blocos da narrativa. */
.case-section + .case-section { margin-top: clamp(32px, 4vw, 48px); }
.case-section-title {
  font-family: var(--font-ui);
  font-size: var(--text-meta);
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--color-green);
  margin-bottom: 12px;
}
.case-section p + p { margin-top: .9em; }
.case-list {
  margin: 12px 0 0;
  padding-left: 1.1em;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.case-list li {
  font-size: clamp(.98rem, 1.15vw, 1.15rem);
  line-height: 1.55;
  color: var(--color-ink-soft);
}
.case-list li::marker { color: var(--color-green); }

/* Requisitos e etapas. Os cards são propriedades simultâneas do produto;
   as etapas são uma sequência. Por isso um é <ul> e o outro <ol>, e por
   isso só as etapas levam número. */
.case-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 12px;
  list-style: none;
  margin: 16px 0 0;
  padding: 0;
}
.case-card {
  padding: clamp(18px, 2vw, 24px);
  border-radius: var(--radius-lg);
  background: var(--color-paper);
  border: 0;
  box-shadow: var(--card-shadow);
}
.case-card-title {
  font-family: var(--font-ui);
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--color-ink);
  margin-bottom: 6px;
}
.case-card-body {
  margin: 0;
  font-size: .95rem;
  line-height: 1.5;
  color: var(--color-ink-soft);
}
.case-steps {
  display: flex;
  flex-direction: column;
  gap: 18px;
  list-style: none;
  counter-reset: step;
  margin: 16px 0 0;
  padding: 0;
}
.case-step {
  counter-increment: step;
  position: relative;
  padding-left: 44px;
}
.case-step::before {
  content: counter(step);
  position: absolute;
  left: 0; top: 0;
  width: 28px; height: 28px;
  display: grid; place-items: center;
  border-radius: var(--radius-round);
  background: var(--color-ink);
  color: #fff;
  font-family: var(--font-ui);
  font-size: .8rem;
  font-weight: 600;
}
.case-step-title {
  font-family: var(--font-ui);
  font-size: 1rem;
  font-weight: 600;
  color: var(--color-ink);
  margin-bottom: 4px;
}
.case-step-body {
  margin: 0;
  font-size: .95rem;
  line-height: 1.55;
  color: var(--color-ink-soft);
}

/* ─── Lightbox ────────────────────────────────────────────────────────── */
/* <dialog> próprio, por cima do case: fecha no Escape e prende o foco sem
   precisar de código, e como trava o documento, a página atrás não rola
   junto. */
.case-lightbox {
  position: fixed;
  inset: 0;
  width: 100%; max-width: none;
  height: 100%; max-height: none;
  margin: 0;
  padding: clamp(16px, 4vw, 48px);
  border: 0;
  background: transparent;
  opacity: 0;
  transition: opacity .25s ease;
  overflow: auto;
}
.case-lightbox[open] { display: grid; place-items: center; }
.case-lightbox.visible { opacity: 1; }
.case-lightbox::backdrop { background: rgba(16, 16, 18, .82); }
.case-lightbox-figure {
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  max-width: min(92vw, 460px);
}
.case-lightbox-img {
  display: block;
  width: 100%;
  height: auto;
  max-height: 82vh;
  object-fit: contain;
  border-radius: 18px;
  background: #f6f6f6;
  box-shadow: 0 24px 60px -20px rgba(0, 0, 0, .6);
}
.case-lightbox-cap {
  font-size: var(--text-meta);
  line-height: 1.4;
  color: rgba(255, 255, 255, .86);
  text-align: center;
  text-wrap: pretty;
}
.case-lightbox-close {
  position: fixed;
  top: 16px; right: 16px;
  width: 48px; height: 48px;
  display: grid; place-items: center;
  border-radius: var(--radius-round);
  background: rgba(255, 255, 255, .94);
  color: var(--color-ink);
  z-index: 1;
}
.case-lightbox-close:hover { background: #fff; }
.case-lightbox-close:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 3px;
}
@media (prefers-reduced-motion: reduce) {
  .case-lightbox { transition: none; }
}

/* ─── Fita de telas dentro de uma seção ───────────────────────────────── */
/* A narrativa cita telas específicas: o fluxo de cadastro, os avisos de
   erro. Elas entram aqui, menores que a faixa do topo, com legenda visível
   — dentro do texto a tela precisa se explicar sozinha, porque não há
   contexto de "produto inteiro" como no hero. */
/* `min-width: 0` impede que a grade de telas estique a coluna do grid: sem
   ele, a largura mínima da grade vira a largura mínima da coluna inteira e
   o texto ao lado transborda. */
.case-strip { margin-top: 20px; min-width: 0; }
.case-strip-track {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  gap: 14px;
  list-style: none;
  margin: 0;
  padding: 0;
}
.case-strip-item { min-width: 0; }
.case-strip-item img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 10px;
  background: #f6f6f6;
  box-shadow: 0 1px 2px rgba(20, 20, 20, .06), 0 6px 18px -12px rgba(20, 20, 20, .3);
}
.case-strip-item figcaption {
  margin-top: 8px;
  font-size: calc(var(--text-meta) * .92);
  line-height: 1.35;
  color: var(--color-ink-faint);
  text-wrap: pretty;
}

.case-metrics { display: flex; flex-direction: column; gap: 20px; }
.case-metrics-title {
  font-family: var(--font-ui);
  font-size: var(--text-meta);
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--color-ink-faint);
  margin-bottom: 4px;
}
/* A fonte de cada número fica visível: um resultado sem procedência não
   deve parecer tão sólido quanto um medido. */
.case-metric-source {
  font-size: calc(var(--text-meta) * .92);
  color: var(--color-ink-faint);
  line-height: 1.4;
}
.case-metric {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding-top: 16px;
  border-top: 1px solid color-mix(in srgb, var(--color-ink) 18%, transparent);
}
.case-metric-number {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(1.8rem, 2.6vw, 2.6rem);
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--color-green);
}
.case-metric-label {
  font-size: var(--text-meta);
  color: var(--color-ink-faint);
}
@media (max-width: 900px) {
  /* `minmax(0, 1fr)`, e não `1fr`: uma coluna `1fr` tem largura mínima
     automática, então qualquer conteúdo largo dentro dela (uma grade de
     telas, uma tabela) empurra a coluna para além do painel e a página
     inteira passa a rolar de lado. */
  .case-main { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 640px) {
  /* Duas colunas no telefone: uma tela por linha ficaria com 300px de
     largura e viraria um corredor de rolagem sem fim. */
  .case-screens-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .case-screens { padding-top: clamp(24px, 4vh, 40px); }
  .case-lead { padding-top: clamp(24px, 4vh, 40px); }
  .case-hero img { max-height: 48vh; }
}
@media (max-width: 340px) {
  .case-screens-grid { grid-template-columns: minmax(0, 1fr); }
}

/* ─── Site loader ────────────────────────────────────────────────────────
   Escondido, a menos que o script no <head> tenha posto .has-loader no
   <html>. Sendo display: none até lá, o overlay aparece desde o primeiro
   frame ou nunca aparece — não existe um frame de página nua antes dele. */
.site-loader { display: none; }
html.has-loader { overflow: hidden; }
html.has-loader .site-loader {
  display: block;
  position: fixed;
  inset: 0;
  z-index: 1000;
  overflow: hidden;
  pointer-events: none;
}
.sl-bg {
  position: absolute;
  inset: 0;
  background: var(--color-ink);
}
.sl-content {
  position: relative;
  width: 100%; height: 100%;
  display: grid;
  place-items: center;
}
.sl-marks { position: absolute; inset: 28px; }
.sl-marks i {
  position: absolute;
  width: 18px; height: 18px;
  border: 1.5px solid color-mix(in srgb, var(--color-cream) 55%, transparent);
}
.sl-marks i:nth-child(1) { left: 0; top: 0; border-right: 0; border-bottom: 0; }
.sl-marks i:nth-child(2) { right: 0; top: 0; border-left: 0; border-bottom: 0; }
.sl-marks i:nth-child(3) { left: 0; bottom: 0; border-right: 0; border-top: 0; }
.sl-marks i:nth-child(4) { right: 0; bottom: 0; border-left: 0; border-top: 0; }

.sl-words {
  position: absolute;
  font-family: var(--font-accent);
  font-weight: 300;
  font-size: clamp(1.8rem, 3.6vw, 3.4rem);
  color: var(--color-cream);
  white-space: nowrap;
}
.sl-words span { display: none; }

.sl-name {
  position: absolute;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(2.4rem, 7vw, 6rem);
  line-height: 0.95;
  letter-spacing: -0.04em;
  text-align: center;
  color: var(--color-cream);
  opacity: 0;
}

.sl-tiles { position: absolute; inset: 0; }
.sl-tile {
  position: absolute;
  aspect-ratio: 3 / 4;
  width: 14vw;
  border-radius: 8px;
  opacity: 0;
  background: color-mix(in srgb, var(--color-charcoal) calc(100% - var(--tile-depth, 0) * 45%), var(--color-ink));
  box-shadow: 0 16px 40px -14px rgba(0, 0, 0, .6);
  overflow: hidden;
}
.sl-tile--photo img { width: 100%; height: 100%; object-fit: cover; }

/* O tile que voa para o hero já nasce na proporção do card do hero (280/400).
   Antes ele usava 3/4 (0,75) e o card é 0,70: como o voo termina exatamente
   sobre o card, essa diferença de 7% aparecia como uma esticada durante a
   transição. Igualando a proporção na origem, o card é o mesmo do primeiro
   ao último quadro e não há o que deformar. */
.sl-tile--photo { aspect-ratio: 280 / 400; }
.sl-tile-title {
  position: absolute;
  left: 50%; bottom: 8%;
  translate: -50% 0;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(14px, 1.6vw, 22px);
  letter-spacing: 0.06em;
  white-space: nowrap;
  color: var(--color-cream);
  text-shadow: 0 4px 16px rgba(0, 0, 0, .4);
}

/* ─── Utilitários ─────────────────────────────────────────────────────── */
.no-scroll { overflow: hidden; }

@media (min-width: 641px) {
  :root {
    --text-hero: clamp(2.5rem, 4.4vw, 4rem);
    --text-display: clamp(2.5rem, 4.4vw, 4rem);
  }
}

@media (max-width: 700px) {
  :root { --page-margin: 6vw; }
  .section { padding-block: 96px 64px; }
  .section-title { max-width: 100%; }
  .contact-row-text { font-size: clamp(1.5rem, 6vw, 2.4rem); }
  .cursor-label { display: none; }
}

/* ─── Movimento reduzido: regra geral ───────────────────────────────────
   Os blocos acima desligam animações pontuais. Este aqui fecha o resto:
   qualquer transição de posição, escala ou opacidade longa passa a ser
   instantânea, e o que sobra é só a mudança de cor/estado, que não desloca
   nada. Isso importa em especial para os painéis (.more-overlay,
   .case-overlay), cujo fade de 350ms some sem que a abertura deixe de ser
   indicada — o painel continua aparecendo, e o foco continua indo para
   dentro dele.

   Não use `transition: none` em tudo: o foco visível precisa do seu estado
   final imediatamente, e é isso que acontece quando a duração é zero. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}


