/* ============================================================
   Vision — site público
   Depende de tokens.css (variáveis de marca, fontes, escala).
   Prefixo .v-* para todo componente, como no UI kit do design system.
   ============================================================ */

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

html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--vision-black);
  color: var(--vision-paper);
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

a { color: inherit; text-decoration: none; }
img, svg { max-width: 100%; }
button { font: inherit; }

/* A home inteira é uma superfície escura: fixa os tons de texto do tema dark
   sem depender do atributo [data-theme], que ainda não temos no site. */
.v-page {
  min-height: 100vh;
  --fg-1: #F5F4F7;
  --fg-2: #C8C8D2;
  --fg-3: #8A8A95;
}

.v-container {
  width: 100%;
  max-width: 1280px;
  margin: 0 auto;
  padding: 0 32px;
}

/* Acessibilidade -------------------------------------------------------- */

.v-skip-link {
  position: absolute;
  left: 16px;
  top: -100px;
  z-index: 100;
  padding: 12px 20px;
  border-radius: var(--radius-pill);
  background: var(--vision-purple);
  color: var(--vision-black);
  font-weight: var(--fw-semibold);
  transition: top var(--dur-2) var(--ease-standard);
}
.v-skip-link:focus { top: 16px; }

:where(a, button, [tabindex]):focus-visible {
  outline: 2px solid var(--vision-purple);
  outline-offset: 3px;
  border-radius: var(--radius-xs);
}

.v-visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ============================= NAV ============================= */

.v-nav {
  position: sticky;
  top: 0;
  z-index: 50;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 24px;
  padding: 18px 32px;
  background: rgba(10, 10, 10, 0.6);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}

.v-nav__brand {
  justify-self: start;
  display: inline-flex;
  align-items: center;
  /* Logotipo branco: o SVG é inline com fill="currentColor", então a cor vem
     daqui. Os arquivos "-white" do design system não servem por si só — são
     idênticos aos "-black" e não declaram fill (renderizam preto). */
  color: var(--vision-white);
}
.v-nav__brand svg { height: 26px; width: auto; display: block; }

.v-nav__links {
  justify-self: center;
  display: flex;
  align-items: center;
  gap: 28px;
  font-size: 14px;
  font-weight: var(--fw-medium);
}
.v-nav__link {
  position: relative;
  color: var(--fg-2);
  padding: 4px 0;
  transition: color var(--dur-2) var(--ease-standard);
}
.v-nav__link:hover { color: var(--vision-white); }
.v-nav__link[aria-current="true"] { color: var(--vision-white); }
.v-nav__link[aria-current="true"]::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -6px;
  height: 1.5px;
  background: var(--vision-purple);
}

.v-nav__actions { justify-self: end; display: flex; align-items: center; gap: 14px; }

/* Alternador de idioma — usa a view set_language do Django, então é um form. */
.v-lang { display: flex; align-items: center; gap: 2px; }
.v-lang__btn {
  padding: 6px 8px;
  border-radius: var(--radius-sm);
  font-size: 13px;
  font-weight: var(--fw-semibold);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--fg-3);
  transition: color var(--dur-2) var(--ease-standard);
}
.v-lang__btn:hover { color: var(--vision-white); }
.v-lang__btn[aria-current="true"] { color: var(--vision-purple); }
.v-lang__sep { color: var(--fg-4); font-size: 12px; }

.v-nav__toggle {
  display: none;
  background: none;
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: var(--radius-sm);
  color: var(--vision-paper);
  padding: 8px;
  cursor: pointer;
  line-height: 0;
}

/* ============================= BOTÕES ============================= */

.v-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 14px 24px;
  border: none;
  border-radius: var(--radius-pill);
  font-family: var(--font-sans);
  font-size: var(--fs-body-sm);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-button);
  white-space: nowrap;   /* rótulo de 2+ palavras não pode quebrar: a pílula vira círculo */
  cursor: pointer;
  transition: background var(--dur-2) var(--ease-standard),
              color var(--dur-2) var(--ease-standard),
              border-color var(--dur-2) var(--ease-standard),
              transform var(--dur-2) var(--ease-standard);
}
.v-btn--sm { padding: 10px 18px; font-size: 14px; }

.v-btn--accent { background: var(--vision-purple); color: var(--vision-black); }
.v-btn--accent:hover { background: var(--vision-white); transform: translateY(-1px); }
.v-btn--accent:active { background: var(--vision-purple-strong); color: var(--vision-white); }

.v-btn--ghost {
  background: transparent;
  color: var(--vision-paper);
  border: 1px solid rgba(255, 255, 255, 0.2);
}
.v-btn--ghost:hover { border-color: var(--vision-purple); color: var(--vision-purple); }
.v-btn--ghost:active { border-color: var(--vision-purple-strong); color: var(--vision-purple-strong); }

.v-btn--dark { background: var(--vision-black); color: var(--vision-white); }

/* Contorno em gradiente sobre fundo transparente.
   `border` não aceita gradiente e `border-image` ignora border-radius (a pílula
   viraria retângulo). Por isso a borda é um pseudo-elemento preenchido com o
   gradiente e mascarado para mostrar só o anel — o miolo fica de fato
   transparente e o glow do hero aparece através dele. */
.v-btn--gradient {
  position: relative;
  background: transparent;
  color: var(--vision-paper);
}
.v-btn--gradient::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1.5px;          /* espessura da borda */
  background: linear-gradient(
    115deg,
    var(--vision-purple-strong) 0%,
    var(--vision-purple) 45%,
    var(--vision-purple-light) 100%
  );
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  pointer-events: none;
}
.v-btn--gradient:hover { background: rgba(169, 147, 255, 0.12); color: var(--vision-white); }
.v-btn--gradient:active { background: rgba(169, 147, 255, 0.22); }

/* Ponto de radar: o círculo sólido mais dois anéis que se expandem. Os anéis
   ficam defasados em meio ciclo, o que dá a leitura de varredura contínua em
   vez de piscada. */
.v-pulse {
  position: relative;
  display: inline-block;
  width: 7px;
  height: 7px;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--vision-purple);
}
.v-pulse::before,
.v-pulse::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 1.5px solid var(--vision-purple);
  box-shadow: 0 0 6px rgba(169, 147, 255, 0.45);
  animation: v-radar 2.4s var(--ease-out) infinite;
}
.v-pulse::after { animation-delay: 1.2s; }

@keyframes v-radar {
  /* Sem parada intermediária de opacidade: o esmaecimento acompanha toda a
     expansão, senão o anel some antes de chegar na borda e a varredura
     praticamente não é percebida. */
  from { transform: scale(1);   opacity: 0.9; }
  to   { transform: scale(3.6); opacity: 0; }
}

.v-btn--dark:hover { background: var(--vision-white); color: var(--vision-black); transform: translateY(-1px); }

.v-icon { width: 16px; height: 16px; stroke-width: 1.5; flex-shrink: 0; }

/* ============================= HERO ============================= */

.v-hero {
  position: relative;
  padding: 88px 0 120px;
  overflow: hidden;
  /* Medida da coluna de abertura: cerca de 60% da tela. O limite em px segura
     a linha em telas largas, onde o container já parou de crescer. Vive aqui
     porque o título e a linha fina abaixo dele têm de andar juntos. */
  --v-hero-measure: min(60vw, 760px);
}
.v-hero__inner { position: relative; z-index: 2; }

.v-hero__glow,
.v-hero__glow-2 {
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
  z-index: 1;
}
.v-hero__glow {
  right: -120px; top: -40px;
  width: 560px; height: 560px;
  background: radial-gradient(circle at 30% 30%, var(--vision-purple) 0%, var(--vision-purple-strong) 35%, transparent 70%);
  filter: blur(40px);
  opacity: 0.7;
  animation: v-breathe 12s var(--ease-standard) infinite;
}
.v-hero__glow-2 {
  left: -100px; bottom: -150px;
  width: 380px; height: 380px;
  background: radial-gradient(circle, var(--vision-purple-strong) 0%, transparent 70%);
  filter: blur(50px);
  opacity: 0.5;
  animation: v-breathe 9s var(--ease-standard) infinite reverse;
}

@keyframes v-breathe {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
  50%      { transform: translate3d(0, -18px, 0) scale(1.06); }
}

.v-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: var(--fs-eyebrow);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--vision-purple);
  margin: 0 0 24px;
}
.v-eyebrow::before { content: "|"; }

.v-hero__title {
  font-family: var(--font-display);
  font-size: clamp(44px, 6.4vw, 92px);
  font-weight: var(--fw-bold);
  line-height: 1.02;
  letter-spacing: -0.035em;
  margin: 0 0 28px;
  max-width: var(--v-hero-measure);
}
.v-hero__title em { font-style: italic; font-weight: var(--fw-regular); color: var(--vision-purple); }

/* Fecha o título e abre o texto de apoio, na mesma medida da coluna. */
.v-hero__rule {
  width: var(--v-hero-measure);
  max-width: 100%;
  height: 1px;
  background: rgba(255, 255, 255, 0.28);
  margin: 0 0 28px;
}

.v-hero__sub {
  font-size: clamp(17px, 2vw, 19px);
  line-height: var(--lh-body);
  color: var(--fg-2);
  max-width: 52ch;
  margin: 0 0 36px;
}
/* Mesma fonte e mesmo tamanho do restante do subtexto; o destaque vem da cor,
   do negrito e do itálico (sintetizado, já que a Darker Grotesque não tem face
   itálica própria). */
.v-hero__sub em {
  font-style: italic;
  font-weight: 700;
  color: var(--vision-purple);
}

.v-hero__ctas { display: flex; flex-wrap: wrap; gap: 12px; }

.v-hero__stats {
  display: grid;
  /* Colunas do tamanho do conteúdo, e não em fração do container: assim os três
     ficam agrupados no meio da tela, em vez de esticados até as bordas. */
  grid-template-columns: repeat(3, auto);
  justify-content: center;
  gap: 24px clamp(56px, 11vw, 168px);
  margin-top: 80px;
  padding-top: 32px;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}
.v-stat { display: flex; flex-direction: column; align-items: center; gap: 6px; text-align: center; }
.v-stat__value {
  /* Origem do confete do contador de cafés. */
  position: relative;
  font-family: var(--font-display);
  font-size: 36px;
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-heading);
  line-height: 1;
}
.v-stat__value em { font-style: italic; font-weight: var(--fw-regular); color: var(--vision-purple); }
/* Último dígito do número que segue subindo: entra de baixo, com a mesma
   máscara e o mesmo quadro-chave das palavras do título, para a troca não ser
   um corte seco. Mais curto que o título, porque se repete a cada passo. */
.v-digit {
  display: inline-block;
  clip-path: inset(-0.3em -0.12em 0 -0.12em);
  margin-bottom: -0.16em;
}
.v-digit__inner {
  display: inline-block;
  padding-bottom: 0.16em;
  transform: translateY(120%);
  animation: v-word-up 340ms var(--ease-out) forwards;
}

/* Confete: pedaços criados pelo JavaScript ao contador de cafés bater em 1000,
   espalhados em leque a partir do centro do número e removidos no fim. Cada um
   traz a própria direção, giro e cor em variáveis inline. */
.v-confetti {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 5px;
  height: 9px;
  border-radius: 1px;
  background: var(--cor);
  pointer-events: none;
  opacity: 0;
  /* 900ms é o mesmo valor de CONFETE_DURACAO no site.js, que agenda a
     remoção dos pedaços — mexer aqui pede mexer lá. */
  animation: v-confetti 900ms var(--ease-out) var(--atraso) forwards;
}

@keyframes v-confetti {
  0%   { opacity: 1; transform: translate3d(-50%, -50%, 0) rotate(0deg); }
  60%  { opacity: 1; }
  100% {
    opacity: 0;
    transform: translate3d(calc(-50% + var(--dx)), calc(-50% + var(--dy)), 0) rotate(var(--rot));
  }
}

.v-stat__label {
  font-size: var(--fs-eyebrow);
  font-weight: var(--fw-medium);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--fg-3);
}

/* ============================= SEÇÕES ============================= */

.v-section { padding: 100px 0; }
.v-section__head { max-width: 900px; margin-bottom: 64px; }
.v-section__eyebrow {
  font-size: var(--fs-eyebrow);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--section-accent, var(--vision-purple));
  margin: 0 0 18px;
}
.v-section__title {
  font-family: var(--font-display);
  font-size: clamp(36px, 5vw, 72px);
  font-weight: var(--fw-bold);
  line-height: 1;
  letter-spacing: var(--ls-display);
  margin: 0 0 18px;
}
.v-section__title em { font-style: italic; font-weight: var(--fw-regular); color: var(--section-accent, var(--vision-purple)); }
.v-section__sub {
  font-size: var(--fs-h5);
  line-height: var(--lh-body);
  color: var(--fg-2);
  max-width: 60ch;
  margin: 0;
}

/* Superfície escura própria da seção — daí os tons de texto, as bordas e o
   realce virem redeclarados aqui, e não herdados da página.

   `--section-bg` e `--section-accent` existem para os componentes que vivem nas
   duas superfícies: o realce é o roxo claro no escuro e o forte no claro (o
   claro não tem contraste sobre papel), e quem precisa da cor do fundo — a aba
   selecionada, que inverte — lê daqui em vez de fixar preto ou branco. Assim
   virar uma seção de lado é trocar a classe, e não caçar cor por cor. */
.v-section--dark {
  --section-bg: var(--vision-black);
  --section-accent: var(--vision-purple);
  background: var(--section-bg);
  color: var(--vision-paper);
  --fg-1: #F5F4F7;
  --fg-2: #C8C8D2;
  --fg-3: #8A8A95;
  --fg-4: #5C5C66;
  /* Bordas e realces do tema escuro: os do `:root` são pretos translúcidos e
     sumiriam sobre o preto da seção. */
  --border-1: rgba(255, 255, 255, 0.08);
  --border-2: rgba(255, 255, 255, 0.16);
  --surface-overlay: rgba(255, 255, 255, 0.05);
}

/* ============================= NOSSO DNA ============================= */

/* Duas colunas de peso igual: texto à esquerda, card à direita. `start` no
   alinhamento para o card não esticar até a altura do texto. */
.v-dna {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 64px;
  align-items: start;
}

/* Dentro da coluna a abertura não precisa do respiro de uma seção inteira, e a
   largura máxima de 900px é maior que a própria coluna. */
.v-dna__text .v-section__head { max-width: none; margin-bottom: 40px; }

.v-dna__eyebrow {
  font-size: var(--fs-eyebrow);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  /* Mais apagado que o olho da seção — são dois olhos na mesma tela e só o de
     cima é o roxo da marca. */
  color: var(--fg-3);
  margin: 0 0 16px;
}

.v-dna__lead {
  font-family: var(--font-display);
  font-size: clamp(26px, 2.8vw, 40px);
  font-weight: var(--fw-bold);
  line-height: 1.1;
  letter-spacing: var(--ls-heading);
  margin: 0 0 28px;
  max-width: 22ch;
}
.v-dna__lead em { font-style: italic; font-weight: var(--fw-regular); color: var(--vision-purple); }

.v-dna__body {
  font-size: var(--fs-body-lg);
  line-height: var(--lh-body);
  color: var(--fg-2);
  max-width: 52ch;
}
.v-dna__body p { margin: 0 0 20px; }
.v-dna__body p:last-child { margin-bottom: 0; }

/* A linha solta do meio é a virada do texto: ganha respiro e a barra roxa. */
.v-dna__accent {
  padding-left: 20px;
  border-left: 2px solid var(--vision-purple);
  margin: 28px 0;
}
.v-dna__accent em {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: var(--fw-regular);
  font-size: var(--fs-h4);
  line-height: 1.25;
  color: var(--vision-paper);
}

/* Card em retrato: cabeçalho, linha divisória e corpo empilhados. Sem padding
   no card — quem espaça são o cabeçalho e o corpo, para a linha entre os dois
   correr de ponta a ponta. */
.v-profile-card {
  display: flex;
  flex-direction: column;
  background: var(--vision-ink);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: var(--radius-lg);
  overflow: hidden;
}

.v-profile-card__head {
  padding: 24px 28px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.12);
}

/* Perfil resumido, abrindo o corpo do card: avatar à esquerda, nome e @ à
   direita dele. */
.v-profile-card__profile { display: flex; align-items: center; gap: 12px; }

.v-profile-card__avatar {
  flex: none;
  display: grid;
  place-items: center;
  width: 44px; height: 44px;
  border-radius: 50%;
  background: var(--vision-white);
  color: var(--vision-black);   /* o logotipo é inline e herda a cor daqui */
}
.v-profile-card__avatar svg { width: 24px; height: 24px; display: block; }

.v-profile-card__id { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.v-profile-card__name {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: var(--fs-body-sm);
  font-weight: var(--fw-bold);
  line-height: 1.2;
  color: var(--vision-paper);
}
/* Azul do selo do Instagram, não da paleta Vision: é a citação de uma marca. */
.v-profile-card__badge { width: 15px; height: 15px; color: #3897F0; flex: none; }
.v-profile-card__handle {
  font-size: var(--fs-body-sm);
  line-height: 1.2;
  color: var(--fg-3);
}

.v-profile-card__phrase {
  margin: 0 0 0 auto;   /* auto à esquerda: a frase encosta na direita */
  text-align: right;
  /* Uma linha só, no mesmo corpo do texto da coluna da esquerda. */
  white-space: nowrap;
  font-family: var(--font-sans);
  font-weight: var(--fw-regular);
  font-size: var(--fs-body-lg);
  line-height: 1.3;
  color: var(--fg-2);
}

/* Logotipo completo em branco, a 40% da largura do card e encostado à esquerda
   — a proporção do SVG (318.88 x 66) cuida da altura sozinha. */
.v-profile-card__logo {
  margin-top: 32px;
  color: var(--vision-white);
}
.v-profile-card__logo svg { display: block; width: 40%; height: auto; }

.v-profile-card__body {
  flex: 1;
  display: flex;
  flex-direction: column;
  padding: 28px;
}

.v-profile-card__spacer { flex: 1; min-height: 96px; }

/* Rodapé: a linha de cima é a mesma do cabeçalho — como o card não tem padding
   próprio, ela corre de ponta a ponta. */
.v-profile-card__foot {
  display: flex;
  justify-content: flex-end;
  padding: 20px 28px;
  border-top: 1px solid rgba(255, 255, 255, 0.12);
  color: var(--vision-white);
}
.v-profile-card__foot svg { display: block; width: 96px; height: auto; }

.v-profile-card__text {
  margin-top: 28px;
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--fg-2);
}
.v-profile-card__text p { margin: 0 0 16px; }
.v-profile-card__text p:last-child { margin-bottom: 0; }
/* Exceção ao destaque serifado em itálico usado no resto do site: dentro do
   card o realce é a própria fonte do texto, em negrito. */
.v-profile-card__text em {
  font-family: inherit;
  font-style: normal;
  font-weight: var(--fw-bold);
  color: var(--vision-purple);
}

/* Superfície clara. `.v-page` fixa os tons do tema escuro para a página toda,
   então a seção precisa devolver os do tema claro — inclusive o roxo, que na
   versão clara da marca é o forte: o roxo claro não tem contraste sobre papel. */
.v-section--light {
  --section-bg: var(--vision-paper);
  --section-accent: var(--vision-purple-strong);
  background: var(--section-bg);
  color: var(--vision-ink);
  --fg-1: var(--vision-ink);
  --fg-2: var(--vision-graphite);
  --fg-3: var(--vision-slate);
  --fg-4: var(--vision-mist);
}

/* ============================= SERVIÇOS ============================= */

/* Abertura em duas colunas: intro à esquerda, abas à direita, alinhadas pela
   base do título. O subtexto vem abaixo das duas, na largura da esquerda. */
.v-services__head {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: end;
  gap: 32px;
  margin-bottom: 18px;
}
.v-services__intro .v-section__title { margin-bottom: 0; }
.v-services__sub { margin-bottom: 64px; }

/* ------------------------------- ABAS ------------------------------- */

.v-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: flex-end;
}
.v-tabs__tab {
  padding: 10px 18px;
  border: 1px solid var(--border-2);
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--fg-2);
  font-size: 14px;
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-button);
  white-space: nowrap;
  cursor: pointer;
  transition: background var(--dur-2) var(--ease-standard),
              color var(--dur-2) var(--ease-standard),
              border-color var(--dur-2) var(--ease-standard);
}
.v-tabs__tab:hover { border-color: var(--section-accent); color: var(--section-accent); }
/* A aba escolhida inverte a seção: pinta-se com a cor do texto e escreve com a
   cor do fundo. Fixar o preto aqui só funcionava enquanto a seção era clara —
   sobre o escuro a pastilha sumiria dentro do próprio fundo. */
.v-tabs__tab[aria-selected="true"] {
  background: var(--fg-1);
  border-color: var(--fg-1);
  color: var(--section-bg);
}

/* ---------------------- CONTEÚDO DE CADA ABA ---------------------- */

/* Título do serviço, abrindo o painel da aba. Antes vinha sobreposto a uma
   foto de largura cheia; a foto saiu e o título passou a valer sozinho, então
   nada aqui precisa de posicionamento — é um heading comum, com a margem que
   antes pertencia ao cartão da foto. */
.v-service-title {
  display: flex;
  align-items: center;
  gap: clamp(16px, 2vw, 28px);
  margin: 0 0 48px;
  font-family: var(--font-display);
  /* Fluido em vez de um degrau no celular: o piso é o tamanho que a regra de
     768px fixava antes, então nada encolheu na tela estreita. */
  font-size: clamp(28px, 3.5vw, 48px);
  font-weight: var(--fw-bold);
  line-height: 1.1;
  color: var(--vision-white);
}
/* Um item de flex só, para o nome não se partir no `gap`. O `min-width` deixa
   ele encolher e quebrar linha na tela estreita, em vez de empurrar a faixa. */
.v-service-title__text { min-width: 0; }

/* Mesmo destaque das headlines da seção, em `.v-section__title em`: itálico,
   peso normal e o roxo da seção. Quem escolhe a palavra é o filtro
   `accent_last_word`, depois da tradução. */
.v-service-title em {
  font-style: italic;
  font-weight: var(--fw-regular);
  color: var(--section-accent, var(--vision-purple));
}

/* A linha é pseudo-elemento porque é ornamento, não conteúdo: não entra na
   marcação e leitor de tela não anuncia. `flex: 1` faz ela ocupar tudo que
   sobra, então termina na borda do container seja qual for o comprimento do
   nome do serviço. A cor vem de `--section-accent` — a seção é escura e o
   token já resolve para o roxo claro; se um dia virar clara, acompanha. */
.v-service-title::after {
  content: "";
  flex: 1;
  min-width: 40px;
  height: 1px;
  background: var(--section-accent, var(--vision-purple));
}

/* De 4 a 6 informações: duas colunas acomodam bem os dois extremos.
   A margem negativa compensa o padding dos itens: a superfície do hover avança
   para fora, mas número e texto seguem alinhados com o resto da seção. */
.v-service-info {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 24px;
  list-style: none;
  margin: 0 -24px;
  padding: 0;
}
/* Número à esquerda, o resto à direita. */
.v-service-info__item {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 28px;
  /* O número acompanha o topo do card, e não a meia-altura do texto: como as
     etapas têm descrições de comprimentos diferentes, centralizar deixava cada
     numeral numa altura, e a coluna da esquerda perdia a linha de base comum. */
  align-items: start;
  padding: 20px 24px;
  border-radius: var(--radius-md);
  transition: background var(--dur-2) var(--ease-standard);
}
/* Fundo levemente mais escuro no hover. `--surface-overlay` é o preto a 4% do
   tema claro — o mesmo realce discreto que o design system usa. */
.v-service-info__item:hover { background: var(--surface-overlay); }

.v-service-info__num {
  font-family: var(--font-sans);
  font-weight: var(--fw-black);
  font-size: var(--fs-display-2);
  line-height: 1;
  /* O roxo que a seção define: o forte sobre papel, o claro sobre preto. */
  color: var(--section-accent);
  margin: 0;
}

.v-service-info__eyebrow {
  font-size: var(--fs-eyebrow);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--fg-3);
  margin: 0 0 6px;
}
.v-service-info__title {
  font-size: var(--fs-h2);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-heading);
  margin: 0 0 10px;
}
.v-service-info__desc {
  font-size: var(--fs-body-lg);
  line-height: var(--lh-body);
  color: var(--fg-2);
  margin: 0;
  max-width: 46ch;
}
/* Chamada da aba Soluções Personalizadas, no lugar da lista de etapas.

   Centrada, e não alinhada à esquerda como a lista que ela substitui: a lista
   ocupa duas colunas e ancora o olho na margem esquerda, enquanto aqui há um
   texto só — encostado à esquerda ele deixaria metade da faixa vazia. O fundo
   é o mesmo realce do hover das etapas, o preto a 4%, para o bloco ler como
   parte do painel e não como um card de outra seção. */
.v-service-callout {
  display: grid;
  justify-items: center;
  text-align: center;
  gap: 14px;
  padding: 56px 40px;
  border-radius: var(--radius-lg);
  background: var(--surface-overlay);
}
/* A ordem visual inverte a do documento: o subtítulo é o rótulo da divisão e
   vem acima do título, mas no HTML o título vem primeiro para o <h4> abrir o
   bloco — o leitor de tela anuncia o cabeçalho antes do rótulo que o qualifica. */
.v-service-callout__sub {
  order: -1;
  font-size: var(--fs-eyebrow);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--section-accent);
  margin: 0;
}
.v-service-callout__title {
  font-size: var(--fs-h2);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-heading);
  margin: 0;
  max-width: 20ch;
}
.v-service-callout__text {
  font-size: var(--fs-body-lg);
  line-height: var(--lh-body);
  color: var(--fg-2);
  margin: 0;
  max-width: 52ch;
}
.v-service-callout__cta { margin-top: 10px; }

/* O painel recebe foco pelo teclado, mas não é um controle: o anel do :focus
   padrão poluiria a área inteira. O contorno só aparece na navegação por teclado
   fora de um clique — que é o que :focus-visible já resolve. */
.v-tabs__panel:focus { outline: none; }

/* Sem script os painéis viram uma lista corrida; quem identifica cada um é o
   título em `.v-service-title`. */
.no-js .v-tabs__panels { display: grid; gap: 40px; }


.v-services {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1px;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
.v-service {
  display: flex;
  flex-direction: column;
  gap: 14px;
  min-height: 280px;
  padding: 36px 32px;
  background: var(--vision-black);
  transition: background var(--dur-2) var(--ease-standard);
}
.v-service:hover { background: var(--vision-ink); }
.v-service__icon {
  display: grid;
  place-items: center;
  width: 48px; height: 48px;
  border-radius: var(--radius-md);
  background: var(--vision-purple);
  color: var(--vision-black);
}
.v-service__icon svg { width: 24px; height: 24px; stroke-width: 1.5; }
.v-service__num {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  color: var(--fg-3);
}
.v-service__title {
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  font-weight: var(--fw-bold);
  line-height: 1.1;
  letter-spacing: var(--ls-heading);
  margin: 4px 0;
}
.v-service__title em { font-style: italic; font-weight: var(--fw-regular); }
.v-service__desc {
  font-size: 14px;
  line-height: var(--lh-body);
  color: var(--fg-2);
  margin: 0;
}

/* ------------------------- CARROSSEL DA ABA ------------------------- */

/* A faixa anda para a esquerda a largura de uma lista inteira e recomeça. Para
   a emenda ser invisível, a largura de uma lista tem de ser exatamente metade
   da faixa: por isso o espaço entre os cartões é `margin-right` no item, e não
   `gap` — assim o último cartão carrega o próprio intervalo e as duas listas
   ficam idênticas. Com `gap`, o intervalo entre as listas contaria só uma vez e
   o ciclo saltaria meio espaço a cada volta. */
.v-marquee {
  margin-top: 60px;
  /* O recorte da faixa acontece na borda do padding, então esta folga é o que
     permite o card crescer no hover sem ter o topo e a base cortados. */
  padding: 12px 0;
  overflow: hidden;
}
.v-marquee__track {
  display: flex;
  width: max-content;
  /* Sem pausa: nada aqui interrompe o ciclo — nem hover, nem foco. Quem não
     quer movimento é atendido pelo bloco de `prefers-reduced-motion`. */
  animation: v-marquee-scroll 60s linear infinite;
  animation-play-state: running;
}
.v-marquee__group { display: flex; list-style: none; margin: 0; padding: 0; }
.v-marquee__item { margin-right: 20px; }

.v-marquee__media {
  position: relative;   /* os fundos `.bg-*` posicionam pseudo-elementos */
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  width: clamp(170px, 20vw, 240px);
  aspect-ratio: 9 / 16;
  /* Cobre o intervalo entre o card aparecer e o pôster pintar. Os `.bg-*` vêm
     depois no arquivo, então quem tem fundo abstrato continua com o dele. */
  background: var(--vision-black);
  padding: 14px;
  border-radius: var(--radius-md);
  transition: transform var(--dur-2) var(--ease-standard),
              box-shadow var(--dur-2) var(--ease-standard);
}
/* Preenche o card inteiro, atrás da cortina do `::after` e das legendas — a
   ordem de pintura vem do DOM (pseudo-elemento depois do conteúdo), então não
   precisa de `z-index` para ninguém. `object-fit` recorta o 9:16 do arquivo no
   9:16 do card sem esticar. */
.v-marquee__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* O contorno é `box-shadow`, e não `border`: anel não entra no cálculo da
   caixa, então o card não muda de tamanho nem desalinha a faixa — e ele
   acompanha o arredondamento sozinho. */
.v-marquee__media:hover {
  transform: scale(1.05);
  box-shadow: 0 0 0 2px var(--section-accent);
}
/* Escurece só as pontas, onde o texto fica: os fundos do design system vão do
   quase preto ao lilás claro, e sem isto a legenda some sobre os claros. Os
   `.bg-*` já usam `::before`, então a cortina vai no `::after`. */
.v-marquee__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg,
              rgba(10, 10, 10, 0.55) 0%, transparent 35%,
              transparent 65%, rgba(10, 10, 10, 0.55) 100%);
}
.v-marquee__name,
.v-marquee__place {
  position: relative;   /* acima da cortina */
  z-index: 1;
  margin: 0;
  color: var(--vision-white);
  line-height: 1.25;
}
.v-marquee__name {
  font-size: var(--fs-body-sm);
  font-weight: var(--fw-semibold);
}
.v-marquee__place {
  align-self: flex-end;
  text-align: right;
  font-size: var(--fs-caption);
  color: rgba(255, 255, 255, 0.75);
}

/* Dentro da aba o carrossel abre o painel, logo abaixo do título: o respiro de
   cima já é a margem do título, e o de baixo é que separa das etapas. Escopado
   no painel para não mexer na faixa de logotipos, que usa a mesma base. */
.v-tabs__panel .v-marquee {
  margin-top: 0;
  margin-bottom: 56px;
}

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

/* ---------------------- RESUMO NO PÉ DA ABA ---------------------- */

/* Três tópicos de largura igual, ocupando a página toda. Caixa alta e nada em
   negrito: o realce dos rótulos é só a cor. */
.v-service-meta {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  margin: 40px 0 0;
  font-size: var(--fs-body-sm);
  font-weight: var(--fw-regular);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--fg-3);
}

/* A divisão entre tópicos é a borda da própria coluna, não um caractere: ela
   acompanha a altura da faixa, inclusive quando um tópico quebra em duas
   linhas e os outros não. */
.v-service-meta__pair {
  font-weight: var(--fw-regular);
  padding-right: 24px;
  text-align: center;
}
.v-service-meta__pair + .v-service-meta__pair {
  padding-left: 24px;
  border-left: 1px solid var(--border-2);
}
.v-service-meta__pair:last-child { padding-right: 0; }

/* O roxo da seção: em corpo pequeno é o contraste que decide, e nenhum dos dois
   roxos serve nas duas superfícies. */
.v-service-meta__label { color: var(--section-accent); }

/* ============================== CASES ============================== */

/* Duas linhas de quatro. */
.v-cases {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 18px;
}

/* O card é claro como a seção: branco sobre o papel, que é o que separa um do
   outro sem precisar de sombra. Os tons de texto são os da seção — quem escurece
   é só a peça do hover, que cobre o card inteiro e leva os próprios tons. */
.v-case {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  aspect-ratio: 4 / 3;
  padding: 20px;
  background: var(--vision-white);
  border: 1px solid var(--vision-cloud);
  border-radius: var(--radius-lg);
}

.v-case__head { display: flex; flex-direction: column; gap: 2px; }
.v-case__name {
  font-size: var(--fs-body-sm);
  font-weight: var(--fw-semibold);
  line-height: 1.2;
  color: var(--fg-1);
  margin: 0;
}
.v-case__place {
  font-size: var(--fs-caption);
  line-height: 1.2;
  color: var(--fg-3);
  margin: 0;
}

/* O logotipo ocupa o que sobra e fica no centro dos dois eixos. */
.v-case__logo { flex: 1; display: grid; place-items: center; min-height: 0; }

/* A imagem não ocupa a área toda: o recuo deixa o logotipo respirar entre o
   cabeçalho e a borda de baixo do card. O `contain` decide o resto — os
   arquivos vêm todos em 5:3, mas com margens internas diferentes e um lockup
   vertical no meio, então é a proporção de cada arte que manda no tamanho
   aparente; esticar qualquer uma para igualar seria deformar marca de cliente. */
.v-case__logo img {
  width: 78%;
  height: 78%;
  object-fit: contain;
}

/* A peça cobre o card inteiro no hover. `position: relative` também porque os
   fundos `.bg-*` posicionam pseudo-elementos. */
.v-case__cover {
  position: absolute;
  inset: 0;
  padding: 20px;
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--dur-3) var(--ease-standard),
              visibility var(--dur-3) var(--ease-standard);
}
.v-case:hover .v-case__cover,
.v-case:focus-within .v-case__cover { opacity: 1; visibility: visible; }

/* O nome fica acima da peça e do gradiente que a escurece no topo. */
.v-case__cover-name {
  position: relative;
  z-index: 1;
  margin: 0;
  font-size: var(--fs-body-sm);
  font-weight: var(--fw-bold);
  line-height: 1.2;
  color: var(--vision-white);
}
/* Os `.bg-*` já usam `::before`; a cortina do topo vai no `::after`. */
.v-case__cover::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(10, 10, 10, 0.6), transparent 40%);
}

/* Faixa de logotipos: mesma mecânica do carrossel das abas, outro conteúdo.
   A duração é menor porque a lista é mais estreita — o que se quer igual entre
   as duas faixas é a velocidade, não o tempo da volta. */

/* Vive fora do `.v-container`, então ocupa a largura inteira da tela. A linha
   de cima é o que separa os cards dos logotipos. */
.v-logo-strip {
  margin-top: 72px;
  border-top: 1px solid var(--border-2);
}

/* A faixa já fecha a seção com o respiro dela, então o rodapé de 100px da
   seção cairia por cima e abriria um vão grande demais até a seção seguinte.
   Quem tem faixa fecha mais curto — e é a presença dela que decide, não o id
   de Cases: a próxima seção que ganhar uma faixa herda o mesmo fecho. */
.v-section:has(.v-logo-strip) { padding-bottom: 24px; }
/* Mais apagado que o olho da seção, e sem as barras: são dois olhos na mesma
   tela e só o de cima é o roxo da marca — mesma regra do Nosso DNA. */
.v-logo-strip__eyebrow {
  margin: 0;
  padding-top: 32px;
  font-size: var(--fs-eyebrow);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--fg-3);
}
.v-marquee--logos { margin-top: 0; padding: 24px 0 32px; }
.v-marquee--logos .v-marquee__track { animation-duration: 45s; }
.v-marquee--logos .v-marquee__item { margin-right: 18px; }

/* Sem moldura: a caixa com borda era o desenho do marcador, e logotipo de
   cliente numa faixa não se emoldura — o que separa um do outro é o espaço.
   A caixa continua de tamanho fixo para todos, e o `contain` acomoda cada arte
   dentro dela, do lockup deitado ao quadrado. */
.v-logo-mark {
  display: block;
  width: 132px;
  height: 74px;
  object-fit: contain;
}

/* ======================== FUNDOS ABSTRATOS ======================== */

/* Visual de marca (spec §9), não imagem provisória. Usados hoje pelos cards
   de Cases e pelos carrosséis dos serviços. */
.bg-purple-haze { background: radial-gradient(circle at 30% 30%, var(--vision-purple) 0%, var(--vision-purple-strong) 50%, var(--vision-ink) 100%); }
.bg-bw-glow { background: radial-gradient(ellipse at 70% 30%, rgba(169, 147, 255, 0.5), transparent 60%), linear-gradient(140deg, var(--vision-black), var(--vision-graphite)); }
.bg-stripe { background: var(--vision-purple-haze); }
.bg-stripe::before {
  content: "";
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(60deg, rgba(169, 147, 255, 0.4) 0 3px, transparent 3px 18px);
}
.bg-conic { background: var(--vision-black); }
.bg-conic::before {
  content: "";
  position: absolute;
  inset: 20%;
  border-radius: 50%;
  background: conic-gradient(from 90deg at 50% 50%, var(--vision-purple), var(--vision-purple-strong), var(--vision-purple-haze), var(--vision-purple));
  filter: blur(20px);
}
.bg-grid {
  background-color: var(--vision-ink);
  background-image: linear-gradient(rgba(169, 147, 255, 0.18) 1px, transparent 1px),
                    linear-gradient(90deg, rgba(169, 147, 255, 0.18) 1px, transparent 1px);
  background-size: 32px 32px;
}
.bg-grid::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse at 30% 50%, rgba(169, 147, 255, 0.4), transparent 60%);
}

/* Cards claros precisam inverter o texto e o véu de escurecimento. */
/* ============================= FEEDBACKS ============================= */

/* Três colunas em duas linhas. Sem proporção fixa, ao contrário dos Cases: o
   card acompanha o comprimento do depoimento. A linha inteira fica na altura do
   card mais alto (o `stretch` padrão da grade) e o rodapé desce para a base. */
.v-feedbacks {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 18px;
}

/* Card padrão da spec (§7): papel branco sobre o fundo claro da seção, borda
   fina, sombra leve em repouso e a subida de 4px no hover. */
.v-feedback {
  display: flex;
  flex-direction: column;
  margin: 0;
  padding: 28px;
  background: var(--vision-white);
  border: 1px solid var(--border-1);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-2);
  transition: box-shadow var(--dur-2) var(--ease-standard),
              transform var(--dur-2) var(--ease-standard);
}
.v-feedback:hover { box-shadow: var(--shadow-3); transform: translateY(-4px); }

/* A aspa ocupa só uma faixa estreita no alto da caixa do glifo: em The Seasons
   itálico negrito o desenho tem 0,211em de altura e começa 0,481em acima do
   meio da entrelinha. Daí os dois números — `line-height: 0.962` faz o topo da
   caixa cair exatamente no topo do desenho, e a margem negativa devolve o vão
   que sobra embaixo, para o card medir a aspa pelo desenho (~44px) e não pela
   caixa (~200px). Com a margem zerando o vão, a distância até o depoimento é o
   `margin-top` do próprio texto. O recuo à esquerda é da mesma família: o
   glifo tem 0,194em de espaço em branco antes do desenho, e sem descontá-lo a
   aspa nasceria adiantada em relação ao texto. Mudou a fonte, remedir com
   `measureText()` e os campos `actualBoundingBox*`. */
.v-feedback__mark {
  margin: 0 0 -0.751em -0.194em;
  font-family: var(--font-display);
  font-style: italic;
  font-weight: var(--fw-bold);
  font-size: 210px;
  line-height: 0.962;
  color: var(--vision-purple-strong);
}

.v-feedback__text {
  margin: 20px 0 24px;
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--fg-2);
}

/* `margin-top: auto` cola o rodapé na base: com depoimentos de comprimentos
   diferentes, os rodapés de uma mesma linha ficam alinhados entre si. Dentro
   dele, quem falou à esquerda e a nota à direita, centradas uma na outra. */
.v-feedback__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-top: auto;
  padding-top: 20px;
  border-top: 1px solid var(--border-1);
}
/* `min-width: 0` para o nome e o ramo poderem quebrar em vez de empurrar as
   estrelas para fora do card nas colunas mais estreitas. */
.v-feedback__who { min-width: 0; }
.v-feedback__stars {
  display: flex;
  gap: 3px;
  flex-shrink: 0;
  margin: 0;
  color: var(--vision-purple-strong);
}
.v-feedback__star { width: 16px; height: 16px; }
.v-feedback__name {
  margin: 0;
  font-size: var(--fs-body-sm);
  font-weight: var(--fw-bold);
  line-height: 1.3;
  color: var(--fg-1);
}
.v-feedback__meta {
  margin: 2px 0 0;
  font-size: var(--fs-caption);
  line-height: 1.4;
  color: var(--fg-3);
}

/* ============================= DEPOIMENTO ============================= */

.v-quote {
  position: relative;
  overflow: hidden;
  margin: 0;
  padding: 80px 64px;
  border-radius: var(--radius-xl);
  background: var(--vision-paper);
  color: var(--vision-ink);
}
.v-quote::before {
  content: "\201D";
  position: absolute;
  top: 30px; right: 60px;
  font-family: var(--font-display);
  font-style: italic;
  font-size: 220px;
  line-height: 0.8;
  color: var(--vision-purple);
  opacity: 0.8;
}
.v-quote__text {
  position: relative;
  z-index: 1;
  font-family: var(--font-sans);
  font-weight: var(--fw-medium);
  font-size: clamp(24px, 3.4vw, 36px);
  line-height: 1.35;
  letter-spacing: -0.01em;
  max-width: 720px;
  margin: 0 0 32px;
}
.v-quote__author { position: relative; z-index: 1; display: flex; align-items: center; gap: 14px; }
.v-quote__avatar {
  display: grid;
  place-items: center;
  width: 48px; height: 48px;
  border-radius: var(--radius-pill);
  background: var(--vision-purple);
  color: var(--vision-black);
  font-family: var(--font-display);
  font-size: var(--fs-h5);
  font-weight: var(--fw-bold);
}
.v-quote__name { font-size: var(--fs-body-sm); font-weight: var(--fw-semibold); }
.v-quote__role { font-size: var(--fs-caption); color: var(--vision-slate); }

/* ============================= FAQ ============================= */

/* Lista corrida separada por linhas, sem card: são onze itens, e onze caixas
   empilhadas pesariam mais que o conteúdo. A borda de baixo do último fecha o
   bloco. */
.v-faq {
  list-style: none;
  /* Mesma medida do `.v-section__head`: a lista corrida na largura inteira
     jogaria a seta a meia tela de distância da pergunta. */
  max-width: 900px;
  margin: 0;
  padding: 0;
  border-top: 1px solid rgba(255, 255, 255, 0.12);
}
.v-faq__item { border-bottom: 1px solid rgba(255, 255, 255, 0.12); }

/* O `h3` existe pela semântica; o peso e o tamanho vêm do botão. */
.v-faq__heading { margin: 0; font: inherit; }

/* Linha inteira clicável: número, pergunta e seta em uma grade de três
   colunas, com a pergunta ocupando o que sobra. */
.v-faq__question {
  display: grid;
  /* A coluna do índice é fixa em vez de `auto` porque cada item é uma grade
     própria: com `auto`, o 10 e o 11 seriam mais largos que os de um dígito e
     empurrariam só as suas perguntas para a direita. */
  grid-template-columns: 2ch 1fr auto;
  align-items: baseline;
  gap: 20px;
  width: 100%;
  padding: 26px 0;
  border: 0;
  background: none;
  color: inherit;
  text-align: left;
  cursor: pointer;
}

/* Índice em peso normal e no roxo da marca — o contraponto da pergunta, que é
   o negrito ao lado. */
.v-faq__num {
  font-size: var(--fs-body);
  font-weight: var(--fw-regular);
  font-variant-numeric: tabular-nums;
  color: var(--vision-purple);
}

.v-faq__label {
  font-size: var(--fs-h4);
  font-weight: var(--fw-bold);
  line-height: 1.25;
  letter-spacing: var(--ls-heading);
  color: var(--fg-1);
  transition: color var(--dur-2) var(--ease-standard);
}
.v-faq__question:hover .v-faq__label { color: var(--vision-purple); }

/* A seta gira meia volta quando a resposta abre. `align-self: center` porque a
   grade alinha pela linha de base do texto, e um ícone não tem uma. */
.v-faq__chevron {
  width: 20px;
  height: 20px;
  align-self: center;
  color: var(--fg-3);
  transition: transform var(--dur-3) var(--ease-standard),
              color var(--dur-2) var(--ease-standard);
}
.v-faq__question[aria-expanded="true"] .v-faq__chevron { transform: rotate(180deg); }
.v-faq__question:hover .v-faq__chevron { color: var(--vision-purple); }

/* A altura da resposta anima de `0fr` a `1fr` porque `height: auto` não é
   animável: a grade de uma linha só resolve a altura do conteúdo sozinha, e a
   fração interpola. O recorte fica no filho — é ele que tem altura fixa
   durante a transição. */
.v-faq__answer {
  display: grid;
  grid-template-rows: 1fr;
  transition: grid-template-rows var(--dur-3) var(--ease-standard);
}
.v-faq__answer-inner {
  overflow: hidden;
  /* `visibility` troca de valor de uma vez, no fim da transição ao fechar e no
     começo ao abrir: é o que tira a resposta fechada do leitor de tela e da
     busca da página sem cortar a animação pela metade. */
  transition: visibility var(--dur-3);
}

/* Estado fechado. O `aria-expanded` do botão é a única fonte da verdade — o
   JavaScript não guarda estado em classe nenhuma. */
.v-faq__item:has(.v-faq__question[aria-expanded="false"]) .v-faq__answer {
  grid-template-rows: 0fr;
}
.v-faq__item:has(.v-faq__question[aria-expanded="false"]) .v-faq__answer-inner {
  visibility: hidden;
}

/* O recuo alinha a resposta com a pergunta, e não com o número: 20px do gap da
   grade mais a largura de dois dígitos. */
.v-faq__text {
  margin: 0;
  padding: 0 40px 28px calc(20px + 2ch);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--fg-2);
  max-width: 68ch;
}

/* ============================= CTA ============================= */

/* Coluna única e centrada: título, texto e botões empilhados nessa ordem.

   O degradê abre no lilás quase branco e fecha no roxo mais fundo. O limite
   do lado escuro é o `--vision-purple-bright`: o texto do card é preto, e ali
   ele ainda dá 5,3:1 de contraste — acima dos 4,5:1 que a WCAG AA pede para
   texto normal. Descer até o `--vision-purple-strong` cairia para 3,0:1 e
   obrigaria a virar o texto para branco, então a amplitude foi ganha
   clareando o topo, não escurecendo a base. A claridade do canto é uma
   segunda camada, radial, sobre a diagonal — mesma ideia do `.bg-bw-glow`. */
.v-cta {
  display: grid;
  justify-items: center;
  text-align: center;
  gap: 26px;
  padding: 80px 64px;
  border-radius: var(--radius-xl);
  background:
    radial-gradient(110% 130% at 12% 0%, var(--vision-purple-soft) 0%, transparent 58%),
    linear-gradient(135deg, var(--vision-purple-light) 0%, var(--vision-purple) 42%, var(--vision-purple-bright) 100%);
  color: var(--vision-black);
}
.v-cta__title {
  font-family: var(--font-display);
  font-size: clamp(36px, 5vw, 72px);
  font-weight: var(--fw-bold);
  line-height: 0.98;
  letter-spacing: var(--ls-display);
  margin: 0;
  /* Sem limite a manchete centrada abre até a borda do card e vira uma linha
     larga demais para ler de uma vez. */
  max-width: 16ch;
}
.v-cta__title em { font-style: italic; font-weight: var(--fw-regular); }
.v-cta__sub {
  font-size: var(--fs-body);
  line-height: 1.5;
  margin: 0;
  max-width: 52ch;
}
/* Os três canais na mesma linha, centrados, quebrando quando o card aperta. */
.v-cta__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
  margin-top: 6px;
}

/* Faixa que fecha o card. Itens do tamanho do conteúdo, e não colunas iguais
   como no `.v-service-meta`: aqui a linha é centrada, e colunas iguais
   deixariam vãos desiguais entre os textos e as barras. */
.v-cta__meta {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  margin: 10px 0 0;
  font-size: var(--fs-caption);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  /* Preto aliviado: a faixa fecha o card, não disputa com os botões. */
  color: rgba(10, 10, 10, 0.66);
}
/* A barra entre os tópicos é a borda da coluna, não um caractere — assim ela
   acompanha a altura da faixa se um tópico quebrar em duas linhas. */
.v-cta__meta-pair { padding: 0 18px; }
.v-cta__meta-pair + .v-cta__meta-pair { border-left: 1px solid rgba(10, 10, 10, 0.28); }
.v-cta__meta-pair:first-child { padding-left: 0; }
.v-cta__meta-pair:last-child { padding-right: 0; }
/* O rótulo é a parte com destaque; o valor é que fica aliviado. */
.v-cta__meta-label { font-weight: var(--fw-bold); color: var(--vision-black); }

/* ============================= RODAPÉ ============================= */

.v-footer {
  margin-top: 100px;
  padding: 60px 0 40px;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}
/* Marca à esquerda, os três canais em uma linha à direita. */
.v-footer__top {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 24px 40px;
  padding-bottom: 40px;
}
.v-footer__brand { color: var(--vision-white); }
.v-footer__brand svg { height: 40px; width: auto; display: block; }

.v-footer__links {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 28px;
  margin: 0;
  padding: 0;
}
/* `inline-block` para o `::before` de baixo poder ser um bloco dentro do link:
   é ele que fixa a largura. */
.v-footer__link {
  display: inline-block;
  color: var(--fg-2);
  font-size: 14px;
  transition: color var(--dur-2) var(--ease-standard);
}
/* Cópia invisível do rótulo já em negrito, de altura zero: ela dita a largura
   do link, então engrossar no hover não alarga nada e a linha não treme. Fora
   da árvore de acessibilidade por causa do `visibility: hidden`. */
.v-footer__link::before {
  content: attr(data-label);
  display: block;
  height: 0;
  overflow: hidden;
  visibility: hidden;
  font-weight: var(--fw-bold);
  pointer-events: none;
}
.v-footer__link:hover,
.v-footer__link:focus-visible {
  color: var(--vision-purple);
  font-weight: var(--fw-bold);
}
.v-footer__bottom {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  justify-content: space-between;
  padding-top: 20px;
  border-top: 1px solid rgba(255, 255, 255, 0.06);
  font-size: var(--fs-eyebrow);
  color: var(--fg-3);
  align-items: center;
}
/* Fica junto ao aviso de direitos, à esquerda; a assinatura segue à direita.
   Herda tamanho e cor da faixa: é texto do rodapé, não um botão. Sem hover, a
   pedido — o sublinhado é o que sobra para dizer que dá para clicar. */
.v-footer__legal {
  margin-right: auto;
  margin-left: 20px;
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* ===================== ENTRADA PALAVRA A PALAVRA ===================== */

/* Marcação vinda do filtro `word_reveal` (apps/website/templatetags/text.py).
   Cada palavra é uma janela mascarada embaixo e sobe de dentro dela, uma de
   cada vez — o atraso vem do índice `--i` que o filtro escreve em cada
   elemento. Tudo em CSS: roda na primeira pintura e não depende do script. */

.v-words {
  --v-word-dur: 720ms;
  --v-word-step: 90ms;
}

.v-word {
  display: inline-block;
  /* A máscara é `clip-path`, não `overflow`: um inline-block com overflow
     diferente de `visible` passa a ter como linha de base a própria borda de
     baixo, o que subiria as palavras e desalinharia o cursor ao lado delas.
     Aberta em cima e nos lados — o corte que importa é o de baixo, por onde a
     palavra entra —, para não aparar acentos nem a inclinação do itálico. */
  clip-path: inset(-0.3em -0.12em 0 -0.12em);
  /* Cancela o respiro de baixo do miolo, que senão afastaria as linhas. */
  margin-bottom: -0.16em;
}

.v-word__inner {
  display: inline-block;
  /* Respiro para que descendentes (o "q" de "que") fiquem acima do corte. */
  padding-bottom: 0.16em;
  transform: translateY(120%);
  animation: v-word-up var(--v-word-dur) var(--ease-out) forwards;
  animation-delay: calc(var(--i) * var(--v-word-step));
}

@keyframes v-word-up {
  to { transform: translateY(0); }
}

/* Cursor de inserção: entra depois da última palavra e fica piscando, como um
   campo de texto esperando a próxima letra. */
.v-caret {
  display: inline-block;
  width: 0.055em;
  min-width: 2px;
  height: 0.78em;
  margin-left: 0.1em;
  vertical-align: -0.04em;
  background: var(--vision-white);
  opacity: 0;
  animation: v-caret-blink 1.06s steps(1, end) infinite;
  /* O índice do cursor é o seguinte ao da última palavra; somar a duração faz
     ele esperar ela terminar de subir. Durante o atraso vale a opacidade 0
     acima — a animação não tem fill-mode, então não pisca antes da hora. */
  animation-delay: calc(var(--i) * var(--v-word-step) + var(--v-word-dur));
}

@keyframes v-caret-blink {
  0%, 49%   { opacity: 1; }
  50%, 100% { opacity: 0; }
}

/* ============================= REVEAL ============================= */

.v-reveal {
  opacity: 0;
  transform: translateY(12px);
  transition: opacity var(--dur-3) var(--ease-standard),
              transform var(--dur-3) var(--ease-standard);
}
.v-reveal.is-visible { opacity: 1; transform: none; }

/* Sem JS o conteúdo não pode ficar invisível. */
.no-js .v-reveal { opacity: 1; transform: none; transition: none; }

/* ==================== ÁRVORE DE LINKS (/minella/) ==================== */

/* Coluna estreita e centrada, sem cabeçalho nem rodapé: a página é aberta a
   partir da bio de uma rede social, quase sempre no celular, e tudo o que ela
   oferece cabe numa rolagem curta. O preto vem do `body`, que já é preto — aqui
   só entram os realces do tema escuro, porque os do `:root` são pretos
   translúcidos e sumiriam sobre ele. */
.v-tree {
  --border-2: rgba(255, 255, 255, 0.16);
  --surface-overlay: rgba(255, 255, 255, 0.05);
  --surface-overlay-strong: rgba(255, 255, 255, 0.10);
  display: grid;
  justify-items: center;
  gap: 26px;
  width: 100%;
  max-width: 560px;
  margin: 0 auto;
  padding: 64px 20px 88px;
  text-align: center;
}

.v-tree__head {
  display: grid;
  justify-items: center;
  gap: 18px;
}

/* O retrato é redondo e o arquivo pode não ser: `object-fit` recorta ao centro
   em vez de espremer o rosto na moldura. */
.v-tree__photo {
  width: 132px;
  height: 132px;
  border-radius: 50%;
  object-fit: cover;
  display: block;
  margin: 0;
}
.v-tree__name {
  font-family: var(--font-display);
  font-size: clamp(30px, 8vw, 42px);
  font-weight: var(--fw-bold);
  line-height: 1.05;
  letter-spacing: var(--ls-display);
  margin: 0;
}

.v-tree__social {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 14px;
  list-style: none;
  margin: 0;
  padding: 0;
}
/* Círculos de toque: 52px é o alvo confortável no celular, acima do mínimo de
   44px das diretrizes de acessibilidade. */
.v-tree__social-link {
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  border: 1px solid var(--border-2);
  color: var(--fg-1);
  transition: border-color var(--dur-2) var(--ease-standard),
              color var(--dur-2) var(--ease-standard),
              background var(--dur-2) var(--ease-standard),
              transform var(--dur-2) var(--ease-standard);
}
.v-tree__social-link:hover {
  border-color: var(--vision-purple);
  color: var(--vision-purple);
  background: var(--surface-overlay);
  transform: translateY(-2px);
}
.v-tree__social-link .v-icon { width: 22px; height: 22px; }

/* Três partes numa linha: marca, texto e seta. As pontas têm a largura do
   conteúdo e o meio fica com o que sobra, então o texto pode quebrar em duas
   linhas sem empurrar o lagarto ou a seta para fora. */
.v-tree__pitch {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 16px;
  width: 100%;
  padding: 18px 20px;
  border-radius: var(--radius-lg);
  border: 1px solid var(--border-2);
  background: var(--surface-overlay);
  text-align: left;
  transition: border-color var(--dur-2) var(--ease-standard),
              background var(--dur-2) var(--ease-standard);
}
.v-tree__pitch:hover {
  border-color: var(--vision-purple);
  background: var(--surface-overlay-strong);
}
.v-tree__pitch-mark {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  border-radius: var(--radius-md);
  /* Roxo rebaixado, e não o cheio: o botão de cima é que carrega o roxo sólido,
     e dois blocos na mesma cor disputariam a atenção. */
  background: rgba(169, 147, 255, 0.14);
  color: var(--vision-purple);
}
.v-tree__pitch-mark .v-icon { width: 26px; height: 26px; }
.v-tree__pitch-text { display: grid; gap: 3px; min-width: 0; }
.v-tree__pitch-title {
  font-size: var(--fs-h5);
  font-weight: var(--fw-semibold);
  line-height: 1.25;
}
.v-tree__pitch-sub {
  font-size: var(--fs-body-sm);
  line-height: 1.4;
  color: var(--fg-2);
}
.v-tree__pitch-arrow {
  width: 20px;
  height: 20px;
  color: var(--fg-3);
  transition: transform var(--dur-2) var(--ease-standard),
              color var(--dur-2) var(--ease-standard);
}
.v-tree__pitch:hover .v-tree__pitch-arrow {
  transform: translateX(3px);
  color: var(--vision-purple);
}

.v-tree__services { width: 100%; margin-top: 14px; }
.v-tree__services-title {
  font-family: var(--font-display);
  font-size: clamp(26px, 7vw, 34px);
  font-weight: var(--fw-bold);
  line-height: 1.1;
  letter-spacing: var(--ls-display);
  margin: 0 0 22px;
}

/* Carrossel: os cinco serviços numa faixa só, que corre para o lado. É rolagem
   nativa, sem JavaScript — o dedo arrasta no celular, o trackpad desliza no
   computador e o Tab entre os botões traz cada card para dentro da vista
   sozinho. O `scroll-snap` de proximidade acomoda o card no lugar quando a
   rolagem para perto de uma borda, mas não briga com quem está navegando pelo
   teclado, como o `mandatory` faria.

   As margens negativas cancelam o respiro lateral da coluna: a faixa encosta
   nas duas bordas e os cards sobram para fora, e é essa sobra que diz que há
   mais coisa para o lado. O `padding` devolve o alinhamento, então o primeiro
   card nasce na mesma linha do resto da página.

   A barra de rolagem fica escondida de propósito: ela atravessaria a faixa logo
   abaixo dos botões, e o card cortado na borda já cumpre o papel de dizer que
   dá para arrastar. */
.v-tree__cards {
  display: flex;
  gap: 16px;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  scroll-padding-left: 20px;
  list-style: none;
  margin: 0 -20px;
  padding: 4px 20px 12px;
  scrollbar-width: none;
}
.v-tree__cards::-webkit-scrollbar { display: none; }

/* Título e botão vão por cima da imagem, no pé do card. Com o texto dentro, o
   card fica em retrato: deitado, a faixa que o texto ocupa comeria metade da
   foto e não sobraria imagem para ver. */
.v-tree-card {
  position: relative;
  overflow: hidden;
  flex: 0 0 200px;
  aspect-ratio: 3 / 4;
  scroll-snap-align: start;
  border-radius: var(--radius-md);
  /* Cor de espera enquanto o arquivo não chegou, como no cabeçalho das abas. */
  background-color: var(--vision-ink);
}
/* Serve à foto e ao vídeo: o card aceita os dois, e o que muda entre eles é só
   o elemento. `display: block` porque `<video>` nasce inline e herdaria a
   folga da linha de texto. */
.v-tree-card__media {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--dur-3) var(--ease-standard);
}
.v-tree-card:hover .v-tree-card__media { transform: scale(1.04); }

/* Véu que escurece só o pé, onde o texto fica: as fotos vão do quase preto ao
   claro, e sem ele o título sumiria sobre as claras. Começa transparente na
   metade de cima para a imagem continuar sendo o que se vê primeiro. */
.v-tree-card::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg,
              rgba(10, 10, 10, 0) 38%,
              rgba(10, 10, 10, 0.62) 68%,
              rgba(10, 10, 10, 0.9) 100%);
}
/* Acima do véu — o `::after` vem depois na pintura. */
.v-tree-card__body {
  position: absolute;
  z-index: 1;
  inset: auto 0 0 0;
  display: grid;
  justify-items: center;
  gap: 10px;
  padding: 14px 12px 14px;
}
.v-tree-card__title {
  font-size: var(--fs-body-lg);
  font-weight: var(--fw-semibold);
  line-height: 1.15;
  color: var(--vision-white);
  text-align: center;
  margin: 0;
}
/* Sobre foto, o contorno sozinho não segura o botão: o fundo escurecido e o
   desfoque dão a ele uma superfície própria, e a borda fica mais firme que a do
   fantasma padrão, que foi calibrada para fundo chapado. */
.v-tree-card__cta {
  background: rgba(10, 10, 10, 0.5);
  border-color: rgba(255, 255, 255, 0.38);
  -webkit-backdrop-filter: blur(5px);
  backdrop-filter: blur(5px);
}
.v-tree-card__cta:hover {
  background: rgba(10, 10, 10, 0.72);
  border-color: var(--vision-purple);
}

/* A página das cinco perguntas usa a mesma coluna, sem os blocos da árvore. */
.v-tree--simples { gap: 18px; padding-top: 96px; }

/* ============================= RESPONSIVO ============================= */

@media (max-width: 1024px) {
  /* Seis itens no menu já espremem os lados da grade da nav nessa faixa. */
  .v-nav__links { gap: 16px; }
  .v-dna { grid-template-columns: 1fr; gap: 48px; }
  .v-services__head { grid-template-columns: 1fr; align-items: start; gap: 24px; }
  .v-tabs { justify-content: flex-start; }
  .v-service-info { grid-template-columns: 1fr; }
  .v-cases { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .v-feedbacks { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .v-services { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .v-quote, .v-cta { padding: 56px 40px; }
}

@media (max-width: 768px) {
  .v-page { --v-nav-h: 69px; }

  .v-tree { padding: 48px 20px 72px; gap: 22px; }
  .v-tree__photo { width: 112px; height: 112px; }
  .v-tree__pitch { gap: 13px; padding: 16px; }
  .v-tree__pitch-mark { width: 42px; height: 42px; }

  .v-container { padding: 0 20px; }
  .v-profile-card__head { padding: 20px; }
  .v-profile-card__body { padding: 20px; }
  .v-profile-card__foot { padding: 16px 20px; }
  .v-service-title { margin-bottom: 32px; }
  .v-service-info__num { font-size: 64px; }
  .v-service-info { margin: 0 -20px; }
  .v-service-info__item { padding: 16px 20px; gap: 20px; }
  .v-service-callout { padding: 40px 24px; }
  .v-service-callout__title { font-size: var(--fs-h3); }
  .v-cases { grid-template-columns: 1fr; }
  .v-feedbacks { grid-template-columns: 1fr; }
  .v-faq__question { gap: 14px; padding: 22px 0; }
  .v-faq__label { font-size: var(--fs-h5); }
  .v-faq__text { padding: 0 0 24px calc(14px + 2ch); }
  .v-service-meta { grid-template-columns: 1fr; gap: 14px; }
  .v-service-meta__pair { padding-right: 0; }
  .v-service-meta__pair + .v-service-meta__pair {
    padding: 14px 0 0;
    border-left: none;
    border-top: 1px solid var(--border-2);
  }
  /* Única faixa em que a frase não cabe em uma linha nos 20px: aqui o corpo
     cede para a linha não estourar o card. */
  .v-profile-card__phrase { font-size: clamp(12px, 3.9vw, var(--fs-body-lg)); }
  .v-nav {
    display: flex;
    justify-content: space-between;
    padding: 14px 20px;
    /* A barra é sticky, então ocupa espaço no topo: a abertura do hero desconta
       esta altura para caber em uma tela. Fixá-la aqui mantém a conta válida —
       14px de padding em cima e embaixo, 40px do botão do menu, 1px da borda. */
    min-height: var(--v-nav-h);
  }

  /* O menu vira uma gaveta controlada pelo botão; sem JS, o botão some e os
     links continuam visíveis empilhados. */
  .v-nav__toggle { display: block; }
  .v-nav__links {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    /* Desfaz o `justify-self: center` que centraliza o menu na grade do
       desktop: em um elemento absoluto, um alinhamento diferente de
       `normal`/`stretch` faz a caixa ignorar `left`/`right` e encolher até o
       conteúdo — a gaveta abria como uma coluna estreita no meio da tela. */
    justify-self: stretch;
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
    padding: 20px;
    background: rgba(10, 10, 10, 0.96);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
    font-size: var(--fs-h5);
  }
  .v-nav__links[hidden] { display: none; }
  .v-nav__link { padding: 10px 0; width: 100%; }
  .v-nav__link[aria-current="true"]::after { display: none; }
  .v-nav__cta { display: none; }

  .v-section { padding: 72px 0; }
  .v-hero { padding: 0 0 88px; --v-hero-measure: 100%; }
  /* No celular a abertura ocupa a primeira tela e o texto fica no meio dela —
     centralizado só na vertical: as linhas continuam alinhadas à esquerda.
     `svh` mede a tela com a barra do navegador visível, então o bloco não
     salta quando ela se recolhe. Passando disso, o conteúdo simplesmente
     empurra o bloco para baixo. */
  .v-hero__lead {
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-height: calc(100svh - var(--v-nav-h));
    padding: 32px 0;
  }
  .v-hero__title { font-size: clamp(40px, 10.5vw, 68px); }
  /* No celular os três continuam lado a lado, agora dividindo a largura em
     partes iguais — com colunas do tamanho do conteúdo, a mais estreita
     encolheria demais. */
  .v-hero__stats {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 20px 12px;
    margin-top: 56px;
  }
  .v-stat__value { font-size: 30px; }
  .v-services { grid-template-columns: 1fr; }
  /* Sem espaço para marca e canais lado a lado: empilha, tudo à esquerda. */
  .v-footer__top { flex-direction: column; align-items: flex-start; gap: 28px; }
  .v-quote, .v-cta { padding: 40px 24px; }
  /* Três tópicos lado a lado não cabem em 390px: a faixa empilha e a divisão
     passa a ser a borda de cima. */
  .v-cta__meta { flex-direction: column; gap: 12px; }
  .v-cta__meta-pair { padding: 0; }
  .v-cta__meta-pair + .v-cta__meta-pair {
    padding-top: 12px;
    border-left: none;
    border-top: 1px solid rgba(10, 10, 10, 0.28);
  }
  .v-quote::before { font-size: 140px; top: 12px; right: 24px; }
  .v-section__head { margin-bottom: 40px; }
}

/* Terceiro ponto de quebra, só para a árvore de links: os outros dois nasceram
   das grades largas da home, e nada nela precisa deste tamanho. */
@media (max-width: 480px) {
  /* Card mais estreito para o seguinte aparecer cortado na borda: é esse pedaço
     à mostra que conta que a faixa anda para o lado. Com 200px na tela mais
     estreita o segundo card mal apareceria, e o carrossel passaria por uma
     imagem solta. */
  .v-tree-card { flex-basis: 168px; }
  .v-tree__social { gap: 12px; }
}

/* ============================= TEXTO LEGAL ============================= */

/* Coluna de leitura para a política de privacidade. A medida em `ch` acompanha
   a fonte: é a largura em que o olho acha a linha seguinte sem se perder, e
   vale mais que um valor em pixels que muda de sentido a cada tipo. */
.v-legal {
  max-width: 68ch;
  color: var(--fg-2);
}
.v-legal .v-section__title { margin-bottom: 8px; }
.v-legal__date {
  margin: 0 0 32px;
  font-size: var(--fs-caption);
  color: var(--fg-3);
}
.v-legal__lead {
  font-size: var(--fs-body-lg, 18px);
  color: var(--fg-1);
}
/* O espaço acima do título é maior que o abaixo: é isso que amarra cada
   cabeçalho ao texto que ele abre, em vez de deixá-lo solto entre dois blocos. */
.v-legal h2 {
  margin: 40px 0 12px;
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  font-weight: var(--fw-bold);
  line-height: 1.2;
  color: var(--fg-1);
}
.v-legal p {
  margin: 0 0 16px;
  line-height: 1.65;
}
.v-legal .v-btn { margin-top: 8px; }

/* ============================= PÁGINA 404 ============================= */

/* Coluna única e centrada: não há conteúdo para comparar nem para percorrer,
   só um caminho de volta. Tudo o que a página faz é dizer onde a pessoa está e
   oferecer a saída. */
.v-404 { padding: 120px 0; }
.v-404__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

/* O número é ornamento, não informação — quem chega aqui já sabe que algo deu
   errado, e "404" só diz isso a quem conhece o código. Por isso ele fica em
   tom apagado, um degrau abaixo do recado, e `aria-hidden` no HTML o tira da
   leitura em voz alta, onde soletrar "quatro zero quatro" não ajudaria
   ninguém.

   A folga abaixo é dele mesmo: a `line-height` apertada que o número precisa
   encosta o título nele, e sem esse respiro os dois leem como um bloco só. */
.v-404__code {
  margin: 0 0 var(--space-5);
  font-family: var(--font-display);
  font-size: clamp(88px, 18vw, 200px);
  line-height: var(--lh-display);
  letter-spacing: var(--ls-display);
  color: var(--vision-purple-soft);
  user-select: none;
}

.v-404__title {
  margin: 0 0 var(--space-4);
  font-family: var(--font-display);
  font-size: clamp(32px, 5vw, 56px);
  line-height: var(--lh-heading);
  letter-spacing: var(--ls-heading);
  color: var(--fg-1);
}

.v-404__text {
  max-width: 46ch;
  margin: 0 0 var(--space-7);
  font-size: var(--fs-body-lg);
  color: var(--fg-3);
}

@media (max-width: 640px) {
  .v-404 { padding: 72px 0; }
}

/* ============================= CONSENTIMENTO ============================= */

/* Faixa no pé da tela. Fica acima de tudo, mas não cobre a página inteira: a
   escolha não impede a leitura, e prender quem só quer ler seria pior que não
   perguntar. O `max-width` acompanha o container do site para a faixa não
   virar uma linha de texto larga demais nas telas grandes. */
.v-consent {
  position: fixed;
  z-index: 60;
  left: 16px;
  right: 16px;
  /* Acima da barra de gestos do iOS, que come os últimos pixels. */
  bottom: max(16px, env(safe-area-inset-bottom));
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  max-width: 1216px;
  margin: 0 auto;
  padding: 16px 20px;
  border-radius: var(--radius-md);
  /* O banner vive fora de qualquer `.v-section`, então precisa trocar os
     tokens de borda por conta própria — os do `:root` são pretos translúcidos
     e sumiriam sobre este fundo escuro. Mesma troca que `.v-section--dark`. */
  --border-2: rgba(255, 255, 255, 0.16);
  border: 1px solid var(--border-2);
  background: var(--vision-ink);
  color: var(--vision-paper);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);
}
/* `display: flex` acima é estilo de autor e venceria o `[hidden] {display:none}`
   da folha do navegador, que tem a mesma especificidade. Sem esta linha o
   banner apareceria mesmo escondido — inclusive depois de respondido. */
.v-consent[hidden] { display: none; }

/* Sublinhado permanente: dentro de um bloco de texto curto, cor sozinha não
   basta para dizer que é link — e não se deve exigir que o visitante passe o
   mouse para descobrir onde está a política. */
.v-consent__link {
  color: var(--vision-purple);
  text-decoration: underline;
  text-underline-offset: 2px;
  white-space: nowrap;
}
.v-consent__link:hover { color: var(--vision-white); }

.v-consent__text {
  margin: 0;
  font-size: var(--fs-body-sm);
  line-height: 1.45;
  color: var(--vision-paper);
}
/* Os botões não encolhem: o texto é que quebra linha antes deles. */
.v-consent__actions {
  display: flex;
  flex-shrink: 0;
  gap: 10px;
}

@media (max-width: 640px) {
  /* Empilha, e os botões passam a dividir a largura em partes iguais — recusar
     com o mesmo alcance de polegar que aceitar. */
  .v-consent {
    flex-direction: column;
    align-items: stretch;
    gap: 14px;
  }
  .v-consent__actions > * { flex: 1; justify-content: center; }
}

/* ============================= MOVIMENTO REDUZIDO ============================= */

@media (prefers-reduced-motion: reduce) {
  .v-marquee { overflow-x: auto; }
  .v-marquee__track { animation: none; }
  .v-marquee__group[aria-hidden] { display: none; }

  html { scroll-behavior: auto; }
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  .v-reveal { opacity: 1; transform: none; }
  /* Sem a subida, a palavra tem de estar no lugar; sem a piscada, o cursor
     ainda marca o fim da frase. */
  .v-word__inner { transform: none; }
  .v-caret { opacity: 1; animation: none; }
  /* Sem a varredura o ponto continua legível como indicador de "estamos aqui". */
  .v-pulse::before,
  .v-pulse::after { display: none; }
}
