/* ============================================================
   NÍTIDA — estúdio de software
   Sistema: 6 cores nomeadas, derivadas por color-mix.
   Planos: claro = informação/prova · escuro = declaração/decisão.
   Raio 0. Sem sombra. Profundidade por plano + hairline 1px.
   ============================================================ */

:root {
  /* As 6 cores fechadas (2.2 do briefing) */
  --white: #FFFFFF;
  --black: #0A0A0A;
  --ink: #111827;
  --line-light: #E5E7EB;
  --teal: #0E4F5C;
  --ice: #98CFDF;

  /* Derivadas — fallbacks literais para navegadores sem color-mix */
  --ink-2: #4B5563;
  --ink-3: #6B7280;
  --paper-2: #D4D4D4;
  --paper-3: #A1A1AA;
  --line-dark: #1F2937;
  --ink-2: color-mix(in srgb, var(--ink) 68%, var(--white));
  --ink-3: color-mix(in srgb, var(--ink) 52%, var(--white));
  --paper-2: color-mix(in srgb, var(--white) 83%, var(--black));
  --paper-3: color-mix(in srgb, var(--white) 64%, var(--black));
  --line-dark: color-mix(in srgb, var(--white) 13%, var(--black));

  /* Plano corrente (default = claro) */
  --bg: var(--white);
  --fg: var(--ink);
  --fg-2: var(--ink-2);
  --fg-3: var(--ink-3);
  --hair: var(--line-light);
  --acc: var(--teal);

  /* Tipografia */
  --brand: 'Montserrat', sans-serif;
  --body: 'Plus Jakarta Sans', sans-serif;
  --sign: 'Montserrat', sans-serif;

  /* Espaçamento (tokens da REF-01) */
  --space-xs: 0.25rem;
  --space-sm: 0.5rem;
  --space-md: 1rem;
  --space-lg: 2rem;
  --space-xl: 4rem;
  --space-2xl: 8rem;

  --header-h: 5rem;

  /* Movimento — dois gestos: o texto sai de trás de um corte; o filete se desenha.
     Só transform e opacity. */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);   /* sai rápido, assenta longo */
  --ease-draw: cubic-bezier(0.65, 0, 0.35, 1); /* traço de régua */
  --t-state: 180ms;
  --t-draw: 900ms;
  --t-text: 1100ms;
  --stagger: 110ms;
}

/* Plano escuro. Cada plano pinta a própria cor: funciona sem JS e sem
   movimento. A troca entre planos é uma borda seca, não um fade de cor.
   O header assume o plano que passa por baixo dele (.is-dark, via JS). */
.plane--dark,
.site-header.is-dark {
  --bg: var(--black);
  --fg: var(--white);
  --fg-2: var(--paper-2);
  --fg-3: var(--paper-3);
  --hair: var(--line-dark);
  --acc: var(--ice);
}

.plane {
  background-color: var(--bg);
  color: var(--fg);
}

/* Overscroll no fim da página (macOS/iOS) continua no plano do rodapé */
html.at-dark-end { background-color: var(--black); }


/* ---------- Base ---------- */

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

[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; }

@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

body {
  margin: 0;
  font-family: var(--body);
  font-size: 1rem;
  line-height: 1.75;
  background-color: var(--bg);
  color: var(--fg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3, h4, p, ul, ol, dl, dd, figure { margin: 0; }
ul, ol { padding: 0; list-style: none; }
a { color: inherit; }
img { display: block; max-width: 100%; height: auto; }

::selection { background: var(--teal); color: var(--white); }
.plane--dark ::selection { background: var(--ice); color: var(--black); }

a:focus-visible,
button:focus-visible {
  outline: 1px solid var(--acc);
  outline-offset: 3px;
}

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

section[id] { scroll-margin-top: var(--header-h); }

.wrap {
  width: 100%;
  max-width: 90rem;
  margin-inline: auto;
  padding-inline: 1.5rem;
}

/* ---------- Vozes tipográficas ----------
   Institucional: Montserrat 300 uppercase tracked — SÓ wordmark e assinatura.
   Editorial: Montserrat 500/600, caixa normal, tracking negativo — declarações e títulos.
   Mono: Plus Jakarta Sans — labels, numeração, metadados, status. Nada além disso.
   Corpo: Plus Jakarta Sans, uma única família, via token. */

.wordmark {
  font-family: var(--brand);
  font-weight: 300;
  font-size: 1.125rem;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  line-height: 1;
  text-decoration: none;
}
.wordmark:hover { color: var(--acc); } /* instantâneo: só transform e opacity animam */

.sig {
  font-family: var(--brand);
  font-weight: 300;
  font-size: 0.75rem;
  letter-spacing: 0.25em;
  text-transform: uppercase;
  color: var(--fg-3);
}

.display {
  font-family: var(--brand);
  font-weight: 500;
  letter-spacing: -0.02em;
  line-height: 1.12;
  color: var(--fg);
}
.display .strong { font-weight: 600; }
.display .dim { color: var(--fg-2); }

.mono {
  font-family: var(--sign);
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  color: var(--fg-2);
}
.meta { color: var(--fg-3); }

.label {
  display: inline-flex;
  align-items: center;
  gap: 0.625rem;
  font-family: var(--sign);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--fg);
}
.label .dot { width: 0.5rem; height: 0.5rem; background: var(--acc); flex: none; border-radius: 9999px; }

.lead {
  font-size: 1.125rem;
  line-height: 1.7;
  color: var(--fg-2);
}

/* Escala editorial — definida, não improvisada */
.t-display    { font-size: clamp(2.5rem, 1.6rem + 4.2vw, 5rem); line-height: 1.08; }
.t-title      { font-size: clamp(1.875rem, 1.4rem + 2.2vw, 3rem); }
.t-question   { font-size: clamp(1.375rem, 1.05rem + 1.8vw, 2.25rem); line-height: 1.3; }
.t-question-lg{ font-size: clamp(2rem, 1.4rem + 3.2vw, 3.75rem); line-height: 1.15; }
.t-pair       { font-size: clamp(1.25rem, 1rem + 1.4vw, 1.875rem); line-height: 1.35; }
.t-step       { font-size: clamp(1.375rem, 1.1rem + 1.3vw, 2rem); }

/* Revelação por linha: estado final é o default visível; o movimento recua e anima.
   A máscara tem respiro vertical compensado por margem negativa — Montserrat
   estoura a line-box (acentos e descenders seriam cortados pelo overflow). */
.line {
  display: block;
  overflow: hidden;
  padding-block: 0.12em 0.2em;
  margin-block: -0.12em -0.2em;
}
.line-inner { display: block; }
.line:nth-child(2) { --i: 1; }
.line:nth-child(3) { --i: 2; }

/* Hairlines que o movimento desenha: pseudo-elemento sobre uma borda
   transparente, para o layout não mudar. */
.rule-b::after,
.service::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -1px;
  height: 1px;
  background: var(--hair);
  transform-origin: left center;
}

/* ---------- Botão Fale Conosco (REF-01) ---------- */
.btn-01 {
  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  gap: 0.625rem;
  padding: 0.625rem 1.5rem;
  border-radius: 9999px;
  border: 1px solid var(--hair); /* Adapta ao fundo claro/escuro */
  color: var(--fg); /* Branco no escuro, preto no claro */
  font-size: 11px;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  text-decoration: none;
  font-weight: 500;
  font-family: var(--brand); /* Voltando para Montserrat como manda o documento */
}
/* Hover, foco e toque em camadas: o preenchimento e o anel de acento
   aparecem por opacidade; a seta desliza na direção dela. Sem cor interpolada. */
.btn-01::before,
.btn-01::after {
  content: "";
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  opacity: 0;
  pointer-events: none;
}
.btn-01::before { background-color: rgba(128, 128, 128, 0.1); z-index: -1; } /* Seguro para ambos os fundos */
.btn-01::after { border: 1px solid var(--acc); }
@media (hover: hover) {
  .btn-01:hover::before,
  .btn-01:hover::after { opacity: 1; }
  .btn-01:hover .arrow { color: var(--acc); transform: translate(0.125rem, 0.125rem); }
}
/* Teclado e toque não dependem de hover */
.btn-01:focus-visible::before,
.btn-01:active::before { opacity: 1; }
.btn-01 .dot {
  width: 0.375rem;
  height: 0.375rem;
  border-radius: 9999px;
  background-color: var(--acc);
  display: inline-block;
  flex: none;
}
.btn-01 .arrow {
  width: 1em;
  height: 1em;
  color: var(--fg-3);
}


/* ---------- Header ----------
   Estrutura herdada da REF-01. O border-b do header é o ÚNICO filete
   da transição header/hero: o main compensa exatamente os 80px e a
   primeira linha do hero não tem borda. */
.site-header {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 50;
  height: var(--header-h);
  background: var(--bg);
  border-bottom: 1px solid var(--hair);
  color: var(--fg);
}
.header-row {
  height: 100%;
  max-width: 90rem;
  margin-inline: auto;
  padding-inline: 1.5rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}
.header-actions { display: flex; align-items: center; gap: 1rem; }
.header-link { color: var(--fg-2); text-decoration: none; white-space: nowrap; }
.header-link:hover { color: var(--acc); }

main { padding-top: var(--header-h); }

/* ---------- Hero ---------- */

.hero { min-height: calc(100svh - var(--header-h)); }
.hero-wrap {
  min-height: inherit;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  gap: 2rem;
  padding-block: 2rem;
  position: relative;
}
.hero-meta {
  position: relative;
  flex: none;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  flex-wrap: wrap;
}
.hero-center {
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  flex: 1;
  padding-block: 2rem;
  margin-top: 0;
}
.filete {
  width: 3rem;
  height: 1px;
  background: var(--acc);
  margin-bottom: 2.5rem;
}
.filete-md {
  width: 6rem;
  height: 1px;
  background: var(--acc);
  margin-block: 2.5rem; /* sem margem de cima, a margem negativa da .line puxava o filete para dentro do título */
}
.filete-lg {
  width: 12rem;
  height: 1px;
  background: var(--acc);
  margin-top: 4rem;
  margin-bottom: 4rem;
}
.dash-acc {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
}
.dash-acc::after {
  content: "";
  display: inline-block;
  width: 1.25em;
  height: 1px;
  background-color: var(--acc);
  flex: none;
}
.hero-sub {
  margin-top: 2.5rem;
  max-width: 56ch;
}
.hero-cta { margin-top: 3.5rem; }
.hero-price-link { display: inline-block; margin: 1.25rem 0 0 1rem; color: var(--fg-2); font-size: 0.875rem; text-underline-offset: 0.25em; }
.hero-price-link:hover { color: var(--acc); }

/* ---------- Seções ---------- */

.section {
  padding-block: 5rem;
}

.sec-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  flex-wrap: wrap;
  padding-bottom: 2rem;
}
.rule-b { position: relative; border-bottom: 1px solid transparent; }

/* ---------- 02 · O que fazemos ----------
   Sem cards: o conteúdo é resolvido com estrutura — grid 12 colunas e
   hairlines entre linhas. Sem hover: a linha não é clicável. */
.services { margin-top: 3rem; }
.service {
  position: relative;
  display: grid;
  grid-template-columns: 1fr;
  gap: 1rem;
  padding: 2.5rem 0;
  border-bottom: 1px solid transparent;
}
.service-num {
  font-family: var(--brand); /* Montserrat para numeração estática de serviços */
  color: var(--acc);
  font-size: 0.875rem;
  font-weight: 500;
  letter-spacing: 0.1em;
}
.service-name {
  font-family: var(--brand);
  font-size: 1.25rem;
  font-weight: 300;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--fg);
  line-height: 1.2;
}
.service-desc p {
  font-family: var(--body);
  font-size: 0.875rem;
  color: var(--fg-2); /* variavel de tema, funciona em plano claro e escuro */
  line-height: 1.7;
  font-weight: 400;
}

/* ---------- 03 · O corte ----------
   .cut-stage segura as 4 "batidas" (título, pergunta, par, cortes). Em
   fluxo normal (sem pin) elas só empilham com respiro entre si — o
   max-width fica em cada .cut-beat, não no palco, porque a batida dos
   cortes precisa da largura cheia para a grade de 4 colunas. No modo
   pin (.js-pin, ver seção Reels) cada .beat vira uma tela inteira,
   sobreposta às outras. */
.cut-stage { padding-block: 5rem 4rem; }
.cut-beat {
  max-width: 56rem;
  margin-inline: auto;
  text-align: center;
}
.cut-beat + .cut-beat,
.cut-stage > .cuts-block { margin-top: 4rem; }
.cut-beat > .mono { margin-bottom: 1.5rem; }
.dot-inline {
  display: inline-block;
  width: 0.16em;
  height: 0.16em;
  background: var(--acc);
  margin-left: 0.12em;
  border-radius: 9999px;
}

.cuts-block {
  border-top: 1px solid var(--hair);
  padding-top: 2rem;
  margin-top: 2rem;
}
.cuts-title { font-size: 0.6875rem; font-weight: 500; letter-spacing: 0.15em; }
.cuts {
  margin-top: 2rem;
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.5rem;
}
.cut-item {
  border-top: 1px solid var(--hair);
  padding-top: 1.25rem;
}
/* O "não" visível: cada item vem riscado por padrão, em acento.
   line-through nativo acompanha cada linha quando o texto quebra. */
.cut-text {
  position: relative;
  display: block;
  font-size: 1.0625rem;
  font-weight: 500;
  color: var(--fg-3);
  text-decoration-line: line-through;
  text-decoration-color: var(--acc);
  text-decoration-thickness: 1px;
}
/* Cópia só com o risco, posta pelo JS para o movimento desenhar */
.cut-stroke {
  position: absolute;
  inset: 0;
  color: transparent;
  text-decoration-line: line-through;
  text-decoration-color: var(--acc);
  text-decoration-thickness: 1px;
  transform-origin: left center;
  pointer-events: none;
  user-select: none;
}

/* ---------- 04 · Como trabalhamos ---------- */

.method {
  margin-top: 3rem;
  display: grid;
  grid-template-columns: 1fr;
  gap: 3rem;
}
.method-sub { margin-top: 1.5rem; max-width: 52ch; color: var(--fg-2); }
.method-num { display: none; }

.steps { position: relative; padding-left: 2.5rem; }
.steps::before {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 1px;
  background: var(--hair);
}
.steps-rail {
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 1px;
  background: var(--acc);
  transform: scaleY(1);
  transform-origin: top;
}
.step { position: relative; padding: 2rem 0 2.5rem; }
.step::before {
  content: "";
  position: absolute;
  left: -2.5rem;
  top: 2.5rem;
  width: 0.625rem;
  height: 0.625rem;
  background: var(--bg);
  border: 1px solid var(--fg-3);
  border-radius: 9999px;
  transform: translateX(-50%);
}
/* Etapa ativa: o ponto de acento cresce dentro do anel (transform, não cor) */
.step::after {
  content: "";
  position: absolute;
  left: -2.5rem;
  top: 2.5rem;
  width: 0.625rem;
  height: 0.625rem;
  background: var(--acc);
  border-radius: 9999px;
  transform: translateX(-50%) scale(0);
}
.step.is-active::after { transform: translateX(-50%) scale(1); }
.label-step { font-size: 0.6875rem; font-weight: 500; letter-spacing: 0.15em; }
.num-acc { color: var(--acc); }
.step .t-step { margin-top: 0.75rem; }
.step-text { margin-top: 1rem; max-width: 60ch; color: var(--fg-2); }

/* Pontos de navegação — só existem no modo pin (ver Reels). Em fluxo
   normal o rail já indica progresso, então ficam ocultos. */
.step-dots { display: none; }

/* ---------- 05 · Um caso ---------- */

.case { display: none; margin-top: 3rem; }
.case.is-active { display: block; }

.case-nav { display: flex; gap: 1.5rem; margin-top: 2rem; }
.case-nav[hidden] { display: none; }
.case-btn {
  background: none;
  border: none;
  border-bottom: 1px solid transparent;
  padding: 0 0 0.25rem;
  font-family: var(--sign);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.15em;
  color: var(--fg-3);
  cursor: pointer;
}
.case-btn.is-active { color: var(--fg); border-bottom-color: var(--acc); }

.field {
  position: relative;
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.5rem;
  padding-block: 1.75rem;
}
.field::before {
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 1px;
  background: var(--hair);
  transform-origin: left;
}
.field dt {
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.15em;
}
.field dd { max-width: 64ch; }
.field-value { color: var(--fg-3); font-size: clamp(1rem, 0.9rem + 0.5vw, 1.125rem); }
/* "O que foi cortado": mesmo peso visual dos outros campos, marcado
   por filete de acento — distinguido, nunca escondido. */
.field--cut { padding-left: 1.25rem; }
.field--cut::after {
  content: "";
  position: absolute;
  left: 0; top: 1.75rem; bottom: 1.75rem;
  width: 1px;
  background: var(--acc);
  transform-origin: top;
}
.field--cut dt { color: var(--acc); }

.case-figure { margin-top: 4rem; border: 1px solid var(--hair); padding: 0.5rem; }
.case-context-note { max-width: 76ch; margin-top: 1.5rem; color: var(--fg-3); font-size: 0.8125rem; }

/* Pontos de navegação — só existem no modo pin (ver Reels). */
.field-dots { display: none; }

/* ---------- 06 · Contato ---------- */

.contact-center {
  max-width: 52rem;
  margin-inline: auto;
  text-align: center;
  padding-block: 5rem 4rem;
}
.contact-pair { margin-top: 0; }
.contact-center .t-question-lg { margin-top: 4rem; }
.contact-note {
  margin-top: 2.5rem;
  margin-bottom: 2.5rem;
  color: var(--fg-3);
}
.contact-center .btn-01 {
  margin-top: 0;
}

/* ---------- 06 · Valores ---------- */
.pricing-summary { border-top: 1px solid var(--hair); }
.pricing-heading { margin-top: 1rem; }
.pricing-intro { margin-top: 0.75rem; color: var(--fg-2); }
.pricing-options { display: grid; grid-template-columns: 1fr; margin-top: 3rem; }
.pricing-option { padding-block: 2rem; border-top: 1px solid var(--hair); }
.pricing-option:last-child { border-bottom: 1px solid var(--hair); }
.pricing-option h3 { margin-top: 1.5rem; }
.pricing-description { max-width: 52ch; margin-top: 1rem; color: var(--fg-2); }
.pricing-price { margin-top: 2rem; font-family: var(--brand); font-size: clamp(1.75rem, 1.4rem + 1vw, 2.5rem); font-weight: 500; line-height: 1.15; }
.pricing-price span { font-family: var(--body); font-size: 0.875rem; font-weight: 400; color: var(--fg-2); }
.pricing-monthly { margin-top: 0.5rem; font-size: 0.9375rem; }
.pricing-term { margin-top: 1.25rem; color: var(--fg-2); font-size: 0.875rem; }
.text-link { color: inherit; text-underline-offset: 0.25em; }
.text-link:hover { color: var(--acc); }
.pricing-option > .text-link { display: inline-block; margin-top: 1.5rem; }
.pricing-footnote { max-width: 76ch; margin-top: 2rem; color: var(--fg-2); font-size: 0.875rem; }
.pricing-custom { margin-top: 1.5rem; }

/* ---------- Página /precos ---------- */
.pricing-page-intro { padding-bottom: 4rem; }
.pricing-page-lead { max-width: 58rem; padding-top: 3rem; }
.pricing-page-lead .lead { max-width: 54ch; margin-top: 1.5rem; }
.pricing-back { text-decoration: none; }
.pricing-index { display: flex; flex-wrap: wrap; gap: 1.5rem 3rem; margin-top: 4rem; padding-block: 1.25rem; border-block: 1px solid var(--hair); font-size: 0.75rem; letter-spacing: 0.08em; }
.pricing-index a { display: flex; gap: 1rem; text-decoration: none; }
.pricing-index a:hover { color: var(--acc); }
.pricing-index span { color: var(--acc); }
.pricing-detail { border-top: 1px solid var(--hair); }
.pricing-detail-grid { display: grid; grid-template-columns: 1fr; gap: 3rem; padding-top: 1rem; }
.pricing-detail-lead > p:first-of-type { max-width: 45ch; margin-top: 1.25rem; color: var(--fg-2); }
.pricing-detail-lead .pricing-price { margin-top: 2.5rem; }
.pricing-detail-lead .pricing-cta { margin-top: 2rem; }
.pricing-detail-content { display: grid; grid-template-columns: 1fr; gap: 2rem; }
.pricing-list-block { padding-top: 1.5rem; border-top: 1px solid var(--hair); }
.pricing-list { margin-top: 1rem; }
.pricing-list li { padding-block: 0.625rem; border-bottom: 1px solid var(--hair); line-height: 1.6; }
.pricing-limit { margin-top: 1rem; color: var(--fg-2); font-size: 0.875rem; }
.pricing-maintenance { border-block: 1px solid var(--hair); }
.pricing-maintenance-grid, .pricing-payment-grid { display: grid; grid-template-columns: 1fr; gap: 2rem; }
.pricing-maintenance-copy, .pricing-payment-copy { display: grid; gap: 1rem; }
.pricing-maintenance-copy { color: var(--fg-2); }
.pricing-payment-grid { margin-top: 2rem; }
.pricing-next { border-top: 1px solid var(--hair); }
.pricing-next-inner { max-width: 70rem; }
.pricing-next-inner > p { max-width: 60ch; margin-top: 1rem; color: var(--fg-2); }
.pricing-next-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 1.5rem; margin-top: 2rem; }

/* ---------- Rodapé ---------- */

.footer {
  padding-block: 2.5rem;
}
.footer-row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 1.5rem 3rem;
}
.footer-brand { display: flex; align-items: baseline; gap: 1.25rem; flex-wrap: wrap; }
.footer .wordmark { font-size: 1rem; }
.f-link { text-decoration: none; }
.f-link:hover { color: var(--fg); }

/* ---------- Breakpoints ---------- */

@media (min-width: 48em) {
  .cuts { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 24em) {
  .header-row { padding-inline: 1rem; gap: 0.5rem; }
  .header-actions { gap: 0.625rem; }
  .header-link { font-size: 0.625rem; letter-spacing: 0.05em; }
  .site-header .btn-01 { padding-inline: 0.75rem; letter-spacing: 0.1em; white-space: nowrap; }
  .hero-meta { gap: 0.5rem; }
  .hero-meta .meta { font-size: 0.6875rem; }
}

@media (min-width: 64em) {
  .wrap { padding-inline: 4rem; }
  .header-row { padding-inline: 4rem; }
  .section { padding-block: var(--space-2xl); }
  .sec-head { padding-bottom: 4rem; } /* Mais respiro no cabeçalho das seções no desktop */
  .hero-wrap { padding-block: 4rem; gap: 2rem; }
  .hero-center { padding-block: 3rem; }
  .hero-statement { font-size: clamp(2.5rem, 5vw, 5rem); }
  .cut-stage, .contact-center { padding-block: var(--space-2xl) 5rem; } /* Alinhado com o respiro de .section */

  .service {
    grid-template-columns: repeat(12, 1fr);
    gap: 1.5rem;
    padding: 3rem 0; /* mais respiro que o mobile 2.5rem */
    align-items: baseline; /* alinha numeracao, titulo e descricao pela linha de base */
  }
  .service-num { grid-column: 1 / 3; }
  .service-name { grid-column: 3 / 8; }
  .service-desc { grid-column: 8 / 13; max-width: 52ch; }

  .pricing-summary { min-height: 100svh; display: flex; align-items: center; }
  .pricing-summary > .wrap { width: 100%; }
  .pricing-options { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 4rem; }
  .pricing-option { display: flex; flex-direction: column; align-items: flex-start; }
  .pricing-option > .text-link { margin-top: auto; padding-top: 1.5rem; }
  .pricing-page-intro { padding-bottom: 6rem; }
  .pricing-page-lead { padding-top: 5rem; }
  .pricing-detail-grid { grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 3rem; }
  .pricing-detail-lead { grid-column: 1 / 6; }
  .pricing-detail-content { grid-column: 7 / 13; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 2rem; }
  .pricing-maintenance-grid, .pricing-payment-grid { grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 3rem; }
  .pricing-maintenance-grid > h2, .pricing-payment-grid > h2 { grid-column: 1 / 6; }
  .pricing-maintenance-copy, .pricing-payment-copy { grid-column: 7 / 13; }

  .cuts { grid-template-columns: repeat(4, 1fr); }

  .method { grid-template-columns: repeat(12, 1fr); gap: 2rem; }
  .method-left { grid-column: 1 / 6; }
  .method-sticky { position: sticky; top: calc(var(--header-h) + 2rem); }
  .method-sub { max-width: 44ch; } /* mais contido na coluna de 5 colunas */
  .steps { grid-column: 7 / 13; }
  .method-num {
    display: flex;
    align-items: baseline;
    margin-top: 4rem;
    font-family: var(--brand); /* Voltando a numeração gigante para Montserrat */
    line-height: 1;
  }
  /* Numeração em fita: 01–04 empilhados, a janela mostra a etapa ativa (--step, via JS) */
  .num-current {
    height: 1em;
    clip-path: inset(0 -0.1em);
    font-size: clamp(6rem, 8vw, 9rem);
    font-weight: 400;
    letter-spacing: -0.02em;
  }
  .num-strip { display: block; transform: translateY(calc(var(--step, 0) * -25%)); }
  .num-strip > span { display: block; }
  .num-total { font-size: 1rem; margin-left: 0.75rem; }

  .step { padding: 2.5rem 0 3rem; } /* steps mais espaçados no desktop */

  .field { grid-template-columns: repeat(12, 1fr); gap: 1.5rem; align-items: baseline; }
  .field dt { grid-column: 1 / 5; }
  .field dd { grid-column: 5 / 13; }
}

/* ============================================================
   Movimento
   Tudo o que está acima é o estado final. Aqui o movimento recua a partir
   dele, e só quando: o usuário não pediu movimento reduzido (media query)
   e o JS está de pé (.js-motion, posta no <head>, desfeita se o main.js
   não confirmar). Sem JS, sem movimento: a página é a mesma.
   ============================================================ */

@media (prefers-reduced-motion: no-preference) {

  /* ---------- Hero: filete desenha, linhas sobem do corte, botão e metadados chegam ----------
     O parágrafo não anima: é texto corrido e é o elemento de LCP no celular.
     Escondê-lo atrasava o LCP em ~2,4s (lab, CPU 4x). */
  .js-motion .hero .filete { transform: scaleX(0); }
  .js-motion .hero .line-inner { transform: translateY(125%); }
  .js-motion .hero :is(.hero-meta, .hero-cta) {
    opacity: 0;
    transform: translateY(0.75rem);
  }

  .js-motion .hero.is-in .filete {
    transform: none;
    transition: transform var(--t-draw) var(--ease-draw);
  }
  .js-motion .hero.is-in .line-inner {
    transform: none;
    transition: transform var(--t-text) var(--ease-out) calc(180ms + var(--i, 0) * var(--stagger));
  }
  .js-motion .hero.is-in :is(.hero-meta, .hero-cta) {
    opacity: 1;
    transform: none;
    transition: opacity 800ms ease, transform var(--t-text) var(--ease-out);
    transition-delay: var(--d);
  }
  .hero-cta { --d: 620ms; }
  .hero-meta { --d: 800ms; }

  /* ---------- Títulos: cada linha sai de trás do próprio corte ----------
     A linha é a do autor (span no HTML), não a visual: se quebrar no
     celular, sobe inteira. Texto corrido não anima. */
  .js-motion [data-reveal="lines"] .line-inner { transform: translateY(125%); }
  .js-motion [data-reveal="lines"].is-in .line-inner {
    transform: none;
    transition: transform var(--t-text) var(--ease-out) calc((var(--batch, 0) + var(--i, 0)) * var(--stagger));
  }

  /* ---------- Filetes: 1px que se desenha ----------
     Réguas de seção e linhas da tabela da esquerda para a direita; filetes
     centrais do centro para fora; a marca de "o que foi cortado" desce
     depois da régua do próprio campo. */
  .js-motion [data-reveal="rule"]:is(.filete-md, .filete-lg),
  .js-motion [data-reveal="rule"].rule-b::after,
  .js-motion [data-reveal="rules"] > .service::after,
  .js-motion [data-reveal="rules"] > .field::before { transform: scaleX(0); }
  .js-motion [data-reveal="rules"] > .field--cut::after { transform: scaleY(0); }

  .js-motion .is-in:is(.filete-md, .filete-lg),
  .js-motion .is-in.rule-b::after,
  .js-motion .service.is-in::after,
  .js-motion .field.is-in::before {
    transform: none;
    transition: transform var(--t-draw) var(--ease-draw) calc(var(--batch, 0) * var(--stagger));
  }
  .js-motion .field--cut.is-in::after {
    transform: none;
    transition: transform var(--t-draw) var(--ease-out) calc(var(--batch, 0) * var(--stagger) + 500ms);
  }

  /* Serviços: número, nome e explicação entram em tempos e direções
     diferentes. A composição final continua sendo o CSS sem movimento. */
  .js-motion [data-reveal="rules"] > .service .service-num {
    opacity: 0;
    transform: translateY(0.75rem) scale(0.82);
  }
  .js-motion [data-reveal="rules"] > .service .service-name {
    opacity: 0;
    transform: translateX(-2rem);
  }
  .js-motion [data-reveal="rules"] > .service .service-desc {
    opacity: 0;
    transform: translateX(2rem);
  }
  .js-motion [data-reveal="rules"] > .service.is-in :is(.service-num, .service-name, .service-desc) {
    opacity: 1;
    transform: none;
    transition: opacity 620ms ease, transform 760ms var(--ease-out);
  }
  .js-motion [data-reveal="rules"] > .service.is-in .service-name { transition-delay: 90ms; }
  .js-motion [data-reveal="rules"] > .service.is-in .service-desc { transition-delay: 170ms; }

  /* ---------- O Corte: cada item é riscado, um a um, e fica riscado ----------
     Disparado e irreversível: rolar de volta não desfaz o corte. */
  .js-motion [data-reveal="cuts"] .cut-text {
    color: var(--fg-2);
    text-decoration-color: transparent;
  }
  .js-motion [data-reveal="cuts"] .cut-stroke { transform: scaleX(0); }
  .js-motion .cut-item.is-in .cut-stroke {
    transform: none;
    transition: transform 700ms var(--ease-draw) calc(var(--batch, 0) * 240ms);
  }
  /* O texto apaga no instante em que o risco termina: troca de estado, sem interpolar cor */
  .js-motion .cut-item.is-in .cut-text {
    color: var(--fg-3);
    transition: color 0s linear calc(var(--batch, 0) * 240ms + 700ms);
  }

  /* ---------- Cortina: o plano escuro sobe por cima ----------
     Nos dois planos escuros, a seção anterior para quando o fim dela chega
     ao pé da tela, e o plano escuro rola por cima. position: sticky nativo:
     sem pin, a página não ganha distância de rolagem. --h é a altura da
     seção que para, medida pelo JS; sem medida, sem cortina. */
  .js-motion .stack.is-measured > .plane:first-child {
    position: sticky;
    top: min(0px, calc(100svh - var(--h)));
    z-index: 0;
  }
  .js-motion .stack.is-measured > .plane + .plane {
    position: relative;
    z-index: 1;
  }

  /* ---------- Método: troca de etapa ----------
     Estado vem do JS; aqui só a duração. Transição CSS retoma de onde está
     se a etapa mudar no meio: a fita nunca para no número errado. */
  .step::after { transition: transform 320ms var(--ease-out); }

  /* ---------- Botão ---------- */
  .btn-01::before,
  .btn-01::after { transition: opacity var(--t-state) ease; }
  .btn-01 .arrow { transition: transform 320ms var(--ease-out); }
  .num-strip { transition: transform 700ms var(--ease-out); }

  /* O ponto de "cortamos" pousa depois da linha: fecha a frase */
  .js-motion [data-reveal="lines"] .dot-inline { transform: scale(0); }
  .js-motion [data-reveal="lines"].is-in .dot-inline {
    transform: none;
    transition: transform 500ms var(--ease-out) calc((var(--batch, 0) + var(--i, 0)) * var(--stagger) + 650ms);
  }
}

/* ---------- Atrelado à rolagem (scrub) ----------
   Só para o que É posição: o progresso da animação é a posição da rolagem.
   CSS scroll-driven, fora do main thread, sem JS. Onde não há suporte
   (Firefox em set/2026), a regra inteira é descartada e fica o estado
   final — o trilho inteiro. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    /* Trilho do método: cheio quando a lista termina de passar pelo meio da tela */
    .steps-rail {
      animation: draw-y linear both;
      animation-timeline: view();
      animation-range: entry-crossing 30% exit-crossing 45%;
    }

    /* Progresso da página no filete do header. Fora deste bloco ele não
       existe: um trilho cheio e parado mentiria a posição. */
    .site-header::after {
      content: "";
      position: absolute;
      left: 0; right: 0; bottom: -1px;
      height: 1px;
      background: var(--acc);
      transform-origin: left center;
      animation: draw-x linear both;
      animation-timeline: scroll(root block);
    }
  }
}

@keyframes draw-y { from { transform: scaleY(0); } }
@keyframes draw-x { from { transform: scaleX(0); } }

/* ============================================================
   Reels — rolagem travada por seção
   Camada extra, só existe com a classe .js-pin no <html> — desktop,
   ponteiro fino, sem prefers-reduced-motion, GSAP + ScrollTrigger
   carregados (ver main.js). Sem essa classe (celular, movimento
   reduzido, ou falha ao carregar a lib), nada aqui se aplica e a
   página é exatamente a seção "Movimento" acima: empilhada, um
   embaixo do outro, rolagem nativa.

   Mecânica: cada .reel trava na tela (JS, via ScrollTrigger.pin) e
   ganha uma distância extra de rolagem dividida em "checkpoints".
   Cada checkpoint cruzado revela o próximo pedaço (.reel sem .beat)
   ou troca de batida (.reel com .beat — só uma tela por vez). Ao
   acabar os checkpoints, a trava solta e a seção seguinte já trava
   embaixo, sem distância entre elas — o corte é seco, não um scroll
   suave.
   ============================================================ */

/* Cada reel ocupa exatamente uma tela enquanto está travado. O pin alinha
   o topo da seção com o topo da janela (o header é fixo, por cima), então
   o respiro do header vem como padding do .wrap, não como margem da seção. */
.js-pin .reel {
  overflow: clip;
  padding-block: 0;
}
.js-pin .reel > .wrap {
  position: relative;
  height: 100svh;
  padding-top: calc(var(--header-h) + 6rem);
  padding-bottom: 6rem;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.js-pin .reel .sec-head {
  position: absolute;
  top: calc(var(--header-h) + 2rem);
  left: 4rem;
  right: 4rem;
  padding-block: 0 2rem;
}

/* A cortina por sticky (seção "Movimento" acima) e o motor de pin não
   convivem — o próprio pin já produz o corte entre planos. */
.js-pin .stack.is-measured > .plane:first-child {
  position: static;
  top: auto;
}

/* Beats: cada um preenche a tela do reel, sobrepostos; só o ativo
   aparece. O palco (.cut-stage, .steps, .case-fields) precisa de
   position:relative e altura definida — cada um declara a própria. */
/* A batida que sai apaga rápido; a que entra espera ela sumir. Sem esse
   intervalo, os dois textos display convivem por meio segundo e a troca
   lê como borrão em vez de corte. */
.js-pin .beat {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  opacity: 0;
  transform: translateY(1.25rem);
  transition: opacity 200ms ease, transform 0ms linear 200ms;
  pointer-events: none;
}
.js-pin .beat.is-active {
  opacity: 1;
  transform: none;
  pointer-events: auto;
  z-index: 1;
  transition: opacity 420ms ease 170ms, transform 620ms var(--ease-out) 170ms;
}

.js-pin .cut-stage {
  position: relative;
  flex: 1 1 auto;
  min-height: 0; /* item de flex-column: sem isso o conteúdo absoluto não encolhe o suficiente */
  padding-block: 0;
}
.js-pin .cut-stage > .beat { margin-top: 0; }
.js-pin .cut-stage > .cuts-block { margin-top: 0; border-top: none; padding-top: 0; }
.js-pin #o-corte .cuts-block {
  width: min(100%, 64rem);
  margin-inline: auto;
}
.js-pin #o-corte .cuts-title { text-align: center; }
.js-pin #o-corte .cuts {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 2rem 3rem;
  margin-top: 2.5rem;
}
.js-pin #o-corte .cut-item { padding-top: 1.5rem; }

/* Como trabalhamos: as etapas anteriores permanecem na linha do tempo.
   A etapa ativa ganha peso; as concluídas recuam e ficam menos opacas. */
.js-pin #como-trabalhamos .steps {
  position: relative;
  height: 100%;
  min-height: 0;
  padding-left: 2.5rem;
}
.js-pin #como-trabalhamos .steps-rail {
  top: calc(62% - 18.25rem);
  bottom: auto;
  height: 13.5rem;
  transform: scaleY(var(--step-progress, 0));
  transform-origin: bottom;
  animation: none;
  transition: transform 620ms var(--ease-out);
}
.js-pin #como-trabalhamos .steps::before { opacity: 0; }
.js-pin #como-trabalhamos .step.beat {
  position: absolute;
  inset: auto 0 auto 2.5rem;
  top: 62%;
  height: 12rem;
  display: block;
  padding: 0;
  opacity: 0;
  transform: translateY(calc(-50% + var(--stack-y, 5rem))) scale(0.96);
  transform-origin: left center;
  pointer-events: none;
  transition: opacity 320ms ease, transform 520ms var(--ease-out);
}
.js-pin #como-trabalhamos .step.beat.is-past {
  opacity: 0.42;
  transform: translateY(calc(-50% + var(--stack-y))) scale(0.92);
}
.js-pin #como-trabalhamos .step.beat.is-active {
  opacity: 1;
  transform: translateY(calc(-50% + var(--stack-y))) scale(1);
  pointer-events: auto;
}
.js-pin #como-trabalhamos .step::before,
.js-pin #como-trabalhamos .step::after { display: block; }
.js-pin #como-trabalhamos .step::before,
.js-pin #como-trabalhamos .step::after { top: 1.25rem; }
.js-pin #como-trabalhamos .step.is-past::after,
.js-pin #como-trabalhamos .step.is-active::after {
  transform: translateX(-50%) scale(1);
}
.js-pin #como-trabalhamos .step-text {
  margin-top: 0.5rem;
  transition: opacity 320ms ease;
}
.js-pin #como-trabalhamos .step.is-past .step-text { opacity: 0; }
.js-pin #como-trabalhamos .step.is-past .t-step { font-size: 1.375rem; }
.js-pin .method { align-items: center; flex: 1; min-height: 0; margin-top: 0; }
.js-pin .method-sticky { position: static; }
.js-pin #como-trabalhamos .step-dots { display: none; }

.step-dots {
  gap: 0.625rem;
  margin-top: 2rem;
}
.js-pin .step-dots { display: flex; }
.step-dots li {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 9999px;
  border: 1px solid var(--fg-3);
  transition: background-color var(--t-state) ease, border-color var(--t-state) ease, transform var(--t-state) ease;
}
.step-dots li.is-active {
  background: var(--acc);
  border-color: var(--acc);
  transform: scale(1.2);
}

/* Um caso: conteúdo centralizado e pontos de navegação abaixo dele. */
.js-pin #um-caso .case.is-active {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  margin-top: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.js-pin #um-caso .case-fields {
  order: 1;
  position: relative;
  width: min(100%, 68rem);
  height: 100%;
  min-height: 0;
  margin: 0 auto;
  text-align: center;
}
.js-pin #um-caso .field-dots {
  position: absolute;
  bottom: -2rem;
  left: 0;
  right: 0;
}
.js-pin .field { padding: 0; align-items: center; gap: 1.5rem; }
.js-pin .field dd { max-width: 48ch; }
.js-pin .field::before,
.js-pin .field--cut::after { display: none; } /* réguas não fazem sentido com um campo só na tela */
.js-pin .field-value {
  font-size: clamp(1.375rem, 1.05rem + 1.8vw, 2.25rem);
  line-height: 1.5;
  color: var(--fg-2);
  text-wrap: balance;
}

.field-dots {
  gap: 0.625rem;
  justify-content: center;
}
.js-pin .field-dots { display: flex; }
.field-dots li {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 9999px;
  border: 1px solid var(--fg-3);
  transition: background-color var(--t-state) ease, border-color var(--t-state) ease, transform var(--t-state) ease;
}
.field-dots li.is-active {
  background: var(--acc);
  border-color: var(--acc);
  transform: scale(1.2);
}

/* O que fazemos / Contato: sem beat, o pin só segura enquanto os
   checkpoints revelam em sequência — o layout final é o mesmo de
   sempre, nada precisa de posicionamento novo. */
/* Sem lista rolável, o conteúdo precisa caber numa tela — aperta o
   ritmo vertical só no modo pin; em fluxo normal o respiro é o mesmo de sempre. */
.js-pin .services { margin-top: 0; }
.js-pin .service { padding: 1.25rem 0; }
.js-pin #o-que-fazemos .service::after {
  background: var(--acc);
  opacity: 0.62;
}
.js-pin .filete-lg { margin-block: 2rem; }
.js-pin .contact-note { margin-block: 1.5rem; }
.js-pin .contact-center {
  padding-block: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  width: 100%;
}
.js-pin .contact-center .t-question-lg { margin-top: 0; }

/* Botão do Contato: 4º checkpoint. Some com movimento reduzido pela
   mesma media query que envolve o resto da seção "Movimento". */
@media (prefers-reduced-motion: no-preference) {
  .js-motion [data-reveal="fade"] { opacity: 0; transform: translateY(0.75rem); }
  .js-motion [data-reveal="fade"].is-in {
    opacity: 1;
    transform: none;
    transition: opacity 700ms ease, transform 700ms var(--ease-out);
  }
}

/* ============================================================
   Cursor customizado
   Só existe com .js-cursor no <html> — pointer:fine, hover:hover, sem
   prefers-reduced-motion, aplicado pelo JS depois de rodar (nunca
   cursor:none estático: se o JS falhar, o cursor do sistema continua).
   Dois elementos, dois fatores de lerp — o anel arrasta mais que o
   ponto, dá o peso de "persegue o mouse" sem ser grudento.
   ============================================================ */

.cursor-dot,
.cursor-ring {
  display: none;
  position: fixed;
  top: 0; left: 0;
  border-radius: 9999px;
  pointer-events: none;
  z-index: 9999;
  will-change: transform;
}

.js-cursor,
.js-cursor a,
.js-cursor button { cursor: none; }

/* Só aparece depois do primeiro movimento do mouse — antes disso não há
   posição real para mostrar, e um anel parado no meio da tela é lixo visual. */
.js-cursor .cursor-dot,
.js-cursor .cursor-ring { visibility: hidden; }
.js-cursor.cursor-live .cursor-dot,
.js-cursor.cursor-live .cursor-ring { visibility: visible; }

.js-cursor .cursor-dot {
  display: block;
  width: 0.375rem;
  height: 0.375rem;
  margin: -0.1875rem 0 0 -0.1875rem;
  background: var(--acc);
}
.js-cursor .cursor-ring {
  display: block;
  width: 2.5rem;
  height: 2.5rem;
  margin: -1.25rem 0 0 -1.25rem;
  border: 1px solid var(--acc);
  opacity: 0.6;
  transition: width 320ms var(--ease-out), height 320ms var(--ease-out),
    margin 320ms var(--ease-out), opacity 320ms ease, background-color 320ms ease, border-color 320ms ease;
}
/* Em cima de algo clicável: o anel encolhe, preenche e o ponto some —
   o preenchimento é o alvo, não precisa de duas marcas. */
.js-cursor.cursor-hover .cursor-ring {
  width: 3.5rem;
  height: 3.5rem;
  margin: -1.75rem 0 0 -1.75rem;
  background: var(--acc);
  opacity: 0.14;
}
.js-cursor.cursor-hover .cursor-dot { opacity: 0; transition: opacity 200ms ease; }
/* Em cima de texto corrido: o anel achata numa barra fina — sinaliza
   "isto é para ler", não para clicar. */
.js-cursor.cursor-text .cursor-ring {
  width: 0.125rem;
  height: 1.5rem;
  margin: -0.75rem 0 0 -0.0625rem;
  opacity: 0.5;
  border-radius: 2px;
}
.js-cursor.cursor-text .cursor-dot { opacity: 0; }
